From 6d03e9449177c7b0e9d749de8507eaaea653397b Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 16 Mar 2015 15:45:34 +0100 Subject: Get rid of gluBuild2DMipmaps on gpu_draw.c (use our own imbuf scaling functions instead) --- source/blender/gpu/intern/gpu_draw.c | 63 ++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 3ed7253d309..722a7bdf114 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -723,43 +723,56 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int glGenTextures(1, (GLuint *)bind); glBindTexture(GL_TEXTURE_2D, *bind); - if (!(GPU_get_mipmap() && mipmap)) { - if (use_high_bit_depth) { - if (GLEW_ARB_texture_float) - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); - else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); - } + if (use_high_bit_depth) { + if (GLEW_ARB_texture_float) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); } - else { - if (GTS.gpu_mipmap) { - if (use_high_bit_depth) { - if (GLEW_ARB_texture_float) - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); - else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); - } - else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); + else + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + + if (GPU_get_mipmap() && mipmap) { + if (GTS.gpu_mipmap) { gpu_generate_mipmap(GL_TEXTURE_2D); } else { - if (use_high_bit_depth) - gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA16, rectw, recth, GL_RGBA, GL_FLOAT, frect); - else - gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect); + int i; + + if (!ibuf) { + if (use_high_bit_depth) { + ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy); + } + else { + ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy); + } + } + + IMB_makemipmap(ibuf, true); + + for (i = 1; i < ibuf->miptot; i++) { + ImBuf *mip = ibuf->mipmap[i - 1]; + if (use_high_bit_depth) { + if (GLEW_ARB_texture_float) + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16F, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float); + else + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float); + } + else { + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); + } + } } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); if (ima) ima->tpageflag |= IMA_MIPMAP_COMPLETE; } + else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } if (GLEW_EXT_texture_filter_anisotropic) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); -- cgit v1.2.3 From 664c611fc8838151bc570fc39657dac9970a1c6f Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 16 Mar 2015 16:07:21 +0100 Subject: Get rid of gluBuild2DMipmaps on rna API. Code here is a bit weird/simpler than GPU_draw, but we can reuse the API here, albeit with a few restrictions (no high resolution, custom filtering mode - which will probably get lost next time blender reloads textures) --- source/blender/makesrna/intern/rna_image_api.c | 28 ++++++++++---------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index 357490924f2..b9a1237c1f2 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -35,6 +35,7 @@ #include #include "DNA_packedFile_types.h" +#include "DNA_userdef_types.h" #include "BLI_utildefines.h" #include "BLI_path_util.h" @@ -57,6 +58,7 @@ #include "BIF_gl.h" #include "GPU_draw.h" +#include "GPU_debug.h" #include "DNA_image_types.h" #include "DNA_scene_types.h" @@ -232,31 +234,23 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int f ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); + /* clean glError buffer */ + while (glGetError() != GL_NO_ERROR) {} + if (ibuf == NULL || ibuf->rect == NULL) { BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); BKE_image_release_ibuf(image, ibuf, NULL); return (int)GL_INVALID_OPERATION; } - /* could be made into a function? */ - glGenTextures(1, (GLuint *)bind); - glBindTexture(GL_TEXTURE_2D, *bind); - - if (filter != GL_NEAREST && filter != GL_LINEAR) - error = (int)gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + GPU_create_gl_tex(bind, ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, + (filter != GL_NEAREST && filter != GL_LINEAR), false, image); - if (!error) { - /* clean glError buffer */ - while (glGetError() != GL_NO_ERROR) {} + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint)mag); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, image->tpageflag & IMA_CLAMP_U ? GL_CLAMP : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, image->tpageflag & IMA_CLAMP_V ? GL_CLAMP : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint)mag); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); - error = (int)glGetError(); - } + error = glGetError(); if (error) { glDeleteTextures(1, (GLuint *)bind); -- cgit v1.2.3 From 77bc623bc4b1b1d6389eb749468348c13ed19ce8 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 16 Mar 2015 16:18:37 +0100 Subject: Get rid og gluBuild2DMipmaps on game engine. --- source/gameengine/Ketsji/BL_Texture.cpp | 24 ++++++++++++++++++++++-- source/gameengine/VideoTexture/Texture.cpp | 14 +++++++++++++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index 58739e7ef81..e1a28961a68 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -203,9 +203,21 @@ void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap) glBindTexture(GL_TEXTURE_2D, mTexture ); if ( mipmap ) { + int i; + ImBuf *ibuf; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, x, y, GL_RGBA, GL_UNSIGNED_BYTE, pix ); + + ibuf = IMB_allocFromBuffer(pix, NULL, x, y); + + IMB_makemipmap(ibuf, true); + + for (i = 0; i < ibuf->miptot; i++) { + ImBuf *mip = IMB_getmipmap(ibuf, i); + + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); + } + IMB_freeImBuf(ibuf); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -245,9 +257,17 @@ void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap) glBindTexture(GL_TEXTURE_2D, mTexture ); if ( mipmap ) { + int i; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect ); + + IMB_makemipmap(ibuf, true); + + for (i = 0; i < ibuf->miptot; i++) { + ImBuf *mip = IMB_getmipmap(ibuf, i); + + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); + } } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp index 9640c5544da..c31faf5a463 100644 --- a/source/gameengine/VideoTexture/Texture.cpp +++ b/source/gameengine/VideoTexture/Texture.cpp @@ -79,9 +79,21 @@ void loadTexture(unsigned int texId, unsigned int *texture, short *size, glBindTexture(GL_TEXTURE_2D, texId); if (mipmap) { + int i; + ImBuf *ibuf; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, texture); + + ibuf = IMB_allocFromBuffer(texture, NULL, size[0], size[1]); + + IMB_makemipmap(ibuf, true); + + for (i = 0; i < ibuf->miptot; i++) { + ImBuf *mip = IMB_getmipmap(ibuf, i); + + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); + } + IMB_freeImBuf(ibuf); } else { -- cgit v1.2.3 From 9ed5a1073ef9db3761ab5ddc30f34955096f9ea8 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Mon, 16 Mar 2015 18:46:40 +0100 Subject: fix D1130 renamed the enum OBJ_FONT to OBJ_TEXT to avoid naming conflicts in Windows --- source/gameengine/GameLogic/SCA_IObject.h | 2 +- source/gameengine/Ketsji/KX_FontObject.h | 2 +- source/gameengine/Ketsji/KX_Scene.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h index d5972a0a807..a695fd4e7be 100644 --- a/source/gameengine/GameLogic/SCA_IObject.h +++ b/source/gameengine/GameLogic/SCA_IObject.h @@ -221,7 +221,7 @@ public: OBJ_ARMATURE=0, OBJ_CAMERA=1, OBJ_LIGHT=2, - OBJ_FONT=3, + OBJ_TEXT=4 } ObjectTypes; }; diff --git a/source/gameengine/Ketsji/KX_FontObject.h b/source/gameengine/Ketsji/KX_FontObject.h index 3a25d366148..bf70eedfde6 100644 --- a/source/gameengine/Ketsji/KX_FontObject.h +++ b/source/gameengine/Ketsji/KX_FontObject.h @@ -54,7 +54,7 @@ public: */ virtual CValue* GetReplica(); virtual void ProcessReplica(); - virtual int GetGameObjectType() { return OBJ_FONT; } + virtual int GetGameObjectType() { return OBJ_TEXT; } protected: std::vector m_text; diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 6d989ca1760..d1b10098237 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -532,7 +532,7 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal m_objectlist->Add(newobj->AddRef()); if (newobj->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) m_lightlist->Add(newobj->AddRef()); - else if (newobj->GetGameObjectType()==SCA_IObject::OBJ_FONT) + else if (newobj->GetGameObjectType()==SCA_IObject::OBJ_TEXT) AddFont((KX_FontObject*)newobj); newobj->AddMeshUser(); -- cgit v1.2.3 From ef70d644d6c32339d42eedd27c7b805eb8af1d07 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Mon, 16 Mar 2015 18:58:58 +0100 Subject: reverting unintentionally changed value of enum OBJ_TEXT --- source/gameengine/GameLogic/SCA_IObject.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h index a695fd4e7be..21e2c1cbcfc 100644 --- a/source/gameengine/GameLogic/SCA_IObject.h +++ b/source/gameengine/GameLogic/SCA_IObject.h @@ -221,7 +221,7 @@ public: OBJ_ARMATURE=0, OBJ_CAMERA=1, OBJ_LIGHT=2, - OBJ_TEXT=4 + OBJ_TEXT=3 } ObjectTypes; }; -- cgit v1.2.3 From b0bbd34ac260c46e0e2a3fdadce96b766531f88a Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 16 Mar 2015 20:51:02 +0100 Subject: I18n: update for new akward algo names in UI messages... --- release/scripts/modules/bl_i18n_utils/utils_spell_check.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py index 4126dde1225..cdb3a3fedb5 100644 --- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py +++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py @@ -576,6 +576,8 @@ class SpellChecker: "btx", "cineon", "dpx", + "dwaa", + "dwab", "dxf", "eps", "exr", -- cgit v1.2.3 From c0fa864e24c0a80d55cc7a3e3dcc29f6c2c99df7 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 16 Mar 2015 22:57:56 -0400 Subject: Cleanup: bool & const Using bool when we're asking yes/no questions such as whether some GPU feature is supported. Consolidated these simple functions into gpu_extensions.c and grouped them in the header. Const-ified some args where the functions don't modify the pointed-to data. --- source/blender/gpu/GPU_extensions.h | 38 ++++++++++---------- source/blender/gpu/intern/gpu_codegen.c | 5 --- source/blender/gpu/intern/gpu_extensions.c | 56 ++++++++++++++++-------------- 3 files changed, 50 insertions(+), 49 deletions(-) diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 228bea14e00..985cebc8687 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -56,14 +56,16 @@ typedef struct GPUShader GPUShader; void GPU_extensions_disable(void); -int GPU_glsl_support(void); -int GPU_non_power_of_two_support(void); -int GPU_vertex_buffer_support(void); -int GPU_display_list_support(void); +bool GPU_glsl_support(void); +bool GPU_non_power_of_two_support(void); +bool GPU_vertex_buffer_support(void); +bool GPU_display_list_support(void); +bool GPU_bicubic_bump_support(void); + +int GPU_max_texture_size(void); int GPU_color_depth(void); + void GPU_code_generate_glsl_lib(void); -int GPU_bicubic_bump_support(void); -int GPU_max_texture_size (void); /* GPU Types */ @@ -91,7 +93,7 @@ typedef enum GPUDriverType { GPU_DRIVER_ANY = (0xff0000) } GPUDriverType; -int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver); +bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver); /* GPU Texture * - always returns unsigned char RGBA textures @@ -113,13 +115,13 @@ typedef enum GPUHDRType { GPU_HDR_FULL_FLOAT = (1 << 1), } GPUHDRType; -GPUTexture *GPU_texture_create_1D(int w, float *pixels, char err_out[256]); -GPUTexture *GPU_texture_create_2D(int w, int h, float *pixels, GPUHDRType hdr, char err_out[256]); -GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *fpixels); +GPUTexture *GPU_texture_create_1D(int w, const float *pixels, char err_out[256]); +GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, GPUHDRType hdr, char err_out[256]); +GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels); GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]); GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]); -GPUTexture *GPU_texture_create_2D_procedural(int w, int h, float *pixels, char err_out[256]); -GPUTexture *GPU_texture_create_1D_procedural(int w, float *pixels, char err_out[256]); +GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, char err_out[256]); +GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]); GPUTexture *GPU_texture_from_blender(struct Image *ima, struct ImageUser *iuser, bool is_data, double time, int mipmap); GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap); @@ -138,10 +140,10 @@ void GPU_depth_texture_mode(GPUTexture *tex, bool compare, bool use_filter); GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex); -int GPU_texture_target(GPUTexture *tex); -int GPU_texture_opengl_width(GPUTexture *tex); -int GPU_texture_opengl_height(GPUTexture *tex); -int GPU_texture_opengl_bindcode(GPUTexture *tex); +int GPU_texture_target(const GPUTexture *tex); +int GPU_texture_opengl_width(const GPUTexture *tex); +int GPU_texture_opengl_height(const GPUTexture *tex); +int GPU_texture_opengl_bindcode(const GPUTexture *tex); /* GPU Framebuffer * - this is a wrapper for an OpenGL framebuffer object (FBO). in practice @@ -174,8 +176,8 @@ void GPU_offscreen_free(GPUOffScreen *ofs); void GPU_offscreen_bind(GPUOffScreen *ofs, bool save); void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore); void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels); -int GPU_offscreen_width(GPUOffScreen *ofs); -int GPU_offscreen_height(GPUOffScreen *ofs); +int GPU_offscreen_width(const GPUOffScreen *ofs); +int GPU_offscreen_height(const GPUOffScreen *ofs); /* GPU Shader * - only for fragment shaders now diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 47d2ac2d2e5..40c9ec0d862 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -719,11 +719,6 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type) return code; } -int GPU_bicubic_bump_support(void) -{ - return GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0; -} - void GPU_code_generate_glsl_lib(void) { DynStr *ds; diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 63f0bc37acf..f16b1525622 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -123,7 +123,7 @@ struct GPUFrameBuffer { /* GPU Types */ -int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver) +bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver) { return (GG.device & device) && (GG.os & os) && (GG.driver & driver); } @@ -250,29 +250,34 @@ void gpu_extensions_exit(void) GPU_invalid_tex_free(); } -int GPU_glsl_support(void) +bool GPU_glsl_support(void) { return !GG.extdisabled && GG.glslsupport; } -int GPU_non_power_of_two_support(void) +bool GPU_non_power_of_two_support(void) { if (GG.npotdisabled) - return 0; + return false; return GLEW_ARB_texture_non_power_of_two; } -int GPU_vertex_buffer_support(void) +bool GPU_vertex_buffer_support(void) { return GLEW_ARB_vertex_buffer_object || GLEW_VERSION_1_5; } -int GPU_display_list_support(void) +bool GPU_display_list_support(void) { return !GG.dlistsdisabled; } +bool GPU_bicubic_bump_support(void) +{ + return GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0; +} + int GPU_color_depth(void) { return GG.colordepth; @@ -333,17 +338,16 @@ struct GPUTexture { GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */ int fb_attachment; /* slot the texture is attached to */ - int depth; /* is a depth texture? */ + int depth; /* is a depth texture? if 3D how deep? */ }; -static unsigned char *GPU_texture_convert_pixels(int length, float *fpixels) +static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels) { unsigned char *pixels, *p; - const float *fp; - int a, len; + const float *fp = fpixels; + const int len = 4*length; + int a; - len = 4*length; - fp = fpixels; p = pixels = MEM_callocN(sizeof(unsigned char)*len, "GPUTexturePixels"); for (a=0; arefcount++; } -int GPU_texture_target(GPUTexture *tex) +int GPU_texture_target(const GPUTexture *tex) { return tex->target; } -int GPU_texture_opengl_width(GPUTexture *tex) +int GPU_texture_opengl_width(const GPUTexture *tex) { return tex->w; } -int GPU_texture_opengl_height(GPUTexture *tex) +int GPU_texture_opengl_height(const GPUTexture *tex) { return tex->h; } -int GPU_texture_opengl_bindcode(GPUTexture *tex) +int GPU_texture_opengl_bindcode(const GPUTexture *tex) { return tex->bindcode; } @@ -1364,12 +1368,12 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels) glReadPixels(0, 0, ofs->color->w, ofs->color->h, GL_RGBA, type, pixels); } -int GPU_offscreen_width(GPUOffScreen *ofs) +int GPU_offscreen_width(const GPUOffScreen *ofs) { return ofs->color->w; } -int GPU_offscreen_height(GPUOffScreen *ofs) +int GPU_offscreen_height(const GPUOffScreen *ofs) { return ofs->color->h; } -- cgit v1.2.3 From f138666f684a6055679f54d4c091201345a9cf8b Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 17 Mar 2015 01:18:52 -0400 Subject: cleanup: Mac #include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don’t need all of Cocoa, or any of Carbon here. --- intern/ghost/intern/GHOST_SystemPathsCocoa.mm | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.mm b/intern/ghost/intern/GHOST_SystemPathsCocoa.mm index 50ad91eeb99..36ae534da87 100644 --- a/intern/ghost/intern/GHOST_SystemPathsCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.mm @@ -24,14 +24,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -#import - -/*For the currently not ported to Cocoa keyboard layout functions (64bit & 10.6 compatible)*/ -#include - -#include -#include -#include +#import #include "GHOST_SystemPathsCocoa.h" -- cgit v1.2.3 From 1724513fc647056fc5831a344809058b695fcdb5 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 17 Mar 2015 12:02:10 +0500 Subject: Fix T44021: Crash switching Rendering Engines while viewport rendering + animating Make sure preview render job is cancelled before freeing the render engine associated to the viewport. --- source/blender/editors/include/ED_render.h | 2 +- source/blender/editors/include/ED_view3d.h | 2 ++ source/blender/editors/render/render_update.c | 16 +++++----------- source/blender/editors/space_view3d/space_view3d.c | 6 +++--- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h index 293621c3d19..1b1d8d723ee 100644 --- a/source/blender/editors/include/ED_render.h +++ b/source/blender/editors/include/ED_render.h @@ -50,7 +50,7 @@ void ED_operatortypes_render(void); void ED_render_id_flush_update(struct Main *bmain, struct ID *id); void ED_render_engine_changed(struct Main *bmain); -void ED_render_engine_area_exit(struct ScrArea *sa); +void ED_render_engine_area_exit(struct Main *bmain, struct ScrArea *sa); void ED_render_scene_update(struct Main *bmain, struct Scene *scene, int updated); void ED_viewport_render_kill_jobs(struct wmWindowManager *wm, struct Main *bmain, bool free_database); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 5fc5738c88f..11f961605af 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -61,6 +61,7 @@ struct rcti; struct wmOperator; struct wmOperatorType; struct wmWindow; +struct wmWindowManager; struct GPUFX; struct GPUOffScreen; struct GPUFXSettings; @@ -377,6 +378,7 @@ void ED_view3d_operator_properties_viewmat_get(struct wmOperator *op, int *winx, #endif /* render */ +void ED_view3d_stop_render_preview(struct wmWindowManager *wm, struct ARegion *ar); void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View3D *v3d, struct ScrArea *sa); #endif /* __ED_VIEW3D_H__ */ diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index be42e2ed518..4980e0bba80 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -61,6 +61,7 @@ #include "ED_node.h" #include "ED_render.h" +#include "ED_view3d.h" #include "render_intern.h" // own include @@ -141,26 +142,19 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated) recursive_check = false; } -void ED_render_engine_area_exit(ScrArea *sa) +void ED_render_engine_area_exit(Main *bmain, ScrArea *sa) { /* clear all render engines in this area */ ARegion *ar; + wmWindowManager *wm = bmain->wm.first; if (sa->spacetype != SPACE_VIEW3D) return; for (ar = sa->regionbase.first; ar; ar = ar->next) { - RegionView3D *rv3d; - if (ar->regiontype != RGN_TYPE_WINDOW || !(ar->regiondata)) continue; - - rv3d = ar->regiondata; - - if (rv3d->render_engine) { - RE_engine_free(rv3d->render_engine); - rv3d->render_engine = NULL; - } + ED_view3d_stop_render_preview(wm, ar); } } @@ -173,7 +167,7 @@ void ED_render_engine_changed(Main *bmain) for (sc = bmain->screen.first; sc; sc = sc->id.next) for (sa = sc->areabase.first; sa; sa = sa->next) - ED_render_engine_area_exit(sa); + ED_render_engine_area_exit(bmain, sa); RE_FreePersistentData(); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 35fb2bce115..ddb3e2f20c5 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -266,7 +266,7 @@ void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d) } #endif -static void view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar) +void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar) { RegionView3D *rv3d = ar->regiondata; @@ -297,7 +297,7 @@ void ED_view3d_shade_update(Main *bmain, Scene *scene, View3D *v3d, ScrArea *sa) for (ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->regiondata) - view3d_stop_render_preview(wm, ar); + ED_view3d_stop_render_preview(wm, ar); } } else if (scene->obedit != NULL && scene->obedit->type == OB_MESH) { @@ -563,7 +563,7 @@ static void view3d_main_area_exit(wmWindowManager *wm, ARegion *ar) { RegionView3D *rv3d = ar->regiondata; - view3d_stop_render_preview(wm, ar); + ED_view3d_stop_render_preview(wm, ar); if (rv3d->gpuoffscreen) { GPU_offscreen_free(rv3d->gpuoffscreen); -- cgit v1.2.3 From 07f53d6454e9a6a0c104a4bb3dc1e074a654c05b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 17 Mar 2015 12:59:44 +0500 Subject: Fix T44020: Crash exporting fluid sim to fbx The issue is coming from wrong fluid modifier copy callback, which might have left some pointers shared across original and target fluid modifiers. --- source/blender/modifiers/intern/MOD_fluidsim.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c index 6344ec83a31..9f05d357299 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim.c +++ b/source/blender/modifiers/intern/MOD_fluidsim.c @@ -71,6 +71,9 @@ static void copyData(ModifierData *md, ModifierData *target) MEM_freeN(tfluidmd->fss); tfluidmd->fss = MEM_dupallocN(fluidmd->fss); + if (tfluidmd->fss->meshVelocities != NULL) { + tfluidmd->fss->meshVelocities = MEM_dupallocN(tfluidmd->fss->meshVelocities); + } } -- cgit v1.2.3 From bf8ea6b60e69e6dd77d94c66cbcbab2a8e0b73f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20T=C3=B6nne?= Date: Tue, 17 Mar 2015 11:04:44 +0100 Subject: Kick particle systems to force redistribution, needed for reliably applying recent jitter fix. --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenloader/intern/versioning_270.c | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index dad7f1916a1..eb6797ed4dd 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 274 -#define BLENDER_SUBVERSION 0 +#define BLENDER_SUBVERSION 1 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 5 diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index ab5c8ace430..ee015fa5652 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -655,4 +655,16 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } + if (!MAIN_VERSION_ATLEAST(main, 274, 1)) { + /* particle systems need to be forced to redistribute for jitter mode fix */ + { + Object *ob; + ParticleSystem *psys; + for (ob = main->object.first; ob; ob = ob->id.next) { + for (psys = ob->particlesystem.first; psys; psys = psys->next) { + psys->recalc |= PSYS_RECALC_RESET; + } + } + } + } } -- cgit v1.2.3 From 42aac45d7f0e0f43725093e97ebb8175a95aa247 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 17 Mar 2015 14:15:05 +0100 Subject: Part 1 of D1082 by Troy Sobotka, add API in OCIO for luminance calculation. --- intern/opencolorio/fallback_impl.cc | 13 +++++++++++++ intern/opencolorio/ocio_capi.cc | 5 +++++ intern/opencolorio/ocio_capi.h | 2 ++ intern/opencolorio/ocio_impl.cc | 10 ++++++++++ intern/opencolorio/ocio_impl.h | 6 ++++++ release/datafiles/colormanagement/config.ocio | 2 +- 6 files changed, 37 insertions(+), 1 deletion(-) diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc index d1493cb3ad5..136f427ee0e 100644 --- a/intern/opencolorio/fallback_impl.cc +++ b/intern/opencolorio/fallback_impl.cc @@ -162,6 +162,19 @@ const char *FallbackImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr * return "sRGB"; } +void FallbackImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr * /*config*/, float *rgb) +{ + /* Here we simply use the older Blender assumed primaries of + * ITU-BT.709 / sRGB, or 0.2126729 0.7151522 0.0721750. Brute + * force stupid, but only plausible option given no color management + * system in place. + */ + + rgb[0] = 0.2126729f; + rgb[1] = 0.7151522f; + rgb[2] = 0.0721750f; +} + int FallbackImpl::configGetNumLooks(OCIO_ConstConfigRcPtr * /*config*/) { return 0; diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc index a4f2db456e8..7a0b9faa5fc 100644 --- a/intern/opencolorio/ocio_capi.cc +++ b/intern/opencolorio/ocio_capi.cc @@ -132,6 +132,11 @@ const char *OCIO_configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, c return impl->configGetDisplayColorSpaceName(config, display, view); } +void OCIO_configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb) +{ + impl->configGetDefaultLumaCoefs(config, rgb); +} + int OCIO_configGetNumLooks(OCIO_ConstConfigRcPtr *config) { return impl->configGetNumLooks(config); diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index d667dece62a..52a86727902 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -140,6 +140,8 @@ int OCIO_configGetNumViews(OCIO_ConstConfigRcPtr *config, const char *di const char *OCIO_configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index); const char *OCIO_configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view); +void OCIO_configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb); + int OCIO_configGetNumLooks(OCIO_ConstConfigRcPtr *config); const char *OCIO_configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index); OCIO_ConstLookRcPtr *OCIO_configGetLook(OCIO_ConstConfigRcPtr *config, const char *name); diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc index 5015f3a5c7d..bf5590077ef 100644 --- a/intern/opencolorio/ocio_impl.cc +++ b/intern/opencolorio/ocio_impl.cc @@ -272,6 +272,16 @@ const char *OCIOImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *conf return NULL; } +void OCIOImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb) +{ + try { + (*(ConstConfigRcPtr *) config)->getDefaultLumaCoefs(rgb); + } + catch (Exception &exception) { + OCIO_reportException(exception); + } +} + int OCIOImpl::configGetNumLooks(OCIO_ConstConfigRcPtr *config) { try { diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h index 47e6d829902..f086bbb1a26 100644 --- a/intern/opencolorio/ocio_impl.h +++ b/intern/opencolorio/ocio_impl.h @@ -58,6 +58,8 @@ public: virtual const char *configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index) = 0; virtual const char *configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view) = 0; + virtual void configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb) = 0; + virtual int configGetNumLooks(OCIO_ConstConfigRcPtr *config) = 0; virtual const char *configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index) = 0; virtual OCIO_ConstLookRcPtr *configGetLook(OCIO_ConstConfigRcPtr *config, const char *name) = 0; @@ -145,6 +147,8 @@ public: const char *configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index); const char *configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view); + void configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb); + int configGetNumLooks(OCIO_ConstConfigRcPtr *config); const char *configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index); OCIO_ConstLookRcPtr *configGetLook(OCIO_ConstConfigRcPtr *config, const char *name); @@ -233,6 +237,8 @@ public: const char *configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index); const char *configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view); + void configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb); + int configGetNumLooks(OCIO_ConstConfigRcPtr *config); const char *configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index); OCIO_ConstLookRcPtr *configGetLook(OCIO_ConstConfigRcPtr *config, const char *name); diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index 1cf9a3bb36e..7ecc9768d57 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -6,7 +6,7 @@ ocio_profile_version: 1 search_path: luts strictparsing: true -luma: [0.2126, 0.7152, 0.0722] +luma: [0.2126729, 0.7151522, 0.0721750] description: RRT version ut33 -- cgit v1.2.3 From dd38dce7f0ae604396d1e96bc49500369fdedf29 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 17 Mar 2015 15:20:33 +0100 Subject: Part 2 of D1082 by Troy Sobotka, remove our functions that do luma calculations and use the OCIO one instead. --- source/blender/blenkernel/intern/colortools.c | 6 +-- source/blender/blenlib/BLI_math_color.h | 7 --- source/blender/blenlib/intern/math_color_inline.c | 55 ---------------------- .../operations/COM_CalculateMeanOperation.cpp | 6 ++- .../COM_CalculateStandardDeviationOperation.cpp | 6 ++- .../operations/COM_ColorCorrectionOperation.cpp | 6 ++- .../compositor/operations/COM_ConvertOperation.cpp | 5 +- .../operations/COM_GlareThresholdOperation.cpp | 6 ++- .../compositor/operations/COM_TonemapOperation.cpp | 8 +++- source/blender/editors/interface/interface_draw.c | 2 +- .../blender/editors/interface/interface_regions.c | 6 +-- .../blender/editors/interface/interface_widgets.c | 3 +- .../blender/editors/sculpt_paint/paint_image_2d.c | 2 +- .../editors/sculpt_paint/paint_image_proj.c | 4 +- source/blender/editors/sculpt_paint/paint_vertex.c | 5 +- .../editors/space_sequencer/sequencer_scopes.c | 5 +- source/blender/imbuf/IMB_colormanagement.h | 3 ++ source/blender/imbuf/intern/colormanagement.c | 36 ++++++++++++++ source/blender/imbuf/intern/divers.c | 4 +- source/blender/imbuf/intern/png.c | 4 +- .../nodes/shader/nodes/node_shader_valToRgb.c | 3 +- .../nodes/texture/nodes/node_texture_valToRgb.c | 3 +- .../blender/render/intern/source/render_texture.c | 38 +++++++-------- source/blender/render/intern/source/shadeoutput.c | 22 +++++---- source/blender/render/intern/source/volumetric.c | 12 +++-- 25 files changed, 131 insertions(+), 126 deletions(-) diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 89c3e4b0cfc..616e8a0486b 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -994,7 +994,7 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorM copy_v3_v3(rgb, fp); IMB_colormanagement_processor_apply_v3(cm_processor, rgb); - hist->data_luma[i] = rgb_to_luma(rgb); + hist->data_luma[i] = IMB_colormanagement_get_luminance(rgb); hist->data_r[i] = rgb[0]; hist->data_g[i] = rgb[1]; hist->data_b[i] = rgb[2]; @@ -1002,7 +1002,7 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorM } else if (ibuf->rect) { cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x); - hist->data_luma[i] = (float)rgb_to_luma_byte(cp) / 255.0f; + hist->data_luma[i] = (float)IMB_colormanagement_get_luminance_byte(cp) / 255.0f; hist->data_r[i] = (float)cp[0] / 255.0f; hist->data_g[i] = (float)cp[1] / 255.0f; hist->data_b[i] = (float)cp[2] / 255.0f; @@ -1124,7 +1124,7 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings * } /* we still need luma for histogram */ - luma = rgb_to_luma(rgba); + luma = IMB_colormanagement_get_luminance(rgba); /* check for min max */ if (ycc_mode == -1) { diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 55e57b14d09..5652c8056c0 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -80,13 +80,6 @@ void rgb_to_xyz(float r, float g, float b, float *x, float *y, float *z); unsigned int rgb_to_cpack(float r, float g, float b); unsigned int hsv_to_cpack(float h, float s, float v); -MINLINE float rgb_to_bw(const float rgb[3]); -MINLINE float rgb_to_grayscale(const float rgb[3]); -MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3]); -MINLINE float rgb_to_luma(const float rgb[3]); -MINLINE unsigned char rgb_to_luma_byte(const unsigned char rgb[3]); -MINLINE float rgb_to_luma_y(const float rgb[3]); - /**************** Profile Transformations *****************/ float srgb_to_linearrgb(float c); diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c index dc62d04ad55..96aa4b55201 100644 --- a/source/blender/blenlib/intern/math_color_inline.c +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -200,61 +200,6 @@ MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack) r_col[2] = ((pack) >> 16) & 0xFF; } -/* TODO: - * - * regarding #rgb_to_bw vs #rgb_to_grayscale, - * it seems nobody knows why we have both functions which convert color to grays - * but with different influences, this is quite stupid, and should be resolved - * by someone who knows this stuff: see this thread - * http://lists.blender.org/pipermail/bf-committers/2012-June/037180.html - * - * Only conclusion is that rgb_to_grayscale is used more for compositing. - */ -MINLINE float rgb_to_bw(const float rgb[3]) -{ - return 0.35f * rgb[0] + 0.45f * rgb[1] + 0.2f * rgb[2]; -} - -/* non-linear luma from ITU-R BT.601-2 - * see: http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC11 - * note: the values used for are not exact matches to those documented above, - * but they are from the same */ -MINLINE float rgb_to_grayscale(const float rgb[3]) -{ - return 0.3f * rgb[0] + 0.58f * rgb[1] + 0.12f * rgb[2]; -} - -MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3]) -{ - return (unsigned char)(((76 * (unsigned short)rgb[0]) + - (148 * (unsigned short)rgb[1]) + - (31 * (unsigned short)rgb[2])) / 255); -} - -/* luma from defined by 'YCC_JFIF', see #rgb_to_ycc */ -MINLINE float rgb_to_luma(const float rgb[3]) -{ - return 0.299f * rgb[0] + 0.587f * rgb[1] + 0.114f * rgb[2]; -} - -MINLINE unsigned char rgb_to_luma_byte(const unsigned char rgb[3]) -{ - return (unsigned char)(((76 * (unsigned short)rgb[0]) + - (150 * (unsigned short)rgb[1]) + - (29 * (unsigned short)rgb[2])) / 255); -} - -/* gamma-corrected RGB --> CIE XYZ - * for this function we only get the Y component - * see: http://software.intel.com/sites/products/documentation/hpc/ipp/ippi/ippi_ch6/ch6_color_models.html - * - * also known as: - * luminance rec. 709 */ -MINLINE float rgb_to_luma_y(const float rgb[3]) -{ - return 0.212671f * rgb[0] + 0.71516f * rgb[1] + 0.072169f * rgb[2]; -} - MINLINE int compare_rgb_uchar(const unsigned char col_a[3], const unsigned char col_b[3], const int limit) { const int r = (int)col_a[0] - (int)col_b[0]; diff --git a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp index a2954a20e90..54b0e37c791 100644 --- a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp +++ b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp @@ -24,7 +24,9 @@ #include "BLI_math.h" #include "BLI_utildefines.h" - +extern "C" { +#include "IMB_colormanagement.h" +} CalculateMeanOperation::CalculateMeanOperation() : NodeOperation() { @@ -96,7 +98,7 @@ void CalculateMeanOperation::calculateMean(MemoryBuffer *tile) switch (this->m_setting) { case 1: { - sum += rgb_to_bw(&buffer[offset]); + sum += IMB_colormanagement_get_luminance(&buffer[offset]); break; } case 2: diff --git a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp index 0c67da2d552..32c5fc1adc7 100644 --- a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp +++ b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp @@ -24,7 +24,9 @@ #include "BLI_math.h" #include "BLI_utildefines.h" - +extern "C" { +#include "IMB_colormanagement.h" +} CalculateStandardDeviationOperation::CalculateStandardDeviationOperation() : CalculateMeanOperation() { @@ -55,7 +57,7 @@ void *CalculateStandardDeviationOperation::initializeTileData(rcti *rect) switch (this->m_setting) { case 1: /* rgb combined */ { - float value = rgb_to_bw(&buffer[offset]); + float value = IMB_colormanagement_get_luminance(&buffer[offset]); sum += (value - mean) * (value - mean); break; } diff --git a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp index 19209951005..54e0fb41abf 100644 --- a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp @@ -23,6 +23,10 @@ #include "COM_ColorCorrectionOperation.h" #include "BLI_math.h" +extern "C" { +#include "IMB_colormanagement.h" +} + ColorCorrectionOperation::ColorCorrectionOperation() : NodeOperation() { this->addInputSocket(COM_DT_COLOR); @@ -90,7 +94,7 @@ void ColorCorrectionOperation::executePixelSampled(float output[4], float x, flo lift += (levelShadows * this->m_data->shadows.lift) + (levelMidtones * this->m_data->midtones.lift) + (levelHighlights * this->m_data->highlights.lift); float invgamma = 1.0f / gamma; - float luma = rgb_to_luma_y(inputImageColor); + float luma = IMB_colormanagement_get_luminance(inputImageColor); r = inputImageColor[0]; g = inputImageColor[1]; diff --git a/source/blender/compositor/operations/COM_ConvertOperation.cpp b/source/blender/compositor/operations/COM_ConvertOperation.cpp index 977586acb60..8b8e8408208 100644 --- a/source/blender/compositor/operations/COM_ConvertOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvertOperation.cpp @@ -22,6 +22,9 @@ #include "COM_ConvertOperation.h" +extern "C" { +#include "IMB_colormanagement.h" +} ConvertBaseOperation::ConvertBaseOperation() { @@ -84,7 +87,7 @@ void ConvertColorToBWOperation::executePixelSampled(float output[4], float x, fl { float inputColor[4]; this->m_inputOperation->readSampled(inputColor, x, y, sampler); - output[0] = rgb_to_bw(inputColor); + output[0] = IMB_colormanagement_get_luminance(inputColor); } diff --git a/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp b/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp index 78e1e80cafc..d2bd7cbeeab 100644 --- a/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp @@ -23,6 +23,10 @@ #include "COM_GlareThresholdOperation.h" #include "BLI_math.h" +extern "C" { +#include "IMB_colormanagement.h" +} + GlareThresholdOperation::GlareThresholdOperation() : NodeOperation() { this->addInputSocket(COM_DT_COLOR, COM_SC_FIT); @@ -47,7 +51,7 @@ void GlareThresholdOperation::executePixelSampled(float output[4], float x, floa const float threshold = this->m_settings->threshold; this->m_inputProgram->readSampled(output, x, y, sampler); - if (rgb_to_luma_y(output) >= threshold) { + if (IMB_colormanagement_get_luminance(output) >= threshold) { output[0] -= threshold, output[1] -= threshold, output[2] -= threshold; output[0] = max(output[0], 0.0f); output[1] = max(output[1], 0.0f); diff --git a/source/blender/compositor/operations/COM_TonemapOperation.cpp b/source/blender/compositor/operations/COM_TonemapOperation.cpp index e8a578fa131..54ba218b802 100644 --- a/source/blender/compositor/operations/COM_TonemapOperation.cpp +++ b/source/blender/compositor/operations/COM_TonemapOperation.cpp @@ -24,6 +24,10 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +extern "C" { +#include "IMB_colormanagement.h" +} + TonemapOperation::TonemapOperation() : NodeOperation() { this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); @@ -69,7 +73,7 @@ void PhotoreceptorTonemapOperation::executePixel(float output[4], int x, int y, this->m_imageReader->read(output, x, y, NULL); - const float L = rgb_to_luma_y(output); + const float L = IMB_colormanagement_get_luminance(output); float I_l = output[0] + ic * (L - output[0]); float I_g = avg->cav[0] + ic * (avg->lav - avg->cav[0]); float I_a = I_l + ia * (I_g - I_l); @@ -125,7 +129,7 @@ void *TonemapOperation::initializeTileData(rcti *rect) float Lav = 0.f; float cav[4] = {0.0f, 0.0f, 0.0f, 0.0f}; while (p--) { - float L = rgb_to_luma_y(bc); + float L = IMB_colormanagement_get_luminance(bc); Lav += L; add_v3_v3(cav, bc); lsum += logf(MAX2(L, 0.0f) + 1e-5f); diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 07d580b9138..414903fa194 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -1453,7 +1453,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti glEnd(); } else if (cumap->cur == 3) { - float lum = rgb_to_bw(cumap->sample); + float lum = IMB_colormanagement_get_luminance(cumap->sample); glColor3ub(240, 240, 240); glBegin(GL_LINES); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 6e5f6af3c5f..adcd615368b 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -237,8 +237,8 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) /* find the brightness difference between background and text colors */ - tone_bg = rgb_to_grayscale(background_color); - /* tone_fg = rgb_to_grayscale(main_color); */ + tone_bg = IMB_colormanagement_get_luminance(background_color); + /* tone_fg = IMB_colormanagement_get_luminance(main_color); */ /* mix the colors */ rgb_tint(value_color, 0.0f, 0.0f, tone_bg, 0.2f); /* light grey */ @@ -261,7 +261,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) /* override text-style */ fstyle_header.shadow = 1; - fstyle_header.shadowcolor = rgb_to_luma(tip_colors[UI_TIP_LC_MAIN]); + fstyle_header.shadowcolor = IMB_colormanagement_get_luminance(tip_colors[UI_TIP_LC_MAIN]); fstyle_header.shadx = fstyle_header.shady = 0; fstyle_header.shadowalpha = 1.0f; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 91186a14b49..9020522bb59 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -56,6 +56,7 @@ #include "UI_interface.h" #include "UI_interface_icons.h" +#include "IMB_colormanagement.h" #include "interface_intern.h" @@ -3027,7 +3028,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat float width = rect->xmax - rect->xmin; float height = rect->ymax - rect->ymin; /* find color luminance and change it slightly */ - float bw = rgb_to_bw(col); + float bw = IMB_colormanagement_get_luminance(col); bw += (bw < 0.5f) ? 0.5f : -0.5f; diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index eb96d1d20d5..4f71bea7cd2 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -889,7 +889,7 @@ static void paint_2d_lift_soften(ImagePaintState *s, ImBuf *ibuf, ImBuf *ibufb, /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid * colored speckles appearing in final image, and also to check for threshold */ - outrgb[0] = outrgb[1] = outrgb[2] = rgb_to_grayscale(outrgb); + outrgb[0] = outrgb[1] = outrgb[2] = IMB_colormanagement_get_luminance(outrgb); if (fabsf(outrgb[0]) > threshold) { float mask = BKE_brush_alpha_get(s->scene, s->brush); float alpha = rgba[3]; diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 098f0d04d78..805c271f2d1 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -4207,7 +4207,7 @@ static void do_projectpaint_soften_f(ProjPaintState *ps, ProjPixel *projPixel, f /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid * colored speckles appearing in final image, and also to check for threshold */ - rgba[0] = rgba[1] = rgba[2] = rgb_to_grayscale(rgba); + rgba[0] = rgba[1] = rgba[2] = IMB_colormanagement_get_luminance(rgba); if (fabsf(rgba[0]) > ps->brush->sharp_threshold) { float alpha = projPixel->pixel.f_pt[3]; projPixel->pixel.f_pt[3] = rgba[3] = mask; @@ -4268,7 +4268,7 @@ static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, flo sub_v3_v3v3(rgba, rgba_pixel, rgba); /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid * colored speckles appearing in final image, and also to check for threshold */ - rgba[0] = rgba[1] = rgba[2] = rgb_to_grayscale(rgba); + rgba[0] = rgba[1] = rgba[2] = IMB_colormanagement_get_luminance(rgba); if (fabsf(rgba[0]) > ps->brush->sharp_threshold) { float alpha = rgba_pixel[3]; rgba[3] = rgba_pixel[3] = mask; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index e87dd6c2810..9bca0fd2976 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -37,6 +37,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" #include "DNA_armature_types.h" #include "DNA_mesh_types.h" @@ -768,7 +769,7 @@ BLI_INLINE unsigned int mcol_lighten(unsigned int col1, unsigned int col2, int f /* See if are lighter, if so mix, else don't do anything. * if the paint col is darker then the original, then ignore */ - if (rgb_to_grayscale_byte(cp1) > rgb_to_grayscale_byte(cp2)) { + if (IMB_colormanagement_get_luminance_byte(cp1) > IMB_colormanagement_get_luminance_byte(cp2)) { return col1; } @@ -801,7 +802,7 @@ BLI_INLINE unsigned int mcol_darken(unsigned int col1, unsigned int col2, int fa /* See if were darker, if so mix, else don't do anything. * if the paint col is brighter then the original, then ignore */ - if (rgb_to_grayscale_byte(cp1) < rgb_to_grayscale_byte(cp2)) { + if (IMB_colormanagement_get_luminance_byte(cp1) < IMB_colormanagement_get_luminance_byte(cp2)) { return col1; } diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index 24b3776da6d..b4bcfb4eb07 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -32,6 +32,7 @@ #include "BLI_math_color.h" #include "BLI_utildefines.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -167,7 +168,7 @@ static ImBuf *make_waveform_view_from_ibuf_byte(ImBuf *ibuf) for (x = 0; x < ibuf->x; x++) { const unsigned char *rgb = src + 4 * (ibuf->x * y + x); - float v = (float)rgb_to_luma_byte(rgb) / 255.0f; + float v = (float)IMB_colormanagement_get_luminance_byte(rgb) / 255.0f; unsigned char *p = tgt; p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1); @@ -207,7 +208,7 @@ static ImBuf *make_waveform_view_from_ibuf_float(ImBuf *ibuf) for (x = 0; x < ibuf->x; x++) { const float *rgb = src + 4 * (ibuf->x * y + x); - float v = rgb_to_luma(rgb); + float v = IMB_colormanagement_get_luminance(rgb); unsigned char *p = tgt; CLAMP(v, 0.0f, 1.0f); diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 262e87bedf5..9407750c039 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -71,6 +71,9 @@ void IMB_colormanagement_assign_rect_colorspace(struct ImBuf *ibuf, const char * const char *IMB_colormanagement_get_float_colorspace(struct ImBuf *ibuf); const char *IMB_colormanagement_get_rect_colorspace(struct ImBuf *ibuf); +float IMB_colormanagement_get_luminance(const float rgb[3]); +unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char[3]); + /* ** Color space transformation functions ** */ void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 95e166b2f8b..588d81f9a75 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -90,6 +90,11 @@ static int global_tot_display = 0; static int global_tot_view = 0; static int global_tot_looks = 0; +/* Set to ITU-BT.709 / sRGB primaries weight. Brute force stupid, but only + * option with no colormanagement in place. + */ +static float luma_coefficients[3] = { 0.2126729f, 0.7151522f, 0.0721750f }; + /* lock used by pre-cached processors getters, so processor wouldn't * be created several times * LOCK_COLORMANAGE can not be used since this mutex could be needed to @@ -545,6 +550,9 @@ static void colormanage_load_config(OCIO_ConstConfigRcPtr *config) colormanage_look_add(name, process_space, false); } + + /* Load luminance coefficients. */ + OCIO_configGetDefaultLumaCoefs(config, luma_coefficients); } static void colormanage_free_config(void) @@ -1222,6 +1230,34 @@ const char *IMB_colormanagement_get_rect_colorspace(ImBuf *ibuf) return ibuf->rect_colorspace->name; } +/* Convert a float RGB triplet to the correct luminance weighted average. + * + * Grayscale, or Luma is a distillation of RGB data values down to a weighted average + * based on the luminance positions of the red, green, and blue primaries. + * Given that the internal reference space may be arbitrarily set, any + * effort to glean the luminance coefficients must be aware of the reference + * space primaries. + * + * See http://wiki.blender.org/index.php/User:Nazg-gul/ColorManagement#Luminance + */ + +float IMB_colormanagement_get_luminance(const float rgb[3]) +{ + return dot_v3v3(luma_coefficients, rgb); +} + +/* Byte equivalent of IMB_colormanagement_get_luminance(). */ +unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char rgb[3]) +{ + float rgbf[3]; + + rgbf[0] = (float) rgb[0] / 255.0f; + rgbf[1] = (float) rgb[1] / 255.0f; + rgbf[2] = (float) rgb[2] / 255.0f; + + return FTOCHAR(dot_v3v3(luma_coefficients, rgbf)); +} + /*********************** Threaded display buffer transform routines *************************/ typedef struct DisplayBufferThread { diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 65abf22ff2c..3417fe2fc1d 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -775,12 +775,12 @@ void IMB_color_to_bw(ImBuf *ibuf) if (rct_fl) { for (i = ibuf->x * ibuf->y; i > 0; i--, rct_fl += 4) - rct_fl[0] = rct_fl[1] = rct_fl[2] = rgb_to_grayscale(rct_fl); + rct_fl[0] = rct_fl[1] = rct_fl[2] = IMB_colormanagement_get_luminance(rct_fl); } if (rct) { for (i = ibuf->x * ibuf->y; i > 0; i--, rct += 4) - rct[0] = rct[1] = rct[2] = rgb_to_grayscale_byte(rct); + rct[0] = rct[1] = rct[2] = IMB_colormanagement_get_luminance_byte(rct); } } diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index 683bdabcd6c..f3ff6659e1c 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -312,7 +312,7 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) rgb[0] = chanel_colormanage_cb(from_straight[0]); rgb[1] = chanel_colormanage_cb(from_straight[1]); rgb[2] = chanel_colormanage_cb(from_straight[2]); - to16[0] = ftoshort(rgb_to_bw(rgb)); + to16[0] = ftoshort(IMB_colormanagement_get_luminance(rgb)); to16++; from_float += 4; } } @@ -321,7 +321,7 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) rgb[0] = chanel_colormanage_cb(from_float[0]); rgb[1] = chanel_colormanage_cb(from_float[1]); rgb[2] = chanel_colormanage_cb(from_float[2]); - to16[0] = ftoshort(rgb_to_bw(rgb)); + to16[0] = ftoshort(IMB_colormanagement_get_luminance(rgb)); to16++; from_float += 3; } } diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c index fa5d9b43ee7..72942cce9c5 100644 --- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c @@ -31,6 +31,7 @@ #include "node_shader_util.h" +#include "IMB_colormanagement.h" /* **************** VALTORGB ******************** */ static bNodeSocketTemplate sh_node_valtorgb_in[] = { @@ -106,7 +107,7 @@ static void node_shader_exec_rgbtobw(void *UNUSED(data), int UNUSED(thread), bNo float col[3]; nodestack_get_vec(col, SOCK_VECTOR, in[0]); - out[0]->vec[0] = rgb_to_bw(col); + out[0]->vec[0] = IMB_colormanagement_get_luminance(col); } static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) diff --git a/source/blender/nodes/texture/nodes/node_texture_valToRgb.c b/source/blender/nodes/texture/nodes/node_texture_valToRgb.c index 7f8adab2da5..a49d82d27a9 100644 --- a/source/blender/nodes/texture/nodes/node_texture_valToRgb.c +++ b/source/blender/nodes/texture/nodes/node_texture_valToRgb.c @@ -32,6 +32,7 @@ #include "node_texture_util.h" #include "NOD_texture.h" +#include "IMB_colormanagement.h" /* **************** VALTORGB ******************** */ static bNodeSocketTemplate valtorgb_in[] = { @@ -91,7 +92,7 @@ static void rgbtobw_valuefn(float *out, TexParams *p, bNode *UNUSED(node), bNode { float cin[4]; tex_input_rgba(cin, in[0], p, thread); - *out = rgb_to_bw(cin); + *out = IMB_colormanagement_get_luminance(cin); } static void rgbtobw_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index 17039bca63a..531c31848a6 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -1982,14 +1982,14 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T /* use texres for the center sample, set rgbnor */ rgbnor = multitex_mtex(shi, mtex, STll, dxt, dyt, texres, pool, skip_load_image); - Hll = (fromrgb) ? rgb_to_grayscale(&texres->tr) : texres->tin; + Hll = (fromrgb) ? IMB_colormanagement_get_luminance(&texres->tr) : texres->tin; /* use ttexr for the other 2 taps */ multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr, pool, skip_load_image); - Hlr = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin; + Hlr = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin; multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr, pool, skip_load_image); - Hul = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin; + Hul = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin; dHdx = Hscale*(Hlr - Hll); dHdy = Hscale*(Hul - Hll); @@ -2020,17 +2020,17 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T /* use texres for the center sample, set rgbnor */ rgbnor = multitex_mtex(shi, mtex, STc, dxt, dyt, texres, pool, skip_load_image); - /* Hc = (fromrgb) ? rgb_to_grayscale(&texres->tr) : texres->tin; */ /* UNUSED */ + /* Hc = (fromrgb) ? IMB_colormanagement_get_luminance(&texres->tr) : texres->tin; */ /* UNUSED */ /* use ttexr for the other taps */ multitex_mtex(shi, mtex, STl, dxt, dyt, &ttexr, pool, skip_load_image); - Hl = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin; + Hl = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin; multitex_mtex(shi, mtex, STr, dxt, dyt, &ttexr, pool, skip_load_image); - Hr = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin; + Hr = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin; multitex_mtex(shi, mtex, STd, dxt, dyt, &ttexr, pool, skip_load_image); - Hd = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin; + Hd = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin; multitex_mtex(shi, mtex, STu, dxt, dyt, &ttexr, pool, skip_load_image); - Hu = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin; + Hu = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin; dHdx = Hscale*(Hr - Hl); dHdy = Hscale*(Hu - Hd); @@ -2328,7 +2328,7 @@ void do_material_tex(ShadeInput *shi, Render *re) /* texture output */ if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) { - texres.tin = rgb_to_grayscale(&texres.tr); + texres.tin = IMB_colormanagement_get_luminance(&texres.tr); rgbnor -= TEX_RGB; } if (mtex->texflag & MTEX_NEGATIVE) { @@ -2568,7 +2568,7 @@ void do_material_tex(ShadeInput *shi, Render *re) } if (rgbnor & TEX_RGB) { - texres.tin = rgb_to_grayscale(&texres.tr); + texres.tin = IMB_colormanagement_get_luminance(&texres.tr); } factt= (0.5f-texres.tin)*mtex->dispfac*stencilTin; facmm= 1.0f-factt; @@ -2596,7 +2596,7 @@ void do_material_tex(ShadeInput *shi, Render *re) if (rgbnor & TEX_RGB) { if (texres.talpha) texres.tin = texres.ta; - else texres.tin = rgb_to_grayscale(&texres.tr); + else texres.tin = IMB_colormanagement_get_luminance(&texres.tr); } if (mtex->mapto & MAP_REF) { @@ -2767,7 +2767,7 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_ /* texture output */ if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) { - texres.tin = rgb_to_grayscale(&texres.tr); + texres.tin = IMB_colormanagement_get_luminance(&texres.tr); rgbnor -= TEX_RGB; } if (mtex->texflag & MTEX_NEGATIVE) { @@ -2836,7 +2836,7 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_ /* convert RGB to intensity if intensity info isn't provided */ if (rgbnor & TEX_RGB) { if (texres.talpha) texres.tin = texres.ta; - else texres.tin = rgb_to_grayscale(&texres.tr); + else texres.tin = IMB_colormanagement_get_luminance(&texres.tr); } if ((mapto_flag & MAP_EMISSION) && (mtex->mapto & MAP_EMISSION)) { @@ -2934,7 +2934,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4]) /* texture output */ if (rgb && (mtex->texflag & MTEX_RGBTOINT)) { - texres.tin = rgb_to_bw(&texres.tr); + texres.tin = IMB_colormanagement_get_luminance(&texres.tr); rgb= 0; } if (mtex->texflag & MTEX_NEGATIVE) { @@ -3006,7 +3006,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4]) texres.tin = texres.ta; } else { - texres.tin = rgb_to_bw(&texres.tr); + texres.tin = IMB_colormanagement_get_luminance(&texres.tr); } } @@ -3140,7 +3140,7 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h /* texture output */ if (rgb && (mtex->texflag & MTEX_RGBTOINT)) { - texres.tin = rgb_to_bw(&texres.tr); + texres.tin = IMB_colormanagement_get_luminance(&texres.tr); rgb= 0; } if (mtex->texflag & MTEX_NEGATIVE) { @@ -3215,7 +3215,7 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h } } if (mtex->mapto & WOMAP_BLEND) { - if (rgb) texres.tin = rgb_to_bw(&texres.tr); + if (rgb) texres.tin = IMB_colormanagement_get_luminance(&texres.tr); *blend= texture_value_blend(mtex->def_var, *blend, texres.tin, mtex->blendfac, mtex->blendtype); } @@ -3356,7 +3356,7 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r /* texture output */ if (rgb && (mtex->texflag & MTEX_RGBTOINT)) { - texres.tin = rgb_to_bw(&texres.tr); + texres.tin = IMB_colormanagement_get_luminance(&texres.tr); rgb= 0; } if (mtex->texflag & MTEX_NEGATIVE) { @@ -3455,7 +3455,7 @@ int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, rgb = multitex(tex, texvec, dxt, dyt, 0, &texr, thread, mtex->which_output, pool, skip_load_image); if (rgb) { - texr.tin = rgb_to_bw(&texr.tr); + texr.tin = IMB_colormanagement_get_luminance(&texr.tr); } else { texr.tr= mtex->r; diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 63a97a04b39..586345d1eb4 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -55,6 +55,8 @@ #include "shading.h" /* own include */ +#include "IMB_colormanagement.h" + /* could enable at some point but for now there are far too many conversions */ #ifdef __GNUC__ # pragma GCC diagnostic ignored "-Wdouble-promotion" @@ -948,7 +950,7 @@ static void ramp_diffuse_result(float *diff, ShadeInput *shi) if (ma->ramp_col) { if (ma->rampin_col==MA_RAMP_IN_RESULT) { - float fac = rgb_to_grayscale(diff); + float fac = IMB_colormanagement_get_luminance(diff); do_colorband(ma->ramp_col, fac, col); /* blending method */ @@ -980,7 +982,7 @@ static void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, floa /* input */ switch (ma->rampin_col) { case MA_RAMP_IN_ENERGY: - /* should use 'rgb_to_grayscale' but we only have a vector version */ + /* should use 'IMB_colormanagement_get_luminance' but we only have a vector version */ fac= 0.3f*r + 0.58f*g + 0.12f*b; break; case MA_RAMP_IN_SHADER: @@ -1023,7 +1025,7 @@ static void ramp_spec_result(float spec_col[3], ShadeInput *shi) if (ma->ramp_spec && (ma->rampin_spec==MA_RAMP_IN_RESULT)) { float col[4]; - float fac = rgb_to_grayscale(spec_col); + float fac = IMB_colormanagement_get_luminance(spec_col); do_colorband(ma->ramp_spec, fac, col); @@ -1619,10 +1621,10 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr) if (shi->mat->shadowonly_flag == MA_SO_OLD) { /* Old "Shadows Only" */ - accum+= (1.0f-visifac) + (visifac)*rgb_to_grayscale(shadfac)*shadfac[3]; + accum+= (1.0f-visifac) + (visifac)*IMB_colormanagement_get_luminance(shadfac)*shadfac[3]; } else { - shaded += rgb_to_grayscale(shadfac)*shadfac[3] * visifac * lar->energy; + shaded += IMB_colormanagement_get_luminance(shadfac)*shadfac[3] * visifac * lar->energy; if (shi->mat->shadowonly_flag == MA_SO_SHADOW) { lightness += visifac * lar->energy; @@ -1671,26 +1673,26 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr) if (R.wrld.aomix==WO_AOADD) { if (shi->mat->shadowonly_flag == MA_SO_OLD) { - f= f*(1.0f - rgb_to_grayscale(shi->ao)); + f= f*(1.0f - IMB_colormanagement_get_luminance(shi->ao)); shr->alpha= (shr->alpha + f)*f; } else { - shr->alpha -= f*rgb_to_grayscale(shi->ao); + shr->alpha -= f*IMB_colormanagement_get_luminance(shi->ao); if (shr->alpha<0.0f) shr->alpha=0.0f; } } else /* AO Multiply */ - shr->alpha= (1.0f - f)*shr->alpha + f*(1.0f - (1.0f - shr->alpha)*rgb_to_grayscale(shi->ao)); + shr->alpha= (1.0f - f)*shr->alpha + f*(1.0f - (1.0f - shr->alpha)*IMB_colormanagement_get_luminance(shi->ao)); } if (R.wrld.mode & WO_ENV_LIGHT) { if (shi->mat->shadowonly_flag == MA_SO_OLD) { - f= R.wrld.ao_env_energy*shi->amb*(1.0f - rgb_to_grayscale(shi->env)); + f= R.wrld.ao_env_energy*shi->amb*(1.0f - IMB_colormanagement_get_luminance(shi->env)); shr->alpha= (shr->alpha + f)*f; } else { f= R.wrld.ao_env_energy*shi->amb; - shr->alpha -= f*rgb_to_grayscale(shi->env); + shr->alpha -= f*IMB_colormanagement_get_luminance(shi->env); if (shr->alpha<0.0f) shr->alpha=0.0f; } } diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c index d5c4c407bf6..2c0917243a3 100644 --- a/source/blender/render/intern/source/volumetric.c +++ b/source/blender/render/intern/source/volumetric.c @@ -41,6 +41,8 @@ #include "RE_shader_ext.h" +#include "IMB_colormanagement.h" + #include "DNA_material_types.h" #include "DNA_group_types.h" #include "DNA_lamp_types.h" @@ -504,7 +506,7 @@ static void vol_shade_one_lamp(struct ShadeInput *shi, const float co[3], const if (shi->mat->vol.shadeflag & MA_VOL_RECV_EXT_SHADOW) { mul_v3_fl(lacol, vol_get_shadow(shi, lar, co)); - if (rgb_to_luma_y(lacol) < 0.001f) return; + if (IMB_colormanagement_get_luminance(lacol) < 0.001f) return; } /* find minimum of volume bounds, or lamp coord */ @@ -538,7 +540,7 @@ static void vol_shade_one_lamp(struct ShadeInput *shi, const float co[3], const } } - if (rgb_to_luma_y(lacol) < 0.001f) return; + if (IMB_colormanagement_get_luminance(lacol) < 0.001f) return; normalize_v3(lv); p = vol_get_phasefunc(shi, shi->mat->vol.asymmetry, view, lv); @@ -620,7 +622,7 @@ static void volumeintegrate(struct ShadeInput *shi, float col[4], const float co if (t0 > t1 * 0.25f) { /* only use depth cutoff after we've traced a little way into the volume */ - if (rgb_to_luma_y(tr) < shi->mat->vol.depth_cutoff) break; + if (IMB_colormanagement_get_luminance(tr) < shi->mat->vol.depth_cutoff) break; } vol_get_emission(shi, emit_col, p); @@ -649,7 +651,7 @@ static void volumeintegrate(struct ShadeInput *shi, float col[4], const float co add_v3_v3(col, radiance); /* alpha <-- transmission luminance */ - col[3] = 1.0f - rgb_to_luma_y(tr); + col[3] = 1.0f - IMB_colormanagement_get_luminance(tr); } /* the main entry point for volume shading */ @@ -790,7 +792,7 @@ void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct copy_v3_v3(shr->combined, tr); - shr->combined[3] = 1.0f - rgb_to_luma_y(tr); + shr->combined[3] = 1.0f - IMB_colormanagement_get_luminance(tr); shr->alpha = shr->combined[3]; } -- cgit v1.2.3 From a43d00d51e15a311dfab1b87c7c9065f4081e625 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 17 Mar 2015 19:36:29 +0500 Subject: Cycles: Fix displacement code creating cyclic dependencies in graph Bump result was passed to set_normal node and then set_node was connected to all unconnected Normal inputs, including the one from original Bump node, causing cycles. --- intern/cycles/render/graph.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 9896eaba89b..5b81a2ccb9e 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -727,10 +727,18 @@ void ShaderGraph::bump_from_displacement() /* connect bump output to normal input nodes that aren't set yet. actually * this will only set the normal input to the geometry node that we created * and connected to all other normal inputs already. */ - foreach(ShaderNode *node, nodes) - foreach(ShaderInput *input, node->inputs) + foreach(ShaderNode *node, nodes) { + /* Don't connect normal to the bump node we're coming from, + * otherwise it'll be a cycle in graph. + */ + if(node == bump) { + continue; + } + foreach(ShaderInput *input, node->inputs) { if(!input->link && input->default_value == ShaderInput::NORMAL) connect(set_normal->output("Normal"), input); + } + } /* for displacement bump, clear the normal input in case the above loop * connected the setnormal out to the bump normalin */ -- cgit v1.2.3 From 948bc66a004d15324236f516a9b05001a39e1610 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 17 Mar 2015 21:15:17 +0500 Subject: Cycles: Improve readability of dumped graphs --- intern/cycles/render/graph.cpp | 44 +++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 5b81a2ccb9e..4767bbb4806 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -844,29 +844,59 @@ void ShaderGraph::dump_graph(const char *filename) fprintf(fd, "digraph shader_graph {\n"); fprintf(fd, "ranksep=1.5\n"); + fprintf(fd, "rankdir=LR\n"); fprintf(fd, "splines=false\n"); foreach(ShaderNode *node, nodes) { fprintf(fd, "// NODE: %p\n", node); - fprintf(fd, - "\"%p\" [shape=record,label=\"%s\"]\n", - node, - node->name.c_str()); + fprintf(fd, "\"%p\" [shape=record,label=\"{", node); + if(node->inputs.size()) { + fprintf(fd, "{"); + foreach(ShaderInput *socket, node->inputs) { + if(socket != node->inputs[0]) { + fprintf(fd, "|"); + } + fprintf(fd, "%s", socket, socket->name); + } + fprintf(fd, "}|"); + } + fprintf(fd, "%s", node->name.c_str()); + if(node->bump == SHADER_BUMP_CENTER) { + fprintf(fd, " (bump:center)"); + } + else if(node->bump == SHADER_BUMP_DX) { + fprintf(fd, " (bump:dx)"); + } + else if(node->bump == SHADER_BUMP_DY) { + fprintf(fd, " (bump:dy)"); + } + if(node->outputs.size()) { + fprintf(fd, "|{"); + foreach(ShaderOutput *socket, node->outputs) { + if(socket != node->outputs[0]) { + fprintf(fd, "|"); + } + fprintf(fd, "%s", socket, socket->name); + } + fprintf(fd, "}"); + } + fprintf(fd, "}\"]"); } foreach(ShaderNode *node, nodes) { foreach(ShaderOutput *output, node->outputs) { foreach(ShaderInput *input, output->links) { fprintf(fd, - "// CONNECTION: %p->%p (%s:%s)\n", + "// CONNECTION: OUT_%p->IN_%p (%s:%s)\n", output, input, output->name, input->name); fprintf(fd, - "\"%p\":s -> \"%p\":n [label=\"%s:%s\"]\n", + "\"\%p\":\"OUT_%p\":e -> \"%p\":\"IN_%p\":w [label=\"\"]\n", output->parent, + output, input->parent, - output->name, input->name); + input); } } } -- cgit v1.2.3 From 6ceb84c21724c6c3278abb1bfc27813f7a8f4036 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 17 Mar 2015 18:13:35 +0100 Subject: BLI math vec: add 'abs' functions to get absolute values of a vector. Unseful when handling e.g. scale, sometimes. --- source/blender/blenlib/BLI_math_vector.h | 7 ++++ source/blender/blenlib/intern/math_vector_inline.c | 42 ++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index ffd80f46725..de712cbaa12 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -146,6 +146,13 @@ MINLINE void negate_v4_v4(float r[4], const float a[3]); MINLINE void negate_v3_short(short r[3]); +MINLINE void abs_v2(float r[2]); +MINLINE void abs_v2_v2(float r[2], const float a[2]); +MINLINE void abs_v3(float r[3]); +MINLINE void abs_v3_v3(float r[3], const float a[3]); +MINLINE void abs_v4(float r[4]); +MINLINE void abs_v4_v4(float r[4], const float a[4]); + MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT; MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT; MINLINE float dot_v3v3v3(const float p[3], const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index 6b6a3113e0b..89ae23fd448 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -611,6 +611,48 @@ MINLINE void negate_v3_short(short r[3]) r[2] = (short)-r[2]; } +MINLINE void abs_v2(float r[2]) +{ + r[0] = fabs(r[0]); + r[1] = fabs(r[1]); +} + +MINLINE void abs_v2_v2(float r[2], const float a[2]) +{ + r[0] = fabs(a[0]); + r[1] = fabs(a[1]); +} + +MINLINE void abs_v3(float r[3]) +{ + r[0] = fabs(r[0]); + r[1] = fabs(r[1]); + r[2] = fabs(r[2]); +} + +MINLINE void abs_v3_v3(float r[3], const float a[3]) +{ + r[0] = fabs(a[0]); + r[1] = fabs(a[1]); + r[2] = fabs(a[2]); +} + +MINLINE void abs_v4(float r[4]) +{ + r[0] = fabs(r[0]); + r[1] = fabs(r[1]); + r[2] = fabs(r[2]); + r[3] = fabs(r[3]); +} + +MINLINE void abs_v4_v4(float r[4], const float a[4]) +{ + r[0] = fabs(a[0]); + r[1] = fabs(a[1]); + r[2] = fabs(a[2]); + r[3] = fabs(a[3]); +} + MINLINE float dot_v2v2(const float a[2], const float b[2]) { return a[0] * b[0] + a[1] * b[1]; -- cgit v1.2.3 From 2ab4489f179eebb1f1070a1d32f01f4e7f0c85c7 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 17 Mar 2015 18:14:38 +0100 Subject: Fix T44027: Normal Edit Mod : Radial from object normals affected by target object scale. The way we were getting diff to apply to vcos from target object was just bad! Also, fixed another related issue - negated scale would be clamped to nearly zero, now only consider absolute version of size (we do not care about its sign here anyway). This should be backported to 2.74 (with previous commit too). --- source/blender/modifiers/intern/MOD_normal_edit.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index edb7278789b..80636986583 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -60,7 +60,8 @@ static void generate_vert_coordinates( /* Get size (i.e. deformation of the spheroid generating normals), either from target object, or own geometry. */ if (ob_center) { - copy_v3_v3(r_size, ob_center->size); + /* Not we are not interested in signs here - they are even troublesome actually, due to security clamping! */ + abs_v3_v3(r_size, ob_center->size); } else { minmax_v3v3_v3_array(min_co, max_co, r_cos, num_verts); @@ -80,12 +81,10 @@ static void generate_vert_coordinates( if (ob_center) { /* Translate our coordinates so that center of ob_center is at (0, 0, 0). */ - float mat[4][4]; - - /* Get ob_center coordinates in ob local coordinates. */ - invert_m4_m4(mat, ob_center->obmat); - mul_m4_m4m4(mat, mat, ob->obmat); - copy_v3_v3(diff, mat[3]); + /* Get ob_center (world) coordinates in ob local coordinates. + * No need to take into accound ob_center's space here, see T44027. */ + mul_v3_m4v3(diff, ob->obmat, ob_center->obmat[3]); + negate_v3(diff); do_diff = true; } -- cgit v1.2.3 From 63897304a90a8b13304771af0f466f6d13cb9227 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 18 Mar 2015 00:09:54 +0500 Subject: Fix T44028: Vertex Colors Baking error Was wrong color management flag used for some bakers. Actually goes back to 7997e38. --- source/blender/render/intern/source/bake.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c index 4aa2f4e919e..b602753dff4 100644 --- a/source/blender/render/intern/source/bake.c +++ b/source/blender/render/intern/source/bake.c @@ -984,8 +984,12 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up int a, vdone = false, result = BAKE_RESULT_OK; bool use_mask = false; bool use_displacement_buffer = false; - bool do_manage = BKE_scene_check_color_management_enabled(re->scene); - + bool do_manage = false; + + if (ELEM(type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) { + do_manage = BKE_scene_check_color_management_enabled(re->scene); + } + re->scene_color_manage = BKE_scene_check_color_management_enabled(re->scene); /* initialize render global */ -- cgit v1.2.3 From d0fcbab15283efa35b30c9950cbdd762c5ae411e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 18 Mar 2015 15:14:32 +1100 Subject: Fix RNA active spline assignment --- source/blender/makesrna/intern/rna_curve.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 29f1dd5f29f..9a9ac28a7fd 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -1300,16 +1300,13 @@ static void rna_def_curve_splines(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "clear", "rna_Curve_spline_clear"); - RNA_def_function_ui_description(func, "Remove all spline from a curve"); + RNA_def_function_ui_description(func, "Remove all splines from a curve"); prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); - RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_struct_type(prop, "Spline"); RNA_def_property_pointer_funcs(prop, "rna_Curve_active_spline_get", "rna_Curve_active_spline_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Active Spline", "Active curve spline"); - /* Could call: ED_base_object_activate(C, scene->basact); - * but would be a bad level call and it seems the notifier is enough */ - RNA_def_property_update(prop, NC_SCENE | ND_OB_ACTIVE, NULL); } -- cgit v1.2.3 From db710e6c0d8c40a3df75cb14411f4ae51e62dfec Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 18 Mar 2015 15:50:29 +1100 Subject: Fix crash using removed data as function arguments --- source/blender/python/intern/bpy_rna.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index fadc50e3317..2aab7e070c0 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -1829,26 +1829,24 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb else if (RNA_struct_is_a(param->ptr.type, ptr_type)) { RNA_property_pointer_set(ptr, prop, param->ptr); } + else { + raise_error = true; + } + } + + if (raise_error) { + if (pyrna_struct_validity_check(param) == -1) { + /* error set */ + } else { PointerRNA tmp; RNA_pointer_create(NULL, ptr_type, NULL, &tmp); PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a %.200s type. not %.200s", + "%.200s %.200s.%.200s expected a %.200s type, not %.200s", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), RNA_struct_identifier(tmp.type), RNA_struct_identifier(param->ptr.type)); - Py_XDECREF(value_new); return -1; } - } - - if (raise_error) { - PointerRNA tmp; - RNA_pointer_create(NULL, ptr_type, NULL, &tmp); - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a %.200s type, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), RNA_struct_identifier(tmp.type), - RNA_struct_identifier(param->ptr.type)); Py_XDECREF(value_new); return -1; } } -- cgit v1.2.3 From a975a3ca63d155e9ee1f0ba96fd451c330885aaa Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 18 Mar 2015 14:03:59 +1100 Subject: RNA: move palette into its own file --- source/blender/makesrna/intern/CMakeLists.txt | 1 + source/blender/makesrna/intern/makesrna.c | 1 + source/blender/makesrna/intern/rna_internal.h | 1 + source/blender/makesrna/intern/rna_palette.c | 93 +++++++++++++++++++++++ source/blender/makesrna/intern/rna_sculpt_paint.c | 45 ----------- 5 files changed, 96 insertions(+), 45 deletions(-) create mode 100644 source/blender/makesrna/intern/rna_palette.c diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index fa7fd6da8bb..69c5955c454 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -67,6 +67,7 @@ set(DEFSRC rna_object.c rna_object_force.c rna_packedfile.c + rna_palette.c rna_particle.c rna_pose.c rna_property.c diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index e0075414615..894d5ef20a8 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -3309,6 +3309,7 @@ static RNAProcessItem PROCESS_ITEMS[] = { {"rna_object.c", "rna_object_api.c", RNA_def_object}, {"rna_object_force.c", NULL, RNA_def_object_force}, {"rna_packedfile.c", NULL, RNA_def_packedfile}, + {"rna_palette.c", NULL, RNA_def_palette}, {"rna_particle.c", NULL, RNA_def_particle}, {"rna_pose.c", "rna_pose_api.c", RNA_def_pose}, {"rna_property.c", NULL, RNA_def_gameproperty}, diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index f225387baa4..da657a70e4e 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -164,6 +164,7 @@ void RNA_def_nodetree(struct BlenderRNA *brna); void RNA_def_object(struct BlenderRNA *brna); void RNA_def_object_force(struct BlenderRNA *brna); void RNA_def_packedfile(struct BlenderRNA *brna); +void RNA_def_palette(struct BlenderRNA *brna); void RNA_def_particle(struct BlenderRNA *brna); void RNA_def_pose(struct BlenderRNA *brna); void RNA_def_render(struct BlenderRNA *brna); diff --git a/source/blender/makesrna/intern/rna_palette.c b/source/blender/makesrna/intern/rna_palette.c new file mode 100644 index 00000000000..54e5881a44c --- /dev/null +++ b/source/blender/makesrna/intern/rna_palette.c @@ -0,0 +1,93 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/makesrna/intern/rna_palette.c + * \ingroup RNA + */ + +#include + +#include "BLI_utildefines.h" + +#include "RNA_define.h" + +#include "rna_internal.h" + +#include "WM_types.h" + +#ifdef RNA_RUNTIME + +#include "DNA_brush_types.h" + +#else + + +static void rna_def_palettecolor(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "PaletteColor", NULL); + RNA_def_struct_ui_text(srna, "Palette Color", ""); + + prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_float_sdna(prop, NULL, "rgb"); + RNA_def_property_ui_text(prop, "Color", ""); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); + + prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_float_sdna(prop, NULL, "value"); + RNA_def_property_ui_text(prop, "Value", ""); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); + + prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_float_sdna(prop, NULL, "value"); + RNA_def_property_ui_text(prop, "Weight", ""); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); +} + +static void rna_def_palette(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "Palette", "ID"); + RNA_def_struct_ui_text(srna, "Palette", ""); + RNA_def_struct_ui_icon(srna, ICON_COLOR); + + prop = RNA_def_property(srna, "colors", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "PaletteColor"); + RNA_def_property_ui_text(prop, "Palette Color", "Colors that are part of this palette"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); +} + +void RNA_def_palette(BlenderRNA *brna) +{ + /* *** Non-Animated *** */ + RNA_define_animate_sdna(false); + rna_def_palettecolor(brna); + rna_def_palette(brna); + RNA_define_animate_sdna(true); +} + +#endif diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index e09e0354e0b..b98652de759 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -361,49 +361,6 @@ static int rna_ImaPaint_detect_data(ImagePaintSettings *imapaint) } #else -static void rna_def_palettecolor(BlenderRNA *brna) -{ - StructRNA *srna; - PropertyRNA *prop; - - srna = RNA_def_struct(brna, "PaletteColor", NULL); - RNA_def_struct_ui_text(srna, "Palette Color", ""); - - prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); - RNA_def_property_range(prop, 0.0, 1.0); - RNA_def_property_float_sdna(prop, NULL, "rgb"); - RNA_def_property_ui_text(prop, "Color", ""); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - - prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); - RNA_def_property_range(prop, 0.0, 1.0); - RNA_def_property_float_sdna(prop, NULL, "value"); - RNA_def_property_ui_text(prop, "Value", ""); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - - prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_NONE); - RNA_def_property_range(prop, 0.0, 1.0); - RNA_def_property_float_sdna(prop, NULL, "value"); - RNA_def_property_ui_text(prop, "Weight", ""); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); -} - - -static void rna_def_palette(BlenderRNA *brna) -{ - StructRNA *srna; - PropertyRNA *prop; - - srna = RNA_def_struct(brna, "Palette", "ID"); - RNA_def_struct_ui_text(srna, "Palette", ""); - RNA_def_struct_ui_icon(srna, ICON_COLOR); - - prop = RNA_def_property(srna, "colors", PROP_COLLECTION, PROP_NONE); - RNA_def_property_struct_type(prop, "PaletteColor"); - RNA_def_property_ui_text(prop, "Palette Color", "Colors that are part of this palette"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); -} - static void rna_def_paint_curve(BlenderRNA *brna) { StructRNA *srna; @@ -962,8 +919,6 @@ void RNA_def_sculpt_paint(BlenderRNA *brna) { /* *** Non-Animated *** */ RNA_define_animate_sdna(false); - rna_def_palettecolor(brna); - rna_def_palette(brna); rna_def_paint_curve(brna); rna_def_paint(brna); rna_def_sculpt(brna); -- cgit v1.2.3 From 29195197147a882849859ea963cae42484dfeaba Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 18 Mar 2015 15:09:04 +1100 Subject: RNA: palette colors api Methods so Python can manage colors. palette.colors.new()/remove()/clear()/active --- source/blender/blenkernel/BKE_paint.h | 2 + source/blender/blenkernel/intern/paint.c | 35 +++++++-- source/blender/editors/sculpt_paint/paint_ops.c | 9 ++- source/blender/editors/sculpt_paint/paint_utils.c | 1 + source/blender/makesrna/intern/rna_palette.c | 92 ++++++++++++++++++++++- 5 files changed, 127 insertions(+), 12 deletions(-) diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 3e4e6ab4146..58c0b495062 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -102,8 +102,10 @@ void BKE_palette_free(struct Palette *palette); struct Palette *BKE_palette_add(struct Main *bmain, const char *name); struct PaletteColor *BKE_palette_color_add(struct Palette *palette); bool BKE_palette_is_empty(const struct Palette *palette); +void BKE_palette_color_remove_ex(struct Palette *palette, struct PaletteColor *color, bool use_free); void BKE_palette_color_remove(struct Palette *palette, struct PaletteColor *color); void BKE_palette_cleanup(struct Palette *palette); +void BKE_palette_clear(struct Palette *palette); /* paint curves */ struct PaintCurve *BKE_paint_curve_add(struct Main *bmain, const char *name); diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 431eec0d220..2082066d395 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -314,18 +314,38 @@ void BKE_paint_curve_set(Brush *br, PaintCurve *pc) } /* remove colour from palette. Must be certain color is inside the palette! */ -void BKE_palette_color_remove(Palette *palette, PaletteColor *color) +void BKE_palette_color_remove_ex(Palette *palette, PaletteColor *color, bool use_free) { - if (color) { - int numcolors = BLI_listbase_count(&palette->colors); - if ((numcolors == palette->active_color + 1) && (numcolors != 1)) - palette->active_color--; - - BLI_remlink(&palette->colors, color); + if (BLI_listbase_count_ex(&palette->colors, palette->active_color) == palette->active_color) { + palette->active_color--; + } + + BLI_remlink(&palette->colors, color); + + if (palette->active_color < 0 && !BLI_listbase_is_empty(&palette->colors)) { + palette->active_color = 0; + } + + if (use_free) { + MEM_freeN(color); + } + else { BLI_addhead(&palette->deleted, color); } } +void BKE_palette_color_remove(Palette *palette, PaletteColor *color) +{ + BKE_palette_color_remove_ex(palette, color, false); +} + +void BKE_palette_clear(Palette *palette) +{ + BLI_freelistN(&palette->colors); + BLI_freelistN(&palette->deleted); + palette->active_color = 0; +} + void BKE_palette_cleanup(Palette *palette) { BLI_freelistN(&palette->deleted); @@ -353,7 +373,6 @@ PaletteColor *BKE_palette_color_add(Palette *palette) { PaletteColor *color = MEM_callocN(sizeof(*color), "Pallete Color"); BLI_addtail(&palette->colors, color); - palette->active_color = BLI_listbase_count(&palette->colors) - 1; return color; } diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 121b0b83a4b..eebd49895ef 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -196,7 +196,10 @@ static int palette_color_add_exec(bContext *C, wmOperator *UNUSED(op)) Brush *brush = paint->brush; PaintMode mode = BKE_paintmode_get_active_from_context(C); Palette *palette = paint->palette; - PaletteColor *color = BKE_palette_color_add(palette); + PaletteColor *color; + + color = BKE_palette_color_add(palette); + palette->active_color = BLI_listbase_count(&palette->colors) - 1; if (ELEM(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX)) { copy_v3_v3(color->rgb, BKE_brush_color_get(scene, brush)); @@ -231,7 +234,9 @@ static int palette_color_delete_exec(bContext *C, wmOperator *UNUSED(op)) Palette *palette = paint->palette; PaletteColor *color = BLI_findlink(&palette->colors, palette->active_color); - BKE_palette_color_remove(palette, color); + if (color) { + BKE_palette_color_remove(palette, color); + } return OPERATOR_FINISHED; } diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index c0ed5005397..b19cced2f8e 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -439,6 +439,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr } color = BKE_palette_color_add(palette); + palette->active_color = BLI_listbase_count(&palette->colors) - 1; } diff --git a/source/blender/makesrna/intern/rna_palette.c b/source/blender/makesrna/intern/rna_palette.c index 54e5881a44c..7405df967a0 100644 --- a/source/blender/makesrna/intern/rna_palette.c +++ b/source/blender/makesrna/intern/rna_palette.c @@ -27,6 +27,7 @@ #include "BLI_utildefines.h" #include "RNA_define.h" +#include "RNA_access.h" #include "rna_internal.h" @@ -36,8 +37,96 @@ #include "DNA_brush_types.h" +#include "BKE_paint.h" +#include "BKE_report.h" + +static PaletteColor *rna_Palette_color_new(Palette *palette) +{ + PaletteColor *color = BKE_palette_color_add(palette); + return color; +} + +static void rna_Palette_color_remove(Palette *palette, ReportList *reports, PointerRNA *color_ptr) +{ + PaletteColor *color = color_ptr->data; + + if (BLI_findindex(&palette->colors, color) == -1) { + BKE_reportf(reports, RPT_ERROR, "Palette '%s' does not contain color given", palette->id.name + 2); + return; + } + + BKE_palette_color_remove_ex(palette, color, true); + + RNA_POINTER_INVALIDATE(color_ptr); +} + +static void rna_Palette_color_clear(Palette *palette) +{ + BKE_palette_clear(palette); +} + +static PointerRNA rna_Palette_active_color_get(PointerRNA *ptr) +{ + Palette *palette = ptr->data; + PaletteColor *color; + + color = BLI_findlink(&palette->colors, palette->active_color); + + if (color) + return rna_pointer_inherit_refine(ptr, &RNA_PaletteColor, color); + + return rna_pointer_inherit_refine(ptr, NULL, NULL); +} + +static void rna_Palette_active_color_set(PointerRNA *ptr, PointerRNA value) +{ + Palette *palette = ptr->data; + PaletteColor *color = value.data; + + /* -1 is ok for an unset index */ + if (color == NULL) + palette->active_color = -1; + else + palette->active_color = BLI_findindex(&palette->colors, color); +} + #else +/* palette.colors */ +static void rna_def_palettecolors(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + PropertyRNA *prop; + + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "PaletteColors"); + srna = RNA_def_struct(brna, "PaletteColors", NULL); + RNA_def_struct_sdna(srna, "Palette"); + RNA_def_struct_ui_text(srna, "Palette Splines", "Collection of palette colors"); + + func = RNA_def_function(srna, "new", "rna_Palette_color_new"); + RNA_def_function_ui_description(func, "Add a new color to the palette"); + parm = RNA_def_pointer(func, "color", "PaletteColor", "", "The newly created color"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_Palette_color_remove"); + RNA_def_function_ui_description(func, "Remove a color from the palette"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "color", "PaletteColor", "", "The color to remove"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); + + func = RNA_def_function(srna, "clear", "rna_Palette_color_clear"); + RNA_def_function_ui_description(func, "Remove all colors from the palette"); + + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "PaletteColor"); + RNA_def_property_pointer_funcs(prop, "rna_Palette_active_color_get", "rna_Palette_active_color_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Active Palette Color", ""); +} static void rna_def_palettecolor(BlenderRNA *brna) { @@ -77,8 +166,7 @@ static void rna_def_palette(BlenderRNA *brna) prop = RNA_def_property(srna, "colors", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "PaletteColor"); - RNA_def_property_ui_text(prop, "Palette Color", "Colors that are part of this palette"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); + rna_def_palettecolors(brna, prop); } void RNA_def_palette(BlenderRNA *brna) -- cgit v1.2.3 From ff1ed872d93b5c40f1de599d79084d48f213921d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 18 Mar 2015 18:50:33 +1100 Subject: Fix crash using "Copy to selected" on ID-props --- source/blender/makesrna/intern/rna_access.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 2a0fd14e13b..06fdf6d3b77 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -6517,6 +6517,12 @@ bool RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, /* In case of IDProperty, we have to find the *real* idprop of ptr, * since prop in this case is just a fake wrapper around actual IDProp data, and not a 'real' PropertyRNA. */ prop = (PropertyRNA *)rna_idproperty_find(ptr, ((IDProperty *)fromprop)->name); + + /* its possible the custom-prop doesn't exist on this datablock */ + if (prop == NULL) { + return false; + } + /* Even though currently we now prop will always be the 'fromprop', this might not be the case in the future. */ if (prop == fromprop) { fromprop = (PropertyRNA *)rna_idproperty_find(fromptr, ((IDProperty *)prop)->name); -- cgit v1.2.3 From aff4aa173a78c7bbd7d08666f995d48ea18cdb50 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 18 Mar 2015 12:40:53 +0100 Subject: Support UV island selection in UV synch and face select mode. Enough said, people wanted this for ages, enjoy! --- source/blender/editors/uvedit/uvedit_ops.c | 100 +++++++++++++++++++---------- 1 file changed, 67 insertions(+), 33 deletions(-) diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index c70fcdbbd94..444c579a62b 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -1114,7 +1114,7 @@ static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestH /*********************** linked select ***********************/ -static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float limit[2], NearestHit *hit, bool extend) +static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float limit[2], NearestHit *hit, bool extend, bool select_faces) { BMFace *efa; BMLoop *l; @@ -1131,7 +1131,7 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */ - vmap = BM_uv_vert_map_create(em->bm, 1, limit); + vmap = BM_uv_vert_map_create(em->bm, !select_faces, limit); if (vmap == NULL) return; @@ -1144,15 +1144,24 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, efa, tf)) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (luv->flag & MLOOPUV_VERTSEL) { + if (select_faces) { + if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { stack[stacksize] = a; stacksize++; flag[a] = 1; + } + } + else { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - break; + if (luv->flag & MLOOPUV_VERTSEL) { + stack[stacksize] = a; + stacksize++; + flag[a] = 1; + + break; + } } } } @@ -1204,13 +1213,21 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo if (!extend) { BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - + if (select_faces) { if (flag[a]) - luv->flag |= MLOOPUV_VERTSEL; + BM_face_select_set(em->bm, efa, true); else - luv->flag &= ~MLOOPUV_VERTSEL; + BM_face_select_set(em->bm, efa, false); + } + else { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + if (flag[a]) + luv->flag |= MLOOPUV_VERTSEL; + else + luv->flag &= ~MLOOPUV_VERTSEL; + } } } } @@ -1219,17 +1236,23 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo if (!flag[a]) { continue; } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (luv->flag & MLOOPUV_VERTSEL) { + + if (select_faces) { + if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) break; - } } - - if (l) { - break; + else { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + if (luv->flag & MLOOPUV_VERTSEL) { + break; + } + } + + if (l) { + break; + } } } @@ -1239,10 +1262,15 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo continue; } - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - luv->flag &= ~MLOOPUV_VERTSEL; + if (select_faces) { + BM_face_select_set(em->bm, efa, false); + } + else { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + luv->flag &= ~MLOOPUV_VERTSEL; + } } } } @@ -1252,10 +1280,15 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo continue; } - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - luv->flag |= MLOOPUV_VERTSEL; + if (select_faces) { + BM_face_select_set(em->bm, efa, true); + } + else { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + luv->flag |= MLOOPUV_VERTSEL; + } } } } @@ -2154,7 +2187,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo flush = uv_select_edgeloop(scene, ima, em, &hit, limit, extend); } else if (selectmode == UV_SELECT_ISLAND) { - uv_select_linked(scene, ima, em, limit, &hit, extend); + uv_select_linked(scene, ima, em, limit, &hit, extend, false); } else if (extend) { if (selectmode == UV_SELECT_VERTEX) { @@ -2375,11 +2408,12 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent BMEditMesh *em = BKE_editmesh_from_object(obedit); float limit[2]; int extend; + bool select_faces = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE); NearestHit hit, *hit_p = NULL; - if (ts->uv_flag & UV_SYNC_SELECTION) { - BKE_report(op->reports, RPT_ERROR, "Cannot select linked when sync selection is enabled"); + if ((ts->uv_flag & UV_SYNC_SELECTION) && !(ts->selectmode & SCE_SELECT_FACE)) { + BKE_report(op->reports, RPT_ERROR, "Select linked only works in face select mode when sync selection is enabled"); return OPERATOR_CANCELLED; } @@ -2405,7 +2439,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent hit_p = &hit; } - uv_select_linked(scene, ima, em, limit, hit_p, extend); + uv_select_linked(scene, ima, em, limit, hit_p, extend, select_faces); DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); -- cgit v1.2.3 From 3e5cd527834f8ae84d52ba208ba17f611fd0721d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 18 Mar 2015 17:17:04 +0500 Subject: Fix bad memory access freeing viewport which uses movie clip --- source/blender/blenkernel/intern/library.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index fa4f9c6ed52..c602067d5bd 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -610,13 +610,13 @@ int set_listbasepointers(Main *main, ListBase **lb) lb[a++] = &(main->speaker); lb[a++] = &(main->world); + lb[a++] = &(main->movieclip); lb[a++] = &(main->screen); lb[a++] = &(main->object); lb[a++] = &(main->linestyle); /* referenced by scenes */ lb[a++] = &(main->scene); lb[a++] = &(main->library); lb[a++] = &(main->wm); - lb[a++] = &(main->movieclip); lb[a++] = &(main->mask); lb[a] = NULL; -- cgit v1.2.3 From 72419eebc26ca17c588b3d7fe5ccbb0f22d33ad4 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 18 Mar 2015 13:48:37 +0100 Subject: Fix T44029 textures disappear in viewport if GPU mipmap generation is off. GPUs need a full tree of mipmaps up to dimension 1xn to work. This will make it so for all imbufs but cost is negligible and it's unlikely that something could break due to that. --- source/blender/imbuf/intern/filter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c index 352e230068b..7adb2c7cc1d 100644 --- a/source/blender/imbuf/intern/filter.c +++ b/source/blender/imbuf/intern/filter.c @@ -526,7 +526,7 @@ void IMB_makemipmap(ImBuf *ibuf, int use_filter) hbuf = ibuf->mipmap[curmap]; hbuf->miplevel = curmap + 1; - if (hbuf->x <= 2 && hbuf->y <= 2) + if (hbuf->x < 2 && hbuf->y < 2) break; curmap++; -- cgit v1.2.3 From 9231d35caac39bf4e444cb08979859c313963a53 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 18 Mar 2015 14:09:03 +0100 Subject: Simplify math in mix_linear glsl function. Thanks to valentin for pointing out on irc. --- source/blender/gpu/shaders/gpu_shader_material.glsl | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 945b7ef303f..5268dea5d55 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -698,22 +698,7 @@ void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol) { fac = clamp(fac, 0.0, 1.0); - outcol = col1; - - if(col2.r > 0.5) - outcol.r= col1.r + fac*(2.0*(col2.r - 0.5)); - else - outcol.r= col1.r + fac*(2.0*(col2.r) - 1.0); - - if(col2.g > 0.5) - outcol.g= col1.g + fac*(2.0*(col2.g - 0.5)); - else - outcol.g= col1.g + fac*(2.0*(col2.g) - 1.0); - - if(col2.b > 0.5) - outcol.b= col1.b + fac*(2.0*(col2.b - 0.5)); - else - outcol.b= col1.b + fac*(2.0*(col2.b) - 1.0); + outcol = col1 + fac*(2.0*(col2 - vec4(0.5))); } void valtorgb(float fac, sampler2D colormap, out vec4 outcol, out float outalpha) -- cgit v1.2.3 From 64451f0928a82a344f596d931ec6a581b5fcf586 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Mar 2015 01:09:41 +1100 Subject: Fix for crash adding mask modifier --- source/blender/blenkernel/intern/seqmodifier.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index b78529f51b4..edd3d8efd55 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -531,15 +531,11 @@ static void maskmodifier_apply_threaded(int width, int height, unsigned char *re } } -static void maskmodifier_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +static void maskmodifier_apply(struct SequenceModifierData *UNUSED(smd), ImBuf *ibuf, ImBuf *mask) { - BrightContrastModifierData *bcmd = (BrightContrastModifierData *) smd; - BrightContrastThreadData data; - - data.bright = bcmd->bright; - data.contrast = bcmd->contrast; + // SequencerMaskModifierData *bcmd = (SequencerMaskModifierData *)smd; - modifier_apply_threaded(ibuf, mask, maskmodifier_apply_threaded, &data); + modifier_apply_threaded(ibuf, mask, maskmodifier_apply_threaded, NULL); } static SequenceModifierTypeInfo seqModifier_Mask = { -- cgit v1.2.3 From 1dd1d286c67ef1948bd717a8c52e9667cf3382b1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Mar 2015 04:40:43 +1100 Subject: Select nth option to skip steps Patch T43752 @codemanx, added matching curve option. --- source/blender/editors/curve/editcurve.c | 30 +++++++++++++++++---------- source/blender/editors/include/ED_curve.h | 2 +- source/blender/editors/mesh/editmesh_select.c | 23 ++++++++++---------- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 936a40b83b6..cbbee2f206f 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -6142,7 +6142,7 @@ void CURVE_OT_select_random(wmOperatorType *ot) /********************* every nth number of point *******************/ -static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth) +static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth, int skip, int offset) { int a, start; @@ -6151,7 +6151,8 @@ static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth) bezt = &nu->bezt[a - 1]; while (a--) { - if (abs(start - a) % nth) { + const int depth = abs(start - a); + if ((offset + depth) % (skip + nth) >= skip) { select_beztriple(bezt, DESELECT, SELECT, HIDDEN); } @@ -6159,10 +6160,10 @@ static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth) } } -static void select_nth_bp(Nurb *nu, BPoint *bp, int nth) +static void select_nth_bp(Nurb *nu, BPoint *bp, int nth, int skip, int offset) { int a, startrow, startpnt; - int dist, row, pnt; + int row, pnt; startrow = (bp - nu->bp) / nu->pntsu; startpnt = (bp - nu->bp) % nu->pntsu; @@ -6173,8 +6174,8 @@ static void select_nth_bp(Nurb *nu, BPoint *bp, int nth) pnt = nu->pntsu - 1; while (a--) { - dist = abs(pnt - startpnt) + abs(row - startrow); - if (dist % nth) { + const int depth = abs(pnt - startpnt) + abs(row - startrow); + if ((offset + depth) % (skip + nth) >= skip) { select_bpoint(bp, DESELECT, SELECT, HIDDEN); } @@ -6188,7 +6189,7 @@ static void select_nth_bp(Nurb *nu, BPoint *bp, int nth) } } -bool ED_curve_select_nth(Curve *cu, int nth) +bool ED_curve_select_nth(Curve *cu, int nth, int skip, int offset) { Nurb *nu = NULL; void *vert = NULL; @@ -6197,10 +6198,10 @@ bool ED_curve_select_nth(Curve *cu, int nth) return false; if (nu->bezt) { - select_nth_bezt(nu, vert, nth); + select_nth_bezt(nu, vert, nth, skip, offset); } else { - select_nth_bp(nu, vert, nth); + select_nth_bp(nu, vert, nth, skip, offset); } return true; @@ -6209,9 +6210,14 @@ bool ED_curve_select_nth(Curve *cu, int nth) static int select_nth_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); - int nth = RNA_int_get(op->ptr, "nth"); + const int nth = RNA_int_get(op->ptr, "nth") - 1; + const int skip = RNA_int_get(op->ptr, "skip"); + int offset = RNA_int_get(op->ptr, "offset"); - if (!ED_curve_select_nth(obedit->data, nth)) { + /* so input of offset zero ends up being (nth - 1) */ + offset = mod_i(offset, nth + skip); + + if (!ED_curve_select_nth(obedit->data, nth, skip, offset)) { if (obedit->type == OB_SURF) { BKE_report(op->reports, RPT_ERROR, "Surface has not got active point"); } @@ -6242,6 +6248,8 @@ void CURVE_OT_select_nth(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_int(ot->srna, "nth", 2, 2, INT_MAX, "Nth Selection", "", 2, 100); + RNA_def_int(ot->srna, "skip", 1, 1, INT_MAX, "Skip", "", 1, 100); + RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "", -100, 100); } /********************** add duplicate operator *********************/ diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h index 27e9cad4fd5..982e17cfce4 100644 --- a/source/blender/editors/include/ED_curve.h +++ b/source/blender/editors/include/ED_curve.h @@ -79,7 +79,7 @@ void free_editText(struct Object *obedit); void ED_text_to_object(struct bContext *C, struct Text *text, const bool split_lines); -bool ED_curve_select_nth(struct Curve *cu, int nth); +bool ED_curve_select_nth(struct Curve *cu, int nth, int skip, int offset); void ED_curve_beztcpy(struct EditNurb *editnurb, struct BezTriple *dst, struct BezTriple *src, int count); void ED_curve_bpcpy(struct EditNurb *editnurb, struct BPoint *dst, struct BPoint *src, int count); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index d3073d519f6..c020243c8ff 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2552,7 +2552,7 @@ static bool bm_edge_is_select_isolated(BMEdge *e) /* Walk all reachable elements of the same type as h_act in breadth-first * order, starting from h_act. Deselects elements if the depth when they * are reached is not a multiple of "nth". */ -static void walker_deselect_nth(BMEditMesh *em, int nth, int offset, BMHeader *h_act) +static void walker_deselect_nth(BMEditMesh *em, int nth, int skip, int offset, BMHeader *h_act) { BMElem *ele; BMesh *bm = em->bm; @@ -2618,7 +2618,8 @@ static void walker_deselect_nth(BMEditMesh *em, int nth, int offset, BMHeader *h for (ele = BMW_begin(&walker, h_act); ele != NULL; ele = BMW_step(&walker)) { if (!BM_elem_flag_test(ele, BM_ELEM_TAG)) { /* Deselect elements that aren't at "nth" depth from active */ - if ((offset + BMW_current_depth(&walker)) % nth) { + const int depth = BMW_current_depth(&walker) - 1; + if ((offset + depth) % (skip + nth) >= skip) { BM_elem_select_set(bm, ele, false); } BM_elem_flag_enable(ele, BM_ELEM_TAG); @@ -2685,7 +2686,7 @@ static void deselect_nth_active(BMEditMesh *em, BMVert **r_eve, BMEdge **r_eed, } } -static bool edbm_deselect_nth(BMEditMesh *em, int nth, int offset) +static bool edbm_deselect_nth(BMEditMesh *em, int nth, int skip, int offset) { BMVert *v; BMEdge *e; @@ -2694,15 +2695,15 @@ static bool edbm_deselect_nth(BMEditMesh *em, int nth, int offset) deselect_nth_active(em, &v, &e, &f); if (v) { - walker_deselect_nth(em, nth, offset, &v->head); + walker_deselect_nth(em, nth, skip, offset, &v->head); return true; } else if (e) { - walker_deselect_nth(em, nth, offset, &e->head); + walker_deselect_nth(em, nth, skip, offset, &e->head); return true; } else if (f) { - walker_deselect_nth(em, nth, offset, &f->head); + walker_deselect_nth(em, nth, skip, offset, &f->head); return true; } @@ -2713,15 +2714,14 @@ static int edbm_select_nth_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); - const int nth = RNA_int_get(op->ptr, "nth"); + const int nth = RNA_int_get(op->ptr, "nth") - 1; + const int skip = RNA_int_get(op->ptr, "skip"); int offset = RNA_int_get(op->ptr, "offset"); /* so input of offset zero ends up being (nth - 1) */ - offset = mod_i(offset, nth); - /* depth starts at 1, this keeps active item selected */ - offset -= 1; + offset = mod_i(offset, nth + skip); - if (edbm_deselect_nth(em, nth, offset) == false) { + if (edbm_deselect_nth(em, nth, skip, offset) == false) { BKE_report(op->reports, RPT_ERROR, "Mesh has no active vert/edge/face"); return OPERATOR_CANCELLED; } @@ -2747,6 +2747,7 @@ void MESH_OT_select_nth(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_int(ot->srna, "nth", 2, 2, INT_MAX, "Nth Selection", "", 2, 100); + RNA_def_int(ot->srna, "skip", 1, 1, INT_MAX, "Skip", "", 1, 100); RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "", -100, 100); } -- cgit v1.2.3 From c31aae04870013f5913e03d3a5f6b72c5fc142d9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Mar 2015 06:13:50 +1100 Subject: Use fabsf for floats --- source/blender/blenlib/intern/math_vector_inline.c | 36 +++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index 89ae23fd448..621d5fbfbfe 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -613,44 +613,44 @@ MINLINE void negate_v3_short(short r[3]) MINLINE void abs_v2(float r[2]) { - r[0] = fabs(r[0]); - r[1] = fabs(r[1]); + r[0] = fabsf(r[0]); + r[1] = fabsf(r[1]); } MINLINE void abs_v2_v2(float r[2], const float a[2]) { - r[0] = fabs(a[0]); - r[1] = fabs(a[1]); + r[0] = fabsf(a[0]); + r[1] = fabsf(a[1]); } MINLINE void abs_v3(float r[3]) { - r[0] = fabs(r[0]); - r[1] = fabs(r[1]); - r[2] = fabs(r[2]); + r[0] = fabsf(r[0]); + r[1] = fabsf(r[1]); + r[2] = fabsf(r[2]); } MINLINE void abs_v3_v3(float r[3], const float a[3]) { - r[0] = fabs(a[0]); - r[1] = fabs(a[1]); - r[2] = fabs(a[2]); + r[0] = fabsf(a[0]); + r[1] = fabsf(a[1]); + r[2] = fabsf(a[2]); } MINLINE void abs_v4(float r[4]) { - r[0] = fabs(r[0]); - r[1] = fabs(r[1]); - r[2] = fabs(r[2]); - r[3] = fabs(r[3]); + r[0] = fabsf(r[0]); + r[1] = fabsf(r[1]); + r[2] = fabsf(r[2]); + r[3] = fabsf(r[3]); } MINLINE void abs_v4_v4(float r[4], const float a[4]) { - r[0] = fabs(a[0]); - r[1] = fabs(a[1]); - r[2] = fabs(a[2]); - r[3] = fabs(a[3]); + r[0] = fabsf(a[0]); + r[1] = fabsf(a[1]); + r[2] = fabsf(a[2]); + r[3] = fabsf(a[3]); } MINLINE float dot_v2v2(const float a[2], const float b[2]) -- cgit v1.2.3 From ce11e1c878fa5fffb4ab0a5d0a4b453dc21b8c2e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Mar 2015 12:42:34 +1100 Subject: Cleanup: better not pass function call to FTOCHAR also use rgb_uchar_to_float --- source/blender/imbuf/intern/colormanagement.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 588d81f9a75..a1b7a14c9fe 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1243,19 +1243,19 @@ const char *IMB_colormanagement_get_rect_colorspace(ImBuf *ibuf) float IMB_colormanagement_get_luminance(const float rgb[3]) { - return dot_v3v3(luma_coefficients, rgb); + return dot_v3v3(luma_coefficients, rgb); } /* Byte equivalent of IMB_colormanagement_get_luminance(). */ unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char rgb[3]) { - float rgbf[3]; + float rgbf[3]; + float val; - rgbf[0] = (float) rgb[0] / 255.0f; - rgbf[1] = (float) rgb[1] / 255.0f; - rgbf[2] = (float) rgb[2] / 255.0f; + rgb_uchar_to_float(rgbf, rgb); + val = dot_v3v3(luma_coefficients, rgbf); - return FTOCHAR(dot_v3v3(luma_coefficients, rgbf)); + return FTOCHAR(val); } /*********************** Threaded display buffer transform routines *************************/ -- cgit v1.2.3 From 255b07681acfe2ce8dd3af7d5b032d3c759cb93e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Mar 2015 12:59:36 +1100 Subject: Color managed luminance for shader ramp-in-energy --- source/blender/render/intern/source/shadeoutput.c | 69 +++++++++++++++-------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 586345d1eb4..b29038b2c34 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -962,7 +962,7 @@ static void ramp_diffuse_result(float *diff, ShadeInput *shi) } /* r,g,b denote energy, ramp is used with different values to make new material color */ -static void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, float g, float b) +static void add_to_diffuse(float diff[3], const ShadeInput *shi, const float is, const float rgb[3]) { Material *ma= shi->mat; @@ -971,9 +971,9 @@ static void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, floa /* MA_RAMP_IN_RESULT is exceptional */ if (ma->rampin_col==MA_RAMP_IN_RESULT) { /* normal add */ - diff[0] += r * shi->r; - diff[1] += g * shi->g; - diff[2] += b * shi->b; + diff[0] += rgb[0] * shi->r; + diff[1] += rgb[1] * shi->g; + diff[2] += rgb[2] * shi->b; } else { float colt[3], col[4]; @@ -982,40 +982,37 @@ static void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, floa /* input */ switch (ma->rampin_col) { case MA_RAMP_IN_ENERGY: - /* should use 'IMB_colormanagement_get_luminance' but we only have a vector version */ - fac= 0.3f*r + 0.58f*g + 0.12f*b; + fac = IMB_colormanagement_get_luminance(rgb); break; case MA_RAMP_IN_SHADER: - fac= is; + fac = is; break; case MA_RAMP_IN_NOR: - fac= shi->view[0]*shi->vn[0] + shi->view[1]*shi->vn[1] + shi->view[2]*shi->vn[2]; + fac = dot_v3v3(shi->view, shi->vn); break; default: - fac= 0.0f; + fac = 0.0f; break; } do_colorband(ma->ramp_col, fac, col); /* blending method */ - fac= col[3]*ma->rampfac_col; - colt[0]= shi->r; - colt[1]= shi->g; - colt[2]= shi->b; + fac = col[3] * ma->rampfac_col; + copy_v3_v3(colt, &shi->r); ramp_blend(ma->rampblend_col, colt, fac, col); /* output to */ - diff[0] += r * colt[0]; - diff[1] += g * colt[1]; - diff[2] += b * colt[2]; + diff[0] += rgb[0] * colt[0]; + diff[1] += rgb[1] * colt[1]; + diff[2] += rgb[2] * colt[2]; } } else { - diff[0] += r * shi->r; - diff[1] += g * shi->g; - diff[2] += b * shi->b; + diff[0] += rgb[0] * shi->r; + diff[1] += rgb[1] * shi->g; + diff[2] += rgb[2] * shi->b; } } @@ -1484,20 +1481,42 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int /* in case 'no diffuse' we still do most calculus, spec can be in shadow.*/ if (!(lar->mode & LA_NO_DIFF)) { if (i>0.0f) { - if (ma->mode & MA_SHADOW_TRA) - add_to_diffuse(shr->shad, shi, is, i*shadfac[0]*lacol[0], i*shadfac[1]*lacol[1], i*shadfac[2]*lacol[2]); - else - add_to_diffuse(shr->shad, shi, is, i*lacol[0], i*lacol[1], i*lacol[2]); + if (ma->mode & MA_SHADOW_TRA) { + const float tcol[3] = { + i * shadfac[0] * lacol[0], + i * shadfac[1] * lacol[1], + i * shadfac[2] * lacol[2], + }; + add_to_diffuse(shr->shad, shi, is, tcol); + } + else { + const float tcol[3] = { + i * lacol[0], + i * lacol[1], + i * lacol[2], + }; + add_to_diffuse(shr->shad, shi, is, tcol); + } } /* add light for colored shadow */ if (i_noshad>i && !(lashdw[0]==0 && lashdw[1]==0 && lashdw[2]==0)) { - add_to_diffuse(shr->shad, shi, is, lashdw[0]*(i_noshad-i)*lacol[0], lashdw[1]*(i_noshad-i)*lacol[1], lashdw[2]*(i_noshad-i)*lacol[2]); + const float tcol[3] = { + lashdw[0] * (i_noshad - i) * lacol[0], + lashdw[1] * (i_noshad - i) * lacol[1], + lashdw[2] * (i_noshad - i) * lacol[2], + }; + add_to_diffuse(shr->shad, shi, is, tcol); } if (i_noshad>0.0f) { if (passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW) || ((passflag & SCE_PASS_COMBINED) && !(shi->combinedflag & SCE_PASS_SHADOW))) { - add_to_diffuse(shr->diff, shi, is, i_noshad*lacol[0], i_noshad*lacol[1], i_noshad*lacol[2]); + const float tcol[3] = { + i_noshad * lacol[0], + i_noshad * lacol[1], + i_noshad * lacol[2] + }; + add_to_diffuse(shr->diff, shi, is, tcol); } else { copy_v3_v3(shr->diff, shr->shad); -- cgit v1.2.3 From 4f602ff943d91d0e6069e231916d2482ee859688 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Mar 2015 14:09:01 +1100 Subject: Revert part of recent color-management commit This adds back rgb_to_grayscale, not all color is managed or depends on the current loaded blend file's CM options. Noted in comments that this is only to be used outside the CM pipeline. --- source/blender/blenlib/intern/math_color_inline.c | 31 ++++++++++++++++++++++ .../blender/editors/interface/interface_regions.c | 6 ++--- .../blender/editors/interface/interface_widgets.c | 5 +--- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c index 96aa4b55201..0e955c1602e 100644 --- a/source/blender/blenlib/intern/math_color_inline.c +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -200,6 +200,37 @@ MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack) r_col[2] = ((pack) >> 16) & 0xFF; } + +/** \name RGB/Grayscale Functions + * + * \warning + * These are only an approximation, + * in almost _all_ cases, #IMB_colormanagement_get_luminance should be used instead. + * however for screen-only colors which don't depend on the currently loaded profile - this is preferred. + * Checking theme colors for contrast, etc. Basically anything outside the render pipeline. + * + * \{ */ + +/* non-linear luma from ITU-R BT.601-2 + * see: http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC11 + * note: the values used for are not exact matches to those documented above, + * but they are from the same */ +MINLINE float rgb_to_grayscale(const float rgb[3]) +{ + return 0.3f * rgb[0] + 0.58f * rgb[1] + 0.12f * rgb[2]; +} + +MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3]) +{ + return (unsigned char)(((76 * (unsigned short)rgb[0]) + + (148 * (unsigned short)rgb[1]) + + (31 * (unsigned short)rgb[2])) / 255); +} + +/** \} */ + + + MINLINE int compare_rgb_uchar(const unsigned char col_a[3], const unsigned char col_b[3], const int limit) { const int r = (int)col_a[0] - (int)col_b[0]; diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index adcd615368b..ae62b61736a 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -237,8 +237,8 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) /* find the brightness difference between background and text colors */ - tone_bg = IMB_colormanagement_get_luminance(background_color); - /* tone_fg = IMB_colormanagement_get_luminance(main_color); */ + tone_bg = rgb_to_grayscale(background_color); + /* tone_fg = rgb_to_grayscale(main_color); */ /* mix the colors */ rgb_tint(value_color, 0.0f, 0.0f, tone_bg, 0.2f); /* light grey */ @@ -261,7 +261,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) /* override text-style */ fstyle_header.shadow = 1; - fstyle_header.shadowcolor = IMB_colormanagement_get_luminance(tip_colors[UI_TIP_LC_MAIN]); + fstyle_header.shadowcolor = rgb_to_grayscale(tip_colors[UI_TIP_LC_MAIN]); fstyle_header.shadx = fstyle_header.shady = 0; fstyle_header.shadowalpha = 1.0f; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 9020522bb59..3d021e7dd10 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -27,7 +27,6 @@ * \ingroup edinterface */ - #include #include #include @@ -56,8 +55,6 @@ #include "UI_interface.h" #include "UI_interface_icons.h" -#include "IMB_colormanagement.h" - #include "interface_intern.h" #ifdef WITH_INPUT_IME @@ -3028,7 +3025,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat float width = rect->xmax - rect->xmin; float height = rect->ymax - rect->ymin; /* find color luminance and change it slightly */ - float bw = IMB_colormanagement_get_luminance(col); + float bw = rgb_to_grayscale(col); bw += (bw < 0.5f) ? 0.5f : -0.5f; -- cgit v1.2.3 From 9b54c88e0fdadf3a42cdd85bab68766dc83861a5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Mar 2015 14:14:48 +1100 Subject: Cleanup: spelling grey -> gray --- source/blender/compositor/intern/COM_Debug.cpp | 2 +- source/blender/editors/animation/keyframes_draw.c | 2 +- source/blender/editors/include/UI_interface.h | 2 +- source/blender/editors/interface/interface.c | 4 ++-- source/blender/editors/interface/interface_regions.c | 6 +++--- source/blender/editors/interface/resources.c | 4 ++-- source/blender/freestyle/intern/image/Image.h | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/source/blender/compositor/intern/COM_Debug.cpp b/source/blender/compositor/intern/COM_Debug.cpp index ffaa4cc45a8..3b3ab5082c5 100644 --- a/source/blender/compositor/intern/COM_Debug.cpp +++ b/source/blender/compositor/intern/COM_Debug.cpp @@ -356,7 +356,7 @@ bool DebugInfo::graphviz_system(const ExecutionSystem *system, char *str, int ma std::string color; switch (from->getDataType()) { case COM_DT_VALUE: - color = "grey"; + color = "gray"; break; case COM_DT_VECTOR: color = "blue"; diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index d2dbe961b42..9e38dd5507d 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -528,7 +528,7 @@ void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, } /* NOTE: we don't use the straight alpha from the theme, or else effects such as - * greying out protected/muted channels doesn't work correctly! + * graying out protected/muted channels doesn't work correctly! */ inner_col[3] *= alpha; glColor4fv(inner_col); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index b1bb48b58ed..4542627277a 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -181,7 +181,7 @@ enum { UI_BUT_COLOR_CUBIC = (1 << 23), /* cubic saturation for the color wheel */ UI_BUT_LIST_ITEM = (1 << 24), /* This but is "inside" a list item (currently used to change theme colors). */ UI_BUT_DRAG_MULTI = (1 << 25), /* edit this button as well as the active button (not just dragging) */ - UI_BUT_SCA_LINK_GREY = (1 << 26), /* used to flag if sca links shoud be grey out */ + UI_BUT_SCA_LINK_GREY = (1 << 26), /* used to flag if sca links shoud be gray out */ UI_BUT_HAS_SEP_CHAR = (1 << 27), /* but->str contains UI_SEP_CHAR, used for key shortcuts */ UI_BUT_TIP_FORCE = (1 << 28), /* force show tooltips when holding option/alt if U's USER_TOOLTIPS is off */ UI_BUT_TEXTEDIT_UPDATE = (1 << 29), /* when widget is in textedit mode, update value on each char stroke */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index bad09a7c441..48a7cf4ecf3 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -513,7 +513,7 @@ static void ui_draw_links(uiBlock *block) uiBut *but; uiLinkLine *line; - /* Draw the grey out lines. Do this first so they appear at the + /* Draw the gray out lines. Do this first so they appear at the * bottom of inactive or active lines. * As we go, remember if we see any active or selected lines. */ bool found_selectline = false; @@ -548,7 +548,7 @@ static void ui_draw_links(uiBlock *block) } /* Draw any active lines (lines with either button being hovered over). - * Do this last so they appear on top of inactive and grey out lines. */ + * Do this last so they appear on top of inactive and gray out lines. */ if (found_activeline) { for (but = block->buttons.first; but; but = but->next) { if (but->type == UI_BTYPE_LINK && but->link) { diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index ae62b61736a..8d7330c4dd7 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -241,10 +241,10 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) /* tone_fg = rgb_to_grayscale(main_color); */ /* mix the colors */ - rgb_tint(value_color, 0.0f, 0.0f, tone_bg, 0.2f); /* light grey */ + rgb_tint(value_color, 0.0f, 0.0f, tone_bg, 0.2f); /* light gray */ rgb_tint(active_color, 0.6f, 0.2f, tone_bg, 0.2f); /* light blue */ - rgb_tint(normal_color, 0.0f, 0.0f, tone_bg, 0.4f); /* grey */ - rgb_tint(python_color, 0.0f, 0.0f, tone_bg, 0.5f); /* dark grey */ + rgb_tint(normal_color, 0.0f, 0.0f, tone_bg, 0.4f); /* gray */ + rgb_tint(python_color, 0.0f, 0.0f, tone_bg, 0.5f); /* dark gray */ rgb_tint(alert_color, 0.0f, 0.8f, tone_bg, 0.1f); /* red */ /* draw text */ diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index a9cc53852c0..15e742c930a 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1098,7 +1098,7 @@ void ui_theme_init_default(void) rgba_char_args_set(btheme->text.syntaxd, 50, 0, 140, 255); /* Decorator/Preprocessor Dir. Blue-purple */ rgba_char_args_set(btheme->text.syntaxr, 140, 60, 0, 255); /* Reserved Orange*/ rgba_char_args_set(btheme->text.syntaxb, 128, 0, 80, 255); /* Builtin Red-purple */ - rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Grey (mix between fg/bg) */ + rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Gray (mix between fg/bg) */ /* space oops */ btheme->toops = btheme->tv3d; @@ -2351,7 +2351,7 @@ void init_userdef_do_versions(void) for (btheme = U.themes.first; btheme; btheme = btheme->next) { rgba_char_args_set(btheme->text.syntaxd, 50, 0, 140, 255); /* Decorator/Preprocessor Dir. Blue-purple */ rgba_char_args_set(btheme->text.syntaxr, 140, 60, 0, 255); /* Reserved Orange */ - rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Grey (mix between fg/bg) */ + rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Gray (mix between fg/bg) */ } } diff --git a/source/blender/freestyle/intern/image/Image.h b/source/blender/freestyle/intern/image/Image.h index 577dc0fb866..2e78e784214 100644 --- a/source/blender/freestyle/intern/image/Image.h +++ b/source/blender/freestyle/intern/image/Image.h @@ -134,7 +134,7 @@ public: return _height; } - /*! Returns the grey value for pixel x,y */ + /*! Returns the gray value for pixel x,y */ virtual float pixel(unsigned x, unsigned y) const = 0; /*! Sets the array. -- cgit v1.2.3 From 2a2bf3c1ab1f9f844a66d1f5f69232d64e16d678 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Mar 2015 14:33:05 +1100 Subject: Freestyle: pass Main struct to new/copy --- source/blender/blenkernel/BKE_freestyle.h | 3 ++- source/blender/blenkernel/BKE_linestyle.h | 4 ++-- source/blender/blenkernel/intern/freestyle.c | 4 ++-- source/blender/blenkernel/intern/library.c | 2 +- source/blender/blenkernel/intern/linestyle.c | 11 ++++------- source/blender/editors/render/render_shading.c | 8 +++++--- source/blender/makesrna/intern/rna_main_api.c | 2 +- source/blender/makesrna/intern/rna_scene.c | 6 +++--- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/source/blender/blenkernel/BKE_freestyle.h b/source/blender/blenkernel/BKE_freestyle.h index bb909e4aa9d..e10594634f0 100644 --- a/source/blender/blenkernel/BKE_freestyle.h +++ b/source/blender/blenkernel/BKE_freestyle.h @@ -41,6 +41,7 @@ extern "C" { struct FreestyleConfig; struct FreestyleLineSet; struct FreestyleModuleConfig; +struct Main; /* RNA aliases */ typedef struct FreestyleSettings FreestyleSettings; @@ -58,7 +59,7 @@ bool BKE_freestyle_module_move_up(FreestyleConfig *config, FreestyleModuleConfig bool BKE_freestyle_module_move_down(FreestyleConfig *config, FreestyleModuleConfig *module_conf); /* FreestyleConfig.linesets */ -FreestyleLineSet *BKE_freestyle_lineset_add(FreestyleConfig *config, const char *name); +FreestyleLineSet *BKE_freestyle_lineset_add(struct Main *bmain, FreestyleConfig *config, const char *name); bool BKE_freestyle_lineset_delete(FreestyleConfig *config, FreestyleLineSet *lineset); FreestyleLineSet *BKE_freestyle_lineset_get_active(FreestyleConfig *config); short BKE_freestyle_lineset_get_active_index(FreestyleConfig *config); diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h index ae10ba4caab..e77b4f5e8fe 100644 --- a/source/blender/blenkernel/BKE_linestyle.h +++ b/source/blender/blenkernel/BKE_linestyle.h @@ -49,9 +49,9 @@ struct Object; struct ColorBand; struct bContext; -FreestyleLineStyle *BKE_linestyle_new(const char *name, struct Main *main); +FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name); void BKE_linestyle_free(FreestyleLineStyle *linestyle); -FreestyleLineStyle *BKE_linestyle_copy(FreestyleLineStyle *linestyle); +FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *linestyle); FreestyleLineStyle *BKE_linestyle_active_from_scene(struct Scene *scene); diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c index cc9ad63d451..f6c4263cff7 100644 --- a/source/blender/blenkernel/intern/freestyle.c +++ b/source/blender/blenkernel/intern/freestyle.c @@ -179,7 +179,7 @@ static FreestyleLineSet *alloc_lineset(void) return (FreestyleLineSet *)MEM_callocN(sizeof(FreestyleLineSet), "Freestyle line set"); } -FreestyleLineSet *BKE_freestyle_lineset_add(FreestyleConfig *config, const char *name) +FreestyleLineSet *BKE_freestyle_lineset_add(struct Main *bmain, FreestyleConfig *config, const char *name) { int lineset_index = BLI_listbase_count(&config->linesets); @@ -187,7 +187,7 @@ FreestyleLineSet *BKE_freestyle_lineset_add(FreestyleConfig *config, const char BLI_addtail(&config->linesets, (void *)lineset); BKE_freestyle_lineset_set_active_index(config, lineset_index); - lineset->linestyle = BKE_linestyle_new("LineStyle", NULL); + lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle"); lineset->flags |= FREESTYLE_LINESET_ENABLED; lineset->selection = FREESTYLE_SEL_VISIBILITY | FREESTYLE_SEL_EDGE_TYPES | FREESTYLE_SEL_IMAGE_BORDER; lineset->qi = FREESTYLE_QI_VISIBLE; diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index c602067d5bd..9cda4d91933 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -384,7 +384,7 @@ bool id_copy(ID *id, ID **newid, bool test) if (!test) *newid = (ID *)BKE_mask_copy((Mask *)id); return true; case ID_LS: - if (!test) *newid = (ID *)BKE_linestyle_copy((FreestyleLineStyle *)id); + if (!test) *newid = (ID *)BKE_linestyle_copy(G.main, (FreestyleLineStyle *)id); return true; } diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index b97bf0ed9b0..28b7ceded67 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -107,14 +107,11 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle) linestyle->caps = LS_CAPS_BUTT; } -FreestyleLineStyle *BKE_linestyle_new(const char *name, struct Main *main) +FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name) { FreestyleLineStyle *linestyle; - if (!main) - main = G.main; - - linestyle = (FreestyleLineStyle *)BKE_libblock_alloc(main, ID_LS, name); + linestyle = (FreestyleLineStyle *)BKE_libblock_alloc(bmain, ID_LS, name); default_linestyle_settings(linestyle); @@ -149,13 +146,13 @@ void BKE_linestyle_free(FreestyleLineStyle *linestyle) BKE_linestyle_geometry_modifier_remove(linestyle, m); } -FreestyleLineStyle *BKE_linestyle_copy(FreestyleLineStyle *linestyle) +FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *linestyle) { FreestyleLineStyle *new_linestyle; LineStyleModifier *m; int a; - new_linestyle = BKE_linestyle_new(linestyle->id.name + 2, NULL); + new_linestyle = BKE_linestyle_new(bmain, linestyle->id.name + 2); BKE_linestyle_free(new_linestyle); for (a = 0; a < MAX_MTEX; a++) { diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index ff90f48d705..75b8b8cebde 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -731,10 +731,11 @@ void SCENE_OT_freestyle_module_move(wmOperatorType *ot) static int freestyle_lineset_add_exec(bContext *C, wmOperator *UNUSED(op)) { + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); - BKE_freestyle_lineset_add(&srl->freestyleConfig, NULL); + BKE_freestyle_lineset_add(bmain, &srl->freestyleConfig, NULL); DAG_id_tag_update(&scene->id, 0); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); @@ -893,6 +894,7 @@ void SCENE_OT_freestyle_lineset_move(wmOperatorType *ot) static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig); @@ -903,10 +905,10 @@ static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op) } if (lineset->linestyle) { lineset->linestyle->id.us--; - lineset->linestyle = BKE_linestyle_copy(lineset->linestyle); + lineset->linestyle = BKE_linestyle_copy(bmain, lineset->linestyle); } else { - lineset->linestyle = BKE_linestyle_new("LineStyle", NULL); + lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle"); } DAG_id_tag_update(&lineset->linestyle->id, 0); WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index ed8b85f724e..ed28b0b1255 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -705,7 +705,7 @@ static void rna_Main_grease_pencil_remove(Main *bmain, ReportList *reports, Poin static FreestyleLineStyle *rna_Main_linestyles_new(Main *bmain, const char *name) { - FreestyleLineStyle *linestyle = BKE_linestyle_new(name, bmain); + FreestyleLineStyle *linestyle = BKE_linestyle_new(bmain, name); id_us_min(&linestyle->id); return linestyle; } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 3e7ffcd8cf0..629fbbf66e9 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1636,10 +1636,10 @@ static void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr, PointerRNA value lineset->linestyle->id.us++; } -static FreestyleLineSet *rna_FreestyleSettings_lineset_add(ID *id, FreestyleSettings *config, const char *name) +static FreestyleLineSet *rna_FreestyleSettings_lineset_add(ID *id, FreestyleSettings *config, Main *bmain, const char *name) { Scene *scene = (Scene *)id; - FreestyleLineSet *lineset = BKE_freestyle_lineset_add((FreestyleConfig *)config, name); + FreestyleLineSet *lineset = BKE_freestyle_lineset_add(bmain, (FreestyleConfig *)config, name); DAG_id_tag_update(&scene->id, 0); WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL); @@ -2841,7 +2841,7 @@ static void rna_def_freestyle_linesets(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "new", "rna_FreestyleSettings_lineset_add"); RNA_def_function_ui_description(func, "Add a line set to scene render layer Freestyle settings"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_SELF_ID); parm = RNA_def_string(func, "name", "LineSet", 0, "", "New name for the line set (not unique)"); RNA_def_property_flag(parm, PROP_REQUIRED); parm = RNA_def_pointer(func, "lineset", "FreestyleLineSet", "", "Newly created line set"); -- cgit v1.2.3 From 2df4444deff15d7e1cb150a201e0ffc9b44d9fd1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Mar 2015 14:48:52 +1100 Subject: CMake: exclude Colamd when OpenNL's disabled --- extern/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt index 110c88f8e4a..3dc790f2932 100644 --- a/extern/CMakeLists.txt +++ b/extern/CMakeLists.txt @@ -26,11 +26,14 @@ # Otherwise we get warnings here that we cant fix in external projects remove_strict_flags() -add_subdirectory(colamd) add_subdirectory(rangetree) add_subdirectory(wcwidth) add_subdirectory(libmv) +if(WITH_OPENNL) + add_subdirectory(colamd) +endif() + if(WITH_BULLET) if(NOT WITH_SYSTEM_BULLET) add_subdirectory(bullet2) -- cgit v1.2.3 From 4b88541d59302d4e65ecc66093a367091538c32d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Mar 2015 15:41:41 +1100 Subject: CMake: unbundle eigen3 Optionally use systems eigen3 library. T41989 by @hasufell with edits --- CMakeLists.txt | 15 + build_files/cmake/Modules/FindEigen3.cmake | 56 +++ extern/libmv/CMakeLists.txt | 2 +- extern/libmv/bundle.sh | 2 +- extern/libmv/third_party/ceres/CMakeLists.txt | 2 +- extern/libmv/third_party/ceres/bundle.sh | 2 +- intern/dualcon/CMakeLists.txt | 2 +- intern/itasc/CMakeLists.txt | 469 +++++++++++++------------- source/blender/ikplugin/CMakeLists.txt | 2 +- source/gameengine/Converter/CMakeLists.txt | 2 +- 10 files changed, 316 insertions(+), 238 deletions(-) create mode 100644 build_files/cmake/Modules/FindEigen3.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e54ddc9274..2e8552f2a1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,6 +261,10 @@ endif() # (unix defaults to System OpenJPEG On) option(WITH_SYSTEM_OPENJPEG "Use the operating systems OpenJPEG library" OFF) +if(UNIX AND NOT APPLE) + option(WITH_SYSTEM_EIGEN3 "Use the systems Eigen3 library" OFF) +endif() + # Modifiers option(WITH_MOD_FLUID "Enable Elbeem Modifier (Fluid Simulation)" ON) @@ -811,6 +815,14 @@ if(UNIX AND NOT APPLE) endif() endif() + if(WITH_SYSTEM_EIGEN3) + find_package_wrapper(Eigen3) + if(NOT EIGEN3_FOUND) + message(FATAL_ERROR "Failed finding system Eigen3 version!") + endif() + endif() + # else values are set below for all platforms + if(WITH_PYTHON) # No way to set py34. remove for now. # find_package(PythonLibs) @@ -2246,6 +2258,9 @@ if(WITH_IMAGE_REDCODE) set(REDCODE_INC ${REDCODE}) endif() +if(NOT WITH_SYSTEM_EIGEN3) + set(EIGEN3_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/Eigen3) +endif() #----------------------------------------------------------------------------- # Configure OpenGL. diff --git a/build_files/cmake/Modules/FindEigen3.cmake b/build_files/cmake/Modules/FindEigen3.cmake new file mode 100644 index 00000000000..400e8eb047d --- /dev/null +++ b/build_files/cmake/Modules/FindEigen3.cmake @@ -0,0 +1,56 @@ +# - Find Eigen3 library +# Find the native Eigen3 includes and library +# This module defines +# EIGEN3_INCLUDE_DIRS, where to find spnav.h, Set when +# EIGEN3_INCLUDE_DIR is found. +# EIGEN3_ROOT_DIR, The base directory to search for Eigen3. +# This can also be an environment variable. +# EIGEN3_FOUND, If false, do not try to use Eigen3. +# +#============================================================================= +# Copyright 2015 Blender Foundation. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= + +# If EIGEN3_ROOT_DIR was defined in the environment, use it. +IF(NOT EIGEN3_ROOT_DIR AND NOT $ENV{EIGEN3_ROOT_DIR} STREQUAL "") + SET(EIGEN3_ROOT_DIR $ENV{EIGEN3_ROOT_DIR}) +ENDIF() + +SET(_eigen3_SEARCH_DIRS + ${EIGEN3_ROOT_DIR} + /usr/local + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave +) + +FIND_PATH(EIGEN3_INCLUDE_DIR + NAMES + # header has no '.h' suffix + Eigen/Eigen + HINTS + ${_eigen3_SEARCH_DIRS} + PATH_SUFFIXES + include/eigen3 +) + +# handle the QUIETLY and REQUIRED arguments and set EIGEN3_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Eigen3 DEFAULT_MSG + EIGEN3_INCLUDE_DIR) + +IF(EIGEN3_FOUND) + SET(EIGEN3_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR}) +ENDIF(EIGEN3_FOUND) + +MARK_AS_ADVANCED( + EIGEN3_INCLUDE_DIR +) diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt index 80e64046534..089743567f0 100644 --- a/extern/libmv/CMakeLists.txt +++ b/extern/libmv/CMakeLists.txt @@ -48,7 +48,7 @@ if(WITH_LIBMV OR WITH_GTESTS OR (WITH_CYCLES AND WITH_CYCLES_LOGGING)) ) list(APPEND INC_SYS - ../Eigen3 + ${EIGEN3_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS} ) diff --git a/extern/libmv/bundle.sh b/extern/libmv/bundle.sh index 66023fa693c..ac4190041bd 100755 --- a/extern/libmv/bundle.sh +++ b/extern/libmv/bundle.sh @@ -141,7 +141,7 @@ if(WITH_LIBMV OR WITH_GTESTS OR (WITH_CYCLES AND WITH_CYCLES_LOGGING)) ) list(APPEND INC_SYS - ../Eigen3 + \${EIGEN3_INCLUDE_DIRS} \${PNG_INCLUDE_DIRS} \${ZLIB_INCLUDE_DIRS} ) diff --git a/extern/libmv/third_party/ceres/CMakeLists.txt b/extern/libmv/third_party/ceres/CMakeLists.txt index 0ca888f6393..694982ec606 100644 --- a/extern/libmv/third_party/ceres/CMakeLists.txt +++ b/extern/libmv/third_party/ceres/CMakeLists.txt @@ -36,7 +36,7 @@ set(INC ) set(INC_SYS - ../../../Eigen3 + ${EIGEN3_INCLUDE_DIRS} ) set(SRC diff --git a/extern/libmv/third_party/ceres/bundle.sh b/extern/libmv/third_party/ceres/bundle.sh index 659f29e98ea..0becc87dd4f 100755 --- a/extern/libmv/third_party/ceres/bundle.sh +++ b/extern/libmv/third_party/ceres/bundle.sh @@ -129,7 +129,7 @@ set(INC ) set(INC_SYS - ../../../Eigen3 + ${EIGEN3_INCLUDE_DIRS} ) set(SRC diff --git a/intern/dualcon/CMakeLists.txt b/intern/dualcon/CMakeLists.txt index da5e10fe6a7..40c8ef8ff9c 100644 --- a/intern/dualcon/CMakeLists.txt +++ b/intern/dualcon/CMakeLists.txt @@ -22,7 +22,7 @@ set(INC ) set(INC_SYS - ../../extern/Eigen3 + ${EIGEN3_INCLUDE_DIRS} ) set(SRC diff --git a/intern/itasc/CMakeLists.txt b/intern/itasc/CMakeLists.txt index bc3ea0cf24c..bdf0f88e516 100644 --- a/intern/itasc/CMakeLists.txt +++ b/intern/itasc/CMakeLists.txt @@ -28,9 +28,244 @@ set(INC ) set(INC_SYS - ../../extern/Eigen3 + ${EIGEN3_INCLUDE_DIRS} ) +if(NOT WITH_SYSTEM_EIGEN3) + set(EIGEN3_HEADERS + # until we have another user... + ../../extern/Eigen3/Eigen/src/Cholesky/LDLT.h + ../../extern/Eigen3/Eigen/src/Cholesky/LLT.h + ../../extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h + ../../extern/Eigen3/Eigen/src/CholmodSupport/CholmodSupport.h + ../../extern/Eigen3/Eigen/src/Core/Array.h + ../../extern/Eigen3/Eigen/src/Core/ArrayBase.h + ../../extern/Eigen3/Eigen/src/Core/ArrayWrapper.h + ../../extern/Eigen3/Eigen/src/Core/Assign.h + ../../extern/Eigen3/Eigen/src/Core/Assign_MKL.h + ../../extern/Eigen3/Eigen/src/Core/BandMatrix.h + ../../extern/Eigen3/Eigen/src/Core/Block.h + ../../extern/Eigen3/Eigen/src/Core/BooleanRedux.h + ../../extern/Eigen3/Eigen/src/Core/CommaInitializer.h + ../../extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h + ../../extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h + ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h + ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h + ../../extern/Eigen3/Eigen/src/Core/DenseBase.h + ../../extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h + ../../extern/Eigen3/Eigen/src/Core/DenseStorage.h + ../../extern/Eigen3/Eigen/src/Core/Diagonal.h + ../../extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h + ../../extern/Eigen3/Eigen/src/Core/DiagonalProduct.h + ../../extern/Eigen3/Eigen/src/Core/Dot.h + ../../extern/Eigen3/Eigen/src/Core/EigenBase.h + ../../extern/Eigen3/Eigen/src/Core/Flagged.h + ../../extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h + ../../extern/Eigen3/Eigen/src/Core/Functors.h + ../../extern/Eigen3/Eigen/src/Core/Fuzzy.h + ../../extern/Eigen3/Eigen/src/Core/GeneralProduct.h + ../../extern/Eigen3/Eigen/src/Core/GenericPacketMath.h + ../../extern/Eigen3/Eigen/src/Core/GlobalFunctions.h + ../../extern/Eigen3/Eigen/src/Core/IO.h + ../../extern/Eigen3/Eigen/src/Core/Map.h + ../../extern/Eigen3/Eigen/src/Core/MapBase.h + ../../extern/Eigen3/Eigen/src/Core/MathFunctions.h + ../../extern/Eigen3/Eigen/src/Core/Matrix.h + ../../extern/Eigen3/Eigen/src/Core/MatrixBase.h + ../../extern/Eigen3/Eigen/src/Core/NestByValue.h + ../../extern/Eigen3/Eigen/src/Core/NoAlias.h + ../../extern/Eigen3/Eigen/src/Core/NumTraits.h + ../../extern/Eigen3/Eigen/src/Core/PermutationMatrix.h + ../../extern/Eigen3/Eigen/src/Core/PlainObjectBase.h + ../../extern/Eigen3/Eigen/src/Core/Product.h + ../../extern/Eigen3/Eigen/src/Core/ProductBase.h + ../../extern/Eigen3/Eigen/src/Core/Random.h + ../../extern/Eigen3/Eigen/src/Core/Redux.h + ../../extern/Eigen3/Eigen/src/Core/Replicate.h + ../../extern/Eigen3/Eigen/src/Core/ReturnByValue.h + ../../extern/Eigen3/Eigen/src/Core/Reverse.h + ../../extern/Eigen3/Eigen/src/Core/Select.h + ../../extern/Eigen3/Eigen/src/Core/SelfAdjointView.h + ../../extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h + ../../extern/Eigen3/Eigen/src/Core/SolveTriangular.h + ../../extern/Eigen3/Eigen/src/Core/StableNorm.h + ../../extern/Eigen3/Eigen/src/Core/Stride.h + ../../extern/Eigen3/Eigen/src/Core/Swap.h + ../../extern/Eigen3/Eigen/src/Core/Transpose.h + ../../extern/Eigen3/Eigen/src/Core/Transpositions.h + ../../extern/Eigen3/Eigen/src/Core/TriangularMatrix.h + ../../extern/Eigen3/Eigen/src/Core/VectorBlock.h + ../../extern/Eigen3/Eigen/src/Core/VectorwiseOp.h + ../../extern/Eigen3/Eigen/src/Core/Visitor.h + ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h + ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h + ../../extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h + ../../extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h + ../../extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h + ../../extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h + ../../extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h + ../../extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h + ../../extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/Parallelizer.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h + ../../extern/Eigen3/Eigen/src/Core/util/BlasUtil.h + ../../extern/Eigen3/Eigen/src/Core/util/Constants.h + ../../extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h + ../../extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h + ../../extern/Eigen3/Eigen/src/Core/util/Macros.h + ../../extern/Eigen3/Eigen/src/Core/util/Memory.h + ../../extern/Eigen3/Eigen/src/Core/util/Meta.h + ../../extern/Eigen3/Eigen/src/Core/util/MKL_support.h + ../../extern/Eigen3/Eigen/src/Core/util/NonMPL2.h + ../../extern/Eigen3/Eigen/src/Core/util/ReenableStupidWarnings.h + ../../extern/Eigen3/Eigen/src/Core/util/StaticAssert.h + ../../extern/Eigen3/Eigen/src/Core/util/XprHelper.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Block.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/LU.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Macros.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Memory.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Meta.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Minor.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/QR.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/SVD.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/All.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AngleAxis.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur_MKL.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/RealSchur_MKL.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h + ../../extern/Eigen3/Eigen/src/Geometry/AlignedBox.h + ../../extern/Eigen3/Eigen/src/Geometry/AngleAxis.h + ../../extern/Eigen3/Eigen/src/Geometry/EulerAngles.h + ../../extern/Eigen3/Eigen/src/Geometry/Homogeneous.h + ../../extern/Eigen3/Eigen/src/Geometry/Hyperplane.h + ../../extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h + ../../extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h + ../../extern/Eigen3/Eigen/src/Geometry/Quaternion.h + ../../extern/Eigen3/Eigen/src/Geometry/Rotation2D.h + ../../extern/Eigen3/Eigen/src/Geometry/RotationBase.h + ../../extern/Eigen3/Eigen/src/Geometry/Scaling.h + ../../extern/Eigen3/Eigen/src/Geometry/Transform.h + ../../extern/Eigen3/Eigen/src/Geometry/Translation.h + ../../extern/Eigen3/Eigen/src/Geometry/Umeyama.h + ../../extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h + ../../extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h + ../../extern/Eigen3/Eigen/src/Householder/Householder.h + ../../extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h + ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h + ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h + ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h + ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h + ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h + ../../extern/Eigen3/Eigen/src/Jacobi/Jacobi.h + ../../extern/Eigen3/Eigen/src/LU/Determinant.h + ../../extern/Eigen3/Eigen/src/LU/FullPivLU.h + ../../extern/Eigen3/Eigen/src/LU/Inverse.h + ../../extern/Eigen3/Eigen/src/LU/PartialPivLU.h + ../../extern/Eigen3/Eigen/src/LU/PartialPivLU_MKL.h + ../../extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h + ../../extern/Eigen3/Eigen/src/misc/blas.h + ../../extern/Eigen3/Eigen/src/misc/Image.h + ../../extern/Eigen3/Eigen/src/misc/Kernel.h + ../../extern/Eigen3/Eigen/src/misc/Solve.h + ../../extern/Eigen3/Eigen/src/misc/SparseSolve.h + ../../extern/Eigen3/Eigen/src/OrderingMethods/Amd.h + ../../extern/Eigen3/Eigen/src/PardisoSupport/PardisoSupport.h + ../../extern/Eigen3/Eigen/src/PaStiXSupport/PaStiXSupport.h + ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h + ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h + ../../extern/Eigen3/Eigen/src/plugins/BlockMethods.h + ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h + ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h + ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h + ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h + ../../extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h + ../../extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR_MKL.h + ../../extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h + ../../extern/Eigen3/Eigen/src/QR/HouseholderQR.h + ../../extern/Eigen3/Eigen/src/QR/HouseholderQR_MKL.h + ../../extern/Eigen3/Eigen/src/SparseCholesky/SimplicialCholesky.h + ../../extern/Eigen3/Eigen/src/SparseCore/AmbiVector.h + ../../extern/Eigen3/Eigen/src/SparseCore/CompressedStorage.h + ../../extern/Eigen3/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h + ../../extern/Eigen3/Eigen/src/SparseCore/CoreIterators.h + ../../extern/Eigen3/Eigen/src/SparseCore/MappedSparseMatrix.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseAssign.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseBlock.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseCwiseBinaryOp.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseCwiseUnaryOp.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseDenseProduct.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseDiagonalProduct.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseDot.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseFuzzy.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseMatrix.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseMatrixBase.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparsePermutation.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseProduct.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseRedux.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseSelfAdjointView.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseSparseProductWithPruning.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseTranspose.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseTriangularView.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseUtil.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseVector.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseView.h + ../../extern/Eigen3/Eigen/src/SparseCore/TriangularSolver.h + ../../extern/Eigen3/Eigen/src/StlSupport/details.h + ../../extern/Eigen3/Eigen/src/StlSupport/StdDeque.h + ../../extern/Eigen3/Eigen/src/StlSupport/StdList.h + ../../extern/Eigen3/Eigen/src/StlSupport/StdVector.h + ../../extern/Eigen3/Eigen/src/SuperLUSupport/SuperLUSupport.h + ../../extern/Eigen3/Eigen/src/SVD/JacobiSVD.h + ../../extern/Eigen3/Eigen/src/SVD/JacobiSVD_MKL.h + ../../extern/Eigen3/Eigen/src/SVD/UpperBidiagonalization.h + ../../extern/Eigen3/Eigen/src/UmfPackSupport/UmfPackSupport.h + ) +endif() + set(SRC Armature.cpp Cache.cpp @@ -120,237 +355,9 @@ set(SRC kdl/frames.inl kdl/framevel.inl - # until we have another user... - ../../extern/Eigen3/Eigen/src/Cholesky/LDLT.h - ../../extern/Eigen3/Eigen/src/Cholesky/LLT.h - ../../extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h - ../../extern/Eigen3/Eigen/src/CholmodSupport/CholmodSupport.h - ../../extern/Eigen3/Eigen/src/Core/Array.h - ../../extern/Eigen3/Eigen/src/Core/ArrayBase.h - ../../extern/Eigen3/Eigen/src/Core/ArrayWrapper.h - ../../extern/Eigen3/Eigen/src/Core/Assign.h - ../../extern/Eigen3/Eigen/src/Core/Assign_MKL.h - ../../extern/Eigen3/Eigen/src/Core/BandMatrix.h - ../../extern/Eigen3/Eigen/src/Core/Block.h - ../../extern/Eigen3/Eigen/src/Core/BooleanRedux.h - ../../extern/Eigen3/Eigen/src/Core/CommaInitializer.h - ../../extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h - ../../extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h - ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h - ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h - ../../extern/Eigen3/Eigen/src/Core/DenseBase.h - ../../extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h - ../../extern/Eigen3/Eigen/src/Core/DenseStorage.h - ../../extern/Eigen3/Eigen/src/Core/Diagonal.h - ../../extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h - ../../extern/Eigen3/Eigen/src/Core/DiagonalProduct.h - ../../extern/Eigen3/Eigen/src/Core/Dot.h - ../../extern/Eigen3/Eigen/src/Core/EigenBase.h - ../../extern/Eigen3/Eigen/src/Core/Flagged.h - ../../extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h - ../../extern/Eigen3/Eigen/src/Core/Functors.h - ../../extern/Eigen3/Eigen/src/Core/Fuzzy.h - ../../extern/Eigen3/Eigen/src/Core/GeneralProduct.h - ../../extern/Eigen3/Eigen/src/Core/GenericPacketMath.h - ../../extern/Eigen3/Eigen/src/Core/GlobalFunctions.h - ../../extern/Eigen3/Eigen/src/Core/IO.h - ../../extern/Eigen3/Eigen/src/Core/Map.h - ../../extern/Eigen3/Eigen/src/Core/MapBase.h - ../../extern/Eigen3/Eigen/src/Core/MathFunctions.h - ../../extern/Eigen3/Eigen/src/Core/Matrix.h - ../../extern/Eigen3/Eigen/src/Core/MatrixBase.h - ../../extern/Eigen3/Eigen/src/Core/NestByValue.h - ../../extern/Eigen3/Eigen/src/Core/NoAlias.h - ../../extern/Eigen3/Eigen/src/Core/NumTraits.h - ../../extern/Eigen3/Eigen/src/Core/PermutationMatrix.h - ../../extern/Eigen3/Eigen/src/Core/PlainObjectBase.h - ../../extern/Eigen3/Eigen/src/Core/Product.h - ../../extern/Eigen3/Eigen/src/Core/ProductBase.h - ../../extern/Eigen3/Eigen/src/Core/Random.h - ../../extern/Eigen3/Eigen/src/Core/Redux.h - ../../extern/Eigen3/Eigen/src/Core/Replicate.h - ../../extern/Eigen3/Eigen/src/Core/ReturnByValue.h - ../../extern/Eigen3/Eigen/src/Core/Reverse.h - ../../extern/Eigen3/Eigen/src/Core/Select.h - ../../extern/Eigen3/Eigen/src/Core/SelfAdjointView.h - ../../extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h - ../../extern/Eigen3/Eigen/src/Core/SolveTriangular.h - ../../extern/Eigen3/Eigen/src/Core/StableNorm.h - ../../extern/Eigen3/Eigen/src/Core/Stride.h - ../../extern/Eigen3/Eigen/src/Core/Swap.h - ../../extern/Eigen3/Eigen/src/Core/Transpose.h - ../../extern/Eigen3/Eigen/src/Core/Transpositions.h - ../../extern/Eigen3/Eigen/src/Core/TriangularMatrix.h - ../../extern/Eigen3/Eigen/src/Core/VectorBlock.h - ../../extern/Eigen3/Eigen/src/Core/VectorwiseOp.h - ../../extern/Eigen3/Eigen/src/Core/Visitor.h - ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h - ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h - ../../extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h - ../../extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h - ../../extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h - ../../extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h - ../../extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h - ../../extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h - ../../extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h - ../../extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h - ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h - ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h - ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h - ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h - ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h - ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector_MKL.h - ../../extern/Eigen3/Eigen/src/Core/products/Parallelizer.h - ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h - ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h - ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h - ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h - ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h - ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h - ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h - ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h - ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h - ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector_MKL.h - ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h - ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h - ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h - ../../extern/Eigen3/Eigen/src/Core/util/BlasUtil.h - ../../extern/Eigen3/Eigen/src/Core/util/Constants.h - ../../extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h - ../../extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h - ../../extern/Eigen3/Eigen/src/Core/util/Macros.h - ../../extern/Eigen3/Eigen/src/Core/util/Memory.h - ../../extern/Eigen3/Eigen/src/Core/util/Meta.h - ../../extern/Eigen3/Eigen/src/Core/util/MKL_support.h - ../../extern/Eigen3/Eigen/src/Core/util/NonMPL2.h - ../../extern/Eigen3/Eigen/src/Core/util/ReenableStupidWarnings.h - ../../extern/Eigen3/Eigen/src/Core/util/StaticAssert.h - ../../extern/Eigen3/Eigen/src/Core/util/XprHelper.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Block.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/LU.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Macros.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Memory.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Meta.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Minor.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/QR.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/SVD.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/All.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AngleAxis.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur_MKL.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/RealSchur_MKL.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h - ../../extern/Eigen3/Eigen/src/Geometry/AlignedBox.h - ../../extern/Eigen3/Eigen/src/Geometry/AngleAxis.h - ../../extern/Eigen3/Eigen/src/Geometry/EulerAngles.h - ../../extern/Eigen3/Eigen/src/Geometry/Homogeneous.h - ../../extern/Eigen3/Eigen/src/Geometry/Hyperplane.h - ../../extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h - ../../extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h - ../../extern/Eigen3/Eigen/src/Geometry/Quaternion.h - ../../extern/Eigen3/Eigen/src/Geometry/Rotation2D.h - ../../extern/Eigen3/Eigen/src/Geometry/RotationBase.h - ../../extern/Eigen3/Eigen/src/Geometry/Scaling.h - ../../extern/Eigen3/Eigen/src/Geometry/Transform.h - ../../extern/Eigen3/Eigen/src/Geometry/Translation.h - ../../extern/Eigen3/Eigen/src/Geometry/Umeyama.h - ../../extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h - ../../extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h - ../../extern/Eigen3/Eigen/src/Householder/Householder.h - ../../extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h - ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h - ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h - ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h - ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h - ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h - ../../extern/Eigen3/Eigen/src/Jacobi/Jacobi.h - ../../extern/Eigen3/Eigen/src/LU/Determinant.h - ../../extern/Eigen3/Eigen/src/LU/FullPivLU.h - ../../extern/Eigen3/Eigen/src/LU/Inverse.h - ../../extern/Eigen3/Eigen/src/LU/PartialPivLU.h - ../../extern/Eigen3/Eigen/src/LU/PartialPivLU_MKL.h - ../../extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h - ../../extern/Eigen3/Eigen/src/misc/blas.h - ../../extern/Eigen3/Eigen/src/misc/Image.h - ../../extern/Eigen3/Eigen/src/misc/Kernel.h - ../../extern/Eigen3/Eigen/src/misc/Solve.h - ../../extern/Eigen3/Eigen/src/misc/SparseSolve.h - ../../extern/Eigen3/Eigen/src/OrderingMethods/Amd.h - ../../extern/Eigen3/Eigen/src/PardisoSupport/PardisoSupport.h - ../../extern/Eigen3/Eigen/src/PaStiXSupport/PaStiXSupport.h - ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h - ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h - ../../extern/Eigen3/Eigen/src/plugins/BlockMethods.h - ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h - ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h - ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h - ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h - ../../extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h - ../../extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR_MKL.h - ../../extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h - ../../extern/Eigen3/Eigen/src/QR/HouseholderQR.h - ../../extern/Eigen3/Eigen/src/QR/HouseholderQR_MKL.h - ../../extern/Eigen3/Eigen/src/SparseCholesky/SimplicialCholesky.h - ../../extern/Eigen3/Eigen/src/SparseCore/AmbiVector.h - ../../extern/Eigen3/Eigen/src/SparseCore/CompressedStorage.h - ../../extern/Eigen3/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h - ../../extern/Eigen3/Eigen/src/SparseCore/CoreIterators.h - ../../extern/Eigen3/Eigen/src/SparseCore/MappedSparseMatrix.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseAssign.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseBlock.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseCwiseBinaryOp.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseCwiseUnaryOp.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseDenseProduct.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseDiagonalProduct.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseDot.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseFuzzy.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseMatrix.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseMatrixBase.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparsePermutation.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseProduct.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseRedux.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseSelfAdjointView.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseSparseProductWithPruning.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseTranspose.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseTriangularView.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseUtil.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseVector.h - ../../extern/Eigen3/Eigen/src/SparseCore/SparseView.h - ../../extern/Eigen3/Eigen/src/SparseCore/TriangularSolver.h - ../../extern/Eigen3/Eigen/src/StlSupport/details.h - ../../extern/Eigen3/Eigen/src/StlSupport/StdDeque.h - ../../extern/Eigen3/Eigen/src/StlSupport/StdList.h - ../../extern/Eigen3/Eigen/src/StlSupport/StdVector.h - ../../extern/Eigen3/Eigen/src/SuperLUSupport/SuperLUSupport.h - ../../extern/Eigen3/Eigen/src/SVD/JacobiSVD.h - ../../extern/Eigen3/Eigen/src/SVD/JacobiSVD_MKL.h - ../../extern/Eigen3/Eigen/src/SVD/UpperBidiagonalization.h - ../../extern/Eigen3/Eigen/src/UmfPackSupport/UmfPackSupport.h + ${EIGEN3_HEADERS} ) +unset(EIGEN3_HEADERS) blender_add_lib(bf_intern_itasc "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/ikplugin/CMakeLists.txt b/source/blender/ikplugin/CMakeLists.txt index 0a0e0e664b4..139dbd32349 100644 --- a/source/blender/ikplugin/CMakeLists.txt +++ b/source/blender/ikplugin/CMakeLists.txt @@ -59,7 +59,7 @@ if(WITH_IK_ITASC) ../../../intern/itasc ) list(APPEND INC_SYS - ../../../extern/Eigen3 + ${EIGEN3_INCLUDE_DIRS} ) list(APPEND SRC intern/itasc_plugin.cpp diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt index 9c0d25e56ff..9721149314f 100644 --- a/source/gameengine/Converter/CMakeLists.txt +++ b/source/gameengine/Converter/CMakeLists.txt @@ -56,7 +56,7 @@ set(INC set(INC_SYS ../../../intern/moto/include ../../../extern/recastnavigation/Detour/Include - ../../../extern/Eigen3 + ${EIGEN3_INCLUDE_DIRS} ${PTHREADS_INCLUDE_DIRS} ${BOOST_INCLUDE_DIR} ) -- cgit v1.2.3 From 8b6e777736db88d8877235dc849e52eb7924c1bb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Mar 2015 18:00:10 +1100 Subject: Fix out-of-bounds read BKE_deform_flip_side_name --- source/blender/blenkernel/intern/deform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 0adea59c245..350b19b0250 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -649,7 +649,7 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[ BLI_strncpy(prefix, name, sizeof(prefix)); /* first case; separator . - _ with extensions r R l L */ - if (is_char_sep(name[len - 2])) { + if ((len > 1) && is_char_sep(name[len - 2])) { is_set = true; switch (name[len - 1]) { case 'l': -- cgit v1.2.3 From c6ee43d384242fad7e50132905555ed7372a157a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Mar 2015 17:29:46 +1100 Subject: Cleanup: style (armature duplicate) --- source/blender/editors/armature/armature_add.c | 113 +++++++++++++------------ 1 file changed, 57 insertions(+), 56 deletions(-) diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index 22aaeccc4a8..a4520dbc0a4 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -398,13 +398,11 @@ EditBone *duplicateEditBone(EditBone *curBone, const char *name, ListBase *editb return duplicateEditBoneObjects(curBone, name, editbones, ob, ob); } -/* previously adduplicate_armature */ static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op)) { bArmature *arm; - EditBone *eBone = NULL; - EditBone *curBone; - EditBone *firstDup = NULL; /* The beginning of the duplicated bones in the edbo list */ + EditBone *ebone_iter; + EditBone *ebone_first_dupe = NULL; /* The beginning of the duplicated bones in the edbo list */ Object *obedit = CTX_data_edit_object(C); arm = obedit->data; @@ -419,77 +417,80 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op)) /* Select mirrored bones */ if (arm->flag & ARM_MIRROR_EDIT) { - for (curBone = arm->edbo->first; curBone; curBone = curBone->next) { - if (EBONE_VISIBLE(arm, curBone)) { - if (curBone->flag & BONE_SELECTED) { - eBone = ED_armature_bone_get_mirrored(arm->edbo, curBone); - if (eBone) - eBone->flag |= BONE_SELECTED; + for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) { + if (EBONE_VISIBLE(arm, ebone_iter) && + (ebone_iter->flag & BONE_SELECTED)) + { + EditBone *ebone; + + ebone = ED_armature_bone_get_mirrored(arm->edbo, ebone_iter); + if (ebone) { + ebone->flag |= BONE_SELECTED; } } } } - /* Find the selected bones and duplicate them as needed */ - for (curBone = arm->edbo->first; curBone && curBone != firstDup; curBone = curBone->next) { - if (EBONE_VISIBLE(arm, curBone)) { - if (curBone->flag & BONE_SELECTED) { - - eBone = duplicateEditBone(curBone, curBone->name, arm->edbo, obedit); - - if (!firstDup) - firstDup = eBone; + /* Find the selected bones and duplicate them as needed */ + for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) { + if (EBONE_VISIBLE(arm, ebone_iter) && + (ebone_iter->flag & BONE_SELECTED)) + { + EditBone *ebone; + + ebone = duplicateEditBone(ebone_iter, ebone_iter->name, arm->edbo, obedit); + if (!ebone_first_dupe) { + ebone_first_dupe = ebone; } } } - /* Run though the list and fix the pointers */ - for (curBone = arm->edbo->first; curBone && curBone != firstDup; curBone = curBone->next) { - if (EBONE_VISIBLE(arm, curBone)) { - if (curBone->flag & BONE_SELECTED) { - eBone = (EditBone *) curBone->temp; - - if (!curBone->parent) { - /* If this bone has no parent, - * Set the duplicate->parent to NULL - */ - eBone->parent = NULL; - } - else if (curBone->parent->temp) { - /* If this bone has a parent that was duplicated, - * Set the duplicate->parent to the curBone->parent->temp - */ - eBone->parent = (EditBone *)curBone->parent->temp; - } - else { - /* If this bone has a parent that IS not selected, - * Set the duplicate->parent to the curBone->parent - */ - eBone->parent = (EditBone *) curBone->parent; - eBone->flag &= ~BONE_CONNECTED; - } - - /* Lets try to fix any constraint subtargets that might - * have been duplicated + /* Run though the list and fix the pointers */ + for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) { + if (EBONE_VISIBLE(arm, ebone_iter) && + (ebone_iter->flag & BONE_SELECTED)) + { + EditBone *ebone = ebone_iter->temp; + + if (!ebone_iter->parent) { + /* If this bone has no parent, + * Set the duplicate->parent to NULL + */ + ebone->parent = NULL; + } + else if (ebone_iter->parent->temp) { + /* If this bone has a parent that was duplicated, + * Set the duplicate->parent to the curBone->parent->temp */ - updateDuplicateSubtarget(eBone, arm->edbo, obedit); + ebone->parent = (EditBone *)ebone_iter->parent->temp; } + else { + /* If this bone has a parent that IS not selected, + * Set the duplicate->parent to the curBone->parent + */ + ebone->parent = (EditBone *) ebone_iter->parent; + ebone->flag &= ~BONE_CONNECTED; + } + + /* Lets try to fix any constraint subtargets that might + * have been duplicated + */ + updateDuplicateSubtarget(ebone, arm->edbo, obedit); } } /* correct the active bone */ - if (arm->act_edbone) { - eBone = arm->act_edbone; - if (eBone->temp) - arm->act_edbone = eBone->temp; + if (arm->act_edbone && arm->act_edbone->temp) { + arm->act_edbone = arm->act_edbone->temp; } - /* Deselect the old bones and select the new ones */ - for (curBone = arm->edbo->first; curBone && curBone != firstDup; curBone = curBone->next) { - if (EBONE_VISIBLE(arm, curBone)) - curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + /* Deselect the old bones and select the new ones */ + for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) { + if (EBONE_VISIBLE(arm, ebone_iter)) { + ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } } ED_armature_validate_active(arm); -- cgit v1.2.3 From 156921114ec50760abfaadec3dbc02140f33ef5b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Mar 2015 17:57:17 +1100 Subject: Armature Symmetrize tool D1147 by @julien, with fixes/improvements Duplicate bones where needed, otherwise use existing. Keeps parent relations intact, can operate on parts of an armature. --- release/scripts/startup/bl_ui/space_view3d.py | 2 + source/blender/editors/armature/armature_add.c | 207 ++++++++++++++++++++++ source/blender/editors/armature/armature_intern.h | 1 + source/blender/editors/armature/armature_ops.c | 1 + 4 files changed, 211 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index c65cebfde10..128e24a6d68 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -2710,6 +2710,7 @@ class VIEW3D_MT_edit_armature(Menu): layout.separator() layout.operator_context = 'EXEC_AREA' + layout.operator("armature.symmetrize") layout.operator("armature.autoside_names", text="AutoName Left/Right").type = 'XAXIS' layout.operator("armature.autoside_names", text="AutoName Front/Back").type = 'YAXIS' layout.operator("armature.autoside_names", text="AutoName Top/Bottom").type = 'ZAXIS' @@ -2748,6 +2749,7 @@ class VIEW3D_MT_armature_specials(Menu): layout.operator("armature.autoside_names", text="AutoName Front/Back").type = 'YAXIS' layout.operator("armature.autoside_names", text="AutoName Top/Bottom").type = 'ZAXIS' layout.operator("armature.flip_names", text="Flip Names") + layout.operator("armature.symmetrize") class VIEW3D_MT_edit_armature_parent(Menu): diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index a4520dbc0a4..5cc2101650e 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -43,6 +43,7 @@ #include "BKE_constraint.h" #include "BKE_context.h" #include "BKE_idprop.h" +#include "BKE_deform.h" #include "RNA_access.h" #include "RNA_define.h" @@ -516,6 +517,212 @@ void ARMATURE_OT_duplicate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** + * near duplicate of #armature_duplicate_selected_exec, + * except for parenting part (keep in sync) + */ +static int armature_symmetrize_exec(bContext *C, wmOperator *op) +{ + bArmature *arm; + EditBone *ebone_iter; + EditBone *ebone_first_dupe = NULL; /* The beginning of the duplicated mirrored bones in the edbo list */ + + Object *obedit = CTX_data_edit_object(C); + const int direction = RNA_enum_get(op->ptr, "direction"); + const int axis = 0; + + arm = obedit->data; + + /* cancel if nothing selected */ + if (CTX_DATA_COUNT(C, selected_bones) == 0) + return OPERATOR_CANCELLED; + + ED_armature_sync_selection(arm->edbo); // XXX why is this needed? + + preEditBoneDuplicate(arm->edbo); + + /* Select mirrored bones */ + for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) { + if (EBONE_VISIBLE(arm, ebone_iter) && + (ebone_iter->flag & BONE_SELECTED)) + { + char name_flip[MAX_VGROUP_NAME]; + + BKE_deform_flip_side_name(name_flip, ebone_iter->name, false); + + if (STREQ(name_flip, ebone_iter->name)) { + /* if the name matches, we don't have the potential to be mirrored, just skip */ + ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + else { + EditBone *ebone = ED_armature_bone_find_name(arm->edbo, name_flip); + + if (ebone) { + if ((ebone->flag & BONE_SELECTED) == 0) { + /* simple case, we're selected, the other bone isn't! */ + ebone_iter->temp = ebone; + } + else { + /* complicated - choose which direction to copy */ + float axis_delta; + + axis_delta = ebone->head[axis] - ebone_iter->head[axis]; + if (axis_delta == 0.0f) { + axis_delta = ebone->tail[axis] - ebone_iter->tail[axis]; + } + + if (axis_delta == 0.0f) { + /* both mirrored bones exist and point to eachother and overlap exactly. + * + * in this case theres no well defined solution, so de-select both and skip. + */ + ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + else { + EditBone *ebone_src, *ebone_dst; + if (((axis_delta < 0.0f) ? -1 : 1) == direction) { + ebone_src = ebone; + ebone_dst = ebone_iter; + } + else { + ebone_src = ebone_iter; + ebone_dst = ebone; + } + + ebone_src->temp = ebone_dst; + ebone_dst->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + } + } + } + } + } + + /* Find the selected bones and duplicate them as needed, with mirrored name */ + for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) { + if (EBONE_VISIBLE(arm, ebone_iter) && + (ebone_iter->flag & BONE_SELECTED) && + /* will be set if the mirror bone already exists (no need to make a new one) */ + (ebone_iter->temp == NULL)) + { + char name_flip[MAX_VGROUP_NAME]; + + BKE_deform_flip_side_name(name_flip, ebone_iter->name, false); + + /* bones must have a side-suffix */ + if (!STREQ(name_flip, ebone_iter->name)) { + EditBone *ebone; + + ebone = duplicateEditBone(ebone_iter, name_flip, arm->edbo, obedit); + + if (!ebone_first_dupe) { + ebone_first_dupe = ebone; + } + } + } + } + + /* Run though the list and fix the pointers */ + for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) { + if (ebone_iter->temp) { + /* copy all flags except for ... */ + const int flag_copy = ((int)~0) & ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL); + + EditBone *ebone = ebone_iter->temp; + + /* copy flags incase bone is pre-existing data */ + ebone->flag = (ebone->flag & ~flag_copy) | (ebone_iter->flag & flag_copy); + + if (ebone_iter->parent == NULL) { + /* If this bone has no parent, + * Set the duplicate->parent to NULL + */ + ebone->parent = NULL; + } + else { + /* the parent may have been duplicated, if not lookup the mirror parent */ + EditBone *ebone_parent = + (ebone_iter->parent->temp ? + ebone_iter->parent->temp : ED_armature_bone_get_mirrored(arm->edbo, ebone_iter->parent)); + + if (ebone_parent == NULL) { + /* If the mirror lookup failed, (but the current bone has a parent) + * then we can assume the parent has no L/R but is a center bone. + * So just use the same parent for both. + */ + ebone_parent = ebone_iter->parent; + } + + ebone->parent = ebone_parent; + } + + /* Lets try to fix any constraint subtargets that might + * have been duplicated + */ + updateDuplicateSubtarget(ebone, arm->edbo, obedit); + } + } + + transform_armature_mirror_update(obedit); + + /* Selected bones now have their 'temp' pointer set, + * so we don't need this anymore */ + + /* Deselect the old bones and select the new ones */ + for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) { + if (EBONE_VISIBLE(arm, ebone_iter)) { + ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + } + + /* New bones will be selected, but some of the bones may already exist */ + for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) { + EditBone *ebone = ebone_iter->temp; + if (ebone && EBONE_SELECTABLE(arm, ebone)) { + ED_armature_ebone_select_set(ebone, true); + } + } + + /* correct the active bone */ + if (arm->act_edbone && arm->act_edbone->temp) { + arm->act_edbone = arm->act_edbone->temp; + } + + ED_armature_validate_active(arm); + + WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit); + + return OPERATOR_FINISHED; +} + +/* following conventions from #MESH_OT_symmetrize */ +void ARMATURE_OT_symmetrize(wmOperatorType *ot) +{ + /* subset of 'symmetrize_direction_items' */ + static EnumPropertyItem arm_symmetrize_direction_items[] = { + {-1, "NEGATIVE_X", 0, "-X to +X", ""}, + {+1, "POSITIVE_X", 0, "+X to -X", ""}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "Symmetrize"; + ot->idname = "ARMATURE_OT_symmetrize"; + ot->description = "Enforce symmetry, make copies of the selection or use existing"; + + /* api callbacks */ + ot->exec = armature_symmetrize_exec; + ot->poll = ED_operator_editarmature; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + ot->prop = RNA_def_enum( + ot->srna, "direction", arm_symmetrize_direction_items, -1, + "Direction", "Which sides to copy from and to (when both are selected)"); +} + /* ------------------------------------------ */ /* previously extrude_armature */ diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index 2c64c9aa345..0607bc49515 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -72,6 +72,7 @@ void ARMATURE_OT_shortest_path_pick(struct wmOperatorType *ot); void ARMATURE_OT_delete(struct wmOperatorType *ot); void ARMATURE_OT_duplicate(struct wmOperatorType *ot); +void ARMATURE_OT_symmetrize(struct wmOperatorType *ot); void ARMATURE_OT_extrude(struct wmOperatorType *ot); void ARMATURE_OT_hide(struct wmOperatorType *ot); void ARMATURE_OT_reveal(struct wmOperatorType *ot); diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index c80953d6737..552faa4ecfb 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -66,6 +66,7 @@ void ED_operatortypes_armature(void) WM_operatortype_append(ARMATURE_OT_delete); WM_operatortype_append(ARMATURE_OT_duplicate); + WM_operatortype_append(ARMATURE_OT_symmetrize); WM_operatortype_append(ARMATURE_OT_extrude); WM_operatortype_append(ARMATURE_OT_hide); WM_operatortype_append(ARMATURE_OT_reveal); -- cgit v1.2.3 From ad95cb72bc6e76a2b3dc0996293bfb8379084e38 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Mar 2015 20:09:34 +1100 Subject: Transform: Shift for precision PET adjustment Patch T36753 by @hjaarnio --- source/blender/editors/transform/transform.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 061d00424b8..b562eb2e5f1 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -888,8 +888,12 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_UP); WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_DOWN); + WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PROPSIZE_UP); + WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PROPSIZE_DOWN); WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_UP); WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_DOWN); + WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PROPSIZE_UP); + WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PROPSIZE_DOWN); WM_modalkeymap_add_item(keymap, MOUSEPAN, 0, 0, 0, TFM_MODAL_PROPSIZE); WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_ALT, 0, TFM_MODAL_EDGESLIDE_UP); @@ -1230,7 +1234,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; case TFM_MODAL_PROPSIZE_UP: if (t->flag & T_PROP_EDIT) { - t->prop_size *= 1.1f; + t->prop_size *= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f; if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far); calculatePropRatio(t); @@ -1240,7 +1244,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; case TFM_MODAL_PROPSIZE_DOWN: if (t->flag & T_PROP_EDIT) { - t->prop_size *= 0.90909090f; + t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f; calculatePropRatio(t); t->redraw |= TREDRAW_HARD; handled = true; @@ -1413,7 +1417,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; case PADPLUSKEY: if (event->alt && t->flag & T_PROP_EDIT) { - t->prop_size *= 1.1f; + t->prop_size *= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f; if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far); calculatePropRatio(t); @@ -1434,7 +1438,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; case PADMINUS: if (event->alt && t->flag & T_PROP_EDIT) { - t->prop_size *= 0.90909090f; + t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f; calculatePropRatio(t); t->redraw = TREDRAW_HARD; handled = true; -- cgit v1.2.3 From 52d72a37cd85dc8c23482d4102abb86645a221bb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Mar 2015 20:34:02 +1100 Subject: Cleanup --- build_files/cmake/Modules/FindPCRE.cmake | 1 - source/blender/editors/object/object_shapekey.c | 4 ++-- source/blender/imbuf/intern/bmp.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/build_files/cmake/Modules/FindPCRE.cmake b/build_files/cmake/Modules/FindPCRE.cmake index 9d73e9200d9..ff4b7261555 100644 --- a/build_files/cmake/Modules/FindPCRE.cmake +++ b/build_files/cmake/Modules/FindPCRE.cmake @@ -40,7 +40,6 @@ FIND_PATH(PCRE_INCLUDE_DIR pcre.h ${_pcre_SEARCH_DIRS} PATH_SUFFIXES include - include ) FIND_LIBRARY(PCRE_LIBRARY diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index fb9687da6df..fb0b2ed231c 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -127,8 +127,8 @@ static bool ED_object_shape_key_remove(Main *bmain, Object *ob) } else if (rkb->relative >= ob->shapenr) { /* Fix positional shift of the keys when kb is deleted from the list */ - rkb->relative -= 1; - } + rkb->relative -= 1; + } } BLI_remlink(&key->block, kb); diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c index 19e655a0b3d..298e2da965f 100644 --- a/source/blender/imbuf/intern/bmp.c +++ b/source/blender/imbuf/intern/bmp.c @@ -136,7 +136,7 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); - bmp = mem + LITTLE_LONG(*(int*)(mem + 10)); + bmp = mem + LITTLE_LONG(*(int *)(mem + 10)); if (CHECK_HEADER_FIELD_BMP(mem)) { /* skip fileheader */ -- cgit v1.2.3 From c69b5e027642a3f82f869062e79ee532bec1b723 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 19 Mar 2015 16:04:49 +0500 Subject: Fix T44040: Blender crashes when nodes are muted It was actually an old issue with wrong conversion happening for muted nodes, which wasn't visible before memory optimization commit. This is to be backported to the final release. --- source/blender/compositor/intern/COM_NodeOperationBuilder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp index 74c05c3e62e..45105bade08 100644 --- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp +++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp @@ -101,12 +101,12 @@ void NodeOperationBuilder::convertToOperations(ExecutionSystem *system) } } + resolve_proxies(); + add_datatype_conversions(); add_operation_input_constants(); - resolve_proxies(); - determineResolutions(); /* surround complex ops with read/write buffer */ -- cgit v1.2.3 From 15b37a4a4dc8e3684aa53140e7285eb3deaec52b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 19 Mar 2015 18:28:49 +0500 Subject: Speedup for constraints update from python script General idea is to avoid actual calculation from property update() callback and tag things for update later instead. That said, pose constraint flags are now tagged for update and handled as a part of object update. In the new depsgraph it'll be a nice dedicated operation node. Also avoid updating disabled flags for all the modifiers. This part of the path is not totally optimal since it'll still need to iterate over bones in order to get pchan, but to optimize it further would be nice to find a way to avoid pchan requirement all together. Reviewers: campbellbarton Reviewed By: campbellbarton Differential Revision: https://developer.blender.org/D1191 --- source/blender/blenkernel/BKE_action.h | 3 + source/blender/blenkernel/intern/action.c | 6 + source/blender/blenkernel/intern/object.c | 6 +- source/blender/editors/include/ED_object.h | 3 + source/blender/editors/object/object_constraint.c | 512 ++++++++++++---------- source/blender/makesdna/DNA_action_types.h | 4 +- source/blender/makesrna/intern/rna_constraint.c | 4 +- 7 files changed, 309 insertions(+), 229 deletions(-) diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 57ba6fd55ca..f51e0fe6979 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -161,6 +161,9 @@ void extract_pose_from_pose(struct bPose *pose, const struct bPose *src); /* sets constraint flags */ void BKE_pose_update_constraint_flags(struct bPose *pose); +/* tag constraint flags for update */ +void BKE_pose_tag_update_constraint_flags(struct bPose *pose); + /* return the name of structure pointed by pose->ikparam */ const char *BKE_pose_ikparam_get_name(struct bPose *pose); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index f9556bf39ab..9ce198bd687 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -929,6 +929,12 @@ void BKE_pose_update_constraint_flags(bPose *pose) pchan->constflag |= PCHAN_HAS_CONST; } } + pose->flag &= ~POSE_CONSTRAINTS_NEED_UPDATE_FLAGS; +} + +void BKE_pose_tag_update_constraint_flags(bPose *pose) +{ + pose->flag |= POSE_CONSTRAINTS_NEED_UPDATE_FLAGS; } /* Clears all BONE_UNKEYED flags for every pose channel in every pose diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index d63e2516805..08a74d0c6cd 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -3012,8 +3012,12 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx, { if (ob->recalc & OB_RECALC_ALL) { /* speed optimization for animation lookups */ - if (ob->pose) + if (ob->pose) { BKE_pose_channels_hash_make(ob->pose); + if (ob->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) { + BKE_pose_update_constraint_flags(ob->pose); + } + } if (ob->recalc & OB_RECALC_DATA) { if (ob->type == OB_ARMATURE) { diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 295bb752a08..3d791839a3c 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -175,6 +175,9 @@ void ED_object_constraint_set_active(struct Object *ob, struct bConstraint *con) void ED_object_constraint_update(struct Object *ob); void ED_object_constraint_dependency_update(struct Main *bmain, struct Object *ob); +void ED_object_constraint_tag_update(struct Object *ob, struct bConstraint *con); +void ED_object_constraint_dependency_tag_update(struct Main *bmain, struct Object *ob, struct bConstraint *con); + /* object_lattice.c */ bool mouse_lattice(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); void undo_push_lattice(struct bContext *C, const char *name); diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 231d23b481d..f1b349d5a44 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -260,17 +260,221 @@ static void set_constraint_nth_target(bConstraint *con, Object *target, const ch /* ------------- Constraint Sanity Testing ------------------- */ -/* checks validity of object pointers, and NULLs, - * if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag. - */ -static void test_constraints(Object *owner, bPoseChannel *pchan) +static void test_constraint(Object *owner, bPoseChannel *pchan, bConstraint *con, int type) +{ + bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + ListBase targets = {NULL, NULL}; + bConstraintTarget *ct; + bool check_targets = true; + + /* clear disabled-flag first */ + con->flag &= ~CONSTRAINT_DISABLE; + + if (con->type == CONSTRAINT_TYPE_KINEMATIC) { + bKinematicConstraint *data = con->data; + + /* bad: we need a separate set of checks here as poletarget is + * optional... otherwise poletarget must exist too or else + * the constraint is deemed invalid + */ + /* default IK check ... */ + if (BKE_object_exists_check(data->tar) == 0) { + data->tar = NULL; + con->flag |= CONSTRAINT_DISABLE; + } + else if (data->tar == owner) { + if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) { + con->flag |= CONSTRAINT_DISABLE; + } + } + + if (data->poletar) { + if (BKE_object_exists_check(data->poletar) == 0) { + data->poletar = NULL; + con->flag |= CONSTRAINT_DISABLE; + } + else if (data->poletar == owner) { + if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->polesubtarget)) { + con->flag |= CONSTRAINT_DISABLE; + } + } + } + /* ... can be overwritten here */ + BIK_test_constraint(owner, con); + /* targets have already been checked for this */ + check_targets = false; + } + else if (con->type == CONSTRAINT_TYPE_PIVOT) { + bPivotConstraint *data = con->data; + + /* target doesn't have to exist, but if it is non-null, it must exist! */ + if (data->tar && BKE_object_exists_check(data->tar) == 0) { + data->tar = NULL; + con->flag |= CONSTRAINT_DISABLE; + } + else if (data->tar == owner) { + if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) { + con->flag |= CONSTRAINT_DISABLE; + } + } + + /* targets have already been checked for this */ + check_targets = false; + } + else if (con->type == CONSTRAINT_TYPE_ACTION) { + bActionConstraint *data = con->data; + + /* validate action */ + if (data->act == NULL) { + /* must have action */ + con->flag |= CONSTRAINT_DISABLE; + } + else if (data->act->idroot != ID_OB) { + /* only object-rooted actions can be used */ + data->act = NULL; + con->flag |= CONSTRAINT_DISABLE; + } + } + else if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) { + bFollowPathConstraint *data = con->data; + + /* don't allow track/up axes to be the same */ + if (data->upflag == data->trackflag) + con->flag |= CONSTRAINT_DISABLE; + if (data->upflag + 3 == data->trackflag) + con->flag |= CONSTRAINT_DISABLE; + } + else if (con->type == CONSTRAINT_TYPE_TRACKTO) { + bTrackToConstraint *data = con->data; + + /* don't allow track/up axes to be the same */ + if (data->reserved2 == data->reserved1) + con->flag |= CONSTRAINT_DISABLE; + if (data->reserved2 + 3 == data->reserved1) + con->flag |= CONSTRAINT_DISABLE; + } + else if (con->type == CONSTRAINT_TYPE_LOCKTRACK) { + bLockTrackConstraint *data = con->data; + + if (data->lockflag == data->trackflag) + con->flag |= CONSTRAINT_DISABLE; + if (data->lockflag + 3 == data->trackflag) + con->flag |= CONSTRAINT_DISABLE; + } + else if (con->type == CONSTRAINT_TYPE_SPLINEIK) { + bSplineIKConstraint *data = con->data; + + /* if the number of points does not match the amount required by the chain length, + * free the points array and request a rebind... + */ + if ((data->points == NULL) || (data->numpoints != data->chainlen + 1)) { + /* free the points array */ + if (data->points) { + MEM_freeN(data->points); + data->points = NULL; + } + + /* clear the bound flag, forcing a rebind next time this is evaluated */ + data->flag &= ~CONSTRAINT_SPLINEIK_BOUND; + } + } + else if (con->type == CONSTRAINT_TYPE_FOLLOWTRACK) { + bFollowTrackConstraint *data = con->data; + + if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0) { + if (data->clip != NULL && data->track[0]) { + MovieTracking *tracking = &data->clip->tracking; + MovieTrackingObject *tracking_object; + + if (data->object[0]) + tracking_object = BKE_tracking_object_get_named(tracking, data->object); + else + tracking_object = BKE_tracking_object_get_camera(tracking); + + if (!tracking_object) { + con->flag |= CONSTRAINT_DISABLE; + } + else { + if (!BKE_tracking_track_get_named(tracking, tracking_object, data->track)) + con->flag |= CONSTRAINT_DISABLE; + } + } + else { + con->flag |= CONSTRAINT_DISABLE; + } + } + } + else if (con->type == CONSTRAINT_TYPE_CAMERASOLVER) { + bCameraSolverConstraint *data = con->data; + + if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL)) + con->flag |= CONSTRAINT_DISABLE; + } + else if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) { + bObjectSolverConstraint *data = con->data; + + if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL)) + con->flag |= CONSTRAINT_DISABLE; + } + + /* Check targets for constraints */ + if (check_targets && cti && cti->get_constraint_targets) { + cti->get_constraint_targets(con, &targets); + + /* disable and clear constraints targets that are incorrect */ + for (ct = targets.first; ct; ct = ct->next) { + /* general validity checks (for those constraints that need this) */ + if (BKE_object_exists_check(ct->tar) == 0) { + /* object doesn't exist, but constraint requires target */ + ct->tar = NULL; + con->flag |= CONSTRAINT_DISABLE; + } + else if (ct->tar == owner) { + if (type == CONSTRAINT_OBTYPE_BONE) { + if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), ct->subtarget)) { + /* bone must exist in armature... */ + /* TODO: clear subtarget? */ + con->flag |= CONSTRAINT_DISABLE; + } + else if (STREQ(pchan->name, ct->subtarget)) { + /* cannot target self */ + ct->subtarget[0] = '\0'; + con->flag |= CONSTRAINT_DISABLE; + } + } + else { + /* cannot use self as target */ + ct->tar = NULL; + con->flag |= CONSTRAINT_DISABLE; + } + } + + /* target checks for specific constraints */ + if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) { + if (ct->tar) { + if (ct->tar->type != OB_CURVE) { + ct->tar = NULL; + con->flag |= CONSTRAINT_DISABLE; + } + else { + Curve *cu = ct->tar->data; + + /* auto-set 'Path' setting on curve so this works */ + cu->flag |= CU_PATH; + } + } + } + } + + /* free any temporary targets */ + if (cti->flush_constraint_targets) + cti->flush_constraint_targets(con, &targets, 0); + } +} + +static int constraint_type_get(Object *owner, bPoseChannel *pchan) { - bConstraint *curcon; - ListBase *conlist = NULL; int type; - - if (owner == NULL) return; - /* Check parents */ if (pchan) { switch (owner->type) { @@ -284,7 +488,22 @@ static void test_constraints(Object *owner, bPoseChannel *pchan) } else type = CONSTRAINT_OBTYPE_OBJECT; + return type; +} + +/* checks validity of object pointers, and NULLs, + * if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag. + */ +static void test_constraints(Object *owner, bPoseChannel *pchan) +{ + bConstraint *curcon; + ListBase *conlist = NULL; + int type; + if (owner == NULL) return; + + type = constraint_type_get(owner, pchan); + /* Get the constraint list for this object */ switch (type) { case CONSTRAINT_OBTYPE_OBJECT: @@ -298,213 +517,7 @@ static void test_constraints(Object *owner, bPoseChannel *pchan) /* Check all constraints - is constraint valid? */ if (conlist) { for (curcon = conlist->first; curcon; curcon = curcon->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon); - ListBase targets = {NULL, NULL}; - bConstraintTarget *ct; - - /* clear disabled-flag first */ - curcon->flag &= ~CONSTRAINT_DISABLE; - - if (curcon->type == CONSTRAINT_TYPE_KINEMATIC) { - bKinematicConstraint *data = curcon->data; - - /* bad: we need a separate set of checks here as poletarget is - * optional... otherwise poletarget must exist too or else - * the constraint is deemed invalid - */ - /* default IK check ... */ - if (BKE_object_exists_check(data->tar) == 0) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - } - else if (data->tar == owner) { - if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) { - curcon->flag |= CONSTRAINT_DISABLE; - } - } - - if (data->poletar) { - if (BKE_object_exists_check(data->poletar) == 0) { - data->poletar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - } - else if (data->poletar == owner) { - if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->polesubtarget)) { - curcon->flag |= CONSTRAINT_DISABLE; - } - } - } - /* ... can be overwritten here */ - BIK_test_constraint(owner, curcon); - /* targets have already been checked for this */ - continue; - } - else if (curcon->type == CONSTRAINT_TYPE_PIVOT) { - bPivotConstraint *data = curcon->data; - - /* target doesn't have to exist, but if it is non-null, it must exist! */ - if (data->tar && BKE_object_exists_check(data->tar) == 0) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - } - else if (data->tar == owner) { - if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) { - curcon->flag |= CONSTRAINT_DISABLE; - } - } - - /* targets have already been checked for this */ - continue; - } - else if (curcon->type == CONSTRAINT_TYPE_ACTION) { - bActionConstraint *data = curcon->data; - - /* validate action */ - if (data->act == NULL) { - /* must have action */ - curcon->flag |= CONSTRAINT_DISABLE; - } - else if (data->act->idroot != ID_OB) { - /* only object-rooted actions can be used */ - data->act = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - } - } - else if (curcon->type == CONSTRAINT_TYPE_FOLLOWPATH) { - bFollowPathConstraint *data = curcon->data; - - /* don't allow track/up axes to be the same */ - if (data->upflag == data->trackflag) - curcon->flag |= CONSTRAINT_DISABLE; - if (data->upflag + 3 == data->trackflag) - curcon->flag |= CONSTRAINT_DISABLE; - } - else if (curcon->type == CONSTRAINT_TYPE_TRACKTO) { - bTrackToConstraint *data = curcon->data; - - /* don't allow track/up axes to be the same */ - if (data->reserved2 == data->reserved1) - curcon->flag |= CONSTRAINT_DISABLE; - if (data->reserved2 + 3 == data->reserved1) - curcon->flag |= CONSTRAINT_DISABLE; - } - else if (curcon->type == CONSTRAINT_TYPE_LOCKTRACK) { - bLockTrackConstraint *data = curcon->data; - - if (data->lockflag == data->trackflag) - curcon->flag |= CONSTRAINT_DISABLE; - if (data->lockflag + 3 == data->trackflag) - curcon->flag |= CONSTRAINT_DISABLE; - } - else if (curcon->type == CONSTRAINT_TYPE_SPLINEIK) { - bSplineIKConstraint *data = curcon->data; - - /* if the number of points does not match the amount required by the chain length, - * free the points array and request a rebind... - */ - if ((data->points == NULL) || (data->numpoints != data->chainlen + 1)) { - /* free the points array */ - if (data->points) { - MEM_freeN(data->points); - data->points = NULL; - } - - /* clear the bound flag, forcing a rebind next time this is evaluated */ - data->flag &= ~CONSTRAINT_SPLINEIK_BOUND; - } - } - else if (curcon->type == CONSTRAINT_TYPE_FOLLOWTRACK) { - bFollowTrackConstraint *data = curcon->data; - - if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0) { - if (data->clip != NULL && data->track[0]) { - MovieTracking *tracking = &data->clip->tracking; - MovieTrackingObject *tracking_object; - - if (data->object[0]) - tracking_object = BKE_tracking_object_get_named(tracking, data->object); - else - tracking_object = BKE_tracking_object_get_camera(tracking); - - if (!tracking_object) { - curcon->flag |= CONSTRAINT_DISABLE; - } - else { - if (!BKE_tracking_track_get_named(tracking, tracking_object, data->track)) - curcon->flag |= CONSTRAINT_DISABLE; - } - } - else { - curcon->flag |= CONSTRAINT_DISABLE; - } - } - } - else if (curcon->type == CONSTRAINT_TYPE_CAMERASOLVER) { - bCameraSolverConstraint *data = curcon->data; - - if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL)) - curcon->flag |= CONSTRAINT_DISABLE; - } - else if (curcon->type == CONSTRAINT_TYPE_OBJECTSOLVER) { - bObjectSolverConstraint *data = curcon->data; - - if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL)) - curcon->flag |= CONSTRAINT_DISABLE; - } - - /* Check targets for constraints */ - if (cti && cti->get_constraint_targets) { - cti->get_constraint_targets(curcon, &targets); - - /* disable and clear constraints targets that are incorrect */ - for (ct = targets.first; ct; ct = ct->next) { - /* general validity checks (for those constraints that need this) */ - if (BKE_object_exists_check(ct->tar) == 0) { - /* object doesn't exist, but constraint requires target */ - ct->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - } - else if (ct->tar == owner) { - if (type == CONSTRAINT_OBTYPE_BONE) { - if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), ct->subtarget)) { - /* bone must exist in armature... */ - /* TODO: clear subtarget? */ - curcon->flag |= CONSTRAINT_DISABLE; - } - else if (STREQ(pchan->name, ct->subtarget)) { - /* cannot target self */ - ct->subtarget[0] = '\0'; - curcon->flag |= CONSTRAINT_DISABLE; - } - } - else { - /* cannot use self as target */ - ct->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - } - } - - /* target checks for specific constraints */ - if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) { - if (ct->tar) { - if (ct->tar->type != OB_CURVE) { - ct->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - } - else { - Curve *cu = ct->tar->data; - - /* auto-set 'Path' setting on curve so this works */ - cu->flag |= CU_PATH; - } - } - } - } - - /* free any temporary targets */ - if (cti->flush_constraint_targets) - cti->flush_constraint_targets(curcon, &targets, 0); - } + test_constraint(owner, pchan, curcon, type); } } } @@ -524,6 +537,26 @@ void object_test_constraints(Object *owner) } } +static void object_test_constraint(Object *owner, bConstraint *con) +{ + if (owner->type == OB_ARMATURE && owner->pose) { + if (BLI_findindex(&owner->constraints, con) != -1) { + test_constraint(owner, NULL, con, CONSTRAINT_OBTYPE_OBJECT); + } + else { + bPoseChannel *pchan; + for (pchan = owner->pose->chanbase.first; pchan; pchan = pchan->next) { + if (BLI_findindex(&pchan->constraints, con) != -1) { + test_constraint(owner, pchan, con, CONSTRAINT_OBTYPE_BONE); + break; + } + } + } + } + else { + test_constraint(owner, NULL, con, CONSTRAINT_OBTYPE_OBJECT); + } +} /************************ generic functions for operators using constraint names and data context *********************/ @@ -1161,20 +1194,49 @@ void ED_object_constraint_update(Object *ob) DAG_id_tag_update(&ob->id, OB_RECALC_OB); } +static void object_pose_tag_update(Object *ob) +{ + ob->pose->flag |= POSE_RECALC; /* Checks & sort pose channels. */ + if (ob->proxy && ob->adt) { + /* We need to make use of ugly POSE_ANIMATION_WORKAROUND here too, else anim data are not reloaded + * after calling `BKE_pose_rebuild()`, which causes T43872. + * Note that this is a bit wide here, since we cannot be sure whether there are some locked proxy bones + * or not... + * XXX Temp hack until new depsgraph hopefully solves this. */ + ob->adt->recalc |= ADT_RECALC_ANIM; + } +} + void ED_object_constraint_dependency_update(Main *bmain, Object *ob) { ED_object_constraint_update(ob); if (ob->pose) { - ob->pose->flag |= POSE_RECALC; /* Checks & sort pose channels. */ - if (ob->proxy && ob->adt) { - /* We need to make use of ugly POSE_ANIMATION_WORKAROUND here too, else anim data are not reloaded - * after calling `BKE_pose_rebuild()`, which causes T43872. - * Note that this is a bit wide here, since we cannot be sure whether there are some locked proxy bones - * or not... - * XXX Temp hack until new depsgraph hopefully solves this. */ - ob->adt->recalc |= ADT_RECALC_ANIM; - } + object_pose_tag_update(ob); + } + DAG_relations_tag_update(bmain); +} + +void ED_object_constraint_tag_update(Object *ob, bConstraint *con) +{ + if (ob->pose) { + BKE_pose_tag_update_constraint_flags(ob->pose); + } + + object_test_constraint(ob, con); + + if (ob->type == OB_ARMATURE) + DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); + else + DAG_id_tag_update(&ob->id, OB_RECALC_OB); +} + +void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstraint *con) +{ + ED_object_constraint_tag_update(ob, con); + + if (ob->pose) { + object_pose_tag_update(ob); } DAG_relations_tag_update(bmain); } diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 7b331181a58..761e76eb249 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -375,7 +375,9 @@ typedef enum ePose_Flags { /* set by BKE_pose_rebuild to give a chance to the IK solver to rebuild IK tree */ POSE_WAS_REBUILT = (1 << 5), /* set by game_copy_pose to indicate that this pose is used in the game engine */ - POSE_GAME_ENGINE = (1 << 6) + POSE_GAME_ENGINE = (1 << 6), + /* pose constraint flags needs to be updated */ + POSE_CONSTRAINTS_NEED_UPDATE_FLAGS = (1 << 7), } ePose_Flags; /* IK Solvers ------------------------------------ */ diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index aaacf07567e..0f4830a8a7e 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -271,12 +271,12 @@ static char *rna_Constraint_path(PointerRNA *ptr) static void rna_Constraint_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - ED_object_constraint_update(ptr->id.data); + ED_object_constraint_tag_update(ptr->id.data, ptr->data); } static void rna_Constraint_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ED_object_constraint_dependency_update(bmain, ptr->id.data); + ED_object_constraint_dependency_tag_update(bmain, ptr->id.data, ptr->data); } static void rna_Constraint_influence_update(Main *bmain, Scene *scene, PointerRNA *ptr) -- cgit v1.2.3 From 7c65b75d01c6e92458dd2deb937c39641f05792f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 20 Mar 2015 00:41:29 +1100 Subject: Correct recent armature symmetrize Duplicating part of a chain could have invalid 'connected' flag. --- source/blender/editors/armature/armature_add.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index 5cc2101650e..c2158f02ae3 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -639,6 +639,7 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) * Set the duplicate->parent to NULL */ ebone->parent = NULL; + ebone->flag &= ~BONE_CONNECTED; } else { /* the parent may have been duplicated, if not lookup the mirror parent */ @@ -652,6 +653,7 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) * So just use the same parent for both. */ ebone_parent = ebone_iter->parent; + ebone->flag &= ~BONE_CONNECTED; } ebone->parent = ebone_parent; -- cgit v1.2.3 From 93048873f10bab6ebcee9467a1e462f410f1bf12 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 19 Mar 2015 19:10:09 +0500 Subject: Fix compilation error of blenderplayer after recent constraint commit --- source/blenderplayer/bad_level_call_stubs/stubs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 0856b50c19b..893eae8485a 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -476,7 +476,9 @@ int ED_mesh_uv_texture_add(struct Mesh *me, const char *name, const bool active_ bool ED_mesh_color_remove_named(struct Mesh *me, const char *name) RET_ZERO bool ED_mesh_uv_texture_remove_named(struct Mesh *me, const char *name) RET_ZERO void ED_object_constraint_dependency_update(struct Main *bmain, struct Object *ob) RET_NONE +void ED_object_constraint_dependency_tag_update(struct Main *bmain, struct Object *ob, struct bConstraint *con) RET_NONE void ED_object_constraint_update(struct Object *ob) RET_NONE +void ED_object_constraint_tag_update(struct Object *ob, struct bConstraint *con) RET_NONE void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode) RET_NONE void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum) RET_NONE float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum) RET_ZERO -- cgit v1.2.3 From 3e9947c4d4714a4752c768bb78fe6d227fc6be97 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 3 Mar 2015 17:47:31 +0100 Subject: Depth of field high quality: A new checkbox "High quality" is provided in camera settings to enable this. This creates a depth of field that is much closer to the rendered result and even supports aperture blades in the effect, but it's more expensive too. There are optimizations to do here since the technique is very fill rate heavy. People, be careful, this -can- lock up your screen if depth of field blurring is too extreme. Technical details: This uses geometry shaders + instancing and is an adaptation of techniques gathered from http://bartwronski.com/2014/04/07/bokeh-depth-of-field-going-insane- http://advances.realtimerendering.com/s2011/SousaSchulzKazyan%20- %20in%20Real-Time%20Rendering%20Course).ppt TODOs: * Support dithering to minimize banding. * Optimize fill rate in geometry shader. --- intern/cycles/blender/addon/ui.py | 5 +- .../startup/bl_ui/properties_data_camera.py | 3 + source/blender/gpu/CMakeLists.txt | 6 + source/blender/gpu/GPU_compositing.h | 9 +- source/blender/gpu/GPU_extensions.h | 13 +- source/blender/gpu/intern/gpu_codegen.c | 2 +- source/blender/gpu/intern/gpu_compositing.c | 763 ++++++++++++++------- source/blender/gpu/intern/gpu_extensions.c | 167 ++++- source/blender/gpu/intern/gpu_simple_shader.c | 1 + .../gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl | 166 +++++ .../gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl | 50 ++ .../gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl | 58 ++ source/blender/makesdna/DNA_gpu_types.h | 2 + source/blender/makesrna/intern/rna_scene.c | 24 + 14 files changed, 981 insertions(+), 288 deletions(-) create mode 100644 source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl create mode 100644 source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl create mode 100644 source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 63518d7fdb6..b0337a69e7d 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -457,7 +457,10 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel): sub.active = cam.dof_object is None sub.prop(cam, "dof_distance", text="Distance") col.prop(dof_options, "fstop") - + col.prop(dof_options, "high_quality") + if dof_options.high_quality: + col.prop(dof_options, "num_blades") + col = split.column() col.label("Aperture:") diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py index 106e31ea89a..2097e82f992 100644 --- a/release/scripts/startup/bl_ui/properties_data_camera.py +++ b/release/scripts/startup/bl_ui/properties_data_camera.py @@ -187,6 +187,9 @@ class DATA_PT_camera_dof(CameraButtonsPanel, Panel): col = split.column() col.prop(dof_options, "fstop") + col.prop(dof_options, "high_quality") + if dof_options.high_quality: + col.prop(dof_options, "num_blades") sub = col.column() sub.active = cam.dof_object is None sub.prop(cam, "dof_distance", text="Distance") diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index b5d9028a8ae..97b0e7e1e0e 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -61,6 +61,9 @@ set(SRC shaders/gpu_shader_fx_ssao_frag.glsl shaders/gpu_shader_fx_dof_frag.glsl shaders/gpu_shader_fx_dof_vert.glsl + shaders/gpu_shader_fx_dof_hq_frag.glsl + shaders/gpu_shader_fx_dof_hq_vert.glsl + shaders/gpu_shader_fx_dof_hq_geo.glsl shaders/gpu_shader_fx_vert.glsl shaders/gpu_shader_material.glsl shaders/gpu_shader_sep_gaussian_blur_frag.glsl @@ -99,6 +102,9 @@ data_to_c_simple(shaders/gpu_shader_fx_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_ssao_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_dof_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_dof_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_fx_dof_hq_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_fx_dof_hq_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_fx_dof_hq_geo.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_depth_resolve.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_lib.glsl SRC) diff --git a/source/blender/gpu/GPU_compositing.h b/source/blender/gpu/GPU_compositing.h index 93f1bc64922..5589084705b 100644 --- a/source/blender/gpu/GPU_compositing.h +++ b/source/blender/gpu/GPU_compositing.h @@ -61,11 +61,16 @@ typedef enum GPUFXShaderEffect { GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR = 5, GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE = 6, - GPU_SHADER_FX_DEPTH_RESOLVE = 7, + /* high quality */ + GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE = 7, + GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO = 8, + GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE = 9, + + GPU_SHADER_FX_DEPTH_RESOLVE = 10, } GPUFXShaderEffect; /* keep in synch with enum above! */ -#define MAX_FX_SHADERS 8 +#define MAX_FX_SHADERS 11 /* generate a new FX compositor */ GPUFX *GPU_fx_compositor_create(void); diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 985cebc8687..aed1a88938a 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -61,13 +61,14 @@ bool GPU_non_power_of_two_support(void); bool GPU_vertex_buffer_support(void); bool GPU_display_list_support(void); bool GPU_bicubic_bump_support(void); +bool GPU_geometry_shader_support(void); +bool GPU_instanced_drawing_support(void); int GPU_max_texture_size(void); int GPU_color_depth(void); void GPU_code_generate_glsl_lib(void); - /* GPU Types */ typedef enum GPUDeviceType { @@ -120,7 +121,7 @@ GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, GPUHDRType GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels); GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]); GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]); -GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, char err_out[256]); +GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]); GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]); GPUTexture *GPU_texture_from_blender(struct Image *ima, struct ImageUser *iuser, bool is_data, double time, int mipmap); @@ -136,7 +137,7 @@ void GPU_texture_ref(GPUTexture *tex); void GPU_texture_bind(GPUTexture *tex, int number); void GPU_texture_unbind(GPUTexture *tex); -void GPU_depth_texture_mode(GPUTexture *tex, bool compare, bool use_filter); +void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter); GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex); @@ -183,7 +184,7 @@ int GPU_offscreen_height(const GPUOffScreen *ofs); * - only for fragment shaders now * - must call texture bind before setting a texture as uniform! */ -GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *libcode, const char *defines); +GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines); void GPU_shader_free(GPUShader *shader); void GPU_shader_bind(GPUShader *shader); @@ -192,8 +193,12 @@ void GPU_shader_unbind(void); int GPU_shader_get_uniform(GPUShader *shader, const char *name); void GPU_shader_uniform_vector(GPUShader *shader, int location, int length, int arraysize, const float *value); +void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length, + int arraysize, const int *value); + void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex); void GPU_shader_uniform_int(GPUShader *shader, int location, int value); +void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number); int GPU_shader_get_attribute(GPUShader *shader, const char *name); diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 40c9ec0d862..fcfb68d4629 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -1419,7 +1419,7 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, /* generate code and compile with opengl */ fragmentcode = code_generate_fragment(nodes, outlink->output); vertexcode = code_generate_vertex(nodes, type); - shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library, NULL); + shader = GPU_shader_create(vertexcode, fragmentcode, NULL, glsl_material_library, NULL); /* failed? */ if (!shader) { diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index 511167b775a..bfa938d0fed 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -62,11 +62,20 @@ struct GPUFX { * depth/color framebuffer. Could be extended later though */ GPUFrameBuffer *gbuffer; + /* dimensions of the gbuffer */ + int gbuffer_dim[2]; + /* texture bound to the first color attachment of the gbuffer */ GPUTexture *color_buffer; /* second texture used for ping-pong compositing */ GPUTexture *color_buffer_sec; + /* texture bound to the depth attachment of the gbuffer */ + GPUTexture *depth_buffer; + GPUTexture *depth_buffer_xray; + + /* texture used for jittering for various effects */ + GPUTexture *jitter_buffer; /* all those buffers below have to coexist. Fortunately they are all quarter sized (1/16th of memory) of original framebuffer */ int dof_downsampled_w; @@ -80,26 +89,20 @@ struct GPUFX { GPUTexture *dof_near_coc_final_buffer; /* half size blur buffer */ - GPUTexture *dof_half_downsampled; - /* high quality dof texture downsamplers. 6 levels means 64 pixels wide */ - GPUTexture *dof_nearfar_coc[6]; + GPUTexture *dof_half_downsampled_near; + GPUTexture *dof_half_downsampled_far; + /* high quality dof texture downsamplers. 6 levels means 64 pixels wide - should be enough */ + GPUTexture *dof_nearfar_coc; GPUTexture *dof_near_blur; GPUTexture *dof_far_blur; - GPUTexture *dof_concentric_samples_tex; - - /* texture bound to the depth attachment of the gbuffer */ - GPUTexture *depth_buffer; - GPUTexture *depth_buffer_xray; - /* texture used for jittering for various effects */ - GPUTexture *jitter_buffer; + /* for high quality we use again a spiral texture with radius adapted */ + bool dof_high_quality; /* texture used for ssao */ - int ssao_sample_count; - GPUTexture *ssao_concentric_samples_tex; + int ssao_sample_count_cache; + GPUTexture *ssao_spiral_samples_tex; - /* dimensions of the gbuffer */ - int gbuffer_dim[2]; GPUFXSettings settings; @@ -192,16 +195,17 @@ static void cleanup_fx_dof_buffers(GPUFX *fx) fx->dof_near_coc_final_buffer = NULL; } - if (fx->dof_half_downsampled) { - GPU_texture_free(fx->dof_half_downsampled); - fx->dof_half_downsampled = NULL; + if (fx->dof_half_downsampled_near) { + GPU_texture_free(fx->dof_half_downsampled_near); + fx->dof_half_downsampled_near = NULL; } - if (fx->dof_nearfar_coc[0]) { - int i; - for (i = 0; i < 6; i++) { - GPU_texture_free(fx->dof_nearfar_coc[i]); - fx->dof_nearfar_coc[i] = NULL; - } + if (fx->dof_half_downsampled_far) { + GPU_texture_free(fx->dof_half_downsampled_far); + fx->dof_half_downsampled_far = NULL; + } + if (fx->dof_nearfar_coc) { + GPU_texture_free(fx->dof_nearfar_coc); + fx->dof_nearfar_coc = NULL; } if (fx->dof_near_blur) { GPU_texture_free(fx->dof_near_blur); @@ -211,10 +215,6 @@ static void cleanup_fx_dof_buffers(GPUFX *fx) GPU_texture_free(fx->dof_far_blur); fx->dof_far_blur = NULL; } - if (fx->dof_concentric_samples_tex) { - GPU_texture_free(fx->dof_concentric_samples_tex); - fx->dof_concentric_samples_tex = NULL; - } } static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo) @@ -245,9 +245,9 @@ static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo) cleanup_fx_dof_buffers(fx); - if (fx->ssao_concentric_samples_tex) { - GPU_texture_free(fx->ssao_concentric_samples_tex); - fx->ssao_concentric_samples_tex = NULL; + if (fx->ssao_spiral_samples_tex) { + GPU_texture_free(fx->ssao_spiral_samples_tex); + fx->ssao_spiral_samples_tex = NULL; } if (fx->jitter_buffer && do_fbo) { @@ -279,7 +279,7 @@ static GPUTexture * create_jitter_texture(void) normalize_v2(jitter[i]); } - return GPU_texture_create_2D_procedural(64, 64, &jitter[0][0], NULL); + return GPU_texture_create_2D_procedural(64, 64, &jitter[0][0], true, NULL); } @@ -356,54 +356,108 @@ bool GPU_fx_compositor_initialize_passes( } if (fx_flag & GPU_FX_FLAG_SSAO) { - if (fx_settings->ssao->samples != fx->ssao_sample_count || !fx->ssao_concentric_samples_tex) { + if (fx_settings->ssao->samples != fx->ssao_sample_count_cache || !fx->ssao_spiral_samples_tex) { if (fx_settings->ssao->samples < 1) fx_settings->ssao->samples = 1; - fx->ssao_sample_count = fx_settings->ssao->samples; + fx->ssao_sample_count_cache = fx_settings->ssao->samples; - if (fx->ssao_concentric_samples_tex) { - GPU_texture_free(fx->ssao_concentric_samples_tex); + if (fx->ssao_spiral_samples_tex) { + GPU_texture_free(fx->ssao_spiral_samples_tex); } - fx->ssao_concentric_samples_tex = create_spiral_sample_texture(fx_settings->ssao->samples); + fx->ssao_spiral_samples_tex = create_spiral_sample_texture(fx_settings->ssao->samples); } } else { - if (fx->ssao_concentric_samples_tex) { - GPU_texture_free(fx->ssao_concentric_samples_tex); - fx->ssao_concentric_samples_tex = NULL; + if (fx->ssao_spiral_samples_tex) { + GPU_texture_free(fx->ssao_spiral_samples_tex); + fx->ssao_spiral_samples_tex = NULL; } } /* create textures for dof effect */ if (fx_flag & GPU_FX_FLAG_DOF) { - if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) { + bool dof_high_quality = (fx_settings->dof->high_quality != 0); + + if (dof_high_quality) { + fx->dof_downsampled_w = w / 2; + fx->dof_downsampled_h = h / 2; + + if (!fx->dof_half_downsampled_near || !fx->dof_nearfar_coc || !fx->dof_near_blur || + !fx->dof_far_blur || !fx->dof_half_downsampled_far) { + + if (!(fx->dof_half_downsampled_near = GPU_texture_create_2D( + fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) + { + printf("%.256s\n", err_out); + cleanup_fx_gl_data(fx, true); + return false; + } + if (!(fx->dof_half_downsampled_far = GPU_texture_create_2D( + fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) + { + printf("%.256s\n", err_out); + cleanup_fx_gl_data(fx, true); + return false; + } + if (!(fx->dof_nearfar_coc = GPU_texture_create_2D_procedural( + fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, false, err_out))) + { + printf("%.256s\n", err_out); + cleanup_fx_gl_data(fx, true); + return false; + } + + + if (!(fx->dof_near_blur = GPU_texture_create_2D( + fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out))) + { + printf("%.256s\n", err_out); + cleanup_fx_gl_data(fx, true); + return false; + } + + if (!(fx->dof_far_blur = GPU_texture_create_2D( + fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out))) + { + printf("%.256s\n", err_out); + cleanup_fx_gl_data(fx, true); + return false; + } + } + } + else { fx->dof_downsampled_w = w / 4; fx->dof_downsampled_h = h / 4; - if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D( - fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) - { - printf("%.256s\n", err_out); - cleanup_fx_gl_data(fx, true); - return false; - } - if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D( - fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) - { - printf("%.256s\n", err_out); - cleanup_fx_gl_data(fx, true); - return false; - } - if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D( - fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) - { - printf("%.256s\n", err_out); - cleanup_fx_gl_data(fx, true); - return false; + if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) { + + if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D( + fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) + { + printf("%.256s\n", err_out); + cleanup_fx_gl_data(fx, true); + return false; + } + if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D( + fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) + { + printf("%.256s\n", err_out); + cleanup_fx_gl_data(fx, true); + return false; + } + if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D( + fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) + { + printf("%.256s\n", err_out); + cleanup_fx_gl_data(fx, true); + return false; + } } } + + fx->dof_high_quality = dof_high_quality; } else { /* cleanup unnecessary buffers */ @@ -544,14 +598,14 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx) GPU_shader_bind(depth_resolve_shader); GPU_texture_bind(fx->depth_buffer_xray, 0); - GPU_depth_texture_mode(fx->depth_buffer_xray, false, true); + GPU_texture_filter_mode(fx->depth_buffer_xray, false, true); GPU_shader_uniform_texture(depth_resolve_shader, depth_uniform, fx->depth_buffer_xray); /* draw */ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* disable bindings */ - GPU_depth_texture_mode(fx->depth_buffer_xray, true, false); + GPU_texture_filter_mode(fx->depth_buffer_xray, true, false); GPU_texture_unbind(fx->depth_buffer_xray); GPU_shader_unbind(); @@ -643,7 +697,7 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, fx_ssao->attenuation, 0.0f}; float sample_params[4]; - sample_params[0] = fx->ssao_sample_count; + sample_params[0] = fx->ssao_sample_count_cache; /* multiplier so we tile the random texture on screen */ sample_params[2] = fx->gbuffer_dim[0] / 64.0; sample_params[3] = fx->gbuffer_dim[1] / 64.0; @@ -668,14 +722,14 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str GPU_shader_uniform_texture(ssao_shader, color_uniform, src); GPU_texture_bind(fx->depth_buffer, numslots++); - GPU_depth_texture_mode(fx->depth_buffer, false, true); + GPU_texture_filter_mode(fx->depth_buffer, false, true); GPU_shader_uniform_texture(ssao_shader, depth_uniform, fx->depth_buffer); GPU_texture_bind(fx->jitter_buffer, numslots++); GPU_shader_uniform_texture(ssao_shader, ssao_jitter_uniform, fx->jitter_buffer); - GPU_texture_bind(fx->ssao_concentric_samples_tex, numslots++); - GPU_shader_uniform_texture(ssao_shader, ssao_concentric_tex, fx->ssao_concentric_samples_tex); + GPU_texture_bind(fx->ssao_spiral_samples_tex, numslots++); + GPU_shader_uniform_texture(ssao_shader, ssao_concentric_tex, fx->ssao_spiral_samples_tex); /* draw */ gpu_fx_bind_render_target(&passes_left, fx, ofs, target); @@ -684,10 +738,10 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str /* disable bindings */ GPU_texture_unbind(src); - GPU_depth_texture_mode(fx->depth_buffer, true, false); + GPU_texture_filter_mode(fx->depth_buffer, true, false); GPU_texture_unbind(fx->depth_buffer); GPU_texture_unbind(fx->jitter_buffer); - GPU_texture_unbind(fx->ssao_concentric_samples_tex); + GPU_texture_unbind(fx->ssao_spiral_samples_tex); /* may not be attached, in that case this just returns */ if (target) { @@ -709,7 +763,6 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str /* second pass, dof */ if (fx->effects & GPU_FX_FLAG_DOF) { const GPUDOFSettings *fx_dof = fx->settings.dof; - GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3, *dof_shader_pass4, *dof_shader_pass5; float dof_params[4]; float scale = scene->unit.system ? scene->unit.scale_length : 1.0f; /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm @@ -722,243 +775,456 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str dof_params[0] = aperture * fabsf(scale_camera * fx_dof->focal_length / ((fx_dof->focus_distance / scale) - scale_camera * fx_dof->focal_length)); dof_params[1] = fx_dof->focus_distance / scale; dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor); - dof_params[3] = 0.0f; - - /* DOF effect has many passes but most of them are performed on a texture whose dimensions are 4 times less than the original - * (16 times lower than original screen resolution). Technique used is not very exact but should be fast enough and is based - * on "Practical Post-Process Depth of Field" see http://http.developer.nvidia.com/GPUGems3/gpugems3_ch28.html */ - dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE, is_persp); - dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO, is_persp); - dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE, is_persp); - dof_shader_pass4 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR, is_persp); - dof_shader_pass5 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE, is_persp); - - /* error occured, restore framebuffers and return */ - if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3 && dof_shader_pass4 && dof_shader_pass5)) { - GPU_framebuffer_texture_unbind(fx->gbuffer, NULL); - GPU_framebuffer_restore(); - return false; - } + dof_params[3] = fx_dof->num_blades; - /* pass first, first level of blur in low res buffer */ - { - int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform; - int viewvecs_uniform; + if (fx->dof_high_quality) { + GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3; - float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]}; + /* custom shaders close to the effect described in CryEngine 3 Graphics Gems */ + dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE, is_persp); + dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO, is_persp); + dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE, is_persp); - dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params"); - invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim"); - color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer"); - depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer"); - viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs"); + /* error occured, restore framebuffers and return */ + if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3)) { + GPU_framebuffer_texture_unbind(fx->gbuffer, NULL); + GPU_framebuffer_restore(); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); - GPU_shader_bind(dof_shader_pass1); + GPU_shader_unbind(); + return false; + } - GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params); - GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim); - GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]); + /* pass first, downsample the color buffer to near/far targets and calculate coc texture */ + { + int depth_uniform, dof_uniform; + int viewvecs_uniform; + int invrendertargetdim_uniform, color_uniform; + + float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h}; + + invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim"); + color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer"); + dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params"); + invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim"); + depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer"); + viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs"); + + GPU_shader_bind(dof_shader_pass1); + + GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params); + GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim); + GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]); + + GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim); + + GPU_texture_bind(fx->depth_buffer, numslots++); + GPU_texture_filter_mode(fx->depth_buffer, false, false); + GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer); + + GPU_texture_bind(src, numslots++); + /* disable filtering for the texture so custom downsample can do the right thing */ + GPU_texture_filter_mode(src, false, false); + GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, src); + + /* target is the downsampled coc buffer */ + GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_near, 0, NULL); + GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_far, 1, NULL); + GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_nearfar_coc, 2, NULL); + /* binding takes care of setting the viewport to the downsampled size */ + GPU_framebuffer_slots_bind(fx->gbuffer, 0); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + /* disable bindings */ + GPU_texture_filter_mode(src, false, true); + GPU_texture_unbind(src); + GPU_texture_filter_mode(fx->depth_buffer, true, false); + GPU_texture_unbind(fx->depth_buffer); + + GPU_framebuffer_texture_detach(fx->dof_half_downsampled_near); + GPU_framebuffer_texture_detach(fx->dof_half_downsampled_far); + GPU_framebuffer_texture_detach(fx->dof_nearfar_coc); + GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_half_downsampled_near); + + numslots = 0; + } - GPU_texture_bind(src, numslots++); - GPU_shader_uniform_texture(dof_shader_pass1, color_uniform, src); + /* second pass, shoot quads for every pixel in the downsampled buffers, scaling according + * to circle of confusion */ + { + int rendertargetdim_uniform, coc_uniform, color_uniform, select_uniform, dof_uniform; + int rendertargetdim[2] = {fx->dof_downsampled_w, fx->dof_downsampled_h}; + float selection[2] = {0.0f, 1.0f}; - GPU_texture_bind(fx->depth_buffer, numslots++); - GPU_depth_texture_mode(fx->depth_buffer, false, true); - GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer); + rendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "rendertargetdim"); - /* target is the downsampled coc buffer */ - GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL); - /* binding takes care of setting the viewport to the downsampled size */ - GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer); + color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer"); + coc_uniform = GPU_shader_get_uniform(dof_shader_pass2, "cocbuffer"); + select_uniform = GPU_shader_get_uniform(dof_shader_pass2, "layerselection"); + dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params"); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - /* disable bindings */ - GPU_texture_unbind(src); - GPU_depth_texture_mode(fx->depth_buffer, true, false); - GPU_texture_unbind(fx->depth_buffer); + GPU_shader_bind(dof_shader_pass2); - GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer); - numslots = 0; + GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params); + GPU_shader_uniform_vector_int(dof_shader_pass2, rendertargetdim_uniform, 2, 1, rendertargetdim); + GPU_shader_uniform_vector(dof_shader_pass2, select_uniform, 2, 1, selection); + + GPU_texture_bind(fx->dof_nearfar_coc, numslots++); + GPU_shader_uniform_texture(dof_shader_pass2, coc_uniform, fx->dof_nearfar_coc); + + GPU_texture_bind(fx->dof_half_downsampled_far, numslots++); + GPU_texture_bind(fx->dof_half_downsampled_near, numslots++); + GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_half_downsampled_far); + GPU_texture_filter_mode(fx->dof_half_downsampled_far, false, false); + + /* target is the downsampled coc buffer */ + GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_far_blur, 0, NULL); + GPU_texture_bind_as_framebuffer(fx->dof_far_blur); + + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + /* have to clear the buffer unfortunately */ + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */ + glDrawArraysInstancedEXT(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h); + + GPU_texture_unbind(fx->dof_half_downsampled_far); + GPU_framebuffer_texture_detach(fx->dof_far_blur); + + GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_half_downsampled_near); + GPU_texture_filter_mode(fx->dof_half_downsampled_near, false, false); + + selection[0] = 1.0f; + selection[1] = 0.0f; + + GPU_shader_uniform_vector(dof_shader_pass2, select_uniform, 2, 1, selection); + + GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_blur, 0, NULL); + /* have to clear the buffer unfortunately */ + glClear(GL_COLOR_BUFFER_BIT); + /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */ + glDrawArraysInstancedEXT(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h); + + /* disable bindings */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_BLEND); + + GPU_framebuffer_texture_detach(fx->dof_near_blur); + + GPU_texture_unbind(fx->dof_half_downsampled_near); + GPU_texture_unbind(fx->dof_nearfar_coc); + + GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_far_blur); + } + + /* third pass, accumulate the near/far blur fields */ + { + int invrendertargetdim_uniform, near_uniform, color_uniform; + int dof_uniform, far_uniform, viewvecs_uniform, depth_uniform; + + float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h}; + + dof_uniform = GPU_shader_get_uniform(dof_shader_pass3, "dof_params"); + invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass3, "invrendertargetdim"); + color_uniform = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer"); + far_uniform = GPU_shader_get_uniform(dof_shader_pass3, "farbuffer"); + near_uniform = GPU_shader_get_uniform(dof_shader_pass3, "nearbuffer"); + viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs"); + depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer"); + + GPU_shader_bind(dof_shader_pass3); + + GPU_shader_uniform_vector(dof_shader_pass3, dof_uniform, 4, 1, dof_params); + + GPU_shader_uniform_vector(dof_shader_pass3, invrendertargetdim_uniform, 2, 1, invrendertargetdim); + GPU_shader_uniform_vector(dof_shader_pass3, viewvecs_uniform, 4, 3, viewvecs[0]); + + GPU_texture_bind(fx->dof_near_blur, numslots++); + GPU_shader_uniform_texture(dof_shader_pass3, near_uniform, fx->dof_near_blur); + GPU_texture_filter_mode(fx->dof_near_blur, false, false); + + GPU_texture_bind(fx->dof_far_blur, numslots++); + GPU_shader_uniform_texture(dof_shader_pass3, far_uniform, fx->dof_far_blur); + GPU_texture_filter_mode(fx->dof_far_blur, false, false); + + GPU_texture_bind(fx->depth_buffer, numslots++); + GPU_texture_filter_mode(fx->depth_buffer, false, false); + GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer); + + GPU_texture_bind(src, numslots++); + GPU_shader_uniform_texture(dof_shader_pass3, color_uniform, src); + + /* if this is the last pass, prepare for rendering on the frambuffer */ + gpu_fx_bind_render_target(&passes_left, fx, ofs, target); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + /* disable bindings */ + GPU_texture_unbind(fx->dof_near_blur); + GPU_texture_unbind(fx->dof_far_blur); + GPU_texture_unbind(src); + GPU_texture_filter_mode(fx->depth_buffer, true, false); + GPU_texture_unbind(fx->depth_buffer); + + /* may not be attached, in that case this just returns */ + if (target) { + GPU_framebuffer_texture_detach(target); + if (ofs) { + GPU_offscreen_bind(ofs, false); + } + else { + GPU_framebuffer_restore(); + } + } + + numslots = 0; + } } + else { + GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3, *dof_shader_pass4, *dof_shader_pass5; + + /* DOF effect has many passes but most of them are performed on a texture whose dimensions are 4 times less than the original + * (16 times lower than original screen resolution). Technique used is not very exact but should be fast enough and is based + * on "Practical Post-Process Depth of Field" see http://http.developer.nvidia.com/GPUGems3/gpugems3_ch28.html */ + dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE, is_persp); + dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO, is_persp); + dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE, is_persp); + dof_shader_pass4 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR, is_persp); + dof_shader_pass5 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE, is_persp); + + /* error occured, restore framebuffers and return */ + if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3 && dof_shader_pass4 && dof_shader_pass5)) { + GPU_framebuffer_texture_unbind(fx->gbuffer, NULL); + GPU_framebuffer_restore(); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + GPU_shader_unbind(); + return false; + } - /* second pass, gaussian blur the downsampled image */ - { - int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform; - int viewvecs_uniform; - float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer), - 1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)}; - float tmp = invrendertargetdim[0]; - invrendertargetdim[0] = 0.0f; + /* pass first, first level of blur in low res buffer */ + { + int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform; + int viewvecs_uniform; - dof_params[2] = GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor); + float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]}; - dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params"); - invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "invrendertargetdim"); - color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer"); - depth_uniform = GPU_shader_get_uniform(dof_shader_pass2, "depthbuffer"); - viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass2, "viewvecs"); + dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params"); + invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim"); + color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer"); + depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer"); + viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs"); - /* Blurring vertically */ - GPU_shader_bind(dof_shader_pass2); + GPU_shader_bind(dof_shader_pass1); - GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params); - GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim); - GPU_shader_uniform_vector(dof_shader_pass2, viewvecs_uniform, 4, 3, viewvecs[0]); + GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params); + GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim); + GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]); - GPU_texture_bind(fx->depth_buffer, numslots++); - GPU_depth_texture_mode(fx->depth_buffer, false, true); - GPU_shader_uniform_texture(dof_shader_pass2, depth_uniform, fx->depth_buffer); + GPU_texture_bind(src, numslots++); + GPU_shader_uniform_texture(dof_shader_pass1, color_uniform, src); - GPU_texture_bind(fx->dof_near_coc_buffer, numslots++); - GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_buffer); + GPU_texture_bind(fx->depth_buffer, numslots++); + GPU_texture_filter_mode(fx->depth_buffer, false, true); + GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer); - /* use final buffer as a temp here */ - GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL); + /* target is the downsampled coc buffer */ + GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL); + /* binding takes care of setting the viewport to the downsampled size */ + GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer); - /* Drawing quad */ - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + /* disable bindings */ + GPU_texture_unbind(src); + GPU_texture_filter_mode(fx->depth_buffer, true, false); + GPU_texture_unbind(fx->depth_buffer); - /* *unbind/detach */ - GPU_texture_unbind(fx->dof_near_coc_buffer); - GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer); + GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer); + numslots = 0; + } - /* Blurring horizontally */ - invrendertargetdim[0] = tmp; - invrendertargetdim[1] = 0.0f; - GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim); + /* second pass, gaussian blur the downsampled image */ + { + int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform; + int viewvecs_uniform; + float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer), + 1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)}; + float tmp = invrendertargetdim[0]; + invrendertargetdim[0] = 0.0f; - GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++); - GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_final_buffer); + dof_params[2] = GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor); - GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, NULL); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params"); + invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "invrendertargetdim"); + color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer"); + depth_uniform = GPU_shader_get_uniform(dof_shader_pass2, "depthbuffer"); + viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass2, "viewvecs"); - /* *unbind/detach */ - GPU_depth_texture_mode(fx->depth_buffer, true, false); - GPU_texture_unbind(fx->depth_buffer); + /* Blurring vertically */ + GPU_shader_bind(dof_shader_pass2); - GPU_texture_unbind(fx->dof_near_coc_final_buffer); - GPU_framebuffer_texture_detach(fx->dof_near_coc_blurred_buffer); + GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params); + GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim); + GPU_shader_uniform_vector(dof_shader_pass2, viewvecs_uniform, 4, 3, viewvecs[0]); - dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor); + GPU_texture_bind(fx->depth_buffer, numslots++); + GPU_texture_filter_mode(fx->depth_buffer, false, true); + GPU_shader_uniform_texture(dof_shader_pass2, depth_uniform, fx->depth_buffer); - numslots = 0; - } + GPU_texture_bind(fx->dof_near_coc_buffer, numslots++); + GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_buffer); - /* third pass, calculate near coc */ - { - int near_coc_downsampled, near_coc_blurred; + /* use final buffer as a temp here */ + GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL); - near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer"); - near_coc_blurred = GPU_shader_get_uniform(dof_shader_pass3, "blurredcolorbuffer"); + /* Drawing quad */ + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - GPU_shader_bind(dof_shader_pass3); + /* *unbind/detach */ + GPU_texture_unbind(fx->dof_near_coc_buffer); + GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer); - GPU_texture_bind(fx->dof_near_coc_buffer, numslots++); - GPU_shader_uniform_texture(dof_shader_pass3, near_coc_downsampled, fx->dof_near_coc_buffer); + /* Blurring horizontally */ + invrendertargetdim[0] = tmp; + invrendertargetdim[1] = 0.0f; + GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim); - GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++); - GPU_shader_uniform_texture(dof_shader_pass3, near_coc_blurred, fx->dof_near_coc_blurred_buffer); + GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++); + GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_final_buffer); - GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL); + GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, NULL); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - /* disable bindings */ - GPU_texture_unbind(fx->dof_near_coc_buffer); - GPU_texture_unbind(fx->dof_near_coc_blurred_buffer); + /* *unbind/detach */ + GPU_texture_filter_mode(fx->depth_buffer, true, false); + GPU_texture_unbind(fx->depth_buffer); - /* unbinding here restores the size to the original */ - GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer); + GPU_texture_unbind(fx->dof_near_coc_final_buffer); + GPU_framebuffer_texture_detach(fx->dof_near_coc_blurred_buffer); - numslots = 0; - } + dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor); - /* fourth pass blur final coc once to eliminate discontinuities */ - { - int near_coc_downsampled; - int invrendertargetdim_uniform; - float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer), - 1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)}; + numslots = 0; + } - near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass4, "colorbuffer"); - invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass4, "invrendertargetdim"); + /* third pass, calculate near coc */ + { + int near_coc_downsampled, near_coc_blurred; - GPU_shader_bind(dof_shader_pass4); + near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer"); + near_coc_blurred = GPU_shader_get_uniform(dof_shader_pass3, "blurredcolorbuffer"); - GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++); - GPU_shader_uniform_texture(dof_shader_pass4, near_coc_downsampled, fx->dof_near_coc_final_buffer); - GPU_shader_uniform_vector(dof_shader_pass4, invrendertargetdim_uniform, 2, 1, invrendertargetdim); + GPU_shader_bind(dof_shader_pass3); - GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL); + GPU_texture_bind(fx->dof_near_coc_buffer, numslots++); + GPU_shader_uniform_texture(dof_shader_pass3, near_coc_downsampled, fx->dof_near_coc_buffer); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - /* disable bindings */ - GPU_texture_unbind(fx->dof_near_coc_final_buffer); + GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++); + GPU_shader_uniform_texture(dof_shader_pass3, near_coc_blurred, fx->dof_near_coc_blurred_buffer); - /* unbinding here restores the size to the original */ - GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_near_coc_buffer); - GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer); + GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL); - numslots = 0; - } + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + /* disable bindings */ + GPU_texture_unbind(fx->dof_near_coc_buffer); + GPU_texture_unbind(fx->dof_near_coc_blurred_buffer); - /* final pass, merge blurred layers according to final calculated coc */ - { - int medium_blurred_uniform, high_blurred_uniform, original_uniform, depth_uniform, dof_uniform; - int invrendertargetdim_uniform, viewvecs_uniform; - float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]}; + /* unbinding here restores the size to the original */ + GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer); - medium_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "mblurredcolorbuffer"); - high_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "blurredcolorbuffer"); - dof_uniform = GPU_shader_get_uniform(dof_shader_pass5, "dof_params"); - invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass5, "invrendertargetdim"); - original_uniform = GPU_shader_get_uniform(dof_shader_pass5, "colorbuffer"); - depth_uniform = GPU_shader_get_uniform(dof_shader_pass5, "depthbuffer"); - viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass5, "viewvecs"); + numslots = 0; + } - GPU_shader_bind(dof_shader_pass5); + /* fourth pass blur final coc once to eliminate discontinuities */ + { + int near_coc_downsampled; + int invrendertargetdim_uniform; + float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer), + 1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)}; - GPU_shader_uniform_vector(dof_shader_pass5, dof_uniform, 4, 1, dof_params); - GPU_shader_uniform_vector(dof_shader_pass5, invrendertargetdim_uniform, 2, 1, invrendertargetdim); - GPU_shader_uniform_vector(dof_shader_pass5, viewvecs_uniform, 4, 3, viewvecs[0]); + near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass4, "colorbuffer"); + invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass4, "invrendertargetdim"); - GPU_texture_bind(src, numslots++); - GPU_shader_uniform_texture(dof_shader_pass5, original_uniform, src); + GPU_shader_bind(dof_shader_pass4); - GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++); - GPU_shader_uniform_texture(dof_shader_pass5, high_blurred_uniform, fx->dof_near_coc_blurred_buffer); + GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++); + GPU_shader_uniform_texture(dof_shader_pass4, near_coc_downsampled, fx->dof_near_coc_final_buffer); + GPU_shader_uniform_vector(dof_shader_pass4, invrendertargetdim_uniform, 2, 1, invrendertargetdim); - GPU_texture_bind(fx->dof_near_coc_buffer, numslots++); - GPU_shader_uniform_texture(dof_shader_pass5, medium_blurred_uniform, fx->dof_near_coc_buffer); + GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL); - GPU_texture_bind(fx->depth_buffer, numslots++); - GPU_depth_texture_mode(fx->depth_buffer, false, true); - GPU_shader_uniform_texture(dof_shader_pass5, depth_uniform, fx->depth_buffer); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + /* disable bindings */ + GPU_texture_unbind(fx->dof_near_coc_final_buffer); - /* if this is the last pass, prepare for rendering on the frambuffer */ - gpu_fx_bind_render_target(&passes_left, fx, ofs, target); + /* unbinding here restores the size to the original */ + GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_near_coc_buffer); + GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - /* disable bindings */ - GPU_texture_unbind(fx->dof_near_coc_buffer); - GPU_texture_unbind(fx->dof_near_coc_blurred_buffer); - GPU_texture_unbind(src); - GPU_depth_texture_mode(fx->depth_buffer, true, false); - GPU_texture_unbind(fx->depth_buffer); + numslots = 0; + } - /* may not be attached, in that case this just returns */ - if (target) { - GPU_framebuffer_texture_detach(target); - if (ofs) { - GPU_offscreen_bind(ofs, false); - } - else { - GPU_framebuffer_restore(); + /* final pass, merge blurred layers according to final calculated coc */ + { + int medium_blurred_uniform, high_blurred_uniform, original_uniform, depth_uniform, dof_uniform; + int invrendertargetdim_uniform, viewvecs_uniform; + float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]}; + + medium_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "mblurredcolorbuffer"); + high_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "blurredcolorbuffer"); + dof_uniform = GPU_shader_get_uniform(dof_shader_pass5, "dof_params"); + invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass5, "invrendertargetdim"); + original_uniform = GPU_shader_get_uniform(dof_shader_pass5, "colorbuffer"); + depth_uniform = GPU_shader_get_uniform(dof_shader_pass5, "depthbuffer"); + viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass5, "viewvecs"); + + GPU_shader_bind(dof_shader_pass5); + + GPU_shader_uniform_vector(dof_shader_pass5, dof_uniform, 4, 1, dof_params); + GPU_shader_uniform_vector(dof_shader_pass5, invrendertargetdim_uniform, 2, 1, invrendertargetdim); + GPU_shader_uniform_vector(dof_shader_pass5, viewvecs_uniform, 4, 3, viewvecs[0]); + + GPU_texture_bind(src, numslots++); + GPU_shader_uniform_texture(dof_shader_pass5, original_uniform, src); + + GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++); + GPU_shader_uniform_texture(dof_shader_pass5, high_blurred_uniform, fx->dof_near_coc_blurred_buffer); + + GPU_texture_bind(fx->dof_near_coc_buffer, numslots++); + GPU_shader_uniform_texture(dof_shader_pass5, medium_blurred_uniform, fx->dof_near_coc_buffer); + + GPU_texture_bind(fx->depth_buffer, numslots++); + GPU_texture_filter_mode(fx->depth_buffer, false, true); + GPU_shader_uniform_texture(dof_shader_pass5, depth_uniform, fx->depth_buffer); + + /* if this is the last pass, prepare for rendering on the frambuffer */ + gpu_fx_bind_render_target(&passes_left, fx, ofs, target); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + /* disable bindings */ + GPU_texture_unbind(fx->dof_near_coc_buffer); + GPU_texture_unbind(fx->dof_near_coc_blurred_buffer); + GPU_texture_unbind(src); + GPU_texture_filter_mode(fx->depth_buffer, true, false); + GPU_texture_unbind(fx->depth_buffer); + + /* may not be attached, in that case this just returns */ + if (target) { + GPU_framebuffer_texture_detach(target); + if (ofs) { + GPU_offscreen_bind(ofs, false); + } + else { + GPU_framebuffer_restore(); + } } - } - SWAP(GPUTexture *, target, src); - numslots = 0; + SWAP(GPUTexture *, target, src); + numslots = 0; + } } } @@ -976,6 +1242,7 @@ void GPU_fx_compositor_init_dof_settings(GPUDOFSettings *fx_dof) fx_dof->focal_length = 1.0f; fx_dof->focus_distance = 1.0f; fx_dof->sensor = 1.0f; + fx_dof->num_blades = 6; } void GPU_fx_compositor_init_ssao_settings(GPUSSAOSettings *fx_ssao) diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index f16b1525622..24b54a3af37 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -61,6 +61,7 @@ #endif #define MAX_DEFINE_LENGTH 72 +#define MAX_EXT_DEFINE_LENGTH 280 /* Extensions support */ @@ -83,6 +84,9 @@ extern char datatoc_gpu_shader_fx_vert_glsl[]; extern char datatoc_gpu_shader_fx_ssao_frag_glsl[]; extern char datatoc_gpu_shader_fx_dof_frag_glsl[]; extern char datatoc_gpu_shader_fx_dof_vert_glsl[]; +extern char datatoc_gpu_shader_fx_dof_hq_frag_glsl[]; +extern char datatoc_gpu_shader_fx_dof_hq_vert_glsl[]; +extern char datatoc_gpu_shader_fx_dof_hq_geo_glsl[]; extern char datatoc_gpu_shader_fx_depth_resolve_glsl[]; extern char datatoc_gpu_shader_fx_lib_glsl[]; @@ -278,6 +282,16 @@ bool GPU_bicubic_bump_support(void) return GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0; } +bool GPU_geometry_shader_support(void) +{ + return GLEW_EXT_geometry_shader4 || GLEW_VERSION_3_2; +} + +bool GPU_instanced_drawing_support(void) +{ + return GLEW_EXT_draw_instanced; +} + int GPU_color_depth(void) { return GG.colordepth; @@ -736,14 +750,16 @@ GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]) return tex; } -GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, char err_out[256]) +GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]) { GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, err_out); if (tex) { /* Now we tweak some of the settings */ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + if (repeat) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -863,7 +879,7 @@ void GPU_texture_unbind(GPUTexture *tex) GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind"); } -void GPU_depth_texture_mode(GPUTexture *tex, bool compare, bool use_filter) +void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter) { GLenum arbnumber; @@ -872,11 +888,6 @@ void GPU_depth_texture_mode(GPUTexture *tex, bool compare, bool use_filter) return; } - if (!tex->depth) { - fprintf(stderr, "Not a depth texture."); - return; - } - if (tex->number == -1) return; @@ -884,10 +895,13 @@ void GPU_depth_texture_mode(GPUTexture *tex, bool compare, bool use_filter) arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number); if (tex->number != 0) glActiveTextureARB(arbnumber); - if (compare) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); - else - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + + if (tex->depth) { + if (compare) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + } if (use_filter) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -1384,6 +1398,7 @@ struct GPUShader { GLhandleARB object; /* handle for full shader */ GLhandleARB vertex; /* handle for vertex shader */ GLhandleARB fragment; /* handle for fragment shader */ + GLhandleARB geometry; /* handle for geometry shader */ GLhandleARB lib; /* handle for libment shader */ int totattrib; /* total number of attributes */ int uniforms; /* required uniforms */ @@ -1430,13 +1445,19 @@ static const char *gpu_shader_version(void) } -static const char *gpu_shader_standard_extensions(void) +static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH]) { /* need this extensions for high quality bump mapping */ if (GPU_bicubic_bump_support()) - return "#extension GL_ARB_texture_query_lod: enable\n"; + strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n"); - return ""; + if (GPU_geometry_shader_support()) + strcat(defines, "#extension GL_EXT_geometry_shader4: enable\n"); + + if (GPU_instanced_drawing_support()) { + strcat(defines, "#extension GL_EXT_gpu_shader4: enable\n"); + strcat(defines, "#extension GL_EXT_draw_instanced: enable\n"); + } } static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH]) @@ -1457,15 +1478,16 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH]) return; } -GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *libcode, const char *defines) +GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines) { GLint status; GLcharARB log[5000]; GLsizei length = 0; GPUShader *shader; char standard_defines[MAX_DEFINE_LENGTH] = ""; + char standard_extensions[MAX_EXT_DEFINE_LENGTH] = ""; - if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader) + if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader || (geocode && !GPU_geometry_shader_support())) return NULL; shader = MEM_callocN(sizeof(GPUShader), "GPUShader"); @@ -1474,11 +1496,15 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const shader->vertex = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); if (fragcode) shader->fragment = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); + if (geocode) + shader->geometry = glCreateShaderObjectARB(GL_GEOMETRY_SHADER_EXT); + shader->object = glCreateProgramObjectARB(); if (!shader->object || (vertexcode && !shader->vertex) || - (fragcode && !shader->fragment)) + (fragcode && !shader->fragment) || + (geocode && !shader->geometry)) { fprintf(stderr, "GPUShader, object creation failed.\n"); GPU_shader_free(shader); @@ -1486,6 +1512,7 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const } gpu_shader_standard_defines(standard_defines); + gpu_shader_standard_extensions(standard_extensions); if (vertexcode) { const char *source[5]; @@ -1493,11 +1520,11 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const int num_source = 0; source[num_source++] = gpu_shader_version(); - source[num_source++] = gpu_shader_standard_extensions(); + source[num_source++] = standard_extensions; source[num_source++] = standard_defines; if (defines) source[num_source++] = defines; - if (vertexcode) source[num_source++] = vertexcode; + source[num_source++] = vertexcode; glAttachObjectARB(shader->object, shader->vertex); glShaderSourceARB(shader->vertex, num_source, source, NULL); @@ -1519,12 +1546,12 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const int num_source = 0; source[num_source++] = gpu_shader_version(); - source[num_source++] = gpu_shader_standard_extensions(); + source[num_source++] = standard_extensions; source[num_source++] = standard_defines; if (defines) source[num_source++] = defines; if (libcode) source[num_source++] = libcode; - if (fragcode) source[num_source++] = fragcode; + source[num_source++] = fragcode; glAttachObjectARB(shader->object, shader->fragment); glShaderSourceARB(shader->fragment, num_source, source, NULL); @@ -1541,6 +1568,34 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const } } + if (geocode) { + const char *source[6]; + int num_source = 0; + + source[num_source++] = gpu_shader_version(); + source[num_source++] = standard_extensions; + source[num_source++] = standard_defines; + + if (defines) source[num_source++] = defines; + if (libcode) source[num_source++] = libcode; + source[num_source++] = geocode; + + glAttachObjectARB(shader->object, shader->geometry); + glShaderSourceARB(shader->geometry, num_source, source, NULL); + + glCompileShaderARB(shader->geometry); + glGetObjectParameterivARB(shader->geometry, GL_OBJECT_COMPILE_STATUS_ARB, &status); + + if (!status) { + glGetInfoLogARB(shader->geometry, sizeof(log), &length, log); + shader_print_errors("compile", log, source, num_source); + + GPU_shader_free(shader); + return NULL; + } + } + + #if 0 if (lib && lib->lib) glAttachObjectARB(shader->object, lib->lib); @@ -1553,6 +1608,7 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const if (fragcode) shader_print_errors("linking", log, &fragcode, 1); else if (vertexcode) shader_print_errors("linking", log, &vertexcode, 1); else if (libcode) shader_print_errors("linking", log, &libcode, 1); + else if (geocode) shader_print_errors("linking", log, &geocode, 1); GPU_shader_free(shader); return NULL; @@ -1648,6 +1704,21 @@ void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int leng GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector"); } +void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value) +{ + if (location == -1) + return; + + GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector"); + + if (length == 1) glUniform1ivARB(location, arraysize, value); + else if (length == 2) glUniform2ivARB(location, arraysize, value); + else if (length == 3) glUniform3ivARB(location, arraysize, value); + else if (length == 4) glUniform4ivARB(location, arraysize, value); + + GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector"); +} + void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value) { if (location == -1) @@ -1656,6 +1727,16 @@ void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value) GPU_CHECK_ERRORS_AROUND(glUniform1iARB(location, value)); } +void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number) +{ + glProgramParameteriEXT(shader->object, GL_GEOMETRY_INPUT_TYPE_EXT, input); + glProgramParameteriEXT(shader->object, GL_GEOMETRY_OUTPUT_TYPE_EXT, output); + glProgramParameteriEXT(shader->object, GL_GEOMETRY_VERTICES_OUT_EXT, number); + + /* relink so settings can take effect (sucks but should only be done right after compilation so...) */ + glLinkProgramARB(shader->object); +} + void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex) { GLenum arbnumber; @@ -1703,12 +1784,12 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) switch (shader) { case GPU_SHADER_VSM_STORE: if (!GG.shaders.vsm_store) - GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL); + GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL, NULL); retval = GG.shaders.vsm_store; break; case GPU_SHADER_SEP_GAUSSIAN_BLUR: if (!GG.shaders.sep_gaussian_blur) - GG.shaders.sep_gaussian_blur = GPU_shader_create(datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, NULL, NULL); + GG.shaders.sep_gaussian_blur = GPU_shader_create(datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, NULL, NULL, NULL); retval = GG.shaders.sep_gaussian_blur; break; } @@ -1737,38 +1818,60 @@ GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp) } if (!GG.shaders.fx_shaders[offset]) { + GPUShader *shader; + switch(effects) { case GPU_SHADER_FX_SSAO: - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); break; case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE: strcat(defines, "#define FIRST_PASS\n"); - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); break; case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO: strcat(defines, "#define SECOND_PASS\n"); - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); break; case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE: strcat(defines, "#define THIRD_PASS\n"); - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); break; case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR: strcat(defines, "#define FOURTH_PASS\n"); - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); break; case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE: strcat(defines, "#define FIFTH_PASS\n"); - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); + break; + + case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE: + strcat(defines, "#define FIRST_PASS\n"); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); + break; + + case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO: + strcat(defines, "#define SECOND_PASS\n"); + shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl, defines); + + if (shader) { + GG.shaders.fx_shaders[offset] = shader; + GPU_shader_geometry_stage_primitive_io(shader, GL_POINTS, GL_TRIANGLE_STRIP, 4); + } + break; + + case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE: + strcat(defines, "#define THIRD_PASS\n"); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); break; case GPU_SHADER_FX_DEPTH_RESOLVE: - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines); } } diff --git a/source/blender/gpu/intern/gpu_simple_shader.c b/source/blender/gpu/intern/gpu_simple_shader.c index 3fa5975ef15..60d4a2f2875 100644 --- a/source/blender/gpu/intern/gpu_simple_shader.c +++ b/source/blender/gpu/intern/gpu_simple_shader.c @@ -151,6 +151,7 @@ static GPUShader *gpu_simple_shader(int options) shader = GPU_shader_create( datatoc_gpu_shader_simple_vert_glsl, datatoc_gpu_shader_simple_frag_glsl, + NULL, NULL, defines); if (shader) { diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl new file mode 100644 index 00000000000..e2d3ab36ec8 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl @@ -0,0 +1,166 @@ +/* amount of offset to move one pixel left-right. + * In second pass some dimensions are zero to control verical/horizontal convolution */ +uniform vec2 invrendertargetdim; + +uniform ivec2 rendertargetdim; + +/* color buffer */ +uniform sampler2D colorbuffer; +uniform sampler2D farbuffer; +uniform sampler2D nearbuffer; + +/* depth buffer */ +uniform sampler2D depthbuffer; + +uniform sampler2D cocbuffer; + +/* this includes focal distance in x and aperture size in y */ +uniform vec4 dof_params; + +/* viewvectors for reconstruction of world space */ +uniform vec4 viewvecs[3]; + +/* initial uv coordinate */ +varying vec2 uvcoord; + +/* coordinate used for calculating radius et al set in geometry shader */ +varying vec2 particlecoord; +varying vec4 color; + +/* downsampling coordinates */ +varying vec2 downsample1; +varying vec2 downsample2; +varying vec2 downsample3; +varying vec2 downsample4; + +#define M_PI 3.1415926535897932384626433832795 + +/* calculate 4 samples at once */ +vec4 calculate_coc(in vec4 zdepth) +{ + vec4 coc = dof_params.x * (vec4(dof_params.y) / zdepth - vec4(1.0)); + + /* multiply by 1.0 / sensor size to get the normalized size */ + return coc * dof_params.z; +} + +#define THRESHOLD 0.0 + +/* downsample the color buffer to half resolution */ +void downsample_pass() +{ + vec4 depth; + vec4 zdepth; + vec4 coc; + float far_coc, near_coc; + + /* custom downsampling. We need to be careful to sample nearest here to avoid leaks */ + vec4 color1 = texture2D(colorbuffer, downsample1); + vec4 color2 = texture2D(colorbuffer, downsample2); + vec4 color3 = texture2D(colorbuffer, downsample3); + vec4 color4 = texture2D(colorbuffer, downsample4); + + depth.r = texture2D(depthbuffer, downsample1).r; + depth.g = texture2D(depthbuffer, downsample2).r; + depth.b = texture2D(depthbuffer, downsample3).r; + depth.a = texture2D(depthbuffer, downsample4).r; + + zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth); + coc = calculate_coc(zdepth); + vec4 coc_far = -coc; + + /* now we need to write the near-far fields premultiplied by the coc */ + vec4 near_weights = vec4((coc.x >= THRESHOLD) ? 1.0 : 0.0, (coc.y >= THRESHOLD) ? 1.0 : 0.0, + (coc.z >= THRESHOLD) ? 1.0 : 0.0, (coc.w >= THRESHOLD) ? 1.0 : 0.0); + vec4 far_weights = vec4((coc_far.x >= THRESHOLD) ? 1.0 : 0.0, (coc_far.y >= THRESHOLD) ? 1.0 : 0.0, + (coc_far.z >= THRESHOLD) ? 1.0 : 0.0, (coc_far.w >= THRESHOLD) ? 1.0 : 0.0); + + near_coc = max(max(max(coc.x, coc.y), max(coc.z, coc.w)), 0.0); + far_coc = max(max(max(coc_far.x, coc_far.y), max(coc_far.z, coc_far.w)), 0.0); + + float norm_near = dot(near_weights, vec4(1.0)); + float norm_far = dot(far_weights, vec4(1.0)); + + /* now write output to weighted buffers. */ + gl_FragData[0] = color1 * near_weights.x + color2 * near_weights.y + color3 * near_weights.z + + color4 * near_weights.w; + gl_FragData[1] = color1 * far_weights.x + color2 * far_weights.y + color3 * far_weights.z + + color4 * far_weights.w; + + if (norm_near > 0.0) + gl_FragData[0] /= norm_near; + if (norm_far > 0.0) + gl_FragData[1] /= norm_far; + gl_FragData[2] = vec4(near_coc, far_coc, 0.0, 1.0); +} + +/* accumulate color in the near/far blur buffers */ +void accumulate_pass(void) { + float theta = atan(particlecoord.y, particlecoord.x); + float r; + + if (dof_params.w == 0.0) + r = 1.0; + else + r = cos(M_PI / dof_params.w) / (cos(theta - (2.0 * M_PI / dof_params.w) * floor((dof_params.w * theta + M_PI) / (2 * M_PI)))); + + if (dot(particlecoord, particlecoord) > r * r) + discard; + + gl_FragColor = color; +} +#define MERGE_THRESHOLD 4.0 + +/* combine the passes, */ +void final_pass(void) { + vec4 finalcolor; + float totalweight; + float depth = texture2D(depthbuffer, uvcoord).r; + + vec4 zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), vec4(depth)); + float coc_near = calculate_coc(zdepth).r; + float coc_far = max(-coc_near, 0.0); + coc_near = max(coc_near, 0.0); + + vec4 farcolor = texture2D(farbuffer, uvcoord); + float farweight = farcolor.a; + if (farweight > 0) + farcolor /= farweight; + vec4 nearcolor = texture2D(nearbuffer, uvcoord); + + vec4 srccolor = texture2D(colorbuffer, uvcoord); + + vec4 coc = texture2D(cocbuffer, uvcoord); + + float mixfac = smoothstep(1.0, MERGE_THRESHOLD, coc_far); + finalcolor = mix(srccolor, farcolor, mixfac); + + farweight = mix(1.0, farweight, mixfac); + + float nearweight = nearcolor.a; + if (nearweight > 0) { + nearcolor /= nearweight; + } + + if (coc_near > 1.0) { + nearweight = 1.0; + finalcolor = nearcolor; + } + else { + totalweight = nearweight + farweight; + finalcolor = mix(finalcolor, nearcolor, nearweight / totalweight); + } + + gl_FragColor = finalcolor; +} + +void main() +{ +#ifdef FIRST_PASS + downsample_pass(); +#elif defined(SECOND_PASS) + accumulate_pass(); +#elif defined(THIRD_PASS) + final_pass(); +#endif +} diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl new file mode 100644 index 00000000000..9f365a0d671 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl @@ -0,0 +1,50 @@ +uniform ivec2 rendertargetdim; +uniform sampler2D colorbuffer; + +uniform vec2 layerselection; + +uniform sampler2D cocbuffer; + +/* initial uv coordinate */ +varying in vec2 uvcoord[]; +varying out vec2 particlecoord; +varying out vec4 color; + + +#define M_PI 3.1415926535897932384626433832795 + +void main(void) +{ + vec4 coc = texture2DLod(cocbuffer, uvcoord[0], 0.0); + + float offset_val = dot(coc.rg, layerselection); + if (offset_val < 1.0) + return; + + vec4 colortex = texture2DLod(colorbuffer, uvcoord[0], 0.0); + + /* find the area the pixel will cover and divide the color by it */ + float alpha = 1.0 / (offset_val * offset_val * M_PI); + colortex *= alpha; + colortex.a = alpha; + + vec2 offset_far = vec2(offset_val * 0.5) / vec2(rendertargetdim.x, rendertargetdim.y); + + gl_Position = gl_PositionIn[0] + vec4(-offset_far.x, -offset_far.y, 0.0, 0.0); + color = colortex; + particlecoord = vec2(-1.0, -1.0); + EmitVertex(); + gl_Position = gl_PositionIn[0] + vec4(-offset_far.x, offset_far.y, 0.0, 0.0); + particlecoord = vec2(-1.0, 1.0); + color = colortex; + EmitVertex(); + gl_Position = gl_PositionIn[0] + vec4(offset_far.x, -offset_far.y, 0.0, 0.0); + particlecoord = vec2(1.0, -1.0); + color = colortex; + EmitVertex(); + gl_Position = gl_PositionIn[0] + vec4(offset_far.x, offset_far.y, 0.0, 0.0); + particlecoord = vec2(1.0, 1.0); + color = colortex; + EmitVertex(); + EndPrimitive(); +} diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl new file mode 100644 index 00000000000..e8c505bd15f --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl @@ -0,0 +1,58 @@ +uniform vec2 invrendertargetdim; +uniform ivec2 rendertargetdim; +/* initial uv coordinate */ +varying vec2 uvcoord; + +/* coordinate used for calculating radius et al set in geometry shader */ +varying vec2 particlecoord; + +/* downsampling coordinates */ +varying vec2 downsample1; +varying vec2 downsample2; +varying vec2 downsample3; +varying vec2 downsample4; + +void vert_dof_downsample() +{ + /* gather pixels from neighbors. half dimensions means we offset half a pixel to + * get this right though it's possible we may lose a pixel at some point */ + downsample1 = gl_MultiTexCoord0.xy + vec2(-0.5, -0.5) * invrendertargetdim; + downsample2 = gl_MultiTexCoord0.xy + vec2(-0.5, 0.5) * invrendertargetdim; + downsample3 = gl_MultiTexCoord0.xy + vec2(0.5, 0.5) * invrendertargetdim; + downsample4 = gl_MultiTexCoord0.xy + vec2(0.5, -0.5) * invrendertargetdim; + + gl_Position = gl_Vertex; +} + +/* geometry shading pass, calculate a texture coordinate based on the indexed id */ +void vert_dof_coc_scatter_pass() +{ + vec2 pixel = vec2(1.0 / float(rendertargetdim.x), 1.0 / float(rendertargetdim.y)); + /* some math to get the target pixel */ + int row = gl_InstanceID / rendertargetdim.x; + int column = gl_InstanceID % rendertargetdim.x; + uvcoord = vec2(column, row) * pixel + 0.5 * pixel; + + vec2 pos = uvcoord * 2.0 - vec2(1.0); + gl_Position = vec4(pos.x, pos.y, 0.0, 1.0); + +// uvcoord = vec2(0.5, 0.5); +// gl_Position = vec4(0.0, 0.0, 0.0, 1.0); +} + +void vert_dof_final() +{ + uvcoord = gl_MultiTexCoord0.xy; + gl_Position = gl_Vertex; +} + +void main() +{ +#if defined(FIRST_PASS) + vert_dof_downsample(); +#elif defined(SECOND_PASS) + vert_dof_coc_scatter_pass(); +#else + vert_dof_final(); +#endif +} \ No newline at end of file diff --git a/source/blender/makesdna/DNA_gpu_types.h b/source/blender/makesdna/DNA_gpu_types.h index b6009b3f899..967cb7284dc 100644 --- a/source/blender/makesdna/DNA_gpu_types.h +++ b/source/blender/makesdna/DNA_gpu_types.h @@ -38,6 +38,8 @@ typedef struct GPUDOFSettings { float fstop; float focal_length; float sensor; + int num_blades; + int high_quality; } GPUDOFSettings; /* properties for SSAO effect */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 629fbbf66e9..4214c830e4c 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1745,6 +1745,19 @@ static void rna_GPUFXSettings_fx_update(Main *UNUSED(bmain), Scene *UNUSED(scene BKE_screen_gpu_fx_validate(fx_settings); } +static void rna_GPUDOFSettings_blades_set(PointerRNA *ptr, const int value) +{ + GPUDOFSettings *dofsettings = (GPUDOFSettings *)ptr->data; + + if (value < 3 && dofsettings->num_blades > 2) + dofsettings->num_blades = 0; + else if (value > 0 && dofsettings->num_blades == 0) + dofsettings->num_blades = 3; + else + dofsettings->num_blades = value; +} + + #else static void rna_def_transform_orientation(BlenderRNA *brna) @@ -3908,6 +3921,17 @@ static void rna_def_gpu_dof_fx(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, FLT_MAX); RNA_def_property_ui_range(prop, 0.1f, 128.0f, 10, 1); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "num_blades", PROP_INT, PROP_NONE); + RNA_def_property_ui_text(prop, "Viewport Camera Blades", "Blades for dof effect"); + RNA_def_property_range(prop, 0, 16); + RNA_def_property_int_funcs(prop, NULL, "rna_GPUDOFSettings_blades_set", NULL); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "high_quality", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "high_quality", 1); + RNA_def_property_ui_text(prop, "High Quality", "Use high quality depth of field"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); } static void rna_def_gpu_ssao_fx(BlenderRNA *brna) -- cgit v1.2.3 From 881e05fc54058bc04b217817808315b2f9691c2a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 20 Mar 2015 01:37:29 +1100 Subject: Armature select-hierarchy now uses connected bones Traverse down connected child bones (when available) Also remove redundant bone loops. --- source/blender/editors/armature/armature_select.c | 105 +++++++++++----------- source/blender/editors/armature/pose_select.c | 102 ++++++++++----------- 2 files changed, 103 insertions(+), 104 deletions(-) diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 581dd00e285..5061ba9a812 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -962,75 +962,78 @@ void ARMATURE_OT_select_similar(wmOperatorType *ot) /* ********************* select hierarchy operator ************** */ -/* Get the first available child of an editbone */ -static EditBone *editbone_get_child(bArmature *arm, EditBone *pabone, short use_visibility) -{ - EditBone *curbone, *chbone = NULL; - - for (curbone = arm->edbo->first; curbone; curbone = curbone->next) { - if (curbone->parent == pabone) { - if (use_visibility) { - if ((arm->layer & curbone->layer) && !(pabone->flag & BONE_HIDDEN_A)) { - chbone = curbone; - } - } - else - chbone = curbone; - } - } - - return chbone; -} - static int armature_select_hierarchy_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); Object *ob; bArmature *arm; - EditBone *curbone, *pabone, *chbone; + EditBone *ebone_active; int direction = RNA_enum_get(op->ptr, "direction"); const bool add_to_sel = RNA_boolean_get(op->ptr, "extend"); + bool changed = false; ob = obedit; arm = (bArmature *)ob->data; - - for (curbone = arm->edbo->first; curbone; curbone = curbone->next) { - /* only work on bone if it is visible and its selection can change */ - if (EBONE_SELECTABLE(arm, curbone)) { - if (curbone == arm->act_edbone) { - if (direction == BONE_SELECT_PARENT) { - if (curbone->parent == NULL) continue; - else pabone = curbone->parent; - - if (EBONE_VISIBLE(arm, pabone)) { - pabone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - arm->act_edbone = pabone; - if (pabone->parent) pabone->parent->flag |= BONE_TIPSEL; - - if (!add_to_sel) curbone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - break; - } - + + ebone_active = arm->act_edbone; + if (ebone_active == NULL) { + return OPERATOR_CANCELLED; + } + + if (direction == BONE_SELECT_PARENT) { + if (ebone_active->parent) { + EditBone *ebone_parent; + + ebone_parent = ebone_active->parent; + + if (EBONE_SELECTABLE(arm, ebone_parent)) { + arm->act_edbone = ebone_parent; + + if (!add_to_sel) { + ED_armature_ebone_select_set(ebone_active, false); } - else { // BONE_SELECT_CHILD - chbone = editbone_get_child(arm, curbone, 1); - if (chbone == NULL) continue; - - if (EBONE_SELECTABLE(arm, chbone)) { - chbone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - arm->act_edbone = chbone; - - if (!add_to_sel) { - curbone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL); - if (curbone->parent) curbone->parent->flag &= ~BONE_TIPSEL; + ED_armature_ebone_select_set(ebone_parent, true); + + changed = true; + } + } + + } + else { /* BONE_SELECT_CHILD */ + EditBone *ebone_iter, *ebone_child = NULL; + int pass; + + /* first pass, only connected bones (the logical direct child) */ + for (pass = 0; pass < 2 && (ebone_child == NULL); pass++) { + for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) { + /* possible we have multiple children, some invisible */ + if (EBONE_SELECTABLE(arm, ebone_iter)) { + if (ebone_iter->parent == ebone_active) { + if ((pass == 1) || (ebone_iter->flag & BONE_CONNECTED)) { + ebone_child = ebone_iter; + break; } - break; } } } } + + if (ebone_child) { + arm->act_edbone = ebone_child; + + if (!add_to_sel) { + ED_armature_ebone_select_set(ebone_active, false); + } + ED_armature_ebone_select_set(ebone_child, true); + + changed = true; + } } + if (changed == false) { + return OPERATOR_CANCELLED; + } + ED_armature_sync_selection(arm->edbo); WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 5d5a9bf363c..a4a21a0a225 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -518,71 +518,67 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) { Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); bArmature *arm = ob->data; - Bone *curbone, *pabone, *chbone; + bPoseChannel *pchan_act; int direction = RNA_enum_get(op->ptr, "direction"); const bool add_to_sel = RNA_boolean_get(op->ptr, "extend"); - bool found = false; + bool changed = false; - CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones) - { - curbone = pchan->bone; - - if ((curbone->flag & BONE_UNSELECTABLE) == 0) { - if (curbone == arm->act_bone) { - if (direction == BONE_SELECT_PARENT) { - if (pchan->parent == NULL) continue; - else pabone = pchan->parent->bone; - - if (PBONE_SELECTABLE(arm, pabone)) { - if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; - pabone->flag |= BONE_SELECTED; - arm->act_bone = pabone; - - found = 1; - break; - } + pchan_act = BKE_pose_channel_active(ob); + if (pchan_act == NULL) { + return OPERATOR_CANCELLED; + } + + if (direction == BONE_SELECT_PARENT) { + if (pchan_act->parent) { + Bone *bone_parent; + bone_parent = pchan_act->parent->bone; + + if (PBONE_SELECTABLE(arm, bone_parent)) { + if (!add_to_sel) { + pchan_act->bone->flag &= ~BONE_SELECTED; } - else { /* direction == BONE_SELECT_CHILD */ - /* the child member is only assigned to connected bones, see [#30340] */ -#if 0 - if (pchan->child == NULL) continue; - else chbone = pchan->child->bone; -#else - /* instead. find _any_ visible child bone, using the first one is a little arbitrary - campbell */ - chbone = pchan->child ? pchan->child->bone : NULL; - if (chbone == NULL) { - bPoseChannel *pchan_child; - - for (pchan_child = ob->pose->chanbase.first; pchan_child; pchan_child = pchan_child->next) { - /* possible we have multiple children, some invisible */ - if (PBONE_SELECTABLE(arm, pchan_child->bone)) { - if (pchan_child->parent == pchan) { - chbone = pchan_child->bone; - break; - } - } - } - } + bone_parent->flag |= BONE_SELECTED; + arm->act_bone = bone_parent; - if (chbone == NULL) continue; -#endif - - if (PBONE_SELECTABLE(arm, chbone)) { - if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; - chbone->flag |= BONE_SELECTED; - arm->act_bone = chbone; - - found = 1; - break; + changed = true; + } + } + } + else { /* direction == BONE_SELECT_CHILD */ + bPoseChannel *pchan_iter; + Bone *bone_child = NULL; + int pass; + + /* first pass, only connected bones (the logical direct child) */ + for (pass = 0; pass < 2 && (bone_child == NULL); pass++) { + for (pchan_iter = ob->pose->chanbase.first; pchan_iter; pchan_iter = pchan_iter->next) { + /* possible we have multiple children, some invisible */ + if (PBONE_SELECTABLE(arm, pchan_iter->bone)) { + if (pchan_iter->parent == pchan_act) { + if ((pass == 1) || (pchan_iter->bone->flag & BONE_CONNECTED)) { + bone_child = pchan_iter->bone; + break; + } } } } } + + if (bone_child) { + arm->act_bone = bone_child; + + if (!add_to_sel) { + pchan_act->bone->flag &= ~BONE_SELECTED; + } + bone_child->flag |= BONE_SELECTED; + + changed = true; + } } - CTX_DATA_END; - if (found == 0) + if (changed == false) { return OPERATOR_CANCELLED; + } /* updates */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); -- cgit v1.2.3 From cfdd27381c6730dc0d8d4bb51c132b29337b8af5 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 19 Mar 2015 17:36:59 +0100 Subject: GHash - code reorganization, performance enhancements, add a few missing utils to API. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch is the root of the GHash rework, all other diff will be based on it: Reduce average load from 3.0 to 0.75 ---------------------------------- This is the big performance booster part, e.g. makes tracing a dyntopo stroke between 25% and 30% faster. Not much to say about it, aside that it obviously increase memory footprint (about 25% - 30% too). Add optional shrinking ---------------------------------- I.e. ghashes/gsets can now shrink their buckets array when you remove enough entries. This remains optional and OFF by default. Add code to use masking instead of modulo ---------------------------------- Buckets indices are obtained from hashes by “reducing” the hash value into the valid bucket range. This can be done either by bit-masking, or using modulo operation. The former is quicker, but requires real hashes, while the later is slower (average 10% impact on ghash operations) but can also be used as a 'fake' hashing on raw values, like e.g. indices. In Blender currently not all ghash usages actually hash their keys, so we stick to modulo for now (masking is ifdef’ed out), we may however investigate the benefits of switching to masking with systematic very basic hashing later… Add various missing API helpers ---------------------------------- I.e. a way to deep-copy a ghash/gset, and a way to (re-)reserve entries (i.e. manually grow or shrink the ghash after its creation). Various code refactoring ---------------------------------- * Get rid of the 'hack' regarding ghash size when used as gset (it’s simpler and safer to have two structs defined here, and cast pointers as needed). * Various re-shuffle and factorization in low-level internal code. * Some work on hashing helpers, introducing some murmur2a-based hashing too. Thanks a bunch to Campbell for the extensive review work. :) Reviewers: sergey, campbellbarton Subscribers: psy-fi, lukastoenne Projects: #bf_blender Maniphest Tasks: T43766 Differential Revision: https://developer.blender.org/D1178 --- source/blender/blenlib/BLI_ghash.h | 53 +- source/blender/blenlib/BLI_hash_mm2a.h | 2 + source/blender/blenlib/intern/BLI_ghash.c | 777 +++++++++++++++++++------- source/blender/blenlib/intern/hash_mm2a.c | 44 +- source/blender/makesdna/intern/CMakeLists.txt | 1 + 5 files changed, 667 insertions(+), 210 deletions(-) diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index bf2b4126453..16d18ef1315 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -44,6 +44,8 @@ typedef unsigned int (*GHashHashFP) (const void *key); typedef bool (*GHashCmpFP) (const void *a, const void *b); typedef void (*GHashKeyFreeFP) (void *key); typedef void (*GHashValFreeFP) (void *val); +typedef void *(*GHashKeyCopyFP) (void *key); +typedef void *(*GHashValCopyFP) (void *val); typedef struct GHash GHash; @@ -54,7 +56,13 @@ typedef struct GHashIterator { } GHashIterator; enum { - GHASH_FLAG_ALLOW_DUPES = (1 << 0), /* only checked for in debug mode */ + GHASH_FLAG_ALLOW_DUPES = (1 << 0), /* Only checked for in debug mode */ + GHASH_FLAG_ALLOW_SHRINK = (1 << 1), /* Allow to shrink buckets' size. */ + +#ifdef GHASH_INTERNAL_API + /* Internal usage only */ + GHASH_FLAG_IS_GSET = (1 << 16), /* Whether the GHash is actually used as GSet (no value storage). */ +#endif }; /* *** */ @@ -62,7 +70,10 @@ enum { GHash *BLI_ghash_new_ex(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +GHash *BLI_ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, + GHashValCopyFP valcopyfp) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); +void BLI_ghash_reserve(GHash *gh, const unsigned int nentries_reserve); void BLI_ghash_insert(GHash *gh, void *key, void *val); bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void *BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT; @@ -127,23 +138,37 @@ unsigned int BLI_ghashutil_strhash_n(const char *key, size_t n); CHECK_TYPE_ANY(key, char *, const char *, const char * const), \ BLI_ghashutil_strhash_p(key)) unsigned int BLI_ghashutil_strhash_p(const void *key); +unsigned int BLI_ghashutil_strhash_p_murmur(const void *key); bool BLI_ghashutil_strcmp(const void *a, const void *b); #define BLI_ghashutil_inthash(key) ( \ CHECK_TYPE_ANY(&(key), int *, const int *), \ BLI_ghashutil_uinthash((unsigned int)key)) unsigned int BLI_ghashutil_uinthash(unsigned int key); +unsigned int BLI_ghashutil_inthash_p(const void *ptr); +unsigned int BLI_ghashutil_inthash_p_murmur(const void *ptr); +bool BLI_ghashutil_intcmp(const void *a, const void *b); + + +unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]); #define BLI_ghashutil_inthash_v4(key) ( \ CHECK_TYPE_ANY(key, int *, const int *), \ BLI_ghashutil_uinthash_v4((const unsigned int *)key)) -unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]); #define BLI_ghashutil_inthash_v4_p \ ((GSetHashFP)BLI_ghashutil_uinthash_v4) +#define BLI_ghashutil_uinthash_v4_p \ + ((GSetHashFP)BLI_ghashutil_uinthash_v4) +unsigned int BLI_ghashutil_uinthash_v4_murmur(const unsigned int key[4]); +#define BLI_ghashutil_inthash_v4_murmur(key) ( \ + CHECK_TYPE_ANY(key, int *, const int *), \ + BLI_ghashutil_uinthash_v4_murmur((const unsigned int *)key)) +#define BLI_ghashutil_inthash_v4_p_murmur \ + ((GSetHashFP)BLI_ghashutil_uinthash_v4_murmur) +#define BLI_ghashutil_uinthash_v4_p_murmur \ + ((GSetHashFP)BLI_ghashutil_uinthash_v4_murmur) bool BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b); #define BLI_ghashutil_inthash_v4_cmp \ BLI_ghashutil_uinthash_v4_cmp -unsigned int BLI_ghashutil_inthash_p(const void *ptr); -bool BLI_ghashutil_intcmp(const void *a, const void *b); /** \} */ @@ -178,6 +203,7 @@ typedef struct GSet GSet; typedef GHashHashFP GSetHashFP; typedef GHashCmpFP GSetCmpFP; typedef GHashKeyFreeFP GSetKeyFreeFP; +typedef GHashKeyCopyFP GSetKeyCopyFP; /* so we can cast but compiler sees as different */ typedef struct GSetIterator { @@ -191,6 +217,7 @@ typedef struct GSetIterator { GSet *BLI_gset_new_ex(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; GSet *BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +GSet *BLI_gset_copy(GSet *gs, GSetKeyCopyFP keycopyfp) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; int BLI_gset_size(GSet *gs) ATTR_WARN_UNUSED_RESULT; void BLI_gset_flag_set(GSet *gs, unsigned int flag); void BLI_gset_flag_clear(GSet *gs, unsigned int flag); @@ -202,7 +229,7 @@ bool BLI_gset_haskey(GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT; bool BLI_gset_remove(GSet *gs, void *key, GSetKeyFreeFP keyfreefp); void BLI_gset_clear_ex(GSet *gs, GSetKeyFreeFP keyfreefp, const unsigned int nentries_reserve); -void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp); +void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp); GSet *BLI_gset_ptr_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; @@ -229,10 +256,22 @@ BLI_INLINE bool BLI_gsetIterator_done(GSetIterator *gsi) { return BLI_ghashItera BLI_gsetIterator_done(&gs_iter_) == false; \ BLI_gsetIterator_step(&gs_iter_), i_++) -#ifdef DEBUG + +/* For testing, debugging only */ +#ifdef GHASH_INTERNAL_API +int BLI_ghash_buckets_size(GHash *gh); +int BLI_gset_buckets_size(GSet *gs); + +double BLI_ghash_calc_quality_ex( + GHash *gh, double *r_load, double *r_variance, + double *r_prop_empty_buckets, double *r_prop_overloaded_buckets, int *r_biggest_bucket); +double BLI_gset_calc_quality_ex( + GSet *gs, double *r_load, double *r_variance, + double *r_prop_empty_buckets, double *r_prop_overloaded_buckets, int *r_biggest_bucket); double BLI_ghash_calc_quality(GHash *gh); double BLI_gset_calc_quality(GSet *gs); -#endif +#endif /* GHASH_INTERNAL_API */ + #ifdef __cplusplus } diff --git a/source/blender/blenlib/BLI_hash_mm2a.h b/source/blender/blenlib/BLI_hash_mm2a.h index 007dec4f4d6..6beaf50ae8f 100644 --- a/source/blender/blenlib/BLI_hash_mm2a.h +++ b/source/blender/blenlib/BLI_hash_mm2a.h @@ -42,4 +42,6 @@ void BLI_hash_mm2a_add_int(BLI_HashMurmur2A *mm2, int data); uint32_t BLI_hash_mm2a_end(BLI_HashMurmur2A *mm2); +uint32_t BLI_hash_mm2(const unsigned char *data, size_t len, uint32_t seed); + #endif /* __BLI_HASH_MM2A_H__ */ diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 5360ea744a1..a2233c38270 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -36,17 +36,23 @@ #include #include +#include #include #include "MEM_guardedalloc.h" #include "BLI_sys_types.h" /* for intptr_t support */ #include "BLI_utildefines.h" +#include "BLI_hash_mm2a.h" #include "BLI_mempool.h" + +#define GHASH_INTERNAL_API #include "BLI_ghash.h" #include "BLI_strict_flags.h" +#define GHASH_USE_MODULO_BUCKETS +/* Also used by smallhash! */ const unsigned int hashsizes[] = { 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, @@ -54,24 +60,43 @@ const unsigned int hashsizes[] = { 268435459 }; -/* internal flag to ensure sets values aren't used */ -#ifndef NDEBUG -# define GHASH_FLAG_IS_SET (1 << 8) -# define IS_GHASH_ASSERT(gh) BLI_assert((gh->flag & GHASH_FLAG_IS_SET) == 0) -// # define IS_GSET_ASSERT(gs) BLI_assert((gs->flag & GHASH_FLAG_IS_SET) != 0) +#ifdef GHASH_USE_MODULO_BUCKETS +# define GHASH_MAX_SIZE 27 #else -# define IS_GHASH_ASSERT(gh) -// # define IS_GSET_ASSERT(eh) +# define GHASH_BUCKET_BIT_MIN 2 +# define GHASH_BUCKET_BIT_MAX 28 /* About 268M of buckets... */ #endif +/** + * \note Max load #GHASH_LIMIT_GROW used to be 3. (pre 2.74). + * Python uses 0.6666, tommyhaslib even goes down to 0.5. + * Reducing our from 3 to 0.75 gives huge speedup (about twice quicker pure GHash insertions/lookup, + * about 25% - 30% quicker 'dynamic-topology' stroke drawing e.g.). + * Min load #GHASH_LIMIT_SHRINK is a quarter of max load, to avoid resizing to quickly. + */ +#define GHASH_LIMIT_GROW(_nbkt) (((_nbkt) * 3) / 4) +#define GHASH_LIMIT_SHRINK(_nbkt) (((_nbkt) * 3) / 16) + /***/ +/* WARNING! Keep in sync with ugly _gh_Entry in header!!! */ typedef struct Entry { struct Entry *next; - void *key, *val; + void *key; } Entry; +typedef struct GHashEntry { + Entry e; + + void *val; +} GHashEntry; + +typedef Entry GSetEntry; + +#define GHASH_ENTRY_SIZE(_is_gset) \ + ((_is_gset) ? sizeof(GSetEntry) : sizeof(GHashEntry)) + struct GHash { GHashHashFP hashfp; GHashCmpFP cmpfp; @@ -79,11 +104,34 @@ struct GHash { Entry **buckets; struct BLI_mempool *entrypool; unsigned int nbuckets; + unsigned int limit_grow, limit_shrink; +#ifdef GHASH_USE_MODULO_BUCKETS + unsigned int cursize, size_min; +#else + unsigned int bucket_mask, bucket_bit, bucket_bit_min; +#endif + unsigned int nentries; - unsigned int cursize, flag; + unsigned int flag; }; +BLI_INLINE void ghash_entry_copy( + GHash *gh_dst, Entry *dst, GHash *gh_src, Entry *src, + GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp) +{ + dst->key = (keycopyfp) ? keycopyfp(src->key) : src->key; + + if ((gh_dst->flag & GHASH_FLAG_IS_GSET) == 0) { + if ((gh_src->flag & GHASH_FLAG_IS_GSET) == 0) { + ((GHashEntry *)dst)->val = (valcopyfp) ? valcopyfp(((GHashEntry *)src)->val) : ((GHashEntry *)src)->val; + } + else { + ((GHashEntry *)dst)->val = NULL; + } + } +} + /* -------------------------------------------------------------------- */ /* GHash API */ @@ -91,25 +139,37 @@ struct GHash { * \{ */ /** - * Get the hash for a key. + * Get the full hash for a key. */ BLI_INLINE unsigned int ghash_keyhash(GHash *gh, const void *key) { - return gh->hashfp(key) % gh->nbuckets; + return gh->hashfp(key); } /** - * Check if the number of items in the GHash is large enough to require more buckets. + * Get the full hash for an entry. */ -BLI_INLINE bool ghash_test_expand_buckets(const unsigned int nentries, const unsigned int nbuckets) +BLI_INLINE unsigned int ghash_entryhash(GHash *gh, const Entry *e) { - return (nentries > nbuckets * 3); + return gh->hashfp(e->key); } /** - * Expand buckets to the next size up. + * Get the bucket-hash for an already-computed full hash. */ -BLI_INLINE void ghash_resize_buckets(GHash *gh, const unsigned int nbuckets) +BLI_INLINE unsigned int ghash_bucket_index(GHash *gh, const unsigned int hash) +{ +#ifdef GHASH_USE_MODULO_BUCKETS + return hash % gh->nbuckets; +#else + return full_hash & gh->bucket_mask; +#endif +} + +/** + * Expand buckets to the next size up or down. + */ +static void ghash_buckets_resize(GHash *gh, const unsigned int nbuckets) { Entry **buckets_old = gh->buckets; Entry **buckets_new; @@ -117,49 +177,223 @@ BLI_INLINE void ghash_resize_buckets(GHash *gh, const unsigned int nbuckets) unsigned int i; Entry *e; - BLI_assert(gh->nbuckets != nbuckets); + BLI_assert((gh->nbuckets != nbuckets) || !gh->buckets); +// printf("%s: %d -> %d\n", __func__, nbuckets_old, nbuckets); gh->nbuckets = nbuckets; - buckets_new = (Entry **)MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets"); - - for (i = 0; i < nbuckets_old; i++) { - Entry *e_next; - for (e = buckets_old[i]; e; e = e_next) { - const unsigned hash = ghash_keyhash(gh, e->key); - e_next = e->next; - e->next = buckets_new[hash]; - buckets_new[hash] = e; +#ifdef GHASH_USE_MODULO_BUCKETS +#else + gh->bucket_mask = nbuckets - 1; +#endif + + buckets_new = (Entry **)MEM_callocN(sizeof(*gh->buckets) * gh->nbuckets, __func__); + + if (buckets_old) { + if (nbuckets > nbuckets_old) { + for (i = 0; i < nbuckets_old; i++) { + Entry *e_next; + for (e = buckets_old[i]; e; e = e_next) { + const unsigned hash = ghash_entryhash(gh, e); + const unsigned bucket_index = ghash_bucket_index(gh, hash); + e_next = e->next; + e->next = buckets_new[bucket_index]; + buckets_new[bucket_index] = e; + } + } + } + else { + for (i = 0; i < nbuckets_old; i++) { +#ifdef GHASH_USE_MODULO_BUCKETS + Entry *e_next; + for (e = buckets_old[i]; e; e = e_next) { + const unsigned hash = ghash_entryhash(gh, e); + const unsigned bucket_index = ghash_bucket_index(gh, hash); + e_next = e->next; + e->next = buckets_new[bucket_index]; + buckets_new[bucket_index] = e; + } +#else + /* No need to recompute hashes in this case, since our mask is just smaller, all items in old bucket i + * will go in same new bucket (i & new_mask)! */ + const unsigned bucket_index = ghash_bucket_index(gh, i); + BLI_assert(!buckets_old[i] || (bucket_index == ghash_bucket_index(gh, ghash_entryhash(gh, buckets_old[i])))); + for (e = buckets_old[i]; e && e->next; e = e->next); + if (e) { + e->next = buckets_new[bucket_index]; + buckets_new[bucket_index] = buckets_old[i]; + } +#endif + } } } gh->buckets = buckets_new; - MEM_freeN(buckets_old); + if (buckets_old) { + MEM_freeN(buckets_old); + } } /** - * Increase initial bucket size to match a reserved amount. + * Check if the number of items in the GHash is large enough to require more buckets, + * or small enough to require less buckets, and resize \a gh accordingly. */ -BLI_INLINE void ghash_buckets_reserve(GHash *gh, const unsigned int nentries_reserve) +static void ghash_buckets_expand( + GHash *gh, const unsigned int nentries, const bool user_defined) { - while (ghash_test_expand_buckets(nentries_reserve, gh->nbuckets)) { - gh->nbuckets = hashsizes[++gh->cursize]; + unsigned int new_nbuckets; + + if (LIKELY(gh->buckets && (nentries < gh->limit_grow))) { + return; + } + + new_nbuckets = gh->nbuckets; + +#ifdef GHASH_USE_MODULO_BUCKETS + while ((nentries > gh->limit_grow) && + (gh->cursize < GHASH_MAX_SIZE - 1)) + { + new_nbuckets = hashsizes[++gh->cursize]; + gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets); + } +#else + while ((nentries > gh->limit_grow) && + (gh->bucket_bit < GHASH_BUCKET_BIT_MAX)) + { + new_nbuckets = 1u << ++gh->bucket_bit; + gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets); + } +#endif + + if (user_defined) { +#ifdef GHASH_USE_MODULO_BUCKETS + gh->size_min = gh->cursize; +#else + gh->bucket_bit_min = gh->bucket_bit; +#endif } + + if ((new_nbuckets == gh->nbuckets) && gh->buckets) { + return; + } + + gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets); + gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets); + ghash_buckets_resize(gh, new_nbuckets); +} + +static void ghash_buckets_contract( + GHash *gh, const unsigned int nentries, const bool user_defined, const bool force_shrink) +{ + unsigned int new_nbuckets; + + if (!(force_shrink || (gh->flag & GHASH_FLAG_ALLOW_SHRINK))) { + return; + } + + if (LIKELY(gh->buckets && (nentries > gh->limit_shrink))) { + return; + } + + new_nbuckets = gh->nbuckets; + +#ifdef GHASH_USE_MODULO_BUCKETS + while ((nentries < gh->limit_shrink) && + (gh->cursize > gh->size_min)) + { + new_nbuckets = hashsizes[--gh->cursize]; + gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets); + } +#else + while ((nentries < gh->limit_shrink) && + (gh->bucket_bit > gh->bucket_bit_min)) + { + new_nbuckets = 1u << --gh->bucket_bit; + gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets); + } +#endif + + if (user_defined) { +#ifdef GHASH_USE_MODULO_BUCKETS + gh->size_min = gh->cursize; +#else + gh->bucket_bit_min = gh->bucket_bit; +#endif + } + + if ((new_nbuckets == gh->nbuckets) && gh->buckets) { + return; + } + + gh->limit_grow = GHASH_LIMIT_GROW(new_nbuckets); + gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets); + ghash_buckets_resize(gh, new_nbuckets); +} + +/** + * Clear and reset \a gh buckets, reserve again buckets for given number of entries. + */ +BLI_INLINE void ghash_buckets_reset(GHash *gh, const unsigned int nentries) +{ + MEM_SAFE_FREE(gh->buckets); + +#ifdef GHASH_USE_MODULO_BUCKETS + gh->cursize = 0; + gh->size_min = 0; + gh->nbuckets = hashsizes[gh->cursize]; +#else + gh->bucket_bit = GHASH_BUCKET_BIT_MIN; + gh->bucket_bit_min = GHASH_BUCKET_BIT_MIN; + gh->nbuckets = 1u << gh->bucket_bit; + gh->bucket_mask = gh->nbuckets - 1; +#endif + + gh->limit_grow = GHASH_LIMIT_GROW(gh->nbuckets); + gh->limit_shrink = GHASH_LIMIT_SHRINK(gh->nbuckets); + + gh->nentries = 0; + + ghash_buckets_expand(gh, nentries, (nentries != 0)); } /** * Internal lookup function. - * Takes a hash argument to avoid calling #ghash_keyhash multiple times. + * Takes hash and bucket_index arguments to avoid calling #ghash_keyhash and #ghash_bucket_index multiple times. */ -BLI_INLINE Entry *ghash_lookup_entry_ex(GHash *gh, const void *key, - const unsigned int hash) +BLI_INLINE Entry *ghash_lookup_entry_ex( + GHash *gh, const void *key, const unsigned int bucket_index) { Entry *e; + /* If we do not store GHash, not worth computing it for each entry here! + * Typically, comparison function will be quicker, and since it's needed in the end anyway... */ + for (e = gh->buckets[bucket_index]; e; e = e->next) { + if (UNLIKELY(gh->cmpfp(key, e->key) == false)) { + return e; + } + } + + return NULL; +} - for (e = gh->buckets[hash]; e; e = e->next) { +/** + * Internal lookup function, returns previous entry of target one too. + * Takes hash and bucket_index arguments to avoid calling #ghash_keyhash and #ghash_bucket_index multiple times. + * Useful when modifying buckets somehow (like removing an entry...). + */ +BLI_INLINE Entry *ghash_lookup_entry_prev_ex( + GHash *gh, const void *key, Entry **r_e_prev, const unsigned int bucket_index) +{ + Entry *e, *e_prev = NULL; + + /* If we do not store GHash, not worth computing it for each entry here! + * Typically, comparison function will be quicker, and since it's needed in the end anyway... */ + for (e = gh->buckets[bucket_index]; e; e_prev = e, e = e->next) { if (UNLIKELY(gh->cmpfp(key, e->key) == false)) { + *r_e_prev = e_prev; return e; } } + + *r_e_prev = NULL; return NULL; } @@ -169,105 +403,141 @@ BLI_INLINE Entry *ghash_lookup_entry_ex(GHash *gh, const void *key, BLI_INLINE Entry *ghash_lookup_entry(GHash *gh, const void *key) { const unsigned int hash = ghash_keyhash(gh, key); - return ghash_lookup_entry_ex(gh, key, hash); + const unsigned int bucket_index = ghash_bucket_index(gh, hash); + return ghash_lookup_entry_ex(gh, key, bucket_index); } static GHash *ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, - const unsigned int nentries_reserve, - const unsigned int entry_size) + const unsigned int nentries_reserve, const unsigned int flag) { GHash *gh = MEM_mallocN(sizeof(*gh), info); gh->hashfp = hashfp; gh->cmpfp = cmpfp; - gh->nbuckets = hashsizes[0]; /* gh->cursize */ - gh->nentries = 0; - gh->cursize = 0; - gh->flag = 0; + gh->buckets = NULL; + gh->flag = flag; - /* if we have reserved the number of elements that this hash will contain */ - if (nentries_reserve) { - ghash_buckets_reserve(gh, nentries_reserve); - } - - gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets"); - gh->entrypool = BLI_mempool_create(entry_size, 64, 64, BLI_MEMPOOL_NOP); + ghash_buckets_reset(gh, nentries_reserve); + gh->entrypool = BLI_mempool_create(GHASH_ENTRY_SIZE(flag & GHASH_FLAG_IS_GSET), 64, 64, BLI_MEMPOOL_NOP); return gh; } /** * Internal insert function. - * Takes a hash argument to avoid calling #ghash_keyhash multiple times. + * Takes hash and bucket_index arguments to avoid calling #ghash_keyhash and #ghash_bucket_index multiple times. */ -BLI_INLINE void ghash_insert_ex(GHash *gh, void *key, void *val, - unsigned int hash) +BLI_INLINE void ghash_insert_ex( + GHash *gh, void *key, void *val, const unsigned int bucket_index) { - Entry *e = (Entry *)BLI_mempool_alloc(gh->entrypool); + GHashEntry *e = BLI_mempool_alloc(gh->entrypool); + BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)); - IS_GHASH_ASSERT(gh); + BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); - e->next = gh->buckets[hash]; - e->key = key; + e->e.next = gh->buckets[bucket_index]; + e->e.key = key; e->val = val; - gh->buckets[hash] = e; + gh->buckets[bucket_index] = (Entry *)e; - if (UNLIKELY(ghash_test_expand_buckets(++gh->nentries, gh->nbuckets))) { - ghash_resize_buckets(gh, hashsizes[++gh->cursize]); - } + ghash_buckets_expand(gh, ++gh->nentries, false); } /** * Insert function that doesn't set the value (use for GSet) */ -BLI_INLINE void ghash_insert_ex_keyonly(GHash *gh, void *key, - unsigned int hash) +BLI_INLINE void ghash_insert_ex_keyonly( + GHash *gh, void *key, const unsigned int bucket_index) { - Entry *e = (Entry *)BLI_mempool_alloc(gh->entrypool); + GSetEntry *e = BLI_mempool_alloc(gh->entrypool); + BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)); - e->next = gh->buckets[hash]; + BLI_assert((gh->flag & GHASH_FLAG_IS_GSET) != 0); + + e->next = gh->buckets[bucket_index]; e->key = key; - /* intentionally leave value unset */ - gh->buckets[hash] = e; + gh->buckets[bucket_index] = (Entry *)e; - if (UNLIKELY(ghash_test_expand_buckets(++gh->nentries, gh->nbuckets))) { - ghash_resize_buckets(gh, hashsizes[++gh->cursize]); - } + ghash_buckets_expand(gh, ++gh->nentries, false); } BLI_INLINE void ghash_insert(GHash *gh, void *key, void *val) { const unsigned int hash = ghash_keyhash(gh, key); - ghash_insert_ex(gh, key, val, hash); + const unsigned int bucket_index = ghash_bucket_index(gh, hash); + + ghash_insert_ex(gh, key, val, bucket_index); +} + +BLI_INLINE bool ghash_insert_safe( + GHash *gh, void *key, void *val, const bool override, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) +{ + const unsigned int hash = ghash_keyhash(gh, key); + const unsigned int bucket_index = ghash_bucket_index(gh, hash); + GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index); + + BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); + + if (e) { + if (override) { + if (keyfreefp) keyfreefp(e->e.key); + if (valfreefp) valfreefp(e->val); + e->e.key = key; + e->val = val; + } + return false; + } + else { + ghash_insert_ex(gh, key, val, bucket_index); + return true; + } +} + +BLI_INLINE bool ghash_insert_safe_keyonly(GHash *gh, void *key, const bool override, GHashKeyFreeFP keyfreefp) +{ + const unsigned int hash = ghash_keyhash(gh, key); + const unsigned int bucket_index = ghash_bucket_index(gh, hash); + GSetEntry *e = ghash_lookup_entry_ex(gh, key, bucket_index); + + BLI_assert((gh->flag & GHASH_FLAG_IS_GSET) != 0); + + if (e) { + if (override) { + if (keyfreefp) keyfreefp(e->key); + e->key = key; + } + return false; + } + else { + ghash_insert_ex_keyonly(gh, key, bucket_index); + return true; + } } /** * Remove the entry and return it, caller must free from gh->entrypool. */ -static Entry *ghash_remove_ex(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, - unsigned int hash) +static Entry *ghash_remove_ex( + GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, + const unsigned int bucket_index) { - Entry *e; - Entry *e_prev = NULL; + Entry *e_prev; + Entry *e = ghash_lookup_entry_prev_ex(gh, key, &e_prev, bucket_index); - for (e = gh->buckets[hash]; e; e = e->next) { - if (UNLIKELY(gh->cmpfp(key, e->key) == false)) { - Entry *e_next = e->next; + BLI_assert(!valfreefp|| !(gh->flag & GHASH_FLAG_IS_GSET)); - if (keyfreefp) keyfreefp(e->key); - if (valfreefp) valfreefp(e->val); + if (e) { + if (keyfreefp) keyfreefp(e->key); + if (valfreefp) valfreefp(((GHashEntry *)e)->val); - if (e_prev) e_prev->next = e_next; - else gh->buckets[hash] = e_next; + if (e_prev) e_prev->next = e->next; + else gh->buckets[bucket_index] = e->next; - gh->nentries--; - return e; - } - e_prev = e; + ghash_buckets_contract(gh, --gh->nentries, false, false); } - return NULL; + return e; } /** @@ -278,20 +548,56 @@ static void ghash_free_cb(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP va unsigned int i; BLI_assert(keyfreefp || valfreefp); + BLI_assert(!valfreefp|| !(gh->flag & GHASH_FLAG_IS_GSET)); for (i = 0; i < gh->nbuckets; i++) { Entry *e; - for (e = gh->buckets[i]; e; ) { - Entry *e_next = e->next; - + for (e = gh->buckets[i]; e; e = e->next) { if (keyfreefp) keyfreefp(e->key); - if (valfreefp) valfreefp(e->val); + if (valfreefp) valfreefp(((GHashEntry *)e)->val); + } + } +} + +/** + * Copy the GHash. + */ +static GHash *ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp) +{ + GHash *gh_new; + unsigned int i; + /* This allows us to be sure to get the same number of buckets in gh_new as in ghash. */ + const unsigned int reserve_nentries_new = MAX2(GHASH_LIMIT_GROW(gh->nbuckets) - 1, gh->nentries); + + BLI_assert(!valcopyfp || !(gh->flag & GHASH_FLAG_IS_GSET)); + + gh_new = ghash_new(gh->hashfp, gh->cmpfp, __func__, 0, gh->flag); + ghash_buckets_expand(gh_new, reserve_nentries_new, false); + + BLI_assert(gh_new->nbuckets == gh->nbuckets); + + for (i = 0; i < gh->nbuckets; i++) { + Entry *e; + + for (e = gh->buckets[i]; e; e = e->next) { + Entry *e_new = BLI_mempool_alloc(gh_new->entrypool); + ghash_entry_copy(gh_new, e_new, gh, e, keycopyfp, valcopyfp); - e = e_next; + /* Warning! + * This means entries in buckets in new copy will be in reversed order! + * This shall not be an issue though, since order should never be assumed in ghash. */ + + /* Note: We can use 'i' here, since we are sure that 'gh' and 'gh_new' have the same number of buckets! */ + e_new->next = gh_new->buckets[i]; + gh_new->buckets[i] = e_new; } } + gh_new->nentries = gh->nentries; + + return gh_new; } + /** \} */ @@ -311,9 +617,7 @@ static void ghash_free_cb(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP va GHash *BLI_ghash_new_ex(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, const unsigned int nentries_reserve) { - return ghash_new(hashfp, cmpfp, info, - nentries_reserve, - (unsigned int)sizeof(Entry)); + return ghash_new(hashfp, cmpfp, info, nentries_reserve, 0); } /** @@ -324,6 +628,23 @@ GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) return BLI_ghash_new_ex(hashfp, cmpfp, info, 0); } +/** + * Copy given GHash. Keys and values are also copied if relevant callback is provided, else pointers remain the same. + */ +GHash *BLI_ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp) +{ + return ghash_copy(gh, keycopyfp, valcopyfp); +} + +/** + * Reverve given ammount of entries (resize \a gh accordingly if needed). + */ +void BLI_ghash_reserve(GHash *gh, const unsigned int nentries_reserve) +{ + ghash_buckets_expand(gh, nentries_reserve, true); + ghash_buckets_contract(gh, nentries_reserve, true, false); +} + /** * \return size of the GHash. */ @@ -353,19 +674,7 @@ void BLI_ghash_insert(GHash *gh, void *key, void *val) */ bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) { - const unsigned int hash = ghash_keyhash(gh, key); - Entry *e = ghash_lookup_entry_ex(gh, key, hash); - if (e) { - if (keyfreefp) keyfreefp(e->key); - if (valfreefp) valfreefp(e->val); - e->key = key; - e->val = val; - return false; - } - else { - ghash_insert_ex(gh, key, val, hash); - return true; - } + return ghash_insert_safe(gh, key, val, true, keyfreefp, valfreefp); } /** @@ -379,8 +688,8 @@ bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreef */ void *BLI_ghash_lookup(GHash *gh, const void *key) { - Entry *e = ghash_lookup_entry(gh, key); - IS_GHASH_ASSERT(gh); + GHashEntry *e = (GHashEntry *)ghash_lookup_entry(gh, key); + BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); return e ? e->val : NULL; } @@ -389,8 +698,8 @@ void *BLI_ghash_lookup(GHash *gh, const void *key) */ void *BLI_ghash_lookup_default(GHash *gh, const void *key, void *val_default) { - Entry *e = ghash_lookup_entry(gh, key); - IS_GHASH_ASSERT(gh); + GHashEntry *e = (GHashEntry *)ghash_lookup_entry(gh, key); + BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); return e ? e->val : val_default; } @@ -406,8 +715,8 @@ void *BLI_ghash_lookup_default(GHash *gh, const void *key, void *val_default) */ void **BLI_ghash_lookup_p(GHash *gh, const void *key) { - Entry *e = ghash_lookup_entry(gh, key); - IS_GHASH_ASSERT(gh); + GHashEntry *e = (GHashEntry *)ghash_lookup_entry(gh, key); + BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); return e ? &e->val : NULL; } @@ -422,7 +731,8 @@ void **BLI_ghash_lookup_p(GHash *gh, const void *key) bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) { const unsigned int hash = ghash_keyhash(gh, key); - Entry *e = ghash_remove_ex(gh, key, keyfreefp, valfreefp, hash); + const unsigned int bucket_index = ghash_bucket_index(gh, hash); + Entry *e = ghash_remove_ex(gh, key, keyfreefp, valfreefp, bucket_index); if (e) { BLI_mempool_free(gh->entrypool, e); return true; @@ -444,8 +754,9 @@ bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFr void *BLI_ghash_popkey(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) { const unsigned int hash = ghash_keyhash(gh, key); - Entry *e = ghash_remove_ex(gh, key, keyfreefp, NULL, hash); - IS_GHASH_ASSERT(gh); + const unsigned int bucket_index = ghash_bucket_index(gh, hash); + GHashEntry *e = (GHashEntry *)ghash_remove_ex(gh, key, keyfreefp, NULL, bucket_index); + BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); if (e) { void *val = e->val; BLI_mempool_free(gh->entrypool, e); @@ -477,17 +788,7 @@ void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valf if (keyfreefp || valfreefp) ghash_free_cb(gh, keyfreefp, valfreefp); - gh->nbuckets = hashsizes[0]; /* gh->cursize */ - gh->nentries = 0; - gh->cursize = 0; - - if (nentries_reserve) { - ghash_buckets_reserve(gh, nentries_reserve); - } - - MEM_freeN(gh->buckets); - gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets"); - + ghash_buckets_reset(gh, nentries_reserve); BLI_mempool_clear_ex(gh->entrypool, nentries_reserve ? (int)nentries_reserve : -1); } @@ -701,6 +1002,10 @@ unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]) hash += key[3]; return hash; } +unsigned int BLI_ghashutil_uinthash_v4_murmur(const unsigned int key[4]) +{ + return BLI_hash_mm2((const unsigned char *)key, sizeof(key), 0); +} bool BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b) { @@ -733,6 +1038,13 @@ unsigned int BLI_ghashutil_inthash_p(const void *ptr) return (unsigned int)(key & 0xffffffff); } +unsigned int BLI_ghashutil_inthash_p_murmur(const void *ptr) +{ + uintptr_t key = (uintptr_t)ptr; + + return BLI_hash_mm2((const unsigned char *)&key, sizeof(key), 0); +} + bool BLI_ghashutil_intcmp(const void *a, const void *b) { return (a != b); @@ -769,9 +1081,15 @@ unsigned int BLI_ghashutil_strhash_p(const void *ptr) return h; } +unsigned int BLI_ghashutil_strhash_p_murmur(const void *ptr) +{ + const unsigned char *key = ptr; + + return BLI_hash_mm2(key, strlen((const char *)key) + 1, 0); +} bool BLI_ghashutil_strcmp(const void *a, const void *b) { - return (!STREQ(a, b)); + return (a == b) ? false : !STREQ(a, b); } GHashPair *BLI_ghashutil_pairalloc(const void *first, const void *second) @@ -809,44 +1127,36 @@ void BLI_ghashutil_pairfree(void *ptr) /** \name Convenience GHash Creation Functions * \{ */ -GHash *BLI_ghash_ptr_new_ex(const char *info, - const unsigned int nentries_reserve) +GHash *BLI_ghash_ptr_new_ex(const char *info, const unsigned int nentries_reserve) { - return BLI_ghash_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, - nentries_reserve); + return BLI_ghash_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve); } GHash *BLI_ghash_ptr_new(const char *info) { return BLI_ghash_ptr_new_ex(info, 0); } -GHash *BLI_ghash_str_new_ex(const char *info, - const unsigned int nentries_reserve) +GHash *BLI_ghash_str_new_ex(const char *info, const unsigned int nentries_reserve) { - return BLI_ghash_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, - nentries_reserve); + return BLI_ghash_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, nentries_reserve); } GHash *BLI_ghash_str_new(const char *info) { return BLI_ghash_str_new_ex(info, 0); } -GHash *BLI_ghash_int_new_ex(const char *info, - const unsigned int nentries_reserve) +GHash *BLI_ghash_int_new_ex(const char *info, const unsigned int nentries_reserve) { - return BLI_ghash_new_ex(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, info, - nentries_reserve); + return BLI_ghash_new_ex(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, info, nentries_reserve); } GHash *BLI_ghash_int_new(const char *info) { return BLI_ghash_int_new_ex(info, 0); } -GHash *BLI_ghash_pair_new_ex(const char *info, - const unsigned int nentries_reserve) +GHash *BLI_ghash_pair_new_ex(const char *info, const unsigned int nentries_reserve) { - return BLI_ghash_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, - nentries_reserve); + return BLI_ghash_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve); } GHash *BLI_ghash_pair_new(const char *info) { @@ -861,21 +1171,12 @@ GHash *BLI_ghash_pair_new(const char *info) /* Use ghash API to give 'set' functionality */ -/* TODO: typical set functions - * isdisjoint/issubset/issuperset/union/intersection/difference etc */ - /** \name GSet Functions * \{ */ GSet *BLI_gset_new_ex(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info, const unsigned int nentries_reserve) { - GSet *gs = (GSet *)ghash_new(hashfp, cmpfp, info, - nentries_reserve, - sizeof(Entry) - sizeof(void *)); -#ifndef NDEBUG - ((GHash *)gs)->flag |= GHASH_FLAG_IS_SET; -#endif - return gs; + return (GSet *)ghash_new(hashfp, cmpfp, info, nentries_reserve, GHASH_FLAG_IS_GSET); } GSet *BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) @@ -883,6 +1184,14 @@ GSet *BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) return BLI_gset_new_ex(hashfp, cmpfp, info, 0); } +/** + * Copy given GSet. Keys are also copied if callback is provided, else pointers remain the same. + */ +GSet *BLI_gset_copy(GSet *gs, GHashKeyCopyFP keycopyfp) +{ + return (GSet *)ghash_copy((GHash *)gs, keycopyfp, NULL); +} + int BLI_gset_size(GSet *gs) { return (int)((GHash *)gs)->nentries; @@ -895,7 +1204,8 @@ int BLI_gset_size(GSet *gs) void BLI_gset_insert(GSet *gs, void *key) { const unsigned int hash = ghash_keyhash((GHash *)gs, key); - ghash_insert_ex_keyonly((GHash *)gs, key, hash); + const unsigned int bucket_index = ghash_bucket_index((GHash *)gs, hash); + ghash_insert_ex_keyonly((GHash *)gs, key, bucket_index); } /** @@ -906,15 +1216,7 @@ void BLI_gset_insert(GSet *gs, void *key) */ bool BLI_gset_add(GSet *gs, void *key) { - const unsigned int hash = ghash_keyhash((GHash *)gs, key); - Entry *e = ghash_lookup_entry_ex((GHash *)gs, key, hash); - if (e) { - return false; - } - else { - ghash_insert_ex_keyonly((GHash *)gs, key, hash); - return true; - } + return ghash_insert_safe_keyonly((GHash *)gs, key, false, NULL); } /** @@ -925,17 +1227,7 @@ bool BLI_gset_add(GSet *gs, void *key) */ bool BLI_gset_reinsert(GSet *gs, void *key, GSetKeyFreeFP keyfreefp) { - const unsigned int hash = ghash_keyhash((GHash *)gs, key); - Entry *e = ghash_lookup_entry_ex((GHash *)gs, key, hash); - if (e) { - if (keyfreefp) keyfreefp(e->key); - e->key = key; - return false; - } - else { - ghash_insert_ex_keyonly((GHash *)gs, key, hash); - return true; - } + return ghash_insert_safe_keyonly((GHash *)gs, key, true, keyfreefp); } bool BLI_gset_remove(GSet *gs, void *key, GSetKeyFreeFP keyfreefp) @@ -982,22 +1274,18 @@ void BLI_gset_flag_clear(GSet *gs, unsigned int flag) /** \name Convenience GSet Creation Functions * \{ */ -GSet *BLI_gset_ptr_new_ex(const char *info, - const unsigned int nentries_reserve) +GSet *BLI_gset_ptr_new_ex(const char *info, const unsigned int nentries_reserve) { - return BLI_gset_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, - nentries_reserve); + return BLI_gset_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve); } GSet *BLI_gset_ptr_new(const char *info) { return BLI_gset_ptr_new_ex(info, 0); } -GSet *BLI_gset_pair_new_ex(const char *info, - const unsigned int nentries_reserve) +GSet *BLI_gset_pair_new_ex(const char *info, const unsigned int nentries_reserve) { - return BLI_gset_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, - nentries_reserve); + return BLI_gset_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve); } GSet *BLI_gset_pair_new(const char *info) { @@ -1009,37 +1297,126 @@ GSet *BLI_gset_pair_new(const char *info) /** \name Debugging & Introspection * \{ */ -#ifdef DEBUG + +#include "BLI_math.h" /** - * Measure how well the hash function performs - * (1.0 is approx as good as random distribution). + * \return number of buckets in the GHash. + */ +int BLI_ghash_buckets_size(GHash *gh) +{ + return (int)gh->nbuckets; +} +int BLI_gset_buckets_size(GSet *gs) +{ + return BLI_ghash_buckets_size((GHash *)gs); +} + +/** + * Measure how well the hash function performs (1.0 is approx as good as random distribution), + * and return a few other stats like load, variance of the distribution of the entries in the buckets, etc. * * Smaller is better! */ -double BLI_ghash_calc_quality(GHash *gh) +double BLI_ghash_calc_quality_ex( + GHash *gh, double *r_load, double *r_variance, + double *r_prop_empty_buckets, double *r_prop_overloaded_buckets, int *r_biggest_bucket) { - uint64_t sum = 0; + double mean; unsigned int i; - if (gh->nentries == 0) - return -1.0; + if (gh->nentries == 0) { + if (r_load) { + *r_load = 0.0; + } + if (r_variance) { + *r_variance = 0.0; + } + if (r_prop_empty_buckets) { + *r_prop_empty_buckets = 1.0; + } + if (r_prop_overloaded_buckets) { + *r_prop_overloaded_buckets = 0.0; + } + if (r_biggest_bucket) { + *r_biggest_bucket = 0; + } + + return 0.0; + } - for (i = 0; i < gh->nbuckets; i++) { - uint64_t count = 0; - Entry *e; - for (e = gh->buckets[i]; e; e = e->next) { - count += 1; + mean = (double)gh->nentries / (double)gh->nbuckets; + if (r_load) { + *r_load = mean; + } + if (r_biggest_bucket) { + *r_biggest_bucket = 0; + } + + if (r_variance) { + /* We already know our mean (i.e. load factor), easy to compute variance. + * See http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Two-pass_algorithm + */ + double sum = 0.0; + for (i = 0; i < gh->nbuckets; i++) { + int count = 0; + Entry *e; + for (e = gh->buckets[i]; e; e = e->next) { + count++; + } + sum += ((double)count - mean) * ((double)count - mean); } - sum += count * (count + 1); + *r_variance = sum / (double)(gh->nbuckets - 1); } - return ((double)sum * (double)gh->nbuckets / - ((double)gh->nentries * (gh->nentries + 2 * gh->nbuckets - 1))); + + { + uint64_t sum = 0; + uint64_t overloaded_buckets_threshold = (uint64_t)max_ii(GHASH_LIMIT_GROW(1), 1); + uint64_t sum_overloaded = 0; + uint64_t sum_empty = 0; + + for (i = 0; i < gh->nbuckets; i++) { + uint64_t count = 0; + Entry *e; + for (e = gh->buckets[i]; e; e = e->next) { + count++; + } + if (r_biggest_bucket) { + *r_biggest_bucket = max_ii(*r_biggest_bucket, (int)count); + } + if (r_prop_overloaded_buckets && (count > overloaded_buckets_threshold)) { + sum_overloaded++; + } + if (r_prop_empty_buckets && !count) { + sum_empty++; + } + sum += count * (count + 1); + } + if (r_prop_overloaded_buckets) { + *r_prop_overloaded_buckets = (double)sum_overloaded / (double)gh->nbuckets; + } + if (r_prop_empty_buckets) { + *r_prop_empty_buckets = (double)sum_empty / (double)gh->nbuckets; + } + return ((double)sum * (double)gh->nbuckets / + ((double)gh->nentries * (gh->nentries + 2 * gh->nbuckets - 1))); + } +} +double BLI_gset_calc_quality_ex( + GSet *gs, double *r_load, double *r_variance, + double *r_prop_empty_buckets, double *r_prop_overloaded_buckets, int *r_biggest_bucket) +{ + return BLI_ghash_calc_quality_ex((GHash *)gs, r_load, r_variance, + r_prop_empty_buckets, r_prop_overloaded_buckets, r_biggest_bucket); +} + +double BLI_ghash_calc_quality(GHash *gh) +{ + return BLI_ghash_calc_quality_ex(gh, NULL, NULL, NULL, NULL, NULL); } double BLI_gset_calc_quality(GSet *gs) { - return BLI_ghash_calc_quality((GHash *)gs); + return BLI_ghash_calc_quality_ex((GHash *)gs, NULL, NULL, NULL, NULL, NULL); } -#endif /** \} */ diff --git a/source/blender/blenlib/intern/hash_mm2a.c b/source/blender/blenlib/intern/hash_mm2a.c index bae098ae96b..87ba542e147 100644 --- a/source/blender/blenlib/intern/hash_mm2a.c +++ b/source/blender/blenlib/intern/hash_mm2a.c @@ -49,6 +49,13 @@ (h) = ((h) * MM2A_M) ^ (k); \ } (void)0 +#define MM2A_MIX_FINALIZE(h) \ +{ \ + (h) ^= (h) >> 13; \ + (h) *= MM2A_M; \ + (h) ^= (h) >> 15; \ +} (void)0 + static void mm2a_mix_tail(BLI_HashMurmur2A *mm2, const unsigned char **data, size_t *len) { while (*len && ((*len < 4) || mm2->count)) { @@ -99,9 +106,40 @@ uint32_t BLI_hash_mm2a_end(BLI_HashMurmur2A *mm2) MM2A_MIX(mm2->hash, mm2->tail); MM2A_MIX(mm2->hash, mm2->size); - mm2->hash ^= mm2->hash >> 13; - mm2->hash *= MM2A_M; - mm2->hash ^= mm2->hash >> 15; + MM2A_MIX_FINALIZE(mm2->hash); return mm2->hash; } + +/* Non-incremental version, quicker for small keys. */ +uint32_t BLI_hash_mm2(const unsigned char *data, size_t len, uint32_t seed) +{ + /* Initialize the hash to a 'random' value */ + uint32_t h = seed ^ len; + + /* Mix 4 bytes at a time into the hash */ + for (; len >= 4; data += 4, len -= 4) { + uint32_t k = *(uint32_t *)data; + + MM2A_MIX(h, k); + } + + /* Handle the last few bytes of the input array */ + switch (len) { + case 3: + h ^= data[2] << 16; + /* fall through */ + case 2: + h ^= data[1] << 8; + /* fall through */ + case 1: + h ^= data[0]; + h *= MM2A_M; + }; + + /* Do a few final mixes of the hash to ensure the last few bytes are well-incorporated. */ + MM2A_MIX_FINALIZE(h); + + return h; +} + diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt index 317141b14e3..08d2f93866a 100644 --- a/source/blender/makesdna/intern/CMakeLists.txt +++ b/source/blender/makesdna/intern/CMakeLists.txt @@ -97,6 +97,7 @@ set(SRC ../../blenlib/intern/BLI_mempool.c ../../blenlib/intern/listbase.c ../../blenlib/intern/BLI_ghash.c + ../../blenlib/intern/hash_mm2a.c ) blender_add_lib(bf_dna_blenlib "${SRC}" "${INC}" "${INC_SYS}") -- cgit v1.2.3 From 2941b4ad9bd7ee876575b6b4bbe628a9dfaedaa5 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 19 Mar 2015 18:06:15 +0100 Subject: BLI GHash: add some basic gtests. We could likely add much more, but those already covers basic behavior and should be able to catch most errors when editing this code. Also added some performances tests as well (timing ghash insert/lookup under heavy loads, for different kinds of keys). --- tests/gtests/blenlib/BLI_ghash_performance_test.cc | 415 ++++++++++++++ tests/gtests/blenlib/BLI_ghash_test.cc | 158 ++++++ tests/gtests/blenlib/BLI_ressource_strings.h | 602 +++++++++++++++++++++ tests/gtests/blenlib/CMakeLists.txt | 3 + 4 files changed, 1178 insertions(+) create mode 100644 tests/gtests/blenlib/BLI_ghash_performance_test.cc create mode 100644 tests/gtests/blenlib/BLI_ghash_test.cc create mode 100644 tests/gtests/blenlib/BLI_ressource_strings.h diff --git a/tests/gtests/blenlib/BLI_ghash_performance_test.cc b/tests/gtests/blenlib/BLI_ghash_performance_test.cc new file mode 100644 index 00000000000..ef17349268c --- /dev/null +++ b/tests/gtests/blenlib/BLI_ghash_performance_test.cc @@ -0,0 +1,415 @@ +/* Apache License, Version 2.0 */ + +#include "testing/testing.h" +#include "BLI_ressource_strings.h" + +#define GHASH_INTERNAL_API + +extern "C" { +#include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" +#include "BLI_ghash.h" +#include "BLI_rand.h" +#include "BLI_string.h" +#include "PIL_time_utildefines.h" +} + +/* Using http://corpora.uni-leipzig.de/downloads/eng_wikipedia_2010_1M-text.tar.gz + * (1 million of words, about 122MB of text) from http://corpora.informatik.uni-leipzig.de/download.html */ +//#define TEXT_CORPUS_PATH "/path/to/Téléchargements/eng_wikipedia_2010_1M-text/eng_wikipedia_2010_1M-sentences.txt" + +/* Resizing the hash has a huge cost over global filling operation! */ +//#define GHASH_RESERVE + +#define PRINTF_GHASH_STATS(_gh) \ +{ \ + double q, lf, var, pempty, poverloaded; \ + int bigb; \ + q = BLI_ghash_calc_quality_ex((_gh), &lf, &var, &pempty, &poverloaded, &bigb); \ + printf("GHash stats (%d entries):\n\t" \ + "Quality (the lower the better): %f\n\tVariance (the lower the better): %f\n\tLoad: %f\n\t" \ + "Empty buckets: %.2f%%\n\tOverloaded buckets: %.2f%% (biggest bucket: %d)\n", \ + BLI_ghash_size(_gh), q, var, lf, pempty * 100.0, poverloaded * 100.0, bigb); \ +} void (0) + + +/* Str: whole text, lines and words from a 'corpus' text. */ + +static void str_ghash_tests(GHash *ghash, const char *id) +{ + printf("\n========== STARTING %s ==========\n", id); + +#ifdef TEXT_CORPUS_PATH + size_t sz = 0; + char *data; + { + struct stat st; + if (stat(TEXT_CORPUS_PATH, &st) == 0) + sz = st.st_size; + } + if (sz != 0) { + FILE *f = fopen(TEXT_CORPUS_PATH, "r"); + + data = (char *)MEM_mallocN(sz + 1, __func__); + if (fread(data, sizeof(*data), sz, f) != sz) { + printf("ERROR in reading file %s!", TEXT_CORPUS_PATH); + MEM_freeN(data); + data = BLI_strdup(words10k); + } + data[sz] = '\0'; + fclose(f); + } + else { + data = BLI_strdup(words10k); + } +#else + char *data = BLI_strdup(words10k); +#endif + char *data_p = BLI_strdup(data); + char *data_w = BLI_strdup(data); + char *data_bis = BLI_strdup(data); + + { + char *p, *w, *c_p, *c_w; + + TIMEIT_START(string_insert); + +#ifdef GHASH_RESERVE + BLI_ghash_reserve(ghash, strlen(data) / 32); /* rough estimation... */ +#endif + + BLI_ghash_insert(ghash, data, SET_INT_IN_POINTER(data[0])); + + for (p = c_p = data_p, w = c_w = data_w; *c_w; c_w++, c_p++) { + if (*c_p == '.') { + *c_p = *c_w = '\0'; + if (!BLI_ghash_haskey(ghash, p)) { + BLI_ghash_insert(ghash, p, SET_INT_IN_POINTER(p[0])); + } + if (!BLI_ghash_haskey(ghash, w)) { + BLI_ghash_insert(ghash, w, SET_INT_IN_POINTER(w[0])); + } + p = c_p + 1; + w = c_w + 1; + } + else if (*c_w == ' ') { + *c_w = '\0'; + if (!BLI_ghash_haskey(ghash, w)) { + BLI_ghash_insert(ghash, w, SET_INT_IN_POINTER(w[0])); + } + w = c_w + 1; + } + } + + TIMEIT_END(string_insert); + } + + PRINTF_GHASH_STATS(ghash); + + { + char *p, *w, *c; + void *v; + + TIMEIT_START(string_lookup); + + v = BLI_ghash_lookup(ghash, data_bis); + EXPECT_EQ(data_bis[0], GET_INT_FROM_POINTER(v)); + + for (p = w = c = data_bis; *c; c++) { + if (*c == '.') { + *c = '\0'; + v = BLI_ghash_lookup(ghash, w); + EXPECT_EQ(w[0], GET_INT_FROM_POINTER(v)); + v = BLI_ghash_lookup(ghash, p); + EXPECT_EQ(p[0], GET_INT_FROM_POINTER(v)); + p = w = c + 1; + } + else if (*c == ' ') { + *c = '\0'; + v = BLI_ghash_lookup(ghash, w); + EXPECT_EQ(w[0], GET_INT_FROM_POINTER(v)); + w = c + 1; + } + } + + TIMEIT_END(string_lookup); + } + + BLI_ghash_free(ghash, NULL, NULL); + MEM_freeN(data); + MEM_freeN(data_p); + MEM_freeN(data_w); + MEM_freeN(data_bis); + + printf("========== ENDED %s ==========\n\n", id); +} + +TEST(ghash, TextGHash) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, __func__); + + str_ghash_tests(ghash, "StrGHash - GHash"); +} + +TEST(ghash, TextMurmur2a) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_strhash_p_murmur, BLI_ghashutil_strcmp, __func__); + + str_ghash_tests(ghash, "StrGHash - Murmur"); +} + + +/* Int: uniform 100M first integers. */ + +static void int_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr) +{ + printf("\n========== STARTING %s ==========\n", id); + + { + unsigned int i = nbr; + + TIMEIT_START(int_insert); + +#ifdef GHASH_RESERVE + BLI_ghash_reserve(ghash, nbr); +#endif + + while (i--) { + BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(i), SET_UINT_IN_POINTER(i)); + } + + TIMEIT_END(int_insert); + } + + PRINTF_GHASH_STATS(ghash); + + { + unsigned int i = nbr; + + TIMEIT_START(int_lookup); + + while (i--) { + void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(i)); + EXPECT_EQ(i, GET_UINT_FROM_POINTER(v)); + } + + TIMEIT_END(int_lookup); + } + + BLI_ghash_free(ghash, NULL, NULL); + + printf("========== ENDED %s ==========\n\n", id); +} + +TEST(ghash, IntGHash12000) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); + + int_ghash_tests(ghash, "IntGHash - GHash - 12000", 12000); +} + +TEST(ghash, IntGHash100000000) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); + + int_ghash_tests(ghash, "IntGHash - GHash - 100000000", 100000000); +} + +TEST(ghash, IntMurmur2a12000) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__); + + int_ghash_tests(ghash, "IntGHash - Murmur - 12000", 12000); +} + +TEST(ghash, IntMurmur2a100000000) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__); + + int_ghash_tests(ghash, "IntGHash - Murmur - 100000000", 100000000); +} + + +/* Int: random 50M integers. */ + +static void randint_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr) +{ + printf("\n========== STARTING %s ==========\n", id); + + unsigned int *data = (unsigned int *)MEM_mallocN(sizeof(*data) * (size_t)nbr, __func__); + unsigned int *dt; + unsigned int i; + + { + RNG *rng = BLI_rng_new(0); + for (i = nbr, dt = data; i--; dt++) { + *dt = BLI_rng_get_uint(rng); + } + BLI_rng_free(rng); + } + + { + TIMEIT_START(int_insert); + +#ifdef GHASH_RESERVE + BLI_ghash_reserve(ghash, nbr); +#endif + + for (i = nbr, dt = data; i--; dt++) { + BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*dt), SET_UINT_IN_POINTER(*dt)); + } + + TIMEIT_END(int_insert); + } + + PRINTF_GHASH_STATS(ghash); + + { + TIMEIT_START(int_lookup); + + for (i = nbr, dt = data; i--; dt++) { + void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(*dt)); + EXPECT_EQ(*dt, GET_UINT_FROM_POINTER(v)); + } + + TIMEIT_END(int_lookup); + } + + BLI_ghash_free(ghash, NULL, NULL); + + printf("========== ENDED %s ==========\n\n", id); +} + +TEST(ghash, IntRandGHash12000) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); + + randint_ghash_tests(ghash, "RandIntGHash - GHash - 12000", 12000); +} + +TEST(ghash, IntRandGHash50000000) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); + + randint_ghash_tests(ghash, "RandIntGHash - GHash - 50000000", 50000000); +} + +TEST(ghash, IntRandMurmur2a12000) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__); + + randint_ghash_tests(ghash, "RandIntGHash - Murmur - 12000", 12000); +} + +TEST(ghash, IntRandMurmur2a50000000) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__); + + randint_ghash_tests(ghash, "RandIntGHash - Murmur - 50000000", 50000000); +} + +static unsigned int ghashutil_tests_nohash_p(const void *p) +{ + return GET_UINT_FROM_POINTER(p); +} + +static bool ghashutil_tests_cmp_p(const void *a, const void *b) +{ + return a != b; +} + +TEST(ghash, Int4NoHash12000) +{ + GHash *ghash = BLI_ghash_new(ghashutil_tests_nohash_p, ghashutil_tests_cmp_p, __func__); + + randint_ghash_tests(ghash, "RandIntGHash - No Hash - 12000", 12000); +} + +TEST(ghash, Int4NoHash50000000) +{ + GHash *ghash = BLI_ghash_new(ghashutil_tests_nohash_p, ghashutil_tests_cmp_p, __func__); + + randint_ghash_tests(ghash, "RandIntGHash - No Hash - 50000000", 50000000); +} + + +/* Int_v4: 20M of randomly-generated integer vectors. */ + +static void int4_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr) +{ + printf("\n========== STARTING %s ==========\n", id); + + unsigned int (*data)[4] = (unsigned int (*)[4])MEM_mallocN(sizeof(*data) * (size_t)nbr, __func__); + unsigned int (*dt)[4]; + unsigned int i, j; + + { + RNG *rng = BLI_rng_new(0); + for (i = nbr, dt = data; i--; dt++) { + for (j = 4; j--; ) { + (*dt)[j] = BLI_rng_get_uint(rng); + } + } + BLI_rng_free(rng); + } + + { + TIMEIT_START(int_v4_insert); + +#ifdef GHASH_RESERVE + BLI_ghash_reserve(ghash, nbr); +#endif + + for (i = nbr, dt = data; i--; dt++) { + BLI_ghash_insert(ghash, *dt, SET_UINT_IN_POINTER(i)); + } + + TIMEIT_END(int_v4_insert); + } + + PRINTF_GHASH_STATS(ghash); + + { + TIMEIT_START(int_v4_lookup); + + for (i = nbr, dt = data; i--; dt++) { + void *v = BLI_ghash_lookup(ghash, (void *)(*dt)); + EXPECT_EQ(i, GET_UINT_FROM_POINTER(v)); + } + + TIMEIT_END(int_v4_lookup); + } + + BLI_ghash_free(ghash, NULL, NULL); + MEM_freeN(data); + + printf("========== ENDED %s ==========\n\n", id); +} + +TEST(ghash, Int4GHash2000) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__); + + int4_ghash_tests(ghash, "Int4GHash - GHash - 2000", 2000); +} + +TEST(ghash, Int4GHash20000000) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__); + + int4_ghash_tests(ghash, "Int4GHash - GHash - 20000000", 20000000); +} + +TEST(ghash, Int4Murmur2a2000) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p_murmur, BLI_ghashutil_uinthash_v4_cmp, __func__); + + int4_ghash_tests(ghash, "Int4GHash - Murmur - 2000", 2000); +} + +TEST(ghash, Int4Murmur2a20000000) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p_murmur, BLI_ghashutil_uinthash_v4_cmp, __func__); + + int4_ghash_tests(ghash, "Int4GHash - Murmur - 20000000", 20000000); +} diff --git a/tests/gtests/blenlib/BLI_ghash_test.cc b/tests/gtests/blenlib/BLI_ghash_test.cc new file mode 100644 index 00000000000..5fe43d14cbe --- /dev/null +++ b/tests/gtests/blenlib/BLI_ghash_test.cc @@ -0,0 +1,158 @@ +/* Apache License, Version 2.0 */ + +#include "testing/testing.h" + +#define GHASH_INTERNAL_API + +extern "C" { +#include "BLI_utildefines.h" +#include "BLI_ghash.h" +#include "BLI_rand.h" +} + +#define TESTCASE_SIZE 10000 + +/* Only keeping this in case here, for now. */ +#define PRINTF_GHASH_STATS(_gh) \ +{ \ + double q, lf, var, pempty, poverloaded; \ + int bigb; \ + q = BLI_ghash_calc_quality_ex((_gh), &lf, &var, &pempty, &poverloaded, &bigb); \ + printf("GHash stats (%d entries):\n\t" \ + "Quality (the lower the better): %f\n\tVariance (the lower the better): %f\n\tLoad: %f\n\t" \ + "Empty buckets: %.2f%%\n\tOverloaded buckets: %.2f%% (biggest bucket: %d)\n", \ + BLI_ghash_size(_gh), q, var, lf, pempty * 100.0, poverloaded * 100.0, bigb); \ +} void (0) + +/* Note: for pure-ghash testing, nature of the keys and data have absolutely no importance! So here we just use mere + * random integers stored in pointers. */ + +static void init_keys(unsigned int keys[TESTCASE_SIZE], const int seed) +{ + RNG *rng = BLI_rng_new(seed); + unsigned int *k; + int i; + + for (i = 0, k = keys; i < TESTCASE_SIZE; ) { + /* Risks of collision are low, but they do exist. + * And we cannot use a GSet, since we test that here! */ + int j, t = BLI_rng_get_uint(rng); + for (j = i; j--; ) { + if (keys[j] == t) { + continue; + } + } + *k = t; + i++; + k++; + } + BLI_rng_free(rng); +} + +/* Here we simply insert and then lookup all keys, ensuring we do get back the expected stored 'data'. */ +TEST(ghash, InsertLookup) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); + unsigned int keys[TESTCASE_SIZE], *k; + int i; + + init_keys(keys, 0); + + for (i = TESTCASE_SIZE, k = keys; i--; k++) { + BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k)); + } + + EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash)); + + for (i = TESTCASE_SIZE, k = keys; i--; k++) { + void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(*k)); + EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v)); + } + + BLI_ghash_free(ghash, NULL, NULL); +} + +/* Here we simply insert and then remove all keys, ensuring we do get an empty, unshrinked ghash. */ +TEST(ghash, InsertRemove) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); + unsigned int keys[TESTCASE_SIZE], *k; + int i, bkt_size; + + init_keys(keys, 10); + + for (i = TESTCASE_SIZE, k = keys; i--; k++) { + BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k)); + } + + EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash)); + bkt_size = BLI_ghash_buckets_size(ghash); + + for (i = TESTCASE_SIZE, k = keys; i--; k++) { + void *v = BLI_ghash_popkey(ghash, SET_UINT_IN_POINTER(*k), NULL); + EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v)); + } + + EXPECT_EQ(0, BLI_ghash_size(ghash)); + EXPECT_EQ(bkt_size, BLI_ghash_buckets_size(ghash)); + + BLI_ghash_free(ghash, NULL, NULL); +} + +/* Same as above, but this time we allow ghash to shrink. */ +TEST(ghash, InsertRemoveShrink) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); + unsigned int keys[TESTCASE_SIZE], *k; + int i, bkt_size; + + BLI_ghash_flag_set(ghash, GHASH_FLAG_ALLOW_SHRINK); + init_keys(keys, 20); + + for (i = TESTCASE_SIZE, k = keys; i--; k++) { + BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k)); + } + + EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash)); + bkt_size = BLI_ghash_buckets_size(ghash); + + for (i = TESTCASE_SIZE, k = keys; i--; k++) { + void *v = BLI_ghash_popkey(ghash, SET_UINT_IN_POINTER(*k), NULL); + EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v)); + } + + EXPECT_EQ(0, BLI_ghash_size(ghash)); + EXPECT_LT(BLI_ghash_buckets_size(ghash), bkt_size); + + BLI_ghash_free(ghash, NULL, NULL); +} + +/* Check copy. */ +TEST(ghash, Copy) +{ + GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); + GHash *ghash_copy; + unsigned int keys[TESTCASE_SIZE], *k; + int i; + + init_keys(keys, 30); + + for (i = TESTCASE_SIZE, k = keys; i--; k++) { + BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k)); + } + + EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash)); + + ghash_copy = BLI_ghash_copy(ghash, NULL, NULL); + + EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash_copy)); + EXPECT_EQ(BLI_ghash_buckets_size(ghash), BLI_ghash_buckets_size(ghash_copy)); + + for (i = TESTCASE_SIZE, k = keys; i--; k++) { + void *v = BLI_ghash_lookup(ghash_copy, SET_UINT_IN_POINTER(*k)); + EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v)); + } + + BLI_ghash_free(ghash, NULL, NULL); + BLI_ghash_free(ghash_copy, NULL, NULL); +} diff --git a/tests/gtests/blenlib/BLI_ressource_strings.h b/tests/gtests/blenlib/BLI_ressource_strings.h new file mode 100644 index 00000000000..b823f14af53 --- /dev/null +++ b/tests/gtests/blenlib/BLI_ressource_strings.h @@ -0,0 +1,602 @@ +/* Apache License, Version 2.0 */ + +#ifndef __BLENDER_TESTING_BLI_RESSOURCE_STRING_H__ +#define __BLENDER_TESTING_BLI_RESSOURCE_STRING_H__ + +const char *words10k = +"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam auctor ultrices purus tincidunt mollis. Vestibulum " +"tincidunt imperdiet molestie. Vivamus posuere, risus ut mollis rutrum, lacus nulla mollis velit, consectetur auctor " +"erat est in odio. Proin quis lobortis ex. Ut id quam lacus. Morbi ultrices orci quis sem suscipit tincidunt. Nullam " +"ut molestie justo, vulputate placerat diam. Nunc tincidunt auctor venenatis. Phasellus placerat, odio ac dictum " +"pretium, nisi odio tristique sem, sit amet hendrerit odio tortor eu felis. Duis placerat tristique neque, sit amet " +"ornare nulla fermentum vel. Vivamus vitae rhoncus ante. Sed a dolor mauris. Nullam bibendum vehicula semper. Duis ut " +"commodo nibh. Nulla sit amet eros feugiat, accumsan nisl a, ornare quam. In non magna orci. Curabitur finibus tempus " +"semper. Aliquam fringilla arcu consectetur blandit vestibulum. Mauris mollis est arcu. Praesent pellentesque lacus " +"bibendum massa commodo commodo. Aenean facilisis lobortis varius. Ut semper ullamcorper dui, at pellentesque felis. " +"Duis accumsan sapien ut malesuada lacinia. Praesent elementum venenatis arcu in mattis. Nunc sagittis mauris risus, " +"quis rutrum nisi egestas quis. Maecenas pharetra posuere auctor. Suspendisse mollis sollicitudin elit, id cursus " +"massa bibendum eu. Integer tincidunt dolor non porttitor tempus. Donec lacinia sapien eu enim feugiat suscipit non " +"malesuada diam. Suspendisse nec convallis elit. Nulla eu augue ultrices, consequat lorem at, malesuada magna. " +"Aliquam sed tempor ipsum. Sed hendrerit nec lectus et pharetra. In felis sem, cursus at nunc in, tristique convallis " +"purus. Praesent augue turpis, porttitor consequat risus ornare, laoreet commodo dui. Nulla congue ultrices sapien a " +"cursus. Nulla facilisi. Integer lacinia enim sodales sem mattis, sit amet egestas lectus tincidunt. Ut quis nisl ut " +"ex luctus fermentum quis et diam. Maecenas lectus leo, hendrerit eu facilisis et, mattis ut sem. Duis imperdiet nisl " +"vitae urna consequat suscipit. Suspendisse sed viverra massa, dapibus condimentum sem. Morbi suscipit congue odio. " +"Nullam eleifend fringilla nisl et semper. Sed eu neque ante. Sed eget viverra urna. Duis tempor laoreet interdum. " +"Nunc fringilla aliquet urna sit amet commodo. Curabitur non orci nec libero egestas ullamcorper nec nec velit. Nam " +"vitae ligula lobortis, vehicula nulla id, lacinia urna. Morbi id dignissim eros. Etiam eu risus in sem vestibulum " +"dapibus ut mollis sem. Quisque ultricies pulvinar maximus. Proin risus turpis, auctor eget molestie nec, molestie a " +"ipsum. Donec dapibus dui in lorem rhoncus, non rutrum neque convallis. Donec at tincidunt turpis, nec scelerisque " +"lorem. Donec ac sapien mi. Sed commodo efficitur tempus. Maecenas eu lobortis diam. Phasellus enim nulla, ornare ac " +"laoreet egestas, vestibulum ac arcu. Pellentesque ultrices mauris sem, a iaculis diam tristique id. Proin sed " +"facilisis mauris. Aliquam nibh ex, varius in consequat laoreet, sollicitudin id diam. Vivamus semper ultrices sem " +"non tempor. Sed hendrerit maximus malesuada. In ex orci, elementum non magna eget, congue sagittis tellus. Donec " +"malesuada sem leo, quis malesuada risus blandit et. Praesent porta malesuada metus eget pretium. Vestibulum " +"venenatis tempor tellus at varius. Donec mauris arcu, elementum vitae aliquet nec, ullamcorper vitae neque. Nunc eu " +"viverra justo, sit amet viverra elit. Proin urna elit, luctus ut placerat quis, blandit vitae diam. Vestibulum id " +"fringilla enim. Ut eleifend augue ante, ac euismod sapien luctus sit amet. Pellentesque mattis tortor ac rutrum " +"malesuada. Sed et nulla id metus faucibus condimentum. Vestibulum cursus posuere vestibulum. Proin auctor arcu erat, " +"quis porta sem dignissim a. Donec sed finibus ante. Integer porttitor pretium nunc, eu semper elit. Nam sit amet " +"ornare urna. Suspendisse porta augue id massa luctus maximus. Fusce tellus ligula, finibus sed lacus eget, tristique " +"mollis libero. Vivamus velit diam, faucibus vel fringilla vitae, ornare id lacus. Pellentesque vel sem quis nunc " +"semper porta ut sit amet sapien. Integer nec leo at tortor ullamcorper pulvinar at ut ante. Fusce velit nisl, " +"fermentum in tempus ac, gravida ac tellus. In aliquet sollicitudin erat, non vestibulum diam aliquam in. Duis purus " +"justo, aliquet ut libero vel, egestas mollis nibh. Praesent sed tempor mauris, vel tempor augue. Morbi eu eros vel " +"velit condimentum porttitor nec sit amet odio. Nunc suscipit risus at ex aliquam, in pretium mi maximus. Mauris " +"sollicitudin sit amet arcu luctus maximus. Curabitur vehicula condimentum porta. Nunc consequat vitae urna vel " +"gravida. Vivamus vitae mattis augue, sit amet blandit enim. Phasellus odio leo, cursus eget lacus sit amet, " +"facilisis mattis tortor. Duis venenatis ante libero, eu condimentum urna viverra fermentum. Suspendisse libero leo, " +"pretium eu leo at, imperdiet ultricies nunc. Fusce ante neque, feugiat id lacus sed, fringilla suscipit ligula. " +"Phasellus cursus malesuada urna, vel ullamcorper massa suscipit vitae. In eu bibendum augue. Duis auctor posuere " +"turpis nec vestibulum. Vestibulum nec dui in mi consequat auctor sed at nisl. Suspendisse tellus elit, congue ut " +"facilisis vel, ornare id mauris. Integer rutrum fermentum neque, vitae pharetra metus consectetur in. Duis vitae " +"lacus scelerisque, rhoncus nisl id, sagittis elit. Praesent lacinia libero ac ultricies tempus. Etiam ut maximus " +"sapien. Maecenas sit amet ante auctor, feugiat diam non, vulputate diam. Nulla facilisi. Vestibulum id augue velit. " +"Donec at elementum urna. Morbi elementum nunc in neque ornare, sit amet tempor mauris vulputate. Nunc mauris mauris, " +"lobortis non nibh sed, gravida sollicitudin nunc. Nunc vel dolor non augue venenatis semper vitae non turpis. " +"Praesent mattis elit eu interdum porttitor. Etiam quis magna magna. Praesent a ipsum est. Aenean at ligula vel leo " +"faucibus pulvinar sed eget mauris. Nam accumsan blandit nibh, nec tincidunt nisl eleifend sit amet. Etiam ornare, " +"arcu nec dictum volutpat, nulla orci porttitor orci, vel venenatis mi massa at erat. Maecenas eget accumsan nisl, " +"quis ullamcorper turpis. Pellentesque sit amet mi aliquet, feugiat felis in, dictum urna. Cras nulla leo, congue vel " +"consequat gravida, aliquet a nulla. Nulla commodo, nisi eu ultricies feugiat, justo velit tempor ligula, a tincidunt " +"nisi tellus ut sapien. Sed eget ornare magna. Cras ut vehicula sapien. Quisque id malesuada urna, vitae congue ante. " +"Donec nec leo pretium, finibus nibh a, porta lectus. Fusce arcu tellus, tempor semper sem id, aliquam fringilla " +"ipsum. Ut massa ante, placerat quis sapien quis, sollicitudin blandit turpis. Aenean posuere ullamcorper massa. Nam " +"faucibus egestas arcu. Vivamus vehicula auctor diam, eu placerat diam ullamcorper at. Nulla eu consequat elit, vel " +"semper turpis. Curabitur rhoncus nunc vel vestibulum interdum. Nam augue neque, pharetra vel nisi dignissim, " +"vehicula dapibus risus. Cras eget mattis nisi. Sed tempor posuere gravida. Proin sagittis a nisl eget gravida. " +"Curabitur viverra dapibus arcu, sit amet rutrum nibh fringilla euismod. Donec vitae risus non lorem facilisis cursus " +"eu eu quam. Donec quis lacus blandit, consectetur elit ut, sagittis ligula. Etiam dapibus ex sit amet elit commodo " +"finibus. Suspendisse non finibus felis, non cursus libero. Vivamus semper aliquet velit vel elementum. Phasellus " +"dictum, tortor id sagittis ultrices, ex dui porttitor tortor, nec mattis dolor sem nec mi. Ut aliquam consequat eros " +"sit amet mollis. Nullam mollis venenatis porttitor. Donec sit amet velit at velit luctus auctor dictum in neque. Ut " +"vulputate ultricies mollis. Pellentesque elementum augue dolor, non varius ligula tristique ac. Nullam eget mauris " +"urna. Integer elementum eleifend pulvinar. Morbi gravida ante eget ornare faucibus. Mauris pulvinar consequat nunc " +"vel accumsan. Curabitur egestas urna elit, ut accumsan magna dictum in. Nam neque mi, ornare sed leo at, tempor " +"vulputate nunc. Nunc dignissim mauris id dui iaculis fringilla. Praesent malesuada tellus in dapibus feugiat. " +"Vivamus posuere, nisi et consequat euismod, lorem augue iaculis velit, eget iaculis neque quam eu mi. Nullam ac " +"hendrerit felis, non elementum ipsum. Aliquam erat volutpat. Proin vel molestie felis. Nullam luctus vel ante nec " +"facilisis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Duis et metus " +"justo. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut tristique sit amet elit et congue. Aenean " +"quis elementum enim, vitae pharetra sem. Vestibulum vel finibus nisl, at consequat eros. In vitae mollis lacus, et " +"pharetra elit. Mauris varius sapien quis tincidunt blandit. Proin non semper nibh. Aliquam non elit id felis laoreet " +"interdum eget a risus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. " +"Suspendisse nisl tellus, mollis id erat vel, hendrerit volutpat nunc. Quisque scelerisque cursus tellus, nec " +"placerat quam imperdiet in. Sed porttitor arcu vel ligula finibus, a vestibulum enim ultrices. Fusce imperdiet augue " +"eget est vehicula porttitor. Quisque convallis odio vitae lorem porttitor iaculis. Ut dictum velit ac tortor " +"lobortis ultrices. Vestibulum tincidunt vestibulum mauris, at fermentum elit imperdiet nec. Nunc finibus ornare " +"lorem vel malesuada. Praesent arcu turpis, pulvinar sit amet accumsan quis, tincidunt vel justo. Pellentesque " +"volutpat nec enim sit amet pulvinar. Nam eu libero dignissim, volutpat elit ut, semper tortor. Morbi pellentesque " +"nisl lectus. In vel tellus sed sem luctus lobortis ut nec diam. Phasellus id semper sem. Phasellus in purus " +"consequat, rhoncus mi mollis, finibus ligula. Fusce feugiat dictum consequat. Mauris egestas, est ut euismod " +"consequat, arcu dui dignissim quam, pharetra dignissim orci dolor quis nisl. Nunc dapibus blandit urna non feugiat. " +"Suspendisse non maximus augue. Quisque ut orci aliquet, vulputate massa eget, mattis diam. Etiam efficitur " +"consectetur viverra. Nulla massa augue, elementum at turpis et, cursus ultricies risus. Suspendisse vel nibh " +"placerat, imperdiet elit et, viverra ligula. Donec lorem lorem, hendrerit nec aliquam sit amet, scelerisque sit amet " +"massa. Mauris convallis ullamcorper tortor sed malesuada. Fusce ultricies a turpis eu ornare. Suspendisse potenti. " +"Sed non nulla condimentum, vulputate nisi nec, tincidunt arcu. Morbi erat leo, lobortis id odio ac, hendrerit " +"sodales sem. Ut malesuada, lectus at posuere molestie, orci metus vehicula justo, mattis tincidunt arcu risus quis " +"odio. Fusce non sem sed nisi consectetur finibus vitae quis diam. Vivamus a lacinia nisl. Praesent tempus nunc " +"gravida, lacinia lacus in, lobortis massa. Aliquam gravida consequat nisi at fringilla. Quisque tortor tortor, " +"tincidunt cursus lorem eget, ultrices ultricies lacus. Phasellus mattis iaculis elit, eget mattis nisl bibendum sed. " +"Integer faucibus gravida nisl, ac consequat ex tempor at. Sed tempus elementum vestibulum. Suspendisse vitae enim " +"semper, pulvinar diam eget, suscipit turpis. Maecenas ultricies, diam sed consectetur sagittis, diam sem cursus " +"nisl, nec aliquet tellus augue quis ipsum. Cras vel lorem convallis, mattis risus at, placerat massa. Curabitur vel " +"rutrum ligula. Quisque in nibh libero. Pellentesque diam tellus, consectetur eget quam ac, faucibus imperdiet odio. " +"Sed tortor nulla, scelerisque non turpis nec, fringilla bibendum est. Etiam a urna eget erat tincidunt ultrices. " +"Maecenas lorem odio, volutpat nec ligula id, hendrerit aliquam nulla. Aenean congue lacinia fermentum. Suspendisse " +"sed interdum lacus. Fusce scelerisque posuere sagittis. Ut at semper tellus. Donec condimentum orci nunc, non " +"fermentum purus volutpat eget. Maecenas elementum dapibus ante, eu suscipit quam imperdiet ut. Integer non congue " +"elit. Sed venenatis, turpis varius commodo euismod, libero magna fringilla lacus, quis venenatis velit lectus sed " +"augue. Morbi gravida orci odio, ut ornare massa sollicitudin a. Donec convallis mi et sapien tempor, non dapibus " +"dolor fringilla. Aenean euismod rutrum turpis, et facilisis orci porttitor eu. Suspendisse in neque leo. Nulla " +"facilisi. Etiam mollis orci nisl, quis scelerisque metus efficitur vehicula. Nam porta molestie tortor, sit amet " +"consectetur leo vestibulum vel. Pellentesque a volutpat augue. Maecenas vel elementum ex, eget elementum leo. " +"Curabitur at maximus metus, quis porttitor orci. Praesent auctor commodo elit, a dapibus tortor volutpat et. " +"Praesent dictum posuere dolor sit amet molestie. Sed viverra augue nec eros mattis blandit. In quis sodales dolor. " +"Donec sed purus ex. Fusce erat magna, efficitur ac tempus ac, lacinia quis augue. Aliquam porta efficitur est vel " +"placerat. Phasellus egestas vel nunc eu consequat. Maecenas ligula arcu, molestie ut dui ut, ornare finibus felis. " +"Duis condimentum non augue ut posuere. Aenean mattis eros ut ligula ornare finibus. Aliquam feugiat ut turpis a " +"feugiat. Vestibulum eget sollicitudin orci, nec fermentum justo. Praesent efficitur est a metus bibendum, eget " +"feugiat diam suscipit. Suspendisse sit amet ipsum ut purus feugiat pretium. Morbi nisl risus, ultricies sit amet " +"ullamcorper euismod, commodo eu libero. Aenean fringilla ipsum nec orci rutrum aliquet. Aenean lacus ante, eleifend " +"eu eleifend fringilla, elementum ac justo. Vestibulum tincidunt interdum lectus sit amet fermentum. Etiam rhoncus eu " +"ante lacinia sagittis. Maecenas iaculis ut erat quis feugiat. Maecenas sed est vel tellus bibendum rutrum volutpat " +"nec odio. Vivamus euismod augue nec purus euismod, mattis finibus nisi finibus. Donec quis ultrices massa. Quisque " +"at nisl faucibus, facilisis tellus ut, ultricies dui. Class aptent taciti sociosqu ad litora torquent per conubia " +"nostra, per inceptos himenaeos. Donec et arcu eros. Etiam dapibus bibendum felis eu viverra. Integer a lacus " +"venenatis elit lacinia facilisis non non felis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed " +"ultricies augue at sapien mattis aliquam. Quisque nec semper purus. Cras auctor aliquet lacus, sed facilisis urna " +"sollicitudin non. Vivamus eget erat purus. Sed a risus augue. Donec non sem sed sapien accumsan lacinia. Ut mauris " +"odio, vehicula id accumsan at, tincidunt non odio. Nunc porttitor luctus ante ac cursus. Cras et dapibus ex, id " +"pretium ligula. Proin volutpat rhoncus ex vitae venenatis. Pellentesque imperdiet, magna non tempus auctor, metus " +"dolor scelerisque dui, id tempor purus est in risus. Suspendisse vehicula imperdiet sapien, nec pulvinar dolor " +"ornare ac. Nulla luctus, nisl in aliquam blandit, risus orci placerat nunc, id tempus sem neque vitae leo. Aenean at " +"elit elit. Suspendisse finibus dictum interdum. Nunc consectetur eget quam vitae egestas. Pellentesque tellus augue, " +"aliquet at faucibus ac, imperdiet ut nulla. Maecenas quis lorem velit. Donec porta ligula et suscipit luctus. " +"Aliquam sed pretium nunc. Nunc quis posuere tortor. Fusce in lectus nec turpis rhoncus pellentesque eu at quam. " +"Nulla facilisi. Sed ante nulla, posuere ac ullamcorper vel, rhoncus vitae nisl. Nam non pellentesque arcu. Vivamus " +"nibh leo, pellentesque a mollis non, gravida ut erat. Donec purus urna, pulvinar eu iaculis blandit, rutrum eget " +"nulla. Fusce quis fermentum diam, faucibus volutpat lorem. Maecenas aliquet nisi nisl, eget sollicitudin ipsum " +"facilisis at. Mauris nec sapien nisi. Duis ac laoreet sapien, a condimentum nisi. Nam vitae sapien sed sem convallis " +"ornare. Pellentesque neque diam, ullamcorper et dolor sit amet, faucibus venenatis tortor. Nunc vel erat malesuada, " +"vulputate odio sit amet, aliquam dui. Donec tincidunt arcu ut risus laoreet, id malesuada leo ultrices. Praesent a " +"scelerisque libero, vitae suscipit massa. Quisque faucibus mauris rhoncus turpis vestibulum rhoncus. Donec vel " +"molestie magna. Aenean et lorem dui. Nam iaculis ante sapien, semper tincidunt tortor hendrerit id. Nulla sed orci " +"mi. Aliquam hendrerit libero erat, ac aliquam massa rutrum non. Suspendisse eleifend, elit in aliquet hendrerit, " +"tellus erat sodales neque, quis rhoncus tellus sem vitae est. Interdum et malesuada fames ac ante ipsum primis in " +"faucibus. Etiam quis mauris non ipsum tristique interdum sit amet eget mi. Ut velit risus, gravida ut efficitur sit " +"amet, commodo at diam. Sed consectetur dui porttitor quam feugiat, et auctor mauris maximus. Nullam lobortis ac mi " +"lacinia egestas. Proin ante massa, malesuada ut nulla elementum, venenatis mollis ante. Cum sociis natoque penatibus " +"et magnis dis parturient montes, nascetur ridiculus mus. Mauris eget gravida eros, non varius velit. Integer " +"consectetur lectus nec arcu scelerisque, scelerisque vulputate mauris suscipit. Aliquam orci dui, faucibus et rutrum " +"in, rhoncus quis dolor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; " +"Maecenas ante nunc, placerat id lectus sit amet, luctus cursus ante. Nulla nec placerat arcu. Fusce ac dictum ex. " +"Vivamus semper nulla vitae neque volutpat, auctor vestibulum arcu tempus. Pellentesque aliquam tincidunt arcu, et " +"pharetra neque. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nunc " +"risus augue, malesuada quis risus a, suscipit semper metus. Suspendisse ac rhoncus felis. Aliquam orci lectus, " +"elementum at nulla at, ullamcorper pellentesque leo. Quisque nisi tellus, pharetra in pellentesque in, facilisis " +"vitae velit. In ex ex, sagittis at dolor vel, congue ultricies velit. Duis quis gravida mi. Aenean tempor efficitur " +"lectus. Fusce sodales, ex eu efficitur iaculis, metus sem eleifend purus, ut commodo arcu tortor eget urna. Etiam " +"nisi nisl, malesuada convallis ex at, malesuada elementum nunc. Vivamus commodo mi id ligula tincidunt posuere. " +"Integer eget arcu cursus, sagittis quam eu, aliquam leo. In auctor eget mauris et elementum. Aenean sagittis euismod " +"tellus sed accumsan. Aliquam erat volutpat. Aliquam erat volutpat. Ut consectetur porta ipsum sit amet porttitor. " +"Nam ut nunc a turpis auctor finibus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac " +"turpis egestas. Donec non nisl condimentum, fermentum augue in, egestas libero. Pellentesque ut odio rhoncus, " +"sollicitudin felis vitae, pellentesque est. Suspendisse tincidunt eros eget ex vestibulum elementum. Vivamus mollis " +"scelerisque diam, quis dignissim dolor venenatis at. Ut gravida sapien vitae risus efficitur, ut auctor justo " +"gravida. Cras arcu elit, interdum vel purus sit amet, venenatis molestie tellus. Integer consectetur tempor velit a " +"varius. Praesent congue, massa non congue blandit, tortor purus imperdiet elit, sit amet pharetra arcu lacus egestas " +"neque. Maecenas in erat arcu. In varius, risus vitae mollis sodales, nisi velit bibendum tortor, vitae sagittis " +"augue tortor quis nunc. Fusce posuere dolor ac tincidunt facilisis. Phasellus in lacus diam. Fusce mattis sapien " +"tellus, scelerisque pharetra leo eleifend nec. Cras libero diam, convallis in luctus a, iaculis a ipsum. Duis arcu " +"leo, volutpat non mauris et, scelerisque suscipit diam. Ut vulputate placerat velit quis placerat. Duis commodo non " +"turpis et convallis. Duis nec pulvinar metus, ac tristique leo. Fusce vehicula augue ac placerat elementum. Nulla " +"dapibus nisi pretium lectus sodales, ac congue sapien ornare. Vestibulum sagittis orci ut purus efficitur, eu mollis " +"libero placerat. Vestibulum ullamcorper odio non quam mollis, eget rhoncus metus eleifend. Mauris scelerisque, massa " +"rutrum sodales malesuada, elit dolor blandit lectus, quis faucibus felis odio feugiat lacus. Nunc bibendum congue " +"efficitur. Nunc a purus neque. In lobortis metus nisi, vel pellentesque mi facilisis sed. Donec in pretium neque, in " +"maximus metus. Integer faucibus diam sed tristique sagittis. Nullam eget maximus leo, eget malesuada leo. Vestibulum " +"ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean porttitor risus eget eros " +"euismod molestie. Integer tristique tincidunt elit, non posuere libero pretium vel. Fusce dapibus, nisi nec egestas " +"dapibus, lectus arcu maximus leo, a finibus diam arcu ut mauris. Vivamus tincidunt lectus ut augue ultrices, et " +"cursus sem cursus. Proin in quam mauris. Maecenas vel magna dapibus, interdum ipsum mattis, posuere tortor. Cras eu " +"massa ex. Donec eget massa vel dui gravida luctus vel a quam. Etiam eu lobortis neque. Etiam ligula dui, dictum ut " +"turpis ac, eleifend pretium turpis. Vestibulum convallis finibus commodo. Morbi fermentum ante nunc, a rhoncus lacus " +"ultricies quis. Suspendisse finibus quam blandit odio elementum, non efficitur diam laoreet. Cras aliquet ligula " +"eget magna scelerisque, ut ornare nisi elementum. Duis nisl massa, suscipit id nibh a, venenatis auctor risus. Nulla " +"luctus eget odio quis ultrices. Etiam consequat sapien ut nisl mollis cursus. Pellentesque a lacinia odio, id varius " +"lorem. Curabitur scelerisque in urna eget pretium. Class aptent taciti sociosqu ad litora torquent per conubia " +"nostra, per inceptos himenaeos. Sed leo metus, fermentum vitae quam ut, suscipit efficitur purus. Sed facilisis " +"dapibus pulvinar. Cras sed eleifend mi. Sed quis nibh in sapien venenatis interdum ac nec orci. Sed non tortor urna. " +"Nam rutrum lacinia diam id vehicula. Quisque vitae lobortis nibh, at tempor purus. Suspendisse dictum interdum nisi, " +"quis maximus ipsum commodo tempus. Nulla semper congue gravida. Aenean at nibh in eros aliquam egestas. Nulla " +"fermentum efficitur laoreet. Donec non lorem nec augue porttitor cursus eu in quam. Aenean laoreet quam neque, at " +"tempus nisi ultrices id. Quisque in diam lacinia nulla scelerisque rhoncus vitae eget nulla. Donec vel est metus. " +"Nullam suscipit odio eu enim lacinia facilisis eget in tellus. Vestibulum vehicula risus nec odio consectetur, a " +"cursus massa imperdiet. Duis facilisis felis quis nunc mattis, nec volutpat libero tempor. Nulla nec leo sed tellus " +"maximus lobortis. Suspendisse at urna nibh. Vestibulum eget turpis nisl. Donec scelerisque neque auctor erat tempor " +"elementum sed id lacus. Sed metus nulla, dictum non luctus vel, suscipit et ex. Quisque laoreet sapien non neque " +"iaculis, at aliquam massa viverra. Nullam nibh diam, imperdiet eu nunc sed, congue cursus leo. Morbi tristique diam " +"metus, at faucibus magna mollis at. Sed eget nibh nunc. Nam nec elementum sem, sit amet tincidunt lorem. In viverra " +"elit et interdum fermentum. Integer imperdiet orci ac justo molestie ullamcorper. Pellentesque fringilla tortor " +"erat, scelerisque maximus nisl sollicitudin a. Integer nisi elit, pharetra eget lacinia non, congue sit amet ex. " +"Phasellus tempus suscipit ultrices. Quisque ac nibh dignissim erat bibendum cursus vel a enim. Curabitur a augue sit " +"amet lorem pharetra feugiat. Donec euismod, massa at venenatis bibendum, elit libero pellentesque velit, eget congue " +"metus risus a enim. Aenean pretium vestibulum enim, sit amet vulputate urna auctor vitae. Praesent porttitor erat eu " +"mi cursus venenatis. Maecenas ut ultrices neque, ac feugiat libero. Nulla finibus sit amet sem in auctor. Nam " +"fermentum maximus ex, et consequat velit lobortis id. Aliquam eu feugiat est. Donec quis leo ex. Suspendisse " +"convallis eget nulla eu aliquet. Quisque aliquet tortor vitae ipsum fermentum tristique. Sed convallis rutrum augue, " +"ac viverra est pharetra quis. Ut porttitor magna massa, placerat maximus lectus scelerisque quis. Sed viverra urna " +"in neque feugiat rhoncus. Donec ut viverra odio, laoreet dignissim dui. Aenean tristique feugiat diam vel luctus. " +"Cras sit amet condimentum neque, ut faucibus ante. Aenean vitae elit id est laoreet efficitur in sit amet magna. " +"Praesent ante felis, blandit id nisl ut, porta fringilla orci. Aenean vel accumsan metus, vel vehicula metus. Nulla " +"placerat nibh et auctor convallis. Maecenas magna metus, pretium ac sodales ac, eleifend quis eros. Praesent " +"volutpat quam a pulvinar pharetra. Sed arcu dolor, aliquet nec magna in, faucibus consequat lorem. In tincidunt, ex " +"a finibus rutrum, metus dui fringilla ex, ac mollis elit leo eget augue. Nunc vehicula facilisis nibh, quis " +"ultricies sem. Praesent nulla est, finibus in lorem in, mattis placerat urna. Proin hendrerit risus nunc, id congue " +"ex posuere id. Aenean ullamcorper tortor quis lorem consectetur, et euismod leo fermentum. Praesent vulputate congue " +"lectus sit amet pulvinar. Vestibulum vel vestibulum quam, in convallis diam. Maecenas sollicitudin magna odio, eget " +"mollis purus posuere eu. Curabitur molestie mattis ligula, a maximus dui fermentum ut. Fusce justo velit, eleifend " +"ut tellus vitae, volutpat maximus risus. Pellentesque suscipit mauris non purus placerat porta. Nunc in malesuada " +"mi, vel bibendum felis. Aenean pretium nunc id efficitur porttitor. Mauris malesuada, tortor sit amet blandit " +"tincidunt, tellus est ullamcorper diam, sit amet aliquet ex velit interdum quam. In hac habitasse platea dictumst. " +"Sed vitae est eu elit posuere mattis nec a mauris. Morbi id ligula sed nunc sagittis finibus vitae eu nisi. Cras " +"dignissim sagittis tellus a suscipit. Nunc semper erat nec libero vestibulum, at mattis purus scelerisque. " +"Pellentesque egestas volutpat eleifend. Nullam venenatis erat id diam venenatis, sed rhoncus felis hendrerit. Nullam " +"luctus facilisis risus. Mauris sed urna nisi. Ut tempus feugiat metus. Integer at purus velit. Praesent neque felis, " +"pellentesque vitae sem nec, tempor commodo urna. Morbi malesuada ante sit amet purus tincidunt pellentesque. Aenean " +"commodo lectus sit amet dignissim hendrerit. Phasellus auctor tellus ligula, eu ultrices ex egestas non. Mauris eget " +"nisl dictum, scelerisque sapien et, dapibus felis. Aenean in dignissim leo. Sed semper, ex at euismod molestie, ex " +"odio ullamcorper nisi, et facilisis lectus eros non magna. In hac habitasse platea dictumst. Pellentesque sed " +"maximus mauris. Cras luctus dapibus nunc, sit amet suscipit dui viverra nec. Donec gravida tortor porttitor orci " +"malesuada porttitor. Nunc condimentum eu libero sit amet varius. Curabitur mollis urna eu porta tincidunt. Nullam " +"ultricies magna libero, et dapibus tellus tempus eu. Nullam pretium lectus nec iaculis pretium. Maecenas at arcu " +"lobortis, ornare ante nec, euismod metus. Pellentesque volutpat tellus nulla. Aenean mattis efficitur velit vitae " +"blandit. Duis vel egestas eros. Pellentesque aliquam placerat elit, eu congue sem ullamcorper sit amet. Ut erat " +"nisl, luctus vitae pellentesque ut, tristique eu odio. Pellentesque nec fermentum ex, rhoncus varius dui. Mauris " +"lobortis nunc nec dui volutpat consequat. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur " +"ridiculus mus. Aliquam dignissim purus sed ligula pretium placerat. In vestibulum ultricies mauris. Curabitur " +"aliquet lorem quis libero auctor, ut rhoncus purus lobortis. Nulla elementum erat nec rhoncus posuere. Integer " +"faucibus quam sed elementum fringilla. In in lobortis sapien, nec commodo tortor. Aenean euismod ipsum nisi, vitae " +"fringilla leo imperdiet ut. Donec a semper odio, et tempor magna. Cras cursus vel augue quis egestas. Nam nec tortor " +"blandit, mattis quam imperdiet, finibus quam. Pellentesque tincidunt eros urna, ut tristique diam faucibus " +"condimentum. Ut dictum risus mi, non sollicitudin turpis facilisis sit amet. Morbi finibus scelerisque mattis. Fusce " +"vel tempor purus, nec pharetra augue. Curabitur dapibus, orci eu consectetur ultrices, diam mauris sodales urna, non " +"euismod diam lacus luctus risus. Mauris commodo accumsan sapien. Proin vel blandit sapien. Donec porta tortor vel " +"nibh faucibus molestie. Pellentesque placerat justo erat, vitae tristique felis fringilla eget. Quisque facilisis " +"justo at orci lobortis, ut commodo diam egestas. Etiam non tristique nisl. Cras varius, massa a sollicitudin ornare, " +"turpis arcu fringilla leo, non euismod ligula arcu id lacus. Suspendisse potenti. Morbi pharetra dolor eget porta " +"tristique. Nullam sem tortor, lobortis eget hendrerit a, efficitur sit amet sapien. Fusce sit amet condimentum odio, " +"aliquet rutrum velit. Morbi vel rhoncus ante. In blandit eros ut lectus varius, quis tempor arcu iaculis. In massa " +"leo, venenatis nec lobortis non, pulvinar non nunc. Nunc vehicula, erat vitae placerat eleifend, eros ipsum " +"consectetur odio, eu ornare velit mauris nec sapien. Integer a consequat libero. Quisque velit augue, blandit eu " +"luctus sit amet, laoreet sit amet odio. Etiam in enim lacus. Interdum et malesuada fames ac ante ipsum primis in " +"faucibus. In rutrum a tortor id pulvinar. Donec pretium lorem sed sem eleifend fringilla. Fusce sollicitudin ac " +"ligula eget pharetra. Sed cursus diam non sem ullamcorper efficitur. Vivamus congue ligula iaculis justo iaculis " +"elementum. Integer tempor nisl arcu, ut tincidunt erat vestibulum et. Suspendisse rutrum aliquet eros non " +"pellentesque. Mauris laoreet, diam id tincidunt faucibus, risus velit venenatis risus, in venenatis justo diam et " +"orci. Etiam pulvinar pulvinar nisi, id efficitur erat vulputate ut. Sed suscipit sodales ante, a blandit orci " +"maximus vel. Vestibulum at aliquet orci. Proin tincidunt nisi quis eros consequat consectetur. Praesent congue " +"lobortis laoreet. Donec imperdiet risus erat, eu volutpat justo posuere id. Fusce placerat sollicitudin eros vitae " +"tincidunt. Sed orci ante, ultricies sed dapibus vel, sagittis ac massa. Pellentesque vel mauris nec est hendrerit " +"posuere. Integer sagittis diam sed felis facilisis ultrices. Aliquam erat volutpat. Nulla pharetra justo in ipsum " +"dapibus, nec viverra nunc euismod. Nulla massa ante, euismod at interdum vel, dapibus ut ex. Etiam consequat mauris " +"a suscipit lobortis. Donec commodo convallis velit, eget commodo urna vulputate ac. Sed molestie vel dui ut feugiat. " +"Donec orci purus, placerat vitae egestas sed, sodales nec ex. Sed egestas turpis non malesuada semper. Donec et mi a " +"nisi volutpat sagittis. Suspendisse potenti. Phasellus mollis sapien ac tellus imperdiet tempus. Praesent nec sapien " +"sit amet ipsum interdum interdum non eget nunc. Aenean fringilla lorem a viverra rutrum. Donec at maximus nibh. " +"Phasellus facilisis justo sit amet metus pharetra sagittis. Quisque mollis metus laoreet ipsum tincidunt " +"sollicitudin. Maecenas sit amet dictum ligula. Fusce molestie iaculis dui, et gravida libero hendrerit in. Praesent " +"euismod libero metus, vitae rhoncus velit ultrices eget. Vestibulum ac massa bibendum, gravida dolor vel, dapibus " +"est. Etiam non elit varius, mollis purus eget, placerat velit. Nullam lectus dui, mattis at pulvinar eu, elementum " +"et lorem. Sed vel auctor orci, nec semper neque. Nullam cursus commodo quam, in ultricies tellus rhoncus vulputate. " +"Mauris dapibus ipsum ipsum, dapibus euismod purus pellentesque at. Nullam euismod lectus non risus consequat " +"vulputate. Quisque finibus a turpis eu convallis. Nam magna turpis, feugiat ut urna in, tempus facilisis elit. Duis " +"dignissim purus sagittis porttitor posuere. Suspendisse varius ligula at egestas scelerisque. Duis placerat sagittis " +"nisi, et molestie tortor posuere condimentum. Morbi hendrerit, ante ornare tempus finibus, ex ipsum laoreet dui, vel " +"ornare felis tortor sit amet metus. Vivamus laoreet placerat massa, non suscipit nisl faucibus eget. Vestibulum ante " +"ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque orci lacus, vulputate cursus ex " +"eu, porta aliquam massa. Proin dolor massa, faucibus vel rhoncus et, venenatis a nisi. Vivamus venenatis enim mi. " +"Sed viverra augue vitae lectus lobortis vulputate. Phasellus ac ligula congue, sagittis est non, aliquet tortor. " +"Suspendisse faucibus euismod neque, ac congue felis. Curabitur maximus neque sit amet odio varius gravida. Proin " +"egestas nulla eget mi bibendum luctus. Ut non mollis mi. Quisque finibus, eros non lobortis interdum, diam nisi " +"faucibus diam, non imperdiet leo velit et dolor. Nam est massa, vehicula sed diam sed, laoreet convallis nisi. Donec " +"enim ligula, dignissim non sem ut, pulvinar cursus mi. In at dignissim nulla, ac fringilla neque. In hac habitasse " +"platea dictumst. Quisque luctus mattis orci, consequat egestas nisi. Vivamus et metus et quam porttitor elementum. " +"Suspendisse auctor mauris eu sollicitudin sagittis. Vivamus ac ante non augue iaculis consectetur quis quis dui. In " +"bibendum risus tristique ligula iaculis finibus. Phasellus non ante risus. Maecenas ac leo cursus, molestie purus " +"sed, tristique purus. Etiam sem nulla, aliquam nec laoreet nec, iaculis quis nulla. Maecenas id dui id neque " +"venenatis gravida. Etiam vestibulum felis at diam porta ultrices. Ut finibus tortor et augue ornare, et efficitur " +"purus scelerisque. Phasellus et ultricies arcu, vel lacinia lacus. Aenean tincidunt eleifend nunc, sit amet mattis " +"purus venenatis sit amet. Curabitur eleifend sem nisl, et feugiat diam pharetra sit amet. Mauris ullamcorper mi vel " +"condimentum egestas. Nulla pulvinar purus vel sagittis posuere. Nulla quis enim bibendum, iaculis quam in, tincidunt " +"quam. Vestibulum rhoncus volutpat risus. Nulla ultricies bibendum est non malesuada. Nunc porta erat est, a " +"tincidunt magna gravida vel. Maecenas sit amet aliquet odio. Vestibulum egestas, tortor scelerisque consectetur " +"pharetra, nisi tellus feugiat justo, et bibendum libero mi in diam. Aliquam tempus sapien nec tristique convallis. " +"Nullam congue, lacus quis bibendum dignissim, nisl purus molestie dolor, a tempor dolor nibh pretium tellus. In hac " +"habitasse platea dictumst. Cras at est turpis. Nam nec lacus posuere, mattis mi eu, viverra ex. Nullam eleifend " +"ornare orci, vel tempor tellus. Ut nec eros eget tortor tempus tristique commodo sed lorem. Donec quis scelerisque " +"nibh, non tincidunt velit. Fusce in eleifend sapien. Nunc sodales sem ut nunc pellentesque, eget pharetra justo " +"tempor. Proin pretium velit et vehicula interdum. Maecenas luctus venenatis tincidunt. Donec hendrerit, ligula non " +"volutpat porta, dui ante facilisis massa, at congue orci mi sed quam. Donec lorem ipsum, malesuada quis purus in, " +"commodo malesuada justo. Etiam luctus, lorem vel rutrum tristique, mauris urna volutpat felis, a laoreet urna nunc " +"et neque. Morbi a diam tincidunt augue cursus commodo nec ut ligula. Maecenas ultrices purus fermentum ullamcorper " +"aliquet. Maecenas mi enim, semper nec metus at, posuere tristique ligula. Suspendisse est elit, porta quis massa id, " +"gravida commodo ante. Nullam maximus mauris sit amet dolor tempus posuere. Phasellus purus mi, interdum in ipsum " +"quis, tristique venenatis dolor. Suspendisse potenti. Phasellus odio erat, varius sed aliquet vestibulum, laoreet " +"sed mauris. Vivamus sapien erat, maximus tristique elementum ac, eleifend in enim. Morbi accumsan elementum neque, a " +"facilisis enim laoreet non. Donec auctor condimentum fringilla. Proin id urna nec tellus maximus maximus tincidunt " +"et libero. Integer ultricies venenatis odio, ut volutpat odio laoreet non. Donec in scelerisque justo. Integer " +"mauris libero, fringilla vel sapien sit amet, laoreet tincidunt dolor. Nam efficitur sagittis arcu, vel lobortis dui " +"gravida non. Curabitur lobortis feugiat finibus. Vestibulum dictum tortor nec magna fringilla blandit. Nulla " +"facilisi. Sed cursus laoreet neque vitae pulvinar. Ut iaculis euismod ullamcorper. Nunc in hendrerit lectus, sed " +"venenatis mi. Suspendisse et est dui. Sed elementum augue non ornare cursus. Quisque varius facilisis magna nec " +"laoreet. Suspendisse consequat, risus sed tempus egestas, velit felis faucibus erat, eu pharetra erat nisl sed " +"turpis. Sed ultricies ac quam id mollis. In consequat et erat vitae interdum. Pellentesque malesuada feugiat ligula " +"eu consectetur. Vestibulum tempor mi quis purus luctus dictum. Etiam condimentum ac ligula eget imperdiet. Ut " +"placerat, tortor eu lacinia imperdiet, enim nibh aliquam nibh, quis faucibus enim odio eu arcu. Nullam sagittis, " +"diam a ornare congue, ipsum eros scelerisque est, sit amet sagittis nisl tellus in felis. Nam eget ornare turpis. " +"Sed tempor ac enim a vestibulum. Pellentesque eleifend lacus non libero accumsan, ut consectetur sapien lacinia. " +"Etiam ut arcu non mi feugiat accumsan ut sit amet risus. Donec consequat eros sapien, malesuada imperdiet justo " +"bibendum sit amet. Nulla pretium varius lectus, in eleifend quam fringilla in. Quisque eu pretium velit. Sed eget " +"lectus sit amet tortor blandit tempus vel at sapien. Sed at velit porta, venenatis lorem sed, dapibus arcu. Donec " +"pellentesque tortor id massa interdum pretium. Praesent id diam quis nunc dictum finibus quis quis ipsum. Quisque " +"consectetur risus eu elit viverra, eget laoreet odio efficitur. In congue turpis iaculis ullamcorper bibendum. Duis " +"at elit et velit varius vulputate ut ac turpis. Nunc posuere, urna id lobortis ornare, neque ex ultricies erat, id " +"sollicitudin ante quam sed magna. Nunc ultrices quam erat, eget dictum libero sollicitudin in. Nulla facilisi. " +"Pellentesque eleifend risus non justo imperdiet aliquet. Donec finibus auctor ornare. Duis in arcu lacinia, " +"fermentum tellus vel, efficitur justo. Morbi nec nunc leo. Proin lacinia erat vel elementum dapibus. Proin diam " +"ipsum, mollis eu lobortis a, facilisis consectetur est. Vestibulum rutrum pellentesque urna, a laoreet justo dictum " +"vitae. Nullam dictum, mi elementum dictum interdum, sem nisl fermentum est, nec mattis enim ante aliquam tortor. " +"Phasellus eu quam magna. Vivamus augue enim, dictum in nibh non, condimentum tristique lorem. Suspendisse potenti. " +"Sed nibh lacus, auctor ut arcu sollicitudin, posuere tempor urna. Phasellus at odio euismod ipsum congue auctor. " +"Fusce vestibulum elementum nunc, vel feugiat nibh bibendum at. Quisque felis ligula, fermentum a metus ac, pulvinar " +"hendrerit est. Proin vitae tincidunt purus, vestibulum eleifend ipsum. Ut rhoncus et elit ut varius. Praesent eu " +"pharetra tellus. Suspendisse varius, dui quis efficitur fermentum, est lectus ultricies ex, a fermentum orci nunc eu " +"lorem. Integer aliquet nunc ullamcorper lacinia elementum. In cursus tortor nisi, ut pharetra tortor venenatis eu. " +"Duis tincidunt, libero sed varius dictum, neque velit facilisis enim, eget bibendum mi eros et nisl. Nam turpis " +"neque, lobortis eget ante ac, tristique congue lacus. Aenean dictum vitae tortor sed tristique. Donec sodales in " +"arcu ut tristique. Curabitur in facilisis nisi, non vulputate odio. Phasellus ut fringilla nunc, nec dapibus turpis. " +"Sed ut erat tempor sem vulputate gravida at at dui. Aenean id dolor ante. Morbi auctor interdum nisi, id pretium " +"eros ultrices vel. Nulla eget justo fringilla, finibus quam et, accumsan ex. In nisl neque, pharetra nec volutpat " +"at, mattis nec odio. Nam et sapien sed libero lacinia tempor sit amet vitae turpis. Praesent vel porta lacus, porta " +"dignissim nunc. Aenean vitae vulputate purus. Ut at elit arcu. Integer risus neque, varius ac elit maximus, " +"ultricies sagittis nisi. Pellentesque sapien magna, malesuada tincidunt ornare sed, malesuada tempor odio. Morbi id " +"neque velit. Pellentesque at velit sed elit eleifend auctor. Quisque tincidunt tempus justo, venenatis dapibus sem " +"pellentesque quis. Suspendisse finibus feugiat est id consectetur. Nulla commodo, massa auctor vulputate egestas, " +"arcu massa tincidunt leo, quis ullamcorper sapien augue in nibh. Pellentesque ultrices ligula tincidunt urna " +"fringilla, ac ultricies eros convallis. Ut nec massa diam. Maecenas justo nulla, dapibus id justo sollicitudin, " +"fermentum tempor dui. Vivamus laoreet auctor mi non venenatis. Nulla commodo libero ac ex volutpat tincidunt. Donec " +"vestibulum blandit purus bibendum laoreet. Morbi in porta orci. Nam commodo ex eget diam maximus cursus. Proin " +"bibendum quis felis eget euismod. Praesent neque neque, pulvinar eu sem non, gravida ornare tortor. Ut tortor nisi, " +"suscipit in lectus ac, volutpat pretium nisi. Nam rutrum nec dui quis vulputate. Duis in velit enim. Fusce porttitor " +"vitae nisi a tincidunt. Ut enim purus, venenatis ut purus ut, iaculis dignissim ex. Aliquam erat volutpat. " +"Suspendisse potenti. Maecenas ut malesuada elit. Maecenas tellus neque, pulvinar non metus ut, viverra finibus diam. " +"Sed ac porttitor dui. Fusce sit amet ligula metus. Integer id aliquet libero. Sed tempor nisl in porttitor " +"ultricies. Maecenas molestie orci sed sapien molestie interdum non id felis. Nullam sagittis elementum erat in " +"pretium. Nunc pellentesque, ex sit amet fringilla dignissim, augue quam dictum leo, eget tristique turpis mauris sed " +"metus. Praesent vel mauris risus. Etiam eleifend metus ut risus tempor, ac ultrices dolor dictum. Nulla sagittis non " +"urna vitae feugiat. In venenatis arcu vel finibus volutpat. Nam non bibendum magna, nec eleifend ex. Etiam sit amet " +"nisl euismod, mattis nisi quis, commodo nisl. Nunc eget mauris vulputate, cursus neque in, hendrerit ante. Cras non " +"nisl in nisl laoreet aliquam. Sed vestibulum, nunc vitae molestie varius, lectus justo vehicula est, nec placerat " +"ipsum lectus quis leo. Maecenas efficitur semper eros, sed pretium arcu blandit eu. Aliquam eget purus cursus, " +"sollicitudin augue quis, cursus purus. Maecenas sed finibus ligula. Curabitur at diam quis eros mollis semper. Nulla " +"commodo nisi libero, id feugiat nisl tincidunt bibendum. Mauris convallis tincidunt justo eu sodales. Quisque arcu " +"lacus, finibus sed hendrerit at, convallis ut diam. Nulla enim nulla, efficitur quis tincidunt et, pulvinar sit amet " +"enim. Aenean mattis urna id mauris maximus tincidunt. In hac habitasse platea dictumst. Morbi ornare porta congue. " +"Aliquam hendrerit efficitur mi at aliquet. Vivamus rutrum lectus vel turpis volutpat, consectetur congue sem " +"consectetur. Sed rhoncus elit sed orci tincidunt, ut condimentum diam ornare. Nulla facilisi. Ut placerat et massa " +"nec malesuada. Praesent dapibus condimentum augue, at imperdiet lacus facilisis sed. Praesent at metus nunc. Morbi " +"accumsan eros et turpis viverra, nec sagittis odio iaculis. Aenean rhoncus, nibh a consectetur sodales, massa lorem " +"commodo dui, sit amet consequat ex arcu eget augue. Praesent quis nibh urna. Cras eu congue ligula, in ultricies " +"ante. Etiam interdum, est tincidunt euismod sollicitudin, lectus felis mollis ex, pretium fringilla magna lorem non " +"libero. Fusce aliquam tellus eget sodales commodo. Sed sapien lectus, dapibus quis elit at, ultricies tincidunt " +"eros. Nulla suscipit orci sit amet aliquam pellentesque. Cras sed eleifend ligula, quis vehicula ligula. Integer " +"quis tortor in mauris dictum malesuada sed non turpis. Nulla faucibus quis arcu molestie vulputate. Proin fermentum " +"tellus feugiat, imperdiet mi sit amet, tempor sem. Mauris hendrerit augue a vulputate vulputate. Vivamus sagittis at " +"odio non venenatis. Nunc a molestie dolor. Nunc erat nisi, consequat et tristique in, blandit non tortor. Vivamus " +"euismod bibendum augue, ut aliquam lorem mattis quis. Duis laoreet odio at justo ultricies, nec scelerisque enim " +"euismod. Sed eu turpis a lorem cursus feugiat. Duis ultrices molestie nulla non pharetra. Morbi faucibus est auctor " +"faucibus placerat. Donec blandit quis ex ac pulvinar. Vestibulum a consequat quam. Fusce vitae facilisis ex. Etiam a " +"risus eu orci tincidunt interdum. Proin interdum eros nec nibh venenatis, sed luctus sapien tincidunt. In cursus, " +"ante nec dapibus bibendum, augue tortor venenatis felis, eu aliquam erat est vitae diam. Cras lacinia placerat quam, " +"eu finibus purus. Aenean et augue purus. Praesent efficitur ornare magna in cursus. Nunc quis tempor ante, ac " +"accumsan ligula. Nullam elit diam, tempus in sollicitudin at, fermentum tincidunt mi. Vestibulum accumsan, nisi at " +"rutrum scelerisque, justo mauris cursus nulla, finibus cursus nulla elit quis augue. Aliquam lacus ante, ullamcorper " +"quis varius vitae, ullamcorper eget magna. Phasellus mollis nisl eu nulla eleifend, non tempus tellus faucibus. " +"Curabitur molestie eros id eleifend accumsan. Suspendisse tristique sem ante, non blandit eros accumsan ac. Ut sit " +"amet ante justo. Nam condimentum felis quis urna sagittis hendrerit. Cras condimentum est ac massa aliquet finibus. " +"Donec faucibus malesuada fermentum. Aliquam malesuada augue vitae dolor rutrum pellentesque. Nullam vulputate " +"rhoncus porta. Quisque vulputate dignissim felis sit amet aliquet. Nam elementum odio velit, eget fringilla mi " +"dignissim at. Mauris mollis diam orci, vel porta risus tempor a. Nullam quis dolor volutpat, ornare est at, " +"fermentum urna. Fusce mollis nisl a augue condimentum, eu dictum dolor posuere. Mauris et egestas sem. Sed pretium " +"lectus laoreet velit feugiat luctus. Nullam sodales at augue vel semper. Pellentesque vehicula dictum augue, eget " +"tristique orci interdum a. Aenean non est eleifend, tristique urna sed, elementum nunc. Sed consectetur id lorem " +"quis mollis. Ut et blandit velit, et lobortis dolor. Quisque nec odio sed mi ullamcorper pellentesque. Ut vitae " +"eleifend nisi, vitae dapibus est. Vivamus ornare eleifend volutpat. Sed et tincidunt nisi. Praesent maximus risus a " +"bibendum consequat. Vestibulum quis ex vitae ante ultricies ultricies. Maecenas dictum tellus eget enim tincidunt " +"imperdiet. Quisque vel libero gravida, mollis erat id, placerat dolor. Etiam ante eros, bibendum vitae ultricies in, " +"rhoncus nec turpis. Pellentesque gravida nunc sit amet iaculis condimentum. Phasellus in ultricies libero, et " +"maximus justo. Donec ut ultrices elit. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque " +"rhoncus, nunc at iaculis dictum, magna lectus rhoncus augue, vel aliquam sem mauris in metus. Morbi commodo purus " +"mi, ut faucibus dui luctus et. Suspendisse accumsan placerat tortor. Cras dignissim blandit leo, non tincidunt leo. " +"Nulla euismod turpis ac malesuada aliquam. Ut ultrices bibendum elit sed elementum. Donec auctor aliquam vehicula. " +"Mauris lacinia dignissim leo, ullamcorper egestas nibh rutrum eget. In semper sit amet libero eget ultricies. Proin " +"et imperdiet odio. In hac habitasse platea dictumst. In hac habitasse platea dictumst. Integer sed dolor quis tortor " +"pretium euismod at vel dolor. Donec aliquet et urna at porta. Vestibulum tincidunt eget sapien elementum mattis. " +"Proin lacinia faucibus orci, sed eleifend augue mollis et. Vestibulum ante ipsum primis in faucibus orci luctus et " +"ultrices posuere cubilia Curae; Cras pellentesque, dolor eget bibendum tincidunt, turpis ante pharetra tortor, quis " +"interdum tellus tellus sit amet nisl. Nulla convallis tempus egestas. Curabitur quis condimentum metus, eu placerat " +"metus. Nunc ligula nunc, posuere at iaculis nec, convallis id tellus. Curabitur pretium libero lorem, quis placerat " +"nunc fringilla interdum. Vestibulum et finibus ante. Duis quis nisi neque. Curabitur ornare lorem nec ex fringilla, " +"et porta massa consequat. Nulla malesuada turpis nec eleifend tincidunt. Praesent ultricies dolor vitae mauris " +"lacinia tempor. Sed blandit sapien a odio scelerisque consequat. Mauris non dictum eros. Vestibulum ante ipsum " +"primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque habitant morbi tristique senectus et " +"netus et malesuada fames ac turpis egestas. In ut sollicitudin tellus. Suspendisse ultrices vitae erat non pharetra. " +"Nulla pellentesque at diam venenatis sollicitudin. Vestibulum sed finibus sapien. Curabitur a metus convallis, " +"euismod est id, iaculis nunc. Vestibulum laoreet ornare turpis. Integer rhoncus, felis nec fermentum suscipit, dui " +"lacus sagittis ligula, vitae vestibulum urna elit aliquam est. Sed sit amet mi tortor. Suspendisse a dapibus velit. " +"Cras eget imperdiet turpis. Maecenas at lorem condimentum, elementum augue mattis, rutrum purus. Duis imperdiet " +"pellentesque nunc, eu tristique lectus malesuada commodo. Vivamus aliquet congue eros ac dapibus. Nunc quis " +"porttitor odio. Nulla quis dui luctus, vestibulum enim malesuada, imperdiet elit. Donec facilisis mollis diam ut " +"posuere. Nulla facilisi. Duis nec magna lacus. Vestibulum consequat ut tortor ut ornare. Curabitur nec felis sit " +"amet dui finibus rutrum. Phasellus sit amet lectus nec nisl egestas posuere. Etiam nec euismod magna, vitae " +"ullamcorper enim. Vestibulum pretium cursus semper. Cras vel lorem ut urna molestie elementum. Mauris luctus vel " +"arcu quis egestas. Suspendisse potenti. Nullam viverra sollicitudin lacus luctus sodales. Maecenas eget diam cursus " +"quam tincidunt ultricies vitae nec lacus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec urna " +"sapien, porta a efficitur vitae, imperdiet vel ligula. Nulla volutpat massa sit amet est aliquet, ut iaculis tellus " +"convallis. Sed justo tortor, sodales non nisi quis, laoreet commodo quam. Cras tempus purus a tempor malesuada. " +"Curabitur enim nibh, viverra in enim eget, viverra euismod nunc. Mauris nunc leo, faucibus blandit condimentum nec, " +"rutrum sit amet leo. Quisque nec tortor sed felis pretium imperdiet. Morbi lobortis, dolor nec lobortis maximus, " +"turpis justo aliquet massa, eget aliquet nunc mauris a lectus. Phasellus dignissim, est nec luctus consequat, ex " +"nisi euismod lacus, a viverra nulla eros et est. Suspendisse in egestas dolor. Etiam non placerat lorem. " +"Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam ut enim " +"tristique, porta nulla quis, placerat eros. Integer eget feugiat mi, ac condimentum felis. Fusce auctor ligula ut " +"est placerat efficitur. Nam hendrerit condimentum ante eget tincidunt. Phasellus vel convallis neque. Vivamus sit " +"amet elit eu enim iaculis scelerisque. Donec imperdiet lacus id magna luctus, vitae dapibus quam condimentum. Donec " +"laoreet vehicula tellus. Nullam nec neque at massa ultricies dignissim. Suspendisse potenti. Cras convallis nunc " +"urna, a tempor metus volutpat ut. Fusce viverra lorem vitae quam ullamcorper cursus. Mauris maximus et mi eget " +"tincidunt. Proin molestie suscipit felis at ultricies. Duis varius rhoncus metus vehicula bibendum. Aliquam " +"consequat non tellus at aliquam. Vivamus nec turpis facilisis, dapibus lacus in, congue tortor. Curabitur at " +"interdum mi, sed rhoncus nibh. Morbi facilisis purus laoreet, tincidunt justo sit amet, elementum lectus. Vestibulum " +"pellentesque sem lacus, in condimentum purus consequat at. Integer pharetra rhoncus aliquam. Duis nec sem ac elit " +"suscipit laoreet. Integer vel est commodo, feugiat sapien eget, cursus quam. Aenean elit leo, interdum a posuere " +"nec, laoreet eu magna. Nam sit amet felis faucibus, porttitor justo eget, commodo mi. Maecenas a eleifend nibh. " +"Donec ut ornare augue. Aliquam pellentesque aliquet eros in hendrerit. Nullam consectetur odio id lectus ullamcorper " +"facilisis. Donec pulvinar, magna non sollicitudin commodo, erat lacus egestas massa, a egestas nibh nulla ac lorem. " +"Maecenas at mi posuere, fringilla lectus sed, fringilla eros. Vivamus mattis at magna ac suscipit. Proin varius mi a " +"quam efficitur ullamcorper. Curabitur venenatis turpis lacus, vitae volutpat velit ultricies sed. Sed faucibus id " +"neque in consequat. Nulla imperdiet fermentum placerat. Donec rutrum libero ac lorem commodo pellentesque in tempor " +"augue. Maecenas sodales cursus ex, ac elementum felis consectetur vel. Cras ante nulla, porttitor nec ex non, " +"venenatis consectetur justo. Nam vitae enim eget augue euismod suscipit et in nulla. Morbi eu sollicitudin libero, " +"ut lobortis purus. Pellentesque sodales tempor diam, a luctus dui vehicula tempus. Cum sociis natoque penatibus et " +"magnis dis parturient montes, nascetur ridiculus mus. Vestibulum dignissim sagittis diam ac aliquam. Integer iaculis " +"ac est eu molestie. Vivamus convallis arcu nec rutrum molestie. Vestibulum mollis ipsum neque. Vestibulum " +"condimentum neque quis tellus elementum, in facilisis neque venenatis. Donec quis ultrices risus. Cras mattis felis " +"eget erat iaculis, id scelerisque mauris pharetra. Vivamus condimentum tempor ipsum, porta commodo erat dictum ut. " +"Fusce et ligula sed arcu tincidunt efficitur nec ut felis. Donec eu justo pellentesque, finibus diam quis, iaculis " +"erat. Fusce a tempus urna, at fermentum est. Sed pretium orci dapibus ante laoreet, a consequat erat scelerisque. " +"Etiam nisi tortor, vulputate quis sapien sit amet, lobortis blandit felis. Morbi urna purus, pellentesque quis orci " +"id, suscipit consequat velit. Donec vehicula ipsum felis. Donec at elit ipsum. Fusce purus sapien, convallis quis " +"faucibus et, tempus at dolor. Vivamus commodo sem ac congue imperdiet. Vivamus convallis eget est eu vulputate. " +"Aliquam vehicula augue ac urna imperdiet interdum. Praesent euismod arcu quis purus vestibulum, et placerat metus " +"hendrerit. Fusce semper lacus sit amet ligula scelerisque scelerisque. Vestibulum neque ex, aliquam non lorem a, " +"aliquam fringilla enim. Aenean consectetur vestibulum tortor. Donec et elit consectetur, tincidunt augue feugiat, " +"condimentum diam. In luctus tellus at massa euismod faucibus. Ut tempus dui hendrerit, vehicula ex ut, facilisis " +"lacus. Pellentesque bibendum enim auctor, vulputate justo vel, ultricies est. Praesent interdum turpis in convallis " +"luctus. Duis vel enim venenatis, mollis elit vitae, mattis velit. In eu posuere nibh. Duis a est est. Nam semper " +"tincidunt nulla id dignissim. Fusce consectetur maximus eros quis posuere. Sed efficitur, enim quis ultrices " +"eleifend, est diam commodo dui, nec euismod augue velit sit amet ante. Integer fringilla vehicula faucibus. " +"Curabitur non placerat turpis. Integer malesuada quam eget sapien tristique aliquet. In hac habitasse platea " +"dictumst. Cras dignissim mauris neque, in facilisis nulla pulvinar ac. Phasellus sagittis ligula non sem aliquet " +"iaculis. Integer interdum elit in dolor vehicula, non condimentum justo pretium. Aliquam eget feugiat tellus. " +"Suspendisse condimentum dui at erat elementum semper. Aliquam vitae cursus lorem. Ut vestibulum porttitor purus ut " +"dapibus. Curabitur posuere nunc quis nisi rhoncus, ac mollis enim eleifend. Aenean tristique at justo ut tempor. " +"Proin posuere condimentum arcu ac lobortis. Proin euismod posuere ipsum, nec dignissim velit eleifend gravida. " +"Quisque quis sem mi. Proin scelerisque consequat lectus nec sodales. Fusce id sapien a erat cursus sodales. Morbi ac " +"magna vitae lorem dictum luctus in et lacus. Morbi imperdiet mi interdum, molestie sem in, accumsan leo. Sed lacinia " +"enim et sem egestas, a pulvinar velit ullamcorper. Aenean laoreet, erat eu viverra dictum, eros odio venenatis mi, " +"tincidunt blandit odio mauris id augue. Donec pretium mauris nibh, ut eleifend velit auctor vitae. Morbi tincidunt " +"lacus id ullamcorper egestas. Proin vel porttitor purus, eu fermentum dui. Aliquam a interdum mi. Aliquam ut rhoncus " +"nibh. Morbi nulla libero, commodo quis eros eu, scelerisque gravida ligula. Aliquam sed arcu nunc. Sed egestas " +"hendrerit orci, nec rhoncus arcu fringilla quis. Pellentesque lobortis nulla arcu. Integer aliquam vel quam sed " +"tempor. Morbi viverra tempus risus vel convallis. Cras eget neque ex. Mauris porta, risus at rhoncus hendrerit, " +"libero metus pharetra sapien, quis viverra tortor nunc tincidunt magna. Aenean a tellus ullamcorper, convallis urna " +"quis, suscipit sem. Vivamus eu eleifend est. Duis venenatis metus eget ex consequat molestie. In ullamcorper a dolor " +"vitae feugiat. Morbi ultrices vestibulum venenatis. Phasellus luctus enim id aliquet pharetra. Aenean mauris felis, " +"finibus eu dolor at, tempor sodales diam. Sed nisl nibh, tincidunt quis fringilla vel, congue eu dui. Duis viverra " +"justo eu sem ultricies dignissim. Morbi et sollicitudin erat. Proin id porttitor odio, et sagittis ex. Aenean " +"laoreet leo sit amet risus vestibulum, mollis ultrices tortor porttitor. Sed vestibulum varius ligula quis accumsan. " +"Duis fermentum, dolor iaculis condimentum tincidunt, purus nunc bibendum nibh, ac sodales tortor odio non ante. Sed " +"leo mauris, consequat molestie quam eu, vulputate volutpat metus. Cras fringilla risus sed arcu consequat luctus. " +"Nam malesuada, turpis at luctus blandit, velit elit fringilla metus, eu mollis odio felis id tortor. Aliquam erat " +"tellus, pulvinar nec iaculis et, consequat sit amet diam. Sed vestibulum, leo ut vehicula suscipit, quam justo " +"maximus lectus, nec lobortis urna tortor nec nisi. Vestibulum eget ornare arcu, sed viverra turpis. Sed posuere " +"tellus iaculis, scelerisque dui id, convallis lectus. Aliquam sodales at mi consectetur dignissim. In fringilla, " +"urna id placerat mattis, diam magna commodo dui, at elementum arcu elit et libero. Duis venenatis vulputate nisl " +"congue pharetra. Fusce sapien velit, cursus a consectetur quis, auctor gravida sem. Maecenas malesuada metus quis " +"elit congue accumsan. Vivamus scelerisque euismod malesuada. Vestibulum purus metus, tempor eget faucibus a, cursus " +"eu arcu. Morbi dictum urna vitae velit pellentesque facilisis. Sed arcu est, tempor ac turpis sit amet, ultricies " +"venenatis augue. Nunc laoreet leo gravida facilisis dapibus. Aliquam convallis ullamcorper felis, sit amet tempor " +"libero euismod sit amet. Quisque leo augue, finibus et euismod non, venenatis sed libero. Cras pharetra rhoncus " +"odio, in pharetra lacus porttitor scelerisque. Maecenas eleifend felis vitae diam blandit viverra. Fusce at " +"ultricies arcu, pharetra finibus enim. Etiam pellentesque semper ligula, sed tincidunt purus. Sed fermentum metus " +"varius, aliquet libero eget, vehicula erat. Sed ac finibus metus. Pellentesque libero leo, semper et eros nec, " +"gravida condimentum urna. Cras nec turpis convallis, efficitur lacus at, ultricies ex. Fusce eu neque elementum leo " +"gravida semper. Duis sed tellus vitae magna fringilla maximus ac ut nisl. Integer id ligula ullamcorper, ultricies " +"quam sit amet, ullamcorper diam. Maecenas rhoncus nulla eu dui vulputate scelerisque. Vestibulum porttitor eget nibh " +"a mattis. Mauris tempus at urna blandit dignissim. Proin turpis leo, mattis ut turpis eget, aliquet tempor ante. " +"Nunc in mollis nunc, et interdum nisi. Cras tristique sollicitudin tortor sit amet ultrices. Proin rhoncus neque " +"urna. Maecenas bibendum, massa sit amet suscipit suscipit, justo tortor maximus dolor, posuere facilisis nisi tellus " +"elementum diam. Quisque id eros vel lectus malesuada tincidunt. Donec at orci ac ligula venenatis dignissim sit amet " +"nec purus. Sed eu neque finibus, tristique ex a, feugiat ante. Pellentesque tincidunt luctus mollis. Nullam blandit " +"faucibus gravida. Ut sit amet malesuada nibh, vel tincidunt ipsum. Donec suscipit lorem in dui luctus, viverra " +"imperdiet magna placerat. Pellentesque venenatis eros quis urna efficitur facilisis. Cras ligula magna, tempus " +"facilisis tincidunt at, varius quis lectus. Sed quam neque, facilisis vel facilisis vel, lobortis ac orci. Nullam " +"pretium interdum erat ac ultrices. Etiam enim mauris, vehicula nec rhoncus quis, volutpat vel erat. Morbi imperdiet " +"rhoncus rutrum. Nullam auctor condimentum diam nec faucibus. Etiam sit amet porta nulla, sit amet lobortis enim. " +"Aenean tincidunt condimentum accumsan. Vestibulum mollis diam risus, vitae ornare enim iaculis non. Nullam vitae " +"risus tristique, imperdiet augue ut, egestas dolor. Sed sit amet leo eu diam commodo vestibulum id in dolor. Vivamus " +"tristique molestie faucibus. Duis tempor porttitor turpis ac consectetur. Curabitur condimentum, ipsum eu dignissim " +"semper, ipsum erat pretium quam, ut maximus erat ligula eu felis. Sed viverra, mauris id tempus tempor, nisi leo " +"consectetur arcu, ac vulputate lorem mauris non sapien. Maecenas rhoncus magna mauris, in luctus nulla dapibus at. " +"Sed magna est, ultrices sit amet erat nec, dapibus lacinia massa. Morbi cursus ex in elit auctor egestas. Quisque id " +"placerat nibh, at mollis tortor. Proin fringilla sodales sapien, ac ullamcorper sem bibendum eget. Donec dui ligula, " +"viverra eget leo ac, tincidunt fringilla mauris. Quisque vel lectus eget metus feugiat laoreet. Morbi eget " +"vestibulum enim, ac ultricies lorem. Nam at mollis magna. Etiam vitae orci eu leo facilisis vestibulum. Ut sed " +"turpis ut nibh iaculis rhoncus. Phasellus sit amet risus pellentesque, gravida eros a, porta nibh. Suspendisse at " +"tincidunt ligula. Vivamus id libero diam. Morbi viverra ipsum turpis, in ullamcorper enim pellentesque nec. Sed " +"ultricies, lectus quis pellentesque sodales, arcu diam commodo massa, a vestibulum purus sapien eget risus. Duis " +"rhoncus in velit in dignissim. Aliquam sit amet metus in quam finibus cursus. Pellentesque eget aliquam justo. Fusce " +"imperdiet, tellus non venenatis facilisis, diam mi lobortis dolor, at consectetur est massa id elit. Vivamus ante " +"ex, faucibus et mollis eget, dignissim vel massa. Duis ultricies diam commodo purus facilisis pharetra. Curabitur " +"pretium massa sed enim vehicula, id vehicula neque vehicula. In quis lectus non mauris pulvinar fermentum. Aliquam " +"condimentum aliquet dui et congue. Maecenas quis augue eget leo gravida aliquet. Praesent sit amet fermentum odio, " +"ut placerat nulla. Curabitur sit amet iaculis erat, eu volutpat odio. Ut iaculis ex quis tempus commodo. " +"Pellentesque cursus eros at velit vulputate, id luctus massa pretium. Morbi ex dui, sodales id finibus id, aliquet a " +"justo. Maecenas semper leo eget dolor rutrum, at imperdiet nibh eleifend. Aliquam eget purus tortor. Cras rutrum " +"tortor massa, vel bibendum nunc aliquam vel. Nullam vestibulum, metus vel fermentum elementum, nulla sapien egestas " +"justo, ac feugiat ex justo nec eros. Donec sit amet nibh mollis, commodo quam sit amet, semper magna. In tortor " +"magna, elementum nec auctor sed, pellentesque at augue. Sed gravida arcu ac aliquet convallis. Nulla facilisi. Duis " +"nunc quam, gravida non interdum id, cursus ac leo. Suspendisse vel ipsum nisl. Aliquam at gravida libero. Maecenas " +"sit amet efficitur orci. Fusce id vehicula sapien. Proin euismod diam non laoreet ultricies. Nunc ullamcorper, nibh " +"id cursus vehicula, ex purus tempor urna, et euismod orci est sed elit. Duis ut blandit mauris. Ut blandit cursus " +"eros, sed laoreet nisl efficitur ac. Phasellus dui elit, fringilla sit amet cursus nec, pharetra quis odio. Ut ut " +"lorem sit amet sem dapibus accumsan. Aenean a laoreet dolor. Donec eu laoreet velit. Etiam id nisi vel nibh dapibus " +"congue a quis odio. Donec velit risus, semper quis porta non, elementum quis lorem. Interdum et malesuada fames ac " +"ante ipsum primis in faucibus. Nullam sit amet dolor magna. Maecenas quis sapien sit amet est pulvinar lobortis " +"efficitur cursus orci. Phasellus tristique mauris lorem, eu ultricies justo ornare condimentum. Integer urna enim, " +"lobortis id malesuada ut, mattis eget libero. Sed commodo tincidunt eleifend. Fusce sed velit ut dui pellentesque " +"pellentesque eget vel diam. Aenean nec turpis at tortor consectetur consectetur. Vestibulum ultrices elit at nisl " +"pellentesque molestie. Maecenas diam dolor, faucibus eget posuere ut, sodales ut eros. Nam vulputate mollis diam nec " +"gravida. Nam et ullamcorper diam. Aenean non nulla non lorem ullamcorper sagittis non quis erat. Pellentesque " +"habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In hac habitasse platea dictumst. " +"Donec quis mauris ac nibh vestibulum eleifend placerat sed lacus. Suspendisse mi elit, viverra non velit ut, " +"tincidunt tempus felis. Fusce ullamcorper, arcu nec aliquet porttitor, odio lacus mollis mi, id malesuada tortor " +"velit aliquet turpis. Sed hendrerit felis nec faucibus ornare. Nulla ut metus eget augue malesuada posuere eget eu " +"tortor. Cras ultrices odio sit amet porttitor vehicula. Sed vulputate leo vitae justo viverra, nec volutpat eros " +"consectetur. Nunc nunc tellus, porta in arcu in, vulputate ultricies tellus. Fusce commodo efficitur lorem, sit amet " +"lacinia sapien sollicitudin at. Etiam aliquet non mi vitae ornare. Cras condimentum imperdiet elit eu dictum. Donec " +"sed enim sed massa tempor porta et sit amet felis. Nam interdum ornare sem, in tincidunt risus consectetur vel. Ut " +"convallis purus mauris, in consequat ligula ullamcorper ut. Quisque elit ipsum, accumsan eget ligula vitae, " +"sollicitudin luctus tellus. Nunc pretium turpis ligula, id dignissim lorem suscipit eu. Nulla facilisi. Sed lectus " +"odio, vehicula vel vulputate id, ultrices non ipsum. Donec arcu quam, consequat eget aliquet sit amet, ullamcorper " +"non nibh. Etiam finibus, mi id lobortis sagittis, leo leo lobortis lectus, sit amet aliquam dui odio sit amet massa. " +"Suspendisse iaculis urna ac lectus gravida, iaculis efficitur tellus hendrerit. Sed tellus enim, condimentum in " +"augue eget, sagittis ullamcorper sem. Suspendisse vitae aliquet libero. Aenean quis purus in sapien dapibus " +"suscipit. Sed commodo nunc in lacus bibendum, vel tincidunt ante ornare. Ut tristique luctus volutpat. Class aptent " +"taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque a ultricies orci, eu porta " +"odio. Vivamus sapien arcu, ultrices vel dui ut, luctus viverra purus. Praesent fringilla sed odio quis pretium. " +"Vestibulum ullamcorper nisi tortor, id sollicitudin lectus tempor a. Ut malesuada sapien eu sapien posuere, non " +"euismod eros porta. Nunc vel tincidunt ligula. Cras dolor ante, tristique tempor metus quis, mollis vulputate orci. " +"Curabitur vitae nisl euismod, elementum purus vel, dictum lorem. Nunc eu mauris at metus porttitor dignissim ut eu " +"neque. In tempor rhoncus neque sit amet commodo. Maecenas sed lacus semper, tempus enim ac, fermentum lorem. Nullam " +"sollicitudin convallis turpis. Curabitur finibus placerat viverra. Pellentesque convallis condimentum tortor id " +"efficitur. Proin semper pretium est, et vehicula ex cursus a. Nam ut felis purus. Phasellus eget felis eget leo " +"dapibus vestibulum. Nulla eleifend malesuada turpis, quis faucibus eros. Nam aliquet euismod viverra. Ut quis semper " +"felis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque at nulla " +"arcu. Integer ut tellus ac sapien maximus tincidunt sed vitae risus. Nulla viverra, nibh eget eleifend aliquam, quam " +"quam tempor massa, eu semper ipsum lacus in turpis. Nulla sed purus enim. Nullam sed fermentum ipsum. Sed dui nisi, " +"elementum a auctor at, ultrices et nibh. Phasellus aliquam nulla ut lacinia accumsan. Phasellus sed arcu ligula. " +"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam fermentum magna vitae dui sagittis tempor. Vivamus " +"eu ligula blandit, imperdiet arcu at, rutrum sem. Aliquam erat volutpat. Quisque luctus enim quis volutpat lobortis. " +"Vestibulum eget sodales libero. Aenean at condimentum est. Proin eget massa vel nulla efficitur tempor eget at enim. " +"Integer enim sapien, ornare luctus nisl non, pretium facilisis ex. Donec pretium ligula ligula, a facilisis turpis " +"hendrerit at. Nullam eget malesuada justo, at molestie quam. Sed consequat massa eu faucibus maximus. Curabitur " +"placerat orci sapien, sit amet semper magna sodales non. Ut fermentum accumsan odio in consectetur. Morbi neque mi, " +"vulputate nec mi ut, cursus scelerisque lectus. Nulla sapien enim, finibus id ipsum luctus, consequat ullamcorper " +"lectus. Sed volutpat sed massa in sodales. Morbi lacinia diam eu commodo vulputate. Fusce aliquet pulvinar dolor in " +"egestas. Fusce molestie commodo leo eu ultricies. Nulla mollis rhoncus pharetra. Pellentesque rutrum mauris ac lorem " +"posuere, a eleifend mi rutrum. Nulla porta turpis aliquet felis congue rutrum. Fusce quis arcu in sem placerat " +"condimentum a ut turpis. Quisque quis porttitor nulla. Donec sit amet quam tincidunt, pulvinar erat id, molestie " +"dolor. Praesent luctus vitae nunc vitae pellentesque. Praesent faucibus sed urna ut lacinia. Vivamus id justo quis " +"dolor porta rutrum nec nec odio. Cras euismod tortor quis diam ultrices, eu mattis nisi consectetur. Fusce mattis " +"nisi vel condimentum molestie. Fusce fringilla ut nibh volutpat elementum. Mauris posuere consectetur leo a aliquet. " +"Donec quis sodales sapien. Maecenas ut felis tempus, eleifend mauris et, faucibus mi. Quisque fringilla orci arcu, " +"sit amet porta risus hendrerit non. Aenean id sem nisi. Nullam non nisl vestibulum, pellentesque nisl et, imperdiet " +"ligula. Sed laoreet fringilla felis. Proin ac dolor viverra tellus mollis aliquet eget et neque. Suspendisse mattis " +"nulla vitae nulla sagittis blandit. Sed at tortor rutrum, ornare magna nec, pellentesque nisi. Etiam non aliquet " +"tellus. Aliquam at ex suscipit, posuere sem sit amet, tincidunt."; + +#endif /* __BLENDER_TESTING_BLI_RESSOURCE_STRING_H__ */ diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt index 3a86d3f770d..152b65617a4 100644 --- a/tests/gtests/blenlib/CMakeLists.txt +++ b/tests/gtests/blenlib/CMakeLists.txt @@ -43,3 +43,6 @@ BLENDER_TEST(BLI_path_util "bf_blenlib;extern_wcwidth;${ZLIB_LIBRARIES}") BLENDER_TEST(BLI_polyfill2d "bf_blenlib") BLENDER_TEST(BLI_listbase "bf_blenlib") BLENDER_TEST(BLI_hash_mm2a "bf_blenlib") +BLENDER_TEST(BLI_ghash "bf_blenlib") + +BLENDER_TEST(BLI_ghash_performance "bf_blenlib") -- cgit v1.2.3 From bd1e5eeab7a8459755b59672f494609f84ab8302 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 19 Mar 2015 20:04:55 +0100 Subject: Blender will now use trilinear filtering by default --- source/blender/windowmanager/intern/wm_init_exit.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 9778f1651de..32a49b6e160 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -199,6 +199,7 @@ void WM_init(bContext *C, int argc, const char **argv) GPU_init(); GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); + GPU_set_linear_mipmap(true); GPU_set_anisotropic(U.anisotropic_filter); GPU_set_gpu_mipmapping(U.use_gpu_mipmap); -- cgit v1.2.3 From eee538f0d262a430cc622bfe17eef7dba9b251c7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 20 Mar 2015 04:00:05 +1100 Subject: UI: minor re-organization of dof options --- release/scripts/startup/bl_ui/properties_data_camera.py | 10 ++++++---- source/blender/makesrna/intern/rna_scene.c | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py index 2097e82f992..6a0d680df53 100644 --- a/release/scripts/startup/bl_ui/properties_data_camera.py +++ b/release/scripts/startup/bl_ui/properties_data_camera.py @@ -184,16 +184,18 @@ class DATA_PT_camera_dof(CameraButtonsPanel, Panel): col = split.column() col.label(text="Focus:") col.prop(cam, "dof_object", text="") + col.prop(dof_options, "use_high_quality") col = split.column() col.prop(dof_options, "fstop") - col.prop(dof_options, "high_quality") - if dof_options.high_quality: - col.prop(dof_options, "num_blades") + sub = col.column() - sub.active = cam.dof_object is None + sub.active = (cam.dof_object is None) sub.prop(cam, "dof_distance", text="Distance") + if dof_options.use_high_quality: + col.prop(dof_options, "blades") + class DATA_PT_camera_display(CameraButtonsPanel, Panel): bl_label = "Display" diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 4214c830e4c..2e941487e98 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -3922,13 +3922,14 @@ static void rna_def_gpu_dof_fx(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.1f, 128.0f, 10, 1); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - prop = RNA_def_property(srna, "num_blades", PROP_INT, PROP_NONE); + prop = RNA_def_property(srna, "blades", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "num_blades"); RNA_def_property_ui_text(prop, "Viewport Camera Blades", "Blades for dof effect"); RNA_def_property_range(prop, 0, 16); RNA_def_property_int_funcs(prop, NULL, "rna_GPUDOFSettings_blades_set", NULL); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - prop = RNA_def_property(srna, "high_quality", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_high_quality", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "high_quality", 1); RNA_def_property_ui_text(prop, "High Quality", "Use high quality depth of field"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); -- cgit v1.2.3 From 81472aff2be5a8059e046436b4d1810659032716 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 20 Mar 2015 06:07:22 +1100 Subject: Remove deleted list for palette colors was used because of UI memory access only. --- source/blender/blenkernel/BKE_paint.h | 2 -- source/blender/blenkernel/intern/paint.c | 21 ++------------------- source/blender/blenloader/intern/readfile.c | 1 - .../blender/editors/interface/interface_handlers.c | 6 ++++++ .../blender/editors/interface/interface_templates.c | 3 --- source/blender/makesdna/DNA_brush_types.h | 1 - source/blender/makesrna/intern/rna_palette.c | 2 +- 7 files changed, 9 insertions(+), 27 deletions(-) diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 58c0b495062..9076eada312 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -102,9 +102,7 @@ void BKE_palette_free(struct Palette *palette); struct Palette *BKE_palette_add(struct Main *bmain, const char *name); struct PaletteColor *BKE_palette_color_add(struct Palette *palette); bool BKE_palette_is_empty(const struct Palette *palette); -void BKE_palette_color_remove_ex(struct Palette *palette, struct PaletteColor *color, bool use_free); void BKE_palette_color_remove(struct Palette *palette, struct PaletteColor *color); -void BKE_palette_cleanup(struct Palette *palette); void BKE_palette_clear(struct Palette *palette); /* paint curves */ diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 2082066d395..c3c88389e11 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -314,7 +314,7 @@ void BKE_paint_curve_set(Brush *br, PaintCurve *pc) } /* remove colour from palette. Must be certain color is inside the palette! */ -void BKE_palette_color_remove_ex(Palette *palette, PaletteColor *color, bool use_free) +void BKE_palette_color_remove(Palette *palette, PaletteColor *color) { if (BLI_listbase_count_ex(&palette->colors, palette->active_color) == palette->active_color) { palette->active_color--; @@ -326,32 +326,15 @@ void BKE_palette_color_remove_ex(Palette *palette, PaletteColor *color, bool use palette->active_color = 0; } - if (use_free) { - MEM_freeN(color); - } - else { - BLI_addhead(&palette->deleted, color); - } -} - -void BKE_palette_color_remove(Palette *palette, PaletteColor *color) -{ - BKE_palette_color_remove_ex(palette, color, false); + MEM_freeN(color); } void BKE_palette_clear(Palette *palette) { BLI_freelistN(&palette->colors); - BLI_freelistN(&palette->deleted); palette->active_color = 0; } -void BKE_palette_cleanup(Palette *palette) -{ - BLI_freelistN(&palette->deleted); -} - - Palette *BKE_palette_add(Main *bmain, const char *name) { Palette *palette; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 6b4d45a85dc..639ee646a67 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1950,7 +1950,6 @@ static void direct_link_palette(FileData *fd, Palette *palette) { /* palette itself has been read */ link_list(fd, &palette->colors); - BLI_listbase_clear(&palette->deleted); } static void lib_link_paint_curve(FileData *UNUSED(fd), Main *main) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index a6ff5bb3ad3..71b7b95208b 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -4494,6 +4494,12 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co BKE_palette_color_remove(palette, color); button_activate_state(C, but, BUTTON_STATE_EXIT); + + /* this is risky. it works OK for now, + * but if it gives trouble we should delay execution */ + but->rnapoin = PointerRNA_NULL; + but->rnaprop = NULL; + return WM_UI_HANDLER_BREAK; } } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index b3c31a1a644..7db734ee919 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2398,9 +2398,6 @@ void uiTemplatePalette(uiLayout *layout, PointerRNA *ptr, const char *propname, palette = cptr.data; - /* first delete any pending colors */ - BKE_palette_cleanup(palette); - color = palette->colors.first; col = uiLayoutColumn(layout, true); diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 89c8316002b..dd66acf2781 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -151,7 +151,6 @@ typedef struct Palette /* pointer to individual colours */ ListBase colors; - ListBase deleted; int active_color; int pad; diff --git a/source/blender/makesrna/intern/rna_palette.c b/source/blender/makesrna/intern/rna_palette.c index 7405df967a0..8cbb57fde2c 100644 --- a/source/blender/makesrna/intern/rna_palette.c +++ b/source/blender/makesrna/intern/rna_palette.c @@ -55,7 +55,7 @@ static void rna_Palette_color_remove(Palette *palette, ReportList *reports, Poin return; } - BKE_palette_color_remove_ex(palette, color, true); + BKE_palette_color_remove(palette, color); RNA_POINTER_INVALIDATE(color_ptr); } -- cgit v1.2.3 From ea12b87afdb3c57bba2dbf8ba6bf457f83dc8dd0 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 19 Mar 2015 20:48:43 +0100 Subject: Fix cycles dof settings --- intern/cycles/blender/addon/ui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index b0337a69e7d..6b7e03320bc 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -459,7 +459,7 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel): col.prop(dof_options, "fstop") col.prop(dof_options, "high_quality") if dof_options.high_quality: - col.prop(dof_options, "num_blades") + col.prop(dof_options, "blades") col = split.column() -- cgit v1.2.3 From 05e3c261a44b42181aadc8af9d603db2cb721b20 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 19 Mar 2015 20:47:38 +0100 Subject: Fix T43989: Sequencer - Ctrl snapping a sequencer strip does not work if you specify the x axis. New 'strip' snapping was simply not computed in case of constrained transform, hence init '0' value was used as frame offset in this case. This commit reorganizes a bit that snapping, to keep it more 'confined' into `snapSequenceBounds()` dedicated function. It still needs a minor hack (setting snapping mode to something else than defualt `SCE_SNAP_MODE_INCREMENT`, to avoid this snapping to be called by contraint code). Thanks to Antony for review and enhancements. This fix should be backported to 2.74. --- source/blender/editors/transform/transform.c | 25 ++++++----------------- source/blender/editors/transform/transform.h | 2 +- source/blender/editors/transform/transform_snap.c | 11 +++++++--- 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index b562eb2e5f1..f4cb8f724bb 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -7311,40 +7311,28 @@ static void headerSeqSlide(TransInfo *t, const float val[2], char str[MAX_INFO_L WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0)); } -static void applySeqSlideValue(TransInfo *t, const float val[2], int frame) +static void applySeqSlideValue(TransInfo *t, const float val[2]) { TransData *td = t->data; int i; - TransSeq *ts = t->customData; for (i = 0; i < t->total; i++, td++) { - float tvec[2]; - if (td->flag & TD_NOACTION) break; if (td->flag & TD_SKIP) continue; - copy_v2_v2(tvec, val); - - mul_v2_fl(tvec, td->factor); - - if (t->modifiers & MOD_SNAP_INVERT) { - td->loc[0] = frame + td->factor * (td->iloc[0] - ts->min); - } - else { - td->loc[0] = td->iloc[0] + tvec[0]; - } - - td->loc[1] = td->iloc[1] + tvec[1]; + madd_v2_v2v2fl(td->loc, td->iloc, val, td->factor); } } static void applySeqSlide(TransInfo *t, const int mval[2]) { char str[MAX_INFO_LEN]; - int snap_frame = 0; + + snapSequenceBounds(t, mval); + if (t->con.mode & CON_APPLY) { float pvec[3] = {0.0f, 0.0f, 0.0f}; float tvec[3]; @@ -7352,7 +7340,6 @@ static void applySeqSlide(TransInfo *t, const int mval[2]) copy_v3_v3(t->values, tvec); } else { - snap_frame = snapSequenceBounds(t, mval); // snapGridIncrement(t, t->values); applyNumInput(&t->num, t->values); } @@ -7361,7 +7348,7 @@ static void applySeqSlide(TransInfo *t, const int mval[2]) t->values[1] = floor(t->values[1] + 0.5f); headerSeqSlide(t, t->values, str); - applySeqSlideValue(t, t->values, snap_frame); + applySeqSlideValue(t, t->values); recalcData(t); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 8d6c693b14a..97cc6dd9dd1 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -626,7 +626,7 @@ typedef enum { void snapGridIncrement(TransInfo *t, float *val); void snapGridIncrementAction(TransInfo *t, float *val, GearsType action); -int snapSequenceBounds(TransInfo *t, const int mval[2]); +void snapSequenceBounds(TransInfo *t, const int mval[2]); bool activeSnap(TransInfo *t); bool validSnap(TransInfo *t); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 4a2927ace00..1f2a06abfb0 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -577,6 +577,10 @@ static void initSnappingMode(TransInfo *t) t->tsnap.mode = SCE_SNAP_MODE_INCREMENT; } } + else if (t->spacetype == SPACE_SEQ) { + /* We do our own snapping currently, so nothing here */ + t->tsnap.mode = SCE_SNAP_MODE_GRID; /* Dummy, should we rather add a NOP mode? */ + } else { /* Always grid outside of 3D view */ t->tsnap.mode = SCE_SNAP_MODE_INCREMENT; @@ -2431,15 +2435,16 @@ void snapGridIncrement(TransInfo *t, float *val) snapGridIncrementAction(t, val, action); } -int snapSequenceBounds(TransInfo *t, const int mval[2]) +void snapSequenceBounds(TransInfo *t, const int mval[2]) { float xmouse, ymouse; int frame; int mframe; + TransData *td = t->data; TransSeq *ts = t->customData; /* reuse increment, strictly speaking could be another snap mode, but leave as is */ if (!(t->modifiers & MOD_SNAP_INVERT)) - return 0; + return; /* convert to frame range */ UI_view2d_region_to_view(&t->ar->v2d, mval[0], mval[1], &xmouse, &ymouse); @@ -2450,7 +2455,7 @@ int snapSequenceBounds(TransInfo *t, const int mval[2]) if (!ts->snap_left) frame = frame - (ts->max - ts->min); - return frame; + t->values[0] = frame - ts->min; } static void applyGridIncrement(TransInfo *t, float *val, int max_index, const float fac[3], GearsType action) -- cgit v1.2.3 From fd559ed94f7ff522e2657cdc7e7153740c480659 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 19 Mar 2015 21:10:05 +0100 Subject: Missed this last commit. --- intern/cycles/blender/addon/ui.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 6b7e03320bc..1097b79ffa5 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -457,8 +457,8 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel): sub.active = cam.dof_object is None sub.prop(cam, "dof_distance", text="Distance") col.prop(dof_options, "fstop") - col.prop(dof_options, "high_quality") - if dof_options.high_quality: + col.prop(dof_options, "use_high_quality") + if dof_options.use_high_quality: col.prop(dof_options, "blades") col = split.column() -- cgit v1.2.3 From f51a3aedc9540e0bcda4f16deec22e9aa722ef24 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 19 Mar 2015 21:11:33 +0100 Subject: Cleanup remove unused variable --- source/blender/editors/transform/transform_snap.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 1f2a06abfb0..fd189e91141 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -2440,7 +2440,6 @@ void snapSequenceBounds(TransInfo *t, const int mval[2]) float xmouse, ymouse; int frame; int mframe; - TransData *td = t->data; TransSeq *ts = t->customData; /* reuse increment, strictly speaking could be another snap mode, but leave as is */ if (!(t->modifiers & MOD_SNAP_INVERT)) -- cgit v1.2.3 From cf29010bd4085b2ab76c58a30d1148265a879d69 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 20 Mar 2015 15:26:47 +1100 Subject: Cleanup: warnings bit-shift int overflow --- source/blender/blenkernel/intern/screen.c | 4 ++-- source/blender/editors/armature/pose_edit.c | 5 +++-- source/blender/editors/space_view3d/view3d_header.c | 8 ++++---- source/blender/makesrna/intern/makesrna.c | 2 +- source/blender/makesrna/intern/rna_armature.c | 8 ++++---- source/blender/makesrna/intern/rna_controller.c | 2 +- source/blender/makesrna/intern/rna_space.c | 4 ++-- 7 files changed, 17 insertions(+), 16 deletions(-) diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index a6ac4551f4a..3c43bfa2920 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -510,8 +510,8 @@ void BKE_screen_view3d_sync(View3D *v3d, struct Scene *scene) if ((v3d->lay & v3d->layact) == 0) { for (bit = 0; bit < 32; bit++) { - if (v3d->lay & (1 << bit)) { - v3d->layact = 1 << bit; + if (v3d->lay & (1u << bit)) { + v3d->layact = (1u << bit); break; } } diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index 549a3854bac..bc900315247 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -862,7 +862,7 @@ static int pose_bone_layers_invoke(bContext *C, wmOperator *op, const wmEvent *e /* loop over the bits for this pchan's layers, adding layers where they're needed */ for (bit = 0; bit < 32; bit++) { - layers[bit] = (pchan->bone->layer & (1 << bit)) != 0; + layers[bit] = (pchan->bone->layer & (1u << bit)) != 0; } } CTX_DATA_END; @@ -936,8 +936,9 @@ static int armature_bone_layers_invoke(bContext *C, wmOperator *op, const wmEven /* loop over the bits for this pchan's layers, adding layers where they're needed */ for (bit = 0; bit < 32; bit++) { - if (ebone->layer & (1 << bit)) + if (ebone->layer & (1u << bit)) { layers[bit] = 1; + } } } CTX_DATA_END; diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 11ed9867e2f..f8912345e1c 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -105,8 +105,8 @@ static void view3d_layers_editmode_ensure(Scene *scene, View3D *v3d) if (scene->obedit && (scene->obedit->lay & v3d->lay) == 0) { int bit; for (bit = 0; bit < 32; bit++) { - if (scene->obedit->lay & (1 << bit)) { - v3d->lay |= 1 << bit; + if (scene->obedit->lay & (1u << bit)) { + v3d->lay |= (1u << bit); break; } } @@ -161,8 +161,8 @@ static int view3d_layers_exec(bContext *C, wmOperator *op) v3d->layact = 1 << nr; else if ((v3d->lay & v3d->layact) == 0) { for (bit = 0; bit < 32; bit++) { - if (v3d->lay & (1 << bit)) { - v3d->layact = 1 << bit; + if (v3d->lay & (1u << bit)) { + v3d->layact = (1u << bit); break; } } diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 894d5ef20a8..5f8639358b7 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -936,7 +936,7 @@ static char *rna_def_property_set_func(FILE *f, StructRNA *srna, PropertyRNA *pr if (dp->dnaarraylength == 1) { if (prop->type == PROP_BOOLEAN && dp->booleanbit) { - fprintf(f, " if (%svalues[i]) data->%s |= (%d<%s |= (%du << i);\n", (dp->booleannegative) ? "!" : "", dp->dnaname, dp->booleanbit); fprintf(f, " else data->%s &= ~(%du << i);\n", dp->dnaname, dp->booleanbit); } diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 421d7b28dda..93e5ceaa229 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -247,8 +247,8 @@ static void rna_bone_layer_set(int *layer, const int *values) return; for (i = 0; i < 32; i++) { - if (values[i]) *layer |= (1 << i); - else *layer &= ~(1 << i); + if (values[i]) *layer |= (1u << i); + else *layer &= ~(1u << i); } } @@ -272,8 +272,8 @@ static void rna_Armature_layer_set(PointerRNA *ptr, const int *values) return; for (i = 0; i < 32; i++) { - if (values[i]) arm->layer |= (1 << i); - else arm->layer &= ~(1 << i); + if (values[i]) arm->layer |= (1u << i); + else arm->layer &= ~(1u << i); } } diff --git a/source/blender/makesrna/intern/rna_controller.c b/source/blender/makesrna/intern/rna_controller.c index ba0214d36ec..605e28653f9 100644 --- a/source/blender/makesrna/intern/rna_controller.c +++ b/source/blender/makesrna/intern/rna_controller.c @@ -120,7 +120,7 @@ static int rna_Controller_state_number_get(struct PointerRNA *ptr) int bit; for (bit = 0; bit < 32; bit++) { - if (cont->state_mask & (1 << bit)) + if (cont->state_mask & (1u << bit)) return bit + 1; } return 0; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 9e7d70ab3b2..db4b097b9c3 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -413,8 +413,8 @@ static void rna_SpaceView3D_lock_camera_and_layers_set(PointerRNA *ptr, int valu /* seek for layact */ bit = 0; while (bit < 32) { - if (v3d->lay & (1 << bit)) { - v3d->layact = 1 << bit; + if (v3d->lay & (1u << bit)) { + v3d->layact = (1u << bit); break; } bit++; -- cgit v1.2.3 From 35ea7efbca4f9b5b19fb0c277fc225f430e1ee91 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 20 Mar 2015 15:50:56 +1100 Subject: Add missing update adding a shape-key Noticeable when pin is enabled. --- source/blender/editors/object/object_shapekey.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index fb0b2ed231c..674eb25942f 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -332,6 +332,8 @@ static int shape_key_add_exec(bContext *C, wmOperator *op) ED_object_shape_key_add(C, ob, from_mix); + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + return OPERATOR_FINISHED; } -- cgit v1.2.3 From 56edaf78673104728e771b835215c111de9528b2 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 20 Mar 2015 12:25:14 +0500 Subject: Fix stupid strict flags in math_color_inline.c It was unleashed with recent ghash commit and issue seems to be the same as fixed in 69065b5b. --- source/blender/blenlib/BLI_utildefines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 1e8440e55e9..2ddc8faa8b1 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -252,7 +252,7 @@ extern "C" { #define FTOCHAR(val) ((CHECK_TYPE_INLINE(val, float)), \ (char)(((val) <= 0.0f) ? 0 : (((val) > (1.0f - 0.5f / 255.0f)) ? 255 : ((255.0f * (val)) + 0.5f)))) #define FTOUSHORT(val) ((CHECK_TYPE_INLINE(val, float)), \ - ((val >= 1.0f - 0.5f / 65535) ? 65535 : (val <= 0.0f) ? 0 : (unsigned short)(val * 65535.0f + 0.5f))) + (unsigned short)((val >= 1.0f - 0.5f / 65535) ? 65535 : (val <= 0.0f) ? 0 : (val * 65535.0f + 0.5f))) #define USHORTTOUCHAR(val) ((unsigned char)(((val) >= 65535 - 128) ? 255 : ((val) + 128) >> 8)) #define F3TOCHAR3(v2, v1) { \ (v1)[0] = FTOCHAR((v2[0])); \ -- cgit v1.2.3 From 1cd4070e35fa8439bffcf500487e9922e11bd1d4 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 20 Mar 2015 12:41:31 +0500 Subject: Fix T43786: Cycles bake disregards Auto Smooth (vertex per-face normals) Added an utility function which performs vertex split based on the loop normal so now backing API matches to what's happening in Cycles and BI in terms of autosplit. Reviewers: dfelinto, campbellbarton Reviewed By: campbellbarton Differential Revision: https://developer.blender.org/D1174 --- source/blender/blenkernel/BKE_mesh.h | 3 + source/blender/blenkernel/intern/mesh.c | 140 ++++++++++++++++++++++++ source/blender/editors/object/object_bake_api.c | 20 +++- source/blender/makesrna/intern/rna_mesh_api.c | 45 +------- 4 files changed, 160 insertions(+), 48 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 224be0f3685..1f3458c06c2 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -130,6 +130,9 @@ bool BKE_mesh_uv_cdlayer_rename(struct Mesh *me, const char *old_name, const cha float (*BKE_mesh_vertexCos_get(struct Mesh *me, int *r_numVerts))[3]; +void BKE_mesh_calc_normals_split(struct Mesh *mesh); +void BKE_mesh_split_faces(struct Mesh *mesh); + struct Mesh *BKE_mesh_new_from_object(struct Main *bmain, struct Scene *sce, struct Object *ob, int apply_modifiers, int settings, int calc_tessface, int calc_undeformed); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 809d2137187..8ebc318ff9e 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2124,6 +2124,146 @@ void BKE_mesh_mselect_active_set(Mesh *me, int index, int type) (me->mselect[me->totselect - 1].type == type)); } +void BKE_mesh_calc_normals_split(Mesh *mesh) +{ + float (*r_loopnors)[3]; + float (*polynors)[3]; + short (*clnors)[2] = NULL; + bool free_polynors = false; + + if (CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { + r_loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL); + memset(r_loopnors, 0, sizeof(float[3]) * mesh->totloop); + } + else { + r_loopnors = CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CALLOC, NULL, mesh->totloop); + CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); + } + + /* may be NULL */ + clnors = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); + + if (CustomData_has_layer(&mesh->pdata, CD_NORMAL)) { + /* This assume that layer is always up to date, not sure this is the case (esp. in Edit mode?)... */ + polynors = CustomData_get_layer(&mesh->pdata, CD_NORMAL); + free_polynors = false; + } + else { + polynors = MEM_mallocN(sizeof(float[3]) * mesh->totpoly, __func__); + BKE_mesh_calc_normals_poly(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, + polynors, false); + free_polynors = true; + } + + BKE_mesh_normals_loop_split( + mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge, + mesh->mloop, r_loopnors, mesh->totloop, mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly, + (mesh->flag & ME_AUTOSMOOTH) != 0, mesh->smoothresh, NULL, clnors, NULL); + + if (free_polynors) { + MEM_freeN(polynors); + } +} + +/* Spli faces based on the edge angle. + * Matches behavior of face splitting in render engines. + */ +void BKE_mesh_split_faces(Mesh *mesh) +{ + const int num_verts = mesh->totvert; + const int num_edges = mesh->totedge; + const int num_polys = mesh->totpoly; + MVert *mvert = mesh->mvert; + MEdge *medge = mesh->medge; + MLoop *mloop = mesh->mloop; + MPoly *mpoly = mesh->mpoly; + float (*lnors)[3]; + int poly, num_new_verts = 0; + if ((mesh->flag & ME_AUTOSMOOTH) == 0) { + return; + } + BKE_mesh_tessface_clear(mesh); + /* Compute loop normals if needed. */ + if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { + BKE_mesh_calc_normals_split(mesh); + } + lnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL); + /* Count. */ + for (poly = 0; poly < num_polys; poly++) { + MPoly *mp = &mpoly[poly]; + int loop; + for (loop = 0; loop < mp->totloop; loop++) { + MLoop *ml = &mloop[mp->loopstart + loop]; + MVert *mv = &mvert[ml->v]; + float vn[3]; + normal_short_to_float_v3(vn, mv->no); + if (!equals_v3v3(vn, lnors[mp->loopstart + loop])) { + num_new_verts++; + } + } + } + if (num_new_verts == 0) { + /* No new vertices are to be added, can do early exit. */ + return; + } + /* Actual split. */ + mesh->totvert += num_new_verts; + mesh->totedge += 2 * num_new_verts; + mvert = mesh->mvert = MEM_reallocN(mesh->mvert, + sizeof(MVert) * mesh->totvert); + medge = mesh->medge = MEM_reallocN(mesh->medge, + sizeof(MEdge) * mesh->totedge); + CustomData_set_layer(&mesh->vdata, CD_MVERT, mesh->mvert); + CustomData_set_layer(&mesh->edata, CD_MEDGE, mesh->medge); + num_new_verts = 0; + for (poly = 0; poly < num_polys; poly++) { + MPoly *mp = &mpoly[poly]; + int loop; + for (loop = 0; loop < mp->totloop; loop++) { + int poly_loop = mp->loopstart + loop; + MLoop *ml = &mloop[poly_loop]; + MVert *mv = &mvert[ml->v]; + float vn[3]; + normal_short_to_float_v3(vn, mv->no); + if (!equals_v3v3(vn, lnors[mp->loopstart + loop])) { + int poly_loop_prev = mp->loopstart + (loop + mp->totloop - 1) % mp->totloop; + MLoop *ml_prev = &mloop[poly_loop_prev]; + int new_edge_prev, new_edge; + /* Cretae new vertex. */ + int new_vert = num_verts + num_new_verts; + CustomData_copy_data(&mesh->vdata, &mesh->vdata, + ml->v, new_vert, 1); + normal_float_to_short_v3(mvert[new_vert].no, + lnors[poly_loop]); + /* Create new edges. */ + new_edge_prev = num_edges + 2 * num_new_verts; + new_edge = num_edges + 2 * num_new_verts + 1; + CustomData_copy_data(&mesh->edata, &mesh->edata, + ml_prev->e, new_edge_prev, 1); + CustomData_copy_data(&mesh->edata, &mesh->edata, + ml->e, new_edge, 1); + if (medge[new_edge_prev].v1 == ml->v) { + medge[new_edge_prev].v1 = new_vert; + } + else { + medge[new_edge_prev].v2 = new_vert; + } + if (medge[new_edge].v1 == ml->v) { + medge[new_edge].v1 = new_vert; + } + else { + medge[new_edge].v2 = new_vert; + } + + ml->v = new_vert; + ml_prev->e = new_edge_prev; + ml->e = new_edge; + num_new_verts++; + } + } + } +} + /* settings: 1 - preview, 2 - render */ Mesh *BKE_mesh_new_from_object( Main *bmain, Scene *sce, Object *ob, diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 97cb45daae3..fe9ee71aa8e 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -685,7 +685,9 @@ static int bake( result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels"); /* get the mesh as it arrives in the renderer */ - me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 1, 0); + me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0); + BKE_mesh_split_faces(me_low); + BKE_mesh_tessface_ensure(me_low); /* populate the pixel array with the face data */ if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false) @@ -700,7 +702,9 @@ static int bake( /* prepare cage mesh */ if (ob_cage) { - me_cage = BKE_mesh_new_from_object(bmain, scene, ob_cage, 1, 2, 1, 0); + me_cage = BKE_mesh_new_from_object(bmain, scene, ob_cage, 1, 2, 0, 0); + BKE_mesh_split_faces(me_cage); + BKE_mesh_tessface_ensure(me_cage); if (me_low->totface != me_cage->totface) { BKE_report(reports, RPT_ERROR, "Invalid cage object, the cage mesh must have the same number " @@ -732,7 +736,9 @@ static int bake( ob_low->modifiers = modifiers_tmp; /* get the cage mesh as it arrives in the renderer */ - me_cage = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 1, 0); + me_cage = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0); + BKE_mesh_split_faces(me_cage); + BKE_mesh_tessface_ensure(me_cage); RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer); } @@ -760,8 +766,10 @@ static int bake( tmd->quad_method = MOD_TRIANGULATE_QUAD_FIXED; tmd->ngon_method = MOD_TRIANGULATE_NGON_EARCLIP; - highpoly[i].me = BKE_mesh_new_from_object(bmain, scene, highpoly[i].ob, 1, 2, 1, 0); + highpoly[i].me = BKE_mesh_new_from_object(bmain, scene, highpoly[i].ob, 1, 2, 0, 0); highpoly[i].ob->restrictflag &= ~OB_RESTRICT_RENDER; + BKE_mesh_split_faces(highpoly[i].me); + BKE_mesh_tessface_ensure(highpoly[i].me); /* lowpoly to highpoly transformation matrix */ copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat); @@ -867,7 +875,9 @@ cage_cleanup: md->mode &= ~eModifierMode_Render; } - me_nores = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 1, 0); + me_nores = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0); + BKE_mesh_split_faces(me_nores); + BKE_mesh_tessface_ensure(me_nores); RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer); RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low->obmat); diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index abf29ef82a3..48a5f09fda0 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -69,47 +69,6 @@ static void rna_Mesh_create_normals_split(Mesh *mesh) } } -static void rna_Mesh_calc_normals_split(Mesh *mesh) -{ - float (*r_loopnors)[3]; - float (*polynors)[3]; - short (*clnors)[2] = NULL; - bool free_polynors = false; - - if (CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { - r_loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL); - memset(r_loopnors, 0, sizeof(float[3]) * mesh->totloop); - } - else { - r_loopnors = CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CALLOC, NULL, mesh->totloop); - CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); - } - - /* may be NULL */ - clnors = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); - - if (CustomData_has_layer(&mesh->pdata, CD_NORMAL)) { - /* This assume that layer is always up to date, not sure this is the case (esp. in Edit mode?)... */ - polynors = CustomData_get_layer(&mesh->pdata, CD_NORMAL); - free_polynors = false; - } - else { - polynors = MEM_mallocN(sizeof(float[3]) * mesh->totpoly, __func__); - BKE_mesh_calc_normals_poly(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, - polynors, false); - free_polynors = true; - } - - BKE_mesh_normals_loop_split( - mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge, - mesh->mloop, r_loopnors, mesh->totloop, mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly, - (mesh->flag & ME_AUTOSMOOTH) != 0, mesh->smoothresh, NULL, clnors, NULL); - - if (free_polynors) { - MEM_freeN(polynors); - } -} - static void rna_Mesh_free_normals_split(Mesh *mesh) { CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop); @@ -130,7 +89,7 @@ static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char * /* Compute loop normals if needed. */ if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { - rna_Mesh_calc_normals_split(mesh); + BKE_mesh_calc_normals_split(mesh); } BKE_mesh_loop_tangents(mesh, uvmap, r_looptangents, reports); @@ -256,7 +215,7 @@ void RNA_api_mesh(StructRNA *srna) func = RNA_def_function(srna, "create_normals_split", "rna_Mesh_create_normals_split"); RNA_def_function_ui_description(func, "Empty split vertex normals"); - func = RNA_def_function(srna, "calc_normals_split", "rna_Mesh_calc_normals_split"); + func = RNA_def_function(srna, "calc_normals_split", "BKE_mesh_calc_normals_split"); RNA_def_function_ui_description(func, "Calculate split vertex normals, which preserve sharp edges"); func = RNA_def_function(srna, "free_normals_split", "rna_Mesh_free_normals_split"); -- cgit v1.2.3 From 6de12b1b43f846f786abc903b992d9493900f76f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 20 Mar 2015 13:59:05 +0500 Subject: CMake: Suppress unconfigured branch upstream error in the output --- build_files/cmake/buildinfo.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build_files/cmake/buildinfo.cmake b/build_files/cmake/buildinfo.cmake index 8ef29b06213..74c1f8f1f8e 100644 --- a/build_files/cmake/buildinfo.cmake +++ b/build_files/cmake/buildinfo.cmake @@ -60,7 +60,8 @@ if(EXISTS ${SOURCE_DIR}/.git) execute_process(COMMAND git log HEAD..@{u} WORKING_DIRECTORY ${SOURCE_DIR} OUTPUT_VARIABLE _git_below_check - OUTPUT_STRIP_TRAILING_WHITESPACE) + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) if(NOT _git_below_check STREQUAL "") # If there're commits between HEAD and upstream this means # that we're reset-ed to older revision. Use it's hash then. -- cgit v1.2.3 From 6f51df5384f1a78ea0359459f410a9724d7f2e80 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 20 Mar 2015 14:03:54 +0500 Subject: SCons: Attempt to deal with branches without upstream configured --- build_files/scons/tools/Blender.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py index 060904e7cd7..dbe1cafc14f 100644 --- a/build_files/scons/tools/Blender.py +++ b/build_files/scons/tools/Blender.py @@ -441,7 +441,7 @@ def buildinfo(lenv, build_type): no_upstream = False try : - build_hash = btools.get_command_output(['git', 'rev-parse', '--short', '@{u}']).strip() + build_hash = btools.get_command_output(['git', 'rev-parse', '--short', '@{u}'], stderr=subprocess.STDOUT).strip() except subprocess.CalledProcessError: # assume branch has no upstream configured build_hash = btools.get_command_output(['git', 'rev-parse', '--short', 'HEAD']).strip() -- cgit v1.2.3 From 03d945095af38905f3cbb0136e257cd491e3a48b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 20 Mar 2015 14:07:56 +0500 Subject: Cmake: Some more tweaks to building from branch without upstream --- build_files/cmake/packaging.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build_files/cmake/packaging.cmake b/build_files/cmake/packaging.cmake index 95bbb2b59a8..f0dd0482d4d 100644 --- a/build_files/cmake/packaging.cmake +++ b/build_files/cmake/packaging.cmake @@ -27,7 +27,8 @@ if(EXISTS ${CMAKE_SOURCE_DIR}/.git/) execute_process(COMMAND git rev-parse --short @{u} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE MY_WC_HASH - OUTPUT_STRIP_TRAILING_WHITESPACE) + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) endif() endif() set(BUILD_REV ${MY_WC_HASH}) -- cgit v1.2.3 From 6786ef6783fa924d1ad0625d557f0c1fcb5d9ede Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 20 Mar 2015 12:39:25 +0100 Subject: Fix T43986: VSE Mask Modifier don't move with video-Clip. Now mask animation is offset to start of strip, instead of staying at frame 1! Warning: this may break existing files, in case some would be using (hacking around!) current bad behavior... --- source/blender/blenkernel/BKE_sequencer.h | 4 +++- source/blender/blenkernel/intern/seqmodifier.c | 6 +++--- source/blender/blenkernel/intern/sequencer.c | 7 +++++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index c936ce5284d..5649e76efe6 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -449,7 +449,9 @@ void BKE_sequence_modifier_list_copy(struct Sequence *seqn, struct Sequence *seq int BKE_sequence_supports_modifiers(struct Sequence *seq); /* internal filters */ -struct ImBuf *BKE_sequencer_render_mask_input(const SeqRenderData *context, int mask_input_type, struct Sequence *mask_sequence, struct Mask *mask_id, int cfra, bool make_float); +struct ImBuf *BKE_sequencer_render_mask_input( + const SeqRenderData *context, int mask_input_type, struct Sequence *mask_sequence, struct Mask *mask_id, + int cfra, int fra_offset, bool make_float); void BKE_sequencer_color_balance_apply(struct StripColorBalance *cb, struct ImBuf *ibuf, float mul, bool make_float, struct ImBuf *mask_input); #endif /* __BKE_SEQUENCER_H__ */ diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index edd3d8efd55..b9d096f1346 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -77,9 +77,9 @@ typedef struct ModifierThread { } ModifierThread; -static ImBuf *modifier_mask_get(SequenceModifierData *smd, const SeqRenderData *context, int cfra, bool make_float) +static ImBuf *modifier_mask_get(SequenceModifierData *smd, const SeqRenderData *context, int cfra, int fra_offset, bool make_float) { - return BKE_sequencer_render_mask_input(context, smd->mask_input_type, smd->mask_sequence, smd->mask_id, cfra, make_float); + return BKE_sequencer_render_mask_input(context, smd->mask_input_type, smd->mask_sequence, smd->mask_id, cfra, fra_offset, make_float); } static void modifier_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) @@ -667,7 +667,7 @@ ImBuf *BKE_sequence_modifier_apply_stack(const SeqRenderData *context, Sequence continue; if (smti->apply) { - ImBuf *mask = modifier_mask_get(smd, context, cfra, ibuf->rect_float != NULL); + ImBuf *mask = modifier_mask_get(smd, context, cfra, seq->start, ibuf->rect_float != NULL); if (processed_ibuf == ibuf) processed_ibuf = IMB_dupImBuf(ibuf); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index cb23b1eb88e..c45db303467 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1920,7 +1920,10 @@ static void *color_balance_do_thread(void *thread_data_v) return NULL; } -ImBuf *BKE_sequencer_render_mask_input(const SeqRenderData *context, int mask_input_type, Sequence *mask_sequence, Mask *mask_id, int cfra, bool make_float) +/* cfra is offset by fra_offset only in case we are using a real mask. */ +ImBuf *BKE_sequencer_render_mask_input( + const SeqRenderData *context, int mask_input_type, Sequence *mask_sequence, Mask *mask_id, + int cfra, int fra_offset, bool make_float) { ImBuf *mask_input = NULL; @@ -1939,7 +1942,7 @@ ImBuf *BKE_sequencer_render_mask_input(const SeqRenderData *context, int mask_in } } else if (mask_input_type == SEQUENCE_MASK_INPUT_ID) { - mask_input = seq_render_mask(context, mask_id, cfra, make_float); + mask_input = seq_render_mask(context, mask_id, cfra - fra_offset, make_float); } return mask_input; -- cgit v1.2.3 From c0be69f7fdb8f905f6133663e6f91a0d849b7795 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 20 Mar 2015 23:38:08 +1100 Subject: Fix/Improve FKey bone creation - new bone is now made active - previous selection cleared - bone direction places the tip on the active bone (if available) --- source/blender/editors/armature/armature_edit.c | 98 ++++++++++++++----------- 1 file changed, 54 insertions(+), 44 deletions(-) diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index 88c52989c07..6fe4cbf4ade 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -578,6 +578,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); ListBase points = {NULL, NULL}; + EditBone *newbone = NULL; int count; /* sanity checks */ @@ -610,94 +611,97 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op) float curs[3]; /* Get Points - selected joint */ - ebp = (EditBonePoint *)points.first; + ebp = points.first; /* Get points - cursor (tail) */ invert_m4_m4(obedit->imat, obedit->obmat); mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d)); /* Create a bone */ - /* newbone = */ add_points_bone(obedit, ebp->vec, curs); + newbone = add_points_bone(obedit, ebp->vec, curs); } else if (count == 2) { - EditBonePoint *ebp, *ebp2; + EditBonePoint *ebp_a, *ebp_b; float head[3], tail[3]; short headtail = 0; /* check that the points don't belong to the same bone */ - ebp = (EditBonePoint *)points.first; - ebp2 = ebp->next; + ebp_a = (EditBonePoint *)points.first; + ebp_b = ebp_a->next; - if ((ebp->head_owner == ebp2->tail_owner) && (ebp->head_owner != NULL)) { - BKE_report(op->reports, RPT_ERROR, "Same bone selected..."); - BLI_freelistN(&points); - return OPERATOR_CANCELLED; - } - if ((ebp->tail_owner == ebp2->head_owner) && (ebp->tail_owner != NULL)) { + if (((ebp_a->head_owner == ebp_b->tail_owner) && (ebp_a->head_owner != NULL)) || + ((ebp_a->tail_owner == ebp_b->head_owner) && (ebp_a->tail_owner != NULL))) + { BKE_report(op->reports, RPT_ERROR, "Same bone selected..."); BLI_freelistN(&points); return OPERATOR_CANCELLED; } /* find which one should be the 'head' */ - if ((ebp->head_owner && ebp2->head_owner) || (ebp->tail_owner && ebp2->tail_owner)) { - /* rule: whichever one is closer to 3d-cursor */ - float curs[3]; - float vecA[3], vecB[3]; - float distA, distB; - - /* get cursor location */ - invert_m4_m4(obedit->imat, obedit->obmat); - mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d)); - - /* get distances */ - sub_v3_v3v3(vecA, ebp->vec, curs); - sub_v3_v3v3(vecB, ebp2->vec, curs); - distA = len_v3(vecA); - distB = len_v3(vecB); - - /* compare distances - closer one therefore acts as direction for bone to go */ - headtail = (distA < distB) ? 2 : 1; + if ((ebp_a->head_owner && ebp_b->head_owner) || (ebp_a->tail_owner && ebp_b->tail_owner)) { + /* use active, nice predictable */ + if (arm->act_edbone && ELEM(arm->act_edbone, ebp_a->head_owner, ebp_a->tail_owner)) { + headtail = 1; + } + else if (arm->act_edbone && ELEM(arm->act_edbone, ebp_b->head_owner, ebp_b->tail_owner)) { + headtail = 2; + } + else { + /* rule: whichever one is closer to 3d-cursor */ + float curs[3]; + float dist_sq_a, dist_sq_b; + + /* get cursor location */ + invert_m4_m4(obedit->imat, obedit->obmat); + mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d)); + + /* get distances */ + dist_sq_a = len_squared_v3v3(ebp_a->vec, curs); + dist_sq_b = len_squared_v3v3(ebp_b->vec, curs); + + /* compare distances - closer one therefore acts as direction for bone to go */ + headtail = (dist_sq_a < dist_sq_b) ? 2 : 1; + } } - else if (ebp->head_owner) { + else if (ebp_a->head_owner) { headtail = 1; } - else if (ebp2->head_owner) { + else if (ebp_b->head_owner) { headtail = 2; } /* assign head/tail combinations */ if (headtail == 2) { - copy_v3_v3(head, ebp->vec); - copy_v3_v3(tail, ebp2->vec); + copy_v3_v3(head, ebp_a->vec); + copy_v3_v3(tail, ebp_b->vec); } else if (headtail == 1) { - copy_v3_v3(head, ebp2->vec); - copy_v3_v3(tail, ebp->vec); + copy_v3_v3(head, ebp_b->vec); + copy_v3_v3(tail, ebp_a->vec); } /* add new bone and parent it to the appropriate end */ if (headtail) { - EditBone *newbone = add_points_bone(obedit, head, tail); + newbone = add_points_bone(obedit, head, tail); /* do parenting (will need to set connected flag too) */ if (headtail == 2) { /* ebp tail or head - tail gets priority */ - if (ebp->tail_owner) - newbone->parent = ebp->tail_owner; + if (ebp_a->tail_owner) + newbone->parent = ebp_a->tail_owner; else - newbone->parent = ebp->head_owner; + newbone->parent = ebp_a->head_owner; } else { - /* ebp2 tail or head - tail gets priority */ - if (ebp2->tail_owner) - newbone->parent = ebp2->tail_owner; + /* ebp_b tail or head - tail gets priority */ + if (ebp_b->tail_owner) + newbone->parent = ebp_b->tail_owner; else - newbone->parent = ebp2->head_owner; + newbone->parent = ebp_b->head_owner; } /* don't set for bone connecting two head points of bones */ - if (ebp->tail_owner || ebp2->tail_owner) { + if (ebp_a->tail_owner || ebp_b->tail_owner) { newbone->flag |= BONE_CONNECTED; } } @@ -708,6 +712,12 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op) BLI_freelistN(&points); return OPERATOR_CANCELLED; } + + if (newbone) { + ED_armature_deselect_all(obedit, 0); + arm->act_edbone = newbone; + newbone->flag |= BONE_TIPSEL; + } /* updates */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit); -- cgit v1.2.3 From 3d6642db835a9e35ea15cf9f856ce047447690ca Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 20 Mar 2015 17:48:45 +0500 Subject: Fix race condition and bad memory access highlighting render tiles Is was possible that interface will be refreshed at thesame time as render engine will start freeing render parts. Not sure if we can get away without RW mutex here, seems we need one way of synchronization or another.. --- source/blender/render/intern/include/render_types.h | 1 + source/blender/render/intern/source/external_engine.c | 11 ++++++++++- source/blender/render/intern/source/pipeline.c | 5 ++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 8d92fb9eec9..a53ff302475 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -194,6 +194,7 @@ struct Render struct Object *camera_override; unsigned int lay, layer_override; + ThreadRWMutex partsmutex; ListBase parts; /* render engine */ diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 4e63a9918e1..557fcb01778 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -375,9 +375,12 @@ void RE_engine_get_current_tiles(Render *re, int *total_tiles_r, rcti **tiles_r) rcti *tiles = NULL; int allocation_size = 0, allocation_step = BLENDER_MAX_THREADS; + BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_READ); + if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) { *total_tiles_r = 0; *tiles_r = NULL; + BLI_rw_mutex_unlock(&re->partsmutex); return; } @@ -404,7 +407,7 @@ void RE_engine_get_current_tiles(Render *re, int *total_tiles_r, rcti **tiles_r) total_tiles++; } } - + BLI_rw_mutex_unlock(&re->partsmutex); *total_tiles_r = total_tiles; *tiles_r = tiles; } @@ -478,6 +481,8 @@ bool RE_bake_engine( engine->tile_y = 0; engine->flag &= ~RE_ENGINE_RENDERING; + BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE); + /* re->engine becomes zero if user changed active render engine during render */ if (!persistent_data || !re->engine) { RE_engine_free(engine); @@ -485,6 +490,7 @@ bool RE_bake_engine( } RE_parts_free(re); + BLI_rw_mutex_unlock(&re->partsmutex); if (BKE_reports_contain(re->reports, RPT_ERROR)) G.is_break = true; @@ -663,6 +669,8 @@ int RE_engine_render(Render *re, int do_all) render_result_free_list(&engine->fullresult, engine->fullresult.first); + BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE); + /* re->engine becomes zero if user changed active render engine during render */ if (!persistent_data || !re->engine) { RE_engine_free(engine); @@ -682,6 +690,7 @@ int RE_engine_render(Render *re, int do_all) } RE_parts_free(re); + BLI_rw_mutex_unlock(&re->partsmutex); if (BKE_reports_contain(re->reports, RPT_ERROR)) G.is_break = true; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 21ca7924fa0..b397db7c31b 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -385,6 +385,7 @@ Render *RE_NewRender(const char *name) BLI_addtail(&RenderGlobal.renderlist, re); BLI_strncpy(re->name, name, RE_MAXNAME); BLI_rw_mutex_init(&re->resultmutex); + BLI_rw_mutex_init(&re->partsmutex); re->eval_ctx = MEM_callocN(sizeof(EvaluationContext), "re->eval_ctx"); re->eval_ctx->mode = DAG_EVAL_RENDER; } @@ -423,6 +424,7 @@ void RE_FreeRender(Render *re) RE_engine_free(re->engine); BLI_rw_mutex_end(&re->resultmutex); + BLI_rw_mutex_end(&re->partsmutex); BLI_freelistN(&re->r.layers); @@ -1268,8 +1270,9 @@ static void threaded_tile_processor(Render *re) /* unset threadsafety */ g_break = 0; - + BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE); RE_parts_free(re); + BLI_rw_mutex_unlock(&re->partsmutex); re->viewplane = viewplane; /* restore viewplane, modified by pano render */ } -- cgit v1.2.3 From 07b2508305d58d0c772464f9a174fca2b96036c2 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 20 Mar 2015 15:26:13 +0100 Subject: Fix high quality depth of field on the Mac. Quite a few things wrong here: * Mac did not support EXT_draw_instanced, only ARB_draw_instanced * Draw instanced did not work unless data came from vertex buffer, which is second time we see weird things with vertex arrays in mac * There were a few stupid mistakes by me as well, such as binding to uniform locations for the wrong shaders (it's a wonder it ever worked :p) --- source/blender/gpu/GPU_extensions.h | 2 +- source/blender/gpu/intern/gpu_codegen.c | 2 +- source/blender/gpu/intern/gpu_compositing.c | 35 +++++++++++++----- source/blender/gpu/intern/gpu_extensions.c | 43 ++++++++++------------ source/blender/gpu/intern/gpu_simple_shader.c | 2 +- .../gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl | 6 +-- .../gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl | 4 +- 7 files changed, 52 insertions(+), 42 deletions(-) diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index aed1a88938a..401711e84e5 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -184,7 +184,7 @@ int GPU_offscreen_height(const GPUOffScreen *ofs); * - only for fragment shaders now * - must call texture bind before setting a texture as uniform! */ -GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines); +GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines, int input, int output, int number); void GPU_shader_free(GPUShader *shader); void GPU_shader_bind(GPUShader *shader); diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index fcfb68d4629..113ed8e341c 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -1419,7 +1419,7 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, /* generate code and compile with opengl */ fragmentcode = code_generate_fragment(nodes, outlink->output); vertexcode = code_generate_vertex(nodes, type); - shader = GPU_shader_create(vertexcode, fragmentcode, NULL, glsl_material_library, NULL); + shader = GPU_shader_create(vertexcode, fragmentcode, NULL, glsl_material_library, NULL, 0, 0, 0); /* failed? */ if (!shader) { diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index bfa938d0fed..43dfba1925c 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -114,6 +114,8 @@ struct GPUFX { /* we have a stencil, restore the previous state */ bool restore_stencil; + + unsigned int vbuffer; }; #if 0 @@ -177,6 +179,12 @@ GPUFX *GPU_fx_compositor_create(void) { GPUFX *fx = MEM_callocN(sizeof(GPUFX), "GPUFX compositor"); + glGenBuffersARB(1, &fx->vbuffer); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, fx->vbuffer); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, 16 * sizeof(float), NULL, GL_STATIC_DRAW); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, 8 * sizeof(float), fullscreencos); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 8 * sizeof(float), 8 * sizeof(float), fullscreenuvs); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); return fx; } @@ -583,8 +591,9 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx) glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); /* set up quad buffer */ - glVertexPointer(2, GL_FLOAT, 0, fullscreencos); - glTexCoordPointer(2, GL_FLOAT, 0, fullscreenuvs); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, fx->vbuffer); + glVertexPointer(2, GL_FLOAT, 0, NULL); + glTexCoordPointer(2, GL_FLOAT, 0, ((GLubyte *)NULL + 8 * sizeof(float))); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); @@ -613,6 +622,7 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); @@ -649,8 +659,9 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str target = fx->color_buffer_sec; /* set up quad buffer */ - glVertexPointer(2, GL_FLOAT, 0, fullscreencos); - glTexCoordPointer(2, GL_FLOAT, 0, fullscreenuvs); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, fx->vbuffer); + glVertexPointer(2, GL_FLOAT, 0, NULL); + glTexCoordPointer(2, GL_FLOAT, 0, ((GLubyte *)NULL + 8 * sizeof(float))); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); @@ -793,6 +804,7 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str glDisableClientState(GL_TEXTURE_COORD_ARRAY); GPU_shader_unbind(); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); return false; } @@ -862,7 +874,7 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer"); coc_uniform = GPU_shader_get_uniform(dof_shader_pass2, "cocbuffer"); select_uniform = GPU_shader_get_uniform(dof_shader_pass2, "layerselection"); - dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params"); + dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params"); GPU_shader_bind(dof_shader_pass2); @@ -882,13 +894,14 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_far_blur, 0, NULL); GPU_texture_bind_as_framebuffer(fx->dof_far_blur); + glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); /* have to clear the buffer unfortunately */ glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */ - glDrawArraysInstancedEXT(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h); + glDrawArraysInstancedARB(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h); GPU_texture_unbind(fx->dof_half_downsampled_far); GPU_framebuffer_texture_detach(fx->dof_far_blur); @@ -905,7 +918,7 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str /* have to clear the buffer unfortunately */ glClear(GL_COLOR_BUFFER_BIT); /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */ - glDrawArraysInstancedEXT(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h); + glDrawArraysInstancedARB(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h); /* disable bindings */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -931,8 +944,8 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str color_uniform = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer"); far_uniform = GPU_shader_get_uniform(dof_shader_pass3, "farbuffer"); near_uniform = GPU_shader_get_uniform(dof_shader_pass3, "nearbuffer"); - viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs"); - depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer"); + viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass3, "viewvecs"); + depth_uniform = GPU_shader_get_uniform(dof_shader_pass3, "depthbuffer"); GPU_shader_bind(dof_shader_pass3); @@ -951,7 +964,7 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str GPU_texture_bind(fx->depth_buffer, numslots++); GPU_texture_filter_mode(fx->depth_buffer, false, false); - GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer); + GPU_shader_uniform_texture(dof_shader_pass3, depth_uniform, fx->depth_buffer); GPU_texture_bind(src, numslots++); GPU_shader_uniform_texture(dof_shader_pass3, color_uniform, src); @@ -1002,6 +1015,7 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str glDisableClientState(GL_TEXTURE_COORD_ARRAY); GPU_shader_unbind(); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); return false; } @@ -1230,6 +1244,7 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); GPU_shader_unbind(); diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 24b54a3af37..b4ffc978d11 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -289,7 +289,7 @@ bool GPU_geometry_shader_support(void) bool GPU_instanced_drawing_support(void) { - return GLEW_EXT_draw_instanced; + return GLEW_ARB_draw_instanced; } int GPU_color_depth(void) @@ -1456,7 +1456,7 @@ static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH]) if (GPU_instanced_drawing_support()) { strcat(defines, "#extension GL_EXT_gpu_shader4: enable\n"); - strcat(defines, "#extension GL_EXT_draw_instanced: enable\n"); + strcat(defines, "#extension GL_ARB_draw_instanced: enable\n"); } } @@ -1478,7 +1478,7 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH]) return; } -GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines) +GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines, int input, int output, int number) { GLint status; GLcharARB log[5000]; @@ -1577,7 +1577,6 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const source[num_source++] = standard_defines; if (defines) source[num_source++] = defines; - if (libcode) source[num_source++] = libcode; source[num_source++] = geocode; glAttachObjectARB(shader->object, shader->geometry); @@ -1593,6 +1592,8 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const GPU_shader_free(shader); return NULL; } + + GPU_shader_geometry_stage_primitive_io(shader, input, output, number); } @@ -1732,9 +1733,6 @@ void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int ou glProgramParameteriEXT(shader->object, GL_GEOMETRY_INPUT_TYPE_EXT, input); glProgramParameteriEXT(shader->object, GL_GEOMETRY_OUTPUT_TYPE_EXT, output); glProgramParameteriEXT(shader->object, GL_GEOMETRY_VERTICES_OUT_EXT, number); - - /* relink so settings can take effect (sucks but should only be done right after compilation so...) */ - glLinkProgramARB(shader->object); } void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex) @@ -1784,12 +1782,12 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) switch (shader) { case GPU_SHADER_VSM_STORE: if (!GG.shaders.vsm_store) - GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL, NULL); + GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL, NULL, 0, 0, 0); retval = GG.shaders.vsm_store; break; case GPU_SHADER_SEP_GAUSSIAN_BLUR: if (!GG.shaders.sep_gaussian_blur) - GG.shaders.sep_gaussian_blur = GPU_shader_create(datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, NULL, NULL, NULL); + GG.shaders.sep_gaussian_blur = GPU_shader_create(datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, NULL, NULL, NULL, 0, 0, 0); retval = GG.shaders.sep_gaussian_blur; break; } @@ -1822,56 +1820,53 @@ GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp) switch(effects) { case GPU_SHADER_FX_SSAO: - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); break; case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE: strcat(defines, "#define FIRST_PASS\n"); - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); break; case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO: strcat(defines, "#define SECOND_PASS\n"); - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); break; case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE: strcat(defines, "#define THIRD_PASS\n"); - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); break; case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR: strcat(defines, "#define FOURTH_PASS\n"); - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); break; case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE: strcat(defines, "#define FIFTH_PASS\n"); - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); break; case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE: strcat(defines, "#define FIRST_PASS\n"); - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); break; case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO: strcat(defines, "#define SECOND_PASS\n"); - shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl, defines); - - if (shader) { - GG.shaders.fx_shaders[offset] = shader; - GPU_shader_geometry_stage_primitive_io(shader, GL_POINTS, GL_TRIANGLE_STRIP, 4); - } + shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl, + defines, GL_POINTS, GL_TRIANGLE_STRIP, 4); + GG.shaders.fx_shaders[offset] = shader; break; case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE: strcat(defines, "#define THIRD_PASS\n"); - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); break; case GPU_SHADER_FX_DEPTH_RESOLVE: - GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines); + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0); } } diff --git a/source/blender/gpu/intern/gpu_simple_shader.c b/source/blender/gpu/intern/gpu_simple_shader.c index 60d4a2f2875..b439a37f3c3 100644 --- a/source/blender/gpu/intern/gpu_simple_shader.c +++ b/source/blender/gpu/intern/gpu_simple_shader.c @@ -152,7 +152,7 @@ static GPUShader *gpu_simple_shader(int options) datatoc_gpu_shader_simple_vert_glsl, datatoc_gpu_shader_simple_frag_glsl, NULL, - NULL, defines); + NULL, defines, 0, 0, 0); if (shader) { /* set texture map to first texture unit */ diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl index e2d3ab36ec8..8c2aff45679 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl @@ -102,7 +102,7 @@ void accumulate_pass(void) { if (dof_params.w == 0.0) r = 1.0; else - r = cos(M_PI / dof_params.w) / (cos(theta - (2.0 * M_PI / dof_params.w) * floor((dof_params.w * theta + M_PI) / (2 * M_PI)))); + r = cos(M_PI / dof_params.w) / (cos(theta - (2.0 * M_PI / dof_params.w) * floor((dof_params.w * theta + M_PI) / (2.0 * M_PI)))); if (dot(particlecoord, particlecoord) > r * r) discard; @@ -124,7 +124,7 @@ void final_pass(void) { vec4 farcolor = texture2D(farbuffer, uvcoord); float farweight = farcolor.a; - if (farweight > 0) + if (farweight > 0.0) farcolor /= farweight; vec4 nearcolor = texture2D(nearbuffer, uvcoord); @@ -138,7 +138,7 @@ void final_pass(void) { farweight = mix(1.0, farweight, mixfac); float nearweight = nearcolor.a; - if (nearweight > 0) { + if (nearweight > 0.0) { nearcolor /= nearweight; } diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl index e8c505bd15f..09a0c75facc 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl @@ -27,11 +27,11 @@ void vert_dof_downsample() /* geometry shading pass, calculate a texture coordinate based on the indexed id */ void vert_dof_coc_scatter_pass() { - vec2 pixel = vec2(1.0 / float(rendertargetdim.x), 1.0 / float(rendertargetdim.y)); + vec2 pixel = vec2(rendertargetdim.x, rendertargetdim.y); /* some math to get the target pixel */ int row = gl_InstanceID / rendertargetdim.x; int column = gl_InstanceID % rendertargetdim.x; - uvcoord = vec2(column, row) * pixel + 0.5 * pixel; + uvcoord = (vec2(column, row) + vec2(0.5)) / pixel; vec2 pos = uvcoord * 2.0 - vec2(1.0); gl_Position = vec4(pos.x, pos.y, 0.0, 1.0); -- cgit v1.2.3 From 339e43e1e821276cf69c0f9829c83999bf79d769 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 20 Mar 2015 15:43:34 +0100 Subject: Only create vertex buffers if supported and clean them up properly. --- source/blender/gpu/intern/gpu_compositing.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index 43dfba1925c..53ce5145388 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -179,12 +179,14 @@ GPUFX *GPU_fx_compositor_create(void) { GPUFX *fx = MEM_callocN(sizeof(GPUFX), "GPUFX compositor"); - glGenBuffersARB(1, &fx->vbuffer); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, fx->vbuffer); - glBufferDataARB(GL_ARRAY_BUFFER_ARB, 16 * sizeof(float), NULL, GL_STATIC_DRAW); - glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, 8 * sizeof(float), fullscreencos); - glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 8 * sizeof(float), 8 * sizeof(float), fullscreenuvs); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + if (GLEW_ARB_vertex_buffer_object) { + glGenBuffersARB(1, &fx->vbuffer); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, fx->vbuffer); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, 16 * sizeof(float), NULL, GL_STATIC_DRAW); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, 8 * sizeof(float), fullscreencos); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 8 * sizeof(float), 8 * sizeof(float), fullscreenuvs); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + } return fx; } @@ -273,6 +275,8 @@ static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo) void GPU_fx_compositor_destroy(GPUFX *fx) { cleanup_fx_gl_data(fx, true); + if (GLEW_ARB_vertex_buffer_object) + glDeleteBuffersARB(1, &fx->vbuffer); MEM_freeN(fx); } -- cgit v1.2.3 From 62b31a6e997ca6ca10cad695252909c657d67401 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 20 Mar 2015 19:56:09 +0500 Subject: Avoid per-draw allocation when drawing currently rendering tiles --- source/blender/editors/space_image/image_draw.c | 7 +++++-- source/blender/render/extern/include/RE_engine.h | 2 +- source/blender/render/intern/source/external_engine.c | 19 ++++++++++++------- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index d03f3c157a9..517cf64214c 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -106,9 +106,10 @@ static void draw_render_info(const bContext *C, if (re) { int total_tiles; + bool need_free_tiles; rcti *tiles; - RE_engine_get_current_tiles(re, &total_tiles, &tiles); + tiles = RE_engine_get_current_tiles(re, &total_tiles, &need_free_tiles); if (total_tiles) { int i, x, y; @@ -133,7 +134,9 @@ static void draw_render_info(const bContext *C, glaDrawBorderCorners(tile, zoomx, zoomy); } - MEM_freeN(tiles); + if (need_free_tiles) { + MEM_freeN(tiles); + } glPopMatrix(); } diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 5edf970c129..bc4c4c54f17 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -159,7 +159,7 @@ void RE_engines_exit(void); RenderEngineType *RE_engines_find(const char *idname); -void RE_engine_get_current_tiles(struct Render *re, int *total_tiles_r, rcti **tiles_r); +rcti* RE_engine_get_current_tiles(struct Render *re, int *total_tiles_r, bool *needs_free_r); struct RenderData *RE_engine_get_render_data(struct Render *re); void RE_bake_engine_set_engine_parameters(struct Render *re, struct Main *bmain, struct Scene *scene); diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 557fcb01778..d5f1cab3a66 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -368,26 +368,31 @@ void RE_engine_set_error_message(RenderEngine *engine, const char *msg) } } -void RE_engine_get_current_tiles(Render *re, int *total_tiles_r, rcti **tiles_r) +rcti* RE_engine_get_current_tiles(Render *re, int *total_tiles_r, bool *needs_free_r) { + static rcti tiles_static[BLENDER_MAX_THREADS]; + const int allocation_step = BLENDER_MAX_THREADS; RenderPart *pa; int total_tiles = 0; - rcti *tiles = NULL; - int allocation_size = 0, allocation_step = BLENDER_MAX_THREADS; + rcti *tiles = tiles_static; + int allocation_size = BLENDER_MAX_THREADS; BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_READ); if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) { *total_tiles_r = 0; - *tiles_r = NULL; BLI_rw_mutex_unlock(&re->partsmutex); - return; + needs_free_r = false; + return NULL; } for (pa = re->parts.first; pa; pa = pa->next) { if (pa->status == PART_STATUS_IN_PROGRESS) { if (total_tiles >= allocation_size) { - if (tiles == NULL) + /* Just in case we're using crazy network rendering with more + * slaves as BLENDER_MAX_THREADS. + */ + if (tiles == tiles_static) tiles = MEM_mallocN(allocation_step * sizeof(rcti), "current engine tiles"); else tiles = MEM_reallocN(tiles, (total_tiles + allocation_step) * sizeof(rcti)); @@ -409,7 +414,7 @@ void RE_engine_get_current_tiles(Render *re, int *total_tiles_r, rcti **tiles_r) } BLI_rw_mutex_unlock(&re->partsmutex); *total_tiles_r = total_tiles; - *tiles_r = tiles; + return tiles; } RenderData *RE_engine_get_render_data(Render *re) -- cgit v1.2.3 From d12ab9a9a8c39733c35e4c967cee52eb7d274b4b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 20 Mar 2015 23:55:47 +1100 Subject: Remove unused armature code ED_armature_deselect_all now simply de-selects --- source/blender/editors/armature/armature_add.c | 6 +-- source/blender/editors/armature/armature_edit.c | 2 +- source/blender/editors/armature/armature_select.c | 60 +++------------------- source/blender/editors/include/ED_armature.h | 2 +- .../editors/space_outliner/outliner_select.c | 2 +- 5 files changed, 13 insertions(+), 59 deletions(-) diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index c2158f02ae3..8074182c395 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -90,7 +90,7 @@ EditBone *ED_armature_edit_bone_add_primitive(Object *obedit_arm, float length, bArmature *arm = obedit_arm->data; EditBone *bone; - ED_armature_deselect_all(obedit_arm, 0); + ED_armature_deselect_all(obedit_arm); /* Create a bone */ bone = ED_armature_edit_bone_add(arm, "Bone"); @@ -145,7 +145,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op)) to_root = 1; } - ED_armature_deselect_all(obedit, 0); + ED_armature_deselect_all(obedit); /* we re-use code for mirror editing... */ flipbone = NULL; @@ -914,7 +914,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op) mul_m3_m3m3(totmat, obmat, viewmat); invert_m3_m3(imat, totmat); - ED_armature_deselect_all(obedit, 0); + ED_armature_deselect_all(obedit); /* Create a bone */ bone = ED_armature_edit_bone_add(obedit->data, name); diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index 6fe4cbf4ade..29b7872f304 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -714,7 +714,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op) } if (newbone) { - ED_armature_deselect_all(obedit, 0); + ED_armature_deselect_all(obedit); arm->act_edbone = newbone; newbone->flag |= BONE_TIPSEL; } diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 5061ba9a812..720b9b7821a 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -388,61 +388,14 @@ static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2], return NULL; } - - -/* toggle==0: deselect - * toggle==1: swap (based on test) - * toggle==2: swap (no test), CURRENTLY UNUSED - */ -void ED_armature_deselect_all(Object *obedit, int toggle) +void ED_armature_deselect_all(Object *obedit) { bArmature *arm = obedit->data; - EditBone *eBone; - int sel = 1; - - if (toggle == 1) { - /* Determine if there are any selected bones - * and therefore whether we are selecting or deselecting */ - for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { - // if (arm->layer & eBone->layer) { - if (eBone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) { - sel = 0; - break; - } - // } - } - } - else { - sel = toggle; - } + EditBone *ebone; - /* Set the flags */ - for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { - if (sel == 2) { - /* invert selection of bone */ - if (EBONE_VISIBLE(arm, eBone)) { - eBone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - if (arm->act_edbone == eBone) - arm->act_edbone = NULL; - } - } - else if (sel == 1) { - /* select bone */ - if (EBONE_VISIBLE(arm, eBone)) { - eBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - if (eBone->parent) - eBone->parent->flag |= (BONE_TIPSEL); - } - } - else { - /* deselect bone */ - eBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - if (arm->act_edbone == eBone) - arm->act_edbone = NULL; - } + for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { + ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); } - - ED_armature_sync_selection(arm->edbo); } void ED_armature_deselect_all_visible(Object *obedit) @@ -489,8 +442,9 @@ bool mouse_armature(bContext *C, const int mval[2], bool extend, bool deselect, nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, 1, &selmask); if (nearBone) { - if (!extend && !deselect && !toggle) - ED_armature_deselect_all(obedit, 0); + if (!extend && !deselect && !toggle) { + ED_armature_deselect_all(obedit); + } /* by definition the non-root connected bones have no root point drawn, * so a root selection needs to be delivered to the parent tip */ diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index b08cc12dc3e..da756422bdb 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -119,7 +119,7 @@ void ED_keymap_armature(struct wmKeyConfig *keyconf); void ED_armature_from_edit(struct bArmature *arm); void ED_armature_to_edit(struct bArmature *arm); void ED_armature_edit_free(struct bArmature *arm); -void ED_armature_deselect_all(struct Object *obedit, int toggle); +void ED_armature_deselect_all(struct Object *obedit); void ED_armature_deselect_all_visible(struct Object *obedit); int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 730ee02f448..6050b66fdb7 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -618,7 +618,7 @@ static eOLDrawState tree_element_active_ebone( if (set != OL_SETSEL_NONE) { if (set == OL_SETSEL_NORMAL) { if (!(ebone->flag & BONE_HIDDEN_A)) { - ED_armature_deselect_all(scene->obedit, 0); // deselect + ED_armature_deselect_all(scene->obedit); tree_element_active_ebone__sel(C, scene, arm, ebone, true); status = OL_DRAWSEL_NORMAL; } -- cgit v1.2.3 From 63ab5b0883612878818c931b6765237eaeecca4a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 21 Mar 2015 02:16:39 +1100 Subject: Fix for building win32 headless --- intern/ghost/CMakeLists.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index dc55a81b0d8..761bcb4dd27 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -297,11 +297,6 @@ elseif(WIN32) intern/GHOST_NDOFManagerWin32.h ) endif() - - list(APPEND INC - ../utfconv - ) - endif() if(WITH_GL_EGL AND NOT (WITH_HEADLESS OR WITH_GHOST_SDL)) @@ -334,6 +329,10 @@ elseif(WIN32) intern/GHOST_SystemPathsWin32.h ) + list(APPEND INC + ../utfconv + ) + endif() add_definitions(${GL_DEFINITIONS}) -- cgit v1.2.3 From 94a3924eab251c7e487c9f2b631e55e9c6ebf2e9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 21 Mar 2015 02:25:28 +1100 Subject: Correct recent commit --- source/blender/render/intern/source/external_engine.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index d5f1cab3a66..c66b9c2ce0d 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -368,7 +368,7 @@ void RE_engine_set_error_message(RenderEngine *engine, const char *msg) } } -rcti* RE_engine_get_current_tiles(Render *re, int *total_tiles_r, bool *needs_free_r) +rcti* RE_engine_get_current_tiles(Render *re, int *total_tiles_r, bool *r_needs_free) { static rcti tiles_static[BLENDER_MAX_THREADS]; const int allocation_step = BLENDER_MAX_THREADS; @@ -382,7 +382,7 @@ rcti* RE_engine_get_current_tiles(Render *re, int *total_tiles_r, bool *needs_fr if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) { *total_tiles_r = 0; BLI_rw_mutex_unlock(&re->partsmutex); - needs_free_r = false; + *r_needs_free = false; return NULL; } -- cgit v1.2.3 From b9dc4f851bd01a5ca5c7019ea7ef2356d010be5f Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 20 Mar 2015 16:35:26 +0100 Subject: Fix link error with GLEW --- source/blender/gpu/intern/gpu_compositing.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index 53ce5145388..96de0db0acb 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -50,7 +50,7 @@ #include "GPU_extensions.h" #include "GPU_compositing.h" -#include "GL/glew.h" +#include "GPU_glew.h" #include "MEM_guardedalloc.h" -- cgit v1.2.3 From f91850d564576189882e872e26f8da48cfbd8829 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 21 Mar 2015 03:02:09 +1100 Subject: Disable IME for headless builds --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e8552f2a1d..21efa668292 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -674,6 +674,7 @@ if(WITH_GHOST_SDL OR WITH_HEADLESS) set(WITH_X11_XINPUT OFF) set(WITH_X11_XF86VMODE OFF) set(WITH_GHOST_XDND OFF) + set(WITH_INPUT_IME OFF) endif() if(WITH_CPU_SSE) -- cgit v1.2.3 From 8ff4c53e63dc1eb7f4855915dd45d044b854e301 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 20 Mar 2015 21:09:52 +0500 Subject: Correction to previous commit, initialization of needs_free got lost by accident --- source/blender/render/intern/source/external_engine.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index c66b9c2ce0d..653f3f0786a 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -379,10 +379,11 @@ rcti* RE_engine_get_current_tiles(Render *re, int *total_tiles_r, bool *r_needs_ BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_READ); + *r_needs_free = false; + if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) { *total_tiles_r = 0; BLI_rw_mutex_unlock(&re->partsmutex); - *r_needs_free = false; return NULL; } @@ -398,6 +399,7 @@ rcti* RE_engine_get_current_tiles(Render *re, int *total_tiles_r, bool *r_needs_ tiles = MEM_reallocN(tiles, (total_tiles + allocation_step) * sizeof(rcti)); allocation_size += allocation_step; + *r_needs_free = true; } tiles[total_tiles] = pa->disprect; -- cgit v1.2.3 From 919a6654974f40c553ba30a4aba89e9d02251246 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 20 Mar 2015 21:14:50 +0500 Subject: Cycles: Avoid memcpy of intersecting memory Could happen when assignment happens to self during sorting. --- intern/cycles/bvh/bvh_params.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h index 99bfd9449da..af8d8eeb3ee 100644 --- a/intern/cycles/bvh/bvh_params.h +++ b/intern/cycles/bvh/bvh_params.h @@ -113,7 +113,9 @@ public: __forceinline int prim_type() const { return type; } BVHReference& operator=(const BVHReference &arg) { - memcpy(this, &arg, sizeof(BVHReference)); + if(&arg != this) { + memcpy(this, &arg, sizeof(BVHReference)); + } return *this; } -- cgit v1.2.3 From 0582aa6f130a4b1182fc5db646db3c7ac4a8ca46 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Fri, 20 Mar 2015 17:57:35 +0100 Subject: Partly fix T44025, pixelFormat retain was left, for 2.74 backport --- intern/ghost/intern/GHOST_ContextCGL.mm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm index 0b290c617a5..cf94dc83d18 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.mm +++ b/intern/ghost/intern/GHOST_ContextCGL.mm @@ -292,14 +292,16 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext() [m_openGLView setPixelFormat:pixelFormat]; - m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:s_sharedOpenGLContext]; + m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:s_sharedOpenGLContext]; // +1 refCount to pixelFormat if (m_openGLContext == nil) goto error; if (s_sharedCount == 0) s_sharedOpenGLContext = m_openGLContext; - + + [pixelFormat release]; // -1 refCount to pixelFormat + s_sharedCount++; #ifdef GHOST_MULTITHREADED_OPENGL -- cgit v1.2.3 From d5abff589ebdfc2b9c110f4a67dad0db336482b7 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 20 Mar 2015 19:46:48 +0100 Subject: Fix scons build --- SConstruct | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SConstruct b/SConstruct index 00a95b0114b..52fef2f3b87 100644 --- a/SConstruct +++ b/SConstruct @@ -771,6 +771,9 @@ if B.targets != ['cudakernels']: data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl") + data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl") + data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl") + data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_lib.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_vert.glsl") -- cgit v1.2.3 From ed61017391a6d5b9d1bde39e4df95c63ec01cf05 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Fri, 20 Mar 2015 20:24:30 +0100 Subject: Really fix scons with new glsl shaders --- source/blender/gpu/SConscript | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript index f52b39dba3b..9a3ea8f129c 100644 --- a/source/blender/gpu/SConscript +++ b/source/blender/gpu/SConscript @@ -66,6 +66,9 @@ sources.extend(( os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_vert.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_ssao_frag.glsl.c"), + os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_hq_frag.glsl.c"), + os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_hq_vert.glsl.c"), + os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_hq_geo.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_vert.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_depth_resolve.glsl.c"), -- cgit v1.2.3 From 997c0c837b5a4d090b124dc5a2e85b139e1ceb56 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Fri, 20 Mar 2015 20:26:51 +0100 Subject: Fix indentation in last commit, tab slipped in --- source/blender/gpu/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript index 9a3ea8f129c..8d0ef394a06 100644 --- a/source/blender/gpu/SConscript +++ b/source/blender/gpu/SConscript @@ -67,7 +67,7 @@ sources.extend(( os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_vert.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_ssao_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_hq_frag.glsl.c"), - os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_hq_vert.glsl.c"), + os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_hq_vert.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_hq_geo.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_vert.glsl.c"), -- cgit v1.2.3 From e88cfc28b24e1c6c1d67858a6bc930389e0041ea Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 21 Mar 2015 15:11:19 +1100 Subject: View3D: use defines for default zoom-levels --- source/blender/blenkernel/BKE_camera.h | 4 ++++ source/blender/blenkernel/intern/camera.c | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h index 77296920ee2..ead58c25d6b 100644 --- a/source/blender/blenkernel/BKE_camera.h +++ b/source/blender/blenkernel/BKE_camera.h @@ -104,6 +104,10 @@ typedef struct CameraParams { float winmat[4][4]; } CameraParams; +/* values for CameraParams.zoom, need to be taken into account for some operations */ +#define CAMERA_PARAM_ZOOM_INIT_CAMOB 1.0f +#define CAMERA_PARAM_ZOOM_INIT_PERSP 2.0f + void BKE_camera_params_init(CameraParams *params); void BKE_camera_params_from_object(CameraParams *params, struct Object *camera); void BKE_camera_params_from_view3d(CameraParams *params, struct View3D *v3d, struct RegionView3D *rv3d); diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 451656a9bca..4588c00b2f6 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -274,7 +274,7 @@ void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView params->shiftx *= params->zoom; params->shifty *= params->zoom; - params->zoom = 1.0f / params->zoom; + params->zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB / params->zoom; } else if (rv3d->persp == RV3D_ORTHO) { /* orthographic view */ @@ -285,11 +285,11 @@ void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView params->is_ortho = true; /* make sure any changes to this match ED_view3d_radius_to_ortho_dist() */ params->ortho_scale = rv3d->dist * sensor_size / v3d->lens; - params->zoom = 2.0f; + params->zoom = CAMERA_PARAM_ZOOM_INIT_PERSP; } else { /* perspective view */ - params->zoom = 2.0f; + params->zoom = CAMERA_PARAM_ZOOM_INIT_PERSP; } } -- cgit v1.2.3 From e0611ca832d793694cbda0fbae1a4388b81fc589 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 21 Mar 2015 15:11:30 +1100 Subject: View3D: fix view-selected zoom logic - Correct logic converting radius to view distance. - Wasn't taking view-zoom into account converting lens to angle. - Support framing the selection in the camera bounds (for camera locked views). Add ED_view3d_radius_to_dist to handles these details. --- source/blender/blenkernel/intern/camera.c | 2 +- source/blender/editors/include/ED_view3d.h | 8 +- source/blender/editors/space_view3d/view3d_edit.c | 39 ++----- source/blender/editors/space_view3d/view3d_view.c | 134 ++++++++++++++++++---- 4 files changed, 130 insertions(+), 53 deletions(-) diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 4588c00b2f6..ed400bcf565 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -283,7 +283,7 @@ void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView params->clipsta = -params->clipend; params->is_ortho = true; - /* make sure any changes to this match ED_view3d_radius_to_ortho_dist() */ + /* make sure any changes to this match ED_view3d_radius_to_dist_ortho() */ params->ortho_scale = rv3d->dist * sensor_size / v3d->lens; params->zoom = CAMERA_PARAM_ZOOM_INIT_PERSP; } diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 11f961605af..ec53bce2eb7 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -252,8 +252,12 @@ void ED_view3d_clipping_disable(void); float ED_view3d_pixel_size(struct RegionView3D *rv3d, const float co[3]); -float ED_view3d_radius_to_persp_dist(const float angle, const float radius); -float ED_view3d_radius_to_ortho_dist(const float lens, const float radius); +float ED_view3d_radius_to_dist_persp(const float angle, const float radius); +float ED_view3d_radius_to_dist_ortho(const float lens, const float radius); +float ED_view3d_radius_to_dist( + const struct View3D *v3d, const struct ARegion *ar, + const char persp, const bool use_aspect, + const float radius); void drawcircball(int mode, const float cent[3], float rad, float tmat[4][4]); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 51915e05a9e..0bced34e465 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -2748,29 +2748,15 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar, size = max_fff(afm[0], afm[1], afm[2]); if (ok_dist) { - /* fix up zoom distance if needed */ + char persp; if (rv3d->is_persp) { - float lens, sensor_size; - /* offset the view based on the lens */ if (rv3d->persp == RV3D_CAMOB && ED_view3d_camera_lock_check(v3d, rv3d)) { - CameraParams params; - BKE_camera_params_init(¶ms); - params.clipsta = v3d->near; - params.clipend = v3d->far; - BKE_camera_params_from_object(¶ms, v3d->camera); - - lens = params.lens; - sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y); + persp = RV3D_CAMOB; } else { - lens = v3d->lens; - sensor_size = DEFAULT_SENSOR_WIDTH; + persp = RV3D_PERSP; } - size = ED_view3d_radius_to_persp_dist(focallength_to_fov(lens, sensor_size), size / 2.0f) * VIEW3D_MARGIN; - - /* do not zoom closer than the near clipping plane */ - size = max_ff(size, v3d->near * 1.5f); } else { /* ortho */ if (size < 0.0001f) { @@ -2779,7 +2765,15 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar, } else { /* adjust zoom so it looks nicer */ - size = ED_view3d_radius_to_ortho_dist(v3d->lens, size / 2.0f) * VIEW3D_MARGIN; + persp = RV3D_ORTHO; + } + } + + if (ok_dist) { + new_dist = ED_view3d_radius_to_dist(v3d, ar, persp, true, (size / 2) * VIEW3D_MARGIN); + if (rv3d->is_persp) { + /* don't zoom closer than the near clipping plane */ + new_dist = max_ff(new_dist, v3d->near * 1.5f); } } } @@ -2787,15 +2781,6 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar, mid_v3_v3v3(new_ofs, min, max); negate_v3(new_ofs); - new_dist = size; - - /* correction for window aspect ratio */ - if (ar->winy > 2 && ar->winx > 2) { - size = (float)ar->winx / (float)ar->winy; - if (size < 1.0f) size = 1.0f / size; - new_dist *= size; - } - if (rv3d->persp == RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, rv3d)) { rv3d->persp = RV3D_PERSP; ED_view3d_smooth_view(C, v3d, ar, v3d->camera, NULL, diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 4888c6846d2..1c10a857179 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1214,7 +1214,7 @@ static bool view3d_localview_init( View3D *v3d = sa->spacedata.first; Base *base; float min[3], max[3], box[3], mid[3]; - float size = 0.0f, size_persp = 0.0f, size_ortho = 0.0f; + float size = 0.0f; unsigned int locallay; bool ok = false; @@ -1252,13 +1252,6 @@ static bool view3d_localview_init( sub_v3_v3v3(box, max, min); size = max_fff(box[0], box[1], box[2]); - - /* do not zoom closer than the near clipping plane */ - size = max_ff(size, v3d->near * 1.5f); - - /* perspective size (we always switch out of camera view so no need to use its lens size) */ - size_persp = ED_view3d_radius_to_persp_dist(focallength_to_fov(v3d->lens, DEFAULT_SENSOR_WIDTH), size / 2.0f) * VIEW3D_MARGIN; - size_ortho = ED_view3d_radius_to_ortho_dist(v3d->lens, size / 2.0f) * VIEW3D_MARGIN; } if (ok == true) { @@ -1275,6 +1268,7 @@ static bool view3d_localview_init( for (ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->regiontype == RGN_TYPE_WINDOW) { RegionView3D *rv3d = ar->regiondata; + bool ok_dist = true; /* new view values */ Object *camera_old = NULL; @@ -1290,25 +1284,24 @@ static bool view3d_localview_init( camera_old = v3d->camera; } - /* perspective should be a bit farther away to look nice */ - if (rv3d->persp != RV3D_ORTHO) { - dist_new = size_persp; - } - else { - dist_new = size_ortho; + if (rv3d->persp == RV3D_ORTHO) { + if (size < 0.0001) { + ok_dist = false; + } } - /* correction for window aspect ratio */ - if (ar->winy > 2 && ar->winx > 2) { - float asp = (float)ar->winx / (float)ar->winy; - if (asp < 1.0f) asp = 1.0f / asp; - dist_new *= asp; + if (ok_dist) { + dist_new = ED_view3d_radius_to_dist(v3d, ar, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN); + if (rv3d->persp == RV3D_PERSP) { + /* don't zoom closer than the near clipping plane */ + dist_new = max_ff(dist_new, v3d->near * 1.5f); + } } ED_view3d_smooth_view_ex( wm, win, sa, v3d, ar, camera_old, NULL, - ofs_new, NULL, &dist_new, NULL, + ofs_new, NULL, ok_dist ? &dist_new : NULL, NULL, smooth_viewtx); } } @@ -1720,16 +1713,111 @@ float ED_view3d_pixel_size(RegionView3D *rv3d, const float co[3]) return mul_project_m4_v3_zfac(rv3d->persmat, co) * rv3d->pixsize * U.pixelsize; } -float ED_view3d_radius_to_persp_dist(const float angle, const float radius) +float ED_view3d_radius_to_dist_persp(const float angle, const float radius) { - return (radius / 2.0f) * fabsf(1.0f / cosf((((float)M_PI) - angle) / 2.0f)); + return radius * (1.0f / tanf(angle / 2.0f)); } -float ED_view3d_radius_to_ortho_dist(const float lens, const float radius) +float ED_view3d_radius_to_dist_ortho(const float lens, const float radius) { return radius / (DEFAULT_SENSOR_WIDTH / lens); } +/** + * Return a new RegionView3D.dist value to fit the \a radius. + * + * \note Depth isn't taken into account, this will fit a flat plane exactly, + * but points towards the view (with a perspective projection), + * may be within the radius but outside the view. eg: + * + *
+ *           +
+ * pt --> + /^ radius
+ *         / |
+ *        /  |
+ * view  +   +
+ *        \  |
+ *         \ |
+ *          \|
+ *           +
+ * 
+ * + * \param ar Can be NULL if \a use_aspect is false. + * \param persp Allow the caller to tell what kind of perspective to use (ortho/view/camera) + * \param use_aspect Increase the distance to account for non 1:1 view aspect. + * \param radius The radius will be fitted exactly, typically pre-scaled by a margin (#VIEW3D_MARGIN). + */ +float ED_view3d_radius_to_dist( + const View3D *v3d, const ARegion *ar, + const char persp, const bool use_aspect, + const float radius) +{ + float dist; + + BLI_assert(ELEM(persp, RV3D_ORTHO, RV3D_PERSP, RV3D_CAMOB)); + BLI_assert((persp != RV3D_CAMOB) || v3d->camera); + + if (persp == RV3D_ORTHO) { + dist = ED_view3d_radius_to_dist_ortho(v3d->lens, radius); + } + else { + float lens, sensor_size, zoom; + float angle; + + if (persp == RV3D_CAMOB) { + CameraParams params; + BKE_camera_params_init(¶ms); + params.clipsta = v3d->near; + params.clipend = v3d->far; + BKE_camera_params_from_object(¶ms, v3d->camera); + + lens = params.lens; + sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y); + + /* ignore 'rv3d->camzoom' because we wan't to fit to the cameras frame */ + zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB; + } + else { + lens = v3d->lens; + sensor_size = DEFAULT_SENSOR_WIDTH; + zoom = CAMERA_PARAM_ZOOM_INIT_PERSP; + } + + angle = focallength_to_fov(lens, sensor_size); + + /* zoom influences lens, correct this by scaling the angle as a distance (by the zoom-level) */ + angle = ((atanf(tanf(angle / 2.0f) * zoom) * 2.0f)); + + dist = ED_view3d_radius_to_dist_persp(angle, radius); + } + + if (use_aspect) { + const RegionView3D *rv3d = ar->regiondata; + + float winx, winy; + + if (persp == RV3D_CAMOB) { + /* camera frame x/y in pixels */ + winx = ar->winx / rv3d->viewcamtexcofac[0]; + winy = ar->winy / rv3d->viewcamtexcofac[1]; + } + else { + winx = ar->winx; + winy = ar->winy; + } + + if (winx && winy) { + float aspect = winx / winy; + if (aspect < 1.0f) { + aspect = 1.0f / aspect; + } + dist *= aspect; + } + } + + return dist; +} + /* view matrix properties utilities */ /* unused */ -- cgit v1.2.3 From 0025d90b98c69dd4ed149918e716b92c81328bbb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 21 Mar 2015 16:40:17 +1100 Subject: Cleanup: use tabs --- GNUmakefile | 2 +- source/blender/blenkernel/intern/tracking.c | 2 +- source/blender/blenlib/intern/BLI_ghash.c | 66 ++++++++++++++--------------- source/blender/blenlib/intern/hash_mm2a.c | 2 +- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 775d0ae532b..5a3a0b7848d 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -65,7 +65,7 @@ ifneq "$(findstring cycles, $(MAKECMDGOALS))" "" BUILD_CMAKE_ARGS:=$(BUILD_CMAKE_ARGS) -C"$(BLENDER_DIR)/build_files/cmake/config/cycles_standalone.cmake" endif ifneq "$(findstring headless, $(MAKECMDGOALS))" "" - BUILD_DIR:=$(BUILD_DIR)_bpy + BUILD_DIR:=$(BUILD_DIR)_headless BUILD_CMAKE_ARGS:=$(BUILD_CMAKE_ARGS) -C"$(BLENDER_DIR)/build_files/cmake/config/blender_headless.cmake" endif ifneq "$(findstring bpy, $(MAKECMDGOALS))" "" diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 0037002f6d8..83db0639468 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -547,7 +547,7 @@ bool BKE_tracking_track_has_enabled_marker_at_frame(MovieTrackingTrack *track, i * - If action is TRACK_CLEAR_UPTO path from the beginning up to * ref_frame-1 will be clear. * - * - If action is TRACK_CLEAR_ALL only mareker at frame ref_frame will remain. + * - If action is TRACK_CLEAR_ALL only marker at frame ref_frame will remain. * * NOTE: frame number should be in clip space, not scene space */ diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index a2233c38270..49d3cecafed 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -547,8 +547,8 @@ static void ghash_free_cb(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP va { unsigned int i; - BLI_assert(keyfreefp || valfreefp); - BLI_assert(!valfreefp|| !(gh->flag & GHASH_FLAG_IS_GSET)); + BLI_assert(keyfreefp || valfreefp); + BLI_assert(!valfreefp || !(gh->flag & GHASH_FLAG_IS_GSET)); for (i = 0; i < gh->nbuckets; i++) { Entry *e; @@ -1370,37 +1370,37 @@ double BLI_ghash_calc_quality_ex( } { - uint64_t sum = 0; - uint64_t overloaded_buckets_threshold = (uint64_t)max_ii(GHASH_LIMIT_GROW(1), 1); - uint64_t sum_overloaded = 0; - uint64_t sum_empty = 0; - - for (i = 0; i < gh->nbuckets; i++) { - uint64_t count = 0; - Entry *e; - for (e = gh->buckets[i]; e; e = e->next) { - count++; - } - if (r_biggest_bucket) { - *r_biggest_bucket = max_ii(*r_biggest_bucket, (int)count); - } - if (r_prop_overloaded_buckets && (count > overloaded_buckets_threshold)) { - sum_overloaded++; - } - if (r_prop_empty_buckets && !count) { - sum_empty++; - } - sum += count * (count + 1); - } - if (r_prop_overloaded_buckets) { - *r_prop_overloaded_buckets = (double)sum_overloaded / (double)gh->nbuckets; - } - if (r_prop_empty_buckets) { - *r_prop_empty_buckets = (double)sum_empty / (double)gh->nbuckets; - } - return ((double)sum * (double)gh->nbuckets / - ((double)gh->nentries * (gh->nentries + 2 * gh->nbuckets - 1))); - } + uint64_t sum = 0; + uint64_t overloaded_buckets_threshold = (uint64_t)max_ii(GHASH_LIMIT_GROW(1), 1); + uint64_t sum_overloaded = 0; + uint64_t sum_empty = 0; + + for (i = 0; i < gh->nbuckets; i++) { + uint64_t count = 0; + Entry *e; + for (e = gh->buckets[i]; e; e = e->next) { + count++; + } + if (r_biggest_bucket) { + *r_biggest_bucket = max_ii(*r_biggest_bucket, (int)count); + } + if (r_prop_overloaded_buckets && (count > overloaded_buckets_threshold)) { + sum_overloaded++; + } + if (r_prop_empty_buckets && !count) { + sum_empty++; + } + sum += count * (count + 1); + } + if (r_prop_overloaded_buckets) { + *r_prop_overloaded_buckets = (double)sum_overloaded / (double)gh->nbuckets; + } + if (r_prop_empty_buckets) { + *r_prop_empty_buckets = (double)sum_empty / (double)gh->nbuckets; + } + return ((double)sum * (double)gh->nbuckets / + ((double)gh->nentries * (gh->nentries + 2 * gh->nbuckets - 1))); + } } double BLI_gset_calc_quality_ex( GSet *gs, double *r_load, double *r_variance, diff --git a/source/blender/blenlib/intern/hash_mm2a.c b/source/blender/blenlib/intern/hash_mm2a.c index 87ba542e147..af6ef4f355f 100644 --- a/source/blender/blenlib/intern/hash_mm2a.c +++ b/source/blender/blenlib/intern/hash_mm2a.c @@ -135,7 +135,7 @@ uint32_t BLI_hash_mm2(const unsigned char *data, size_t len, uint32_t seed) case 1: h ^= data[0]; h *= MM2A_M; - }; + } /* Do a few final mixes of the hash to ensure the last few bytes are well-incorporated. */ MM2A_MIX_FINALIZE(h); -- cgit v1.2.3 From 6e50bdd870b7486cea128e0dcc9777045237ea4a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 21 Mar 2015 22:10:43 +1100 Subject: Cleanup: constify scene/modifiers --- source/blender/blenkernel/BKE_dynamicpaint.h | 4 ++-- source/blender/blenkernel/BKE_editmesh.h | 2 +- source/blender/blenkernel/BKE_scene.h | 18 +++++++++--------- source/blender/blenkernel/BKE_texture.h | 4 +++- source/blender/blenkernel/intern/DerivedMesh.c | 6 +++--- source/blender/blenkernel/intern/dynamicpaint.c | 14 +++++++------- source/blender/blenkernel/intern/editderivedmesh.c | 2 +- source/blender/blenkernel/intern/scene.c | 20 ++++++++++---------- source/blender/blenkernel/intern/texture.c | 4 +++- source/blender/modifiers/intern/MOD_util.c | 2 +- source/blender/modifiers/intern/MOD_util.h | 2 +- 11 files changed, 41 insertions(+), 37 deletions(-) diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h index a8e152fd301..1aba72e8cd8 100644 --- a/source/blender/blenkernel/BKE_dynamicpaint.h +++ b/source/blender/blenkernel/BKE_dynamicpaint.h @@ -70,8 +70,8 @@ void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct Dyn bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, struct Scene *scene); struct DynamicPaintSurface *dynamicPaint_createNewSurface(struct DynamicPaintCanvasSettings *canvas, struct Scene *scene); -void dynamicPaint_clearSurface(struct Scene *scene, struct DynamicPaintSurface *surface); -bool dynamicPaint_resetSurface(struct Scene *scene, struct DynamicPaintSurface *surface); +void dynamicPaint_clearSurface(const struct Scene *scene, struct DynamicPaintSurface *surface); +bool dynamicPaint_resetSurface(const struct Scene *scene, struct DynamicPaintSurface *surface); void dynamicPaint_freeSurface(struct DynamicPaintSurface *surface); void dynamicPaint_freeCanvas(struct DynamicPaintModifierData *pmd); void dynamicPaint_freeBrush(struct DynamicPaintModifierData *pmd); diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index 38c8cf12969..f80e03fda9b 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -97,7 +97,7 @@ void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype); /* editderivedmesh.c */ /* should really be defined in editmesh.c, but they use 'EditDerivedBMesh' */ void BKE_editmesh_statvis_calc(BMEditMesh *em, struct DerivedMesh *dm, - struct MeshStatVis *statvis); + const struct MeshStatVis *statvis); float (*BKE_editmesh_vertexCos_get(struct BMEditMesh *em, struct Scene *scene, int *r_numVerts))[3]; diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 149472db8fa..c191f3805a6 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -113,8 +113,8 @@ char *BKE_scene_find_last_marker_name(struct Scene *scene, int frame); /* checks for cycle, returns 1 if it's all OK */ bool BKE_scene_validate_setscene(struct Main *bmain, struct Scene *sce); -float BKE_scene_frame_get(struct Scene *scene); -float BKE_scene_frame_get_from_ctime(struct Scene *scene, const float frame); +float BKE_scene_frame_get(const struct Scene *scene); +float BKE_scene_frame_get_from_ctime(const struct Scene *scene, const float frame); void BKE_scene_frame_set(struct Scene *scene, double cfra); /* ** Scene evaluation ** */ @@ -126,15 +126,15 @@ struct SceneRenderLayer *BKE_scene_add_render_layer(struct Scene *sce, const cha bool BKE_scene_remove_render_layer(struct Main *main, struct Scene *scene, struct SceneRenderLayer *srl); /* render profile */ -int get_render_subsurf_level(struct RenderData *r, int level); -int get_render_child_particle_number(struct RenderData *r, int num); -int get_render_shadow_samples(struct RenderData *r, int samples); -float get_render_aosss_error(struct RenderData *r, float error); +int get_render_subsurf_level(const struct RenderData *r, int level); +int get_render_child_particle_number(const struct RenderData *r, int num); +int get_render_shadow_samples(const struct RenderData *r, int samples); +float get_render_aosss_error(const struct RenderData *r, float error); -bool BKE_scene_use_new_shading_nodes(struct Scene *scene); +bool BKE_scene_use_new_shading_nodes(const struct Scene *scene); -bool BKE_scene_uses_blender_internal(struct Scene *scene); -bool BKE_scene_uses_blender_game(struct Scene *scene); +bool BKE_scene_uses_blender_internal(const struct Scene *scene); +bool BKE_scene_uses_blender_game(const struct Scene *scene); void BKE_scene_disable_color_management(struct Scene *scene); bool BKE_scene_check_color_management_enabled(const struct Scene *scene); diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index ebf85ff51d1..03ddbb706d7 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -134,7 +134,9 @@ struct OceanTex *BKE_copy_oceantex(struct OceanTex *ot); bool BKE_texture_dependsOnTime(const struct Tex *texture); bool BKE_texture_is_image_user(const struct Tex *tex); -void BKE_texture_get_value(struct Scene *scene, struct Tex *texture, float *tex_co, struct TexResult *texres, bool use_color_management); +void BKE_texture_get_value( + const struct Scene *scene, struct Tex *texture, + float *tex_co, struct TexResult *texres, bool use_color_management); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 0bfa3628967..bfb5098c5ae 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1131,7 +1131,7 @@ typedef struct DMWeightColorInfo { } DMWeightColorInfo; -static int dm_drawflag_calc(ToolSettings *ts) +static int dm_drawflag_calc(const ToolSettings *ts) { return ((ts->multipaint ? CALC_WP_MULTIPAINT : /* CALC_WP_GROUP_USER_ACTIVE or CALC_WP_GROUP_USER_ALL*/ @@ -1368,7 +1368,7 @@ void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag, } } -static void DM_update_statvis_color(Scene *scene, Object *ob, DerivedMesh *dm) +static void DM_update_statvis_color(const Scene *scene, Object *ob, DerivedMesh *dm) { BMEditMesh *em = BKE_editmesh_from_object(ob); @@ -2340,7 +2340,7 @@ static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, C BLI_assert(!(em->derivedFinal->dirty & DM_DIRTY_NORMALS)); } -static CustomDataMask object_get_datamask(Scene *scene, Object *ob) +static CustomDataMask object_get_datamask(const Scene *scene, Object *ob) { Object *actob = scene->basact ? scene->basact->object : NULL; CustomDataMask mask = ob->customdata_mask; diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 762b24dfdf8..7b7f024d2dc 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -579,7 +579,7 @@ static void scene_setSubframe(Scene *scene, float subframe) scene->r.subframe = subframe; } -static int surface_getBrushFlags(DynamicPaintSurface *surface, Scene *scene) +static int surface_getBrushFlags(DynamicPaintSurface *surface, const Scene *scene) { Base *base = NULL; GroupObject *go = NULL; @@ -1447,7 +1447,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for MEM_freeN(temp_data); } -static void dynamicPaint_setInitialColor(Scene *scene, DynamicPaintSurface *surface) +static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface *surface) { PaintSurfaceData *sData = surface->data; PaintPoint *pPoint = (PaintPoint *)sData->type_data; @@ -1595,7 +1595,7 @@ static void dynamicPaint_setInitialColor(Scene *scene, DynamicPaintSurface *surf } /* clears surface data back to zero */ -void dynamicPaint_clearSurface(Scene *scene, DynamicPaintSurface *surface) +void dynamicPaint_clearSurface(const Scene *scene, DynamicPaintSurface *surface) { PaintSurfaceData *sData = surface->data; if (sData && sData->type_data) { @@ -1620,7 +1620,7 @@ void dynamicPaint_clearSurface(Scene *scene, DynamicPaintSurface *surface) } /* completely (re)initializes surface (only for point cache types)*/ -bool dynamicPaint_resetSurface(Scene *scene, DynamicPaintSurface *surface) +bool dynamicPaint_resetSurface(const Scene *scene, DynamicPaintSurface *surface) { int numOfPoints = dynamicPaint_surfaceNumOfPoints(surface); /* free existing data */ @@ -1647,7 +1647,7 @@ bool dynamicPaint_resetSurface(Scene *scene, DynamicPaintSurface *surface) } /* make sure allocated surface size matches current requirements */ -static bool dynamicPaint_checkSurfaceData(Scene *scene, DynamicPaintSurface *surface) +static bool dynamicPaint_checkSurfaceData(const Scene *scene, DynamicPaintSurface *surface) { if (!surface->data || ((dynamicPaint_surfaceNumOfPoints(surface) != surface->data->total_points))) { return dynamicPaint_resetSurface(scene, surface); @@ -4696,7 +4696,7 @@ static int dynamicPaint_surfaceHasMoved(DynamicPaintSurface *surface, Object *ob return ret; } -static int surface_needsVelocityData(DynamicPaintSurface *surface, Scene *scene) +static int surface_needsVelocityData(DynamicPaintSurface *surface, const Scene *scene) { if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) return 1; @@ -4716,7 +4716,7 @@ static int surface_needsAccelerationData(DynamicPaintSurface *surface) } /* Prepare for surface step by creating PaintBakeNormal data */ -static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *scene, Object *ob) +static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const Scene *scene, Object *ob) { PaintSurfaceData *sData = surface->data; PaintAdjData *adj_data = sData->adj_data; diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 082edb01efd..40f3022c192 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -2253,7 +2253,7 @@ static void statvis_calc_sharp( } void BKE_editmesh_statvis_calc(BMEditMesh *em, DerivedMesh *dm, - MeshStatVis *statvis) + const MeshStatVis *statvis) { EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; BLI_assert(dm == NULL || dm->type == DM_TYPE_EDITBMESH); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index f94f7cd8f0b..c28d741d7ec 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1140,13 +1140,13 @@ bool BKE_scene_validate_setscene(Main *bmain, Scene *sce) /* This function is needed to cope with fractional frames - including two Blender rendering features * mblur (motion blur that renders 'subframes' and blurs them together), and fields rendering. */ -float BKE_scene_frame_get(Scene *scene) +float BKE_scene_frame_get(const Scene *scene) { return BKE_scene_frame_get_from_ctime(scene, scene->r.cfra); } /* This function is used to obtain arbitrary fractional frames */ -float BKE_scene_frame_get_from_ctime(Scene *scene, const float frame) +float BKE_scene_frame_get_from_ctime(const Scene *scene, const float frame) { float ctime = frame; ctime += scene->r.subframe; @@ -1891,7 +1891,7 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer * /* render simplification */ -int get_render_subsurf_level(RenderData *r, int lvl) +int get_render_subsurf_level(const RenderData *r, int lvl) { if (r->mode & R_SIMPLIFY) return min_ii(r->simplify_subsurf, lvl); @@ -1899,7 +1899,7 @@ int get_render_subsurf_level(RenderData *r, int lvl) return lvl; } -int get_render_child_particle_number(RenderData *r, int num) +int get_render_child_particle_number(const RenderData *r, int num) { if (r->mode & R_SIMPLIFY) return (int)(r->simplify_particles * num); @@ -1907,7 +1907,7 @@ int get_render_child_particle_number(RenderData *r, int num) return num; } -int get_render_shadow_samples(RenderData *r, int samples) +int get_render_shadow_samples(const RenderData *r, int samples) { if ((r->mode & R_SIMPLIFY) && samples > 0) return min_ii(r->simplify_shadowsamples, samples); @@ -1915,7 +1915,7 @@ int get_render_shadow_samples(RenderData *r, int samples) return samples; } -float get_render_aosss_error(RenderData *r, float error) +float get_render_aosss_error(const RenderData *r, float error) { if (r->mode & R_SIMPLIFY) return ((1.0f - r->simplify_aosss) * 10.0f + 1.0f) * error; @@ -1947,18 +1947,18 @@ Base *_setlooper_base_step(Scene **sce_iter, Base *base) return NULL; } -bool BKE_scene_use_new_shading_nodes(Scene *scene) +bool BKE_scene_use_new_shading_nodes(const Scene *scene) { - RenderEngineType *type = RE_engines_find(scene->r.engine); + const RenderEngineType *type = RE_engines_find(scene->r.engine); return (type && type->flag & RE_USE_SHADING_NODES); } -bool BKE_scene_uses_blender_internal(struct Scene *scene) +bool BKE_scene_uses_blender_internal(const Scene *scene) { return STREQ(scene->r.engine, RE_engine_id_BLENDER_RENDER); } -bool BKE_scene_uses_blender_game(struct Scene *scene) +bool BKE_scene_uses_blender_game(const Scene *scene) { return STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME); } diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 3293cca76fe..07b1e9e30ac 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -1651,7 +1651,9 @@ bool BKE_texture_dependsOnTime(const struct Tex *texture) /* ------------------------------------------------------------------------- */ -void BKE_texture_get_value(Scene *scene, Tex *texture, float *tex_co, TexResult *texres, bool use_color_management) +void BKE_texture_get_value( + const Scene *scene, Tex *texture, + float *tex_co, TexResult *texres, bool use_color_management) { int result_type; bool do_color_manage = false; diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index c23c22b5fec..eac2f24d064 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -59,7 +59,7 @@ #include "BLI_threads.h" #endif -void modifier_init_texture(Scene *scene, Tex *tex) +void modifier_init_texture(const Scene *scene, Tex *tex) { if (!tex) return; diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h index cb851a51c64..adb1cf31bbd 100644 --- a/source/blender/modifiers/intern/MOD_util.h +++ b/source/blender/modifiers/intern/MOD_util.h @@ -40,7 +40,7 @@ struct Scene; struct Tex; struct TexResult; -void modifier_init_texture(struct Scene *scene, struct Tex *texture); +void modifier_init_texture(const struct Scene *scene, struct Tex *texture); void get_texture_coords(struct MappingInfoModifierData *dmd, struct Object *ob, struct DerivedMesh *dm, float (*co)[3], float (*texco)[3], int numVerts); void modifier_vgroup_cache(struct ModifierData *md, float (*vertexCos)[3]); -- cgit v1.2.3 From d28bfb5022b56a82424c6242e77a7658803ed7ca Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 21 Mar 2015 22:34:20 +1100 Subject: Cleanup: constify view3d/camera --- source/blender/blenkernel/BKE_camera.h | 29 ++++++++------ source/blender/blenkernel/intern/camera.c | 21 ++++++---- source/blender/blenkernel/intern/lattice.c | 5 ++- source/blender/editors/include/ED_view3d.h | 45 ++++++++++++---------- source/blender/editors/space_view3d/view3d_draw.c | 28 ++++++++------ source/blender/editors/space_view3d/view3d_edit.c | 4 +- .../blender/editors/space_view3d/view3d_intern.h | 6 +-- source/blender/editors/space_view3d/view3d_view.c | 32 ++++++++------- source/blender/makesrna/intern/rna_object_api.c | 2 +- 9 files changed, 99 insertions(+), 73 deletions(-) diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h index ead58c25d6b..4849c66df1b 100644 --- a/source/blender/blenkernel/BKE_camera.h +++ b/source/blender/blenkernel/BKE_camera.h @@ -109,23 +109,30 @@ typedef struct CameraParams { #define CAMERA_PARAM_ZOOM_INIT_PERSP 2.0f void BKE_camera_params_init(CameraParams *params); -void BKE_camera_params_from_object(CameraParams *params, struct Object *camera); -void BKE_camera_params_from_view3d(CameraParams *params, struct View3D *v3d, struct RegionView3D *rv3d); +void BKE_camera_params_from_object(CameraParams *params, const struct Object *camera); +void BKE_camera_params_from_view3d(CameraParams *params, const struct View3D *v3d, const struct RegionView3D *rv3d); void BKE_camera_params_compute_viewplane(CameraParams *params, int winx, int winy, float aspx, float aspy); void BKE_camera_params_compute_matrix(CameraParams *params); /* Camera View Frame */ -void BKE_camera_view_frame_ex(struct Scene *scene, struct Camera *camera, float drawsize, const bool do_clip, const float scale[3], - float r_asp[2], float r_shift[2], float *r_drawsize, float r_vec[4][3]); - -void BKE_camera_view_frame(struct Scene *scene, struct Camera *camera, float r_vec[4][3]); - -bool BKE_camera_view_frame_fit_to_scene(struct Scene *scene, struct View3D *v3d, struct Object *camera_ob, - float r_co[3], float *r_scale); -bool BKE_camera_view_frame_fit_to_coords(struct Scene *scene, float (*cos)[3], int num_cos, - struct Object *camera_ob, float r_co[3], float *r_scale); +void BKE_camera_view_frame_ex( + const struct Scene *scene, const struct Camera *camera, + const float drawsize, const bool do_clip, const float scale[3], + float r_asp[2], float r_shift[2], float *r_drawsize, float r_vec[4][3]); +void BKE_camera_view_frame( + const struct Scene *scene, const struct Camera *camera, + float r_vec[4][3]); + +bool BKE_camera_view_frame_fit_to_scene( + struct Scene *scene, struct View3D *v3d, struct Object *camera_ob, + float r_co[3], float *r_scale); +bool BKE_camera_view_frame_fit_to_coords( + const struct Scene *scene, + const float (*cos)[3], int num_cos, + const struct Object *camera_ob, + float r_co[3], float *r_scale); void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings); diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index ed400bcf565..886df16d0ee 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -213,7 +213,7 @@ void BKE_camera_params_init(CameraParams *params) params->clipend = 100.0f; } -void BKE_camera_params_from_object(CameraParams *params, Object *ob) +void BKE_camera_params_from_object(CameraParams *params, const Object *ob) { if (!ob) return; @@ -255,7 +255,7 @@ void BKE_camera_params_from_object(CameraParams *params, Object *ob) } } -void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView3D *rv3d) +void BKE_camera_params_from_view3d(CameraParams *params, const View3D *v3d, const RegionView3D *rv3d) { /* common */ params->lens = v3d->lens; @@ -384,8 +384,10 @@ void BKE_camera_params_compute_matrix(CameraParams *params) /***************************** Camera View Frame *****************************/ -void BKE_camera_view_frame_ex(Scene *scene, Camera *camera, float drawsize, const bool do_clip, const float scale[3], - float r_asp[2], float r_shift[2], float *r_drawsize, float r_vec[4][3]) +void BKE_camera_view_frame_ex( + const Scene *scene, const Camera *camera, + const float drawsize, const bool do_clip, const float scale[3], + float r_asp[2], float r_shift[2], float *r_drawsize, float r_vec[4][3]) { float facx, facy; float depth; @@ -456,7 +458,7 @@ void BKE_camera_view_frame_ex(Scene *scene, Camera *camera, float drawsize, cons r_vec[3][0] = r_shift[0] - facx; r_vec[3][1] = r_shift[1] + facy; r_vec[3][2] = depth; } -void BKE_camera_view_frame(Scene *scene, Camera *camera, float r_vec[4][3]) +void BKE_camera_view_frame(const Scene *scene, const Camera *camera, float r_vec[4][3]) { float dummy_asp[2]; float dummy_shift[2]; @@ -502,7 +504,9 @@ static void camera_to_frame_view_cb(const float co[3], void *user_data) data->tot++; } -static void camera_frame_fit_data_init(Scene *scene, Object *ob, CameraParams *params, CameraViewFrameData *data) +static void camera_frame_fit_data_init( + const Scene *scene, const Object *ob, + CameraParams *params, CameraViewFrameData *data) { float camera_rotmat_transposed_inversed[4][4]; unsigned int i; @@ -521,7 +525,7 @@ static void camera_frame_fit_data_init(Scene *scene, Object *ob, CameraParams *p BKE_camera_params_compute_matrix(params); /* initialize callback data */ - copy_m3_m4(data->camera_rotmat, ob->obmat); + copy_m3_m4(data->camera_rotmat, (float (*)[4])ob->obmat); normalize_m3(data->camera_rotmat); /* To transform a plane which is in its homogeneous representation (4d vector), * we need the inverse of the transpose of the transform matrix... */ @@ -672,7 +676,8 @@ bool BKE_camera_view_frame_fit_to_scene( } bool BKE_camera_view_frame_fit_to_coords( - Scene *scene, float (*cos)[3], int num_cos, Object *camera_ob, float r_co[3], float *r_scale) + const Scene *scene, const float (*cos)[3], int num_cos, const Object *camera_ob, + float r_co[3], float *r_scale) { CameraParams params; CameraViewFrameData data_cb; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index fa62308ec53..11409297a85 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -725,8 +725,9 @@ static bool calc_curve_deform(Scene *scene, Object *par, float co[3], return false; } -void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], - int numVerts, const char *vgroup, short defaxis) +void curve_deform_verts( + Scene *scene, Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], + int numVerts, const char *vgroup, short defaxis) { Curve *cu; int a; diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index ec53bce2eb7..84ac3a7c938 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -104,7 +104,7 @@ void ED_view3d_lastview_store(struct RegionView3D *rv3d); /* Depth buffer */ void ED_view3d_depth_update(struct ARegion *ar); -float ED_view3d_depth_read_cached(struct ViewContext *vc, int x, int y); +float ED_view3d_depth_read_cached(const struct ViewContext *vc, int x, int y); void ED_view3d_depth_tag_update(struct RegionView3D *rv3d); /* Projection */ @@ -224,33 +224,38 @@ void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, cons /* end */ -void ED_view3d_dist_range_get(struct View3D *v3d, - float r_dist_range[2]); -bool ED_view3d_clip_range_get(struct View3D *v3d, struct RegionView3D *rv3d, - float *r_clipsta, float *r_clipend, const bool use_ortho_factor); -bool ED_view3d_viewplane_get(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi, - struct rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize); +void ED_view3d_dist_range_get( + const struct View3D *v3d, + float r_dist_range[2]); +bool ED_view3d_clip_range_get( + const struct View3D *v3d, const struct RegionView3D *rv3d, + float *r_clipsta, float *r_clipend, const bool use_ortho_factor); +bool ED_view3d_viewplane_get( + const struct View3D *v3d, const struct RegionView3D *rv3d, int winxi, int winyi, + struct rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize); void ED_view3d_polygon_offset(const struct RegionView3D *rv3d, const float dist); -void ED_view3d_calc_camera_border(struct Scene *scene, struct ARegion *ar, - struct View3D *v3d, struct RegionView3D *rv3d, - struct rctf *r_viewborder, const bool no_shift); -void ED_view3d_calc_camera_border_size(struct Scene *scene, struct ARegion *ar, - struct View3D *v3d, struct RegionView3D *rv3d, - float r_size[2]); +void ED_view3d_calc_camera_border( + const struct Scene *scene, const struct ARegion *ar, + const struct View3D *v3d, const struct RegionView3D *rv3d, + struct rctf *r_viewborder, const bool no_shift); +void ED_view3d_calc_camera_border_size( + const struct Scene *scene, const struct ARegion *ar, + const struct View3D *v3d, const struct RegionView3D *rv3d, + float r_size[2]); bool ED_view3d_calc_render_border(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, struct rcti *rect); void ED_view3d_clipping_calc_from_boundbox(float clip[6][4], const struct BoundBox *clipbb, const bool is_flip); void ED_view3d_clipping_calc(struct BoundBox *bb, float planes[4][4], struct bglMats *mats, const struct rcti *rect); void ED_view3d_clipping_local(struct RegionView3D *rv3d, float mat[4][4]); -bool ED_view3d_clipping_test(struct RegionView3D *rv3d, const float co[3], const bool is_local); +bool ED_view3d_clipping_test(const struct RegionView3D *rv3d, const float co[3], const bool is_local); void ED_view3d_clipping_set(struct RegionView3D *rv3d); void ED_view3d_clipping_enable(void); void ED_view3d_clipping_disable(void); -float ED_view3d_pixel_size(struct RegionView3D *rv3d, const float co[3]); +float ED_view3d_pixel_size(const struct RegionView3D *rv3d, const float co[3]); float ED_view3d_radius_to_dist_persp(const float angle, const float radius); float ED_view3d_radius_to_dist_ortho(const float lens, const float radius); @@ -334,15 +339,15 @@ char ED_view3d_lock_view_from_index(int index); char ED_view3d_axis_view_opposite(char view); bool ED_view3d_lock(struct RegionView3D *rv3d); -uint64_t ED_view3d_datamask(struct Scene *scene, struct View3D *v3d); -uint64_t ED_view3d_screen_datamask(struct bScreen *screen); +uint64_t ED_view3d_datamask(const struct Scene *scene, const struct View3D *v3d); +uint64_t ED_view3d_screen_datamask(const struct bScreen *screen); -bool ED_view3d_view_lock_check(struct View3D *v3d, struct RegionView3D *rv3d); +bool ED_view3d_view_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d); -bool ED_view3d_offset_lock_check(struct View3D *v3d, struct RegionView3D *rv3d); +bool ED_view3d_offset_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d); /* camera lock functions */ -bool ED_view3d_camera_lock_check(struct View3D *v3d, struct RegionView3D *rv3d); +bool ED_view3d_camera_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d); /* copy the camera to the view before starting a view transformation */ void ED_view3d_camera_lock_init_ex(struct View3D *v3d, struct RegionView3D *rv3d, const bool calc_dist); void ED_view3d_camera_lock_init(struct View3D *v3d, struct RegionView3D *rv3d); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 58ef9184dd0..db4499afc26 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -207,7 +207,7 @@ void ED_view3d_clipping_enable(void) } } -static bool view3d_clipping_test(const float co[3], float clip[6][4]) +static bool view3d_clipping_test(const float co[3], const float clip[6][4]) { if (plane_point_side_v3(clip[0], co) > 0.0f) if (plane_point_side_v3(clip[1], co) > 0.0f) @@ -220,7 +220,7 @@ static bool view3d_clipping_test(const float co[3], float clip[6][4]) /* for 'local' ED_view3d_clipping_local must run first * then all comparisons can be done in localspace */ -bool ED_view3d_clipping_test(RegionView3D *rv3d, const float co[3], const bool is_local) +bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local) { return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip); } @@ -949,8 +949,9 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info)); } -static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, - rctf *r_viewborder, const bool no_shift, const bool no_zoom) +static void view3d_camera_border( + const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d, + rctf *r_viewborder, const bool no_shift, const bool no_zoom) { CameraParams params; rctf rect_view, rect_camera; @@ -983,7 +984,9 @@ static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionV r_viewborder->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy; } -void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, float r_size[2]) +void ED_view3d_calc_camera_border_size( + const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d, + float r_size[2]) { rctf viewborder; @@ -992,8 +995,9 @@ void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, R r_size[1] = BLI_rctf_size_y(&viewborder); } -void ED_view3d_calc_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, - rctf *r_viewborder, const bool no_shift) +void ED_view3d_calc_camera_border( + const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d, + rctf *r_viewborder, const bool no_shift) { view3d_camera_border(scene, ar, v3d, rv3d, r_viewborder, no_shift, false); } @@ -2554,7 +2558,7 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) /* *********************** customdata **************** */ -CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d) +CustomDataMask ED_view3d_datamask(const Scene *scene, const View3D *v3d) { CustomDataMask mask = 0; @@ -2580,16 +2584,16 @@ CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d) } /* goes over all modes and view3d settings */ -CustomDataMask ED_view3d_screen_datamask(bScreen *screen) +CustomDataMask ED_view3d_screen_datamask(const bScreen *screen) { - Scene *scene = screen->scene; + const Scene *scene = screen->scene; CustomDataMask mask = CD_MASK_BAREMESH; - ScrArea *sa; + const ScrArea *sa; /* check if we need tfaces & mcols due to view mode */ for (sa = screen->areabase.first; sa; sa = sa->next) { if (sa->spacetype == SPACE_VIEW3D) { - mask |= ED_view3d_datamask(scene, (View3D *)sa->spacedata.first); + mask |= ED_view3d_datamask(scene, sa->spacedata.first); } } diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 0bced34e465..ddb96f9aefc 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -83,7 +83,7 @@ #include "view3d_intern.h" /* own include */ -bool ED_view3d_offset_lock_check(struct View3D *v3d, struct RegionView3D *rv3d) +bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d) { return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre); } @@ -103,7 +103,7 @@ static bool view3d_operator_offset_lock_check(bContext *C, wmOperator *op) /* ********************** view3d_edit: view manipulations ********************* */ -bool ED_view3d_camera_lock_check(View3D *v3d, RegionView3D *rv3d) +bool ED_view3d_camera_lock_check(const View3D *v3d, const RegionView3D *rv3d) { return ((v3d->camera) && (v3d->camera->id.lib == NULL) && diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 25dbc8830fe..e07d7b3977c 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -208,7 +208,7 @@ void VIEW3D_OT_localview(struct wmOperatorType *ot); void VIEW3D_OT_game_start(struct wmOperatorType *ot); -bool ED_view3d_boundbox_clip_ex(RegionView3D *rv3d, const struct BoundBox *bb, float obmat[4][4]); +bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const struct BoundBox *bb, float obmat[4][4]); bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const struct BoundBox *bb); void ED_view3d_smooth_view_ex( @@ -225,8 +225,8 @@ void ED_view3d_smooth_view( const float *ofs, const float *quat, const float *dist, const float *lens, const int smooth_viewtx); -void view3d_winmatrix_set(ARegion *ar, View3D *v3d, const rctf *rect); -void view3d_viewmatrix_set(Scene *scene, View3D *v3d, RegionView3D *rv3d); +void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rctf *rect); +void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d); void fly_modal_keymap(struct wmKeyConfig *keyconf); void walk_modal_keymap(struct wmKeyConfig *keyconf); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 1c10a857179..4154f8e8845 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -688,7 +688,7 @@ static bool view3d_boundbox_clip_m4(const BoundBox *bb, float persmatob[4][4]) return false; } -bool ED_view3d_boundbox_clip_ex(RegionView3D *rv3d, const BoundBox *bb, float obmat[4][4]) +bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const BoundBox *bb, float obmat[4][4]) { /* return 1: draw */ @@ -697,7 +697,7 @@ bool ED_view3d_boundbox_clip_ex(RegionView3D *rv3d, const BoundBox *bb, float ob if (bb == NULL) return true; if (bb->flag & BOUNDBOX_DISABLED) return true; - mul_m4_m4m4(persmatob, rv3d->persmat, obmat); + mul_m4_m4m4(persmatob, (float(*)[4])rv3d->persmat, obmat); return view3d_boundbox_clip_m4(bb, persmatob); } @@ -710,7 +710,7 @@ bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const BoundBox *bb) return view3d_boundbox_clip_m4(bb, rv3d->persmatob); } -float ED_view3d_depth_read_cached(ViewContext *vc, int x, int y) +float ED_view3d_depth_read_cached(const ViewContext *vc, int x, int y) { ViewDepths *vd = vc->rv3d->depths; @@ -729,16 +729,19 @@ void ED_view3d_depth_tag_update(RegionView3D *rv3d) rv3d->depths->damaged = true; } -void ED_view3d_dist_range_get(struct View3D *v3d, - float r_dist_range[2]) +void ED_view3d_dist_range_get( + const View3D *v3d, + float r_dist_range[2]) { r_dist_range[0] = v3d->grid * 0.001f; r_dist_range[1] = v3d->far * 10.0f; } /* copies logic of get_view3d_viewplane(), keep in sync */ -bool ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *r_clipsta, float *r_clipend, - const bool use_ortho_factor) +bool ED_view3d_clip_range_get( + const View3D *v3d, const RegionView3D *rv3d, + float *r_clipsta, float *r_clipend, + const bool use_ortho_factor) { CameraParams params; @@ -758,8 +761,9 @@ bool ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *r_clipsta, } /* also exposed in previewrender.c */ -bool ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy, - rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize) +bool ED_view3d_viewplane_get( + const View3D *v3d, const RegionView3D *rv3d, int winx, int winy, + rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize) { CameraParams params; @@ -797,7 +801,7 @@ void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist) /** * \param rect optional for picking (can be NULL). */ -void view3d_winmatrix_set(ARegion *ar, View3D *v3d, const rctf *rect) +void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rctf *rect) { RegionView3D *rv3d = ar->regiondata; rctf viewplane; @@ -917,7 +921,7 @@ bool ED_view3d_lock(RegionView3D *rv3d) } /* don't set windows active in here, is used by renderwin too */ -void view3d_viewmatrix_set(Scene *scene, View3D *v3d, RegionView3D *rv3d) +void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d) { if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */ if (v3d->camera) { @@ -956,7 +960,7 @@ void view3d_viewmatrix_set(Scene *scene, View3D *v3d, RegionView3D *rv3d) } else if (v3d->ob_centre_cursor) { float vec[3]; - copy_v3_v3(vec, ED_view3d_cursor3d_get(scene, v3d)); + copy_v3_v3(vec, ED_view3d_cursor3d_get(scene, (View3D *)v3d)); translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]); use_lock_ofs = true; } @@ -1708,9 +1712,9 @@ void VIEW3D_OT_game_start(wmOperatorType *ot) /* ************************************** */ -float ED_view3d_pixel_size(RegionView3D *rv3d, const float co[3]) +float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3]) { - return mul_project_m4_v3_zfac(rv3d->persmat, co) * rv3d->pixsize * U.pixelsize; + return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize * U.pixelsize; } float ED_view3d_radius_to_dist_persp(const float angle, const float radius) diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 2306682ca01..9fe44511c8c 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -131,7 +131,7 @@ static void rna_Object_calc_matrix_camera( static void rna_Object_camera_fit_coords( Object *ob, Scene *scene, int num_cos, float *cos, float co_ret[3], float *scale_ret) { - BKE_camera_view_frame_fit_to_coords(scene, (float (*)[3])cos, num_cos / 3, ob, co_ret, scale_ret); + BKE_camera_view_frame_fit_to_coords(scene, (const float (*)[3])cos, num_cos / 3, ob, co_ret, scale_ret); } /* copied from Mesh_getFromObject and adapted to RNA interface */ -- cgit v1.2.3 From d21018b3340496865626b279852159347ac9c102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Sat, 21 Mar 2015 14:42:57 +0100 Subject: Fix T44065: fixed vehicle constraint Commit ffee7f1a58a18bc08add94176ddffe29809139a6 broke vehicle constraints; this fixes that. --- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index c0aaefe9e37..a30ee0fe34f 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -2644,9 +2644,6 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl if (!rb0) return 0; - // If either of the controllers is missing, we can't do anything. - if (!c0 || !c1) return 0; - btVector3 pivotInB = rb1 ? rb1->getCenterOfMassTransform().inverse()(rb0->getCenterOfMassTransform()(pivotInA)) : rb0->getCenterOfMassTransform() * pivotInA; btVector3 axisInA(axisX,axisY,axisZ); @@ -2658,6 +2655,8 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl { case PHY_POINT2POINT_CONSTRAINT: { + // If either of the controllers is missing, we can't do anything. + if (!c0 || !c1) return 0; btPoint2PointConstraint* p2p = 0; @@ -2686,6 +2685,9 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl case PHY_GENERIC_6DOF_CONSTRAINT: { + // If either of the controllers is missing, we can't do anything. + if (!c0 || !c1) return 0; + btGeneric6DofConstraint* genericConstraint = 0; if (rb1) @@ -2739,7 +2741,7 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl *rb0,s_fixedObject2, frameInA,frameInB,useReferenceFrameA); } - + if (genericConstraint) { //m_constraints.push_back(genericConstraint); @@ -2756,6 +2758,9 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl } case PHY_CONE_TWIST_CONSTRAINT: { + // If either of the controllers is missing, we can't do anything. + if (!c0 || !c1) return 0; + btConeTwistConstraint* coneTwistContraint = 0; @@ -2807,7 +2812,7 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl *rb0,s_fixedObject2, frameInA,frameInB); } - + if (coneTwistContraint) { //m_constraints.push_back(genericConstraint); @@ -2830,6 +2835,9 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl case PHY_LINEHINGE_CONSTRAINT: { + // If either of the controllers is missing, we can't do anything. + if (!c0 || !c1) return 0; + btHingeConstraint* hinge = 0; if (rb1) -- cgit v1.2.3 From 8e9c9fde427c228111cfe2da6dfac9e54abb2a3d Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Sat, 21 Mar 2015 17:15:38 +0100 Subject: OSX/GHOST: need one more release in error case --- intern/ghost/intern/GHOST_ContextCGL.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm index cf94dc83d18..ae7e7a69854 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.mm +++ b/intern/ghost/intern/GHOST_ContextCGL.mm @@ -334,6 +334,7 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext() error: [m_openGLView setOpenGLContext:prev_openGLContext]; + [pixelFormat release]; [pool drain]; -- cgit v1.2.3 From 9ff3d8eafae92a7071d86028d3c71308ad28125b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 22 Mar 2015 03:24:56 +1100 Subject: Cleanup: minor edits to project generators --- build_files/cmake/cmake_netbeans_project.py | 25 +++++++++-------- build_files/cmake/cmake_qtcreator_project.py | 42 +++++++++++++++------------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/build_files/cmake/cmake_netbeans_project.py b/build_files/cmake/cmake_netbeans_project.py index 81b1a460f67..25d07373569 100755 --- a/build_files/cmake/cmake_netbeans_project.py +++ b/build_files/cmake/cmake_netbeans_project.py @@ -29,18 +29,19 @@ Example linux usage Windows not supported so far """ -from project_info import (SIMPLE_PROJECTFILE, - SOURCE_DIR, - CMAKE_DIR, - PROJECT_DIR, - source_list, - is_project_file, - is_c_header, - # is_py, - cmake_advanced_info, - cmake_compiler_defines, - project_name_get, - ) +from project_info import ( + SIMPLE_PROJECTFILE, + SOURCE_DIR, + CMAKE_DIR, + PROJECT_DIR, + source_list, + is_project_file, + is_c_header, + # is_py, + cmake_advanced_info, + cmake_compiler_defines, + project_name_get, + ) import os diff --git a/build_files/cmake/cmake_qtcreator_project.py b/build_files/cmake/cmake_qtcreator_project.py index 1676d634cf2..67302c89a68 100755 --- a/build_files/cmake/cmake_qtcreator_project.py +++ b/build_files/cmake/cmake_qtcreator_project.py @@ -22,26 +22,27 @@ # -""" +r""" +Example Linux usage: + python ~/blender-git/blender/build_files/cmake/cmake_qtcreator_project.py ~/blender-git/cmake + Example Win32 usage: c:\Python32\python.exe c:\blender_dev\blender\build_files\cmake\cmake_qtcreator_project.py c:\blender_dev\cmake_build - -example linux usage - python ~/blender-git/blender/build_files/cmake/cmake_qtcreator_project.py ~/blender-git/cmake """ -from project_info import (SIMPLE_PROJECTFILE, - SOURCE_DIR, - # CMAKE_DIR, - PROJECT_DIR, - source_list, - is_project_file, - is_c_header, - is_py, - cmake_advanced_info, - cmake_compiler_defines, - project_name_get, - ) +from project_info import ( + SIMPLE_PROJECTFILE, + SOURCE_DIR, + # CMAKE_DIR, + PROJECT_DIR, + source_list, + is_project_file, + is_c_header, + is_py, + cmake_advanced_info, + cmake_compiler_defines, + project_name_get, + ) import os import sys @@ -63,18 +64,19 @@ def create_qtc_project_main(): if SIMPLE_PROJECTFILE: # --- qtcreator specific, simple format PROJECT_NAME = "Blender" - with open(os.path.join(PROJECT_DIR, "%s.files" % PROJECT_NAME), 'w') as f: + FILE_NAME = PROJECT_NAME.lower() + with open(os.path.join(PROJECT_DIR, "%s.files" % FILE_NAME), 'w') as f: f.write("\n".join(files_rel)) - with open(os.path.join(PROJECT_DIR, "%s.includes" % PROJECT_NAME), 'w') as f: + with open(os.path.join(PROJECT_DIR, "%s.includes" % FILE_NAME), 'w') as f: f.write("\n".join(sorted(list(set(os.path.dirname(f) for f in files_rel if is_c_header(f)))))) - qtc_prj = os.path.join(PROJECT_DIR, "%s.creator" % PROJECT_NAME) + qtc_prj = os.path.join(PROJECT_DIR, "%s.creator" % FILE_NAME) with open(qtc_prj, 'w') as f: f.write("[General]\n") - qtc_cfg = os.path.join(PROJECT_DIR, "%s.config" % PROJECT_NAME) + qtc_cfg = os.path.join(PROJECT_DIR, "%s.config" % FILE_NAME) if not os.path.exists(qtc_cfg): with open(qtc_cfg, 'w') as f: f.write("// ADD PREDEFINED MACROS HERE!\n") -- cgit v1.2.3 From e1831990227ad43c9c41fca8f3e3639aaa222c2d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 22 Mar 2015 03:29:59 +1100 Subject: Cleanup: instantiate arg once in context macro --- source/creator/creator.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/source/creator/creator.c b/source/creator/creator.c index 0ca5fbeccac..9815b3c7211 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1185,19 +1185,24 @@ static int set_skip_frame(int argc, const char **argv, void *data) #define BPY_CTX_SETUP(_cmd) \ { \ wmWindowManager *wm = CTX_wm_manager(C); \ - wmWindow *prevwin = CTX_wm_window(C); \ - Scene *prevscene = CTX_data_scene(C); \ - if (wm->windows.first) { \ + Scene *scene_prev = CTX_data_scene(C); \ + wmWindow *win_prev; \ + const bool has_win = !BLI_listbase_is_empty(&wm->windows); \ + if (has_win) { \ + win_prev = CTX_wm_window(C); \ CTX_wm_window_set(C, wm->windows.first); \ - _cmd; \ - CTX_wm_window_set(C, prevwin); \ } \ else { \ fprintf(stderr, "Python script \"%s\" " \ "running with missing context data.\n", argv[1]); \ + } \ + { \ _cmd; \ } \ - CTX_data_scene_set(C, prevscene); \ + if (has_win) { \ + CTX_wm_window_set(C, win_prev); \ + } \ + CTX_data_scene_set(C, scene_prev); \ } (void)0 \ #endif /* WITH_PYTHON */ -- cgit v1.2.3 From 2744ce77dea394026bc524e68c687050bc8e0c28 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Sat, 21 Mar 2015 17:53:18 +0100 Subject: Revert part of D1074 related to acceleration taked into account. It has been reverted because it was affecting obstacle avoidance (T44041). This fix should be backported to 2.74 --- source/blender/blenloader/intern/versioning_270.c | 12 ------------ source/gameengine/Ketsji/KX_SteeringActuator.cpp | 11 ++++------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index ee015fa5652..adf5f93ae16 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -616,18 +616,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } - - if (!DNA_struct_elem_find(fd->filesdna, "bSteeringActuator", "float", "acceleration")) { - for (ob = main->object.first; ob; ob = ob->id.next) { - bActuator *act; - for (act = ob->actuators.first; act; act = act->next) { - if (act->type == ACT_STEERING) { - bSteeringActuator *sact = act->data; - sact->acceleration = 1000.f; - } - } - } - } } if (!MAIN_VERSION_ATLEAST(main, 273, 9)) { diff --git a/source/gameengine/Ketsji/KX_SteeringActuator.cpp b/source/gameengine/Ketsji/KX_SteeringActuator.cpp index f859b1ceae9..83597f9125a 100644 --- a/source/gameengine/Ketsji/KX_SteeringActuator.cpp +++ b/source/gameengine/Ketsji/KX_SteeringActuator.cpp @@ -263,12 +263,12 @@ bool KX_SteeringActuator::Update(double curtime, bool frame) if (apply_steerforce) { - MT_Vector3 newvel; bool isdyna = obj->IsDynamic(); if (isdyna) m_steerVec.z() = 0; if (!m_steerVec.fuzzyZero()) m_steerVec.normalize(); + MT_Vector3 newvel = m_velocity * m_steerVec; //adjust velocity to avoid obstacles if (m_simulation && m_obstacle /*&& !newvel.fuzzyZero()*/) @@ -281,16 +281,13 @@ bool KX_SteeringActuator::Update(double curtime, bool frame) KX_RasterizerDrawDebugLine(mypos, mypos + newvel, MT_Vector3(0.0, 1.0, 0.0)); } - HandleActorFace(m_steerVec); + HandleActorFace(newvel); if (isdyna) { - //TODO: Take into account angular velocity on turns + //temporary solution: set 2D steering velocity directly to obj + //correct way is to apply physical force MT_Vector3 curvel = obj->GetLinearVelocity(); - newvel = (curvel.length() * m_steerVec) + (m_acceleration * delta) * m_steerVec; - if (newvel.length2() >= (m_velocity * m_velocity)) - newvel = m_velocity * m_steerVec; - if (m_lockzvel) newvel.z() = 0.0f; else -- cgit v1.2.3 From 0b4a71b07245d5370a02fae4dbde9195c9c58881 Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Sun, 22 Mar 2015 17:55:43 +0100 Subject: BGE: Add physics constraints replication This patch will add a physics constraints replication for group instances (dupli group). It also fix crashing when when a group instance is made from a linked group instance and both are on the active layer. Initial patch T31443 from moerdn (Martin Sell). Reviewers: lordloki, sergof, moguri, sybren Reviewed By: moguri, sybren Differential Revision: https://developer.blender.org/D658 --- .../Converter/BL_BlenderDataConversion.cpp | 128 +++++++++------------ source/gameengine/Ketsji/KX_GameObject.cpp | 15 +++ source/gameengine/Ketsji/KX_GameObject.h | 10 ++ source/gameengine/Ketsji/KX_Scene.cpp | 6 + .../Physics/Bullet/CcdPhysicsController.cpp | 25 ++++ .../Physics/Bullet/CcdPhysicsController.h | 3 + .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 76 ++++++++++++ .../Physics/Bullet/CcdPhysicsEnvironment.h | 4 + .../Physics/common/PHY_IPhysicsController.h | 3 + .../Physics/common/PHY_IPhysicsEnvironment.h | 4 + 10 files changed, 199 insertions(+), 75 deletions(-) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 7e0588fc7d0..cd2e2151034 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1741,6 +1741,16 @@ static KX_GameObject* getGameOb(STR_String busc,CListValue* sumolist) } +static bool bl_isConstraintInList(KX_GameObject *gameobj, set convertedlist) +{ + set::iterator gobit; + for (gobit = convertedlist.begin(); gobit != convertedlist.end(); gobit++) { + if ((*gobit)->GetName() == gameobj->GetName()) + return true; + } + return false; +} + /* helper for BL_ConvertBlenderObjects, avoids code duplication * note: all var names match args are passed from the caller */ static void bl_ConvertBlenderObject_Single( @@ -1900,6 +1910,12 @@ void BL_ConvertBlenderObjects(struct Main* maggie, // is not in a separate thread. BL_Texture::GetMaxUnits(); + /* We have to ensure that group definitions are only converted once + * push all converted group members to this set. + * This will happen when a group instance is made from a linked group instance + * and both are on the active layer. */ + set convertedlist; + if (alwaysUseExpandFraming) { frame_type = RAS_FrameSettings::e_frame_extend; aspect_width = canvas->GetWidth(); @@ -2031,6 +2047,11 @@ void BL_ConvertBlenderObjects(struct Main* maggie, converter, libloading); + /* Insert object to the constraint game object list + * so we can check later if there is a instance in the scene or + * an instance and its actual group definition. */ + convertedlist.insert((KX_GameObject*)gameobj->AddRef()); + bool isInActiveLayer = false; if (gameobj) { @@ -2270,93 +2291,50 @@ void BL_ConvertBlenderObjects(struct Main* maggie, // create physics joints for (i=0;iGetCount();i++) { - KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i); - struct Object* blenderobject = gameobj->GetBlenderObject(); - ListBase *conlist; + PHY_IPhysicsEnvironment *physEnv = kxscene->GetPhysicsEnvironment(); + KX_GameObject *gameobj = (KX_GameObject *)sumolist->GetValue(i); + struct Object *blenderobject = gameobj->GetBlenderObject(); + ListBase *conlist = get_active_constraints2(blenderobject); bConstraint *curcon; - if ((gameobj->GetLayer()&activeLayerBitInfo)==0) + if (!conlist) continue; - conlist = get_active_constraints2(blenderobject); - if (conlist) { - for (curcon = (bConstraint *)conlist->first; curcon; curcon = (bConstraint *)curcon->next) { - if (curcon->type==CONSTRAINT_TYPE_RIGIDBODYJOINT) { - - bRigidBodyJointConstraint *dat=(bRigidBodyJointConstraint *)curcon->data; + for (curcon = (bConstraint *)conlist->first; curcon; curcon = (bConstraint *)curcon->next) { + if (curcon->type != CONSTRAINT_TYPE_RIGIDBODYJOINT) + continue; - if (!dat->child && !(curcon->flag & CONSTRAINT_OFF)) { + bRigidBodyJointConstraint *dat = (bRigidBodyJointConstraint *)curcon->data; + + /* Skip if no target or a child object is selected or constraints are deactivated */ + if (!dat->tar || dat->child || (curcon->flag & CONSTRAINT_OFF)) + continue; - PHY_IPhysicsController* physctr2 = 0; + /* Store constraints of grouped and instanced objects for all layers */ + gameobj->AddConstraint(dat); + + /* Skipped already converted constraints. + * This will happen when a group instance is made from a linked group instance + * and both are on the active layer. */ + if (bl_isConstraintInList(gameobj, convertedlist)) + continue; - if (dat->tar) { - KX_GameObject *gotar=getGameOb(dat->tar->id.name+2,sumolist); - if (gotar && ((gotar->GetLayer()&activeLayerBitInfo)!=0) && gotar->GetPhysicsController()) - physctr2 = gotar->GetPhysicsController(); - } + KX_GameObject *gotar = getGameOb(dat->tar->id.name + 2, sumolist); - if (gameobj->GetPhysicsController()) { - PHY_IPhysicsController* physctrl = gameobj->GetPhysicsController(); - //we need to pass a full constraint frame, not just axis - - //localConstraintFrameBasis - MT_Matrix3x3 localCFrame(MT_Vector3(dat->axX,dat->axY,dat->axZ)); - MT_Vector3 axis0 = localCFrame.getColumn(0); - MT_Vector3 axis1 = localCFrame.getColumn(1); - MT_Vector3 axis2 = localCFrame.getColumn(2); - - int constraintId = kxscene->GetPhysicsEnvironment()->CreateConstraint(physctrl,physctr2,(PHY_ConstraintType)dat->type,(float)dat->pivX, - (float)dat->pivY,(float)dat->pivZ, - (float)axis0.x(),(float)axis0.y(),(float)axis0.z(), - (float)axis1.x(),(float)axis1.y(),(float)axis1.z(), - (float)axis2.x(),(float)axis2.y(),(float)axis2.z(),dat->flag); - if (constraintId) { - //if it is a generic 6DOF constraint, set all the limits accordingly - if (dat->type == PHY_GENERIC_6DOF_CONSTRAINT) { - int dof; - int dofbit=1; - for (dof=0;dof<6;dof++) { - if (dat->flag & dofbit) { - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,dat->minLimit[dof],dat->maxLimit[dof]); - } else { - //minLimit > maxLimit means free(disabled limit) for this degree of freedom - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,1,-1); - } - dofbit<<=1; - } - } else if (dat->type == PHY_CONE_TWIST_CONSTRAINT) { - int dof; - int dofbit = 1<<3; // bitflag use_angular_limit_x - - for (dof=3;dof<6;dof++) { - if (dat->flag & dofbit) { - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,dat->minLimit[dof],dat->maxLimit[dof]); - } else { - //maxLimit < 0 means free(disabled limit) for this degree of freedom - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,1,-1); - } - dofbit<<=1; - } - } else if (dat->type == PHY_LINEHINGE_CONSTRAINT) { - int dof = 3; // dof for angular x - int dofbit = 1<<3; // bitflag use_angular_limit_x - - if (dat->flag & dofbit) { - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof, - dat->minLimit[dof],dat->maxLimit[dof]); - } else { - //minLimit > maxLimit means free(disabled limit) for this degree of freedom - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,1,-1); - } - } - } - } - } - } + if (gotar && (gotar->GetLayer()&activeLayerBitInfo) && gotar->GetPhysicsController() && + (gameobj->GetLayer()&activeLayerBitInfo) && gameobj->GetPhysicsController()) + { + physEnv->SetupObjectConstraints(gameobj, gotar, dat); } } } + /* cleanup converted set of group objects */ + set::iterator gobit; + for (gobit = convertedlist.begin(); gobit != convertedlist.end(); gobit++) + (*gobit)->Release(); + + convertedlist.clear(); sumolist->Release(); // convert world diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 71af263bf46..c8fc64f4679 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -292,6 +292,21 @@ void KX_GameObject::SetDupliGroupObject(KX_GameObject* obj) m_pDupliGroupObject = obj; } +void KX_GameObject::AddConstraint(bRigidBodyJointConstraint *cons) +{ + m_constraints.push_back(cons); +} + +std::vector KX_GameObject::GetConstraints() +{ + return m_constraints; +} + +void KX_GameObject::ClearConstraints() +{ + m_constraints.clear(); +} + KX_GameObject* KX_GameObject::GetParent() { KX_GameObject* result = NULL; diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 7d1a934bcec..132e72c45e2 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -49,6 +49,7 @@ #include "CTR_HashedPtr.h" #include "KX_Scene.h" #include "KX_KetsjiEngine.h" /* for m_anim_framerate */ +#include "DNA_constraint_types.h" /* for constraint replication */ #include "DNA_object_types.h" #include "SCA_LogicManager.h" /* for ConvertPythonToGameObject to search object names */ @@ -117,6 +118,7 @@ protected: SG_Node* m_pSGNode; MT_CmMatrix4x4 m_OpenGL_4x4Matrix; + std::vector m_constraints; KX_ObstacleSimulation* m_pObstacleSimulation; @@ -193,6 +195,14 @@ public: void UpdateBlenderObjectMatrix(Object* blendobj=NULL); + /** + * Used for constraint replication for group instances. + * The list of constraints is filled during data conversion. + */ + void AddConstraint(bRigidBodyJointConstraint *cons); + std::vector GetConstraints(); + void ClearConstraints(); + /** * Get a pointer to the game object that is the parent of * this object. Or NULL if there is no parent. The returned diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index d1b10098237..47510baa436 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -848,6 +848,12 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // now look if object in the hierarchy have dupli group and recurse for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) { + /* Replicate all constraints. */ + if ((*git)->GetPhysicsController()) { + (*git)->GetPhysicsController()->ReplicateConstraints((*git), m_logicHierarchicalGameObjects); + (*git)->ClearConstraints(); + } + if ((*git) != groupobj && (*git)->IsDupliGroup()) // can't instantiate group immediately as it destroys m_logicHierarchicalGameObjects duplilist.push_back((*git)); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 44c4e284e7c..5adff8f7f02 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -1740,6 +1740,31 @@ bool CcdPhysicsController::ReinstancePhysicsShape(KX_GameObject *from_gameobj, R return true; } +void CcdPhysicsController::ReplicateConstraints(KX_GameObject *replica, std::vector constobj) +{ + if (replica->GetConstraints().size() == 0 || !replica->GetPhysicsController()) + return; + + PHY_IPhysicsEnvironment *physEnv = GetPhysicsEnvironment(); + + vector constraints = replica->GetConstraints(); + vector::iterator consit; + + /* Object could have some constraints, iterate over all of theme to ensure that every constraint is recreated. */ + for (consit = constraints.begin(); consit != constraints.end(); ++consit) { + /* Try to find the constraint targets in the list of group objects. */ + bRigidBodyJointConstraint *dat = (*consit); + vector::iterator memit; + for (memit = constobj.begin(); memit != constobj.end(); ++memit) { + KX_GameObject *member = (*memit); + /* If the group member is the actual target for the constraint. */ + if (dat->tar->id.name + 2 == member->GetName() && member->GetPhysicsController()) + physEnv->SetupObjectConstraints(replica, member, dat); + } + } + +} + /////////////////////////////////////////////////////////// ///A small utility class, DefaultMotionState /// diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index de40624d7bb..47bc9cdfbd7 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -719,6 +719,9 @@ protected: virtual bool ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject* from_meshobj); + /* Method to replicate rigid body joint contraints for group instances. */ + virtual void ReplicateConstraints(KX_GameObject *gameobj, std::vector constobj); + #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:CcdPhysicsController") #endif diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index a30ee0fe34f..6d3f6d9ddcb 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -3599,3 +3599,79 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject } #endif } + + +void CcdPhysicsEnvironment::SetupObjectConstraints(KX_GameObject *obj_src, KX_GameObject *obj_dest, + bRigidBodyJointConstraint *dat) +{ + PHY_IPhysicsController *phy_src = obj_src->GetPhysicsController(); + PHY_IPhysicsController *phy_dest = obj_dest->GetPhysicsController(); + PHY_IPhysicsEnvironment *phys_env = obj_src->GetScene()->GetPhysicsEnvironment(); + + /* We need to pass a full constraint frame, not just axis. */ + MT_Matrix3x3 localCFrame(MT_Vector3(dat->axX,dat->axY,dat->axZ)); + MT_Vector3 axis0 = localCFrame.getColumn(0); + MT_Vector3 axis1 = localCFrame.getColumn(1); + MT_Vector3 axis2 = localCFrame.getColumn(2); + MT_Vector3 scale = obj_src->NodeGetWorldScaling(); + + /* Apply not only the pivot and axis values, but also take scale into count + * this is not working well, if only one or two axis are scaled, but works ok on + * homogeneous scaling. */ + int constraintId = phys_env->CreateConstraint( + phy_src, phy_dest, (PHY_ConstraintType)dat->type, + (float)(dat->pivX * scale.x()), (float)(dat->pivY * scale.y()), (float)(dat->pivZ * scale.z()), + (float)(axis0.x() * scale.x()), (float)(axis0.y() * scale.y()), (float)(axis0.z() * scale.z()), + (float)(axis1.x() * scale.x()), (float)(axis1.y() * scale.y()), (float)(axis1.z() * scale.z()), + (float)(axis2.x() * scale.x()), (float)(axis2.y() * scale.y()), (float)(axis2.z() * scale.z()), + dat->flag); + + /* PHY_POINT2POINT_CONSTRAINT = 1, + * PHY_LINEHINGE_CONSTRAINT = 2, + * PHY_ANGULAR_CONSTRAINT = 3, + * PHY_CONE_TWIST_CONSTRAINT = 4, + * PHY_VEHICLE_CONSTRAINT = 11, + * PHY_GENERIC_6DOF_CONSTRAINT = 12 */ + + if (!constraintId) + return; + + int dof = 0; + int dof_max = 0; + int dofbit = 0; + + switch (dat->type) { + /* Set all the limits for generic 6DOF constraint. */ + case PHY_GENERIC_6DOF_CONSTRAINT: + dof_max = 6; + dofbit = 1; + break; + /* Set XYZ angular limits for cone twist constraint. */ + case PHY_CONE_TWIST_CONSTRAINT: + dof = 3; + dof_max = 6; + dofbit = 1 << 3; + break; + /* Set only X angular limits for line hinge and angular constraint. */ + case PHY_LINEHINGE_CONSTRAINT: + case PHY_ANGULAR_CONSTRAINT: + dof = 3; + dof_max = 4; + dofbit = 1 << 3; + break; + default: + break; + } + + for (dof; dof < dof_max; dof++) { + if (dat->flag & dofbit) { + phys_env->SetConstraintParam(constraintId, dof, dat->minLimit[dof], dat->maxLimit[dof]); + } + else { + /* minLimit > maxLimit means free (no limit) for this degree of freedom. */ + phys_env->SetConstraintParam(constraintId, dof, 1.0f, -1.0f); + } + dofbit <<= 1; + } + +} diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 009eb5cde24..113db3348ca 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -275,6 +275,10 @@ protected: bool isCompoundChild, bool hasCompoundChildren); + /* Set the rigid body joints constraints values for converted objects and replicated group instances. */ + virtual void SetupObjectConstraints(KX_GameObject *obj_src, KX_GameObject *obj_dest, + bRigidBodyJointConstraint *dat); + protected: diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h index 1717f8d90cb..68763be4db9 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsController.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h @@ -32,6 +32,7 @@ #ifndef __PHY_IPHYSICSCONTROLLER_H__ #define __PHY_IPHYSICSCONTROLLER_H__ +#include #include "PHY_IController.h" class PHY_IMotionState; @@ -135,6 +136,8 @@ class PHY_IPhysicsController : public PHY_IController virtual bool ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject* from_meshobj) = 0; + /* Method to replicate rigid body joint contraints for group instances. */ + virtual void ReplicateConstraints(KX_GameObject *gameobj, std::vector constobj) = 0; #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:PHY_IPhysicsController") diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index dd762b02b4e..44b61136d3f 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -55,6 +55,7 @@ class KX_Scene; struct PHY_ShapeProps; struct PHY_MaterialProps; class PHY_IMotionState; +struct bRigidBodyJointConstraint; /** * pass back information from rayTest @@ -213,6 +214,9 @@ class PHY_IPhysicsEnvironment bool isCompoundChild, bool hasCompoundChildren) = 0; + /* Set the rigid body joints constraints values for converted objects and replicated group instances. */ + virtual void SetupObjectConstraints(KX_GameObject *obj_src, KX_GameObject *obj_dest, + bRigidBodyJointConstraint *dat) {} #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:PHY_IPhysicsEnvironment") -- cgit v1.2.3 From e7d051043dc82c2991eb491e0630d9b1065934c3 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Sun, 22 Mar 2015 18:13:53 +0100 Subject: BGE: New hysteresis offset to improve LOD level transitions This change introduces a new hysteresis parameter that it will be added or subtracted to/from the LOD distance to avoid popping when a LOD object moves close to the LOD transition continuously. Then, we have the following: - a new LOD Hysteresis setting per scene (default 10%) which is located in Scene context --> Level of Detail panel. This scene parameter also will active/deactive the scene hysteresis. - and a new LOD Hysteresis setting per object (default 10%) which is located in Object context --> Levels of Detail panel. The LOD hysteresis setting per object (if active) will overwrite the hysteresis setting per scene value. For the new blends: the hysteresis setting per scene would be active by default and the per object would be inactive by default. For the old blends: both hysteresis settings (per scene and per object) would be inactive by default. A quick way to take advantage of this feature for old blends would be to activate the hysteresis parameter in the scene context -> Level of Detail panel Reviewers: campbellbarton, kupoman, moguri Reviewed By: kupoman, moguri Subscribers: nonamejuju, lordodin Differential Revision: https://developer.blender.org/D957 --- release/scripts/startup/bl_ui/properties_game.py | 30 +++++++++++++++- source/blender/blenkernel/intern/object.c | 2 ++ source/blender/blenkernel/intern/scene.c | 3 ++ source/blender/blenloader/intern/versioning_270.c | 18 ++++++++++ .../blenloader/intern/versioning_defaults.c | 3 ++ source/blender/makesdna/DNA_object_types.h | 4 ++- source/blender/makesdna/DNA_scene_types.h | 10 +++++- source/blender/makesrna/intern/rna_object.c | 13 +++++++ source/blender/makesrna/intern/rna_scene.c | 14 ++++++++ .../Converter/BL_BlenderDataConversion.cpp | 4 +++ source/gameengine/Ketsji/KX_GameObject.cpp | 42 +++++++++++++++++++++- source/gameengine/Ketsji/KX_GameObject.h | 10 ++++++ source/gameengine/Ketsji/KX_Scene.cpp | 13 ++++++- source/gameengine/Ketsji/KX_Scene.h | 9 +++++ 14 files changed, 170 insertions(+), 5 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py index 32a8e734ab6..8ef9a083104 100644 --- a/release/scripts/startup/bl_ui/properties_game.py +++ b/release/scripts/startup/bl_ui/properties_game.py @@ -523,7 +523,27 @@ class SCENE_PT_game_navmesh(SceneButtonsPanel, Panel): row.prop(rd, "sample_max_error") -class WorldButtonsPanel: +class SCENE_PT_game_hysteresis(SceneButtonsPanel, Panel): + bl_label = "Level of Detail" + COMPAT_ENGINES = {'BLENDER_GAME'} + + @classmethod + def poll(cls, context): + scene = context.scene + return (scene and scene.render.engine in cls.COMPAT_ENGINES) + + def draw(self, context): + layout = self.layout + gs = context.scene.game_settings + + row = layout.row() + row.prop(gs, "use_scene_hysteresis", text="Hysteresis") + row = layout.row() + row.active = gs.use_scene_hysteresis + row.prop(gs, "scene_hysteresis_percentage", text="") + + +class WorldButtonsPanel(): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "world" @@ -765,6 +785,7 @@ class OBJECT_PT_levels_of_detail(ObjectButtonsPanel, Panel): def draw(self, context): layout = self.layout ob = context.object + gs = context.scene.game_settings col = layout.column() @@ -782,6 +803,13 @@ class OBJECT_PT_levels_of_detail(ObjectButtonsPanel, Panel): row.prop(level, "use_mesh", text="") row.prop(level, "use_material", text="") + row = box.row() + row.active = gs.use_scene_hysteresis + row.prop(level, "use_object_hysteresis", text="Hysteresis Override") + row = box.row() + row.active = gs.use_scene_hysteresis and level.use_object_hysteresis + row.prop(level, "object_hysteresis_percentage", text="") + row = col.row(align=True) row.operator("object.lod_add", text="Add", icon='ZOOMIN') row.menu("OBJECT_MT_lod_tools", text="", icon='TRIA_DOWN') diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 08a74d0c6cd..174fb38aada 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1098,10 +1098,12 @@ void BKE_object_lod_add(Object *ob) BLI_addtail(&ob->lodlevels, base); base->flags = OB_LOD_USE_MESH | OB_LOD_USE_MAT; base->source = ob; + base->obhysteresis = 10; last = ob->currentlod = base; } lod->distance = last->distance + 25.0f; + lod->obhysteresis = 10; lod->flags = OB_LOD_USE_MESH | OB_LOD_USE_MAT; BLI_addtail(&ob->lodlevels, lod); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index c28d741d7ec..d2c3f473e11 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -677,6 +677,9 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->gm.recastData.detailsampledist = 6.0f; sce->gm.recastData.detailsamplemaxerror = 1.0f; + sce->gm.lodflag = SCE_LOD_USE_HYST; + sce->gm.scehysteresis = 10; + sce->gm.exitkey = 218; // Blender key code for ESC sound_create_scene(sce); diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index adf5f93ae16..0853c93750c 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -654,5 +654,23 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } + + /* hysteresis setted to 10% but not actived */ + if (!DNA_struct_elem_find(fd->filesdna, "LodLevel", "int", "obhysteresis")) { + Object* ob; + for (ob = main->object.first; ob; ob = ob->id.next) { + LodLevel *level; + for (level = ob->lodlevels.first; level; level = level->next) { + level->obhysteresis = 10; + } + } + } + + if (!DNA_struct_elem_find(fd->filesdna, "GameData", "int", "scehysteresis")) { + Scene *scene; + for (scene = main->scene.first; scene; scene = scene->id.next) { + scene->gm.scehysteresis = 10; + } + } } } diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 4c7b011097b..d320b305c06 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -92,6 +92,9 @@ void BLO_update_defaults_startup_blend(Main *bmain) sculpt->detail_size = 12; } } + + scene->gm.lodflag |= SCE_LOD_USE_HYST; + scene->gm.scehysteresis = 10; } for (linestyle = bmain->linestyle.first; linestyle; linestyle = linestyle->id.next) { diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 2699bb5f22f..4cb979c57b7 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -109,7 +109,8 @@ typedef struct LodLevel { struct LodLevel *next, *prev; struct Object *source; int flags; - float distance; + float distance, pad; + int obhysteresis; } LodLevel; typedef struct Object { @@ -484,6 +485,7 @@ enum { enum { OB_LOD_USE_MESH = 1 << 0, OB_LOD_USE_MAT = 1 << 1, + OB_LOD_USE_HYST = 1 << 2, }; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 0eae50a2562..ac0803d494c 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -718,7 +718,12 @@ typedef struct GameData { short obstacleSimulation; short raster_storage; float levelHeight; - float deactivationtime, lineardeactthreshold, angulardeactthreshold, pad2; + float deactivationtime, lineardeactthreshold, angulardeactthreshold; + + /* Scene LoD */ + short lodflag, pad2; + int scehysteresis, pad5; + } GameData; #define STEREO_NOSTEREO 1 @@ -791,6 +796,9 @@ enum { #pragma GCC poison GAME_MAT_TEXFACE #endif +/* GameData.lodflag */ +#define SCE_LOD_USE_HYST (1 << 0) + /* UV Paint */ #define UV_SCULPT_LOCK_BORDERS 1 #define UV_SCULPT_ALL_ISLANDS 2 diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index d8aa659b68e..a49388866a6 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -2089,6 +2089,14 @@ static void rna_def_object_lodlevel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Distance", "Distance to begin using this level of detail"); RNA_def_property_update(prop, NC_OBJECT | ND_LOD, "rna_Object_lod_distance_update"); + prop = RNA_def_property(srna, "object_hysteresis_percentage", PROP_INT, PROP_PERCENTAGE); + RNA_def_property_int_sdna(prop, NULL, "obhysteresis"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_range(prop, 0, 100, 10, 1); + RNA_def_property_ui_text(prop, "Hysteresis %", "Minimum distance change required to transition to the previous" + " level of detail"); + RNA_def_property_update(prop, NC_OBJECT | ND_LOD, NULL); + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "source"); RNA_def_property_struct_type(prop, "Object"); @@ -2107,6 +2115,11 @@ static void rna_def_object_lodlevel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Use Material", "Use the material from this object at this level of detail"); RNA_def_property_ui_icon(prop, ICON_MATERIAL, 0); RNA_def_property_update(prop, NC_OBJECT | ND_LOD, NULL); + + prop = RNA_def_property(srna, "use_object_hysteresis", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", OB_LOD_USE_HYST); + RNA_def_property_ui_text(prop, "Hysteresis Override", "Override LoD Hysteresis scene setting for this Lod Level"); + RNA_def_property_update(prop, NC_OBJECT | ND_LOD, NULL); } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 2e941487e98..a0a0eedcfed 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -3886,6 +3886,20 @@ static void rna_def_scene_game_data(BlenderRNA *brna) /* Nestled Data */ rna_def_scene_game_recast_data(brna); + + /* LoD */ + prop = RNA_def_property(srna, "use_scene_hysteresis", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "lodflag", SCE_LOD_USE_HYST); + RNA_def_property_ui_text(prop, "Hysteresis", "Use LoD Hysteresis setting for the scene"); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop = RNA_def_property(srna, "scene_hysteresis_percentage", PROP_INT, PROP_PERCENTAGE); + RNA_def_property_int_sdna(prop, NULL, "scehysteresis"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_range(prop, 0, 100, 10, 1); + RNA_def_property_ui_text(prop, "Hysteresis %", "Minimum distance change required to transition to the previous" + " level of detail"); + RNA_def_property_update(prop, NC_SCENE, NULL); } static void rna_def_gpu_dof_fx(BlenderRNA *brna) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index cd2e2151034..7b5cc457ee6 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1554,6 +1554,10 @@ static KX_GameObject *gameobject_from_blenderobject( } gameobj->AddLodMesh(BL_ConvertMesh(lodmesh, lodmatob, kxscene, converter, libloading)); } + if (blenderscene->gm.lodflag & SCE_LOD_USE_HYST) { + kxscene->SetLodHysteresis(true); + gameobj->SetLodHysteresisValue(blenderscene->gm.scehysteresis); + } } // for all objects: check whether they want to diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index c8fc64f4679..16dfe5bd9de 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -92,6 +92,8 @@ KX_GameObject::KX_GameObject( m_bDyna(false), m_layer(0), m_currentLodLevel(0), + m_previousLodLevel(0), + m_lodHysteresis(0), m_pBlenderObject(NULL), m_pBlenderGroupObject(NULL), m_bSuspendDynamics(false), @@ -784,6 +786,11 @@ void KX_GameObject::AddLodMesh(RAS_MeshObject* mesh) m_lodmeshes.push_back(mesh); } +void KX_GameObject::SetLodHysteresisValue(int hysteresis) +{ + m_lodHysteresis = hysteresis; +} + void KX_GameObject::UpdateLod(MT_Vector3 &cam_pos) { // Handle dupligroups @@ -804,14 +811,47 @@ void KX_GameObject::UpdateLod(MT_Vector3 &cam_pos) int level = 0; Object *bob = this->GetBlenderObject(); LodLevel *lod = (LodLevel*) bob->lodlevels.first; + KX_Scene *sce = this->GetScene(); + for (; lod; lod = lod->next, level++) { if (!lod->source || lod->source->type != OB_MESH) level--; - if (!lod->next || lod->next->distance * lod->next->distance > distance2) break; + if (!lod->next) break; + if (level == (this->m_previousLodLevel) || (level == (this->m_previousLodLevel + 1))) { + short hysteresis = 0; + if (sce->IsActivedLodHysteresis()) { + // if exists, LoD level hysteresis will override scene hysteresis + if (lod->next->flags & OB_LOD_USE_HYST) { + hysteresis = lod->next->obhysteresis; + } + else if (this->m_lodHysteresis != 0) { + hysteresis = m_lodHysteresis; + } + } + float hystvariance = MT_abs(lod->next->distance - lod->distance) * hysteresis / 100; + if ((lod->next->distance + hystvariance) * (lod->next->distance + hystvariance) > distance2) + break; + } + else if (level == (this->m_previousLodLevel - 1)) { + short hysteresis = 0; + if (sce->IsActivedLodHysteresis()) { + // if exists, LoD level hysteresis will override scene hysteresis + if (lod->next->flags & OB_LOD_USE_HYST) { + hysteresis = lod->next->obhysteresis; + } + else if (this->m_lodHysteresis != 0) { + hysteresis = m_lodHysteresis; + } + } + float hystvariance = MT_abs(lod->next->distance - lod->distance) * hysteresis / 100; + if ((lod->next->distance - hystvariance) * (lod->next->distance - hystvariance) > distance2) + break; + } } RAS_MeshObject *mesh = this->m_lodmeshes[level]; this->m_currentLodLevel = level; if (mesh != this->m_meshes[0]) { + this->m_previousLodLevel = level; this->GetScene()->ReplaceMesh(this, mesh, true, false); } } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 132e72c45e2..d9810b89c90 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -90,6 +90,8 @@ protected: std::vector m_meshes; std::vector m_lodmeshes; int m_currentLodLevel; + short m_previousLodLevel; + int m_lodHysteresis; SG_QList m_meshSlots; // head of mesh slots of this struct Object* m_pBlenderObject; struct Object* m_pBlenderGroupObject; @@ -804,6 +806,14 @@ public: RAS_MeshObject* mesh ); + /** + * Set lod hysteresis value + */ + void + SetLodHysteresisValue( + int hysteresis + ); + /** * Updates the current lod level based on distance from camera. */ diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 47510baa436..d9d07e78c17 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -156,7 +156,8 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_networkDeviceInterface(ndi), m_active_camera(NULL), m_ueberExecutionPriority(0), - m_blenderScene(scene) + m_blenderScene(scene), + m_isActivedHysteresis(false) { m_suspendedtime = 0.0; m_suspendeddelta = 0.0; @@ -1763,6 +1764,16 @@ void KX_Scene::UpdateObjectLods(void) } } +void KX_Scene::SetLodHysteresis(bool active) +{ + m_isActivedHysteresis = active; +} + +bool KX_Scene::IsActivedLodHysteresis(void) +{ + return m_isActivedHysteresis; +} + void KX_Scene::UpdateObjectActivity(void) { if (m_activity_culling) { diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 2e1ee9f101d..19873daabb3 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -295,6 +295,11 @@ protected: KX_ObstacleSimulation* m_obstacleSimulation; + /** + * Does this scene active the LoD Hysteresis? + */ + bool m_isActivedHysteresis; + public: KX_Scene(class SCA_IInputDevice* keyboarddevice, class SCA_IInputDevice* mousedevice, @@ -546,6 +551,10 @@ public: // Update the mesh for objects based on level of detail settings void UpdateObjectLods(void); + + // Enable/disable LoD Hysteresis + void SetLodHysteresis(bool active); + bool IsActivedLodHysteresis(); // Update the activity box settings for objects in this scene, if needed. void UpdateObjectActivity(void); -- cgit v1.2.3 From 059d5bc80988320dca9cc2797d7bddc75ba0b82f Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Sun, 22 Mar 2015 19:29:31 +0100 Subject: OSX: fix 1 leak ( found and fixed by marcclintdion ) and 1 possible leak in dragndrop, backport to 2.74 --- intern/ghost/intern/GHOST_EventDragnDrop.h | 1 + intern/ghost/intern/GHOST_SystemCocoa.mm | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_EventDragnDrop.h b/intern/ghost/intern/GHOST_EventDragnDrop.h index c51f9568087..b7bf37c99d8 100644 --- a/intern/ghost/intern/GHOST_EventDragnDrop.h +++ b/intern/ghost/intern/GHOST_EventDragnDrop.h @@ -112,6 +112,7 @@ public: for (i = 0; i < strArray->count; i++) free(strArray->strings[i]); + free(strArray->strings); free(strArray); } break; diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 095c738e1e0..ed1200b967c 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -882,7 +882,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType if (!strArray) return GHOST_kFailure; strArray->count = [droppedArray count]; - if (strArray->count == 0) return GHOST_kFailure; + if (strArray->count == 0) { + free(strArray); + return GHOST_kFailure; + } strArray->strings = (GHOST_TUns8**) malloc(strArray->count*sizeof(GHOST_TUns8*)); -- cgit v1.2.3 From 572489ec8936be0dfa1137f497d295e21f9ce693 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 22 Mar 2015 21:13:43 +0100 Subject: Fix wrong sizeof() in new ghash hashing helpers code. Spotted by Coverity. --- source/blender/blenlib/intern/BLI_ghash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 49d3cecafed..cd86bb831f4 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -1004,7 +1004,7 @@ unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]) } unsigned int BLI_ghashutil_uinthash_v4_murmur(const unsigned int key[4]) { - return BLI_hash_mm2((const unsigned char *)key, sizeof(key), 0); + return BLI_hash_mm2((const unsigned char *)key, sizeof(int) * 4 /* sizeof(key) */, 0); } bool BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b) -- cgit v1.2.3 From ed7e593a4b129e1367a7f5aa2d0e9036e5363bea Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 23 Mar 2015 12:48:33 +0500 Subject: Fix T43926: Volume scatter: intersecting objects GPU rendering artifacts Fix T44007: Cycles Volumetrics: block artifacts with overlapping volumes The issue was caused by uninitialized parameters of some closures, which lead to unpredictable behavior of shader_merge_closures(). --- intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h | 1 + intern/cycles/kernel/closure/bsdf_diffuse.h | 4 ++++ intern/cycles/kernel/closure/bsdf_diffuse_ramp.h | 2 ++ intern/cycles/kernel/closure/bsdf_phong_ramp.h | 4 ++-- intern/cycles/kernel/closure/bsdf_reflection.h | 2 ++ intern/cycles/kernel/closure/bsdf_refraction.h | 2 ++ intern/cycles/kernel/closure/bsdf_transparent.h | 2 ++ intern/cycles/kernel/closure/bssrdf.h | 1 + intern/cycles/kernel/closure/volume.h | 1 + 9 files changed, 17 insertions(+), 2 deletions(-) diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h index 580f50d5dd6..98c1159948a 100644 --- a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h @@ -39,6 +39,7 @@ ccl_device int bsdf_ashikhmin_velvet_setup(ShaderClosure *sc) { float sigma = fmaxf(sc->data0, 0.01f); sc->data0 = 1.0f/(sigma * sigma); /* m_invsigma2 */ + sc->data1 = 0.0f; sc->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID; diff --git a/intern/cycles/kernel/closure/bsdf_diffuse.h b/intern/cycles/kernel/closure/bsdf_diffuse.h index 4b29bb096d1..29725c5b5da 100644 --- a/intern/cycles/kernel/closure/bsdf_diffuse.h +++ b/intern/cycles/kernel/closure/bsdf_diffuse.h @@ -40,6 +40,8 @@ CCL_NAMESPACE_BEGIN ccl_device int bsdf_diffuse_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_DIFFUSE_ID; + sc->data0 = 0.0f; + sc->data1 = 0.0f; return SD_BSDF|SD_BSDF_HAS_EVAL; } @@ -83,6 +85,8 @@ ccl_device int bsdf_diffuse_sample(const ShaderClosure *sc, float3 Ng, float3 I, ccl_device int bsdf_translucent_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_TRANSLUCENT_ID; + sc->data0 = 0.0f; + sc->data1 = 0.0f; return SD_BSDF|SD_BSDF_HAS_EVAL; } diff --git a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h index cdaf84f1750..e0287e7655a 100644 --- a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h +++ b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h @@ -52,6 +52,8 @@ ccl_device float3 bsdf_diffuse_ramp_get_color(const ShaderClosure *sc, const flo ccl_device int bsdf_diffuse_ramp_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_DIFFUSE_RAMP_ID; + sc->data0 = 0.0f; + sc->data1 = 0.0f; return SD_BSDF|SD_BSDF_HAS_EVAL; } diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h index f9f263719e9..1ab15eee954 100644 --- a/intern/cycles/kernel/closure/bsdf_phong_ramp.h +++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h @@ -51,9 +51,9 @@ ccl_device float3 bsdf_phong_ramp_get_color(const ShaderClosure *sc, const float ccl_device int bsdf_phong_ramp_setup(ShaderClosure *sc) { - sc->data0 = max(sc->data0, 0.0f); - sc->type = CLOSURE_BSDF_PHONG_RAMP_ID; + sc->data0 = max(sc->data0, 0.0f); + sc->data1 = 0.0f; return SD_BSDF|SD_BSDF_HAS_EVAL; } diff --git a/intern/cycles/kernel/closure/bsdf_reflection.h b/intern/cycles/kernel/closure/bsdf_reflection.h index 303f4c9ce34..d635e734188 100644 --- a/intern/cycles/kernel/closure/bsdf_reflection.h +++ b/intern/cycles/kernel/closure/bsdf_reflection.h @@ -40,6 +40,8 @@ CCL_NAMESPACE_BEGIN ccl_device int bsdf_reflection_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_REFLECTION_ID; + sc->data0 = 0.0f; + sc->data1 = 0.0f; return SD_BSDF; } diff --git a/intern/cycles/kernel/closure/bsdf_refraction.h b/intern/cycles/kernel/closure/bsdf_refraction.h index c78a4b67134..e339778d7d0 100644 --- a/intern/cycles/kernel/closure/bsdf_refraction.h +++ b/intern/cycles/kernel/closure/bsdf_refraction.h @@ -40,6 +40,8 @@ CCL_NAMESPACE_BEGIN ccl_device int bsdf_refraction_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_REFRACTION_ID; + sc->data0 = 0.0f; + sc->data1 = 0.0f; return SD_BSDF; } diff --git a/intern/cycles/kernel/closure/bsdf_transparent.h b/intern/cycles/kernel/closure/bsdf_transparent.h index 3c2fd8004df..78580190f6a 100644 --- a/intern/cycles/kernel/closure/bsdf_transparent.h +++ b/intern/cycles/kernel/closure/bsdf_transparent.h @@ -38,6 +38,8 @@ CCL_NAMESPACE_BEGIN ccl_device int bsdf_transparent_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_TRANSPARENT_ID; + sc->data0 = 0.0f; + sc->data1 = 0.0f; return SD_BSDF|SD_TRANSPARENT; } diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h index b6de2da8c71..43de6e529ee 100644 --- a/intern/cycles/kernel/closure/bssrdf.h +++ b/intern/cycles/kernel/closure/bssrdf.h @@ -30,6 +30,7 @@ ccl_device int bssrdf_setup(ShaderClosure *sc, ClosureType type) return flag; } else { + sc->data0 = 0.0f; sc->data1 = clamp(sc->data1, 0.0f, 1.0f); /* texture blur */ sc->T.x = clamp(sc->T.x, 0.0f, 1.0f); /* sharpness */ sc->type = type; diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h index 439610546e5..4143980f2cd 100644 --- a/intern/cycles/kernel/closure/volume.h +++ b/intern/cycles/kernel/closure/volume.h @@ -35,6 +35,7 @@ ccl_device int volume_henyey_greenstein_setup(ShaderClosure *sc) /* clamp anisotropy to avoid delta function */ sc->data0 = signf(sc->data0) * min(fabsf(sc->data0), 1.0f - 1e-3f); + sc->data1 = 0.0f; return SD_SCATTER; } -- cgit v1.2.3 From c451dba550788c745e3c6c96700fc2620a31eb47 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 23 Mar 2015 17:43:14 +1100 Subject: Mitigate T44035: Proportional editing lag Calculating connected data can be slow, it still lags with heavy meshes but perform some optimizations (nearly twice as fast) --- .../editors/transform/transform_conversions.c | 86 ++++++++++++++-------- 1 file changed, 55 insertions(+), 31 deletions(-) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index b50f56aae3e..2c189b715c4 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -1972,17 +1972,19 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float int i; BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { + float dist; BM_elem_index_set(v, i); /* set_inline */ BM_elem_flag_disable(v, BM_ELEM_TAG); if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { - dists[i] = FLT_MAX; + dist = FLT_MAX; } else { BLI_LINKSTACK_PUSH(queue, v); - - dists[i] = 0.0f; + dist = 0.0f; } + + dists[i] = dists_prev[i] = dist; } bm->elem_index_dirty &= ~BM_VERT; } @@ -1991,55 +1993,77 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float BMVert *v; LinkNode *lnk; + /* this is correct but slow to do each iteration, + * instead sync the dist's while clearing BM_ELEM_TAG (below) */ +#if 0 memcpy(dists_prev, dists, sizeof(float) * bm->totvert); +#endif while ((v = BLI_LINKSTACK_POP(queue))) { - /* quick checks */ - bool has_edges = (v->e != NULL); - bool has_faces = false; + BLI_assert(dists[BM_elem_index_get(v)] != FLT_MAX); /* connected edge-verts */ - if (has_edges) { - BMIter iter; - BMEdge *e; + if (v->e != NULL) { + BMEdge *e_iter, *e_first; + + e_iter = e_first = v->e; - BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { - has_faces |= (BM_edge_is_wire(e) == false); + /* would normally use BM_EDGES_OF_VERT, but this runs so often, + * its faster to iterate on the data directly */ + do { - if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == 0) { - BMVert *v_other = BM_edge_other_vert(e, v); + if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == 0) { + + /* edge distance */ + BMVert *v_other = BM_edge_other_vert(e_iter, v); if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) { if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { BM_elem_flag_enable(v_other, BM_ELEM_TAG); BLI_LINKSTACK_PUSH(queue_next, v_other); } } - } - } - } - - /* imaginary edge diagonally across quad */ - if (has_faces) { - BMIter iter; - BMLoop *l; - BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { - if ((BM_elem_flag_test(l->f, BM_ELEM_HIDDEN) == 0) && (l->f->len == 4)) { - BMVert *v_other = l->next->next->v; - if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) { - if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { - BM_elem_flag_enable(v_other, BM_ELEM_TAG); - BLI_LINKSTACK_PUSH(queue_next, v_other); - } + /* face distance */ + if (e_iter->l) { + BMLoop *l_iter_radial, *l_first_radial; + /** + * imaginary edge diagonally across quad, + * \note, this takes advantage of the rules of winding that we + * know 2 or more of a verts edges wont reference the same face twice. + * Also, if the edge is hidden, the face will be hidden too. + */ + l_iter_radial = l_first_radial = e_iter->l; + + do { + if ((l_iter_radial->v == v) && + (l_iter_radial->f->len == 4) && + (BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0)) + { + BMVert *v_other = l_iter_radial->next->next->v; + if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) { + if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { + BM_elem_flag_enable(v_other, BM_ELEM_TAG); + BLI_LINKSTACK_PUSH(queue_next, v_other); + } + } + } + } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial); } } - } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first); } } + /* clear for the next loop */ for (lnk = queue_next; lnk; lnk = lnk->next) { - BM_elem_flag_disable((BMVert *)lnk->link, BM_ELEM_TAG); + BMVert *v = lnk->link; + const int i = BM_elem_index_get(v); + + BM_elem_flag_disable(v, BM_ELEM_TAG); + + /* keep in sync, avoid having to do full memcpy each iteration */ + dists_prev[i] = dists[i]; } BLI_LINKSTACK_SWAP(queue, queue_next); -- cgit v1.2.3 From 0884c174b3b43cb53b47269cc204f08c0dc68f6a Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 23 Mar 2015 12:00:34 +0100 Subject: Make sure matcap icons are within range. Basically out of range could happen when opening files made in 2.72 when the new icons for texture painting were added. Apparently some more caution is needed here. --- source/blender/editors/space_view3d/drawobject.c | 5 ++++- source/blender/makesrna/intern/rna_space.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 61c9891e201..d4d8db6d6c7 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -7232,8 +7232,11 @@ static void draw_object_matcap_check(View3D *v3d, Object *ob) v3d->defmaterial->preview = NULL; } /* first time users */ - if (v3d->matcap_icon == 0) + if (v3d->matcap_icon < ICON_MATCAP_01 || + v3d->matcap_icon > ICON_MATCAP_24) + { v3d->matcap_icon = ICON_MATCAP_01; + } if (v3d->defmaterial->preview == NULL) v3d->defmaterial->preview = UI_icon_to_preview(v3d->matcap_icon); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index db4b097b9c3..8e262df7e67 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -493,8 +493,11 @@ static void rna_SpaceView3D_matcap_enable(Main *UNUSED(bmain), Scene *UNUSED(sce { View3D *v3d = (View3D *)(ptr->data); - if (v3d->matcap_icon == 0) + if (v3d->matcap_icon < ICON_MATCAP_01 || + v3d->matcap_icon > ICON_MATCAP_24) + { v3d->matcap_icon = ICON_MATCAP_01; + } } static void rna_SpaceView3D_pivot_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) -- cgit v1.2.3 From 3c21885ec4ee2c06e24f43a87ed11a36b0fb7fe7 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 23 Mar 2015 12:18:42 +0100 Subject: Change coefficients to 4 digit precision only. Need to match convention and sum up to 1.0 (previous set had a minor 10^(-10) overflow) Thanks to Campbell for taking notice. --- intern/opencolorio/fallback_impl.cc | 6 +++--- release/datafiles/colormanagement/config.ocio | 2 +- source/blender/imbuf/intern/colormanagement.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc index 136f427ee0e..7ba540a7d77 100644 --- a/intern/opencolorio/fallback_impl.cc +++ b/intern/opencolorio/fallback_impl.cc @@ -170,9 +170,9 @@ void FallbackImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr * /*config*/, * system in place. */ - rgb[0] = 0.2126729f; - rgb[1] = 0.7151522f; - rgb[2] = 0.0721750f; + rgb[0] = 0.2126f; + rgb[1] = 0.7152f; + rgb[2] = 0.0722f; } int FallbackImpl::configGetNumLooks(OCIO_ConstConfigRcPtr * /*config*/) diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index 7ecc9768d57..1cf9a3bb36e 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -6,7 +6,7 @@ ocio_profile_version: 1 search_path: luts strictparsing: true -luma: [0.2126729, 0.7151522, 0.0721750] +luma: [0.2126, 0.7152, 0.0722] description: RRT version ut33 diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index a1b7a14c9fe..20baa1614c9 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -93,7 +93,7 @@ static int global_tot_looks = 0; /* Set to ITU-BT.709 / sRGB primaries weight. Brute force stupid, but only * option with no colormanagement in place. */ -static float luma_coefficients[3] = { 0.2126729f, 0.7151522f, 0.0721750f }; +static float luma_coefficients[3] = { 0.2126f, 0.7152f, 0.0722f }; /* lock used by pre-cached processors getters, so processor wouldn't * be created several times -- cgit v1.2.3 From fd2b4a74c82b75cbbce393a878aa92021b56288d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 23 Mar 2015 22:26:00 +1100 Subject: Use same rgb -> greyscale for BLI_math as imbuf --- source/blender/blenlib/intern/math_color_inline.c | 26 ++++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c index 0e955c1602e..93977a796f5 100644 --- a/source/blender/blenlib/intern/math_color_inline.c +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -211,20 +211,30 @@ MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack) * * \{ */ -/* non-linear luma from ITU-R BT.601-2 - * see: http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC11 - * note: the values used for are not exact matches to those documented above, - * but they are from the same */ +/** + * ITU-R BT.709 primaries + * http://en.wikipedia.org/wiki/Relative_luminance + * + * Real values are: + * ``Y = 0.2126390059(R) + 0.7151686788(G) + 0.0721923154(B)`` + * according to: "Derivation of Basic Television Color Equations", RP 177-1993 + * + * But this is sums slightly above 1.0, the document recommends to use: + * ``0.2126(R) + 0.7152(G) + 0.0722(B)``, as used here. + * + * The high precision values are used to calculate the rounded byte weights so they add up to 255: + * ``54(R) + 182(G) + 19(B)`` + */ MINLINE float rgb_to_grayscale(const float rgb[3]) { - return 0.3f * rgb[0] + 0.58f * rgb[1] + 0.12f * rgb[2]; + return (0.2126f * rgb[0]) + (0.7152f * rgb[1]) + (0.0722f * rgb[2]); } MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3]) { - return (unsigned char)(((76 * (unsigned short)rgb[0]) + - (148 * (unsigned short)rgb[1]) + - (31 * (unsigned short)rgb[2])) / 255); + return (unsigned char)(((54 * (unsigned short)rgb[0]) + + (182 * (unsigned short)rgb[1]) + + (19 * (unsigned short)rgb[2])) / 255); } /** \} */ -- cgit v1.2.3 From c48ebb44ae15b1238a6d86e98fee6cd1ff0cba73 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 23 Mar 2015 12:48:09 +0100 Subject: Tidy up the user interface for depth of field based on feedback by NudelZ on irc, thanks! --- intern/cycles/blender/addon/ui.py | 8 +++++--- release/scripts/startup/bl_ui/properties_data_camera.py | 10 +++++----- source/blender/makesrna/intern/rna_scene.c | 4 ++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 1097b79ffa5..f0f256f979e 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -456,10 +456,12 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel): sub = col.row() sub.active = cam.dof_object is None sub.prop(cam, "dof_distance", text="Distance") - col.prop(dof_options, "fstop") - col.prop(dof_options, "use_high_quality") + sub = col.column(align=True) + sub.label("Viewport:") + sub.prop(dof_options, "use_high_quality") + sub.prop(dof_options, "fstop") if dof_options.use_high_quality: - col.prop(dof_options, "blades") + sub.prop(dof_options, "blades") col = split.column() diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py index 6a0d680df53..bc66e39b48f 100644 --- a/release/scripts/startup/bl_ui/properties_data_camera.py +++ b/release/scripts/startup/bl_ui/properties_data_camera.py @@ -184,15 +184,15 @@ class DATA_PT_camera_dof(CameraButtonsPanel, Panel): col = split.column() col.label(text="Focus:") col.prop(cam, "dof_object", text="") - col.prop(dof_options, "use_high_quality") - - col = split.column() - col.prop(dof_options, "fstop") - sub = col.column() sub.active = (cam.dof_object is None) sub.prop(cam, "dof_distance", text="Distance") + col = split.column(align=True) + col.label("Viewport:") + col.prop(dof_options, "use_high_quality") + col.prop(dof_options, "fstop") + if dof_options.use_high_quality: col.prop(dof_options, "blades") diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index a0a0eedcfed..93bbb6d6491 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -3931,14 +3931,14 @@ static void rna_def_gpu_dof_fx(BlenderRNA *brna) RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "fstop", PROP_FLOAT, PROP_NONE); - RNA_def_property_ui_text(prop, "Viewport F-stop", "F-stop for dof effect"); + RNA_def_property_ui_text(prop, "F-stop", "F-stop for dof effect"); RNA_def_property_range(prop, 0.0f, FLT_MAX); RNA_def_property_ui_range(prop, 0.1f, 128.0f, 10, 1); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "blades", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "num_blades"); - RNA_def_property_ui_text(prop, "Viewport Camera Blades", "Blades for dof effect"); + RNA_def_property_ui_text(prop, "Blades", "Blades for dof effect"); RNA_def_property_range(prop, 0, 16); RNA_def_property_int_funcs(prop, NULL, "rna_GPUDOFSettings_blades_set", NULL); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); -- cgit v1.2.3 From b8a6cd0140cae6d4da1d17577f60dc7b854fdff1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 23 Mar 2015 22:51:12 +1100 Subject: Cleanup: comments, style --- source/blender/blenkernel/intern/bpath.c | 2 +- source/blender/blenlib/intern/BLI_ghash.c | 6 +++--- source/blender/blenlib/intern/BLI_linklist.c | 2 +- source/blender/blenlib/intern/math_color_inline.c | 2 +- source/blender/blenloader/intern/versioning_270.c | 2 +- source/blender/editors/armature/pose_transform.c | 2 +- source/blender/editors/space_view3d/view3d_view.c | 2 +- source/blender/gpu/intern/gpu_extensions.c | 2 +- source/blender/makesrna/intern/rna_object.c | 4 ++-- source/blender/makesrna/intern/rna_scene.c | 4 ++-- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 3488cff7315..e94f30da0c5 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -393,7 +393,7 @@ static bool rewrite_path_alloc(char **path, BPathVisitor visit_cb, const char *a } if (visit_cb(userdata, path_dst, path_src)) { - MEM_freeN((*path)); + MEM_freeN(*path); (*path) = BLI_strdup(path_dst); return true; } diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index cd86bb831f4..f2705c79574 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -298,14 +298,14 @@ static void ghash_buckets_contract( #ifdef GHASH_USE_MODULO_BUCKETS while ((nentries < gh->limit_shrink) && - (gh->cursize > gh->size_min)) + (gh->cursize > gh->size_min)) { new_nbuckets = hashsizes[--gh->cursize]; gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets); } #else while ((nentries < gh->limit_shrink) && - (gh->bucket_bit > gh->bucket_bit_min)) + (gh->bucket_bit > gh->bucket_bit_min)) { new_nbuckets = 1u << --gh->bucket_bit; gh->limit_shrink = GHASH_LIMIT_SHRINK(new_nbuckets); @@ -525,7 +525,7 @@ static Entry *ghash_remove_ex( Entry *e_prev; Entry *e = ghash_lookup_entry_prev_ex(gh, key, &e_prev, bucket_index); - BLI_assert(!valfreefp|| !(gh->flag & GHASH_FLAG_IS_GSET)); + BLI_assert(!valfreefp || !(gh->flag & GHASH_FLAG_IS_GSET)); if (e) { if (keyfreefp) keyfreefp(e->key); diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c index 391f3ef7702..f0efe49cfdb 100644 --- a/source/blender/blenlib/intern/BLI_linklist.c +++ b/source/blender/blenlib/intern/BLI_linklist.c @@ -230,7 +230,7 @@ void *BLI_linklist_pop(struct LinkNode **listp) void *link = (*listp)->link; void *next = (*listp)->next; - MEM_freeN((*listp)); + MEM_freeN(*listp); *listp = next; return link; diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c index 93977a796f5..45466226e72 100644 --- a/source/blender/blenlib/intern/math_color_inline.c +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -219,7 +219,7 @@ MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack) * ``Y = 0.2126390059(R) + 0.7151686788(G) + 0.0721923154(B)`` * according to: "Derivation of Basic Television Color Equations", RP 177-1993 * - * But this is sums slightly above 1.0, the document recommends to use: + * As this sums slightly above 1.0, the document recommends to use: * ``0.2126(R) + 0.7152(G) + 0.0722(B)``, as used here. * * The high precision values are used to calculate the rounded byte weights so they add up to 255: diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 0853c93750c..fc9ea1a3acf 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -657,7 +657,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) /* hysteresis setted to 10% but not actived */ if (!DNA_struct_elem_find(fd->filesdna, "LodLevel", "int", "obhysteresis")) { - Object* ob; + Object *ob; for (ob = main->object.first; ob; ob = ob->id.next) { LodLevel *level; for (level = ob->lodlevels.first; level; level = level->next) { diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index fbf6dccdb38..01e16df9f08 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -320,7 +320,7 @@ static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bo if (selOnly) paste_ok = ((pchan) && (pchan->bone->flag & BONE_SELECTED)); else - paste_ok = ((pchan != NULL)); + paste_ok = (pchan != NULL); /* continue? */ if (paste_ok) { diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 4154f8e8845..2de391c5163 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1790,7 +1790,7 @@ float ED_view3d_radius_to_dist( angle = focallength_to_fov(lens, sensor_size); /* zoom influences lens, correct this by scaling the angle as a distance (by the zoom-level) */ - angle = ((atanf(tanf(angle / 2.0f) * zoom) * 2.0f)); + angle = atanf(tanf(angle / 2.0f) * zoom) * 2.0f; dist = ED_view3d_radius_to_dist_persp(angle, radius); } diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index b4ffc978d11..c6b95caa6f7 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -365,7 +365,7 @@ static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixel p = pixels = MEM_callocN(sizeof(unsigned char)*len, "GPUTexturePixels"); for (a=0; a Date: Tue, 24 Mar 2015 00:02:09 +1100 Subject: Allow bg-image rotation for camera views --- source/blender/editors/space_view3d/view3d_draw.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index db4499afc26..b8599cf6ea8 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1834,9 +1834,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, ED_region_pixelspace(ar); glTranslatef(centx, centy, 0.0); - if (rv3d->persp != RV3D_CAMOB) { - glRotatef(RAD2DEGF(-bgpic->rotation), 0.0f, 0.0f, 1.0f); - } + glRotatef(RAD2DEGF(-bgpic->rotation), 0.0f, 0.0f, 1.0f); if (bgpic->flag & V3D_BGPIC_FLIP_X) { zoomx *= -1.0f; -- cgit v1.2.3 From e8b6d86f9514b86daefe6ee0182c57d794b603f9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Mar 2015 00:18:57 +1100 Subject: Fix T44093: Color picker SV+H order wrong. Based on HSV ordering, SV+H had S<>V swapped. --- source/blender/editors/interface/interface_handlers.c | 8 ++++---- source/blender/editors/interface/interface_widgets.c | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 71b7b95208b..68a69c4cd4e 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -4705,8 +4705,8 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, switch ((int)but->a1) { case UI_GRAD_SV: - hsv[2] = x; - hsv[1] = y; + hsv[1] = x; + hsv[2] = y; break; case UI_GRAD_HV: hsv[0] = x; @@ -4783,8 +4783,8 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, switch ((int)but->a1) { case UI_GRAD_SV: - hsv[2] += ndof->rvec[2] * sensitivity; - hsv[1] += ndof->rvec[0] * sensitivity; + hsv[1] += ndof->rvec[2] * sensitivity; + hsv[2] += ndof->rvec[0] * sensitivity; break; case UI_GRAD_HV: hsv[0] += ndof->rvec[2] * sensitivity; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 3d021e7dd10..0b3684ff755 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2342,9 +2342,9 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons switch (type) { case UI_GRAD_SV: hsv_to_rgb(h, 0.0, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]); - hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]); - hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]); - hsv_to_rgb(h, 1.0, 0.0, &col1[3][0], &col1[3][1], &col1[3][2]); + hsv_to_rgb(h, 0.0, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(h, 0.0, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(h, 0.0, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]); break; case UI_GRAD_HV: hsv_to_rgb(0.0, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]); @@ -2399,10 +2399,10 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons /* new color */ switch (type) { case UI_GRAD_SV: - hsv_to_rgb(h, 0.0, dx, &col1[0][0], &col1[0][1], &col1[0][2]); - hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]); - hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]); - hsv_to_rgb(h, 1.0, dx, &col1[3][0], &col1[3][1], &col1[3][2]); + hsv_to_rgb(h, dx, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]); + hsv_to_rgb(h, dx, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(h, dx, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(h, dx, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]); break; case UI_GRAD_HV: hsv_to_rgb(dx_next, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]); @@ -2485,7 +2485,7 @@ void ui_hsvcube_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float *x switch ((int)but->a1) { case UI_GRAD_SV: - x = hsv[2]; y = hsv[1]; break; + x = hsv[1]; y = hsv[2]; break; case UI_GRAD_HV: x = hsv[0]; y = hsv[2]; break; case UI_GRAD_HS: -- cgit v1.2.3 From f5c33a2d48945482fd685c04a2d011ca5760f72d Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 23 Mar 2015 15:19:54 +0100 Subject: Shader errors: Count line from beginning of the whole shader source instead of each string sepatately since it helps with finding out the error line in most tested platforms --- source/blender/gpu/intern/gpu_extensions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index c6b95caa6f7..ec7e80e6b00 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -1407,12 +1407,12 @@ struct GPUShader { static void shader_print_errors(const char *task, char *log, const char **code, int totcode) { int i; + int line = 1; fprintf(stderr, "GPUShader: %s error:\n", task); for (i = 0; i < totcode; i++) { const char *c, *pos, *end = code[i] + strlen(code[i]); - int line = 1; if ((G.debug & G_DEBUG)) { fprintf(stderr, "===== shader string %d ====\n", i + 1); -- cgit v1.2.3 From b13770215c97194aba0703d9844976f6eb3a61fb Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 23 Mar 2015 17:07:21 +0100 Subject: Use linear filtering for final pass of high quality depth of field, no need to get nearest point anymore. --- source/blender/gpu/intern/gpu_compositing.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index 96de0db0acb..7b2aca65324 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -960,11 +960,11 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str GPU_texture_bind(fx->dof_near_blur, numslots++); GPU_shader_uniform_texture(dof_shader_pass3, near_uniform, fx->dof_near_blur); - GPU_texture_filter_mode(fx->dof_near_blur, false, false); + GPU_texture_filter_mode(fx->dof_near_blur, false, true); GPU_texture_bind(fx->dof_far_blur, numslots++); GPU_shader_uniform_texture(dof_shader_pass3, far_uniform, fx->dof_far_blur); - GPU_texture_filter_mode(fx->dof_far_blur, false, false); + GPU_texture_filter_mode(fx->dof_far_blur, false, true); GPU_texture_bind(fx->depth_buffer, numslots++); GPU_texture_filter_mode(fx->depth_buffer, false, false); -- cgit v1.2.3 From 1b71279adccb9f8cc1f4d7cbb3cbb06871da982e Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 23 Mar 2015 18:33:50 +0100 Subject: Versioning code to correct socket naming after 340b76b42c53816ddac1b4cecdff3d8d2010a9cc Reported by formerly Old_Demon on blenderartists. Apparently this caused old files to lose their links to material sockets (noob own mistake from inexperience with node system). This should either be included in release with version checking being set to version 2.73 and subversion 10, without tweaking the BKE_blender.h file OR 340b76b42c53816ddac1b4cecdff3d8d2010a9cc should be reverted for this release. Thanks to Lukas for checking this out. --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenloader/intern/versioning_270.c | 27 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index eb6797ed4dd..98672025028 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 274 -#define BLENDER_SUBVERSION 1 +#define BLENDER_SUBVERSION 2 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 5 diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index fc9ea1a3acf..9c8db6d6a9b 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -673,4 +673,31 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } + + if (!MAIN_VERSION_ATLEAST(main, 274, 2)) { + FOREACH_NODETREE(main, ntree, id) { + bNode *node; + bNodeSocket *sock; + + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_MATERIAL) { + for (sock = node->inputs.first; sock; sock = sock->next) { + if (STREQ(sock->name, "Refl")) { + BLI_strncpy(sock->name, "DiffuseIntensity", sizeof(sock->name)); + } + } + } + else if (node->type == SH_NODE_MATERIAL_EXT) { + for (sock = node->outputs.first; sock; sock = sock->next) { + if (STREQ(sock->name, "Refl")) { + BLI_strncpy(sock->name, "DiffuseIntensity", sizeof(sock->name)); + } + else if (STREQ(sock->name, "Ray Mirror")) { + BLI_strncpy(sock->name, "Reflectivity", sizeof(sock->name)); + } + } + } + } + } FOREACH_NODETREE_END + } } -- cgit v1.2.3 From f65e3c7f1b5aaa9b5376c20a36267aad27ce40ec Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 23 Mar 2015 18:54:56 +0100 Subject: Fix T44076, SSAO in solid mode will disable antialiasing in wireframe mode. Yes it will, because those modes stay active. So on user side, expose depth of field option always (I don't see why not), but disable SSAO in wireframe/bounding box mode. It is a known limitation that compositing does not support antialiasing yet, but better give users some more control. This could be included in final release but it's not that serious either. --- release/scripts/startup/bl_ui/space_view3d.py | 10 ++++++---- source/blender/editors/space_view3d/view3d_draw.c | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 128e24a6d68..a5d399ee55e 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -2975,12 +2975,14 @@ class VIEW3D_PT_view3d_shading(Panel): if obj and obj.mode == 'EDIT': col.prop(view, "show_occlude_wire") - fx_settings = view.fx_settings - sub = col.column() - sub.active = view.region_3d.view_perspective == 'CAMERA' - sub.prop(fx_settings, "use_dof") + fx_settings = view.fx_settings + sub = col.column() + sub.active = view.region_3d.view_perspective == 'CAMERA' + sub.prop(fx_settings, "use_dof") + + if view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}: col.prop(fx_settings, "use_ssao", text="Ambient Occlusion") if fx_settings.use_ssao: ssao_settings = fx_settings.ssao diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index b8599cf6ea8..116eb48bf88 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -3120,7 +3120,17 @@ void ED_view3d_draw_offscreen( /* framebuffer fx needed, we need to draw offscreen first */ if (v3d->fx_settings.fx_flag && fx) { + GPUSSAOSettings *ssao = NULL; + + if (v3d->drawtype < OB_SOLID) { + ssao = v3d->fx_settings.ssao; + v3d->fx_settings.ssao = NULL; + } + do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings); + + if (ssao) + v3d->fx_settings.ssao = ssao; } /* clear opengl buffers */ @@ -3551,6 +3561,10 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3 else { fx_settings.dof = NULL; } + + if (v3d->drawtype < OB_SOLID) + fx_settings.ssao = NULL; + do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings); } -- cgit v1.2.3 From ddf58004c4a4ad7fc59f9cd1c3f6f0a800424ee3 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Mon, 23 Mar 2015 18:57:19 +0100 Subject: BGE: LoD Hysteresis clean up Move scene hysteresis value to KX_Scene where it should be (instead of KX_GameObject) --- .../Converter/BL_BlenderDataConversion.cpp | 2 +- source/gameengine/Ketsji/KX_GameObject.cpp | 20 +++++++------------- source/gameengine/Ketsji/KX_GameObject.h | 9 --------- source/gameengine/Ketsji/KX_Scene.cpp | 13 ++++++++++++- source/gameengine/Ketsji/KX_Scene.h | 7 +++++-- 5 files changed, 25 insertions(+), 26 deletions(-) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 7b5cc457ee6..6e3a321bfdf 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1556,7 +1556,7 @@ static KX_GameObject *gameobject_from_blenderobject( } if (blenderscene->gm.lodflag & SCE_LOD_USE_HYST) { kxscene->SetLodHysteresis(true); - gameobj->SetLodHysteresisValue(blenderscene->gm.scehysteresis); + kxscene->SetLodHysteresisValue(blenderscene->gm.scehysteresis); } } diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 16dfe5bd9de..d0c6792cce0 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -93,7 +93,6 @@ KX_GameObject::KX_GameObject( m_layer(0), m_currentLodLevel(0), m_previousLodLevel(0), - m_lodHysteresis(0), m_pBlenderObject(NULL), m_pBlenderGroupObject(NULL), m_bSuspendDynamics(false), @@ -786,11 +785,6 @@ void KX_GameObject::AddLodMesh(RAS_MeshObject* mesh) m_lodmeshes.push_back(mesh); } -void KX_GameObject::SetLodHysteresisValue(int hysteresis) -{ - m_lodHysteresis = hysteresis; -} - void KX_GameObject::UpdateLod(MT_Vector3 &cam_pos) { // Handle dupligroups @@ -811,20 +805,20 @@ void KX_GameObject::UpdateLod(MT_Vector3 &cam_pos) int level = 0; Object *bob = this->GetBlenderObject(); LodLevel *lod = (LodLevel*) bob->lodlevels.first; - KX_Scene *sce = this->GetScene(); + KX_Scene *kxscene = this->GetScene(); for (; lod; lod = lod->next, level++) { if (!lod->source || lod->source->type != OB_MESH) level--; if (!lod->next) break; if (level == (this->m_previousLodLevel) || (level == (this->m_previousLodLevel + 1))) { short hysteresis = 0; - if (sce->IsActivedLodHysteresis()) { + if (kxscene->IsActivedLodHysteresis()) { // if exists, LoD level hysteresis will override scene hysteresis if (lod->next->flags & OB_LOD_USE_HYST) { hysteresis = lod->next->obhysteresis; } - else if (this->m_lodHysteresis != 0) { - hysteresis = m_lodHysteresis; + else { + hysteresis = kxscene->GetLodHysteresisValue(); } } float hystvariance = MT_abs(lod->next->distance - lod->distance) * hysteresis / 100; @@ -833,13 +827,13 @@ void KX_GameObject::UpdateLod(MT_Vector3 &cam_pos) } else if (level == (this->m_previousLodLevel - 1)) { short hysteresis = 0; - if (sce->IsActivedLodHysteresis()) { + if (kxscene->IsActivedLodHysteresis()) { // if exists, LoD level hysteresis will override scene hysteresis if (lod->next->flags & OB_LOD_USE_HYST) { hysteresis = lod->next->obhysteresis; } - else if (this->m_lodHysteresis != 0) { - hysteresis = m_lodHysteresis; + else { + hysteresis = kxscene->GetLodHysteresisValue(); } } float hystvariance = MT_abs(lod->next->distance - lod->distance) * hysteresis / 100; diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index d9810b89c90..acc63585749 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -91,7 +91,6 @@ protected: std::vector m_lodmeshes; int m_currentLodLevel; short m_previousLodLevel; - int m_lodHysteresis; SG_QList m_meshSlots; // head of mesh slots of this struct Object* m_pBlenderObject; struct Object* m_pBlenderGroupObject; @@ -806,14 +805,6 @@ public: RAS_MeshObject* mesh ); - /** - * Set lod hysteresis value - */ - void - SetLodHysteresisValue( - int hysteresis - ); - /** * Updates the current lod level based on distance from camera. */ diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index d9d07e78c17..e26fdaa4898 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -157,7 +157,8 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_active_camera(NULL), m_ueberExecutionPriority(0), m_blenderScene(scene), - m_isActivedHysteresis(false) + m_isActivedHysteresis(false), + m_lodHysteresisValue(0) { m_suspendedtime = 0.0; m_suspendeddelta = 0.0; @@ -1774,6 +1775,16 @@ bool KX_Scene::IsActivedLodHysteresis(void) return m_isActivedHysteresis; } +void KX_Scene::SetLodHysteresisValue(int hysteresisvalue) +{ + m_lodHysteresisValue = hysteresisvalue; +} + +int KX_Scene::GetLodHysteresisValue(void) +{ + return m_lodHysteresisValue; +} + void KX_Scene::UpdateObjectActivity(void) { if (m_activity_culling) { diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 19873daabb3..a031be78e92 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -296,9 +296,10 @@ protected: KX_ObstacleSimulation* m_obstacleSimulation; /** - * Does this scene active the LoD Hysteresis? + * LOD Hysteresis settings */ bool m_isActivedHysteresis; + int m_lodHysteresisValue; public: KX_Scene(class SCA_IInputDevice* keyboarddevice, @@ -552,9 +553,11 @@ public: // Update the mesh for objects based on level of detail settings void UpdateObjectLods(void); - // Enable/disable LoD Hysteresis + // LoD Hysteresis functions void SetLodHysteresis(bool active); bool IsActivedLodHysteresis(); + void SetLodHysteresisValue(int hysteresisvalue); + int GetLodHysteresisValue(); // Update the activity box settings for objects in this scene, if needed. void UpdateObjectActivity(void); -- cgit v1.2.3 From 1bee77b77ad625111489e4d44531e8fdc5107e7c Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 23 Mar 2015 19:23:49 +0100 Subject: Disable high quality depth of field for GPUs that don't support it, system will fall back to low quality depth of field. Also add check in case some of the errors are caused by crappy framebuffer object support. --- source/blender/gpu/intern/gpu_compositing.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index 7b2aca65324..a12b9c8a05b 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -469,7 +469,7 @@ bool GPU_fx_compositor_initialize_passes( } } - fx->dof_high_quality = dof_high_quality; + fx->dof_high_quality = dof_high_quality && GPU_geometry_shader_support() && GPU_instanced_drawing_support(); } else { /* cleanup unnecessary buffers */ @@ -851,6 +851,8 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str /* binding takes care of setting the viewport to the downsampled size */ GPU_framebuffer_slots_bind(fx->gbuffer, 0); + GPU_framebuffer_check_valid(fx->gbuffer); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* disable bindings */ GPU_texture_filter_mode(src, false, true); -- cgit v1.2.3 From 6af89c99130cc559d28876946f35f06b72f25e5a Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 23 Mar 2015 15:04:11 -0400 Subject: compile fix --- source/blender/gpu/intern/gpu_compositing.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index a12b9c8a05b..ed8af17b34c 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -851,7 +851,7 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str /* binding takes care of setting the viewport to the downsampled size */ GPU_framebuffer_slots_bind(fx->gbuffer, 0); - GPU_framebuffer_check_valid(fx->gbuffer); + GPU_framebuffer_check_valid(fx->gbuffer, NULL); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* disable bindings */ -- cgit v1.2.3 From 722ddaaccd089457d40f4be01c891a91f707c597 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Mar 2015 06:15:52 +1100 Subject: Remove 'lorem ipsum' operator its a very specific function, and not hard to paste body text from elsewhere. We can make an addon if its important to some users. --- release/scripts/startup/bl_ui/space_view3d.py | 4 - source/blender/editors/curve/CMakeLists.txt | 1 - source/blender/editors/curve/curve_intern.h | 3 - source/blender/editors/curve/curve_ops.c | 1 - source/blender/editors/curve/editfont.c | 51 -- source/blender/editors/curve/lorem.c | 658 -------------------------- 6 files changed, 718 deletions(-) delete mode 100644 source/blender/editors/curve/lorem.c diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index a5d399ee55e..9de40171e51 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -2568,10 +2568,6 @@ class VIEW3D_MT_edit_font(Menu): layout.operator("font.style_toggle", text="Toggle Underline").style = 'UNDERLINE' layout.operator("font.style_toggle", text="Toggle Small Caps").style = 'SMALL_CAPS' - layout.separator() - - layout.operator("font.insert_lorem") - class VIEW3D_MT_edit_text_chars(Menu): bl_label = "Special Characters" diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt index 0b449c4334d..1b877c0fba9 100644 --- a/source/blender/editors/curve/CMakeLists.txt +++ b/source/blender/editors/curve/CMakeLists.txt @@ -38,7 +38,6 @@ set(SRC editcurve.c editcurve_add.c editfont.c - lorem.c curve_intern.h ) diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h index d54db77754f..579f149ea8b 100644 --- a/source/blender/editors/curve/curve_intern.h +++ b/source/blender/editors/curve/curve_intern.h @@ -38,9 +38,6 @@ struct EditNurb; struct Object; struct wmOperatorType; -/* lorem.c */ -extern const char ED_lorem[]; - /* editfont.c */ enum { DEL_ALL, DEL_NEXT_CHAR, DEL_PREV_CHAR, DEL_SELECTION, DEL_NEXT_SEL, DEL_PREV_SEL }; enum { CASE_LOWER, CASE_UPPER }; diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c index 0f42dc923a4..4bcb16d31ef 100644 --- a/source/blender/editors/curve/curve_ops.c +++ b/source/blender/editors/curve/curve_ops.c @@ -54,7 +54,6 @@ void ED_operatortypes_curve(void) { WM_operatortype_append(FONT_OT_text_insert); WM_operatortype_append(FONT_OT_line_break); - WM_operatortype_append(FONT_OT_insert_lorem); WM_operatortype_append(FONT_OT_case_toggle); WM_operatortype_append(FONT_OT_case_set); diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 8393acc6919..303aa2ccded 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -275,57 +275,6 @@ static void text_update_edited(bContext *C, Object *obedit, int mode) WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); } -/********************** insert lorem operator *********************/ - -static int insert_lorem_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Object *obedit = CTX_data_edit_object(C); - const char *p, *p2; - int i; - static const char *lastlorem = NULL; - - if (lastlorem) - p = lastlorem; - else - p = ED_lorem; - - i = rand() / (RAND_MAX / 6) + 4; - - for (p2 = p; *p2 && i; p2++) { - insert_into_textbuf(obedit, *p2); - - if (*p2 == '.') - i--; - } - - lastlorem = p2 + 1; - if (strlen(lastlorem) < 5) - lastlorem = ED_lorem; - - insert_into_textbuf(obedit, '\n'); - insert_into_textbuf(obedit, '\n'); - - DAG_id_tag_update(obedit->data, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -void FONT_OT_insert_lorem(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Insert Lorem"; - ot->description = "Insert placeholder text"; - ot->idname = "FONT_OT_insert_lorem"; - - /* api callbacks */ - ot->exec = insert_lorem_exec; - ot->poll = ED_operator_editfont; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - /* -------------------------------------------------------------------- */ /* Generic Paste Functions */ diff --git a/source/blender/editors/curve/lorem.c b/source/blender/editors/curve/lorem.c deleted file mode 100644 index 59bf3f50dbc..00000000000 --- a/source/blender/editors/curve/lorem.c +++ /dev/null @@ -1,658 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/editors/curve/lorem.c - * \ingroup edcurve - */ - - -#include "BLI_sys_types.h" -#include "curve_intern.h" - -const char ED_lorem[] = { -76, 111, 114, 101, 109, 32, 105, 112, 115, 117, 109, 32, 100, 111, 108, 111, 114, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 99, -111, 110, 115, 101, 99, 116, 101, 116, 117, 101, 114, 32, 97, 100, 105, 112, 105, 115, 99, 105, 110, 103, 32, 101, 108, 105, 116, 46, 32, 65, 108, 105, -113, 117, 97, 109, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 115, 101, 109, 46, 32, 78, 117, 108, -108, 97, 109, 32, 112, 114, 101, 116, 105, 117, 109, 44, 32, 116, 111, 114, 116, 111, 114, 32, 110, 111, 110, 32, 101, 117, 105, 115, 109, 111, 100, 32, -118, 97, 114, 105, 117, 115, 44, 32, 110, 117, 108, 108, 97, 32, 111, 100, 105, 111, 32, 115, 111, 100, 97, 108, 101, 115, 32, 110, 117, 108, 108, 97, -44, 32, 97, 116, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 108, 111, 114, 101, 109, 32, 109, 101, 116, 117, 115, 32, 115, 101, 100, 32, 110, 117, -108, 108, 97, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 105, 110, 32, 108, 101, 99, 116, 117, 115, 32, 97, 116, 32, 112, 101, 100, -101, 32, 98, 108, 97, 110, 100, 105, 116, 32, 118, 105, 118, 101, 114, 114, 97, 46, 32, 70, 117, 115, 99, 101, 32, 115, 99, 101, 108, 101, 114, 105, -115, 113, 117, 101, 32, 105, 112, 115, 117, 109, 32, 110, 101, 99, 32, 101, 110, 105, 109, 46, 32, 70, 117, 115, 99, 101, 32, 101, 117, 105, 115, 109, -111, 100, 32, 110, 117, 110, 99, 32, 105, 100, 32, 101, 110, 105, 109, 46, 32, 73, 110, 32, 118, 101, 110, 101, 110, 97, 116, 105, 115, 32, 99, 117, -114, 115, 117, 115, 32, 97, 114, 99, 117, 46, 32, 65, 101, 110, 101, 97, 110, 32, 113, 117, 105, 115, 32, 100, 117, 105, 46, 32, 77, 97, 101, 99, -101, 110, 97, 115, 32, 108, 97, 111, 114, 101, 101, 116, 46, 32, 78, 117, 108, 108, 97, 32, 116, 101, 109, 112, 111, 114, 44, 32, 97, 114, 99, 117, -32, 112, 117, 108, 118, 105, 110, 97, 114, 32, 112, 114, 101, 116, 105, 117, 109, 32, 115, 117, 115, 99, 105, 112, 105, 116, 44, 32, 116, 111, 114, 116, -111, 114, 32, 119, 105, 115, 105, 32, 100, 97, 112, 105, 98, 117, 115, 32, 108, 105, 98, 101, 114, 111, 44, 32, 105, 100, 32, 111, 114, 110, 97, 114, -101, 32, 102, 101, 108, 105, 115, 32, 105, 112, 115, 117, 109, 32, 115, 117, 115, 99, 105, 112, 105, 116, 32, 112, 117, 114, 117, 115, 46, 32, 77, 97, -101, 99, 101, 110, 97, 115, 32, 105, 112, 115, 117, 109, 46, 32, 77, 111, 114, 98, 105, 32, 99, 117, 114, 115, 117, 115, 46, 32, 86, 101, 115, 116, -105, 98, 117, 108, 117, 109, 32, 100, 105, 97, 109, 32, 112, 117, 114, 117, 115, 44, 32, 99, 111, 109, 109, 111, 100, 111, 32, 101, 116, 44, 32, 99, -111, 110, 118, 97, 108, 108, 105, 115, 32, 101, 117, 44, 32, 112, 111, 115, 117, 101, 114, 101, 32, 97, 116, 44, 32, 108, 105, 103, 117, 108, 97, 46, -32, 78, 117, 108, 108, 97, 32, 97, 108, 105, 113, 117, 97, 109, 32, 97, 108, 105, 113, 117, 101, 116, 32, 108, 111, 114, 101, 109, 46, 32, 78, 117, -110, 99, 32, 101, 116, 32, 109, 97, 117, 114, 105, 115, 32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 32, 101, 115, 116, 32, 98, 105, 98, 101, 110, -100, 117, 109, 32, 115, 117, 115, 99, 105, 112, 105, 116, 46, 32, 68, 111, 110, 101, 99, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, -32, 108, 105, 98, 101, 114, 111, 32, 101, 117, 32, 110, 105, 115, 108, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 101, 103, -101, 116, 32, 108, 105, 98, 101, 114, 111, 46, 32, 68, 111, 110, 101, 99, 32, 116, 101, 109, 112, 117, 115, 32, 105, 112, 115, 117, 109, 32, 115, 101, -100, 32, 113, 117, 97, 109, 46, 32, 83, 101, 100, 32, 98, 108, 97, 110, 100, 105, 116, 32, 110, 117, 110, 99, 32, 113, 117, 105, 115, 32, 101, 110, -105, 109, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 108, 101, 99, 116, 117, 115, 32, 100, 105, 97, 109, 44, 32, 97, 100, 105, 112, 105, 115, 99, -105, 110, 103, 32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 44, 32, 112, 108, 97, 99, 101, 114, 97, 116, 32, 110, 111, 110, 44, 32, 112, 117, 108, -118, 105, 110, 97, 114, 32, 105, 100, 44, 32, 102, 101, 108, 105, 115, 46, 32, 73, 110, 32, 99, 111, 110, 103, 117, 101, 32, 109, 97, 103, 110, 97, -32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 117, 114, 110, 97, 46, 32, 78, 117, 110, 99, 32, 110, 111, 110, 32, 97, 117, 103, 117, 101, 32, 115, -101, 100, 32, 110, 105, 115, 108, 32, 100, 105, 99, 116, 117, 109, 32, 108, 97, 111, 114, 101, 101, 116, 46, 32, 67, 117, 109, 32, 115, 111, 99, 105, -105, 115, 32, 110, 97, 116, 111, 113, 117, 101, 32, 112, 101, 110, 97, 116, 105, 98, 117, 115, 32, 101, 116, 32, 109, 97, 103, 110, 105, 115, 32, 100, -105, 115, 32, 112, 97, 114, 116, 117, 114, 105, 101, 110, 116, 32, 109, 111, 110, 116, 101, 115, 44, 32, 110, 97, 115, 99, 101, 116, 117, 114, 32, 114, -105, 100, 105, 99, 117, 108, 117, 115, 32, 109, 117, 115, 46, 32, 73, 110, 32, 118, 101, 110, 101, 110, 97, 116, 105, 115, 32, 100, 97, 112, 105, 98, -117, 115, 32, 109, 97, 115, 115, 97, 46, 32, 78, 117, 108, 108, 97, 32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 32, 115, 97, 112, 105, 101, 110, -32, 101, 116, 32, 113, 117, 97, 109, 46, 32, 78, 117, 110, 99, 32, 97, 99, 32, 109, 97, 103, 110, 97, 32, 108, 111, 98, 111, 114, 116, 105, 115, -32, 116, 101, 108, 108, 117, 115, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 112, 111, 115, 117, 101, 114, 101, 46, 32, 67, 114, 97, 115, 32, -97, 117, 103, 117, 101, 32, 109, 97, 117, 114, 105, 115, 44, 32, 109, 97, 116, 116, 105, 115, 32, 108, 111, 98, 111, 114, 116, 105, 115, 44, 32, 102, -101, 114, 109, 101, 110, 116, 117, 109, 32, 97, 116, 44, 32, 115, 101, 109, 112, 101, 114, 32, 97, 99, 44, 32, 116, 101, 108, 108, 117, 115, 46, 32, -67, 114, 97, 115, 32, 118, 105, 116, 97, 101, 32, 108, 105, 103, 117, 108, 97, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 115, 101, 109, 32, 112, -111, 115, 117, 101, 114, 101, 32, 105, 97, 99, 117, 108, 105, 115, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 99, 111, 110, 100, 105, 109, 101, 110, -116, 117, 109, 32, 101, 108, 101, 105, 102, 101, 110, 100, 32, 102, 101, 108, 105, 115, 46, 32, 85, 116, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, -115, 97, 112, 105, 101, 110, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 112, 111, 116, 101, 110, 116, 105, 46, 32, 77, 97, 117, -114, 105, 115, 32, 117, 114, 110, 97, 46, 32, 85, 116, 32, 101, 117, 32, 101, 110, 105, 109, 32, 101, 117, 32, 97, 110, 116, 101, 32, 112, 111, 114, -116, 97, 32, 118, 101, 115, 116, 105, 98, 117, 108, 117, 109, 46, 32, 65, 101, 110, 101, 97, 110, 32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117, -101, 32, 101, 115, 116, 32, 97, 99, 32, 102, 101, 108, 105, 115, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 97, 117, 99, 116, -111, 114, 46, 32, 78, 117, 110, 99, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 46, 32, 77, 111, 114, 98, 105, 32, 108, 97, 111, -114, 101, 101, 116, 32, 97, 110, 116, 101, 32, 101, 116, 32, 110, 105, 98, 104, 46, 32, 68, 111, 110, 101, 99, 32, 102, 101, 117, 103, 105, 97, 116, -32, 97, 114, 99, 117, 32, 101, 103, 101, 116, 32, 101, 110, 105, 109, 46, 32, 77, 111, 114, 98, 105, 32, 118, 101, 104, 105, 99, 117, 108, 97, 32, -116, 111, 114, 116, 111, 114, 32, 97, 99, 32, 105, 112, 115, 117, 109, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 108, 97, 99, 117, 115, 32, 97, -114, 99, 117, 44, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 32, 97, 99, 44, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 118, 101, 108, 44, -32, 112, 111, 115, 117, 101, 114, 101, 32, 105, 100, 44, 32, 101, 115, 116, 46, 32, 80, 114, 111, 105, 110, 32, 99, 111, 109, 109, 111, 100, 111, 32, -103, 114, 97, 118, 105, 100, 97, 32, 115, 101, 109, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 118, -101, 104, 105, 99, 117, 108, 97, 32, 108, 105, 98, 101, 114, 111, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 119, 105, 115, 105, 46, 32, -77, 97, 101, 99, 101, 110, 97, 115, 32, 112, 114, 101, 116, 105, 117, 109, 32, 116, 101, 108, 108, 117, 115, 32, 101, 117, 32, 115, 97, 112, 105, 101, -110, 46, 32, 78, 117, 110, 99, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 110, 117, 110, 99, 46, 32, 73, 110, 32, 104, 97, 99, 32, 104, 97, -98, 105, 116, 97, 115, 115, 101, 32, 112, 108, 97, 116, 101, 97, 32, 100, 105, 99, 116, 117, 109, 115, 116, 46, 32, 65, 101, 110, 101, 97, 110, 32, -100, 105, 99, 116, 117, 109, 32, 110, 101, 113, 117, 101, 32, 115, 101, 100, 32, 116, 111, 114, 116, 111, 114, 46, 32, 68, 111, 110, 101, 99, 32, 101, -116, 32, 101, 114, 97, 116, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 97, 110, 116, 101, 32, 105, 112, 115, 117, 109, 32, 112, 114, -105, 109, 105, 115, 32, 105, 110, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 111, 114, 99, 105, 32, 108, 117, 99, 116, 117, 115, 32, 101, 116, 32, -117, 108, 116, 114, 105, 99, 101, 115, 32, 112, 111, 115, 117, 101, 114, 101, 32, 99, 117, 98, 105, 108, 105, 97, 32, 67, 117, 114, 97, 101, 59, 32, -83, 101, 100, 32, 106, 117, 115, 116, 111, 32, 116, 117, 114, 112, 105, 115, 44, 32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117, 101, 32, 117, 116, -44, 32, 109, 97, 116, 116, 105, 115, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 111, 114, 110, 97, 114, 101, 32, 114, 117, 116, 114, 117, 109, -44, 32, 109, 97, 115, 115, 97, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 101, 110, 105, -109, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 118, 101, 108, 105, 116, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 116, 101, 108, 108, 117, 115, -32, 105, 112, 115, 117, 109, 44, 32, 108, 117, 99, 116, 117, 115, 32, 117, 116, 44, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117, 101, 114, 32, -118, 105, 116, 97, 101, 44, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 110, 111, 110, 44, 32, 108, 105, 103, 117, 108, 97, 46, 32, 80, 104, -97, 115, 101, 108, 108, 117, 115, 32, 108, 97, 99, 105, 110, 105, 97, 32, 119, 105, 115, 105, 32, 97, 116, 32, 101, 115, 116, 46, 32, 68, 111, 110, -101, 99, 32, 101, 108, 105, 116, 32, 119, 105, 115, 105, 44, 32, 99, 111, 109, 109, 111, 100, 111, 32, 110, 111, 110, 44, 32, 112, 108, 97, 99, 101, -114, 97, 116, 32, 105, 110, 44, 32, 99, 111, 110, 118, 97, 108, 108, 105, 115, 32, 105, 100, 44, 32, 101, 108, 105, 116, 46, 32, 78, 117, 110, 99, -32, 100, 111, 108, 111, 114, 32, 100, 111, 108, 111, 114, 44, 32, 118, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 105, 100, 44, 32, 98, 105, 98, -101, 110, 100, 117, 109, 32, 118, 105, 116, 97, 101, 44, 32, 108, 97, 99, 105, 110, 105, 97, 32, 105, 100, 44, 32, 101, 114, 97, 116, 46, 32, 67, -114, 97, 115, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 101, 114, 111, 115, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 115, -117, 115, 99, 105, 112, 105, 116, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 108, 101, 99, 116, 117, 115, 46, 32, 67, 108, 97, 115, 115, 32, 97, -112, 116, 101, 110, 116, 32, 116, 97, 99, 105, 116, 105, 32, 115, 111, 99, 105, 111, 115, 113, 117, 32, 97, 100, 32, 108, 105, 116, 111, 114, 97, 32, -116, 111, 114, 113, 117, 101, 110, 116, 32, 112, 101, 114, 32, 99, 111, 110, 117, 98, 105, 97, 32, 110, 111, 115, 116, 114, 97, 44, 32, 112, 101, 114, -32, 105, 110, 99, 101, 112, 116, 111, 115, 32, 104, 121, 109, 101, 110, 97, 101, 111, 115, 46, 32, 67, 114, 97, 115, 32, 111, 114, 99, 105, 46, 32, -80, 114, 97, 101, 115, 101, 110, 116, 32, 109, 97, 115, 115, 97, 32, 117, 114, 110, 97, 44, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 115, 101, -109, 112, 101, 114, 44, 32, 97, 117, 99, 116, 111, 114, 32, 97, 44, 32, 112, 114, 101, 116, 105, 117, 109, 32, 118, 105, 116, 97, 101, 44, 32, 116, -101, 108, 108, 117, 115, 46, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 97, 116, 32, 112, 117, 114, 117, 115, 46, 32, 77, 111, 114, 98, 105, -32, 116, 111, 114, 116, 111, 114, 32, 113, 117, 97, 109, 44, 32, 105, 109, 112, 101, 114, 100, 105, 101, 116, 32, 118, 101, 110, 101, 110, 97, 116, 105, -115, 44, 32, 101, 103, 101, 115, 116, 97, 115, 32, 97, 44, 32, 99, 117, 114, 115, 117, 115, 32, 101, 117, 44, 32, 101, 115, 116, 46, 32, 78, 117, -110, 99, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 108, 101, 99, 116, 117, 115, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 108, 105, 98, 101, -114, 111, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 112, 108, 97, 99, 101, 114, 97, 116, 32, 108, -105, 103, 117, 108, 97, 46, 32, 78, 117, 110, 99, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 112, 111, 115, 117, 101, 114, 101, 32, 97, 114, -99, 117, 46, 32, 77, 97, 117, 114, 105, 115, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 113, 117, 97, 109, 32, 97, 116, 32, 109, 97, 115, 115, -97, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 115, 111, 100, 97, 108, 101, 115, 32, 97, 108, 105, 113, 117, 101, 116, 32, 109, 97, 117, 114, 105, -115, 46, 32, 73, 110, 32, 105, 100, 32, 97, 110, 116, 101, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 118, 97, 114, 105, -117, 115, 32, 105, 112, 115, 117, 109, 32, 105, 110, 32, 97, 114, 99, 117, 46, 32, 70, 117, 115, 99, 101, 32, 109, 97, 117, 114, 105, 115, 32, 108, -97, 99, 117, 115, 44, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 97, 99, 44, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 113, 117, 105, -115, 44, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 108, 117, 99, 116, 117, 115, 44, 32, 112, 101, 100, 101, 46, 32, 83, 101, 100, 32, 119, 105, -115, 105, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 109, 97, 116, 116, 105, 115, 46, 32, 77, 97, 101, 99, 101, 110, 97, 115, 32, -104, 101, 110, 100, 114, 101, 114, 105, 116, 32, 115, 101, 109, 32, 110, 101, 99, 32, 112, 117, 114, 117, 115, 46, 32, 80, 114, 111, 105, 110, 32, 105, -100, 32, 113, 117, 97, 109, 46, 32, 67, 114, 97, 115, 32, 110, 101, 99, 32, 109, 97, 117, 114, 105, 115, 46, 32, 73, 110, 116, 101, 103, 101, 114, -32, 111, 114, 99, 105, 46, 32, 78, 117, 108, 108, 97, 109, 32, 100, 117, 105, 32, 115, 101, 109, 44, 32, 109, 111, 108, 101, 115, 116, 105, 101, 32, -115, 101, 100, 44, 32, 101, 103, 101, 115, 116, 97, 115, 32, 113, 117, 105, 115, 44, 32, 99, 117, 114, 115, 117, 115, 32, 105, 110, 44, 32, 109, 97, -103, 110, 97, 46, 32, 77, 97, 117, 114, 105, 115, 32, 110, 101, 113, 117, 101, 32, 108, 97, 99, 117, 115, 44, 32, 99, 111, 110, 115, 101, 99, 116, -101, 116, 117, 101, 114, 32, 110, 101, 99, 44, 32, 115, 97, 103, 105, 116, 116, 105, 115, 32, 101, 117, 44, 32, 112, 111, 114, 116, 116, 105, 116, 111, -114, 32, 101, 103, 101, 116, 44, 32, 100, 117, 105, 46, 32, 70, 117, 115, 99, 101, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117, 101, 114, 46, -32, 68, 111, 110, 101, 99, 32, 110, 101, 99, 32, 116, 101, 108, 108, 117, 115, 32, 113, 117, 105, 115, 32, 108, 101, 111, 32, 108, 111, 98, 111, 114, -116, 105, 115, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 46, 32, 69, 116, 105, 97, 109, 32, 109, 101, 116, 117, 115, 32, 117, 114, 110, -97, 44, 32, 97, 108, 105, 113, 117, 101, 116, 32, 112, 114, 101, 116, 105, 117, 109, 44, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 101, 117, 44, -32, 99, 117, 114, 115, 117, 115, 32, 117, 116, 44, 32, 116, 117, 114, 112, 105, 115, 46, 32, 77, 111, 114, 98, 105, 32, 98, 105, 98, 101, 110, 100, -117, 109, 32, 118, 101, 104, 105, 99, 117, 108, 97, 32, 108, 101, 99, 116, 117, 115, 46, 32, 83, 101, 100, 32, 110, 111, 110, 32, 97, 110, 116, 101, -32, 118, 105, 116, 97, 101, 32, 97, 114, 99, 117, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 116, 101, 109, 112, 111, 114, 46, -32, 70, 117, 115, 99, 101, 32, 115, 101, 100, 32, 108, 105, 103, 117, 108, 97, 32, 105, 110, 32, 115, 101, 109, 32, 116, 101, 109, 112, 111, 114, 32, -105, 109, 112, 101, 114, 100, 105, 101, 116, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 118, 101, 108, 32, 101, 115, 116, 46, 32, 80, 104, 97, 115, -101, 108, 108, 117, 115, 32, 115, 111, 108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32, 115, 111, 108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32, -110, 105, 98, 104, 46, 32, 67, 108, 97, 115, 115, 32, 97, 112, 116, 101, 110, 116, 32, 116, 97, 99, 105, 116, 105, 32, 115, 111, 99, 105, 111, 115, -113, 117, 32, 97, 100, 32, 108, 105, 116, 111, 114, 97, 32, 116, 111, 114, 113, 117, 101, 110, 116, 32, 112, 101, 114, 32, 99, 111, 110, 117, 98, 105, -97, 32, 110, 111, 115, 116, 114, 97, 44, 32, 112, 101, 114, 32, 105, 110, 99, 101, 112, 116, 111, 115, 32, 104, 121, 109, 101, 110, 97, 101, 111, 115, -46, 32, 83, 101, 100, 32, 118, 101, 108, 32, 108, 101, 111, 32, 110, 101, 99, 32, 101, 114, 111, 115, 32, 98, 108, 97, 110, 100, 105, 116, 32, 105, -109, 112, 101, 114, 100, 105, 101, 116, 46, 32, 78, 117, 108, 108, 97, 32, 102, 97, 99, 105, 108, 105, 115, 105, 46, 32, 83, 117, 115, 112, 101, 110, -100, 105, 115, 115, 101, 32, 108, 111, 98, 111, 114, 116, 105, 115, 44, 32, 100, 117, 105, 32, 117, 116, 32, 102, 114, 105, 110, 103, 105, 108, 108, 97, -32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 44, 32, 106, 117, 115, 116, 111, 32, 112, 117, 114, 117, 115, 32, 117, 108, 108, 97, 109, 99, 111, 114, -112, 101, 114, 32, 108, 105, 103, 117, 108, 97, 44, 32, 117, 108, 116, 114, 105, 99, 105, 101, 115, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 100, -111, 108, 111, 114, 32, 101, 110, 105, 109, 32, 105, 110, 32, 108, 105, 98, 101, 114, 111, 46, 32, 83, 101, 100, 32, 101, 108, 101, 109, 101, 110, 116, -117, 109, 44, 32, 112, 101, 100, 101, 32, 101, 103, 101, 116, 32, 112, 111, 114, 116, 97, 32, 99, 111, 110, 118, 97, 108, 108, 105, 115, 44, 32, 100, -117, 105, 32, 110, 117, 108, 108, 97, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 112, 101, 100, 101, 44, 32, 101, 103, 101, 116, 32, 118, 101, -104, 105, 99, 117, 108, 97, 32, 111, 100, 105, 111, 32, 97, 110, 116, 101, 32, 97, 116, 32, 115, 101, 109, 46, 32, 80, 101, 108, 108, 101, 110, 116, -101, 115, 113, 117, 101, 32, 104, 97, 98, 105, 116, 97, 110, 116, 32, 109, 111, 114, 98, 105, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 115, -101, 110, 101, 99, 116, 117, 115, 32, 101, 116, 32, 110, 101, 116, 117, 115, 32, 101, 116, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 102, 97, -109, 101, 115, 32, 97, 99, 32, 116, 117, 114, 112, 105, 115, 32, 101, 103, 101, 115, 116, 97, 115, 46, 32, 83, 101, 100, 32, 117, 108, 108, 97, 109, -99, 111, 114, 112, 101, 114, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 105, 112, 115, 117, 109, 46, 32, 70, 117, 115, 99, 101, 32, 114, 105, -115, 117, 115, 32, 110, 105, 98, 104, 44, 32, 97, 99, 99, 117, 109, 115, 97, 110, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 116, 101, 109, -112, 117, 115, 32, 101, 103, 101, 116, 44, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 97, 99, 44, 32, 110, 101, 113, 117, 101, 46, 32, 83, -101, 100, 32, 113, 117, 105, 115, 32, 108, 111, 114, 101, 109, 32, 117, 116, 32, 116, 111, 114, 116, 111, 114, 32, 102, 97, 99, 105, 108, 105, 115, 105, -115, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109, 46, 32, 70, 117, 115, 99, 101, 32, 112, 117, 108, 118, 105, 110, 97, 114, 32, 113, 117, 97, 109, -32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 105, 112, 115, 117, 109, 46, 32, 77, 111, 114, 98, 105, 32, 97, 99, 32, 101, 108, 105, 116, 32, 113, -117, 105, 115, 32, 116, 101, 108, 108, 117, 115, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 98, 108, 97, 110, 100, 105, 116, 46, 32, 77, 97, -101, 99, 101, 110, 97, 115, 32, 115, 117, 115, 99, 105, 112, 105, 116, 32, 115, 111, 108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32, 115, 101, 109, -46, 32, 78, 97, 109, 32, 115, 101, 100, 32, 101, 114, 111, 115, 32, 118, 101, 108, 32, 108, 97, 99, 117, 115, 32, 108, 111, 98, 111, 114, 116, 105, -115, 32, 99, 111, 110, 103, 117, 101, 46, 32, 80, 114, 111, 105, 110, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 110, 117, 110, 99, 32, 108, 111, -98, 111, 114, 116, 105, 115, 32, 111, 114, 99, 105, 46, 32, 68, 111, 110, 101, 99, 32, 101, 103, 101, 115, 116, 97, 115, 32, 101, 110, 105, 109, 32, -101, 117, 32, 111, 100, 105, 111, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 105, 100, 32, 109, 101, 116, 117, 115, 46, 32, 80, 101, -108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 97, 117, 99, 116, 111, 114, 44, 32, 115, 101, 109, 32, 118, 97, 114, 105, 117, 115, 32, 108, 117, -99, 116, 117, 115, 32, 116, 101, 109, 112, 117, 115, 44, 32, 108, 105, 98, 101, 114, 111, 32, 109, 97, 103, 110, 97, 32, 99, 117, 114, 115, 117, 115, -32, 110, 101, 113, 117, 101, 44, 32, 101, 116, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 100, 105, 97, 109, 32, 100, 105, 97, 109, 32, 113, -117, 105, 115, 32, 112, 117, 114, 117, 115, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 100, -111, 108, 111, 114, 46, 32, 78, 117, 108, 108, 97, 32, 105, 110, 32, 109, 97, 103, 110, 97, 46, 32, 67, 114, 97, 115, 32, 105, 100, 32, 100, 105, -97, 109, 32, 97, 116, 32, 108, 101, 99, 116, 117, 115, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 112, 108, 97, 99, 101, 114, 97, 116, 46, 32, -78, 117, 110, 99, 32, 112, 111, 114, 116, 97, 32, 112, 111, 115, 117, 101, 114, 101, 32, 115, 97, 112, 105, 101, 110, 46, 32, 69, 116, 105, 97, 109, -32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117, 101, 46, 32, 67, 108, 97, 115, 115, 32, 97, 112, 116, 101, 110, 116, 32, 116, 97, 99, 105, 116, -105, 32, 115, 111, 99, 105, 111, 115, 113, 117, 32, 97, 100, 32, 108, 105, 116, 111, 114, 97, 32, 116, 111, 114, 113, 117, 101, 110, 116, 32, 112, 101, -114, 32, 99, 111, 110, 117, 98, 105, 97, 32, 110, 111, 115, 116, 114, 97, 44, 32, 112, 101, 114, 32, 105, 110, 99, 101, 112, 116, 111, 115, 32, 104, -121, 109, 101, 110, 97, 101, 111, 115, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 109, -105, 32, 115, 101, 100, 32, 116, 111, 114, 116, 111, 114, 46, 32, 77, 97, 101, 99, 101, 110, 97, 115, 32, 101, 108, 101, 105, 102, 101, 110, 100, 32, -100, 105, 97, 109, 32, 110, 111, 110, 32, 117, 114, 110, 97, 46, 32, 68, 111, 110, 101, 99, 32, 108, 117, 99, 116, 117, 115, 32, 112, 104, 97, 114, -101, 116, 114, 97, 32, 116, 101, 108, 108, 117, 115, 46, 32, 80, 114, 111, 105, 110, 32, 97, 99, 32, 105, 112, 115, 117, 109, 32, 101, 103, 101, 116, -32, 108, 105, 98, 101, 114, 111, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 118, 111, 108, 117, 116, 112, 97, 116, 46, 32, 67, 114, 97, 115, 32, -105, 100, 32, 116, 101, 108, 108, 117, 115, 46, 32, 78, 117, 108, 108, 97, 32, 110, 111, 110, 32, 114, 105, 115, 117, 115, 46, 32, 73, 110, 32, 100, -111, 108, 111, 114, 46, 32, 70, 117, 115, 99, 101, 32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117, 101, 32, 113, 117, 97, 109, 32, 105, 110, 32, -109, 97, 115, 115, 97, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 112, 111, 114, 116, 97, 46, 32, 77, 111, 114, 98, 105, 32, 117, 116, 32, 100, -111, 108, 111, 114, 32, 101, 117, 32, 109, 97, 115, 115, 97, 32, 101, 103, 101, 115, 116, 97, 115, 32, 99, 111, 110, 100, 105, 109, 101, 110, 116, 117, -109, 46, 32, 77, 97, 117, 114, 105, 115, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 46, 32, 73, 110, 32, 104, 97, 99, 32, 104, 97, 98, 105, -116, 97, 115, 115, 101, 32, 112, 108, 97, 116, 101, 97, 32, 100, 105, 99, 116, 117, 109, 115, 116, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, -115, 101, 32, 112, 111, 116, 101, 110, 116, 105, 46, 32, 77, 97, 117, 114, 105, 115, 32, 118, 101, 104, 105, 99, 117, 108, 97, 32, 108, 101, 111, 32, -105, 110, 32, 116, 111, 114, 116, 111, 114, 46, 32, 77, 97, 117, 114, 105, 115, 32, 118, 101, 108, 32, 101, 114, 97, 116, 32, 97, 32, 117, 114, 110, -97, 32, 108, 97, 111, 114, 101, 101, 116, 32, 115, 101, 109, 112, 101, 114, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 117, -116, 32, 109, 101, 116, 117, 115, 32, 97, 99, 32, 116, 101, 108, 108, 117, 115, 32, 99, 111, 109, 109, 111, 100, 111, 32, 101, 108, 101, 105, 102, 101, -110, 100, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 113, 117, 105, 115, 32, 117, 114, 110, 97, 46, 32, 67, 117, 114, 97, 98, -105, 116, 117, 114, 32, 108, 97, 99, 105, 110, 105, 97, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 100, 117, 105, 46, 32, 78, 97, 109, 32, -110, 101, 99, 32, 97, 110, 116, 101, 46, 32, 73, 110, 32, 105, 100, 32, 101, 110, 105, 109, 46, 32, 65, 101, 110, 101, 97, 110, 32, 109, 97, 116, -116, 105, 115, 32, 101, 110, 105, 109, 46, 32, 73, 110, 32, 117, 116, 32, 110, 101, 113, 117, 101, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, -114, 105, 115, 117, 115, 32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 46, 32, 83, 117, 115, 112, 101, -110, 100, 105, 115, 115, 101, 32, 112, 111, 116, 101, 110, 116, 105, 46, 32, 85, 116, 32, 118, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 108, 101, -99, 116, 117, 115, 32, 118, 105, 116, 97, 101, 32, 116, 111, 114, 116, 111, 114, 46, 32, 68, 117, 105, 115, 32, 118, 101, 108, 105, 116, 46, 32, 78, -117, 108, 108, 97, 32, 102, 97, 99, 105, 108, 105, 115, 105, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, -117, 114, 110, 97, 46, 32, 67, 114, 97, 115, 32, 118, 97, 114, 105, 117, 115, 32, 116, 111, 114, 116, 111, 114, 32, 105, 110, 32, 112, 101, 100, 101, -46, 32, 83, 101, 100, 32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 108, 97, 99, 105, 110, 105, -97, 32, 108, 105, 98, 101, 114, 111, 32, 110, 101, 99, 32, 110, 105, 98, 104, 46, 32, 68, 111, 110, 101, 99, 32, 97, 108, 105, 113, 117, 97, 109, -32, 114, 105, 115, 117, 115, 32, 110, 111, 110, 32, 110, 105, 115, 108, 46, 32, 78, 97, 109, 32, 97, 32, 110, 117, 110, 99, 32, 101, 116, 32, 102, -101, 108, 105, 115, 32, 116, 101, 109, 112, 111, 114, 32, 102, 101, 117, 103, 105, 97, 116, 46, 32, 78, 117, 110, 99, 32, 109, 101, 116, 117, 115, 46, -32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 101, 117, 105, 115, 109, 111, 100, 44, 32, 109, 101, 116, 117, 115, 32, 105, 110, 32, 115, 101, -109, 112, 101, 114, 32, 108, 97, 111, 114, 101, 101, 116, 44, 32, 117, 114, 110, 97, 32, 105, 112, 115, 117, 109, 32, 112, 104, 97, 114, 101, 116, 114, -97, 32, 108, 111, 114, 101, 109, 44, 32, 115, 101, 100, 32, 117, 108, 116, 114, 105, 99, 105, 101, 115, 32, 109, 97, 103, 110, 97, 32, 108, 111, 114, -101, 109, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 119, 105, 115, 105, 46, 32, 83, 101, 100, 32, 119, 105, 115, 105, 46, 32, 78, 117, 108, 108, -97, 109, 32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 32, 101, 108, 105, 116, 32, 115, 101, 100, 32, 110, 105, 115, 108, 46, 32, 80, 104, 97, 115, -101, 108, 108, 117, 115, 32, 109, 97, 116, 116, 105, 115, 32, 108, 101, 111, 32, 110, 101, 99, 32, 109, 97, 115, 115, 97, 46, 32, 65, 101, 110, 101, -97, 110, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 46, 32, 67, 114, 97, 115, 32, 119, 105, 115, 105, 32, 101, 114, 97, 116, 44, 32, 108, 111, -98, 111, 114, 116, 105, 115, 32, 110, 101, 99, 44, 32, 99, 117, 114, 115, 117, 115, 32, 101, 103, 101, 116, 44, 32, 108, 111, 98, 111, 114, 116, 105, -115, 32, 97, 116, 44, 32, 108, 105, 98, 101, 114, 111, 46, 32, 73, 110, 32, 109, 97, 115, 115, 97, 32, 110, 105, 115, 108, 44, 32, 114, 117, 116, -114, 117, 109, 32, 110, 111, 110, 44, 32, 99, 117, 114, 115, 117, 115, 32, 110, 101, 99, 44, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 115, 101, -100, 44, 32, 108, 97, 99, 117, 115, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, -46, 32, 67, 114, 97, 115, 32, 101, 117, 105, 115, 109, 111, 100, 44, 32, 110, 101, 113, 117, 101, 32, 97, 99, 32, 115, 117, 115, 99, 105, 112, 105, -116, 32, 116, 101, 109, 112, 117, 115, 44, 32, 118, 101, 108, 105, 116, 32, 108, 111, 114, 101, 109, 32, 108, 117, 99, 116, 117, 115, 32, 101, 108, 105, -116, 44, 32, 100, 97, 112, 105, 98, 117, 115, 32, 114, 104, 111, 110, 99, 117, 115, 32, 119, 105, 115, 105, 32, 101, 115, 116, 32, 117, 116, 32, 115, -101, 109, 46, 32, 80, 114, 111, 105, 110, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 101, 110, 105, 109, 32, 105, 110, 32, 101, 114, 111, 115, -32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 32, 97, 99, 99, 117, 109, 115, 97, 110, 46, 32, 85, 116, 32, 108, 111, 114, 101, 109, 32, 110, 105, -115, 108, 44, 32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 32, 101, 116, 44, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 110, 101, 99, 44, 32, -108, 97, 99, 105, 110, 105, 97, 32, 105, 110, 44, 32, 100, 111, 108, 111, 114, 46, 32, 68, 117, 105, 115, 32, 110, 101, 99, 32, 113, 117, 97, 109, -46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 118, 101, 108, 105, 116, 32, 102, 101, 108, 105, 115, 44, 32, 112, 111, 115, 117, 101, 114, 101, 32, -105, 100, 44, 32, 108, 117, 99, 116, 117, 115, 32, 113, 117, 105, 115, 44, 32, 108, 97, 111, 114, 101, 101, 116, 32, 117, 116, 44, 32, 105, 112, 115, -117, 109, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 101, 103, 101, 116, 32, 97, 114, 99, 117, 46, 32, 77, 97, 117, 114, 105, 115, 32, 109, -97, 115, 115, 97, 32, 102, 101, 108, 105, 115, 44, 32, 111, 114, 110, 97, 114, 101, 32, 110, 111, 110, 44, 32, 117, 108, 116, 114, 105, 99, 101, 115, -32, 105, 100, 44, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 105, 110, 44, 32, 101, 108, 105, 116, 46, 32, 80, 101, 108, 108, 101, 110, 116, -101, 115, 113, 117, 101, 32, 104, 97, 98, 105, 116, 97, 110, 116, 32, 109, 111, 114, 98, 105, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 115, -101, 110, 101, 99, 116, 117, 115, 32, 101, 116, 32, 110, 101, 116, 117, 115, 32, 101, 116, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 102, 97, -109, 101, 115, 32, 97, 99, 32, 116, 117, 114, 112, 105, 115, 32, 101, 103, 101, 115, 116, 97, 115, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, -32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 44, 32, 109, 105, 32, 97, 99, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 102, 97, 99, 105, 108, -105, 115, 105, 115, 44, 32, 108, 105, 98, 101, 114, 111, 32, 101, 110, 105, 109, 32, 115, 117, 115, 99, 105, 112, 105, 116, 32, 108, 101, 111, 44, 32, -110, 111, 110, 32, 110, 111, 110, 117, 109, 109, 121, 32, 112, 101, 100, 101, 32, 100, 105, 97, 109, 32, 101, 103, 101, 116, 32, 110, 105, 98, 104, 46, -32, 83, 101, 100, 32, 116, 101, 109, 112, 117, 115, 46, 32, 65, 101, 110, 101, 97, 110, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 115, 117, 115, -99, 105, 112, 105, 116, 32, 100, 117, 105, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 101, 114, 97, 116, 32, 118, 111, 108, 117, 116, 112, 97, 116, -46, 32, 85, 116, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 46, 32, 78, 97, 109, 32, 99, 111, 109, 109, 111, 100, 111, 44, 32, 110, 117, 108, -108, 97, 32, 117, 116, 32, 102, 114, 105, 110, 103, 105, 108, 108, 97, 32, 114, 117, 116, 114, 117, 109, 44, 32, 111, 114, 99, 105, 32, 101, 108, 105, -116, 32, 118, 105, 118, 101, 114, 114, 97, 32, 100, 105, 97, 109, 44, 32, 118, 105, 116, 97, 101, 32, 109, 111, 108, 108, 105, 115, 32, 111, 100, 105, -111, 32, 111, 100, 105, 111, 32, 101, 116, 32, 112, 117, 114, 117, 115, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 101, 114, 97, 116, 32, 118, 111, -108, 117, 116, 112, 97, 116, 46, 32, 83, 101, 100, 32, 97, 108, 105, 113, 117, 101, 116, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 105, 112, 115, -117, 109, 46, 32, 73, 110, 32, 117, 116, 32, 101, 115, 116, 46, 32, 69, 116, 105, 97, 109, 32, 99, 111, 110, 100, 105, 109, 101, 110, 116, 117, 109, -46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 116, 111, 114, 116, 111, 114, -32, 112, 117, 108, 118, 105, 110, 97, 114, 32, 108, 97, 99, 117, 115, 46, 32, 65, 101, 110, 101, 97, 110, 32, 111, 114, 99, 105, 46, 32, 83, 117, -115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 108, 97, 99, 117, 115, 32, 110, 117, 108, 108, 97, 44, 32, 110, 111, 110, 117, 109, 109, 121, 32, 97, -44, 32, 100, 105, 99, 116, 117, 109, 32, 118, 105, 116, 97, 101, 44, 32, 101, 103, 101, 115, 116, 97, 115, 32, 113, 117, 105, 115, 44, 32, 101, 114, -111, 115, 46, 32, 68, 111, 110, 101, 99, 32, 97, 117, 99, 116, 111, 114, 32, 103, 114, 97, 118, 105, 100, 97, 32, 110, 105, 115, 108, 46, 32, 67, -114, 97, 115, 32, 97, 99, 32, 101, 115, 116, 32, 114, 117, 116, 114, 117, 109, 32, 97, 117, 103, 117, 101, 32, 112, 117, 108, 118, 105, 110, 97, 114, -32, 111, 114, 110, 97, 114, 101, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 109, 97, 117, 114, 105, 115, 32, 110, 105, 98, 104, 44, 32, -118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 105, 110, 44, 32, 114, 104, 111, 110, 99, 117, 115, 32, 105, 109, 112, 101, 114, 100, 105, 101, 116, 44, -32, 100, 97, 112, 105, 98, 117, 115, 32, 101, 103, 101, 116, 44, 32, 108, 97, 99, 117, 115, 46, 32, 78, 97, 109, 32, 110, 117, 110, 99, 32, 109, -97, 117, 114, 105, 115, 44, 32, 115, 117, 115, 99, 105, 112, 105, 116, 32, 97, 116, 44, 32, 117, 108, 116, 114, 105, 99, 105, 101, 115, 32, 97, 44, -32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 32, 97, 116, 44, 32, 116, 101, 108, 108, 117, 115, 46, 32, 78, 97, 109, 32, 97, 99, 99, 117, 109, -115, 97, 110, 32, 109, 111, 108, 108, 105, 115, 32, 108, 105, 98, 101, 114, 111, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 99, 111, 110, 100, 105, -109, 101, 110, 116, 117, 109, 32, 109, 97, 116, 116, 105, 115, 32, 101, 115, 116, 46, 32, 68, 111, 110, 101, 99, 32, 108, 97, 99, 117, 115, 46, 32, -78, 117, 108, 108, 97, 109, 32, 97, 99, 32, 115, 97, 112, 105, 101, 110, 32, 105, 100, 32, 109, 97, 115, 115, 97, 32, 108, 111, 98, 111, 114, 116, -105, 115, 32, 109, 111, 108, 101, 115, 116, 105, 101, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 101, 108, 101, 109, 101, 110, -116, 117, 109, 46, 32, 80, 114, 111, 105, 110, 32, 117, 116, 32, 112, 117, 114, 117, 115, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 101, 116, 32, -115, 97, 112, 105, 101, 110, 32, 113, 117, 105, 115, 32, 116, 117, 114, 112, 105, 115, 32, 99, 111, 109, 109, 111, 100, 111, 32, 109, 111, 108, 108, 105, -115, 46, 32, 78, 117, 108, 108, 97, 32, 99, 111, 110, 115, 101, 113, 117, 97, 116, 46, 32, 80, 114, 111, 105, 110, 32, 97, 32, 119, 105, 115, 105, -32, 117, 116, 32, 116, 101, 108, 108, 117, 115, 32, 98, 108, 97, 110, 100, 105, 116, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 46, 32, 65, 108, -105, 113, 117, 97, 109, 32, 110, 117, 108, 108, 97, 32, 108, 111, 114, 101, 109, 44, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 97, 99, 44, 32, -109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 118, 101, 108, 44, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 32, 101, 116, 44, 32, 109, 101, 116, -117, 115, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 101, 103, 101, 115, 116, 97, 115, 32, 110, 105, 98, 104, 32, 101, 116, 32, 108, 105, -103, 117, 108, 97, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 100, 105, 97, 109, 32, 111, 100, 105, 111, 44, 32, 108, 97, 99, 105, 110, 105, 97, -32, 113, 117, 105, 115, 44, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 113, 117, 105, 115, 44, 32, 115, 111, 108, 108, 105, 99, 105, 116, 117, -100, 105, 110, 32, 117, 116, 44, 32, 101, 114, 111, 115, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 97, 108, 105, 113, 117, 101, 116, 32, -108, 111, 114, 101, 109, 32, 97, 99, 32, 105, 112, 115, 117, 109, 46, 32, 83, 101, 100, 32, 99, 117, 114, 115, 117, 115, 32, 116, 101, 108, 108, 117, -115, 32, 97, 99, 32, 111, 114, 99, 105, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 97, 116, 32, 110, 117, 108, 108, 97, 46, 32, 68, -111, 110, 101, 99, 32, 112, 111, 114, 116, 97, 32, 115, 111, 100, 97, 108, 101, 115, 32, 97, 110, 116, 101, 46, 32, 80, 101, 108, 108, 101, 110, 116, -101, 115, 113, 117, 101, 32, 104, 97, 98, 105, 116, 97, 110, 116, 32, 109, 111, 114, 98, 105, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 115, -101, 110, 101, 99, 116, 117, 115, 32, 101, 116, 32, 110, 101, 116, 117, 115, 32, 101, 116, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 102, 97, -109, 101, 115, 32, 97, 99, 32, 116, 117, 114, 112, 105, 115, 32, 101, 103, 101, 115, 116, 97, 115, 46, 32, 83, 101, 100, 32, 105, 100, 32, 108, 101, -99, 116, 117, 115, 32, 97, 116, 32, 109, 97, 115, 115, 97, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 32, 116, 114, 105, 115, 116, 105, -113, 117, 101, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 108, 97, 99, 117, 115, -46, 32, 73, 110, 32, 104, 97, 99, 32, 104, 97, 98, 105, 116, 97, 115, 115, 101, 32, 112, 108, 97, 116, 101, 97, 32, 100, 105, 99, 116, 117, 109, -115, 116, 46, 32, 78, 117, 110, 99, 32, 110, 111, 110, 32, 116, 117, 114, 112, 105, 115, 46, 32, 83, 101, 100, 32, 115, 97, 103, 105, 116, 116, 105, -115, 46, 32, 77, 111, 114, 98, 105, 32, 108, 97, 111, 114, 101, 101, 116, 32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117, 101, 32, 100, 117, 105, -46, 32, 78, 97, 109, 32, 97, 114, 99, 117, 32, 116, 101, 108, 108, 117, 115, 44, 32, 116, 101, 109, 112, 111, 114, 32, 118, 105, 116, 97, 101, 44, -32, 118, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 101, 116, 44, 32, 105, 109, 112, 101, 114, 100, 105, 101, 116, 32, 117, 116, 44, 32, 118, 101, -108, 105, 116, 46, 32, 73, 110, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 97, 117, 103, 117, 101, 32, 97, 32, 97, 114, 99, 117, 32, 118, 111, -108, 117, 116, 112, 97, 116, 32, 115, 117, 115, 99, 105, 112, 105, 116, 46, 32, 68, 111, 110, 101, 99, 32, 100, 105, 99, 116, 117, 109, 32, 117, 108, -116, 114, 105, 99, 101, 115, 32, 108, 101, 99, 116, 117, 115, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 97, 32, 112, 117, 114, 117, 115, -32, 101, 116, 32, 111, 114, 99, 105, 32, 100, 105, 99, 116, 117, 109, 32, 108, 97, 99, 105, 110, 105, 97, 46, 32, 85, 116, 32, 108, 101, 111, 46, -32, 67, 114, 97, 115, 32, 115, 101, 109, 112, 101, 114, 44, 32, 108, 111, 114, 101, 109, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 116, 105, 110, -99, 105, 100, 117, 110, 116, 32, 99, 111, 110, 103, 117, 101, 44, 32, 106, 117, 115, 116, 111, 32, 101, 114, 111, 115, 32, 118, 97, 114, 105, 117, 115, -32, 112, 101, 100, 101, 44, 32, 105, 110, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 116, 117, 114, 112, 105, 115, 32, 108, 101, 99, 116, 117, 115, -32, 110, 111, 110, 32, 101, 114, 111, 115, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 113, 117, 97, 109, 46, 32, 83, 117, 115, 112, 101, -110, 100, 105, 115, 115, 101, 32, 109, 97, 116, 116, 105, 115, 32, 115, 111, 108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32, 109, 97, 103, 110, 97, -46, 32, 65, 101, 110, 101, 97, 110, 32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 32, 100, 105, 97, 109, 32, 118, 101, 108, 32, 110, 105, 115, 108, -32, 110, 111, 110, 117, 109, 109, 121, 32, 99, 111, 110, 100, 105, 109, 101, 110, 116, 117, 109, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, -101, 32, 118, 101, 108, 32, 100, 111, 108, 111, 114, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 110, 111, 110, 117, 109, 109, 121, 46, -32, 77, 97, 117, 114, 105, 115, 32, 105, 109, 112, 101, 114, 100, 105, 101, 116, 32, 115, 101, 109, 112, 101, 114, 32, 97, 110, 116, 101, 46, 32, 77, -97, 101, 99, 101, 110, 97, 115, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 101, 114, 111, 115, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, -117, 109, 32, 97, 99, 32, 100, 111, 108, 111, 114, 46, 32, 70, 117, 115, 99, 101, 32, 114, 105, 115, 117, 115, 32, 109, 101, 116, 117, 115, 44, 32, -97, 108, 105, 113, 117, 101, 116, 32, 101, 103, 101, 116, 44, 32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 32, 101, 116, 44, 32, 102, 101, 117, 103, -105, 97, 116, 32, 118, 101, 108, 44, 32, 111, 114, 99, 105, 46, 32, 85, 116, 32, 97, 116, 32, 110, 117, 110, 99, 32, 105, 100, 32, 97, 110, 116, -101, 32, 115, 111, 100, 97, 108, 101, 115, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 46, 32, 68, 117, 105, 115, 32, 116, 114, 105, 115, 116, 105, -113, 117, 101, 32, 109, 97, 116, 116, 105, 115, 32, 97, 110, 116, 101, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 110, 101, 113, 117, -101, 32, 109, 97, 117, 114, 105, 115, 44, 32, 108, 97, 111, 114, 101, 101, 116, 32, 105, 100, 44, 32, 99, 111, 110, 103, 117, 101, 32, 105, 110, 116, -101, 114, 100, 117, 109, 44, 32, 97, 108, 105, 113, 117, 101, 116, 32, 117, 116, 44, 32, 100, 105, 97, 109, 46, 32, 78, 117, 108, 108, 97, 32, 118, -111, 108, 117, 116, 112, 97, 116, 32, 98, 108, 97, 110, 100, 105, 116, 32, 109, 97, 103, 110, 97, 46, 32, 68, 111, 110, 101, 99, 32, 97, 99, 99, -117, 109, 115, 97, 110, 32, 99, 111, 110, 103, 117, 101, 32, 100, 105, 97, 109, 46, 32, 69, 116, 105, 97, 109, 32, 118, 101, 108, 32, 100, 117, 105, -32, 101, 103, 101, 116, 32, 110, 105, 115, 108, 32, 116, 101, 109, 112, 111, 114, 32, 118, 97, 114, 105, 117, 115, 46, 32, 67, 114, 97, 115, 32, 100, -105, 99, 116, 117, 109, 32, 109, 97, 115, 115, 97, 32, 115, 101, 100, 32, 101, 110, 105, 109, 46, 32, 67, 114, 97, 115, 32, 117, 114, 110, 97, 32, -116, 111, 114, 116, 111, 114, 44, 32, 102, 114, 105, 110, 103, 105, 108, 108, 97, 32, 97, 99, 44, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101, -114, 32, 105, 110, 44, 32, 101, 117, 105, 115, 109, 111, 100, 32, 118, 101, 108, 44, 32, 97, 114, 99, 117, 46, 32, 77, 111, 114, 98, 105, 32, 112, -111, 115, 117, 101, 114, 101, 32, 108, 117, 99, 116, 117, 115, 32, 97, 117, 103, 117, 101, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 100, 117, 105, -32, 100, 117, 105, 44, 32, 97, 100, 105, 112, 105, 115, 99, 105, 110, 103, 32, 105, 110, 44, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 101, 117, -44, 32, 108, 117, 99, 116, 117, 115, 32, 101, 117, 44, 32, 110, 117, 108, 108, 97, 46, 32, 67, 114, 97, 115, 32, 118, 101, 108, 105, 116, 32, 112, -101, 100, 101, 44, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 102, 101, 117, 103, 105, -97, 116, 32, 105, 110, 44, 32, 97, 117, 99, 116, 111, 114, 32, 118, 105, 116, 97, 101, 44, 32, 97, 110, 116, 101, 46, 32, 83, 117, 115, 112, 101, -110, 100, 105, 115, 115, 101, 32, 100, 105, 99, 116, 117, 109, 32, 102, 114, 105, 110, 103, 105, 108, 108, 97, 32, 109, 97, 117, 114, 105, 115, 46, 32, -73, 110, 32, 97, 32, 110, 105, 98, 104, 46, 32, 68, 111, 110, 101, 99, 32, 97, 99, 32, 108, 105, 103, 117, 108, 97, 46, 32, 73, 110, 32, 113, -117, 97, 109, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 118, 105, 116, 97, 101, 32, 117, 114, 110, 97, 32, 117, 108, 116, 114, 105, 99, 105, -101, 115, 32, 115, 101, 109, 32, 97, 108, 105, 113, 117, 97, 109, 32, 112, 108, 97, 99, 101, 114, 97, 116, 46, 32, 65, 108, 105, 113, 117, 97, 109, -32, 101, 114, 97, 116, 32, 118, 111, 108, 117, 116, 112, 97, 116, 46, 32, 78, 97, 109, 32, 101, 115, 116, 46, 32, 68, 111, 110, 101, 99, 32, 102, -97, 117, 99, 105, 98, 117, 115, 32, 115, 111, 100, 97, 108, 101, 115, 32, 109, 101, 116, 117, 115, 46, 32, 85, 116, 32, 99, 111, 110, 103, 117, 101, -46, 32, 68, 111, 110, 101, 99, 32, 97, 114, 99, 117, 32, 116, 101, 108, 108, 117, 115, 44, 32, 112, 104, 97, 114, 101, 116, 114, 97, 32, 97, 99, -44, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 97, 99, 44, 32, 109, 111, 108, 108, 105, 115, 32, 115, 101, 100, 44, 32, 108, 101, 99, 116, -117, 115, 46, 32, 78, 117, 108, 108, 97, 32, 102, 97, 99, 105, 108, 105, 115, 105, 46, 32, 78, 117, 108, 108, 97, 109, 32, 118, 111, 108, 117, 116, -112, 97, 116, 32, 110, 117, 110, 99, 32, 101, 116, 32, 102, 101, 108, 105, 115, 46, 32, 83, 101, 100, 32, 112, 101, 100, 101, 32, 111, 100, 105, 111, -44, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 105, 110, 44, 32, 118, 111, 108, 117, 116, 112, 97, 116, 32, 109, 97, 108, 101, 115, 117, 97, -100, 97, 44, 32, 102, 101, 117, 103, 105, 97, 116, 32, 103, 114, 97, 118, 105, 100, 97, 44, 32, 110, 117, 108, 108, 97, 46, 32, 78, 117, 108, 108, -97, 32, 97, 108, 105, 113, 117, 97, 109, 32, 112, 101, 100, 101, 32, 118, 105, 116, 97, 101, 32, 97, 114, 99, 117, 46, 32, 80, 114, 111, 105, 110, -32, 118, 101, 108, 105, 116, 32, 101, 108, 105, 116, 44, 32, 110, 111, 110, 117, 109, 109, 121, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 101, -108, 101, 109, 101, 110, 116, 117, 109, 32, 118, 105, 116, 97, 101, 44, 32, 118, 97, 114, 105, 117, 115, 32, 118, 105, 116, 97, 101, 44, 32, 100, 111, -108, 111, 114, 46, 32, 68, 111, 110, 101, 99, 32, 114, 117, 116, 114, 117, 109, 32, 105, 112, 115, 117, 109, 32, 101, 117, 32, 109, 105, 46, 32, 65, -108, 105, 113, 117, 97, 109, 32, 101, 116, 32, 115, 101, 109, 46, 32, 73, 110, 32, 97, 100, 105, 112, 105, 115, 99, 105, 110, 103, 32, 114, 104, 111, -110, 99, 117, 115, 32, 118, 101, 108, 105, 116, 46, 32, 78, 97, 109, 32, 118, 105, 118, 101, 114, 114, 97, 32, 115, 99, 101, 108, 101, 114, 105, 115, -113, 117, 101, 32, 97, 114, 99, 117, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 115, 101, 109, 46, 32, 83, 101, 100, 32, 116, 105, 110, 99, 105, -100, 117, 110, 116, 32, 110, 117, 108, 108, 97, 32, 113, 117, 105, 115, 32, 109, 97, 115, 115, 97, 46, 32, 77, 97, 117, 114, 105, 115, 32, 102, 97, -117, 99, 105, 98, 117, 115, 32, 116, 101, 109, 112, 117, 115, 32, 110, 117, 110, 99, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 99, 111, -110, 100, 105, 109, 101, 110, 116, 117, 109, 46, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 97, 108, 105, 113, 117, 101, 116, 32, 105, 97, 99, -117, 108, 105, 115, 32, 115, 97, 112, 105, 101, 110, 46, 32, 78, 117, 110, 99, 32, 114, 104, 111, 110, 99, 117, 115, 44, 32, 111, 100, 105, 111, 32, -118, 105, 116, 97, 101, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 44, 32, 116, 101, 108, 108, 117, 115, -32, 108, 105, 98, 101, 114, 111, 32, 99, 111, 109, 109, 111, 100, 111, 32, 105, 112, 115, 117, 109, 44, 32, 117, 116, 32, 115, 111, 108, 108, 105, 99, -105, 116, 117, 100, 105, 110, 32, 110, 105, 115, 108, 32, 110, 105, 115, 108, 32, 118, 101, 108, 32, 106, 117, 115, 116, 111, 46, 32, 78, 117, 108, 108, -97, 32, 102, 97, 99, 105, 108, 105, 115, 105, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 98, 108, 97, 110, 100, 105, 116, 32, 101, 110, 105, -109, 32, 117, 116, 32, 106, 117, 115, 116, 111, 46, 32, 80, 114, 111, 105, 110, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 44, 32, 101, 108, 105, -116, 32, 101, 103, 101, 116, 32, 97, 99, 99, 117, 109, 115, 97, 110, 32, 112, 117, 108, 118, 105, 110, 97, 114, 44, 32, 111, 114, 99, 105, 32, 113, -117, 97, 109, 32, 97, 117, 99, 116, 111, 114, 32, 110, 101, 113, 117, 101, 44, 32, 115, 101, 100, 32, 99, 111, 110, 118, 97, 108, 108, 105, 115, 32, -100, 105, 97, 109, 32, 112, 117, 114, 117, 115, 32, 118, 101, 108, 32, 102, 101, 108, 105, 115, 46, 32, 83, 101, 100, 32, 111, 114, 99, 105, 32, 108, -101, 111, 44, 32, 101, 108, 101, 105, 102, 101, 110, 100, 32, 118, 101, 108, 44, 32, 98, 108, 97, 110, 100, 105, 116, 32, 110, 111, 110, 44, 32, 115, -101, 109, 112, 101, 114, 32, 101, 117, 44, 32, 112, 117, 114, 117, 115, 46, 32, 80, 114, 111, 105, 110, 32, 98, 105, 98, 101, 110, 100, 117, 109, 44, -32, 108, 105, 98, 101, 114, 111, 32, 97, 99, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117, 101, 114, 32, 99, 111, 109, 109, 111, 100, 111, 44, -32, 101, 114, 111, 115, 32, 115, 97, 112, 105, 101, 110, 32, 98, 108, 97, 110, 100, 105, 116, 32, 110, 105, 115, 108, 44, 32, 101, 117, 32, 101, 108, -101, 105, 102, 101, 110, 100, 32, 110, 105, 98, 104, 32, 110, 105, 98, 104, 32, 118, 101, 108, 32, 108, 101, 99, 116, 117, 115, 46, 32, 86, 105, 118, -97, 109, 117, 115, 32, 112, 108, 97, 99, 101, 114, 97, 116, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 111, 100, 105, 111, 32, 100, 111, 108, 111, -114, 44, 32, 112, 104, 97, 114, 101, 116, 114, 97, 32, 110, 111, 110, 44, 32, 115, 111, 100, 97, 108, 101, 115, 32, 105, 100, 44, 32, 118, 105, 118, -101, 114, 114, 97, 32, 101, 103, 101, 116, 44, 32, 100, 105, 97, 109, 46, 32, 78, 117, 110, 99, 32, 109, 97, 117, 114, 105, 115, 32, 109, 97, 103, -110, 97, 44, 32, 101, 103, 101, 115, 116, 97, 115, 32, 113, 117, 105, 115, 44, 32, 102, 101, 117, 103, 105, 97, 116, 32, 105, 100, 44, 32, 102, 101, -114, 109, 101, 110, 116, 117, 109, 32, 118, 105, 118, 101, 114, 114, 97, 44, 32, 109, 105, 46, 32, 65, 101, 110, 101, 97, 110, 32, 115, 117, 115, 99, -105, 112, 105, 116, 32, 110, 105, 115, 108, 32, 110, 111, 110, 32, 110, 117, 110, 99, 46, 32, 80, 114, 111, 105, 110, 32, 113, 117, 105, 115, 32, 108, -101, 99, 116, 117, 115, 32, 97, 99, 32, 116, 101, 108, 108, 117, 115, 32, 110, 111, 110, 117, 109, 109, 121, 32, 99, 111, 109, 109, 111, 100, 111, 46, -32, 78, 117, 110, 99, 32, 101, 103, 101, 116, 32, 100, 105, 97, 109, 32, 97, 99, 32, 101, 108, 105, 116, 32, 118, 101, 115, 116, 105, 98, 117, 108, -117, 109, 32, 97, 117, 99, 116, 111, 114, 46, 32, 69, 116, 105, 97, 109, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 44, 32, 111, 100, 105, 111, -32, 115, 101, 100, 32, 108, 97, 99, 105, 110, 105, 97, 32, 99, 111, 110, 115, 101, 113, 117, 97, 116, 44, 32, 106, 117, 115, 116, 111, 32, 109, 105, -32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 112, 117, 114, 117, 115, 44, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 101, 117, 105, 115, 109, -111, 100, 32, 108, 105, 98, 101, 114, 111, 32, 109, 101, 116, 117, 115, 32, 115, 101, 100, 32, 116, 111, 114, 116, 111, 114, 46, 32, 77, 97, 101, 99, -101, 110, 97, 115, 32, 97, 99, 32, 101, 108, 105, 116, 32, 115, 101, 100, 32, 108, 111, 114, 101, 109, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, -32, 103, 114, 97, 118, 105, 100, 97, 46, 32, 80, 114, 111, 105, 110, 32, 108, 101, 99, 116, 117, 115, 32, 101, 114, 111, 115, 44, 32, 117, 108, 108, -97, 109, 99, 111, 114, 112, 101, 114, 32, 105, 100, 44, 32, 118, 111, 108, 117, 116, 112, 97, 116, 32, 113, 117, 105, 115, 44, 32, 99, 111, 110, 100, -105, 109, 101, 110, 116, 117, 109, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 44, 32, 115, 97, 112, 105, 101, 110, 46, 32, 83, 101, 100, 32, 101, -116, 32, 109, 97, 115, 115, 97, 32, 101, 103, 101, 116, 32, 108, 111, 114, 101, 109, 32, 97, 108, 105, 113, 117, 101, 116, 32, 116, 101, 109, 112, 117, -115, 46, 32, 68, 117, 105, 115, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 110, 105, 115, 108, 32, 110, 111, 110, 32, 114, 105, 115, 117, 115, -46, 32, 78, 97, 109, 32, 105, 100, 32, 113, 117, 97, 109, 46, 32, 78, 117, 108, 108, 97, 109, 32, 101, 115, 116, 46, 32, 80, 114, 111, 105, 110, -32, 111, 114, 99, 105, 32, 100, 105, 97, 109, 44, 32, 112, 111, 115, 117, 101, 114, 101, 32, 101, 116, 44, 32, 112, 104, 97, 114, 101, 116, 114, 97, -32, 99, 111, 109, 109, 111, 100, 111, 44, 32, 100, 105, 99, 116, 117, 109, 32, 118, 101, 108, 44, 32, 101, 110, 105, 109, 46, 32, 80, 114, 111, 105, -110, 32, 101, 103, 101, 116, 32, 101, 114, 97, 116, 46, 32, 68, 111, 110, 101, 99, 32, 110, 105, 115, 108, 46, 32, 77, 97, 101, 99, 101, 110, 97, -115, 32, 97, 117, 99, 116, 111, 114, 32, 118, 101, 108, 105, 116, 32, 117, 116, 32, 112, 101, 100, 101, 46, 32, 78, 117, 110, 99, 32, 118, 105, 116, -97, 101, 32, 108, 101, 99, 116, 117, 115, 32, 110, 101, 99, 32, 108, 105, 98, 101, 114, 111, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 104, -101, 110, 100, 114, 101, 114, 105, 116, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 118, 97, 114, 105, 117, 115, 44, 32, 101, 114, 97, 116, 32, 117, -108, 116, 114, 105, 99, 101, 115, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 101, 117, 105, 115, 109, 111, 100, 44, 32, 112, 117, 114, 117, 115, 32, -108, 97, 99, 117, 115, 32, 100, 105, 99, 116, 117, 109, 32, 101, 114, 111, 115, 44, 32, 97, 116, 32, 99, 111, 110, 100, 105, 109, 101, 110, 116, 117, -109, 32, 101, 110, 105, 109, 32, 100, 117, 105, 32, 110, 101, 99, 32, 109, 97, 103, 110, 97, 46, 32, 77, 111, 114, 98, 105, 32, 100, 105, 97, 109, -46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 115, 101, 100, 32, 101, 115, 116, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 110, -101, 99, 32, 108, 105, 98, 101, 114, 111, 32, 105, 110, 32, 97, 114, 99, 117, 32, 102, 114, 105, 110, 103, 105, 108, 108, 97, 32, 115, 111, 108, 108, -105, 99, 105, 116, 117, 100, 105, 110, 46, 32, 73, 110, 32, 114, 117, 116, 114, 117, 109, 32, 110, 105, 115, 108, 32, 97, 116, 32, 97, 114, 99, 117, -46, 32, 78, 117, 108, 108, 97, 32, 102, 97, 99, 105, 108, 105, 115, 105, 46, 32, 77, 97, 117, 114, 105, 115, 32, 100, 105, 103, 110, 105, 115, 115, -105, 109, 46, 32, 69, 116, 105, 97, 109, 32, 101, 115, 116, 32, 109, 97, 117, 114, 105, 115, 44, 32, 112, 104, 97, 114, 101, 116, 114, 97, 32, 115, -101, 100, 44, 32, 118, 105, 118, 101, 114, 114, 97, 32, 101, 116, 44, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 115, 101, 100, 44, 32, 110, -101, 113, 117, 101, 46, 32, 85, 116, 32, 97, 116, 32, 108, 101, 99, 116, 117, 115, 32, 105, 100, 32, 110, 105, 98, 104, 32, 108, 117, 99, 116, 117, -115, 32, 111, 114, 110, 97, 114, 101, 46, 32, 77, 97, 117, 114, 105, 115, 32, 118, 97, 114, 105, 117, 115, 32, 112, 111, 114, 116, 116, 105, 116, 111, -114, 32, 114, 105, 115, 117, 115, 46, 32, 85, 116, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 97, 108, 105, 113, 117, 101, 116, 32, 114, 105, -115, 117, 115, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 108, 117, 99, 116, 117, 115, 32, 110, 101, 113, 117, 101, 32, 115, 105, 116, -32, 97, 109, 101, 116, 32, 110, 117, 110, 99, 46, 32, 68, 117, 105, 115, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109, 32, 110, 105, 98, 104, 46, -32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 100, 97, 112, 105, 98, 117, 115, 46, 32, 80, 114, 111, 105, 110, 32, 101, 114, 111, -115, 32, 108, 105, 98, 101, 114, 111, 44, 32, 97, 108, 105, 113, 117, 97, 109, 32, 110, 111, 110, 44, 32, 99, 111, 110, 100, 105, 109, 101, 110, 116, -117, 109, 32, 97, 44, 32, 115, 111, 100, 97, 108, 101, 115, 32, 117, 116, 44, 32, 116, 117, 114, 112, 105, 115, 46, 32, 73, 110, 116, 101, 103, 101, -114, 32, 97, 99, 99, 117, 109, 115, 97, 110, 32, 109, 105, 32, 115, 101, 100, 32, 108, 111, 114, 101, 109, 46, 32, 86, 101, 115, 116, 105, 98, 117, -108, 117, 109, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 115, 111, 100, 97, 108, 101, 115, 32, 110, 105, 115, 108, 46, 32, 78, -117, 108, 108, 97, 32, 101, 117, 32, 106, 117, 115, 116, 111, 32, 113, 117, 105, 115, 32, 100, 117, 105, 32, 112, 114, 101, 116, 105, 117, 109, 32, 114, -104, 111, 110, 99, 117, 115, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 118, 105, 118, 101, 114, 114, 97, 32, 99, 111, 109, 109, 111, 100, 111, -32, 109, 105, 46, 32, 77, 97, 101, 99, 101, 110, 97, 115, 32, 100, 111, 108, 111, 114, 32, 108, 105, 98, 101, 114, 111, 44, 32, 118, 105, 118, 101, -114, 114, 97, 32, 97, 44, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 32, 118, 105, 116, 97, 101, 44, 32, 97, 108, 105, 113, 117, 101, 116, 32, -118, 105, 116, 97, 101, 44, 32, 100, 117, 105, 46, 32, 77, 97, 117, 114, 105, 115, 32, 99, 111, 110, 118, 97, 108, 108, 105, 115, 32, 108, 101, 99, -116, 117, 115, 32, 101, 116, 32, 109, 105, 46, 32, 77, 97, 117, 114, 105, 115, 32, 115, 97, 103, 105, 116, 116, 105, 115, 46, 32, 83, 101, 100, 32, -97, 114, 99, 117, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 97, 117, 99, 116, 111, 114, 46, 32, 68, 111, 110, 101, 99, -32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 112, 117, 114, 117, 115, 32, 110, 111, 110, 32, 116, 101, 108, 108, 117, 115, 46, 32, -85, 116, 32, 108, 101, 111, 32, 119, 105, 115, 105, 44, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, -117, 108, 116, 114, 105, 99, 101, 115, 32, 101, 117, 44, 32, 103, 114, 97, 118, 105, 100, 97, 32, 97, 99, 44, 32, 108, 105, 98, 101, 114, 111, 46, -32, 77, 97, 117, 114, 105, 115, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109, 32, 100, 97, 112, 105, 98, 117, 115, 32, 100, 105, 97, 109, 46, 32, -73, 110, 116, 101, 103, 101, 114, 32, 113, 117, 105, 115, 32, 108, 97, 99, 117, 115, 32, 100, 97, 112, 105, 98, 117, 115, 32, 111, 100, 105, 111, 32, -112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 118, 97, 114, 105, 117, 115, 46, 32, 70, 117, 115, 99, 101, 32, 112, 101, 100, 101, 32, -113, 117, 97, 109, 44, 32, 118, 101, 104, 105, 99, 117, 108, 97, 32, 117, 116, 44, 32, 112, 117, 108, 118, 105, 110, 97, 114, 32, 101, 116, 44, 32, -116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 115, 101, 100, 44, 32, 102, 101, 108, 105, 115, 46, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32, -101, 114, 111, 115, 32, 101, 110, 105, 109, 44, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 115, 101, 100, 44, 32, 97, 108, 105, 113, 117, 97, -109, 32, 97, 99, 44, 32, 101, 117, 105, 115, 109, 111, 100, 32, 97, 99, 44, 32, 101, 114, 97, 116, 46, 32, 85, 116, 32, 100, 105, 103, 110, 105, -115, 115, 105, 109, 44, 32, 108, 97, 99, 117, 115, 32, 97, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 105, 97, 99, 117, 108, 105, 115, 44, 32, -101, 110, 105, 109, 32, 111, 114, 99, 105, 32, 112, 111, 115, 117, 101, 114, 101, 32, 110, 117, 110, 99, 44, 32, 110, 101, 99, 32, 117, 108, 116, 114, -105, 99, 105, 101, 115, 32, 108, 101, 99, 116, 117, 115, 32, 114, 105, 115, 117, 115, 32, 105, 110, 32, 111, 100, 105, 111, 46, 32, 69, 116, 105, 97, -109, 32, 101, 116, 32, 109, 97, 115, 115, 97, 32, 105, 100, 32, 100, 117, 105, 32, 99, 111, 109, 109, 111, 100, 111, 32, 118, 101, 104, 105, 99, 117, -108, 97, 46, 32, 78, 117, 110, 99, 32, 98, 108, 97, 110, 100, 105, 116, 32, 116, 111, 114, 116, 111, 114, 32, 113, 117, 105, 115, 32, 100, 117, 105, -46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 110, 105, 115, 108, 46, 32, 83, 101, 100, 32, 118, 101, 110, 101, 110, 97, 116, 105, 115, 32, 98, 108, -97, 110, 100, 105, 116, 32, 108, 105, 103, 117, 108, 97, 46, 32, 70, 117, 115, 99, 101, 32, 118, 105, 118, 101, 114, 114, 97, 32, 105, 109, 112, 101, -114, 100, 105, 101, 116, 32, 109, 97, 103, 110, 97, 46, 32, 68, 111, 110, 101, 99, 32, 101, 103, 101, 116, 32, 110, 117, 110, 99, 32, 113, 117, 105, -115, 32, 101, 115, 116, 32, 112, 104, 97, 114, 101, 116, 114, 97, 32, 108, 111, 98, 111, 114, 116, 105, 115, 46, 32, 86, 101, 115, 116, 105, 98, 117, -108, 117, 109, 32, 113, 117, 105, 115, 32, 108, 101, 99, 116, 117, 115, 46, 32, 77, 97, 117, 114, 105, 115, 32, 118, 101, 108, 32, 111, 114, 99, 105, -32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 110, 117, 110, 99, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109, 32, 98, 105, 98, 101, 110, 100, 117, -109, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 101, 103, 101, 116, 32, 108, 101, 111, 46, 32, 77, 111, 114, 98, 105, 32, -118, 101, 108, 32, 117, 114, 110, 97, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 101, 114, 97, 116, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109, -32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 46, 32, 83, 101, 100, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 44, 32, 108, 105, 98, 101, 114, -111, 32, 101, 116, 32, 115, 111, 108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32, 99, 111, 110, 103, 117, 101, 44, 32, 119, 105, 115, 105, 32, 108, -101, 99, 116, 117, 115, 32, 115, 111, 100, 97, 108, 101, 115, 32, 100, 111, 108, 111, 114, 44, 32, 101, 103, 101, 116, 32, 109, 111, 108, 101, 115, 116, -105, 101, 32, 109, 97, 103, 110, 97, 32, 111, 114, 99, 105, 32, 118, 101, 108, 32, 116, 101, 108, 108, 117, 115, 46, 32, 83, 101, 100, 32, 116, 101, -109, 112, 111, 114, 32, 97, 110, 116, 101, 32, 101, 116, 32, 101, 110, 105, 109, 46, 32, 77, 97, 117, 114, 105, 115, 32, 101, 108, 105, 116, 46, 32, -67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 32, 118, 101, 104, 105, 99, 117, 108, 97, 32, 109, -97, 115, 115, 97, 46, 32, 83, 101, 100, 32, 118, 105, 118, 101, 114, 114, 97, 46, 32, 68, 117, 105, 115, 32, 110, 117, 108, 108, 97, 46, 32, 78, -97, 109, 32, 98, 105, 98, 101, 110, 100, 117, 109, 46, 32, 78, 97, 109, 32, 116, 111, 114, 116, 111, 114, 32, 108, 111, 114, 101, 109, 44, 32, 117, -108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 32, 118, 105, 116, 97, 101, 44, 32, 100, 105, 99, 116, 117, 109, 32, 115, 101, 100, 44, 32, 112, 111, -115, 117, 101, 114, 101, 32, 101, 117, 44, 32, 106, 117, 115, 116, 111, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 97, 100, 105, 112, 105, 115, 99, -105, 110, 103, 32, 97, 114, 99, 117, 32, 118, 105, 116, 97, 101, 32, 116, 117, 114, 112, 105, 115, 46, 32, 68, 111, 110, 101, 99, 32, 109, 97, 108, -101, 115, 117, 97, 100, 97, 32, 112, 111, 115, 117, 101, 114, 101, 32, 108, 105, 98, 101, 114, 111, 46, 32, 85, 116, 32, 115, 101, 100, 32, 116, 101, -108, 108, 117, 115, 46, 32, 70, 117, 115, 99, 101, 32, 115, 101, 100, 32, 110, 117, 110, 99, 32, 101, 103, 101, 116, 32, 110, 105, 115, 108, 32, 100, -97, 112, 105, 98, 117, 115, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 112, 111, -116, 101, 110, 116, 105, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 108, 105, 98, 101, 114, 111, 32, -101, 116, 32, 109, 101, 116, 117, 115, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 112, 111, 115, 117, 101, 114, 101, 46, 32, 77, 97, 101, 99, 101, -110, 97, 115, 32, 110, 111, 110, 32, 115, 101, 109, 32, 110, 111, 110, 32, 113, 117, 97, 109, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109, 32, 98, -108, 97, 110, 100, 105, 116, 46, 32, 68, 117, 105, 115, 32, 114, 105, 115, 117, 115, 32, 116, 101, 108, 108, 117, 115, 44, 32, 114, 117, 116, 114, 117, -109, 32, 118, 105, 116, 97, 101, 44, 32, 105, 109, 112, 101, 114, 100, 105, 101, 116, 32, 110, 101, 99, 44, 32, 109, 97, 108, 101, 115, 117, 97, 100, -97, 32, 110, 101, 99, 44, 32, 105, 112, 115, 117, 109, 46, 32, 78, 117, 110, 99, 32, 113, 117, 97, 109, 32, 100, 111, 108, 111, 114, 44, 32, 108, -117, 99, 116, 117, 115, 32, 101, 103, 101, 116, 44, 32, 112, 108, 97, 99, 101, 114, 97, 116, 32, 110, 111, 110, 44, 32, 114, 104, 111, 110, 99, 117, -115, 32, 97, 116, 44, 32, 116, 101, 108, 108, 117, 115, 46, 32, 68, 117, 105, 115, 32, 112, 101, 100, 101, 32, 108, 101, 99, 116, 117, 115, 44, 32, -109, 97, 116, 116, 105, 115, 32, 97, 100, 105, 112, 105, 115, 99, 105, 110, 103, 44, 32, 116, 101, 109, 112, 111, 114, 32, 117, 116, 44, 32, 112, 111, -114, 116, 97, 32, 97, 116, 44, 32, 109, 105, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 114, 105, 115, 117, 115, 32, 110, -117, 108, 108, 97, 44, 32, 115, 111, 100, 97, 108, 101, 115, 32, 115, 101, 100, 44, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 105, 100, 44, 32, -110, 111, 110, 117, 109, 109, 121, 32, 118, 105, 116, 97, 101, 44, 32, 108, 105, 103, 117, 108, 97, 46, 32, 77, 111, 114, 98, 105, 32, 112, 117, 108, -118, 105, 110, 97, 114, 32, 112, 101, 100, 101, 32, 117, 116, 32, 109, 97, 115, 115, 97, 46, 32, 78, 117, 110, 99, 32, 114, 105, 115, 117, 115, 32, -109, 97, 117, 114, 105, 115, 44, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 101, 116, 44, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 101, -117, 44, 32, 115, 117, 115, 99, 105, 112, 105, 116, 32, 118, 101, 108, 44, 32, 111, 114, 99, 105, 46, 32, 73, 110, 32, 102, 97, 117, 99, 105, 98, -117, 115, 32, 102, 101, 108, 105, 115, 32, 105, 110, 32, 97, 114, 99, 117, 46, 32, 78, 117, 108, 108, 97, 32, 115, 105, 116, 32, 97, 109, 101, 116, -32, 101, 108, 105, 116, 46, 32, 78, 117, 108, 108, 97, 32, 101, 114, 97, 116, 32, 115, 97, 112, 105, 101, 110, 44, 32, 115, 97, 103, 105, 116, 116, -105, 115, 32, 101, 103, 101, 116, 44, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 101, 103, 101, 116, 44, 32, 118, 105, 118, 101, 114, 114, 97, -32, 101, 117, 44, 32, 102, 101, 108, 105, 115, 46, 32, 78, 97, 109, 32, 97, 99, 32, 105, 112, 115, 117, 109, 46, 32, 83, 117, 115, 112, 101, 110, -100, 105, 115, 115, 101, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 116, 117, 114, 112, 105, 115, 32, 118, 101, 108, 32, 115, 101, 109, 32, 108, -97, 99, 105, 110, 105, 97, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 46, 32, 77, 97, 117, 114, 105, 115, 32, 111, 114, 110, 97, 114, -101, 32, 105, 112, 115, 117, 109, 32, 115, 101, 100, 32, 108, 105, 103, 117, 108, 97, 46, 32, 68, 117, 105, 115, 32, 102, 97, 99, 105, 108, 105, 115, -105, 115, 32, 110, 101, 113, 117, 101, 32, 113, 117, 105, 115, 32, 111, 114, 99, 105, 46, 32, 78, 117, 108, 108, 97, 109, 32, 101, 116, 32, 101, 114, -97, 116, 32, 101, 116, 32, 111, 114, 99, 105, 32, 108, 97, 99, 105, 110, 105, 97, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 46, -32, 68, 111, 110, 101, 99, 32, 97, 99, 32, 105, 112, 115, 117, 109, 46, 32, 68, 117, 105, 115, 32, 109, 111, 108, 101, 115, 116, 105, 101, 32, 105, -112, 115, 117, 109, 32, 97, 99, 32, 97, 114, 99, 117, 46, 32, 65, 101, 110, 101, 97, 110, 32, 99, 111, 110, 103, 117, 101, 32, 97, 99, 99, 117, -109, 115, 97, 110, 32, 97, 110, 116, 101, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 98, 105, 98, 101, 110, 100, 117, 109, 44, 32, 108, 101, 111, -32, 117, 116, 32, 111, 114, 110, 97, 114, 101, 32, 97, 108, 105, 113, 117, 97, 109, 44, 32, 110, 117, 110, 99, 32, 101, 114, 97, 116, 32, 99, 111, -110, 100, 105, 109, 101, 110, 116, 117, 109, 32, 97, 114, 99, 117, 44, 32, 117, 116, 32, 112, 117, 108, 118, 105, 110, 97, 114, 32, 109, 105, 32, 97, -117, 103, 117, 101, 32, 101, 116, 32, 110, 117, 108, 108, 97, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 108, 97, 99, 105, 110, 105, 97, 32, 97, -108, 105, 113, 117, 101, 116, 32, 119, 105, 115, 105, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 110, 101, 99, 32, 100, 117, 105, 46, 32, 69, 116, -105, 97, 109, 32, 119, 105, 115, 105, 32, 108, 101, 111, 44, 32, 101, 117, 105, 115, 109, 111, 100, 32, 118, 105, 116, 97, 101, 44, 32, 118, 117, 108, -112, 117, 116, 97, 116, 101, 32, 97, 44, 32, 100, 105, 99, 116, 117, 109, 32, 118, 105, 116, 97, 101, 44, 32, 113, 117, 97, 109, 46, 32, 81, 117, -105, 115, 113, 117, 101, 32, 113, 117, 105, 115, 32, 116, 111, 114, 116, 111, 114, 46, 32, 69, 116, 105, 97, 109, 32, 105, 110, 116, 101, 114, 100, 117, -109, 46, 32, 73, 110, 32, 109, 97, 115, 115, 97, 32, 101, 114, 97, 116, 44, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 115, 101, 100, 44, -32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, 118, 101, 108, 44, 32, 118, 101, 104, 105, 99, 117, 108, 97, 32, 102, 114, 105, 110, 103, 105, 108, -108, 97, 44, 32, 97, 117, 103, 117, 101, 46, 32, 78, 117, 108, 108, 97, 32, 118, 101, 108, 32, 117, 114, 110, 97, 46, 32, 73, 110, 32, 108, 105, -98, 101, 114, 111, 32, 109, 105, 44, 32, 112, 114, 101, 116, 105, 117, 109, 32, 115, 101, 100, 44, 32, 109, 97, 116, 116, 105, 115, 32, 116, 101, 109, -112, 117, 115, 44, 32, 115, 97, 103, 105, 116, 116, 105, 115, 32, 115, 101, 100, 44, 32, 109, 97, 115, 115, 97, 46, 32, 83, 117, 115, 112, 101, 110, -100, 105, 115, 115, 101, 32, 113, 117, 97, 109, 32, 119, 105, 115, 105, 44, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109, 32, 113, 117, 105, 115, 44, -32, 115, 97, 103, 105, 116, 116, 105, 115, 32, 97, 116, 44, 32, 99, 111, 110, 115, 101, 113, 117, 97, 116, 32, 101, 103, 101, 116, 44, 32, 111, 100, -105, 111, 46, 32, 78, 117, 108, 108, 97, 109, 32, 105, 109, 112, 101, 114, 100, 105, 101, 116, 44, 32, 112, 117, 114, 117, 115, 32, 113, 117, 105, 115, -32, 97, 108, 105, 113, 117, 97, 109, 32, 99, 117, 114, 115, 117, 115, 44, 32, 116, 117, 114, 112, 105, 115, 32, 111, 100, 105, 111, 32, 101, 103, 101, -115, 116, 97, 115, 32, 106, 117, 115, 116, 111, 44, 32, 112, 108, 97, 99, 101, 114, 97, 116, 32, 103, 114, 97, 118, 105, 100, 97, 32, 116, 117, 114, -112, 105, 115, 32, 119, 105, 115, 105, 32, 118, 101, 108, 32, 116, 111, 114, 116, 111, 114, 46, 32, 78, 117, 110, 99, 32, 117, 108, 116, 114, 105, 99, -105, 101, 115, 32, 112, 111, 114, 116, 97, 32, 112, 117, 114, 117, 115, 46, 32, 80, 114, 111, 105, 110, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, -32, 101, 114, 97, 116, 32, 97, 99, 32, 111, 114, 99, 105, 46, 32, 85, 116, 32, 118, 101, 108, 32, 109, 97, 103, 110, 97, 32, 110, 101, 99, 32, -109, 105, 32, 102, 101, 117, 103, 105, 97, 116, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 46, 32, 85, 116, 32, 108, 105, 103, 117, 108, 97, 46, -32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 97, 110, 116, 101, 32, 105, 112, 115, 117, 109, 32, 112, 114, 105, 109, 105, 115, 32, 105, 110, -32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 111, 114, 99, 105, 32, 108, 117, 99, 116, 117, 115, 32, 101, 116, 32, 117, 108, 116, 114, 105, 99, 101, -115, 32, 112, 111, 115, 117, 101, 114, 101, 32, 99, 117, 98, 105, 108, 105, 97, 32, 67, 117, 114, 97, 101, 59, 32, 68, 111, 110, 101, 99, 32, 101, -116, 32, 109, 97, 103, 110, 97, 32, 105, 110, 32, 100, 105, 97, 109, 32, 112, 111, 114, 116, 97, 32, 110, 111, 110, 117, 109, 109, 121, 46, 32, 77, -97, 101, 99, 101, 110, 97, 115, 32, 117, 116, 32, 115, 101, 109, 32, 105, 110, 32, 116, 117, 114, 112, 105, 115, 32, 102, 101, 114, 109, 101, 110, 116, -117, 109, 32, 118, 105, 118, 101, 114, 114, 97, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 97, 116, 32, 111, 114, 99, 105, 46, -32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 104, 97, 98, 105, 116, 97, 110, 116, 32, 109, 111, 114, 98, 105, 32, 116, 114, 105, -115, 116, 105, 113, 117, 101, 32, 115, 101, 110, 101, 99, 116, 117, 115, 32, 101, 116, 32, 110, 101, 116, 117, 115, 32, 101, 116, 32, 109, 97, 108, 101, -115, 117, 97, 100, 97, 32, 102, 97, 109, 101, 115, 32, 97, 99, 32, 116, 117, 114, 112, 105, 115, 32, 101, 103, 101, 115, 116, 97, 115, 46, 32, 86, -101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 97, 110, 116, 101, 32, 105, 112, 115, 117, 109, 32, 112, 114, 105, 109, 105, 115, 32, 105, 110, 32, 102, -97, 117, 99, 105, 98, 117, 115, 32, 111, 114, 99, 105, 32, 108, 117, 99, 116, 117, 115, 32, 101, 116, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, -112, 111, 115, 117, 101, 114, 101, 32, 99, 117, 98, 105, 108, 105, 97, 32, 67, 117, 114, 97, 101, 59, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, -113, 117, 101, 32, 114, 117, 116, 114, 117, 109, 32, 101, 108, 101, 105, 102, 101, 110, 100, 32, 106, 117, 115, 116, 111, 46, 32, 78, 117, 108, 108, 97, -109, 32, 118, 105, 116, 97, 101, 32, 112, 101, 100, 101, 46, 32, 68, 111, 110, 101, 99, 32, 99, 111, 110, 100, 105, 109, 101, 110, 116, 117, 109, 32, -110, 105, 98, 104, 32, 101, 116, 32, 111, 100, 105, 111, 46, 32, 83, 101, 100, 32, 101, 116, 32, 109, 101, 116, 117, 115, 46, 32, 67, 108, 97, 115, -115, 32, 97, 112, 116, 101, 110, 116, 32, 116, 97, 99, 105, 116, 105, 32, 115, 111, 99, 105, 111, 115, 113, 117, 32, 97, 100, 32, 108, 105, 116, 111, -114, 97, 32, 116, 111, 114, 113, 117, 101, 110, 116, 32, 112, 101, 114, 32, 99, 111, 110, 117, 98, 105, 97, 32, 110, 111, 115, 116, 114, 97, 44, 32, -112, 101, 114, 32, 105, 110, 99, 101, 112, 116, 111, 115, 32, 104, 121, 109, 101, 110, 97, 101, 111, 115, 46, 32, 78, 97, 109, 32, 116, 101, 109, 112, -117, 115, 46, 32, 83, 101, 100, 32, 97, 99, 32, 119, 105, 115, 105, 46, 32, 73, 110, 32, 104, 97, 99, 32, 104, 97, 98, 105, 116, 97, 115, 115, -101, 32, 112, 108, 97, 116, 101, 97, 32, 100, 105, 99, 116, 117, 109, 115, 116, 46, 32, 83, 101, 100, 32, 115, 101, 100, 32, 119, 105, 115, 105, 46, -32, 85, 116, 32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 32, 116, 101, 108, 108, 117, 115, 32, 110, 111, 110, 32, 108, 105, 103, 117, 108, 97, 46, -32, 73, 110, 116, 101, 103, 101, 114, 32, 109, 101, 116, 117, 115, 46, 32, 73, 110, 32, 108, 97, 99, 105, 110, 105, 97, 32, 100, 117, 105, 46, 32, -67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 111, 114, 110, 97, 114, 101, 46, 32, 77, 97, 117, 114, 105, 115, 32, 118, 101, 108, 32, 117, 114, 110, -97, 46, 32, 78, 97, 109, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117, 101, 114, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 117, 114, -110, 97, 46, 32, 78, 117, 110, 99, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 101, 114, 97, -116, 46, 32, 83, 101, 100, 32, 98, 108, 97, 110, 100, 105, 116, 44, 32, 114, 105, 115, 117, 115, 32, 110, 111, 110, 32, 99, 111, 109, 109, 111, 100, -111, 32, 110, 111, 110, 117, 109, 109, 121, 44, 32, 108, 105, 103, 117, 108, 97, 32, 101, 114, 97, 116, 32, 102, 101, 114, 109, 101, 110, 116, 117, 109, -32, 110, 105, 98, 104, 44, 32, 101, 117, 32, 102, 97, 99, 105, 108, 105, 115, 105, 115, 32, 97, 110, 116, 101, 32, 110, 101, 113, 117, 101, 32, 115, -101, 100, 32, 115, 101, 109, 46, 32, 69, 116, 105, 97, 109, 32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117, 101, 32, 106, 117, 115, 116, 111, 32, -101, 103, 101, 116, 32, 119, 105, 115, 105, 46, 32, 78, 117, 110, 99, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 46, 32, 80, 114, 111, 105, 110, -32, 112, 117, 108, 118, 105, 110, 97, 114, 32, 113, 117, 97, 109, 32, 110, 111, 110, 32, 108, 101, 99, 116, 117, 115, 46, 32, 80, 114, 111, 105, 110, -32, 117, 116, 32, 116, 117, 114, 112, 105, 115, 32, 113, 117, 105, 115, 32, 97, 117, 103, 117, 101, 32, 112, 101, 108, 108, 101, 110, 116, 101, 115, 113, -117, 101, 32, 100, 105, 99, 116, 117, 109, 46, 32, 70, 117, 115, 99, 101, 32, 101, 116, 32, 108, 111, 114, 101, 109, 46, 32, 65, 108, 105, 113, 117, -97, 109, 32, 117, 114, 110, 97, 32, 108, 97, 99, 117, 115, 44, 32, 98, 108, 97, 110, 100, 105, 116, 32, 115, 101, 100, 44, 32, 118, 101, 115, 116, -105, 98, 117, 108, 117, 109, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 112, 108, 97, 99, 101, 114, 97, 116, 32, 101, 116, 44, 32, 100, 111, -108, 111, 114, 46, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 97, 117, 99, 116, 111, 114, 32, 101, 114, 97, 116, 32, 110, 101, 99, 32, 108, -111, 114, 101, 109, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 117, 114, 110, 97, 32, 119, 105, 115, 105, 44, 32, 108, 97, 99, 105, 110, -105, 97, 32, 117, 116, 44, 32, 109, 111, 108, 101, 115, 116, 105, 101, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 44, 32, 99, 111, 110, 100, 105, -109, 101, 110, 116, 117, 109, 32, 105, 100, 44, 32, 111, 100, 105, 111, 46, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 99, 111, 110, 118, 97, -108, 108, 105, 115, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 32, 106, 117, 115, 116, 111, 46, 32, 68, 111, 110, 101, 99, 32, 118, 101, -115, 116, 105, 98, 117, 108, 117, 109, 32, 101, 115, 116, 32, 97, 99, 32, 113, 117, 97, 109, 46, 32, 78, 117, 108, 108, 97, 109, 32, 118, 105, 116, -97, 101, 32, 101, 108, 105, 116, 32, 101, 117, 32, 109, 97, 115, 115, 97, 32, 118, 97, 114, 105, 117, 115, 32, 118, 117, 108, 112, 117, 116, 97, 116, -101, 46, 32, 78, 117, 108, 108, 97, 32, 102, 97, 99, 105, 108, 105, 115, 105, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 112, -111, 116, 101, 110, 116, 105, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 110, 111, 110, 32, 108, 105, 98, 101, 114, 111, 46, 32, 78, 117, 108, -108, 97, 109, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 109, 97, 115, 115, 97, 32, 105, 100, 32, 109, 97, 103, 110, 97, 32, 118, 105, 118, -101, 114, 114, 97, 32, 99, 111, 109, 109, 111, 100, 111, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 108, 105, 98, 101, 114, 111, 32, -116, 111, 114, 116, 111, 114, 44, 32, 108, 117, 99, 116, 117, 115, 32, 97, 99, 44, 32, 118, 105, 118, 101, 114, 114, 97, 32, 99, 111, 110, 103, 117, -101, 44, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117, 101, 114, 32, 118, 101, 108, 44, 32, 108, 105, 98, 101, 114, 111, 46, 32, 65, 101, 110, -101, 97, 110, 32, 97, 114, 99, 117, 32, 97, 117, 103, 117, 101, 44, 32, 108, 117, 99, 116, 117, 115, 32, 105, 100, 44, 32, 108, 97, 111, 114, 101, -101, 116, 32, 112, 117, 108, 118, 105, 110, 97, 114, 44, 32, 100, 105, 99, 116, 117, 109, 32, 115, 101, 100, 44, 32, 108, 101, 99, 116, 117, 115, 46, -32, 68, 111, 110, 101, 99, 32, 118, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 118, 111, 108, 117, 116, 112, 97, 116, 32, 100, 111, 108, 111, 114, -46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 104, 97, 98, 105, 116, 97, 110, 116, 32, 109, 111, 114, 98, 105, 32, 116, 114, -105, 115, 116, 105, 113, 117, 101, 32, 115, 101, 110, 101, 99, 116, 117, 115, 32, 101, 116, 32, 110, 101, 116, 117, 115, 32, 101, 116, 32, 109, 97, 108, -101, 115, 117, 97, 100, 97, 32, 102, 97, 109, 101, 115, 32, 97, 99, 32, 116, 117, 114, 112, 105, 115, 32, 101, 103, 101, 115, 116, 97, 115, 46, 32, -80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 97, 117, 103, 117, 101, 32, 116, 117, 114, 112, 105, 115, 44, 32, 108, 97, 111, 114, 101, -101, 116, 32, 110, 101, 99, 44, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 97, 116, 44, 32, 110, 111, 110, 117, 109, 109, 121, 32, 118, 105, -116, 97, 101, 44, 32, 110, 105, 98, 104, 46, 32, 69, 116, 105, 97, 109, 32, 111, 114, 99, 105, 32, 115, 97, 112, 105, 101, 110, 44, 32, 99, 111, -110, 103, 117, 101, 32, 105, 110, 44, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 114, 117, 116, -114, 117, 109, 32, 118, 101, 108, 44, 32, 110, 105, 98, 104, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 101, 117, 32, 108, 111, 114, 101, 109, 46, -32, 77, 97, 117, 114, 105, 115, 32, 112, 114, 101, 116, 105, 117, 109, 32, 108, 101, 111, 32, 101, 116, 32, 101, 108, 105, 116, 46, 32, 73, 110, 32, -110, 111, 110, 117, 109, 109, 121, 32, 117, 108, 116, 114, 105, 99, 105, 101, 115, 32, 115, 97, 112, 105, 101, 110, 46, 32, 77, 97, 117, 114, 105, 115, -32, 118, 97, 114, 105, 117, 115, 46, 32, 77, 97, 117, 114, 105, 115, 32, 115, 101, 100, 32, 108, 105, 98, 101, 114, 111, 46, 32, 67, 117, 114, 97, -98, 105, 116, 117, 114, 32, 117, 108, 108, 97, 109, 99, 111, 114, 112, 101, 114, 32, 101, 108, 105, 116, 32, 101, 117, 32, 112, 117, 114, 117, 115, 46, -32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 118, 101, 108, 105, 116, 32, 112, 101, 100, 101, 44, 32, 115, 101, 109, 112, 101, 114, 32, 115, -105, 116, 32, 97, 109, 101, 116, 44, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 118, 105, 116, 97, 101, 44, 32, 116, 105, 110, 99, 105, 100, 117, -110, 116, 32, 118, 101, 108, 44, 32, 100, 117, 105, 46, 32, 78, 117, 108, 108, 97, 32, 110, 101, 113, 117, 101, 32, 97, 110, 116, 101, 44, 32, 115, -97, 103, 105, 116, 116, 105, 115, 32, 101, 117, 44, 32, 118, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 101, 116, 44, 32, 108, 97, 99, 105, 110, -105, 97, 32, 97, 44, 32, 108, 105, 98, 101, 114, 111, 46, 32, 77, 111, 114, 98, 105, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 119, 105, 115, -105, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 110, 111, 110, 32, 102, 101, 108, 105, 115, 32, 113, 117, 105, 115, 32, 97, -114, 99, 117, 32, 98, 105, 98, 101, 110, 100, 117, 109, 32, 111, 114, 110, 97, 114, 101, 46, 32, 65, 101, 110, 101, 97, 110, 32, 101, 110, 105, 109, -32, 109, 101, 116, 117, 115, 44, 32, 99, 111, 109, 109, 111, 100, 111, 32, 101, 117, 44, 32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 32, 110, 111, -110, 117, 109, 109, 121, 44, 32, 101, 117, 105, 115, 109, 111, 100, 32, 117, 116, 44, 32, 113, 117, 97, 109, 46, 32, 78, 117, 108, 108, 97, 32, 101, -108, 101, 105, 102, 101, 110, 100, 32, 110, 105, 115, 108, 32, 113, 117, 105, 115, 32, 100, 111, 108, 111, 114, 46, 32, 67, 108, 97, 115, 115, 32, 97, -112, 116, 101, 110, 116, 32, 116, 97, 99, 105, 116, 105, 32, 115, 111, 99, 105, 111, 115, 113, 117, 32, 97, 100, 32, 108, 105, 116, 111, 114, 97, 32, -116, 111, 114, 113, 117, 101, 110, 116, 32, 112, 101, 114, 32, 99, 111, 110, 117, 98, 105, 97, 32, 110, 111, 115, 116, 114, 97, 44, 32, 112, 101, 114, -32, 105, 110, 99, 101, 112, 116, 111, 115, 32, 104, 121, 109, 101, 110, 97, 101, 111, 115, 46, 32, 77, 97, 101, 99, 101, 110, 97, 115, 32, 112, 101, -108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 109, 97, 115, 115, 97, 32, 105, 110, 32, 101, 114, 97, 116, 32, 109, 111, 108, 101, 115, 116, 105, -101, 32, 109, 111, 108, 101, 115, 116, 105, 101, 46, 32, 77, 97, 117, 114, 105, 115, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 100, 97, 112, -105, 98, 117, 115, 32, 108, 105, 98, 101, 114, 111, 46, 32, 83, 101, 100, 32, 115, 101, 100, 32, 114, 105, 115, 117, 115, 32, 105, 100, 32, 110, 101, -113, 117, 101, 32, 100, 105, 99, 116, 117, 109, 32, 111, 114, 110, 97, 114, 101, 46, 32, 83, 101, 100, 32, 101, 117, 32, 108, 105, 103, 117, 108, 97, -32, 97, 116, 32, 102, 101, 108, 105, 115, 32, 115, 111, 100, 97, 108, 101, 115, 32, 97, 99, 99, 117, 109, 115, 97, 110, 46, 32, 83, 101, 100, 32, -105, 110, 116, 101, 114, 100, 117, 109, 44, 32, 117, 114, 110, 97, 32, 110, 111, 110, 32, 112, 104, 97, 114, 101, 116, 114, 97, 32, 104, 101, 110, 100, -114, 101, 114, 105, 116, 44, 32, 113, 117, 97, 109, 32, 109, 105, 32, 111, 114, 110, 97, 114, 101, 32, 108, 105, 98, 101, 114, 111, 44, 32, 105, 100, -32, 102, 114, 105, 110, 103, 105, 108, 108, 97, 32, 116, 111, 114, 116, 111, 114, 32, 111, 114, 99, 105, 32, 110, 111, 110, 32, 118, 101, 108, 105, 116, -46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 110, 101, 99, 32, 114, 105, 115, 117, 115, 46, 32, 68, 111, 110, 101, 99, 32, 97, 116, 32, 110, 117, -110, 99, 32, 118, 105, 116, 97, 101, 32, 116, 101, 108, 108, 117, 115, 32, 109, 111, 108, 101, 115, 116, 105, 101, 32, 118, 101, 115, 116, 105, 98, 117, -108, 117, 109, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, 113, 117, 101, 32, 118, 101, 108, 32, 106, 117, 115, 116, 111, 46, 32, 68, 117, 105, -115, 32, 108, 105, 103, 117, 108, 97, 32, 108, 105, 98, 101, 114, 111, 44, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 113, 117, 105, 115, 44, -32, 97, 100, 105, 112, 105, 115, 99, 105, 110, 103, 32, 98, 105, 98, 101, 110, 100, 117, 109, 44, 32, 102, 101, 117, 103, 105, 97, 116, 32, 118, 105, -116, 97, 101, 44, 32, 118, 101, 108, 105, 116, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 101, 116, 32, 97, 114, 99, 117, 46, 32, 70, 117, 115, -99, 101, 32, 101, 103, 101, 116, 32, 113, 117, 97, 109, 46, 32, 85, 116, 32, 97, 110, 116, 101, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, -115, 101, 32, 102, 101, 117, 103, 105, 97, 116, 32, 109, 101, 116, 117, 115, 32, 110, 111, 110, 32, 105, 112, 115, 117, 109, 46, 32, 78, 117, 108, 108, -97, 32, 116, 101, 109, 112, 117, 115, 32, 108, 101, 111, 32, 117, 116, 32, 109, 105, 46, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 118, 105, -116, 97, 101, 32, 110, 105, 115, 108, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 46, 32, 69, 116, 105, -97, 109, 32, 97, 32, 111, 114, 99, 105, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 97, 110, 116, 101, 32, 105, 112, 115, 117, 109, -32, 112, 114, 105, 109, 105, 115, 32, 105, 110, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 111, 114, 99, 105, 32, 108, 117, 99, 116, 117, 115, 32, -101, 116, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 112, 111, 115, 117, 101, 114, 101, 32, 99, 117, 98, 105, 108, 105, 97, 32, 67, 117, 114, 97, -101, 59, 32, 86, 105, 118, 97, 109, 117, 115, 32, 117, 114, 110, 97, 32, 113, 117, 97, 109, 44, 32, 116, 105, 110, 99, 105, 100, 117, 110, 116, 32, -97, 116, 44, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 118, 101, 108, 44, 32, 102, 101, 117, 103, 105, 97, 116, 32, 101, 103, 101, 116, 44, 32, -110, 117, 108, 108, 97, 46, 32, 77, 97, 101, 99, 101, 110, 97, 115, 32, 108, 97, 99, 117, 115, 32, 109, 97, 103, 110, 97, 44, 32, 110, 111, 110, -117, 109, 109, 121, 32, 101, 117, 44, 32, 105, 97, 99, 117, 108, 105, 115, 32, 115, 101, 100, 44, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117, -101, 114, 32, 113, 117, 105, 115, 44, 32, 101, 110, 105, 109, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 97, 32, 101, 114, 111, 115, 46, 32, -65, 108, 105, 113, 117, 97, 109, 32, 110, 111, 110, 117, 109, 109, 121, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 110, 101, 113, 117, 101, 46, -32, 78, 117, 108, 108, 97, 32, 101, 110, 105, 109, 46, 32, 80, 114, 97, 101, 115, 101, 110, 116, 32, 109, 111, 108, 101, 115, 116, 105, 101, 44, 32, -111, 114, 99, 105, 32, 113, 117, 105, 115, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 118, 111, 108, 117, 116, 112, 97, 116, 44, 32, 108, 97, -99, 117, 115, 32, 109, 101, 116, 117, 115, 32, 108, 117, 99, 116, 117, 115, 32, 115, 97, 112, 105, 101, 110, 44, 32, 101, 116, 32, 102, 97, 99, 105, -108, 105, 115, 105, 115, 32, 101, 114, 111, 115, 32, 110, 101, 113, 117, 101, 32, 105, 100, 32, 115, 97, 112, 105, 101, 110, 46, 32, 78, 117, 110, 99, -32, 99, 111, 110, 100, 105, 109, 101, 110, 116, 117, 109, 32, 100, 111, 108, 111, 114, 32, 118, 101, 108, 32, 111, 114, 99, 105, 46, 32, 73, 110, 116, -101, 103, 101, 114, 32, 119, 105, 115, 105, 32, 100, 105, 97, 109, 44, 32, 112, 111, 114, 116, 116, 105, 116, 111, 114, 32, 115, 105, 116, 32, 97, 109, -101, 116, 44, 32, 102, 101, 117, 103, 105, 97, 116, 32, 105, 110, 44, 32, 100, 97, 112, 105, 98, 117, 115, 32, 105, 110, 44, 32, 108, 101, 99, 116, -117, 115, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 101, 114, 97, 116, 32, 118, 111, 108, 117, 116, 112, 97, 116, 46, 32, 81, 117, 105, 115, 113, -117, 101, 32, 109, 111, 108, 108, 105, 115, 32, 116, 117, 114, 112, 105, 115, 32, 118, 105, 116, 97, 101, 32, 116, 111, 114, 116, 111, 114, 46, 32, 77, -97, 117, 114, 105, 115, 32, 116, 117, 114, 112, 105, 115, 32, 109, 105, 44, 32, 112, 114, 101, 116, 105, 117, 109, 32, 117, 116, 44, 32, 117, 108, 116, -114, 105, 99, 101, 115, 32, 115, 101, 100, 44, 32, 112, 111, 114, 116, 97, 32, 105, 110, 44, 32, 106, 117, 115, 116, 111, 46, 32, 83, 117, 115, 112, -101, 110, 100, 105, 115, 115, 101, 32, 112, 111, 115, 117, 101, 114, 101, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 117, 108, 116, 114, 105, 99, 105, -101, 115, 32, 108, 97, 99, 117, 115, 32, 118, 105, 116, 97, 101, 32, 101, 110, 105, 109, 46, 32, 68, 111, 110, 101, 99, 32, 108, 97, 99, 117, 115, -46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, 112, 111, 116, 101, 110, 116, 105, 46, 32, 68, 111, 110, 101, 99, 32, 109, 111, 108, -101, 115, 116, 105, 101, 44, 32, 109, 97, 103, 110, 97, 32, 115, 101, 100, 32, 101, 117, 105, 115, 109, 111, 100, 32, 100, 105, 99, 116, 117, 109, 44, -32, 109, 97, 103, 110, 97, 32, 109, 97, 103, 110, 97, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 100, 105, 97, 109, 44, 32, 118, 105, 116, 97, -101, 32, 115, 97, 103, 105, 116, 116, 105, 115, 32, 108, 101, 111, 32, 108, 111, 114, 101, 109, 32, 97, 99, 32, 110, 101, 113, 117, 101, 46, 32, 67, -114, 97, 115, 32, 109, 101, 116, 117, 115, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 110, 117, 110, 99, 46, 32, 68, 117, 105, 115, 32, 99, 111, -110, 115, 101, 99, 116, 101, 116, 117, 101, 114, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 103, 114, 97, 118, 105, 100, 97, 32, 115, -111, 108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32, 117, 114, 110, 97, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 118, 111, 108, 117, 116, 112, -97, 116, 44, 32, 109, 97, 115, 115, 97, 32, 113, 117, 105, 115, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 112, 117, 108, 118, 105, 110, 97, 114, -44, 32, 101, 114, 111, 115, 32, 112, 117, 114, 117, 115, 32, 100, 105, 103, 110, 105, 115, 115, 105, 109, 32, 110, 117, 110, 99, 44, 32, 101, 103, 101, -116, 32, 114, 104, 111, 110, 99, 117, 115, 32, 101, 110, 105, 109, 32, 108, 101, 99, 116, 117, 115, 32, 113, 117, 105, 115, 32, 116, 111, 114, 116, 111, -114, 46, 32, 73, 110, 116, 101, 103, 101, 114, 32, 108, 97, 99, 105, 110, 105, 97, 32, 113, 117, 97, 109, 32, 113, 117, 105, 115, 32, 101, 114, 97, -116, 32, 99, 111, 110, 118, 97, 108, 108, 105, 115, 32, 109, 97, 116, 116, 105, 115, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, 32, -105, 97, 99, 117, 108, 105, 115, 32, 112, 111, 115, 117, 101, 114, 101, 32, 118, 101, 108, 105, 116, 46, 32, 69, 116, 105, 97, 109, 32, 116, 101, 108, -108, 117, 115, 32, 101, 110, 105, 109, 44, 32, 97, 108, 105, 113, 117, 101, 116, 32, 110, 101, 99, 44, 32, 108, 97, 111, 114, 101, 101, 116, 32, 97, -44, 32, 109, 111, 108, 101, 115, 116, 105, 101, 32, 110, 111, 110, 44, 32, 118, 101, 108, 105, 116, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 108, -97, 99, 117, 115, 32, 118, 101, 108, 105, 116, 44, 32, 101, 108, 101, 105, 102, 101, 110, 100, 32, 105, 109, 112, 101, 114, 100, 105, 101, 116, 44, 32, -102, 114, 105, 110, 103, 105, 108, 108, 97, 32, 105, 100, 44, 32, 100, 97, 112, 105, 98, 117, 115, 32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117, -101, 44, 32, 108, 101, 99, 116, 117, 115, 46, 32, 78, 117, 108, 108, 97, 32, 113, 117, 105, 115, 32, 108, 111, 114, 101, 109, 46, 32, 78, 117, 108, -108, 97, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 110, 101, 113, 117, 101, 32, 101, 116, 32, 100, 117, 105, 46, 32, 80, 104, 97, 115, 101, -108, 108, 117, 115, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 117, 108, 116, 114, 105, 99, 105, 101, 115, 32, 111, 100, 105, 111, 46, 32, 80, -104, 97, 115, 101, 108, 108, 117, 115, 32, 118, 105, 116, 97, 101, 32, 108, 105, 103, 117, 108, 97, 46, 32, 80, 101, 108, 108, 101, 110, 116, 101, 115, -113, 117, 101, 32, 102, 101, 117, 103, 105, 97, 116, 32, 97, 114, 99, 117, 32, 97, 116, 32, 101, 114, 97, 116, 46, 32, 86, 105, 118, 97, 109, 117, -115, 32, 117, 116, 32, 101, 114, 111, 115, 32, 117, 116, 32, 108, 111, 114, 101, 109, 32, 112, 117, 108, 118, 105, 110, 97, 114, 32, 105, 97, 99, 117, -108, 105, 115, 46, 32, 80, 114, 111, 105, 110, 32, 108, 111, 98, 111, 114, 116, 105, 115, 32, 105, 112, 115, 117, 109, 32, 105, 100, 32, 110, 117, 110, -99, 46, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 118, 101, 108, 32, 109, 97, 115, 115, 97, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, -115, 115, 101, 32, 110, 117, 108, 108, 97, 32, 105, 112, 115, 117, 109, 44, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 118, 101, 108, 44, 32, -112, 111, 115, 117, 101, 114, 101, 32, 101, 103, 101, 116, 44, 32, 109, 111, 108, 108, 105, 115, 32, 97, 116, 44, 32, 114, 105, 115, 117, 115, 46, 32, -86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 115, 101, 100, 32, 100, 105, 97, 109, 32, 105, 100, 32, 101, 115, 116, 32, 100, 97, 112, 105, 98, -117, 115, 32, 117, 108, 116, 114, 105, 99, 101, 115, 46, 32, 80, 114, 111, 105, 110, 32, 116, 101, 109, 112, 117, 115, 44, 32, 101, 114, 111, 115, 32, -97, 32, 115, 99, 101, 108, 101, 114, 105, 115, 113, 117, 101, 32, 118, 101, 115, 116, 105, 98, 117, 108, 117, 109, 44, 32, 105, 112, 115, 117, 109, 32, -97, 114, 99, 117, 32, 97, 108, 105, 113, 117, 97, 109, 32, 109, 105, 44, 32, 117, 116, 32, 102, 101, 117, 103, 105, 97, 116, 32, 108, 105, 98, 101, -114, 111, 32, 111, 100, 105, 111, 32, 105, 110, 32, 110, 105, 115, 108, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 101, 116, 32, 109, 97, 115, 115, -97, 32, 97, 32, 109, 97, 117, 114, 105, 115, 32, 108, 117, 99, 116, 117, 115, 32, 99, 111, 110, 103, 117, 101, 46, 32, 85, 116, 32, 105, 100, 32, -101, 114, 111, 115, 46, 32, 70, 117, 115, 99, 101, 32, 97, 110, 116, 101, 32, 101, 114, 111, 115, 44, 32, 112, 104, 97, 114, 101, 116, 114, 97, 32, -110, 111, 110, 44, 32, 109, 111, 108, 101, 115, 116, 105, 101, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 44, 32, 98, 105, 98, 101, 110, 100, 117, -109, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 119, 105, 115, 105, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 114, 117, 116, 114, -117, 109, 44, 32, 100, 111, 108, 111, 114, 32, 101, 116, 32, 115, 101, 109, 112, 101, 114, 32, 101, 108, 101, 109, 101, 110, 116, 117, 109, 44, 32, 101, -114, 111, 115, 32, 97, 110, 116, 101, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 109, 97, 115, 115, 97, 44, 32, 115, 101, 100, 32, 115, 111, -108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32, 108, 101, 99, 116, 117, 115, 32, 118, 101, 108, 105, 116, 32, 101, 116, 32, 109, 97, 115, 115, 97, -46, 32, 73, 110, 32, 97, 117, 99, 116, 111, 114, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 101, 114, 97, 116, 32, 118, 111, 108, 117, 116, 112, -97, 116, 46, 32, 69, 116, 105, 97, 109, 32, 114, 105, 115, 117, 115, 32, 108, 101, 111, 44, 32, 118, 117, 108, 112, 117, 116, 97, 116, 101, 32, 115, -117, 115, 99, 105, 112, 105, 116, 44, 32, 115, 111, 108, 108, 105, 99, 105, 116, 117, 100, 105, 110, 32, 101, 116, 44, 32, 115, 111, 100, 97, 108, 101, -115, 32, 101, 103, 101, 116, 44, 32, 110, 105, 115, 108, 46, 32, 86, 101, 115, 116, 105, 98, 117, 108, 117, 109, 32, 97, 110, 116, 101, 32, 105, 112, -115, 117, 109, 32, 112, 114, 105, 109, 105, 115, 32, 105, 110, 32, 102, 97, 117, 99, 105, 98, 117, 115, 32, 111, 114, 99, 105, 32, 108, 117, 99, 116, -117, 115, 32, 101, 116, 32, 117, 108, 116, 114, 105, 99, 101, 115, 32, 112, 111, 115, 117, 101, 114, 101, 32, 99, 117, 98, 105, 108, 105, 97, 32, 67, -117, 114, 97, 101, 59, 32, 67, 117, 114, 97, 98, 105, 116, 117, 114, 32, 108, 111, 98, 111, 114, 116, 105, 115, 44, 32, 108, 105, 98, 101, 114, 111, -32, 97, 99, 32, 108, 97, 111, 114, 101, 101, 116, 32, 109, 111, 108, 108, 105, 115, 44, 32, 108, 105, 103, 117, 108, 97, 32, 108, 101, 111, 32, 112, -111, 114, 116, 97, 32, 119, 105, 115, 105, 44, 32, 117, 116, 32, 101, 117, 105, 115, 109, 111, 100, 32, 102, 101, 108, 105, 115, 32, 108, 105, 103, 117, -108, 97, 32, 105, 100, 32, 101, 108, 105, 116, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 109, 97, 108, 101, 115, 117, 97, 100, 97, 32, 110, 117, -108, 108, 97, 32, 101, 117, 32, 101, 110, 105, 109, 46, 32, 68, 111, 110, 101, 99, 32, 97, 99, 99, 117, 109, 115, 97, 110, 32, 102, 97, 117, 99, -105, 98, 117, 115, 32, 111, 114, 99, 105, 46, 32, 78, 117, 108, 108, 97, 32, 108, 97, 99, 105, 110, 105, 97, 32, 97, 110, 116, 101, 46, 32, 80, -114, 97, 101, 115, 101, 110, 116, 32, 97, 116, 32, 110, 105, 98, 104, 46, 32, 77, 97, 117, 114, 105, 115, 32, 112, 111, 114, 116, 97, 32, 100, 105, -103, 110, 105, 115, 115, 105, 109, 32, 119, 105, 115, 105, 46, 32, 85, 116, 32, 108, 97, 99, 105, 110, 105, 97, 32, 116, 111, 114, 116, 111, 114, 32, -110, 101, 99, 32, 110, 117, 110, 99, 46, 32, 80, 104, 97, 115, 101, 108, 108, 117, 115, 32, 101, 116, 32, 97, 117, 103, 117, 101, 46, 32, 73, 110, -116, 101, 103, 101, 114, 32, 114, 104, 111, 110, 99, 117, 115, 44, 32, 108, 105, 98, 101, 114, 111, 32, 97, 32, 112, 101, 108, 108, 101, 110, 116, 101, -115, 113, 117, 101, 32, 114, 104, 111, 110, 99, 117, 115, 44, 32, 116, 111, 114, 116, 111, 114, 32, 115, 97, 112, 105, 101, 110, 32, 108, 111, 98, 111, -114, 116, 105, 115, 32, 112, 101, 100, 101, 44, 32, 101, 103, 101, 116, 32, 99, 111, 110, 100, 105, 109, 101, 110, 116, 117, 109, 32, 115, 97, 112, 105, -101, 110, 32, 114, 105, 115, 117, 115, 32, 118, 105, 116, 97, 101, 32, 101, 108, 105, 116, 46, 32, 83, 117, 115, 112, 101, 110, 100, 105, 115, 115, 101, -32, 115, 101, 100, 32, 116, 117, 114, 112, 105, 115, 32, 117, 116, 32, 100, 111, 108, 111, 114, 32, 112, 108, 97, 99, 101, 114, 97, 116, 32, 100, 105, -103, 110, 105, 115, 115, 105, 109, 46, 32, 81, 117, 105, 115, 113, 117, 101, 32, 113, 117, 105, 115, 32, 108, 101, 111, 46, 32, 67, 114, 97, 115, 32, -117, 108, 116, 114, 105, 99, 101, 115, 46, 32, 77, 97, 101, 99, 101, 110, 97, 115, 32, 104, 101, 110, 100, 114, 101, 114, 105, 116, 32, 97, 117, 99, -116, 111, 114, 32, 116, 111, 114, 116, 111, 114, 46, 32, 69, 116, 105, 97, 109, 32, 115, 105, 116, 32, 97, 109, 101, 116, 32, 97, 114, 99, 117, 46, -0}; -- cgit v1.2.3 From 38321faa8d111ec51ebdeb7f2e939062d5e080a1 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 23 Mar 2015 15:29:42 -0400 Subject: cleanup: use spaces for alignment while studying GPU lib --- source/blender/gpu/GPU_buffers.h | 8 +- source/blender/gpu/GPU_compositing.h | 2 +- source/blender/gpu/GPU_draw.h | 1 + source/blender/gpu/GPU_extensions.h | 32 +- source/blender/gpu/GPU_material.h | 30 +- source/blender/gpu/GPU_simple_shader.h | 8 +- source/blender/gpu/intern/gpu_buffers.c | 193 ++++++------ source/blender/gpu/intern/gpu_codegen.c | 181 ++++++----- source/blender/gpu/intern/gpu_codegen.h | 66 ++-- source/blender/gpu/intern/gpu_compositing.c | 12 +- source/blender/gpu/intern/gpu_debug.c | 4 +- source/blender/gpu/intern/gpu_draw.c | 466 ++++++++++++++-------------- source/blender/gpu/intern/gpu_extensions.c | 110 +++---- source/blender/gpu/intern/gpu_material.c | 419 +++++++++++++------------ 14 files changed, 780 insertions(+), 752 deletions(-) diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h index e9b600a9267..54153cfde5d 100644 --- a/source/blender/gpu/GPU_buffers.h +++ b/source/blender/gpu/GPU_buffers.h @@ -51,10 +51,10 @@ struct GPUVertPointLink; struct PBVH; typedef struct GPUBuffer { - int size; /* in bytes */ - void *pointer; /* used with vertex arrays */ - unsigned int id; /* used with vertex buffer objects */ - bool use_vbo; /* true for VBOs, false for vertex arrays */ + int size; /* in bytes */ + void *pointer; /* used with vertex arrays */ + unsigned int id; /* used with vertex buffer objects */ + bool use_vbo; /* true for VBOs, false for vertex arrays */ } GPUBuffer; typedef struct GPUBufferMaterial { diff --git a/source/blender/gpu/GPU_compositing.h b/source/blender/gpu/GPU_compositing.h index 5589084705b..57d8c0631d6 100644 --- a/source/blender/gpu/GPU_compositing.h +++ b/source/blender/gpu/GPU_compositing.h @@ -52,7 +52,7 @@ enum eGPUFXFlags; typedef enum GPUFXShaderEffect { /* Screen space ambient occlusion shader */ - GPU_SHADER_FX_SSAO = 1, + GPU_SHADER_FX_SSAO = 1, /* depth of field passes. Yep, quite a complex effect */ GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE = 2, diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 57aa7f202b0..0c0ab1097d3 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -84,6 +84,7 @@ int GPU_get_material_alpha_blend(void); int GPU_set_tpage(struct MTFace *tface, int mipmap, int transp); void GPU_clear_tpage(bool force); + /* Lights * - returns how many lights were enabled * - this affects fixed functions materials and texface, not glsl */ diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 401711e84e5..c006540ddf4 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -72,26 +72,26 @@ void GPU_code_generate_glsl_lib(void); /* GPU Types */ typedef enum GPUDeviceType { - GPU_DEVICE_NVIDIA = (1<<0), - GPU_DEVICE_ATI = (1<<1), - GPU_DEVICE_INTEL = (1<<2), - GPU_DEVICE_SOFTWARE = (1<<3), - GPU_DEVICE_UNKNOWN = (1<<4), - GPU_DEVICE_ANY = (0xff) + GPU_DEVICE_NVIDIA = (1<<0), + GPU_DEVICE_ATI = (1<<1), + GPU_DEVICE_INTEL = (1<<2), + GPU_DEVICE_SOFTWARE = (1<<3), + GPU_DEVICE_UNKNOWN = (1<<4), + GPU_DEVICE_ANY = (0xff) } GPUDeviceType; typedef enum GPUOSType { - GPU_OS_WIN = (1<<8), - GPU_OS_MAC = (1<<9), - GPU_OS_UNIX = (1<<10), - GPU_OS_ANY = (0xff00) + GPU_OS_WIN = (1<<8), + GPU_OS_MAC = (1<<9), + GPU_OS_UNIX = (1<<10), + GPU_OS_ANY = (0xff00) } GPUOSType; typedef enum GPUDriverType { - GPU_DRIVER_OFFICIAL = (1<<16), + GPU_DRIVER_OFFICIAL = (1<<16), GPU_DRIVER_OPENSOURCE = (1<<17), - GPU_DRIVER_SOFTWARE = (1<<18), - GPU_DRIVER_ANY = (0xff0000) + GPU_DRIVER_SOFTWARE = (1<<18), + GPU_DRIVER_ANY = (0xff0000) } GPUDriverType; bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver); @@ -204,8 +204,8 @@ int GPU_shader_get_attribute(GPUShader *shader, const char *name); /* Builtin/Non-generated shaders */ typedef enum GPUBuiltinShader { - GPU_SHADER_VSM_STORE = (1<<0), - GPU_SHADER_SEP_GAUSSIAN_BLUR = (1<<1), + GPU_SHADER_VSM_STORE = (1<<0), + GPU_SHADER_SEP_GAUSSIAN_BLUR = (1<<1), } GPUBuiltinShader; GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader); @@ -215,7 +215,7 @@ void GPU_shader_free_builtin_shaders(void); /* Vertex attributes for shaders */ -#define GPU_MAX_ATTRIB 32 +#define GPU_MAX_ATTRIB 32 typedef struct GPUVertexAttribs { struct { diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 64ce936e64a..2d21b1aeb1d 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -92,7 +92,7 @@ typedef enum GPUBuiltin { GPU_VIEW_NORMAL = (1 << 5), GPU_OBCOLOR = (1 << 6), GPU_AUTO_BUMPSCALE = (1 << 7), - GPU_CAMERA_TEXCO_FACTORS = (1 << 8), + GPU_CAMERA_TEXCO_FACTORS = (1 << 8), } GPUBuiltin; typedef enum GPUOpenGLBuiltin { @@ -213,7 +213,7 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr); typedef enum GPUDataType { GPU_DATA_NONE = 0, - GPU_DATA_1I = 1, // 1 integer + GPU_DATA_1I = 1, /* 1 integer */ GPU_DATA_1F = 2, GPU_DATA_2F = 3, GPU_DATA_3F = 4, @@ -226,23 +226,23 @@ typedef enum GPUDataType { /* this structure gives information of each uniform found in the shader */ typedef struct GPUInputUniform { struct GPUInputUniform *next, *prev; - char varname[32]; /* name of uniform in shader */ - GPUDynamicType type; /* type of uniform, data format and calculation derive from it */ - GPUDataType datatype; /* type of uniform data */ - struct Object *lamp; /* when type=GPU_DYNAMIC_LAMP_... or GPU_DYNAMIC_SAMPLER_2DSHADOW */ - struct Image *image; /* when type=GPU_DYNAMIC_SAMPLER_2DIMAGE */ - int texnumber; /* when type=GPU_DYNAMIC_SAMPLER, texture number: 0.. */ - unsigned char *texpixels; /* for internally generated texture, pixel data in RGBA format */ - int texsize; /* size in pixel of the texture in texpixels buffer: for 2D textures, this is S and T size (square texture) */ + char varname[32]; /* name of uniform in shader */ + GPUDynamicType type; /* type of uniform, data format and calculation derive from it */ + GPUDataType datatype; /* type of uniform data */ + struct Object *lamp; /* when type=GPU_DYNAMIC_LAMP_... or GPU_DYNAMIC_SAMPLER_2DSHADOW */ + struct Image *image; /* when type=GPU_DYNAMIC_SAMPLER_2DIMAGE */ + int texnumber; /* when type=GPU_DYNAMIC_SAMPLER, texture number: 0.. */ + unsigned char *texpixels; /* for internally generated texture, pixel data in RGBA format */ + int texsize; /* size in pixel of the texture in texpixels buffer: for 2D textures, this is S and T size (square texture) */ } GPUInputUniform; typedef struct GPUInputAttribute { struct GPUInputAttribute *next, *prev; - char varname[32]; /* name of attribute in shader */ - int type; /* from CustomData.type, data type derives from it */ - GPUDataType datatype; /* type of attribute data */ - const char *name; /* layer name */ - int number; /* generic attribute number */ + char varname[32]; /* name of attribute in shader */ + int type; /* from CustomData.type, data type derives from it */ + GPUDataType datatype; /* type of attribute data */ + const char *name; /* layer name */ + int number; /* generic attribute number */ } GPUInputAttribute; typedef struct GPUShaderExport { diff --git a/source/blender/gpu/GPU_simple_shader.h b/source/blender/gpu/GPU_simple_shader.h index c8fb1f09b04..239296209b4 100644 --- a/source/blender/gpu/GPU_simple_shader.h +++ b/source/blender/gpu/GPU_simple_shader.h @@ -42,11 +42,11 @@ extern "C" { typedef enum GPUSimpleShaderOption { GPU_SHADER_OVERRIDE_DIFFUSE = (1<<0), /* replace diffuse with glcolor */ - GPU_SHADER_LIGHTING = (1<<1), /* use lighting */ - GPU_SHADER_TWO_SIDED = (1<<2), /* flip normals towards viewer */ - GPU_SHADER_TEXTURE_2D = (1<<3), /* use 2D texture to replace diffuse color */ + GPU_SHADER_LIGHTING = (1<<1), /* use lighting */ + GPU_SHADER_TWO_SIDED = (1<<2), /* flip normals towards viewer */ + GPU_SHADER_TEXTURE_2D = (1<<3), /* use 2D texture to replace diffuse color */ - GPU_SHADER_SOLID_LIGHTING = (1<<4), /* use faster lighting (set automatically) */ + GPU_SHADER_SOLID_LIGHTING = (1<<4), /* use faster lighting (set automatically) */ GPU_SHADER_OPTIONS_NUM = 5, GPU_SHADER_OPTION_COMBINATIONS = (1<vert_points = MEM_mallocN(sizeof(GPUVertPointLink) * gdo->totvert, "GPUDrawObject.vert_points"); @@ -1007,7 +1008,7 @@ const GPUBufferTypeSettings gpu_buffer_type_settings[] = { {GPU_buffer_copy_normal, GL_ARRAY_BUFFER_ARB, 3}, {GPU_buffer_copy_mcol, GL_ARRAY_BUFFER_ARB, 3}, {GPU_buffer_copy_uv, GL_ARRAY_BUFFER_ARB, 2}, - {GPU_buffer_copy_uv_texpaint, GL_ARRAY_BUFFER_ARB, 4}, + {GPU_buffer_copy_uv_texpaint, GL_ARRAY_BUFFER_ARB, 4}, {GPU_buffer_copy_edge, GL_ELEMENT_ARRAY_BUFFER_ARB, 2}, {GPU_buffer_copy_uvedge, GL_ELEMENT_ARRAY_BUFFER_ARB, 4} }; @@ -1498,6 +1499,7 @@ struct GPU_PBVH_Buffers { bool use_matcaps; float diffuse_color[4]; }; + typedef enum { VBO_ENABLED, VBO_DISABLED @@ -1577,8 +1579,8 @@ static void gpu_color_from_mask_quad_set(const CCGKey *key, } void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert, - int *vert_indices, int totvert, const float *vmask, - int (*face_vert_indices)[4], bool show_diffuse_color) + int *vert_indices, int totvert, const float *vmask, + int (*face_vert_indices)[4], bool show_diffuse_color) { VertexBufferFormat *vert_data; int i, j, k; @@ -1715,9 +1717,9 @@ void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert, } GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(int (*face_vert_indices)[4], - MFace *mface, MVert *mvert, - int *face_indices, - int totface) + MFace *mface, MVert *mvert, + int *face_indices, + int totface) { GPU_PBVH_Buffers *buffers; unsigned short *tri_data; @@ -1807,8 +1809,8 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(int (*face_vert_indices)[4], } void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids, - const DMFlagMat *grid_flag_mats, int *grid_indices, - int totgrid, const CCGKey *key, bool show_diffuse_color) + const DMFlagMat *grid_flag_mats, int *grid_indices, + int totgrid, const CCGKey *key, bool show_diffuse_color) { VertexBufferFormat *vert_data; int i, j, k, x, y; @@ -1921,51 +1923,51 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids, /* Build the element array buffer of grid indices using either * unsigned shorts or unsigned ints. */ #define FILL_QUAD_BUFFER(type_, tot_quad_, buffer_) \ - { \ - type_ *tri_data; \ - int offset = 0; \ - int i, j, k; \ - \ - glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, \ - sizeof(type_) * (tot_quad_) * 6, NULL, \ - GL_STATIC_DRAW_ARB); \ - \ - /* Fill the buffer */ \ - tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, \ - GL_WRITE_ONLY_ARB); \ - if (tri_data) { \ - for (i = 0; i < totgrid; ++i) { \ - BLI_bitmap *gh = NULL; \ - if (grid_hidden) \ - gh = grid_hidden[(grid_indices)[i]]; \ - \ - for (j = 0; j < gridsize - 1; ++j) { \ - for (k = 0; k < gridsize - 1; ++k) { \ - /* Skip hidden grid face */ \ - if (gh && \ - paint_is_grid_face_hidden(gh, \ - gridsize, k, j)) \ - continue; \ - \ - *(tri_data++) = offset + j * gridsize + k + 1; \ - *(tri_data++) = offset + j * gridsize + k; \ - *(tri_data++) = offset + (j + 1) * gridsize + k; \ - \ - *(tri_data++) = offset + (j + 1) * gridsize + k + 1; \ - *(tri_data++) = offset + j * gridsize + k + 1; \ - *(tri_data++) = offset + (j + 1) * gridsize + k; \ - } \ - } \ - \ - offset += gridsize * gridsize; \ - } \ - glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); \ - } \ - else { \ - glDeleteBuffersARB(1, &(buffer_)); \ - (buffer_) = 0; \ - } \ - } (void)0 + { \ + type_ *tri_data; \ + int offset = 0; \ + int i, j, k; \ + \ + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, \ + sizeof(type_) * (tot_quad_) * 6, NULL, \ + GL_STATIC_DRAW_ARB); \ + \ + /* Fill the buffer */ \ + tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, \ + GL_WRITE_ONLY_ARB); \ + if (tri_data) { \ + for (i = 0; i < totgrid; ++i) { \ + BLI_bitmap *gh = NULL; \ + if (grid_hidden) \ + gh = grid_hidden[(grid_indices)[i]]; \ + \ + for (j = 0; j < gridsize - 1; ++j) { \ + for (k = 0; k < gridsize - 1; ++k) { \ + /* Skip hidden grid face */ \ + if (gh && \ + paint_is_grid_face_hidden(gh, \ + gridsize, k, j)) \ + continue; \ + \ + *(tri_data++) = offset + j * gridsize + k + 1; \ + *(tri_data++) = offset + j * gridsize + k; \ + *(tri_data++) = offset + (j + 1) * gridsize + k; \ + \ + *(tri_data++) = offset + (j + 1) * gridsize + k + 1; \ + *(tri_data++) = offset + j * gridsize + k + 1; \ + *(tri_data++) = offset + (j + 1) * gridsize + k; \ + } \ + } \ + \ + offset += gridsize * gridsize; \ + } \ + glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); \ + } \ + else { \ + glDeleteBuffersARB(1, &(buffer_)); \ + (buffer_) = 0; \ + } \ + } (void)0 /* end FILL_QUAD_BUFFER */ static GLuint gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *totquad) @@ -2021,7 +2023,7 @@ static GLuint gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *to } GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid, - BLI_bitmap **grid_hidden, int gridsize) + BLI_bitmap **grid_hidden, int gridsize) { GPU_PBVH_Buffers *buffers; int totquad; @@ -2103,7 +2105,6 @@ static void gpu_bmesh_vert_to_buffer_copy(BMVert *v, BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset), diffuse_color, vd->color); - /* Assign index for use in the triangle index buffer */ /* note: caller must set: bm->elem_index_dirty |= BM_VERT; */ @@ -2153,11 +2154,11 @@ static int gpu_bmesh_face_visible_count(GSet *bm_faces) /* Creates a vertex buffer (coordinate, normal, color) and, if smooth * shading, an element index buffer. */ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, - BMesh *bm, - GSet *bm_faces, - GSet *bm_unique_verts, - GSet *bm_other_verts, - bool show_diffuse_color) + BMesh *bm, + GSet *bm_faces, + GSet *bm_unique_verts, + GSet *bm_other_verts, + bool show_diffuse_color) { VertexBufferFormat *vert_data; void *tri_data; @@ -2204,8 +2205,8 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, /* Initialize vertex buffer */ glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); glBufferDataARB(GL_ARRAY_BUFFER_ARB, - sizeof(VertexBufferFormat) * totvert, - NULL, GL_STATIC_DRAW_ARB); + sizeof(VertexBufferFormat) * totvert, + NULL, GL_STATIC_DRAW_ARB); /* Fill vertex buffer */ vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); @@ -2246,7 +2247,9 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, float fmask = 0; int i; - // BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 3); +#if 0 + BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 3); +#endif BM_face_as_array_vert_tri(f, v); /* Average mask value */ @@ -2666,7 +2669,7 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces, GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color); } else if (buffers->use_bmesh) { - /* due to dynamc nature of dyntopo, only get first material */ + /* due to dynamic nature of dyntopo, only get first material */ if (BLI_gset_size(bm_faces) > 0) { GSetIterator gs_iter; BMFace *f; @@ -2717,7 +2720,7 @@ static void gpu_pbvh_buffer_free_intern(GLuint id) if (pool->maxpbvhsize == pool->totpbvhbufids) { pool->maxpbvhsize += MAX_FREE_GPU_BUFF_IDS; pool->pbvhbufids = MEM_reallocN(pool->pbvhbufids, - sizeof(*pool->pbvhbufids) * pool->maxpbvhsize); + sizeof(*pool->pbvhbufids) * pool->maxpbvhsize); } /* insert the buffer into the beginning of the pool */ @@ -2742,33 +2745,33 @@ void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers) void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf) { const float quads[4][4][3] = { - { - {min[0], min[1], min[2]}, - {max[0], min[1], min[2]}, - {max[0], min[1], max[2]}, - {min[0], min[1], max[2]} - }, - - { - {min[0], min[1], min[2]}, - {min[0], max[1], min[2]}, - {min[0], max[1], max[2]}, - {min[0], min[1], max[2]} - }, - - { - {max[0], max[1], min[2]}, - {max[0], min[1], min[2]}, - {max[0], min[1], max[2]}, - {max[0], max[1], max[2]} - }, - - { - {max[0], max[1], min[2]}, - {min[0], max[1], min[2]}, - {min[0], max[1], max[2]}, - {max[0], max[1], max[2]} - }, + { + {min[0], min[1], min[2]}, + {max[0], min[1], min[2]}, + {max[0], min[1], max[2]}, + {min[0], min[1], max[2]} + }, + + { + {min[0], min[1], min[2]}, + {min[0], max[1], min[2]}, + {min[0], max[1], max[2]}, + {min[0], min[1], max[2]} + }, + + { + {max[0], max[1], min[2]}, + {max[0], min[1], min[2]}, + {max[0], min[1], max[2]}, + {max[0], max[1], max[2]} + }, + + { + {max[0], max[1], min[2]}, + {min[0], max[1], min[2]}, + {min[0], max[1], max[2]}, + {max[0], max[1], max[2]} + }, }; if (leaf) diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 113ed8e341c..e9bc4002032 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -46,7 +46,7 @@ #include "GPU_material.h" #include "GPU_extensions.h" -#include "BLI_sys_types.h" // for intptr_t support +#include "BLI_sys_types.h" /* for intptr_t support */ #include "gpu_codegen.h" @@ -90,9 +90,11 @@ static const char *GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4", /* GLSL code parsing for finding function definitions. * These are stored in a hash for lookup when creating a material. */ -static GHash *FUNCTION_HASH= NULL; -/* static char *FUNCTION_PROTOTYPES= NULL; - * static GPUShader *FUNCTION_LIB= NULL;*/ +static GHash *FUNCTION_HASH = NULL; +#if 0 +static char *FUNCTION_PROTOTYPES = NULL; +static GPUShader *FUNCTION_LIB = NULL; +#endif static int gpu_str_prefix(const char *str, const char *prefix) { @@ -117,7 +119,7 @@ static char *gpu_str_skip_token(char *str, char *token, int max) break; else { if (token && len < max-1) { - *token= *str; + *token = *str; token++; len++; } @@ -126,7 +128,7 @@ static char *gpu_str_skip_token(char *str, char *token, int max) } if (token) - *token= '\0'; + *token = '\0'; /* skip the next special characters: * note the missing ')' */ @@ -165,10 +167,10 @@ static void gpu_parse_functions_string(GHash *hash, char *code) code = gpu_str_skip_token(code, NULL, 0); /* test for type */ - type= GPU_NONE; - for (i=1; i<=16; i++) { + type = GPU_NONE; + for (i = 1; i <= 16; i++) { if (GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) { - type= i; + type = i; break; } } @@ -220,7 +222,7 @@ static char *gpu_generate_function_prototyps(GHash *hash) function = BLI_ghashIterator_getValue(ghi); BLI_dynstr_appendf(ds, "void %s(", name); - for (a=0; atotparam; a++) { + for (a = 0; a < function->totparam; a++) { if (function->paramqual[a] == FUNCTION_QUAL_OUT) BLI_dynstr_append(ds, "out "); else if (function->paramqual[a] == FUNCTION_QUAL_INOUT) @@ -232,9 +234,10 @@ static char *gpu_generate_function_prototyps(GHash *hash) BLI_dynstr_append(ds, "sampler2DShadow"); else BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]); - - //BLI_dynstr_appendf(ds, " param%d", a); - +# if 0 + BLI_dynstr_appendf(ds, " param%d", a); +# endif + if (a != function->totparam-1) BLI_dynstr_append(ds, ", "); } @@ -267,7 +270,7 @@ void gpu_codegen_init(void) void gpu_codegen_exit(void) { - extern Material defmaterial; // render module abuse... + extern Material defmaterial; /* render module abuse... */ if (defmaterial.gpumaterial.first) GPU_material_free(&defmaterial.gpumaterial); @@ -284,14 +287,16 @@ void gpu_codegen_exit(void) glsl_material_library = NULL; } - /*if (FUNCTION_PROTOTYPES) { +#if 0 + if (FUNCTION_PROTOTYPES) { MEM_freeN(FUNCTION_PROTOTYPES); FUNCTION_PROTOTYPES = NULL; - }*/ - /*if (FUNCTION_LIB) { + } + if (FUNCTION_LIB) { GPU_shader_free(FUNCTION_LIB); FUNCTION_LIB = NULL; - }*/ + } +#endif } /* GLSL code generation */ @@ -345,9 +350,9 @@ static void codegen_print_datatype(DynStr *ds, const GPUType type, float *data) BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]); - for (i=0; ifirst; node; node=node->next) { - for (input=node->inputs.first; input; input=input->next) { + for (node = nodes->first; node; node = node->next) { + for (input = node->inputs.first; input; input = input->next) { /* set id for unique names of uniform variables */ input->id = id++; input->bindtex = false; @@ -463,7 +468,7 @@ static void codegen_set_unique_ids(ListBase *nodes) } } - for (output=node->outputs.first; output; output=output->next) + for (output = node->outputs.first; output; output = output->next) /* set id for unique names of tmp variables storing output */ output->id = id++; } @@ -480,8 +485,8 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes) int builtins = 0; /* print uniforms */ - for (node=nodes->first; node; node=node->next) { - for (input=node->inputs.first; input; input=input->next) { + for (node = nodes->first; node; node = node->next) { + for (input = node->inputs.first; input; input = input->next) { if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) { /* create exactly one sampler for each texture */ if (codegen_input_has_texture(input) && input->bindtex) @@ -537,9 +542,9 @@ static void codegen_declare_tmps(DynStr *ds, ListBase *nodes) GPUInput *input; GPUOutput *output; - for (node=nodes->first; node; node=node->next) { + for (node = nodes->first; node; node = node->next) { /* load pixels from textures */ - for (input=node->inputs.first; input; input=input->next) { + for (input = node->inputs.first; input; input = input->next) { if (input->source == GPU_SOURCE_TEX_PIXEL) { if (codegen_input_has_texture(input) && input->definetex) { BLI_dynstr_appendf(ds, "\tvec4 tex%d = texture2D(", input->texid); @@ -550,7 +555,7 @@ static void codegen_declare_tmps(DynStr *ds, ListBase *nodes) } /* declare temporary variables for node output storage */ - for (output=node->outputs.first; output; output=output->next) + for (output = node->outputs.first; output; output = output->next) BLI_dynstr_appendf(ds, "\t%s tmp%d;\n", GPU_DATATYPE_STR[output->type], output->id); } @@ -564,10 +569,10 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final GPUInput *input; GPUOutput *output; - for (node=nodes->first; node; node=node->next) { + for (node = nodes->first; node; node = node->next) { BLI_dynstr_appendf(ds, "\t%s(", node->name); - for (input=node->inputs.first; input; input=input->next) { + for (input = node->inputs.first; input; input = input->next) { if (input->source == GPU_SOURCE_TEX) { BLI_dynstr_appendf(ds, "samp%d", input->texid); if (input->link) @@ -602,7 +607,7 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final BLI_dynstr_append(ds, ", "); } - for (output=node->outputs.first; output; output=output->next) { + for (output = node->outputs.first; output; output = output->next) { BLI_dynstr_appendf(ds, "tmp%d", output->id); if (output->next) BLI_dynstr_append(ds, ", "); @@ -622,13 +627,17 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output) char *code; int builtins; - /*BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);*/ +#if 0 + BLI_dynstr_append(ds, FUNCTION_PROTOTYPES); +#endif codegen_set_unique_ids(nodes); builtins = codegen_print_uniforms_functions(ds, nodes); - //if (G.debug & G_DEBUG) - // BLI_dynstr_appendf(ds, "/* %s */\n", name); +#if 0 + if (G.debug & G_DEBUG) + BLI_dynstr_appendf(ds, "/* %s */\n", name); +#endif BLI_dynstr_append(ds, "void main(void)\n"); BLI_dynstr_append(ds, "{\n"); @@ -645,7 +654,9 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output) code = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); - //if (G.debug & G_DEBUG) printf("%s\n", code); +#if 0 + if (G.debug & G_DEBUG) printf("%s\n", code); +#endif return code; } @@ -658,8 +669,8 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type) char *code; char *vertcode; - for (node=nodes->first; node; node=node->next) { - for (input=node->inputs.first; input; input=input->next) { + for (node = nodes->first; node; node = node->next) { + for (input = node->inputs.first; input; input = input->next) { if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { BLI_dynstr_appendf(ds, "attribute %s att%d;\n", GPU_DATATYPE_STR[input->type], input->attribid); @@ -685,8 +696,8 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type) BLI_dynstr_append(ds, vertcode); - for (node=nodes->first; node; node=node->next) - for (input=node->inputs.first; input; input=input->next) + for (node = nodes->first; node; node = node->next) + for (input = node->inputs.first; input; input = input->next) if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { if (input->attribtype == CD_TANGENT) { /* silly exception */ BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize(gl_NormalMatrix * att%d.xyz);\n", input->attribid, input->attribid); @@ -714,7 +725,9 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type) BLI_dynstr_free(ds); - //if (G.debug & G_DEBUG) printf("%s\n", code); +#if 0 + if (G.debug & G_DEBUG) printf("%s\n", code); +#endif return code; } @@ -760,9 +773,9 @@ static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes) GPU_shader_bind(shader); - for (node=nodes->first; node; node=node->next) { + for (node = nodes->first; node; node = node->next) { z = 0; - for (input=node->inputs.first; input; input=next, z++) { + for (input = node->inputs.first; input; input = next, z++) { next = input->next; /* attributes don't need to be bound, they already have @@ -815,7 +828,7 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap) GPU_shader_bind(shader); /* now bind the textures */ - for (input=inputs->first; input; input=input->next) { + for (input = inputs->first; input; input = input->next) { if (input->ima) input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->image_isdata, time, mipmap); else if (input->prv) @@ -839,7 +852,7 @@ void GPU_pass_update_uniforms(GPUPass *pass) return; /* pass dynamic inputs to opengl, others were removed */ - for (input=inputs->first; input; input=input->next) + for (input = inputs->first; input; input = input->next) if (!(input->ima || input->tex || input->prv)) GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1, input->dynamicvec); @@ -854,7 +867,7 @@ void GPU_pass_unbind(GPUPass *pass) if (!shader) return; - for (input=inputs->first; input; input=input->next) { + for (input = inputs->first; input; input = input->next) { if (input->tex && input->bindtex) GPU_texture_unbind(input->tex); @@ -896,7 +909,7 @@ static GPUNode *GPU_node_begin(const char *name) { GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode"); - node->name= name; + node->name = name; return node; } @@ -965,7 +978,9 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType input->source = GPU_SOURCE_TEX; input->textype = type; - //input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL); +#if 0 + input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL); +#endif input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, GPU_HDR_NONE, NULL); input->textarget = GL_TEXTURE_2D; @@ -1004,9 +1019,9 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType memcpy(input->vec, link->ptr1, type*sizeof(float)); if (link->dynamic) { - input->dynamicvec= link->ptr1; - input->dynamictype= link->dynamictype; - input->dynamicdata= link->ptr2; + input->dynamicvec = link->ptr1; + input->dynamictype = link->dynamictype; + input->dynamicdata = link->ptr2; } MEM_freeN(link); } @@ -1040,7 +1055,7 @@ static void gpu_node_output(GPUNode *node, const GPUType type, GPUNodeLink **lin output->link->type = type; output->link->output = output; - /* note: the caller owns the reference to the linkfer, GPUOutput + /* note: the caller owns the reference to the link, GPUOutput * merely points to it, and if the node is destroyed it will * set that pointer to NULL */ } @@ -1052,7 +1067,7 @@ static void gpu_inputs_free(ListBase *inputs) { GPUInput *input; - for (input=inputs->first; input; input=input->next) { + for (input = inputs->first; input; input = input->next) { if (input->link) gpu_node_link_free(input->link); else if (input->tex && !input->dynamictex) @@ -1068,7 +1083,7 @@ static void gpu_node_free(GPUNode *node) gpu_inputs_free(&node->inputs); - for (output=node->outputs.first; output; output=output->next) + for (output = node->outputs.first; output; output = output->next) if (output->link) { output->link->output = NULL; gpu_node_link_free(output->link); @@ -1100,10 +1115,10 @@ static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *a memset(attribs, 0, sizeof(*attribs)); - for (node=nodes->first; node; node=node->next) { - for (input=node->inputs.first; input; input=input->next) { + for (node = nodes->first; node; node = node->next) { + for (input = node->inputs.first; input; input = input->next) { if (input->source == GPU_SOURCE_ATTRIB) { - for (a=0; atotlayer; a++) { + for (a = 0; a < attribs->totlayer; a++) { if (attribs->layer[a].type == input->attribtype && STREQ(attribs->layer[a].name, input->attribname)) { @@ -1135,10 +1150,10 @@ static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin) GPUNode *node; GPUInput *input; - *builtin= 0; + *builtin = 0; - for (node=nodes->first; node; node=node->next) - for (input=node->inputs.first; input; input=input->next) + for (node = nodes->first; node; node = node->next) + for (input = node->inputs.first; input; input = input->next) if (input->source == GPU_SOURCE_BUILTIN) *builtin |= input->builtin; } @@ -1149,8 +1164,8 @@ GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name) { GPUNodeLink *link = GPU_node_link_create(); - link->attribtype= type; - link->attribname= name; + link->attribtype = type; + link->attribname = name; return link; } @@ -1159,8 +1174,8 @@ GPUNodeLink *GPU_uniform(float *num) { GPUNodeLink *link = GPU_node_link_create(); - link->ptr1= num; - link->ptr2= NULL; + link->ptr1 = num; + link->ptr2 = NULL; return link; } @@ -1169,9 +1184,9 @@ GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *d { GPUNodeLink *link = GPU_node_link_create(); - link->ptr1= num; - link->ptr2= data; - link->dynamic= true; + link->ptr1 = num; + link->ptr2 = data; + link->dynamic = true; link->dynamictype = dynamictype; @@ -1194,8 +1209,8 @@ GPUNodeLink *GPU_image_preview(PreviewImage *prv) { GPUNodeLink *link = GPU_node_link_create(); - link->image= GPU_NODE_LINK_IMAGE_PREVIEW; - link->ptr1= prv; + link->image = GPU_NODE_LINK_IMAGE_PREVIEW; + link->ptr1 = prv; return link; } @@ -1207,7 +1222,7 @@ GPUNodeLink *GPU_texture(int size, float *pixels) link->texture = true; link->texturesize = size; - link->ptr1= pixels; + link->ptr1 = pixels; return link; } @@ -1259,13 +1274,13 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...) node = GPU_node_begin(name); va_start(params, name); - for (i=0; itotparam; i++) { + for (i = 0; itotparam; i++) { if (function->paramqual[i] != FUNCTION_QUAL_IN) { - linkptr= va_arg(params, GPUNodeLink**); + linkptr = va_arg(params, GPUNodeLink**); gpu_node_output(node, function->paramtype[i], linkptr); } else { - link= va_arg(params, GPUNodeLink*); + link = va_arg(params, GPUNodeLink*); gpu_node_input_link(node, link, function->paramtype[i]); } } @@ -1309,10 +1324,10 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod } va_start(params, out); - for (i=0; itotparam; i++) { + for (i = 0; itotparam; i++) { if (function->paramqual[i] != FUNCTION_QUAL_IN) { if (totout == 0) { - linkptr= va_arg(params, GPUNodeLink**); + linkptr = va_arg(params, GPUNodeLink**); gpu_node_output(node, function->paramtype[i], linkptr); } else @@ -1320,7 +1335,7 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod } else { if (totin == 0) { - link= va_arg(params, GPUNodeLink*); + link = va_arg(params, GPUNodeLink*); if (link->socket) gpu_node_input_socket(node, link->socket); else @@ -1373,7 +1388,7 @@ static void gpu_nodes_tag(GPUNodeLink *link) return; node->tag = true; - for (input=node->inputs.first; input; input=input->next) + for (input = node->inputs.first; input; input = input->next) if (input->link) gpu_nodes_tag(input->link); } @@ -1382,12 +1397,12 @@ static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink) { GPUNode *node, *next; - for (node=nodes->first; node; node=node->next) + for (node = nodes->first; node; node = node->next) node->tag = false; gpu_nodes_tag(outlink); - for (node=nodes->first; node; node=next) { + for (node = nodes->first; node; node = next) { next = node->next; if (!node->tag) { @@ -1405,10 +1420,12 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUPass *pass; char *vertexcode, *fragmentcode; - /*if (!FUNCTION_LIB) { +#if 0 + if (!FUNCTION_LIB) { GPU_nodes_free(nodes); return NULL; - }*/ + } +#endif /* prune unused nodes */ gpu_nodes_prune(nodes, outlink); diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index a6da5e018fd..89bd3a8ee99 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -113,9 +113,9 @@ typedef struct GPUOutput { struct GPUOutput *next, *prev; GPUNode *node; - GPUType type; /* data type = length of vector/matrix */ - GPUNodeLink *link; /* output link */ - int id; /* unique id as created by code generator */ + GPUType type; /* data type = length of vector/matrix */ + GPUNodeLink *link; /* output link */ + int id; /* unique id as created by code generator */ } GPUOutput; typedef struct GPUInput { @@ -123,35 +123,35 @@ typedef struct GPUInput { GPUNode *node; - GPUType type; /* datatype */ - GPUDataSource source; /* data source */ - - int id; /* unique id as created by code generator */ - int texid; /* number for multitexture, starting from zero */ - int attribid; /* id for vertex attributes */ - bool bindtex; /* input is responsible for binding the texture? */ - bool definetex; /* input is responsible for defining the pixel? */ - int textarget; /* GL texture target, e.g. GL_TEXTURE_2D */ - GPUType textype; /* datatype */ - - struct Image *ima; /* image */ - struct ImageUser *iuser;/* image user */ - struct PreviewImage *prv; /* preview images & icons */ - bool image_isdata; /* image does not contain color data */ - float *dynamicvec; /* vector data in case it is dynamic */ - GPUDynamicType dynamictype; /* origin of the dynamic uniform */ - void *dynamicdata; /* data source of the dynamic uniform */ - struct GPUTexture *tex; /* input texture, only set at runtime */ - int shaderloc; /* id from opengl */ - char shadername[32]; /* name in shader */ - - float vec[16]; /* vector data */ + GPUType type; /* datatype */ + GPUDataSource source; /* data source */ + + int id; /* unique id as created by code generator */ + int texid; /* number for multitexture, starting from zero */ + int attribid; /* id for vertex attributes */ + bool bindtex; /* input is responsible for binding the texture? */ + bool definetex; /* input is responsible for defining the pixel? */ + int textarget; /* GL texture target, e.g. GL_TEXTURE_2D */ + GPUType textype; /* datatype */ + + struct Image *ima; /* image */ + struct ImageUser *iuser; /* image user */ + struct PreviewImage *prv; /* preview images & icons */ + bool image_isdata; /* image does not contain color data */ + float *dynamicvec; /* vector data in case it is dynamic */ + GPUDynamicType dynamictype; /* origin of the dynamic uniform */ + void *dynamicdata; /* data source of the dynamic uniform */ + struct GPUTexture *tex; /* input texture, only set at runtime */ + int shaderloc; /* id from opengl */ + char shadername[32]; /* name in shader */ + + float vec[16]; /* vector data */ GPUNodeLink *link; - bool dynamictex; /* dynamic? */ - CustomDataType attribtype; /* attribute type */ - char attribname[MAX_CUSTOMDATA_LAYER_NAME]; /* attribute name */ - int attribfirst; /* this is the first one that is bound */ - GPUBuiltin builtin; /* builtin uniform */ + bool dynamictex; /* dynamic? */ + CustomDataType attribtype; /* attribute type */ + char attribname[MAX_CUSTOMDATA_LAYER_NAME]; /* attribute name */ + int attribfirst; /* this is the first one that is bound */ + GPUBuiltin builtin; /* builtin uniform */ GPUOpenGLBuiltin oglbuiltin; /* opengl built in varying */ } GPUInput; @@ -170,8 +170,8 @@ struct GPUPass { typedef struct GPUPass GPUPass; GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink, - struct GPUVertexAttribs *attribs, int *builtin, - const GPUMatType type, const char *name); + struct GPUVertexAttribs *attribs, int *builtin, + const GPUMatType type, const char *name); struct GPUShader *GPU_pass_shader(GPUPass *pass); diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index ed8af17b34c..6a7805bb614 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -469,7 +469,7 @@ bool GPU_fx_compositor_initialize_passes( } } - fx->dof_high_quality = dof_high_quality && GPU_geometry_shader_support() && GPU_instanced_drawing_support(); + fx->dof_high_quality = dof_high_quality && GPU_geometry_shader_support() && GPU_instanced_drawing_support(); } else { /* cleanup unnecessary buffers */ @@ -478,7 +478,7 @@ bool GPU_fx_compositor_initialize_passes( /* we need to pass data between shader stages, allocate an extra color buffer */ if (num_passes > 1) { - if(!fx->color_buffer_sec) { + if (!fx->color_buffer_sec) { if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) { printf(".256%s\n", err_out); cleanup_fx_gl_data(fx, true); @@ -497,13 +497,13 @@ bool GPU_fx_compositor_initialize_passes( /* bind the buffers */ /* first depth buffer, because system assumes read/write buffers */ - if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, err_out)) + if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, err_out)) printf("%.256s\n", err_out); - if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, err_out)) + if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, err_out)) printf("%.256s\n", err_out); - if(!GPU_framebuffer_check_valid(fx->gbuffer, err_out)) + if (!GPU_framebuffer_check_valid(fx->gbuffer, err_out)) printf("%.256s\n", err_out); GPU_texture_bind_as_framebuffer(fx->color_buffer); @@ -573,7 +573,7 @@ void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray) GPU_framebuffer_texture_detach(fx->depth_buffer); /* first depth buffer, because system assumes read/write buffers */ - if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer_xray, 0, err_out)) + if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer_xray, 0, err_out)) printf("%.256s\n", err_out); } diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c index 627aa41dca5..a0dde9c8f3b 100644 --- a/source/blender/gpu/intern/gpu_debug.c +++ b/source/blender/gpu/intern/gpu_debug.c @@ -45,7 +45,7 @@ static const char* gpu_gl_error_symbol(GLenum err) { - switch(err) { + switch (err) { CASE_CODE_RETURN_STR(GL_NO_ERROR) CASE_CODE_RETURN_STR(GL_INVALID_ENUM) CASE_CODE_RETURN_STR(GL_INVALID_VALUE) @@ -109,7 +109,7 @@ static bool gpu_report_gl_errors(const char *file, int line, const char *str) const char* gpuErrorString(GLenum err) { - switch(err) { + switch (err) { case GL_NO_ERROR: return "No Error"; diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 722a7bdf114..7f3a9981a5c 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -88,7 +88,7 @@ extern Material defmaterial; /* from material.c */ static void gpu_mcol(unsigned int ucol) { /* mcol order is swapped */ - const char *cp= (char *)&ucol; + const char *cp = (char *)&ucol; glColor3ub(cp[3], cp[2], cp[1]); } @@ -96,7 +96,7 @@ void GPU_render_text(MTFace *tface, int mode, const char *textstr, int textlen, unsigned int *col, float *v1, float *v2, float *v3, float *v4, int glattrib) { - if ((mode & GEMAT_TEXT) && (textlen>0) && tface->tpage) { + if ((mode & GEMAT_TEXT) && (textlen > 0) && tface->tpage) { Image* ima = (Image *)tface->tpage; ImBuf *first_ibuf; const size_t textlen_st = textlen; @@ -105,7 +105,7 @@ void GPU_render_text(MTFace *tface, int mode, float advance_tab; /* multiline */ - float line_start= 0.0f, line_height; + float line_start = 0.0f, line_height; if (v4) line_height = max_ffff(v1[1], v2[1], v3[1], v4[2]) - min_ffff(v1[1], v2[1], v3[1], v4[2]); @@ -128,23 +128,23 @@ void GPU_render_text(MTFace *tface, int mode, matrixGlyph(first_ibuf, ' ', ¢erx, ¢ery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); - advance_tab= advance * 4; /* tab width could also be an option */ + advance_tab = advance * 4; /* tab width could also be an option */ for (index = 0; index < textlen_st; ) { unsigned int character; float uv[4][2]; - // lets calculate offset stuff + /* lets calculate offset stuff */ character = BLI_str_utf8_as_unicode_and_size_safe(textstr + index, &index); - if (character=='\n') { - glTranslatef(line_start, -line_height, 0.0); + if (character == '\n') { + glTranslatef(line_start, -line_height, 0.0f); line_start = 0.0f; continue; } - else if (character=='\t') { - glTranslatef(advance_tab, 0.0, 0.0); + else if (character == '\t') { + glTranslatef(advance_tab, 0.0f, 0.0f); line_start -= advance_tab; /* so we can go back to the start of the line */ continue; @@ -154,8 +154,8 @@ void GPU_render_text(MTFace *tface, int mode, character = '?'; } - // space starts at offset 1 - // character = character - ' ' + 1; + /* space starts at offset 1 */ + /* character = character - ' ' + 1; */ matrixGlyph(first_ibuf, character, & centerx, ¢ery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); @@ -193,7 +193,7 @@ void GPU_render_text(MTFace *tface, int mode, } glEnd(); - glTranslatef(advance, 0.0, 0.0); + glTranslatef(advance, 0.0f, 0.0f); line_start -= advance; /* so we can go back to the start of the line */ } glPopMatrix(); @@ -246,7 +246,7 @@ static struct GPUTextureState { float anisotropic; int gpu_mipmap; MTFace *lasttface; -} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, 0, -1, 1.f, 0, NULL}; +} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, 0, -1, 1.0f, 0, NULL}; /* Mipmap settings */ @@ -353,41 +353,41 @@ static void gpu_make_repbind(Image *ima) ImBuf *ibuf; ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - if (ibuf==NULL) + if (ibuf == NULL) return; if (ima->repbind) { glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); MEM_freeN(ima->repbind); - ima->repbind= NULL; + ima->repbind = NULL; ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; } - ima->totbind= ima->xrep*ima->yrep; + ima->totbind = ima->xrep*ima->yrep; if (ima->totbind>1) - ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind"); + ima->repbind = MEM_callocN(sizeof(int) * ima->totbind, "repbind"); BKE_image_release_ibuf(ima, ibuf, NULL); } void GPU_clear_tpage(bool force) { - if (GTS.lasttface==NULL && !force) + if (GTS.lasttface == NULL && !force) return; - GTS.lasttface= NULL; - GTS.curtile= 0; - GTS.curima= NULL; - if (GTS.curtilemode!=0) { + GTS.lasttface = NULL; + GTS.curtile = 0; + GTS.curima = NULL; + if (GTS.curtilemode != 0) { glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); } - GTS.curtilemode= 0; - GTS.curtileXRep=0; - GTS.curtileYRep=0; - GTS.alphablend= -1; + GTS.curtilemode = 0; + GTS.curtileXRep = 0; + GTS.curtileYRep = 0; + GTS.alphablend = -1; glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); @@ -403,7 +403,7 @@ static void gpu_set_alpha_blend(GPUBlendMode alphablend) glDisable(GL_ALPHA_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - else if (alphablend==GPU_BLEND_ADD) { + else if (alphablend == GPU_BLEND_ADD) { glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glDisable(GL_ALPHA_TEST); @@ -429,7 +429,7 @@ static void gpu_set_alpha_blend(GPUBlendMode alphablend) glAlphaFunc(GL_GREATER, U.glalphaclip); } } - else if (alphablend==GPU_BLEND_CLIP) { + else if (alphablend == GPU_BLEND_CLIP) { glDisable(GL_BLEND); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f); @@ -443,7 +443,7 @@ static void gpu_verify_alpha_blend(int alphablend) return; gpu_set_alpha_blend(alphablend); - GTS.alphablend= alphablend; + GTS.alphablend = alphablend; } static void gpu_verify_reflection(Image *ima) @@ -467,9 +467,9 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo { ImBuf *ibuf = NULL; unsigned int *bind = NULL; - int rectw, recth, tpx=0, tpy=0, y; - unsigned int *tilerect= NULL, *rect= NULL; - float *ftilerect= NULL, *frect = NULL; + int rectw, recth, tpx = 0, tpy = 0, y; + unsigned int *tilerect = NULL, *rect = NULL; + float *ftilerect = NULL, *frect = NULL; float *srgb_frect = NULL; short texwindx, texwindy, texwinsx, texwinsy; /* flag to determine whether high resolution format is used */ @@ -477,15 +477,15 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo /* initialize tile mode and number of repeats */ GTS.ima = ima; - GTS.tilemode= (ima && (ima->tpageflag & (IMA_TILES|IMA_TWINANIM))); + GTS.tilemode = (ima && (ima->tpageflag & (IMA_TILES|IMA_TWINANIM))); GTS.tileXRep = 0; GTS.tileYRep = 0; /* setting current tile according to frame */ if (ima && (ima->tpageflag & IMA_TWINANIM)) - GTS.tile= ima->lastframe; + GTS.tile = ima->lastframe; else - GTS.tile= tftile; + GTS.tile = tftile; GTS.tile = MAX2(0, GTS.tile); @@ -503,26 +503,26 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo } /* if tiling mode or repeat changed, change texture matrix to fit */ - if (GTS.tilemode!=GTS.curtilemode || GTS.curtileXRep!=GTS.tileXRep || + if (GTS.tilemode != GTS.curtilemode || GTS.curtileXRep != GTS.tileXRep || GTS.curtileYRep != GTS.tileYRep) { glMatrixMode(GL_TEXTURE); glLoadIdentity(); if (ima && (ima->tpageflag & IMA_TILES)) - glScalef(ima->xrep, ima->yrep, 1.0); + glScalef(ima->xrep, ima->yrep, 1.0f); glMatrixMode(GL_MODELVIEW); } /* check if we have a valid image */ - if (ima==NULL || ima->ok==0) + if (ima == NULL || ima->ok == 0) return 0; /* check if we have a valid image buffer */ - ibuf= BKE_image_acquire_ibuf(ima, iuser, NULL); + ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); - if (ibuf==NULL) + if (ibuf == NULL) return 0; if (ibuf->rect_float) { @@ -552,59 +552,58 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo if (GTS.tilemode) { /* tiled mode */ - if (ima->repbind==NULL) gpu_make_repbind(ima); - if (GTS.tile>=ima->totbind) GTS.tile= 0; + if (ima->repbind == NULL) gpu_make_repbind(ima); + if (GTS.tile >= ima->totbind) GTS.tile = 0; /* this happens when you change repeat buttons */ - if (ima->repbind) bind= &ima->repbind[GTS.tile]; - else bind= &ima->bindcode; + if (ima->repbind) bind = &ima->repbind[GTS.tile]; + else bind = &ima->bindcode; - if (*bind==0) { + if (*bind == 0) { + texwindx = ibuf->x / ima->xrep; + texwindy = ibuf->y / ima->yrep; - texwindx= ibuf->x/ima->xrep; - texwindy= ibuf->y/ima->yrep; - - if (GTS.tile>=ima->xrep*ima->yrep) - GTS.tile= ima->xrep*ima->yrep-1; + if (GTS.tile >= ima->xrep * ima->yrep) + GTS.tile = ima->xrep * ima->yrep - 1; - texwinsy= GTS.tile / ima->xrep; - texwinsx= GTS.tile - texwinsy*ima->xrep; + texwinsy = GTS.tile / ima->xrep; + texwinsx = GTS.tile - texwinsy * ima->xrep; - texwinsx*= texwindx; - texwinsy*= texwindy; + texwinsx *= texwindx; + texwinsy *= texwindy; - tpx= texwindx; - tpy= texwindy; + tpx = texwindx; + tpy = texwindy; if (use_high_bit_depth) { if (do_color_management) { - srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(float)*4, "floar_buf_col_cor"); + srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(float) * 4, "floar_buf_col_cor"); IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float, ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, true, ibuf->x, ibuf->y, ibuf->x, ibuf->x); IMB_buffer_float_unpremultiply(srgb_frect, ibuf->x, ibuf->y); /* clamp buffer colors to 1.0 to avoid artifacts due to glu for hdr images */ IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y); - frect= srgb_frect + texwinsy*ibuf->x + texwinsx; + frect = srgb_frect + texwinsy*ibuf->x + texwinsx; } else - frect= ibuf->rect_float + texwinsy*ibuf->x + texwinsx; + frect = ibuf->rect_float + texwinsy*ibuf->x + texwinsx; } else - rect= ibuf->rect + texwinsy*ibuf->x + texwinsx; + rect = ibuf->rect + texwinsy*ibuf->x + texwinsx; } } else { /* regular image mode */ bind= &ima->bindcode; - if (*bind==0) { - tpx= ibuf->x; - tpy= ibuf->y; - rect= ibuf->rect; + if (*bind == 0) { + tpx = ibuf->x; + tpy = ibuf->y; + rect = ibuf->rect; if (use_high_bit_depth) { if (do_color_management) { - frect = srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(*srgb_frect)*4, "floar_buf_col_cor"); + frect = srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(*srgb_frect) * 4, "floar_buf_col_cor"); IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float, ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, true, ibuf->x, ibuf->y, ibuf->x, ibuf->x); @@ -613,7 +612,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y); } else - frect= ibuf->rect_float; + frect = ibuf->rect_float; } } } @@ -633,30 +632,30 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo if (use_high_bit_depth) { float *frectrow, *ftilerectrow; - ftilerect= MEM_mallocN(rectw*recth*sizeof(*ftilerect), "tilerect"); + ftilerect = MEM_mallocN(rectw*recth*sizeof(*ftilerect), "tilerect"); - for (y=0; yx]; - ftilerectrow= &ftilerect[y*rectw]; + for (y = 0; y < recth; y++) { + frectrow = &frect[y * ibuf->x]; + ftilerectrow = &ftilerect[y * rectw]; - memcpy(ftilerectrow, frectrow, tpx*sizeof(*frectrow)); + memcpy(ftilerectrow, frectrow, tpx * sizeof(*frectrow)); } - frect= ftilerect; + frect = ftilerect; } else { unsigned int *rectrow, *tilerectrow; - tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect"); + tilerect = MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect"); - for (y=0; yx]; - tilerectrow= &tilerect[y*rectw]; + for (y = 0; y < recth; y++) { + rectrow = &rect[y * ibuf->x]; + tilerectrow = &tilerect[y * rectw]; - memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow)); + memcpy(tilerectrow, rectrow, tpx * sizeof(*rectrow)); } - rect= tilerect; + rect = tilerect; } } @@ -725,12 +724,12 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int if (use_high_bit_depth) { if (GLEW_ARB_texture_float) - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); } else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); @@ -756,12 +755,12 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int ImBuf *mip = ibuf->mipmap[i - 1]; if (use_high_bit_depth) { if (GLEW_ARB_texture_float) - glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16F, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float); + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16F, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float); else - glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float); + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float); } else { - glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); } } } @@ -825,7 +824,7 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); blocksize = (ibuf->dds_data.fourcc == FOURCC_DXT1) ? 8 : 16; - for (i=0; idds_data.nummipmaps && (width||height); ++i) { + for (i = 0; i < ibuf->dds_data.nummipmaps && (width||height); ++i) { if (width == 0) width = 1; if (height == 0) @@ -842,7 +841,7 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf) } /* set number of mipmap levels we have, needed in case they don't go down to 1x1 */ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i-1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i - 1); return true; #else @@ -888,21 +887,21 @@ int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend) Image *ima; /* check if we need to clear the state */ - if (tface==NULL) { + if (tface == NULL) { GPU_clear_tpage(false); return 0; } - ima= tface->tpage; - GTS.lasttface= tface; + ima = tface->tpage; + GTS.lasttface = tface; gpu_verify_alpha_blend(alphablend); gpu_verify_reflection(ima); if (GPU_verify_image(ima, NULL, tface->tile, 1, mipmap, false)) { - GTS.curtile= GTS.tile; - GTS.curima= GTS.ima; - GTS.curtilemode= GTS.tilemode; + GTS.curtile = GTS.tile; + GTS.curima = GTS.ima; + GTS.curtilemode = GTS.tilemode; GTS.curtileXRep = GTS.tileXRep; GTS.curtileYRep = GTS.tileYRep; @@ -911,9 +910,9 @@ int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend) else { glDisable(GL_TEXTURE_2D); - GTS.curtile= 0; - GTS.curima= NULL; - GTS.curtilemode= 0; + GTS.curtile = 0; + GTS.curima = NULL; + GTS.curtilemode = 0; GTS.curtileXRep = 0; GTS.curtileYRep = 0; @@ -934,7 +933,7 @@ int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend) * re-uploaded to OpenGL */ void GPU_paint_set_mipmap(int mipmap) { - Image* ima; + Image *ima; if (!GTS.domipmap) return; @@ -942,7 +941,7 @@ void GPU_paint_set_mipmap(int mipmap) GTS.texpaint = !mipmap; if (mipmap) { - for (ima=G.main->image.first; ima; ima=ima->id.next) { + for (ima = G.main->image.first; ima; ima = ima->id.next) { if (ima->bindcode) { if (ima->tpageflag & IMA_MIPMAP_COMPLETE) { glBindTexture(GL_TEXTURE_2D, ima->bindcode); @@ -958,7 +957,7 @@ void GPU_paint_set_mipmap(int mipmap) } else { - for (ima=G.main->image.first; ima; ima=ima->id.next) { + for (ima = G.main->image.first; ima; ima = ima->id.next) { if (ima->bindcode) { glBindTexture(GL_TEXTURE_2D, ima->bindcode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -1071,8 +1070,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h) } glBindTexture(GL_TEXTURE_2D, ima->bindcode); - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, - GL_FLOAT, buffer); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, buffer); MEM_freeN(buffer); @@ -1127,16 +1125,16 @@ void GPU_update_images_framechange(void) { Image *ima; - for (ima=G.main->image.first; ima; ima=ima->id.next) { + for (ima = G.main->image.first; ima; ima = ima->id.next) { if (ima->tpageflag & IMA_TWINANIM) { - if (ima->twend >= ima->xrep*ima->yrep) - ima->twend= ima->xrep*ima->yrep-1; + if (ima->twend >= ima->xrep * ima->yrep) + ima->twend = ima->xrep * ima->yrep - 1; /* check: is bindcode not in the array? free. (to do) */ ima->lastframe++; if (ima->lastframe > ima->twend) - ima->lastframe= ima->twsta; + ima->lastframe = ima->twsta; } } } @@ -1144,33 +1142,33 @@ void GPU_update_images_framechange(void) int GPU_update_image_time(Image *ima, double time) { int inc = 0; - float diff; + float diff; int newframe; if (!ima) return 0; - if (ima->lastupdate<0) + if (ima->lastupdate < 0) ima->lastupdate = 0; if (ima->lastupdate > (float)time) - ima->lastupdate=(float)time; + ima->lastupdate = (float)time; if (ima->tpageflag & IMA_TWINANIM) { - if (ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1; + if (ima->twend >= ima->xrep * ima->yrep) ima->twend = ima->xrep * ima->yrep - 1; /* check: is the bindcode not in the array? Then free. (still to do) */ diff = (float)((float)time - ima->lastupdate); - inc = (int)(diff*(float)ima->animspeed); + inc = (int)(diff * (float)ima->animspeed); - ima->lastupdate+=((float)inc/(float)ima->animspeed); + ima->lastupdate += ((float)inc / (float)ima->animspeed); - newframe = ima->lastframe+inc; + newframe = ima->lastframe + inc; if (newframe > (int)ima->twend) { - if (ima->twend-ima->twsta != 0) - newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta); + if (ima->twend - ima->twsta != 0) + newframe = (int)ima->twsta - 1 + (newframe - ima->twend) % (ima->twend - ima->twsta); else newframe = ima->twsta; } @@ -1207,7 +1205,7 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres) if (!sds->tex && !highres) { /* rgba texture for color + density */ if (smoke_has_colors(sds->fluid)) { - float *data = MEM_callocN(sizeof(float)*sds->total_cells*4, "smokeColorTexture"); + float *data = MEM_callocN(sizeof(float) * sds->total_cells * 4, "smokeColorTexture"); smoke_get_rgba(sds->fluid, data, 0); sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 4, data); MEM_freeN(data); @@ -1221,7 +1219,7 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres) else if (!sds->tex && highres) { /* rgba texture for color + density */ if (smoke_turbulence_has_colors(sds->wt)) { - float *data = MEM_callocN(sizeof(float)*smoke_turbulence_get_cells(sds->wt)*4, "smokeColorTexture"); + float *data = MEM_callocN(sizeof(float) * smoke_turbulence_get_cells(sds->wt) * 4, "smokeColorTexture"); smoke_turbulence_get_rgba(sds->wt, data, 0); sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 4, data); MEM_freeN(data); @@ -1237,9 +1235,9 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres) } #else // WITH_SMOKE (void)highres; - smd->domain->tex= NULL; - smd->domain->tex_flame= NULL; - smd->domain->tex_shadow= NULL; + smd->domain->tex = NULL; + smd->domain->tex_flame = NULL; + smd->domain->tex_shadow = NULL; #endif // WITH_SMOKE } @@ -1263,7 +1261,7 @@ void GPU_free_unused_buffers(void) BLI_lock_thread(LOCK_OPENGL); /* images */ - for (node=image_free_queue; node; node=node->next) { + for (node = image_free_queue; node; node = node->next) { ima = node->link; /* check in case it was freed in the meantime */ @@ -1290,13 +1288,13 @@ void GPU_free_image(Image *ima) /* free regular image binding */ if (ima->bindcode) { glDeleteTextures(1, (GLuint *)&ima->bindcode); - ima->bindcode= 0; + ima->bindcode = 0; } /* free glsl image binding */ if (ima->gputexture) { GPU_texture_free(ima->gputexture); - ima->gputexture= NULL; + ima->gputexture = NULL; } /* free repeated image binding */ @@ -1304,7 +1302,7 @@ void GPU_free_image(Image *ima) glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); MEM_freeN(ima->repbind); - ima->repbind= NULL; + ima->repbind = NULL; } ima->tpageflag &= ~(IMA_MIPMAP_COMPLETE|IMA_GLBIND_IS_DATA); @@ -1312,20 +1310,20 @@ void GPU_free_image(Image *ima) void GPU_free_images(void) { - Image* ima; + Image *ima; if (G.main) - for (ima=G.main->image.first; ima; ima=ima->id.next) + for (ima = G.main->image.first; ima; ima = ima->id.next) GPU_free_image(ima); } /* same as above but only free animated images */ void GPU_free_images_anim(void) { - Image* ima; + Image *ima; if (G.main) - for (ima=G.main->image.first; ima; ima=ima->id.next) + for (ima = G.main->image.first; ima; ima = ima->id.next) if (BKE_image_is_animated(ima)) GPU_free_image(ima); } @@ -1371,7 +1369,7 @@ void GPU_free_images_old(void) /* OpenGL Materials */ -#define FIXEDMAT 8 +#define FIXEDMAT 8 /* OpenGL state caching for materials */ @@ -1414,21 +1412,21 @@ static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat, { if (bmat->mode & MA_SHLESS) { copy_v3_v3(smat->diff, &bmat->r); - smat->diff[3]= 1.0; + smat->diff[3] = 1.0; if (gamma) linearrgb_to_srgb_v3_v3(smat->diff, smat->diff); zero_v4(smat->spec); - smat->hard= 0; + smat->hard = 0; } else if (new_shading_nodes) { copy_v3_v3(smat->diff, &bmat->r); - smat->diff[3]= 1.0; + smat->diff[3] = 1.0; copy_v3_v3(smat->spec, &bmat->specr); smat->spec[3] = 1.0; - smat->hard= CLAMPIS(bmat->har, 0, 128); + smat->hard = CLAMPIS(bmat->har, 0, 128); if (dimdown) { mul_v3_fl(smat->diff, 0.8f); @@ -1442,13 +1440,13 @@ static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat, } else { mul_v3_v3fl(smat->diff, &bmat->r, bmat->ref + bmat->emit); - smat->diff[3]= 1.0; /* caller may set this to bmat->alpha */ + smat->diff[3] = 1.0; /* caller may set this to bmat->alpha */ if (bmat->shade_flag & MA_OBCOLOR) mul_v3_v3(smat->diff, ob->col); mul_v3_v3fl(smat->spec, &bmat->specr, bmat->spec); - smat->spec[3]= 1.0; /* always 1 */ + smat->spec[3] = 1.0; /* always 1 */ smat->hard= CLAMPIS(bmat->har, 0, 128); if (gamma) { @@ -1500,10 +1498,10 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O GMS.gob = ob; GMS.gscene = scene; GMS.totmat = use_matcap ? 1 : ob->totcol + 1; /* materials start from 1, default material is 0 */ - GMS.glay= (v3d->localvd)? v3d->localvd->lay: v3d->lay; /* keep lamps visible in local view */ + GMS.glay = (v3d->localvd)? v3d->localvd->lay: v3d->lay; /* keep lamps visible in local view */ GMS.gscenelock = (v3d->scenelock != 0); - GMS.gviewmat= rv3d->viewmat; - GMS.gviewinv= rv3d->viewinv; + GMS.gviewmat = rv3d->viewmat; + GMS.gviewinv = rv3d->viewinv; GMS.gviewcamtexcofac = rv3d->viewcamtexcofac; /* alpha pass setup. there's various cases to handle here: @@ -1517,14 +1515,14 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O *do_alpha_after = false; if (GMS.totmat > FIXEDMAT) { - GMS.matbuf= MEM_callocN(sizeof(GPUMaterialFixed)*GMS.totmat, "GMS.matbuf"); - GMS.gmatbuf= MEM_callocN(sizeof(*GMS.gmatbuf)*GMS.totmat, "GMS.matbuf"); - GMS.alphablend= MEM_callocN(sizeof(*GMS.alphablend)*GMS.totmat, "GMS.matbuf"); + GMS.matbuf = MEM_callocN(sizeof(GPUMaterialFixed) * GMS.totmat, "GMS.matbuf"); + GMS.gmatbuf = MEM_callocN(sizeof(*GMS.gmatbuf) * GMS.totmat, "GMS.matbuf"); + GMS.alphablend = MEM_callocN(sizeof(*GMS.alphablend) * GMS.totmat, "GMS.matbuf"); } else { - GMS.matbuf= GMS.matbuf_fixed; - GMS.gmatbuf= GMS.gmatbuf_fixed; - GMS.alphablend= GMS.alphablend_fixed; + GMS.matbuf = GMS.matbuf_fixed; + GMS.gmatbuf = GMS.gmatbuf_fixed; + GMS.alphablend = GMS.alphablend_fixed; } /* viewport material, setup in space_view3d, defaults to matcap using ma->preview now */ @@ -1535,38 +1533,38 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O /* do material 1 too, for displists! */ memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed)); - GMS.alphablend[0]= GPU_BLEND_SOLID; + GMS.alphablend[0] = GPU_BLEND_SOLID; } else { /* no materials assigned? */ - if (ob->totcol==0) { + if (ob->totcol == 0) { gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes, true); /* do material 1 too, for displists! */ memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed)); if (glsl) { - GMS.gmatbuf[0]= &defmaterial; + GMS.gmatbuf[0] = &defmaterial; GPU_material_from_blender(GMS.gscene, &defmaterial); } - GMS.alphablend[0]= GPU_BLEND_SOLID; + GMS.alphablend[0] = GPU_BLEND_SOLID; } /* setup materials */ - for (a=1; a<=ob->totcol; a++) { + for (a = 1; a <= ob->totcol; a++) { /* find a suitable material */ - ma= give_current_material(ob, a); - if (!glsl && !new_shading_nodes) ma= gpu_active_node_material(ma); - if (ma==NULL) ma= &defmaterial; + ma = give_current_material(ob, a); + if (!glsl && !new_shading_nodes) ma = gpu_active_node_material(ma); + if (ma == NULL) ma = &defmaterial; /* create glsl material if requested */ - gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL; + gpumat = glsl? GPU_material_from_blender(GMS.gscene, ma): NULL; if (gpumat) { /* do glsl only if creating it succeed, else fallback */ - GMS.gmatbuf[a]= ma; + GMS.gmatbuf[a] = ma; alphablend = GPU_material_alpha_blend(gpumat, ob->col); } else { @@ -1574,11 +1572,11 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes, false); if (GMS.use_alpha_pass && ((ma->mode & MA_TRANSP) || (new_shading_nodes && ma->alpha != 1.0f))) { - GMS.matbuf[a].diff[3]= ma->alpha; + GMS.matbuf[a].diff[3] = ma->alpha; alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA; } else { - GMS.matbuf[a].diff[3]= 1.0f; + GMS.matbuf[a].diff[3] = 1.0f; alphablend = GPU_BLEND_SOLID; } } @@ -1589,10 +1587,10 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O if (ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT)) *do_alpha_after = true; - GMS.alphablend[a]= alphablend; + GMS.alphablend[a] = alphablend; } } - + /* let's start with a clean state */ GPU_disable_material(); } @@ -1610,10 +1608,10 @@ int GPU_enable_material(int nr, void *attribs) memset(&GMS, 0, sizeof(GMS)); mul_v3_v3fl(diff, &defmaterial.r, defmaterial.ref + defmaterial.emit); - diff[3]= 1.0; + diff[3] = 1.0; mul_v3_v3fl(spec, &defmaterial.specr, defmaterial.spec); - spec[3]= 1.0; + spec[3] = 1.0; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); @@ -1623,21 +1621,21 @@ int GPU_enable_material(int nr, void *attribs) } /* prevent index to use un-initialized array items */ - if (nr>=GMS.totmat) - nr= 0; + if (nr >= GMS.totmat) + nr = 0; if (gattribs) memset(gattribs, 0, sizeof(*gattribs)); /* keep current material */ - if (nr==GMS.lastmatnr) + if (nr == GMS.lastmatnr) return GMS.lastretval; /* unbind glsl material */ if (GMS.gboundmat) { if (GMS.is_alpha_pass) glDepthMask(0); GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat)); - GMS.gboundmat= NULL; + GMS.gboundmat = NULL; } /* draw materials with alpha in alpha pass */ @@ -1667,7 +1665,7 @@ int GPU_enable_material(int nr, void *attribs) auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f; GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gob->col, auto_bump_scale); - GMS.gboundmat= mat; + GMS.gboundmat = mat; /* for glsl use alpha blend mode, unless it's set to solid and * we are already drawing in an alpha pass */ @@ -1684,7 +1682,7 @@ int GPU_enable_material(int nr, void *attribs) } if (GMS.use_matcaps) - glColor3f(1.0, 1.0, 1.0f); + glColor3f(1.0f, 1.0f, 1.0f); } else { /* or do fixed function opengl material */ @@ -1716,8 +1714,8 @@ int GPU_get_material_alpha_blend(void) void GPU_disable_material(void) { - GMS.lastmatnr= -1; - GMS.lastretval= 1; + GMS.lastmatnr = -1; + GMS.lastretval = 1; if (GMS.gboundmat) { if (GMS.backface_culling) @@ -1725,7 +1723,7 @@ void GPU_disable_material(void) if (GMS.is_alpha_pass) glDepthMask(0); GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat)); - GMS.gboundmat= NULL; + GMS.gboundmat = NULL; } GPU_set_material_alpha_blend(GPU_BLEND_SOLID); @@ -1762,9 +1760,9 @@ void GPU_end_object_materials(void) MEM_freeN(GMS.alphablend); } - GMS.matbuf= NULL; - GMS.gmatbuf= NULL; - GMS.alphablend= NULL; + GMS.matbuf = NULL; + GMS.gmatbuf = NULL; + GMS.alphablend = NULL; /* resetting the texture matrix after the scaling needed for tiled textures */ if (GTS.tilemode) { @@ -1782,57 +1780,57 @@ int GPU_default_lights(void) int a, count = 0; /* initialize */ - if (U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) { - U.light[0].flag= 1; - U.light[0].vec[0]= -0.3; U.light[0].vec[1]= 0.3; U.light[0].vec[2]= 0.9; - U.light[0].col[0]= 0.8; U.light[0].col[1]= 0.8; U.light[0].col[2]= 0.8; - U.light[0].spec[0]= 0.5; U.light[0].spec[1]= 0.5; U.light[0].spec[2]= 0.5; - U.light[0].spec[3]= 1.0; + if (U.light[0].flag == 0 && U.light[1].flag == 0 && U.light[2].flag == 0) { + U.light[0].flag = 1; + U.light[0].vec[0] = -0.3; U.light[0].vec[1] = 0.3; U.light[0].vec[2] = 0.9; + U.light[0].col[0] = 0.8; U.light[0].col[1] = 0.8; U.light[0].col[2] = 0.8; + U.light[0].spec[0] = 0.5; U.light[0].spec[1] = 0.5; U.light[0].spec[2] = 0.5; + U.light[0].spec[3] = 1.0; - U.light[1].flag= 0; - U.light[1].vec[0]= 0.5; U.light[1].vec[1]= 0.5; U.light[1].vec[2]= 0.1; - U.light[1].col[0]= 0.4; U.light[1].col[1]= 0.4; U.light[1].col[2]= 0.8; - U.light[1].spec[0]= 0.3; U.light[1].spec[1]= 0.3; U.light[1].spec[2]= 0.5; - U.light[1].spec[3]= 1.0; + U.light[1].flag = 0; + U.light[1].vec[0] = 0.5; U.light[1].vec[1] = 0.5; U.light[1].vec[2] = 0.1; + U.light[1].col[0] = 0.4; U.light[1].col[1] = 0.4; U.light[1].col[2] = 0.8; + U.light[1].spec[0] = 0.3; U.light[1].spec[1] = 0.3; U.light[1].spec[2] = 0.5; + U.light[1].spec[3] = 1.0; - U.light[2].flag= 0; - U.light[2].vec[0]= 0.3; U.light[2].vec[1]= -0.3; U.light[2].vec[2]= -0.2; - U.light[2].col[0]= 0.8; U.light[2].col[1]= 0.5; U.light[2].col[2]= 0.4; - U.light[2].spec[0]= 0.5; U.light[2].spec[1]= 0.4; U.light[2].spec[2]= 0.3; - U.light[2].spec[3]= 1.0; + U.light[2].flag = 0; + U.light[2].vec[0] = 0.3; U.light[2].vec[1] = -0.3; U.light[2].vec[2] = -0.2; + U.light[2].col[0] = 0.8; U.light[2].col[1] = 0.5; U.light[2].col[2] = 0.4; + U.light[2].spec[0] = 0.5; U.light[2].spec[1] = 0.4; U.light[2].spec[2] = 0.3; + U.light[2].spec[3] = 1.0; } glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE); - for (a=0; a<8; a++) { - if (a<3) { + for (a = 0; a < 8; a++) { + if (a < 3) { if (U.light[a].flag) { - glEnable(GL_LIGHT0+a); + glEnable(GL_LIGHT0 + a); normalize_v3_v3(position, U.light[a].vec); - position[3]= 0.0f; + position[3] = 0.0f; - glLightfv(GL_LIGHT0+a, GL_POSITION, position); - glLightfv(GL_LIGHT0+a, GL_DIFFUSE, U.light[a].col); - glLightfv(GL_LIGHT0+a, GL_SPECULAR, U.light[a].spec); + glLightfv(GL_LIGHT0 + a, GL_POSITION, position); + glLightfv(GL_LIGHT0 + a, GL_DIFFUSE, U.light[a].col); + glLightfv(GL_LIGHT0 + a, GL_SPECULAR, U.light[a].spec); count++; } else { - glDisable(GL_LIGHT0+a); + glDisable(GL_LIGHT0 + a); - glLightfv(GL_LIGHT0+a, GL_POSITION, zero); - glLightfv(GL_LIGHT0+a, GL_DIFFUSE, zero); - glLightfv(GL_LIGHT0+a, GL_SPECULAR, zero); + glLightfv(GL_LIGHT0 + a, GL_POSITION, zero); + glLightfv(GL_LIGHT0 + a, GL_DIFFUSE, zero); + glLightfv(GL_LIGHT0 + a, GL_SPECULAR, zero); } - // clear stuff from other opengl lamp usage - glLightf(GL_LIGHT0+a, GL_SPOT_CUTOFF, 180.0); - glLightf(GL_LIGHT0+a, GL_CONSTANT_ATTENUATION, 1.0); - glLightf(GL_LIGHT0+a, GL_LINEAR_ATTENUATION, 0.0); + /* clear stuff from other opengl lamp usage */ + glLightf(GL_LIGHT0 + a, GL_SPOT_CUTOFF, 180.0); + glLightf(GL_LIGHT0 + a, GL_CONSTANT_ATTENUATION, 1.0); + glLightf(GL_LIGHT0 + a, GL_LINEAR_ATTENUATION, 0.0); } else - glDisable(GL_LIGHT0+a); + glDisable(GL_LIGHT0 + a); } glDisable(GL_LIGHTING); @@ -1850,68 +1848,68 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][ float position[4], direction[4], energy[4]; /* disable all lights */ - for (count=0; count<8; count++) - glDisable(GL_LIGHT0+count); + for (count = 0; count < 8; count++) + glDisable(GL_LIGHT0 + count); - /* view direction for specular is not compute correct by default in + /* view direction for specular is not computed correct by default in * opengl, so we set the settings ourselfs */ - glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (ortho)? GL_FALSE: GL_TRUE); + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, ortho ? GL_FALSE : GL_TRUE); - count= 0; - - for (base=scene->base.first; base; base=base->next) { - if (base->object->type!=OB_LAMP) + count = 0; + + for (base = scene->base.first; base; base = base->next) { + if (base->object->type != OB_LAMP) continue; if (!(base->lay & lay) || !(base->lay & ob->lay)) continue; - la= base->object->data; + la = base->object->data; /* setup lamp transform */ glPushMatrix(); glLoadMatrixf((float *)viewmat); - if (la->type==LA_SUN) { + if (la->type == LA_SUN) { /* sun lamp */ copy_v3_v3(direction, base->object->obmat[2]); - direction[3]= 0.0; + direction[3] = 0.0; glLightfv(GL_LIGHT0+count, GL_POSITION, direction); } else { /* other lamps with attenuation */ copy_v3_v3(position, base->object->obmat[3]); - position[3]= 1.0f; + position[3] = 1.0f; glLightfv(GL_LIGHT0+count, GL_POSITION, position); glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0); - glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist); - glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist)); + glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1 / la->dist); + glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2 / (la->dist * la->dist)); - if (la->type==LA_SPOT) { + if (la->type == LA_SPOT) { /* spot lamp */ negate_v3_v3(direction, base->object->obmat[2]); - glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, direction); - glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, RAD2DEGF(la->spotsize * 0.5f)); - glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0f*la->spotblend); + glLightfv(GL_LIGHT0 + count, GL_SPOT_DIRECTION, direction); + glLightf(GL_LIGHT0 + count, GL_SPOT_CUTOFF, RAD2DEGF(la->spotsize * 0.5f)); + glLightf(GL_LIGHT0 + count, GL_SPOT_EXPONENT, 128.0f * la->spotblend); } else - glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0); + glLightf(GL_LIGHT0 + count, GL_SPOT_CUTOFF, 180.0); } /* setup energy */ mul_v3_v3fl(energy, &la->r, la->energy); - energy[3]= 1.0; + energy[3] = 1.0; - glLightfv(GL_LIGHT0+count, GL_DIFFUSE, energy); - glLightfv(GL_LIGHT0+count, GL_SPECULAR, energy); - glEnable(GL_LIGHT0+count); + glLightfv(GL_LIGHT0 + count, GL_DIFFUSE, energy); + glLightfv(GL_LIGHT0 + count, GL_SPECULAR, energy); + glEnable(GL_LIGHT0 + count); glPopMatrix(); count++; - if (count==8) + if (count == 8) break; } @@ -1957,8 +1955,8 @@ void GPU_state_init(void) float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 }; float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 }; int a, x, y; - GLubyte pat[32*32]; - const GLubyte *patc= pat; + GLubyte pat[32 * 32]; + const GLubyte *patc = pat; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular); @@ -2003,14 +2001,14 @@ void GPU_state_init(void) glPixelTransferi(GL_DEPTH_SCALE, 1); glDepthRange(0.0, 1.0); - a= 0; - for (x=0; x<32; x++) { - for (y=0; y<4; y++) { - if ( (x) & 1) pat[a++]= 0x88; - else pat[a++]= 0x22; + a = 0; + for (x = 0; x < 32; x++) { + for (y = 0; y < 4; y++) { + if (x & 1) pat[a++] = 0x88; + else pat[a++] = 0x22; } } - + glPolygonStipple(patc); glMatrixMode(GL_TEXTURE); diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index ec7e80e6b00..bc6e24f5072 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -164,7 +164,7 @@ void gpu_extensions_init(void) glGetIntegerv(GL_RED_BITS, &r); glGetIntegerv(GL_GREEN_BITS, &g); glGetIntegerv(GL_BLUE_BITS, &b); - GG.colordepth = r+g+b; /* assumes same depth for RGB */ + GG.colordepth = r + g + b; /* assumes same depth for RGB */ vendor = (const char *)glGetString(GL_VENDOR); renderer = (const char *)glGetString(GL_RENDERER); @@ -299,34 +299,34 @@ int GPU_color_depth(void) static void GPU_print_framebuffer_error(GLenum status, char err_out[256]) { - const char *err= "unknown"; + const char *err = "unknown"; switch (status) { case GL_FRAMEBUFFER_COMPLETE_EXT: break; case GL_INVALID_OPERATION: - err= "Invalid operation"; + err = "Invalid operation"; break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: - err= "Incomplete attachment"; + err = "Incomplete attachment"; break; case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - err= "Unsupported framebuffer format"; + err = "Unsupported framebuffer format"; break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: - err= "Missing attachment"; + err = "Missing attachment"; break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: - err= "Attached images must have same dimensions"; + err = "Attached images must have same dimensions"; break; case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: - err= "Attached images must have same format"; + err = "Attached images must have same format"; break; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: - err= "Missing draw buffer"; + err = "Missing draw buffer"; break; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: - err= "Missing read buffer"; + err = "Missing read buffer"; break; } @@ -343,36 +343,36 @@ static void GPU_print_framebuffer_error(GLenum status, char err_out[256]) /* GPUTexture */ struct GPUTexture { - int w, h; /* width/height */ - int number; /* number for multitexture binding */ - int refcount; /* reference count */ - GLenum target; /* GL_TEXTURE_* */ - GLuint bindcode; /* opengl identifier for texture */ - int fromblender; /* we got the texture from Blender */ - - GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */ - int fb_attachment; /* slot the texture is attached to */ - int depth; /* is a depth texture? if 3D how deep? */ + int w, h; /* width/height */ + int number; /* number for multitexture binding */ + int refcount; /* reference count */ + GLenum target; /* GL_TEXTURE_* */ + GLuint bindcode; /* opengl identifier for texture */ + int fromblender; /* we got the texture from Blender */ + + GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */ + int fb_attachment; /* slot the texture is attached to */ + int depth; /* is a depth texture? if 3D how deep? */ }; static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels) { unsigned char *pixels, *p; const float *fp = fpixels; - const int len = 4*length; + const int len = 4 * length; int a; - p = pixels = MEM_callocN(sizeof(unsigned char)*len, "GPUTexturePixels"); + p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels"); - for (a=0; atarget, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL); @@ -972,7 +974,7 @@ GPUFrameBuffer *GPU_framebuffer_create(void) if (!GLEW_EXT_framebuffer_object) return NULL; - fb= MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer"); + fb = MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer"); glGenFramebuffersEXT(1, &fb->object); if (!fb->object) { @@ -1065,8 +1067,7 @@ void GPU_framebuffer_texture_detach(GPUTexture *tex) attachment = GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment; } - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, - tex->target, 0, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, tex->target, 0, 0); tex->fb = NULL; tex->fb_attachment = -1; @@ -1116,7 +1117,7 @@ void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot) return; } - for (i = 0 ; i < 4; i++) { + for (i = 0; i < 4; i++) { if (fb->colortex[i]) { attachments[numslots] = GL_COLOR_ATTACHMENT0_EXT + i; numslots++; @@ -1306,7 +1307,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256]) { GPUOffScreen *ofs; - ofs= MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen"); + ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen"); ofs->fb = GPU_framebuffer_create(); if (!ofs->fb) { @@ -1395,13 +1396,13 @@ int GPU_offscreen_height(const GPUOffScreen *ofs) /* GPUShader */ struct GPUShader { - GLhandleARB object; /* handle for full shader */ - GLhandleARB vertex; /* handle for vertex shader */ - GLhandleARB fragment; /* handle for fragment shader */ - GLhandleARB geometry; /* handle for geometry shader */ - GLhandleARB lib; /* handle for libment shader */ - int totattrib; /* total number of attributes */ - int uniforms; /* required uniforms */ + GLhandleARB object; /* handle for full shader */ + GLhandleARB vertex; /* handle for vertex shader */ + GLhandleARB fragment; /* handle for fragment shader */ + GLhandleARB geometry; /* handle for geometry shader */ + GLhandleARB lib; /* handle for libment shader */ + int totattrib; /* total number of attributes */ + int uniforms; /* required uniforms */ }; static void shader_print_errors(const char *task, char *log, const char **code, int totcode) @@ -1420,8 +1421,8 @@ static void shader_print_errors(const char *task, char *log, const char **code, c = code[i]; while ((c < end) && (pos = strchr(c, '\n'))) { fprintf(stderr, "%2d ", line); - fwrite(c, (pos+1)-c, 1, stderr); - c = pos+1; + fwrite(c, (pos + 1) - c, 1, stderr); + c = pos + 1; line++; } @@ -1447,7 +1448,7 @@ static const char *gpu_shader_version(void) static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH]) { - /* need this extensions for high quality bump mapping */ + /* need this extension for high quality bump mapping */ if (GPU_bicubic_bump_support()) strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n"); @@ -1818,7 +1819,7 @@ GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp) if (!GG.shaders.fx_shaders[offset]) { GPUShader *shader; - switch(effects) { + switch (effects) { case GPU_SHADER_FX_SSAO: GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); break; @@ -1896,7 +1897,8 @@ void GPU_shader_free_builtin_shaders(void) } } -#if 0 +#if 0 /* unused */ + /* GPUPixelBuffer */ typedef struct GPUPixelBuffer { @@ -1922,7 +1924,7 @@ GPUPixelBuffer *gpu_pixelbuffer_create(int x, int y, int halffloat, int numbuffe return NULL; pb = MEM_callocN(sizeof(GPUPixelBuffer), "GPUPBO"); - pb->datasize = x*y*4*((halffloat)? 16: 8); + pb->datasize = x * y * 4 * (halffloat ? 16 : 8); pb->numbuffers = numbuffers; pb->halffloat = halffloat; @@ -1950,10 +1952,13 @@ void GPU_pixelbuffer_texture(GPUTexture *tex, GPUPixelBuffer *pb) GL_STREAM_DRAW_ARB); pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY); - /*memcpy(pixels, _oImage.data(), pb->datasize);*/ + +# if 0 + memcpy(pixels, _oImage.data(), pb->datasize); +# endif if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) { - fprintf(stderr, "Could not unmap opengl PBO\n"); + fprintf(stderr, "Could not unmap OpenGL PBO\n"); break; } } @@ -1971,7 +1976,7 @@ static int pixelbuffer_map_into_gpu(GLuint bindcode) /* do stuff in pixels */ if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) { - fprintf(stderr, "Could not unmap opengl PBO\n"); + fprintf(stderr, "Could not unmap OpenGL PBO\n"); return 0; } @@ -1984,8 +1989,7 @@ static void pixelbuffer_copy_to_texture(GPUTexture *tex, GPUPixelBuffer *pb, GLu glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode); - glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, tex->w, tex->h, - GL_RGBA, type, NULL); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, tex->w, tex->h, GL_RGBA, type, NULL); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0); @@ -2000,12 +2004,12 @@ void GPU_pixelbuffer_async_to_gpu(GPUTexture *tex, GPUPixelBuffer *pb) pixelbuffer_map_into_gpu(pb->bindcode[0]); } else { - pb->current = (pb->current+1)%pb->numbuffers; - newbuffer = (pb->current+1)%pb->numbuffers; + pb->current = (pb->current + 1) % pb->numbuffers; + newbuffer = (pb->current + 1) % pb->numbuffers; pixelbuffer_map_into_gpu(pb->bindcode[newbuffer]); pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[pb->current]); } } -#endif +#endif /* unused */ diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index c754f63664f..a9c35896a89 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -157,7 +157,7 @@ static GPUMaterial *GPU_material_construct_begin(Material *ma) { GPUMaterial *material = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial"); - material->ma= ma; + material->ma = ma; return material; } @@ -170,14 +170,14 @@ static void gpu_material_set_attrib_id(GPUMaterial *material) char name[32]; int a, b; - attribs= &material->attribs; - pass= material->pass; + attribs = &material->attribs; + pass = material->pass; if (!pass) { attribs->totlayer = 0; return; } - shader= GPU_pass_shader(pass); + shader = GPU_pass_shader(pass); if (!shader) { attribs->totlayer = 0; return; @@ -187,7 +187,7 @@ static void gpu_material_set_attrib_id(GPUMaterial *material) * in case the attrib does not get a valid index back, it was probably * removed by the glsl compiler by dead code elimination */ - for (a=0, b=0; atotlayer; a++) { + for (a = 0, b = 0; a < attribs->totlayer; a++) { BLI_snprintf(name, sizeof(name), "att%d", attribs->layer[a].attribid); attribs->layer[a].glindex = GPU_shader_get_attribute(shader, name); @@ -242,19 +242,19 @@ void GPU_material_free(ListBase *gpumaterial) LinkData *link; LinkData *nlink, *mlink, *next; - for (link=gpumaterial->first; link; link=link->next) { + for (link = gpumaterial->first; link; link = link->next) { GPUMaterial *material = link->data; if (material->pass) GPU_pass_free(material->pass); - for (nlink=material->lamps.first; nlink; nlink=nlink->next) { + for (nlink = material->lamps.first; nlink; nlink = nlink->next) { GPULamp *lamp = nlink->data; if (material->ma) { Material *ma = material->ma; - for (mlink=lamp->materials.first; mlink; mlink=next) { + for (mlink = lamp->materials.first; mlink; mlink = next) { next = mlink->next; if (mlink->data == ma) BLI_freelinkN(&lamp->materials, mlink); @@ -293,8 +293,8 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim /* handle layer lamps */ if (material->type == GPU_MATERIAL_TYPE_MESH) { - for (nlink=material->lamps.first; nlink; nlink=nlink->next) { - lamp= nlink->data; + for (nlink = material->lamps.first; nlink; nlink = nlink->next) { + lamp = nlink->data; if (!lamp->hide && (lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay)) && GPU_lamp_override_visible(lamp, srl, material->ma)) { @@ -303,7 +303,7 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim } else { lamp->dynenergy = 0.0f; - lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f; + lamp->dyncol[0] = lamp->dyncol[1] = lamp->dyncol[2] = 0.0f; } if (material->dynproperty & DYN_LAMP_VEC) { @@ -414,12 +414,12 @@ void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *att void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link) { if (!material->outlink) - material->outlink= link; + material->outlink = link; } void GPU_material_enable_alpha(GPUMaterial *material) { - material->alpha= 1; + material->alpha = 1; } GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]) @@ -455,7 +455,7 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode GPUNodeLink *visifac, *inpr; /* from get_lamp_visibility */ - if (lamp->type==LA_SUN || lamp->type==LA_HEMI) { + if (lamp->type == LA_SUN || lamp->type == LA_HEMI) { mat->dynproperty |= DYN_LAMP_VEC; GPU_link(mat, "lamp_visibility_sun_hemi", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), lv, dist, &visifac); return visifac; @@ -464,7 +464,7 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode mat->dynproperty |= DYN_LAMP_CO; GPU_link(mat, "lamp_visibility_other", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), lv, dist, &visifac); - if (lamp->type==LA_AREA) + if (lamp->type == LA_AREA) return visifac; switch (lamp->falloff_type) { @@ -480,15 +480,16 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode GPU_link(mat, "lamp_falloff_sliders", GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), GPU_dynamic_uniform(&lamp->att1, GPU_DYNAMIC_LAMP_ATT1, lamp->ob), GPU_dynamic_uniform(&lamp->att2, GPU_DYNAMIC_LAMP_ATT2, lamp->ob), *dist, &visifac); break; case LA_FALLOFF_CURVE: - { - float *array; - int size; + { + float *array; + int size; + + curvemapping_initialize(lamp->curfalloff); + curvemapping_table_RGBA(lamp->curfalloff, &array, &size); + GPU_link(mat, "lamp_falloff_curve", GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), GPU_texture(size, array), *dist, &visifac); - curvemapping_initialize(lamp->curfalloff); - curvemapping_table_RGBA(lamp->curfalloff, &array, &size); - GPU_link(mat, "lamp_falloff_curve", GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), GPU_texture(size, array), *dist, &visifac); - } break; + } } if (lamp->mode & LA_SPHERE) @@ -516,34 +517,34 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode #if 0 static void area_lamp_vectors(LampRen *lar) { - float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey, multifac; + float xsize = 0.5f * lar->area_size, ysize = 0.5f * lar->area_sizey, multifac; /* make it smaller, so area light can be multisampled */ - multifac= 1.0f/sqrt((float)lar->ray_totsamp); + multifac = 1.0f / sqrtf((float)lar->ray_totsamp); xsize *= multifac; ysize *= multifac; /* corner vectors */ - lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; - lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; - lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; + lar->area[0][0] = lar->co[0] - xsize * lar->mat[0][0] - ysize * lar->mat[1][0]; + lar->area[0][1] = lar->co[1] - xsize * lar->mat[0][1] - ysize * lar->mat[1][1]; + lar->area[0][2] = lar->co[2] - xsize * lar->mat[0][2] - ysize * lar->mat[1][2]; /* corner vectors */ - lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; - lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; - lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; + lar->area[1][0] = lar->co[0] - xsize * lar->mat[0][0] + ysize * lar->mat[1][0]; + lar->area[1][1] = lar->co[1] - xsize * lar->mat[0][1] + ysize * lar->mat[1][1]; + lar->area[1][2] = lar->co[2] - xsize * lar->mat[0][2] + ysize * lar->mat[1][2]; /* corner vectors */ - lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; - lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; - lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; + lar->area[2][0] = lar->co[0] + xsize * lar->mat[0][0] + ysize * lar->mat[1][0]; + lar->area[2][1] = lar->co[1] + xsize * lar->mat[0][1] + ysize * lar->mat[1][1]; + lar->area[2][2] = lar->co[2] + xsize * lar->mat[0][2] + ysize * lar->mat[1][2]; /* corner vectors */ - lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; - lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; - lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; + lar->area[3][0] = lar->co[0] + xsize * lar->mat[0][0] - ysize * lar->mat[1][0]; + lar->area[3][1] = lar->co[1] + xsize * lar->mat[0][1] - ysize * lar->mat[1][1]; + lar->area[3][2] = lar->co[2] + xsize * lar->mat[0][2] - ysize * lar->mat[1][2]; /* only for correction button size, matrix size works on energy */ - lar->areasize= lar->dist*lar->dist/(4.0*xsize*ysize); + lar->areasize = lar->dist * lar->dist / (4.0f * xsize * ysize); } #endif @@ -577,8 +578,8 @@ static void do_colorband_blend(GPUMaterial *mat, ColorBand *coba, GPUNodeLink *f static void ramp_diffuse_result(GPUShadeInput *shi, GPUNodeLink **diff) { - Material *ma= shi->mat; - GPUMaterial *mat= shi->gpumat; + Material *ma = shi->mat; + GPUMaterial *mat = shi->gpumat; GPUNodeLink *fac; if (!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS)) { @@ -607,18 +608,18 @@ static void add_to_diffuse(GPUMaterial *mat, Material *ma, GPUShadeInput *shi, G else { /* input */ switch (ma->rampin_col) { - case MA_RAMP_IN_ENERGY: - GPU_link(mat, "ramp_rgbtobw", rgb, &fac); - break; - case MA_RAMP_IN_SHADER: - fac= is; - break; - case MA_RAMP_IN_NOR: - GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac); - break; - default: - GPU_link(mat, "set_value_zero", &fac); - break; + case MA_RAMP_IN_ENERGY: + GPU_link(mat, "ramp_rgbtobw", rgb, &fac); + break; + case MA_RAMP_IN_SHADER: + fac= is; + break; + case MA_RAMP_IN_NOR: + GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac); + break; + default: + GPU_link(mat, "set_value_zero", &fac); + break; } /* colorband + blend */ @@ -634,12 +635,12 @@ static void add_to_diffuse(GPUMaterial *mat, Material *ma, GPUShadeInput *shi, G static void ramp_spec_result(GPUShadeInput *shi, GPUNodeLink **spec) { - Material *ma= shi->mat; - GPUMaterial *mat= shi->gpumat; + Material *ma = shi->mat; + GPUMaterial *mat = shi->gpumat; GPUNodeLink *fac; if (!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS) && - ma->ramp_spec && ma->rampin_spec==MA_RAMP_IN_RESULT) + ma->ramp_spec && ma->rampin_spec == MA_RAMP_IN_RESULT) { GPU_link(mat, "ramp_rgbtobw", *spec, &fac); @@ -650,29 +651,29 @@ static void ramp_spec_result(GPUShadeInput *shi, GPUNodeLink **spec) static void do_specular_ramp(GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *t, GPUNodeLink **spec) { - Material *ma= shi->mat; - GPUMaterial *mat= shi->gpumat; + Material *ma = shi->mat; + GPUMaterial *mat = shi->gpumat; GPUNodeLink *fac, *tmp; *spec = shi->specrgb; /* MA_RAMP_IN_RESULT is exception */ - if (ma->ramp_spec && (ma->rampin_spec!=MA_RAMP_IN_RESULT)) { + if (ma->ramp_spec && (ma->rampin_spec != MA_RAMP_IN_RESULT)) { /* input */ switch (ma->rampin_spec) { - case MA_RAMP_IN_ENERGY: - fac = t; - break; - case MA_RAMP_IN_SHADER: - fac = is; - break; - case MA_RAMP_IN_NOR: - GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac); - break; - default: - GPU_link(mat, "set_value_zero", &fac); - break; + case MA_RAMP_IN_ENERGY: + fac = t; + break; + case MA_RAMP_IN_SHADER: + fac = is; + break; + case MA_RAMP_IN_NOR: + GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac); + break; + default: + GPU_link(mat, "set_value_zero", &fac); + break; } /* colorband + blend */ @@ -694,10 +695,10 @@ static void shade_light_textures(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink ** int i; float one = 1.f; - for (i=0; ila->mtex[i]; - if (mtex && mtex->tex->type & TEX_IMAGE && mtex->tex->ima) { + if (mtex && mtex->tex->type & TEX_IMAGE && mtex->tex->ima) { mat->dynproperty |= DYN_LAMP_PERSMAT; GPU_link(mat, "shade_light_texture", @@ -705,29 +706,31 @@ static void shade_light_textures(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink ** GPU_image(mtex->tex->ima, &mtex->tex->iuser, false), GPU_dynamic_uniform((float*)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob), &tex_rgb); - texture_rgb_blend(mat, tex_rgb, *rgb, GPU_uniform(&one), GPU_uniform(&mtex->colfac), mtex->blendtype, rgb); + texture_rgb_blend(mat, tex_rgb, *rgb, GPU_uniform(&one), GPU_uniform(&mtex->colfac), mtex->blendtype, rgb); } } } static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *lamp) { - Material *ma= shi->mat; - GPUMaterial *mat= shi->gpumat; + Material *ma = shi->mat; + GPUMaterial *mat = shi->gpumat; GPUNodeLink *lv, *dist, *visifac, *is, *inp, *i, *vn, *view; - GPUNodeLink *outcol, *specfac, *t, *shadfac= NULL, *lcol; + GPUNodeLink *outcol, *specfac, *t, *shadfac = NULL, *lcol; float one = 1.0f; if ((lamp->mode & LA_ONLYSHADOW) && !(ma->mode & MA_SHADOW)) return; - vn= shi->vn; - view= shi->view; + vn = shi->vn; + view = shi->view; - visifac= lamp_get_visibility(mat, lamp, &lv, &dist); + visifac = lamp_get_visibility(mat, lamp, &lv, &dist); - /*if (ma->mode & MA_TANGENT_V) - GPU_link(mat, "shade_tangent_v", lv, GPU_attribute(CD_TANGENT, ""), &vn);*/ +#if 0 + if (ma->mode & MA_TANGENT_V) + GPU_link(mat, "shade_tangent_v", lv, GPU_attribute(CD_TANGENT, ""), &vn); +#endif GPU_link(mat, "shade_inp", vn, lv, &inp); @@ -739,23 +742,23 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la } else { if (lamp->type == LA_AREA) { - float area[4][4]= {{0.0f}}, areasize= 0.0f; + float area[4][4] = {{0.0f}}, areasize = 0.0f; mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_CO; GPU_link(mat, "shade_inp_area", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), vn, GPU_uniform((float*)area), GPU_uniform(&areasize), GPU_uniform(&lamp->k), &inp); } - is= inp; /* Lambert */ + is = inp; /* Lambert */ if (!(mat->scene->gm.flag & GAME_GLSL_NO_SHADERS)) { - if (ma->diff_shader==MA_DIFF_ORENNAYAR) + if (ma->diff_shader == MA_DIFF_ORENNAYAR) GPU_link(mat, "shade_diffuse_oren_nayer", inp, vn, lv, view, GPU_uniform(&ma->roughness), &is); - else if (ma->diff_shader==MA_DIFF_TOON) + else if (ma->diff_shader == MA_DIFF_TOON) GPU_link(mat, "shade_diffuse_toon", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is); - else if (ma->diff_shader==MA_DIFF_MINNAERT) + else if (ma->diff_shader == MA_DIFF_MINNAERT) GPU_link(mat, "shade_diffuse_minnaert", inp, vn, view, GPU_uniform(&ma->darkness), &is); - else if (ma->diff_shader==MA_DIFF_FRESNEL) + else if (ma->diff_shader == MA_DIFF_FRESNEL) GPU_link(mat, "shade_diffuse_fresnel", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is); } } @@ -777,7 +780,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la #endif /* this replaces if (i > 0.0) conditional until that is supported */ - // done in shade_visifac now, GPU_link(mat, "mtex_value_clamp_positive", i, &i); + /* done in shade_visifac now, GPU_link(mat, "mtex_value_clamp_positive", i, &i); */ if ((ma->mode & MA_SHADOW) && GPU_lamp_has_shadow_buffer(lamp)) { if (!(mat->scene->gm.flag & GAME_GLSL_NO_SHADOWS)) { @@ -850,18 +853,18 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec); } else { - if (ma->spec_shader==MA_SPEC_PHONG) + if (ma->spec_shader == MA_SPEC_PHONG) GPU_link(mat, "shade_phong_spec", vn, lv, view, shi->har, &specfac); - else if (ma->spec_shader==MA_SPEC_COOKTORR) + else if (ma->spec_shader == MA_SPEC_COOKTORR) GPU_link(mat, "shade_cooktorr_spec", vn, lv, view, shi->har, &specfac); - else if (ma->spec_shader==MA_SPEC_BLINN) + else if (ma->spec_shader == MA_SPEC_BLINN) GPU_link(mat, "shade_blinn_spec", vn, lv, view, GPU_uniform(&ma->refrac), shi->har, &specfac); - else if (ma->spec_shader==MA_SPEC_WARDISO) + else if (ma->spec_shader == MA_SPEC_WARDISO) GPU_link(mat, "shade_wardiso_spec", vn, lv, view, GPU_uniform(&ma->rms), &specfac); else GPU_link(mat, "shade_toon_spec", vn, lv, view, GPU_uniform(&ma->param[2]), GPU_uniform(&ma->param[3]), &specfac); - if (lamp->type==LA_AREA) + if (lamp->type == LA_AREA) GPU_link(mat, "shade_spec_area_inp", specfac, inp, &specfac); GPU_link(mat, "shade_spec_t", shadfac, shi->spec, visifac, specfac, &t); @@ -891,9 +894,9 @@ static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr) GPULamp *lamp; for (SETLOOPER(shi->gpumat->scene, sce_iter, base)) { - ob= base->object; + ob = base->object; - if (ob->type==OB_LAMP) { + if (ob->type == OB_LAMP) { lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob, NULL); if (lamp) shade_one_light(shi, shr, lamp); @@ -903,10 +906,10 @@ static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr) DupliObject *dob; ListBase *lb = object_duplilist(G.main->eval_ctx, shi->gpumat->scene, ob); - for (dob=lb->first; dob; dob=dob->next) { + for (dob = lb->first; dob; dob = dob->next) { Object *ob_iter = dob->ob; - if (ob_iter->type==OB_LAMP) { + if (ob_iter->type == OB_LAMP) { float omat[4][4]; copy_m4_m4(omat, ob_iter->obmat); copy_m4_m4(ob_iter->obmat, dob->mat); @@ -1023,8 +1026,8 @@ static void texture_value_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink static void do_material_tex(GPUShadeInput *shi) { - Material *ma= shi->mat; - GPUMaterial *mat= shi->gpumat; + Material *ma = shi->mat; + GPUMaterial *mat = shi->gpumat; MTex *mtex; Tex *tex; GPUNodeLink *texco, *tin, *trgb, *tnor, *tcol, *stencil, *tnorfac; @@ -1035,9 +1038,9 @@ static void do_material_tex(GPUShadeInput *shi) float one = 1.0f, norfac, ofs[3]; int tex_nr, rgbnor, talpha; bool init_done = false; - int iBumpSpacePrev = 0; /* Not necessary, quiting gcc warning. */ + int iBumpSpacePrev = 0; /* Not necessary, quieting gcc warning. */ GPUNodeLink *vNorg, *vNacc, *fPrevMagnitude; - int iFirstTimeNMap=1; + int iFirstTimeNMap = 1; int found_deriv_map = 0; GPU_link(mat, "set_value", GPU_uniform(&one), &stencil); @@ -1047,44 +1050,46 @@ static void do_material_tex(GPUShadeInput *shi) GPU_link(mat, "texco_object", GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), GPU_builtin(GPU_VIEW_POSITION), &texco_object); - //GPU_link(mat, "texco_tangent", GPU_attribute(CD_TANGENT, ""), &texco_tangent); +#if 0 + GPU_link(mat, "texco_tangent", GPU_attribute(CD_TANGENT, ""), &texco_tangent); +#endif GPU_link(mat, "texco_global", GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_POSITION), &texco_global); orn= texco_norm; /* go over texture slots */ - for (tex_nr=0; tex_nrseptex & (1<septex & (1 << tex_nr)) continue; if (ma->mtex[tex_nr]) { - mtex= ma->mtex[tex_nr]; + mtex = ma->mtex[tex_nr]; - tex= mtex->tex; + tex = mtex->tex; if (tex == NULL) continue; /* which coords */ - if (mtex->texco==TEXCO_ORCO) - texco= texco_orco; - else if (mtex->texco==TEXCO_OBJECT) - texco= texco_object; - else if (mtex->texco==TEXCO_NORM) - texco= orn; - else if (mtex->texco==TEXCO_TANGENT) - texco= texco_object; - else if (mtex->texco==TEXCO_GLOB) - texco= texco_global; - else if (mtex->texco==TEXCO_REFL) { + if (mtex->texco == TEXCO_ORCO) + texco = texco_orco; + else if (mtex->texco == TEXCO_OBJECT) + texco = texco_object; + else if (mtex->texco == TEXCO_NORM) + texco = orn; + else if (mtex->texco == TEXCO_TANGENT) + texco = texco_object; + else if (mtex->texco == TEXCO_GLOB) + texco = texco_global; + else if (mtex->texco == TEXCO_REFL) { GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref); - texco= shi->ref; + texco = shi->ref; } - else if (mtex->texco==TEXCO_UV) { + else if (mtex->texco == TEXCO_UV) { if (1) { //!(texco_uv && strcmp(mtex->uvname, lastuvname) == 0)) { GPU_link(mat, "texco_uv", GPU_attribute(CD_MTFACE, mtex->uvname), &texco_uv); /*lastuvname = mtex->uvname;*/ /*UNUSED*/ } - texco= texco_uv; + texco = texco_uv; } else continue; @@ -1096,8 +1101,8 @@ static void do_material_tex(GPUShadeInput *shi) if (mtex->size[0] != 1.0f || mtex->size[1] != 1.0f || mtex->size[2] != 1.0f) GPU_link(mat, "mtex_mapping_size", texco, GPU_uniform(mtex->size), &texco); - ofs[0] = mtex->ofs[0] + 0.5f - 0.5f*mtex->size[0]; - ofs[1] = mtex->ofs[1] + 0.5f - 0.5f*mtex->size[1]; + ofs[0] = mtex->ofs[0] + 0.5f - 0.5f * mtex->size[0]; + ofs[1] = mtex->ofs[1] + 0.5f - 0.5f * mtex->size[1]; ofs[2] = 0.0f; if (ofs[0] != 0.0f || ofs[1] != 0.0f || ofs[2] != 0.0f) GPU_link(mat, "mtex_mapping_ofs", texco, GPU_uniform(ofs), &texco); @@ -1106,7 +1111,7 @@ static void do_material_tex(GPUShadeInput *shi) if (tex && tex->type == TEX_IMAGE && tex->ima) { GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, false), &tin, &trgb); - rgbnor= TEX_RGB; + rgbnor = TEX_RGB; talpha = ((tex->imaflag & TEX_USEALPHA) && tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0); } @@ -1151,7 +1156,7 @@ static void do_material_tex(GPUShadeInput *shi) GPU_link(mat, "set_value_one", &tin); } - if (tex->type==TEX_IMAGE) + if (tex->type == TEX_IMAGE) if (GPU_material_do_color_management(mat)) GPU_link(mat, "srgb_to_linearrgb", tcol, &tcol); @@ -1175,7 +1180,7 @@ static void do_material_tex(GPUShadeInput *shi) } if (!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_NORM)) { - if (tex->type==TEX_IMAGE) { + if (tex->type == TEX_IMAGE) { found_deriv_map = tex->imaflag & TEX_DERIVATIVEMAP; if (tex->imaflag & TEX_NORMALMAP) { @@ -1225,43 +1230,43 @@ static void do_material_tex(GPUShadeInput *shi) } } - else if ( (mtex->texflag & (MTEX_3TAP_BUMP|MTEX_5TAP_BUMP|MTEX_BICUBIC_BUMP)) || found_deriv_map) { + else if ((mtex->texflag & (MTEX_3TAP_BUMP | MTEX_5TAP_BUMP | MTEX_BICUBIC_BUMP)) || found_deriv_map) { /* ntap bumpmap image */ int iBumpSpace; float ima_x, ima_y; float hScale; - float imag_tspace_dimension_x = 1024.0f; // only used for texture space variant + float imag_tspace_dimension_x = 1024.0f; /* only used for texture space variant */ float aspect = 1.0f; GPUNodeLink *vR1, *vR2; GPUNodeLink *dBs, *dBt, *fDet; - hScale = 0.1; // compatibility adjustment factor for all bumpspace types - if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) - hScale = 13.0f; // factor for scaling texspace bumps + hScale = 0.1; /* compatibility adjustment factor for all bumpspace types */ + if (mtex->texflag & MTEX_BUMP_TEXTURESPACE) + hScale = 13.0f; /* factor for scaling texspace bumps */ else if (found_deriv_map!=0) hScale = 1.0f; - // resolve texture resolution - if ( (mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map ) { - ImBuf *ibuf= BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); - ima_x= 512.0f; ima_y= 512.f; // prevent calling textureSize, glsl 1.3 only + /* resolve texture resolution */ + if ((mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map) { + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); + ima_x = 512.0f; ima_y = 512.f; /* prevent calling textureSize, glsl 1.3 only */ if (ibuf) { - ima_x= ibuf->x; - ima_y= ibuf->y; - aspect = ((float) ima_y) / ima_x; + ima_x = ibuf->x; + ima_y = ibuf->y; + aspect = (float)ima_y / ima_x; } BKE_image_release_ibuf(tex->ima, ibuf, NULL); } - // The negate on norfac is done because the - // normal in the renderer points inward which corresponds - // to inverting the bump map. Should this ever change - // this negate must be removed. + /* The negate on norfac is done because the + * normal in the renderer points inward which corresponds + * to inverting the bump map. Should this ever change + * this negate must be removed. */ norfac = -hScale * mtex->norfac; if (found_deriv_map) { - float fVirtDim = sqrtf(fabsf(ima_x*mtex->size[0]*ima_y*mtex->size[1])); + float fVirtDim = sqrtf(fabsf(ima_x * mtex->size[0] * ima_y * mtex->size[1])); norfac /= MAX2(fVirtDim, FLT_EPSILON); } @@ -1273,26 +1278,26 @@ static void do_material_tex(GPUShadeInput *shi) if (GPU_link_changed(stencil)) GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac); - if ( !init_done ) { - // copy shi->vn to vNorg and vNacc, set magnitude to 1 + if (!init_done) { + /* copy shi->vn to vNorg and vNacc, set magnitude to 1 */ GPU_link(mat, "mtex_bump_normals_init", shi->vn, &vNorg, &vNacc, &fPrevMagnitude); iBumpSpacePrev = 0; init_done = true; } // find current bump space - if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE ) + if (mtex->texflag & MTEX_BUMP_OBJECTSPACE) iBumpSpace = 1; - else if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) + else if (mtex->texflag & MTEX_BUMP_TEXTURESPACE) iBumpSpace = 2; else - iBumpSpace = 4; // ViewSpace + iBumpSpace = 4; /* ViewSpace */ - // re-initialize if bump space changed - if ( iBumpSpacePrev != iBumpSpace ) { + /* re-initialize if bump space changed */ + if (iBumpSpacePrev != iBumpSpace) { GPUNodeLink *surf_pos = GPU_builtin(GPU_VIEW_POSITION); - if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE ) + if (mtex->texflag & MTEX_BUMP_OBJECTSPACE) GPU_link(mat, "mtex_bump_init_objspace", surf_pos, vNorg, GPU_builtin(GPU_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), @@ -1300,7 +1305,7 @@ static void do_material_tex(GPUShadeInput *shi) &fPrevMagnitude, &vNacc, &vR1, &vR2, &fDet); - else if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) + else if (mtex->texflag & MTEX_BUMP_TEXTURESPACE) GPU_link(mat, "mtex_bump_init_texturespace", surf_pos, vNorg, fPrevMagnitude, vNacc, @@ -1321,17 +1326,17 @@ static void do_material_tex(GPUShadeInput *shi) if (found_deriv_map) { GPU_link(mat, "mtex_bump_deriv", texco, GPU_image(tex->ima, &tex->iuser, true), GPU_uniform(&ima_x), GPU_uniform(&ima_y), tnorfac, - &dBs, &dBt ); + &dBs, &dBt); } - else if ( mtex->texflag & MTEX_3TAP_BUMP) + else if (mtex->texflag & MTEX_3TAP_BUMP) GPU_link(mat, "mtex_bump_tap3", texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac, - &dBs, &dBt ); - else if ( mtex->texflag & MTEX_5TAP_BUMP) + &dBs, &dBt); + else if (mtex->texflag & MTEX_5TAP_BUMP) GPU_link(mat, "mtex_bump_tap5", texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac, - &dBs, &dBt ); - else if ( mtex->texflag & MTEX_BICUBIC_BUMP ) { + &dBs, &dBt); + else if (mtex->texflag & MTEX_BICUBIC_BUMP) { if (GPU_bicubic_bump_support()) { GPU_link(mat, "mtex_bump_bicubic", texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac, @@ -1345,18 +1350,18 @@ static void do_material_tex(GPUShadeInput *shi) } - if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) { - float imag_tspace_dimension_y = aspect*imag_tspace_dimension_x; + if (mtex->texflag & MTEX_BUMP_TEXTURESPACE) { + float imag_tspace_dimension_y = aspect * imag_tspace_dimension_x; GPU_link(mat, "mtex_bump_apply_texspace", fDet, dBs, dBt, vR1, vR2, GPU_image(tex->ima, &tex->iuser, true), texco, GPU_uniform(&imag_tspace_dimension_x), GPU_uniform(&imag_tspace_dimension_y), vNacc, - &vNacc, &shi->vn ); + &vNacc, &shi->vn); } else GPU_link(mat, "mtex_bump_apply", fDet, dBs, dBt, vR1, vR2, vNacc, - &vNacc, &shi->vn ); + &vNacc, &shi->vn); } } @@ -1466,10 +1471,10 @@ void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi) void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) { - GPUMaterial *mat= shi->gpumat; + GPUMaterial *mat = shi->gpumat; GPUNodeLink *emit, *ulinfac, *ulogfac, *mistfac; - Material *ma= shi->mat; - World *world= mat->scene->world; + Material *ma = shi->mat; + World *world = mat->scene->world; float linfac, logfac, misttype; memset(shr, 0, sizeof(*shr)); @@ -1487,7 +1492,7 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) } else { if (GPU_link_changed(shi->emit) || ma->emit != 0.0f) { - if ((ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL) { + if ((ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) == MA_VERTEXCOL) { GPU_link(mat, "shade_add", shi->emit, shi->vcol, &emit); GPU_link(mat, "shade_mul", emit, shi->rgb, &shr->diff); } @@ -1507,9 +1512,9 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) if (world) { /* exposure correction */ - if (world->exp!=0.0f || world->range!=1.0f) { - linfac= 1.0f + powf((2.0f*world->exp + 0.5f), -10); - logfac= logf((linfac-1.0f)/linfac)/world->range; + if (world->exp != 0.0f || world->range != 1.0f) { + linfac = 1.0f + powf((2.0f * world->exp + 0.5f), -10); + logfac = logf((linfac - 1.0f) / linfac) / world->range; GPU_link(mat, "set_value", GPU_uniform(&linfac), &ulinfac); GPU_link(mat, "set_value", GPU_uniform(&logfac), &ulogfac); @@ -1521,7 +1526,7 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) } /* ambient color */ - if (world->ambr!=0.0f || world->ambg!=0.0f || world->ambb!=0.0f) { + if (world->ambr != 0.0f || world->ambg != 0.0f || world->ambb != 0.0f) { if (GPU_link_changed(shi->amb) || ma->amb != 0.0f) GPU_link(mat, "shade_maddf", shr->combined, GPU_uniform(&ma->amb), GPU_uniform(&world->ambr), &shr->combined); @@ -1612,7 +1617,7 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma) GPUNodeLink *outlink; LinkData *link; - for (link=ma->gpumaterial.first; link; link=link->next) + for (link = ma->gpumaterial.first; link; link = link->next) if (((GPUMaterial*)link->data)->scene == scene) return link->data; @@ -1648,7 +1653,7 @@ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo) LinkData *link; GPUMaterial *mat; - for (link=wo->gpumaterial.first; link; link=link->next) + for (link = wo->gpumaterial.first; link; link = link->next) if (((GPUMaterial*)link->data)->scene == scene) return link->data; @@ -1688,7 +1693,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) GPUNodeLink *outlink; LinkData *link; - for (link=ma->gpumaterial.first; link; link=link->next) + for (link = ma->gpumaterial.first; link; link = link->next) if (((GPUMaterial*)link->data)->scene == scene) return link->data; @@ -1745,15 +1750,15 @@ void GPU_materials_free(void) World *wo; extern Material defmaterial; - for (ma=G.main->mat.first; ma; ma=ma->id.next) + for (ma = G.main->mat.first; ma; ma = ma->id.next) GPU_material_free(&ma->gpumaterial); - for (wo=G.main->world.first; wo; wo=wo->id.next) + for (wo = G.main->world.first; wo; wo = wo->id.next) GPU_material_free(&wo->gpumaterial); GPU_material_free(&defmaterial.gpumaterial); - for (ob=G.main->object.first; ob; ob=ob->id.next) + for (ob = G.main->object.first; ob; ob = ob->id.next) GPU_lamp_free(ob); } @@ -1795,11 +1800,11 @@ void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]) void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy) { lamp->energy = energy; - if (lamp->mode & LA_NEG) lamp->energy= -lamp->energy; + if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy; - lamp->col[0]= r; - lamp->col[1]= g; - lamp->col[2]= b; + lamp->col[0] = r; + lamp->col[1] = g; + lamp->col[2] = b; } void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2) @@ -1829,11 +1834,11 @@ static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *l lamp->type = la->type; lamp->energy = la->energy; - if (lamp->mode & LA_NEG) lamp->energy= -lamp->energy; + if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy; - lamp->col[0]= la->r; - lamp->col[1]= la->g; - lamp->col[2]= la->b; + lamp->col[0] = la->r; + lamp->col[1] = la->g; + lamp->col[2] = la->b; GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat); @@ -1842,20 +1847,20 @@ static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *l if (lamp->spotsi > DEG2RADF(170.0f)) lamp->spotsi = DEG2RADF(170.0f); lamp->spotsi = cosf(lamp->spotsi * 0.5f); - lamp->spotbl= (1.0f - lamp->spotsi)*la->spotblend; - lamp->k= la->k; + lamp->spotbl = (1.0f - lamp->spotsi) * la->spotblend; + lamp->k = la->k; - lamp->dist= la->dist; - lamp->falloff_type= la->falloff_type; - lamp->att1= la->att1; - lamp->att2= la->att2; - lamp->curfalloff= la->curfalloff; + lamp->dist = la->dist; + lamp->falloff_type = la->falloff_type; + lamp->att1 = la->att1; + lamp->att2 = la->att2; + lamp->curfalloff = la->curfalloff; /* initshadowbuf */ - lamp->bias = 0.02f*la->bias; + lamp->bias = 0.02f * la->bias; lamp->size = la->bufsize; - lamp->d= la->clipsta; - lamp->clipend= la->clipend; + lamp->d = la->clipsta; + lamp->clipend = la->clipend; /* arbitrary correction for the fact we do no soft transition */ lamp->bias *= 0.25f; @@ -1868,23 +1873,23 @@ static void gpu_lamp_shadow_free(GPULamp *lamp) { if (lamp->tex) { GPU_texture_free(lamp->tex); - lamp->tex= NULL; + lamp->tex = NULL; } if (lamp->depthtex) { GPU_texture_free(lamp->depthtex); - lamp->depthtex= NULL; + lamp->depthtex = NULL; } if (lamp->fb) { GPU_framebuffer_free(lamp->fb); - lamp->fb= NULL; + lamp->fb = NULL; } if (lamp->blurtex) { GPU_texture_free(lamp->blurtex); - lamp->blurtex= NULL; + lamp->blurtex = NULL; } if (lamp->blurfb) { GPU_framebuffer_free(lamp->blurfb); - lamp->blurfb= NULL; + lamp->blurfb = NULL; } } @@ -1894,7 +1899,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) GPULamp *lamp; LinkData *link; - for (link=ob->gpulamp.first; link; link=link->next) { + for (link = ob->gpulamp.first; link; link = link->next) { lamp = (GPULamp*)link->data; if (lamp->par == par && lamp->scene == scene) @@ -1910,7 +1915,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) la = ob->data; gpu_lamp_from_blender(scene, ob, par, la, lamp); - if ((la->type==LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) || (la->type==LA_SUN && (la->mode & LA_SHAD_RAY))) { + if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) || (la->type == LA_SUN && (la->mode & LA_SHAD_RAY))) { /* opengl */ lamp->fb = GPU_framebuffer_create(); if (!lamp->fb) { @@ -1955,7 +1960,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) return lamp; } - lamp->blurtex = GPU_texture_create_vsm_shadow_map(lamp->size*0.5, NULL); + lamp->blurtex = GPU_texture_create_vsm_shadow_map(lamp->size * 0.5, NULL); if (!lamp->blurtex) { gpu_lamp_shadow_free(lamp); return lamp; @@ -2016,7 +2021,7 @@ void GPU_lamp_free(Object *ob) LinkData *nlink; Material *ma; - for (link=ob->gpulamp.first; link; link=link->next) { + for (link = ob->gpulamp.first; link; link = link->next) { lamp = link->data; while (lamp->materials.first) { @@ -2275,7 +2280,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma) } /* process builtin uniform */ - for (i=0; builtins[i].gputype; i++) { + for (i = 0; builtins[i].gputype; i++) { if (mat->builtins & builtins[i].gputype) { uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform"); uniform->type = builtins[i].dynamictype; @@ -2289,14 +2294,14 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma) /* TBD: remove the function that are not used in the main function */ liblen = (pass->libcode) ? strlen(pass->libcode) : 0; fraglen = strlen(pass->fragmentcode); - shader->fragment = (char *)MEM_mallocN(liblen+fraglen+1, "GPUFragShader"); + shader->fragment = (char *)MEM_mallocN(liblen + fraglen + 1, "GPUFragShader"); if (pass->libcode) memcpy(shader->fragment, pass->libcode, liblen); memcpy(&shader->fragment[liblen], pass->fragmentcode, fraglen); - shader->fragment[liblen+fraglen] = 0; + shader->fragment[liblen + fraglen] = 0; // export the attribute - for (i=0; iattribs.totlayer; i++) { + for (i = 0; i < mat->attribs.totlayer; i++) { attribute = MEM_callocN(sizeof(GPUInputAttribute), "GPUInputAttribute"); attribute->type = mat->attribs.layer[i].type; attribute->number = mat->attribs.layer[i].glindex; @@ -2325,7 +2330,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma) MEM_freeN(attribute); } - // export the vertex shader + /* export the vertex shader */ shader->vertex = BLI_strdup(pass->vertexcode); } @@ -2339,7 +2344,7 @@ void GPU_free_shader_export(GPUShaderExport *shader) if (shader == NULL) return; - for (uniform = shader->uniforms.first; uniform; uniform=uniform->next) + for (uniform = shader->uniforms.first; uniform; uniform = uniform->next) if (uniform->texpixels) MEM_freeN(uniform->texpixels); -- cgit v1.2.3 From 2affbb437bd3cbf3e1a502bd65a5eefb64a92b9b Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Mon, 23 Mar 2015 21:36:08 +0100 Subject: BGE: Multitexture world (mist, ambient) fix This patch fix the existing word API for mist and global ambient lighting. Add deprecated message to disableMist() Add setUseMist(enable). Reviewers: dfelinto, campbellbarton, moguri Reviewed By: moguri Subscribers: solarlune, jta, brecht Projects: #bf_blender:_next Differential Revision: https://developer.blender.org/D148 --- doc/python_api/rst/bge.render.rst | 9 +- source/gameengine/Converter/BlenderWorldInfo.cpp | 41 ++++---- source/gameengine/Converter/BlenderWorldInfo.h | 6 +- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 17 ++-- source/gameengine/Ketsji/KX_PythonInit.cpp | 113 +++++++++++---------- source/gameengine/Ketsji/KX_WorldInfo.h | 8 +- source/gameengine/Ketsji/KX_WorldIpoController.cpp | 4 +- source/gameengine/Rasterizer/RAS_IRasterizer.h | 2 +- .../RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp | 16 +-- .../RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h | 2 +- 10 files changed, 111 insertions(+), 107 deletions(-) diff --git a/doc/python_api/rst/bge.render.rst b/doc/python_api/rst/bge.render.rst index 77d5bd71761..3abbd50a453 100644 --- a/doc/python_api/rst/bge.render.rst +++ b/doc/python_api/rst/bge.render.rst @@ -198,9 +198,16 @@ Functions Disables mist. - .. note:: Set any of the mist properties to enable mist. + .. note:: Deprecated use setUseMist(). +.. function:: setUseMist(enable) + + Disable or enable the mist. + + :type enable: boolean + + .. function:: setEyeSeparation(eyesep) Sets the eye separation for stereo mode. Usually Focal Length/30 provides a confortable value. diff --git a/source/gameengine/Converter/BlenderWorldInfo.cpp b/source/gameengine/Converter/BlenderWorldInfo.cpp index 75beb5d0e0e..28e42c1cc63 100644 --- a/source/gameengine/Converter/BlenderWorldInfo.cpp +++ b/source/gameengine/Converter/BlenderWorldInfo.cpp @@ -69,21 +69,10 @@ BlenderWorldInfo::BlenderWorldInfo(struct Scene *blenderscene, struct World *ble { if (blenderworld) { m_hasworld = true; - - // do we have mist? - if ((blenderworld->mode) & WO_MIST) { - m_hasmist = true; - m_miststart = blenderworld->miststa; - m_mistdistance = blenderworld->mistdist; - copy_v3_v3(m_mistcolor, &blenderworld->horr); - } - else { - m_hasmist = false; - m_miststart = 0.0; - m_mistdistance = 0.0; - zero_v3(m_mistcolor); - } - + m_hasmist = ((blenderworld->mode) & WO_MIST ? true : false); + m_miststart = blenderworld->miststa; + m_mistdistance = blenderworld->mistdist; + copy_v3_v3(m_mistcolor, &blenderworld->horr); copy_v3_v3(m_backgroundcolor, &blenderworld->horr); copy_v3_v3(m_ambientcolor, &blenderworld->ambr); @@ -174,6 +163,11 @@ void BlenderWorldInfo::setBackColor(float r, float g, float b) m_backgroundcolor[2] = b; } +void BlenderWorldInfo::setUseMist(bool enable) +{ + m_hasmist = enable; +} + void BlenderWorldInfo::setMistStart(float d) { m_miststart = d; @@ -184,17 +178,16 @@ void BlenderWorldInfo::setMistDistance(float d) m_mistdistance = d; } -void BlenderWorldInfo::setMistColorRed(float d) -{ - m_mistcolor[0] = d; -} - -void BlenderWorldInfo::setMistColorGreen(float d) +void BlenderWorldInfo::setMistColor(float r, float g, float b) { - m_mistcolor[1] = d; + m_mistcolor[0] = r; + m_mistcolor[1] = g; + m_mistcolor[2] = b; } -void BlenderWorldInfo::setMistColorBlue(float d) +void BlenderWorldInfo::setAmbientColor(float r, float g, float b) { - m_mistcolor[2] = d; + m_ambientcolor[0] = r; + m_ambientcolor[1] = g; + m_ambientcolor[2] = b; } diff --git a/source/gameengine/Converter/BlenderWorldInfo.h b/source/gameengine/Converter/BlenderWorldInfo.h index 2ac2d70b5d1..6c67681c3bc 100644 --- a/source/gameengine/Converter/BlenderWorldInfo.h +++ b/source/gameengine/Converter/BlenderWorldInfo.h @@ -67,11 +67,11 @@ public: float getMistColorBlue(); void setBackColor(float r, float g, float b); + void setUseMist(bool enable); void setMistStart(float d); void setMistDistance(float d); - void setMistColorRed(float d); - void setMistColorGreen(float d); - void setMistColorBlue(float d); + void setMistColor(float r, float g, float b); + void setAmbientColor(float r, float g, float b); #ifdef WITH_CXX_GUARDEDALLOC diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index e453b757b7e..44b667e15e0 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -985,15 +985,14 @@ void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi) { if (wi->hasWorld()) { - // ... - m_rasterizer->SetAmbientColor( - wi->getAmbientColorRed(), - wi->getAmbientColorGreen(), - wi->getAmbientColorBlue() - ); - if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) { + m_rasterizer->SetAmbientColor( + wi->getAmbientColorRed(), + wi->getAmbientColorGreen(), + wi->getAmbientColorBlue() + ); + if (wi->hasMist()) { m_rasterizer->SetFog( @@ -1003,6 +1002,10 @@ void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi) wi->getMistColorGreen(), wi->getMistColorBlue() ); + m_rasterizer->EnableFog(true); + } + else { + m_rasterizer->EnableFog(false); } } } diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index d7dd3fe5253..e0af3283f44 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -1029,108 +1029,118 @@ static PyObject *gPyGetStereoEye(PyObject *, PyObject *, PyObject *) static PyObject *gPySetBackgroundColor(PyObject *, PyObject *value) { - MT_Vector4 vec; if (!PyVecTo(value, vec)) return NULL; - - if (gp_Canvas) - { - gp_Rasterizer->SetBackColor((float)vec[0], (float)vec[1], (float)vec[2], (float)vec[3]); - } KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); - if (wi->hasWorld()) - wi->setBackColor((float)vec[0], (float)vec[1], (float)vec[2]); + if (!wi->hasWorld()) { + PyErr_SetString(PyExc_RuntimeError, "bge.render.SetBackgroundColor(color), World not available"); + return NULL; + } + + wi->setBackColor((float)vec[0], (float)vec[1], (float)vec[2]); Py_RETURN_NONE; } - - static PyObject *gPySetMistColor(PyObject *, PyObject *value) { - MT_Vector3 vec; if (!PyVecTo(value, vec)) return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available"); + + KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); + if (!wi->hasWorld()) { + PyErr_SetString(PyExc_RuntimeError, "bge.render.setMistColor(color), World not available"); return NULL; } - gp_Rasterizer->SetFogColor((float)vec[0], (float)vec[1], (float)vec[2]); - + + wi->setMistColor((float)vec[0], (float)vec[1], (float)vec[2]); + Py_RETURN_NONE; } static PyObject *gPyDisableMist(PyObject *) { - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available"); + KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); + if (!wi->hasWorld()) { + PyErr_SetString(PyExc_RuntimeError, "bge.render.DisableMist(), World not available"); return NULL; } - gp_Rasterizer->DisableFog(); - + ShowDeprecationWarning("DisableMist()", "setUseMist(false)"); + wi->setUseMist(false); + Py_RETURN_NONE; } -static PyObject *gPySetMistStart(PyObject *, PyObject *args) +static PyObject *gPySetUseMist(PyObject *, PyObject *args) { + int enable; + if (!PyArg_ParseTuple(args,"i:setUseMist",&enable)) + return NULL; + + KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); + if (!wi->hasWorld()) { + PyErr_SetString(PyExc_RuntimeError, "bge.render.setUseMist(enable), World not available"); + return NULL; + } + + wi->setUseMist(enable); + + Py_RETURN_NONE; +} +static PyObject *gPySetMistStart(PyObject *, PyObject *args) +{ float miststart; if (!PyArg_ParseTuple(args,"f:setMistStart",&miststart)) return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistStart(float), Rasterizer not available"); + + KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); + if (!wi->hasWorld()) { + PyErr_SetString(PyExc_RuntimeError, "bge.render.setMistStart(float), World not available"); return NULL; } - - gp_Rasterizer->SetFogStart(miststart); - - Py_RETURN_NONE; -} + wi->setMistStart(miststart); + Py_RETURN_NONE; +} static PyObject *gPySetMistEnd(PyObject *, PyObject *args) { - - float mistend; - if (!PyArg_ParseTuple(args,"f:setMistEnd",&mistend)) + float mistdist; + if (!PyArg_ParseTuple(args,"f:setMistEnd",&mistdist)) return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistEnd(float), Rasterizer not available"); + + KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); + if (!wi->hasWorld()) { + PyErr_SetString(PyExc_RuntimeError, "bge.render.setMistEnd(float), World not available"); return NULL; } - - gp_Rasterizer->SetFogEnd(mistend); - + + wi->setMistDistance(mistdist); + Py_RETURN_NONE; } - static PyObject *gPySetAmbientColor(PyObject *, PyObject *value) { - MT_Vector3 vec; if (!PyVecTo(value, vec)) return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setAmbientColor(color), Rasterizer not available"); + + KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); + if (!wi->hasWorld()) { + PyErr_SetString(PyExc_RuntimeError, "bge.render.setAmbientColor(color), World not available"); return NULL; } - gp_Rasterizer->SetAmbientColor((float)vec[0], (float)vec[1], (float)vec[2]); - - Py_RETURN_NONE; -} - + wi->setAmbientColor((float)vec[0], (float)vec[1], (float)vec[2]); + Py_RETURN_NONE; +} static PyObject *gPyMakeScreenshot(PyObject *, PyObject *args) { @@ -1510,9 +1520,10 @@ static struct PyMethodDef rasterizer_methods[] = { {"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_O,"set Background Color (rgb)"}, {"setAmbientColor",(PyCFunction)gPySetAmbientColor,METH_O,"set Ambient Color (rgb)"}, {"disableMist",(PyCFunction)gPyDisableMist,METH_NOARGS,"turn off mist"}, + {"setUseMist",(PyCFunction)gPySetUseMist,METH_VARARGS,"enable or disable mist"}, {"setMistColor",(PyCFunction)gPySetMistColor,METH_O,"set Mist Color (rgb)"}, - {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start(rgb)"}, - {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End(rgb)"}, + {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start"}, + {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End"}, {"enableMotionBlur",(PyCFunction)gPyEnableMotionBlur,METH_VARARGS,"enable motion blur"}, {"disableMotionBlur",(PyCFunction)gPyDisableMotionBlur,METH_NOARGS,"disable motion blur"}, diff --git a/source/gameengine/Ketsji/KX_WorldInfo.h b/source/gameengine/Ketsji/KX_WorldInfo.h index 90b16fe1242..251ba95f43a 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.h +++ b/source/gameengine/Ketsji/KX_WorldInfo.h @@ -61,12 +61,12 @@ public: virtual float getAmbientColorGreen() = 0; virtual float getAmbientColorBlue() = 0; - virtual void setBackColor(float, float, float) = 0; + virtual void setUseMist(bool enable) = 0; virtual void setMistStart(float) = 0; virtual void setMistDistance(float) = 0; - virtual void setMistColorRed(float) = 0; - virtual void setMistColorGreen(float) = 0; - virtual void setMistColorBlue(float) = 0; + virtual void setMistColor(float, float, float) = 0; + virtual void setBackColor(float, float, float) = 0; + virtual void setAmbientColor(float,float,float) = 0; #ifdef WITH_CXX_GUARDEDALLOC diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.cpp b/source/gameengine/Ketsji/KX_WorldIpoController.cpp index 7f83a155643..a30d89284b8 100644 --- a/source/gameengine/Ketsji/KX_WorldIpoController.cpp +++ b/source/gameengine/Ketsji/KX_WorldIpoController.cpp @@ -57,9 +57,7 @@ bool KX_WorldIpoController::Update(double currentTime) } if (m_modify_mist_color) { - world->setMistColorRed(m_mist_rgb[0]); - world->setMistColorGreen(m_mist_rgb[1]); - world->setMistColorBlue(m_mist_rgb[2]); + world->setMistColor(m_mist_rgb[0], m_mist_rgb[1], m_mist_rgb[2]); } if (m_modify_mist_dist) { diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index d7b52213191..6f5273f035f 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -302,7 +302,7 @@ public: virtual void SetFogStart(float start) = 0; virtual void SetFogEnd(float end) = 0; virtual void DisplayFog() = 0; - virtual void DisableFog() = 0; + virtual void EnableFog(bool enable) = 0; virtual bool IsFogEnabled() = 0; virtual void SetBackColor(float red, float green, float blue, float alpha) = 0; diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 116a11339d9..14a184bbe7f 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -229,7 +229,6 @@ void RAS_OpenGLRasterizer::SetFogColor(float r, m_fogr = r; m_fogg = g; m_fogb = b; - m_fogenabled = true; } @@ -237,7 +236,6 @@ void RAS_OpenGLRasterizer::SetFogColor(float r, void RAS_OpenGLRasterizer::SetFogStart(float start) { m_fogstart = start; - m_fogenabled = true; } @@ -245,7 +243,6 @@ void RAS_OpenGLRasterizer::SetFogStart(float start) void RAS_OpenGLRasterizer::SetFogEnd(float fogend) { m_fogdist = fogend; - m_fogenabled = true; } @@ -261,14 +258,13 @@ void RAS_OpenGLRasterizer::SetFog(float start, m_fogr = r; m_fogg = g; m_fogb = b; - m_fogenabled = true; } -void RAS_OpenGLRasterizer::DisableFog() +void RAS_OpenGLRasterizer::EnableFog(bool enable) { - m_fogenabled = false; + m_fogenabled = enable; } bool RAS_OpenGLRasterizer::IsFogEnabled() @@ -281,16 +277,12 @@ void RAS_OpenGLRasterizer::DisplayFog() { if ((m_drawingmode >= KX_SOLID) && m_fogenabled) { - float params[5]; + float params[4] = {m_fogr, m_fogg, m_fogb, 1.0f}; glFogi(GL_FOG_MODE, GL_LINEAR); glFogf(GL_FOG_DENSITY, 0.1f); glFogf(GL_FOG_START, m_fogstart); glFogf(GL_FOG_END, m_fogstart + m_fogdist); - params[0] = m_fogr; - params[1] = m_fogg; - params[2] = m_fogb; - params[3] = 0.0; - glFogfv(GL_FOG_COLOR, params); + glFogfv(GL_FOG_COLOR, params); glEnable(GL_FOG); } else diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 1334ddb2a26..042243230b3 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -202,7 +202,7 @@ public: virtual void SetFogColor(float r, float g, float b); virtual void SetFogStart(float fogstart); virtual void SetFogEnd(float fogend); - void DisableFog(); + virtual void EnableFog(bool enable); virtual void DisplayFog(); virtual bool IsFogEnabled(); -- cgit v1.2.3 From d07c666a0e542517914dad580d1b3f4787525852 Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Mon, 23 Mar 2015 21:40:11 +0100 Subject: BGE: Add setMistType and setMistIntensity API. This patch adds the missing setMistType() and setMistIntensity() to the API Reviewers: campbellbarton, brecht, moguri Reviewed By: campbellbarton, brecht, moguri Subscribers: campbellbarton, dingto Differential Revision: https://developer.blender.org/D149 --- doc/python_api/rst/bge.render.rst | 39 +++++++++++++++--- source/gameengine/Converter/BlenderWorldInfo.cpp | 21 ++++++++++ source/gameengine/Converter/BlenderWorldInfo.h | 6 +++ source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 2 + source/gameengine/Ketsji/KX_PythonInit.cpp | 48 ++++++++++++++++++++++ source/gameengine/Ketsji/KX_WorldInfo.h | 13 ++++++ source/gameengine/Rasterizer/RAS_IRasterizer.h | 2 +- .../RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp | 8 +++- .../RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h | 4 +- 9 files changed, 133 insertions(+), 10 deletions(-) diff --git a/doc/python_api/rst/bge.render.rst b/doc/python_api/rst/bge.render.rst index 3abbd50a453..09d16f4b2ed 100644 --- a/doc/python_api/rst/bge.render.rst +++ b/doc/python_api/rst/bge.render.rst @@ -87,6 +87,19 @@ Constants Right eye being used during stereoscopic rendering. +.. data:: KX_MIST_QUADRATIC + + Type of quadratic attenuation used to fade mist. + +.. data:: KX_MIST_LINEAR + + Type of linear attenuation used to fade mist. + +.. data:: KX_MIST_INV_QUADRATIC + + Type of inverse quadratic attenuation used to fade mist. + + ********* Functions ********* @@ -165,20 +178,27 @@ Functions :type rgba: list [r, g, b, a] -.. function:: setMistColor(rgb) +.. function:: setAmbientColor(rgb) - Sets the mist color. + Sets the color of ambient light. :type rgb: list [r, g, b] - -.. function:: setAmbientColor(rgb) - Sets the color of ambient light. +.. function:: setMistColor(rgb) + + Sets the mist color. :type rgb: list [r, g, b] +.. function:: setMistType(mode) + + Sets the mist attenuation type. + + :type mode: KX_MIST_QUADRATIC, KX_MIST_LINEAR, KX_MIST_INV_QUADRATIC + + .. function:: setMistStart(start) Sets the mist start value. Objects further away than start will have mist applied to them. @@ -193,9 +213,16 @@ Functions :type end: float - + +.. function:: setMistIntensity(intensity) + + Sets the mist intensity value. + + :type start: float + .. function:: disableMist() + Disables mist. .. note:: Deprecated use setUseMist(). diff --git a/source/gameengine/Converter/BlenderWorldInfo.cpp b/source/gameengine/Converter/BlenderWorldInfo.cpp index 28e42c1cc63..5f476949616 100644 --- a/source/gameengine/Converter/BlenderWorldInfo.cpp +++ b/source/gameengine/Converter/BlenderWorldInfo.cpp @@ -70,8 +70,10 @@ BlenderWorldInfo::BlenderWorldInfo(struct Scene *blenderscene, struct World *ble if (blenderworld) { m_hasworld = true; m_hasmist = ((blenderworld->mode) & WO_MIST ? true : false); + m_misttype = blenderworld->mistype; m_miststart = blenderworld->miststa; m_mistdistance = blenderworld->mistdist; + m_mistintensity = blenderworld->misi; copy_v3_v3(m_mistcolor, &blenderworld->horr); copy_v3_v3(m_backgroundcolor, &blenderworld->horr); copy_v3_v3(m_ambientcolor, &blenderworld->ambr); @@ -131,6 +133,11 @@ float BlenderWorldInfo::getAmbientColorBlue() return m_ambientcolor[2]; } +short BlenderWorldInfo::getMistType() +{ + return m_misttype; +} + float BlenderWorldInfo::getMistStart() { return m_miststart; @@ -141,6 +148,11 @@ float BlenderWorldInfo::getMistDistance() return m_mistdistance; } +float BlenderWorldInfo::getMistIntensity() +{ + return m_mistintensity; +} + float BlenderWorldInfo::getMistColorRed() { return m_mistcolor[0]; @@ -163,6 +175,11 @@ void BlenderWorldInfo::setBackColor(float r, float g, float b) m_backgroundcolor[2] = b; } +void BlenderWorldInfo::setMistType(short type) +{ + m_misttype = type; +} + void BlenderWorldInfo::setUseMist(bool enable) { m_hasmist = enable; @@ -178,6 +195,10 @@ void BlenderWorldInfo::setMistDistance(float d) m_mistdistance = d; } +void BlenderWorldInfo::setMistIntensity(float intensity) +{ + m_mistintensity = intensity; +} void BlenderWorldInfo::setMistColor(float r, float g, float b) { m_mistcolor[0] = r; diff --git a/source/gameengine/Converter/BlenderWorldInfo.h b/source/gameengine/Converter/BlenderWorldInfo.h index 6c67681c3bc..4184d428808 100644 --- a/source/gameengine/Converter/BlenderWorldInfo.h +++ b/source/gameengine/Converter/BlenderWorldInfo.h @@ -40,8 +40,10 @@ class BlenderWorldInfo : public KX_WorldInfo float m_backgroundcolor[3]; bool m_hasmist; + short m_misttype; float m_miststart; float m_mistdistance; + float m_mistintensity; float m_mistcolor[3]; float m_ambientcolor[3]; @@ -60,16 +62,20 @@ public: float getAmbientColorGreen(); float getAmbientColorBlue(); + short getMistType(); float getMistStart(); float getMistDistance(); + float getMistIntensity(); float getMistColorRed(); float getMistColorGreen(); float getMistColorBlue(); void setBackColor(float r, float g, float b); void setUseMist(bool enable); + void setMistType(short type); void setMistStart(float d); void setMistDistance(float d); + void setMistIntensity(float intensity); void setMistColor(float r, float g, float b); void setAmbientColor(float r, float g, float b); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 44b667e15e0..8c6cb2b32d4 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -996,8 +996,10 @@ void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi) if (wi->hasMist()) { m_rasterizer->SetFog( + wi->getMistType(), wi->getMistStart(), wi->getMistDistance(), + wi->getMistIntensity(), wi->getMistColorRed(), wi->getMistColorGreen(), wi->getMistColorBlue() diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index e0af3283f44..8fd38db4a2a 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -1091,6 +1091,29 @@ static PyObject *gPySetUseMist(PyObject *, PyObject *args) Py_RETURN_NONE; } +static PyObject *gPySetMistType(PyObject *, PyObject *args) +{ + short type; + + if (!PyArg_ParseTuple(args,"i:setMistType",&type)) + return NULL; + + if (type < 0 || type > 2) { + PyErr_SetString(PyExc_ValueError, "Rasterizer.setMistType(int): Mist type is not known"); + return NULL; + } + + KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); + if (!wi->hasWorld()) { + PyErr_SetString(PyExc_RuntimeError, "bge.render.setMistType(int), World not available"); + return NULL; + } + + wi->setMistType(type); + + Py_RETURN_NONE; +} + static PyObject *gPySetMistStart(PyObject *, PyObject *args) { float miststart; @@ -1125,6 +1148,24 @@ static PyObject *gPySetMistEnd(PyObject *, PyObject *args) Py_RETURN_NONE; } +static PyObject *gPySetMistIntensity(PyObject *, PyObject *args) +{ + + float intensity; + if (!PyArg_ParseTuple(args,"f:setMistIntensity",&intensity)) + return NULL; + + KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); + if (!wi->hasWorld()) { + PyErr_SetString(PyExc_RuntimeError, "bge.render.setMistIntensity(float), World not available"); + return NULL; + } + + wi->setMistIntensity(intensity); + + Py_RETURN_NONE; +} + static PyObject *gPySetAmbientColor(PyObject *, PyObject *value) { MT_Vector3 vec; @@ -1522,8 +1563,10 @@ static struct PyMethodDef rasterizer_methods[] = { {"disableMist",(PyCFunction)gPyDisableMist,METH_NOARGS,"turn off mist"}, {"setUseMist",(PyCFunction)gPySetUseMist,METH_VARARGS,"enable or disable mist"}, {"setMistColor",(PyCFunction)gPySetMistColor,METH_O,"set Mist Color (rgb)"}, + {"setMistType",(PyCFunction)gPySetMistType,METH_VARARGS,"set mist type (short type)"}, {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start"}, {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End"}, + {"setMistIntensity",(PyCFunction)gPySetMistIntensity,METH_VARARGS,"set mist intensity (float intensity)"}, {"enableMotionBlur",(PyCFunction)gPyEnableMotionBlur,METH_VARARGS,"enable motion blur"}, {"disableMotionBlur",(PyCFunction)gPyDisableMotionBlur,METH_NOARGS,"disable motion blur"}, @@ -2370,6 +2413,11 @@ PyMODINIT_FUNC initRasterizerPythonBinding() KX_MACRO_addTypesToDict(d, LEFT_EYE, RAS_IRasterizer::RAS_STEREO_LEFTEYE); KX_MACRO_addTypesToDict(d, RIGHT_EYE, RAS_IRasterizer::RAS_STEREO_RIGHTEYE); + /* KX_WorldInfo mist types */ + KX_MACRO_addTypesToDict(d, KX_MIST_QUADRATIC, KX_WorldInfo::KX_MIST_QUADRATIC); + KX_MACRO_addTypesToDict(d, KX_MIST_LINEAR, KX_WorldInfo::KX_MIST_LINEAR); + KX_MACRO_addTypesToDict(d, KX_MIST_INV_QUADRATIC, KX_WorldInfo::KX_MIST_INV_QUADRATIC); + // XXXX Add constants here // Check for errors diff --git a/source/gameengine/Ketsji/KX_WorldInfo.h b/source/gameengine/Ketsji/KX_WorldInfo.h index 251ba95f43a..f90a4ff6b6d 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.h +++ b/source/gameengine/Ketsji/KX_WorldInfo.h @@ -43,6 +43,15 @@ class MT_CmMatrix4x4; class KX_WorldInfo { public: + /** + * Mist options + */ + enum MistType { + KX_MIST_QUADRATIC, + KX_MIST_LINEAR, + KX_MIST_INV_QUADRATIC, + }; + KX_WorldInfo() {} virtual ~KX_WorldInfo(); @@ -51,8 +60,10 @@ public: virtual float getBackColorRed() = 0; virtual float getBackColorGreen() = 0; virtual float getBackColorBlue() = 0; + virtual short getMistType() = 0; virtual float getMistStart() = 0; virtual float getMistDistance() = 0; + virtual float getMistIntensity() = 0; virtual float getMistColorRed() = 0; virtual float getMistColorGreen() = 0; virtual float getMistColorBlue() = 0; @@ -62,8 +73,10 @@ public: virtual float getAmbientColorBlue() = 0; virtual void setUseMist(bool enable) = 0; + virtual void setMistType(short) = 0; virtual void setMistStart(float) = 0; virtual void setMistDistance(float) = 0; + virtual void setMistIntensity(float) = 0; virtual void setMistColor(float, float, float) = 0; virtual void setBackColor(float, float, float) = 0; virtual void setAmbientColor(float,float,float) = 0; diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index 6f5273f035f..22ffcd48739 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -297,7 +297,7 @@ public: /** * Fog */ - virtual void SetFog(float start, float dist, float r, float g, float b) = 0; + virtual void SetFog(short type, float start, float dist, float intensity, float r, float g, float b) = 0; virtual void SetFogColor(float r, float g,float b) = 0; virtual void SetFogStart(float start) = 0; virtual void SetFogEnd(float end) = 0; diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 14a184bbe7f..9269640afa3 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -247,14 +247,18 @@ void RAS_OpenGLRasterizer::SetFogEnd(float fogend) -void RAS_OpenGLRasterizer::SetFog(float start, +void RAS_OpenGLRasterizer::SetFog(short type, + float start, float dist, + float intensity, float r, float g, float b) { + m_fogtype = type; m_fogstart = start; m_fogdist = dist; + m_fogintensity = intensity; m_fogr = r; m_fogg = g; m_fogb = b; @@ -279,7 +283,7 @@ void RAS_OpenGLRasterizer::DisplayFog() { float params[4] = {m_fogr, m_fogg, m_fogb, 1.0f}; glFogi(GL_FOG_MODE, GL_LINEAR); - glFogf(GL_FOG_DENSITY, 0.1f); + glFogf(GL_FOG_DENSITY, m_fogintensity / 10.0f); glFogf(GL_FOG_START, m_fogstart); glFogf(GL_FOG_END, m_fogstart + m_fogdist); glFogfv(GL_FOG_COLOR, params); diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 042243230b3..48023f9786c 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -80,8 +80,10 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer /* fogging vars */ bool m_fogenabled; + short m_fogtype; float m_fogstart; float m_fogdist; + float m_fogintensity; float m_fogr; float m_fogg; float m_fogb; @@ -198,7 +200,7 @@ public: virtual const MT_Point3& GetCameraPosition(); virtual bool GetCameraOrtho(); - virtual void SetFog(float start, float dist, float r, float g, float b); + virtual void SetFog(short type, float start, float dist, float intensity, float r, float g, float b); virtual void SetFogColor(float r, float g, float b); virtual void SetFogStart(float fogstart); virtual void SetFogEnd(float fogend); -- cgit v1.2.3 From e7ae96ad417947d5f66a11142a6bc8be779538f7 Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Mon, 23 Mar 2015 21:43:42 +0100 Subject: BGE: Fix T27322: World F-Curve This patch fixes the world (mist, background, ambient) F-Curve for for the BGE. Reviewers: moguri, brecht Reviewed By: moguri, brecht Differential Revision: https://developer.blender.org/D150 --- source/gameengine/Ketsji/BL_Action.cpp | 9 +++ source/gameengine/Ketsji/KX_IpoConvert.cpp | 84 ++++++++++++++-------- source/gameengine/Ketsji/KX_IpoConvert.h | 3 +- source/gameengine/Ketsji/KX_WorldIpoController.cpp | 29 +++++--- source/gameengine/Ketsji/KX_WorldIpoController.h | 28 ++++++-- 5 files changed, 107 insertions(+), 46 deletions(-) diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp index a50c07a486a..9bae119107e 100644 --- a/source/gameengine/Ketsji/BL_Action.cpp +++ b/source/gameengine/Ketsji/BL_Action.cpp @@ -49,6 +49,7 @@ extern "C" { // Needed for material IPOs #include "BKE_material.h" #include "DNA_material_types.h" +#include "DNA_scene_types.h" } #include "MEM_guardedalloc.h" @@ -162,6 +163,14 @@ bool BL_Action::Play(const char* name, m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); + // World + sg_contr = BL_CreateWorldIPO(m_action, kxscene->GetBlenderScene()->world, kxscene->GetSceneConverter()); + if (sg_contr) { + m_sg_contr_list.push_back(sg_contr); + m_obj->GetSGNode()->AddSGController(sg_contr); + sg_contr->SetObject(m_obj->GetSGNode()); + } + // Try obcolor sg_contr = BL_CreateObColorIPO(m_action, m_obj, kxscene->GetSceneConverter()); if (sg_contr) { diff --git a/source/gameengine/Ketsji/KX_IpoConvert.cpp b/source/gameengine/Ketsji/KX_IpoConvert.cpp index 57130bf57b2..441c16176aa 100644 --- a/source/gameengine/Ketsji/KX_IpoConvert.cpp +++ b/source/gameengine/Ketsji/KX_IpoConvert.cpp @@ -269,52 +269,80 @@ SG_Controller *BL_CreateCameraIPO(struct bAction *action, KX_GameObject* camera return ipocontr; } -void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *converter) -{ - - if (blenderworld->adt) { - KX_WorldIpoController* ipocontr = new KX_WorldIpoController(); - -// Erwin, hook up the world ipo controller here -// Gino: hook it up to what ? -// is there a userinterface element for that ? -// for now, we have some new python hooks to access the data, for a work-around - - ipocontr->m_mist_start = blenderworld->miststa; - ipocontr->m_mist_dist = blenderworld->mistdist; - ipocontr->m_mist_rgb[0] = blenderworld->horr; - ipocontr->m_mist_rgb[1] = blenderworld->horg; - ipocontr->m_mist_rgb[2] = blenderworld->horb; +SG_Controller * BL_CreateWorldIPO( bAction *action, struct World *blenderworld, KX_BlenderSceneConverter *converter ) +{ + KX_WorldIpoController *ipocontr = NULL; - BL_InterpolatorList *adtList= GetAdtList(blenderworld->adt->action, converter); + if (blenderworld) { + BL_InterpolatorList *adtList = GetAdtList(action, converter); - // For each active channel in the adtList add an - // interpolator to the game object. - + // For each active channel in the adtList add an interpolator to the game object. KX_IInterpolator *interpolator; KX_IScalarInterpolator *interp; - + + for (int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator("ambient_color", i))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_ambi_rgb[i], interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetModifyAmbientColor(true); + } + } + for (int i=0; i<3; i++) { if ((interp = adtList->GetScalarInterpolator("horizon_color", i))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_rgb[i], interp); + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_hori_rgb[i], interp); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyMistColor(true); + ipocontr->SetModifyHorizonColor(true); } } - if ((interp = adtList->GetScalarInterpolator("mist.depth", 0))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_dist, interp); + if ((interp = adtList->GetScalarInterpolator("mist_settings.start", 0))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_mist_start, interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetModifyMistStart(true); + } + + if ((interp = adtList->GetScalarInterpolator("mist_settings.depth", 0))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_mist_dist, interp); ipocontr->AddInterpolator(interpolator); ipocontr->SetModifyMistDist(true); } - if ((interp = adtList->GetScalarInterpolator("mist.start", 0))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_start, interp); + if ((interp = adtList->GetScalarInterpolator("mist_settings.intensity", 0))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_mist_intensity, interp); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyMistStart(true); + ipocontr->SetModifyMistIntensity(true); + } + + if (ipocontr) { + ipocontr->m_mist_start = blenderworld->miststa; + ipocontr->m_mist_dist = blenderworld->mistdist; + ipocontr->m_mist_intensity = blenderworld->misi; + ipocontr->m_hori_rgb[0] = blenderworld->horr; + ipocontr->m_hori_rgb[1] = blenderworld->horg; + ipocontr->m_hori_rgb[2] = blenderworld->horb; + ipocontr->m_ambi_rgb[0] = blenderworld->ambr; + ipocontr->m_ambi_rgb[1] = blenderworld->ambg; + ipocontr->m_ambi_rgb[2] = blenderworld->ambb; } } + return ipocontr; } SG_Controller *BL_CreateMaterialIpo( diff --git a/source/gameengine/Ketsji/KX_IpoConvert.h b/source/gameengine/Ketsji/KX_IpoConvert.h index a653e4e110b..6db43552811 100644 --- a/source/gameengine/Ketsji/KX_IpoConvert.h +++ b/source/gameengine/Ketsji/KX_IpoConvert.h @@ -50,7 +50,8 @@ SG_Controller *BL_CreateLampIPO(bAction *action, KX_GameObject* lightobj, KX_BlenderSceneConverter *converter); -void BL_ConvertWorldIpos(struct World* blenderworld, +SG_Controller *BL_CreateWorldIPO(bAction *action, + struct World *blenderworld, KX_BlenderSceneConverter *converter); SG_Controller *BL_CreateCameraIPO(bAction *action, diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.cpp b/source/gameengine/Ketsji/KX_WorldIpoController.cpp index a30d89284b8..1123e07ebcc 100644 --- a/source/gameengine/Ketsji/KX_WorldIpoController.cpp +++ b/source/gameengine/Ketsji/KX_WorldIpoController.cpp @@ -33,6 +33,8 @@ #include "KX_WorldIpoController.h" #include "KX_ScalarInterpolator.h" #include "KX_WorldInfo.h" +#include "KX_PythonInit.h" +#include "KX_Scene.h" #if defined(_WIN64) typedef unsigned __int64 uint_ptr; @@ -42,29 +44,36 @@ typedef unsigned long uint_ptr; bool KX_WorldIpoController::Update(double currentTime) { - if (m_modified) - { + if (m_modified) { T_InterpolatorList::iterator i; for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) { - (*i)->Execute(m_ipotime);//currentTime); + (*i)->Execute(m_ipotime); } - /* TODO, this will crash! */ - KX_WorldInfo *world = NULL; + KX_WorldInfo *world = KX_GetActiveScene()->GetWorldInfo(); if (m_modify_mist_start) { world->setMistStart(m_mist_start); } - if (m_modify_mist_color) { - world->setMistColor(m_mist_rgb[0], m_mist_rgb[1], m_mist_rgb[2]); - } - if (m_modify_mist_dist) { world->setMistDistance(m_mist_dist); } - m_modified=false; + if (m_modify_mist_intensity) { + world->setMistIntensity(m_mist_intensity); + } + + if (m_modify_horizon_color) { + world->setBackColor(m_hori_rgb[0], m_hori_rgb[1], m_hori_rgb[2]); + world->setMistColor(m_hori_rgb[0], m_hori_rgb[1], m_hori_rgb[2]); + } + + if (m_modify_ambient_color) { + world->setAmbientColor(m_ambi_rgb[0], m_ambi_rgb[1], m_ambi_rgb[2]); + } + + m_modified = false; } return false; } diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.h b/source/gameengine/Ketsji/KX_WorldIpoController.h index 63983b3129b..704f421573e 100644 --- a/source/gameengine/Ketsji/KX_WorldIpoController.h +++ b/source/gameengine/Ketsji/KX_WorldIpoController.h @@ -39,24 +39,30 @@ class KX_WorldIpoController : public SG_Controller { public: - MT_Scalar m_mist_rgb[3]; MT_Scalar m_mist_start; MT_Scalar m_mist_dist; + MT_Scalar m_mist_intensity; + MT_Scalar m_hori_rgb[3]; + MT_Scalar m_ambi_rgb[3]; private: T_InterpolatorList m_interpolators; - unsigned short m_modify_mist_color : 1; unsigned short m_modify_mist_start : 1; unsigned short m_modify_mist_dist : 1; + unsigned short m_modify_mist_intensity : 1; + unsigned short m_modify_horizon_color : 1; + unsigned short m_modify_ambient_color : 1; bool m_modified; double m_ipotime; public: KX_WorldIpoController() : - m_modify_mist_color(false), m_modify_mist_start(false), m_modify_mist_dist(false), + m_modify_mist_intensity(false), + m_modify_horizon_color(false), + m_modify_ambient_color(false), m_modified(true), m_ipotime(0.0) {} @@ -76,14 +82,22 @@ public: m_modify_mist_start = modify; } - void SetModifyMistColor(bool modify) { - m_modify_mist_color = modify; - } - void SetModifyMistDist(bool modify) { m_modify_mist_dist = modify; } + void SetModifyMistIntensity(bool modify) { + m_modify_mist_intensity = modify; + } + + void SetModifyHorizonColor(bool modify) { + m_modify_horizon_color = modify; + } + + void SetModifyAmbientColor(bool modify) { + m_modify_ambient_color = modify; + } + void SetOption( int option, -- cgit v1.2.3 From 0737f59f6273d7c61b23679c8f4736fe25da6da2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Mar 2015 06:49:44 +1100 Subject: tweaks to packman build remove --asroot arg to makepkg --- GNUmakefile | 4 ++-- build_files/package_spec/pacman/PKGBUILD | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 5a3a0b7848d..fc1de5e4954 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -171,7 +171,7 @@ help: FORCE @echo "" @echo "Package Targets" @echo " * package_debian - build a debian package" - @echo " * package_pacman - build an arch linux pacmanpackage" + @echo " * package_pacman - build an arch linux pacman package" @echo " * package_archive - build an archive package" @echo "" @echo "Testing Targets (not associated with building blender)" @@ -218,7 +218,7 @@ package_debian: FORCE cd build_files/package_spec ; DEB_BUILD_OPTIONS="parallel=$(NPROCS)" sh ./build_debian.sh package_pacman: FORCE - cd build_files/package_spec/pacman ; MAKEFLAGS="-j$(NPROCS)" makepkg --asroot + cd build_files/package_spec/pacman ; MAKEFLAGS="-j$(NPROCS)" makepkg package_archive: FORCE make -C "$(BUILD_DIR)" -s package_archive diff --git a/build_files/package_spec/pacman/PKGBUILD b/build_files/package_spec/pacman/PKGBUILD index cc5198a88e3..961e35578b9 100644 --- a/build_files/package_spec/pacman/PKGBUILD +++ b/build_files/package_spec/pacman/PKGBUILD @@ -12,9 +12,9 @@ blender_version_char=$(sed -ne 's/.*BLENDER_VERSION_CHAR.*\([a-z]\)$/\1/p' $blen # map the version a -> 1 # not to be confused with blender's internal subversions if [ "$blender_version_char" ]; then - blender_version_full=${blender_version}.$(expr index abcdefghijklmnopqrstuvwxyz $blender_version_char) + blender_version_full=${blender_version}.$(expr index abcdefghijklmnopqrstuvwxyz $blender_version_char) else - blender_version_full=${blender_version} + blender_version_full=${blender_version} fi blender_ver_string=$blender_version+git$blender_version_full @@ -60,7 +60,7 @@ package() { cd $srcdir/build make DESTDIR="$pkgdir" install python -m compileall \ - $pkgdir/usr/share/blender/$blender_version/scripts/startup \ - $pkgdir/usr/share/blender/$blender_version/scripts/modules \ - $pkgdir/usr/share/blender/$blender_version/scripts/addons + $pkgdir/usr/share/blender/$blender_version/scripts/startup \ + $pkgdir/usr/share/blender/$blender_version/scripts/modules \ + $pkgdir/usr/share/blender/$blender_version/scripts/addons } -- cgit v1.2.3 From da5fb82a63ea95f75e42092bee60027d3706c9ce Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Mar 2015 07:47:01 +1100 Subject: CMake: readme.html version trick broke packages --- source/creator/CMakeLists.txt | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 57e67a971d3..1557cc08182 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -239,28 +239,13 @@ if(WITH_BUILDINFO) add_dependencies(blender buildinfo) endif() -# Post build steps for bundling/packaging. - -function(install_text_files_patch path) - install( - CODE - " - set(DATA_FILE \"${path}/readme.html\") - file(READ \"\${DATA_FILE}\" DATA_SRC) - string(REGEX REPLACE \"BLENDER_VERSION\" \"${BLENDER_VERSION}\" DATA_DST \"\${DATA_SRC}\") - file(WRITE \"\${DATA_FILE}\" \"\${DATA_DST}\") - unset(DATA_FILE) - unset(DATA_SRC) - unset(DATA_DST) - " - ) -endfunction() set(BLENDER_TEXT_FILES ${CMAKE_SOURCE_DIR}/release/text/GPL-license.txt ${CMAKE_SOURCE_DIR}/release/text/Python-license.txt ${CMAKE_SOURCE_DIR}/release/text/copyright.txt - ${CMAKE_SOURCE_DIR}/release/text/readme.html + # generate this file + # ${CMAKE_SOURCE_DIR}/release/text/readme.html ${CMAKE_SOURCE_DIR}/release/datafiles/LICENSE-bfont.ttf.txt ) @@ -972,12 +957,25 @@ endif() # Generic Install, for all targets if(DEFINED BLENDER_TEXT_FILES_DESTINATION) + + install( + CODE + " + file(READ \"${CMAKE_SOURCE_DIR}/release/text/readme.html\" DATA_SRC) + string(REGEX REPLACE \"BLENDER_VERSION\" \"${BLENDER_VERSION}\" DATA_DST \"\${DATA_SRC}\") + file(WRITE \"\${CMAKE_BINARY_DIR}/release/text/readme.html\" \"\${DATA_DST}\") + unset(DATA_SRC) + unset(DATA_DST) + " + ) + list(APPEND BLENDER_TEXT_FILES + ${CMAKE_BINARY_DIR}/release/text/readme.html + ) + install( FILES ${BLENDER_TEXT_FILES} DESTINATION "${BLENDER_TEXT_FILES_DESTINATION}" ) - - install_text_files_patch("\${CMAKE_INSTALL_PREFIX}/${BLENDER_TEXT_FILES_DESTINATION}") endif() # install more files specified elsewhere -- cgit v1.2.3 From c73693d4a5c9b286333a90dd0fc6fd8a7e6ea753 Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Mon, 23 Mar 2015 22:32:49 +0100 Subject: BGE: Fix T43592: World GLSL This patch will fix the world GLSL (mist, background, ambient) update for the BGE. Reviewers: moguri, brecht Reviewed By: moguri, brecht Subscribers: panzergame Differential Revision: https://developer.blender.org/D151 --- source/blender/editors/space_view3d/view3d_draw.c | 17 ++++-- source/blender/gpu/GPU_material.h | 14 +++++ source/blender/gpu/intern/gpu_material.c | 63 +++++++++++++++++----- .../blender/gpu/shaders/gpu_shader_material.glsl | 23 ++++---- source/blender/python/intern/gpu.c | 8 +++ source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 20 +++++++ 6 files changed, 119 insertions(+), 26 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 116eb48bf88..86916a37d43 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2481,13 +2481,14 @@ static void gpu_render_lamp_update(Scene *scene, View3D *v3d, Object *ob, Object } } -static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) +static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d) { ListBase shadows; View3DShadow *shadow; Scene *sce_iter; Base *base; Object *ob; + World *world = scene->world; SceneRenderLayer *srl = v3d->scenelock ? BLI_findlink(&scene->r.layers, scene->r.actlay) : NULL; BLI_listbase_clear(&shadows); @@ -2552,6 +2553,14 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) } BLI_freelistN(&shadows); + + /* update world values */ + if (world) { + GPU_mist_update_enable(world->mode & WO_MIST); + GPU_mist_update_values(world->mistype, world->miststa, world->mistdist, world->misi, &world->horr); + GPU_horizon_update_color(&world->horr); + GPU_ambient_update_color(&world->ambr); + } } /* *********************** customdata **************** */ @@ -2875,7 +2884,7 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d) { /* shadow buffers, before we setup matrices */ if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) - gpu_update_lamps_shadows(scene, v3d); + gpu_update_lamps_shadows_world(scene, v3d); } /* @@ -3527,8 +3536,8 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3 /* shadow buffers, before we setup matrices */ if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) - gpu_update_lamps_shadows(scene, v3d); - + gpu_update_lamps_shadows_world(scene, v3d); + /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */ if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) { rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE; diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 2d21b1aeb1d..e27916e5bf7 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -149,6 +149,14 @@ typedef enum GPUDynamicType { GPU_DYNAMIC_LAMP_ATT2 = 18, GPU_DYNAMIC_LAMP_SPOTSIZE = 19, GPU_DYNAMIC_LAMP_SPOTBLEND = 20, + GPU_DYNAMIC_MIST_ENABLE = 21, + GPU_DYNAMIC_MIST_START = 22, + GPU_DYNAMIC_MIST_DISTANCE = 23, + GPU_DYNAMIC_MIST_INTENSITY = 24, + GPU_DYNAMIC_MIST_TYPE = 25, + GPU_DYNAMIC_MIST_COLOR = 26, + GPU_DYNAMIC_HORIZON_COLOR = 27, + GPU_DYNAMIC_AMBIENT_COLOR = 28, } GPUDynamicType; GPUNodeLink *GPU_attribute(CustomDataType type, const char *name); @@ -273,6 +281,12 @@ void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend); int GPU_lamp_shadow_layer(GPULamp *lamp); GPUNodeLink *GPU_lamp_get_data(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **col, GPUNodeLink **lv, GPUNodeLink **dist, GPUNodeLink **shadow, GPUNodeLink **energy); +/* World */ +void GPU_mist_update_enable(short enable); +void GPU_mist_update_values(int type, float start, float dist, float inten, float color[3]); +void GPU_horizon_update_color(float color[3]); +void GPU_ambient_update_color(float color[3]); + #ifdef __cplusplus } #endif diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index a9c35896a89..480972d161f 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -76,6 +76,16 @@ typedef enum DynMatProperty { DYN_LAMP_PERSMAT = 8, } DynMatProperty; +static struct GPUWorld { + float mistenabled; + float mistype; + float miststart; + float mistdistance; + float mistintensity; + float mistcol[4]; + float horicol[3]; + float ambcol[4]; +} GPUWorld; struct GPUMaterial { Scene *scene; @@ -1469,13 +1479,39 @@ void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi) GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref); } +void GPU_mist_update_enable(short enable) +{ + GPUWorld.mistenabled = (float)enable; +} + +void GPU_mist_update_values(int type, float start, float dist, float inten, float color[3]) +{ + GPUWorld.mistype = (float)type; + GPUWorld.miststart = start; + GPUWorld.mistdistance = dist; + GPUWorld.mistintensity = inten; + copy_v3_v3(GPUWorld.mistcol, color); + GPUWorld.mistcol[3] = 1.0f; +} + +void GPU_horizon_update_color(float color[3]) +{ + copy_v3_v3(GPUWorld.horicol, color); +} + +void GPU_ambient_update_color(float color[3]) +{ + copy_v3_v3(GPUWorld.ambcol, color); + GPUWorld.ambcol[3] = 1.0f; +} + void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) { GPUMaterial *mat = shi->gpumat; GPUNodeLink *emit, *ulinfac, *ulogfac, *mistfac; Material *ma = shi->mat; World *world = mat->scene->world; - float linfac, logfac, misttype; + float linfac, logfac; memset(shr, 0, sizeof(*shr)); @@ -1526,10 +1562,10 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) } /* ambient color */ - if (world->ambr != 0.0f || world->ambg != 0.0f || world->ambb != 0.0f) { - if (GPU_link_changed(shi->amb) || ma->amb != 0.0f) - GPU_link(mat, "shade_maddf", shr->combined, GPU_uniform(&ma->amb), - GPU_uniform(&world->ambr), &shr->combined); + if (GPU_link_changed(shi->amb) || ma->amb != 0.0f) { + GPU_link(mat, "shade_maddf", shr->combined, GPU_uniform(&ma->amb), + GPU_dynamic_uniform(GPUWorld.ambcol, GPU_DYNAMIC_AMBIENT_COLOR, NULL), + &shr->combined); } } @@ -1551,21 +1587,22 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) if (ma->shade_flag & MA_OBCOLOR) GPU_link(mat, "shade_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined); - if (world && (world->mode & WO_MIST) && !(ma->mode & MA_NOMIST)) { - misttype = world->mistype; - + if (!(ma->mode & MA_NOMIST)) { GPU_link(mat, "shade_mist_factor", GPU_builtin(GPU_VIEW_POSITION), - GPU_uniform(&world->miststa), GPU_uniform(&world->mistdist), - GPU_uniform(&misttype), GPU_uniform(&world->misi), &mistfac); + GPU_dynamic_uniform(&GPUWorld.mistenabled, GPU_DYNAMIC_MIST_ENABLE, NULL), + GPU_dynamic_uniform(&GPUWorld.miststart, GPU_DYNAMIC_MIST_START, NULL), + GPU_dynamic_uniform(&GPUWorld.mistdistance, GPU_DYNAMIC_MIST_DISTANCE, NULL), + GPU_dynamic_uniform(&GPUWorld.mistype, GPU_DYNAMIC_MIST_TYPE, NULL), + GPU_dynamic_uniform(&GPUWorld.mistintensity, GPU_DYNAMIC_MIST_INTENSITY, NULL), &mistfac); GPU_link(mat, "mix_blend", mistfac, shr->combined, - GPU_uniform(&world->horr), &shr->combined); + GPU_dynamic_uniform(GPUWorld.mistcol, GPU_DYNAMIC_MIST_COLOR, NULL), &shr->combined); } if (!mat->alpha) { if (world && (GPU_link_changed(shr->alpha) || ma->alpha != 1.0f)) - GPU_link(mat, "shade_world_mix", GPU_uniform(&world->horr), - shr->combined, &shr->combined); + GPU_link(mat, "shade_world_mix", GPU_dynamic_uniform(GPUWorld.horicol, GPU_DYNAMIC_HORIZON_COLOR, NULL), + shr->combined, &shr->combined); GPU_link(mat, "shade_alpha_opaque", shr->combined, &shr->combined); } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 5268dea5d55..8edffe787eb 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2099,18 +2099,23 @@ void shade_exposure_correct(vec3 col, float linfac, float logfac, out vec3 outco outcol = linfac*(1.0 - exp(col*logfac)); } -void shade_mist_factor(vec3 co, float miststa, float mistdist, float misttype, float misi, out float outfac) +void shade_mist_factor(vec3 co, float enable, float miststa, float mistdist, float misttype, float misi, out float outfac) { - float fac, zcor; + if(enable == 1.0) { + float fac, zcor; - zcor = (gl_ProjectionMatrix[3][3] == 0.0)? length(co): -co[2]; - - fac = clamp((zcor-miststa)/mistdist, 0.0, 1.0); - if(misttype == 0.0) fac *= fac; - else if(misttype == 1.0); - else fac = sqrt(fac); + zcor = (gl_ProjectionMatrix[3][3] == 0.0)? length(co): -co[2]; + + fac = clamp((zcor - miststa) / mistdist, 0.0, 1.0); + if(misttype == 0.0) fac *= fac; + else if(misttype == 1.0); + else fac = sqrt(fac); - outfac = 1.0 - (1.0-fac)*(1.0-misi); + outfac = 1.0 - (1.0 - fac) * (1.0 - misi); + } + else { + outfac = 0.0; + } } void shade_world_mix(vec3 hor, vec4 col, out vec4 outcol) diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c index e4580e8035b..b2dc7e866ff 100644 --- a/source/blender/python/intern/gpu.c +++ b/source/blender/python/intern/gpu.c @@ -95,6 +95,14 @@ static PyObject *PyInit_gpu(void) PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DBUFFER); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DIMAGE); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DSHADOW); + PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_ENABLE); + PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_START); + PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_DISTANCE); + PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_INTENSITY); + PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_TYPE); + PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_COLOR); + PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_HORIZON_COLOR); + PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_AMBIENT_COLOR); PY_MODULE_ADD_CONSTANT(m, GPU_DATA_1I); PY_MODULE_ADD_CONSTANT(m, GPU_DATA_1F); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 8c6cb2b32d4..2907371267a 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -80,6 +80,8 @@ #include "KX_NavMeshObject.h" +#include "GPU_material.h" + #define DEFAULT_LOGIC_TIC_RATE 60.0 //#define DEFAULT_PHYSICS_TIC_RATE 60.0 @@ -975,6 +977,9 @@ void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi) wi->getBackColorBlue(), 0.0 ); + + float horicolor[] = {wi->getBackColorRed(), wi->getBackColorGreen(), wi->getBackColorBlue()}; + GPU_horizon_update_color(horicolor); } } } @@ -993,6 +998,9 @@ void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi) wi->getAmbientColorBlue() ); + float ambcolor[] = {wi->getAmbientColorRed(), wi->getAmbientColorGreen(), wi->getAmbientColorBlue()}; + GPU_ambient_update_color(ambcolor); + if (wi->hasMist()) { m_rasterizer->SetFog( @@ -1004,10 +1012,22 @@ void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi) wi->getMistColorGreen(), wi->getMistColorBlue() ); + + float mistcolor[] = {wi->getMistColorRed(), wi->getMistColorGreen(), wi->getMistColorBlue()}; + GPU_mist_update_values( + wi->getMistType(), + wi->getMistStart(), + wi->getMistDistance(), + wi->getMistIntensity(), + mistcolor + ); + m_rasterizer->EnableFog(true); + GPU_mist_update_enable(true); } else { m_rasterizer->EnableFog(false); + GPU_mist_update_enable(false); } } } -- cgit v1.2.3 From 931c3e654404bbff05f1bcce9487fc6e91392300 Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Mon, 23 Mar 2015 22:49:38 +0100 Subject: BGE: Code clean up for world (mist, background, ambient) Code clean up for BGE world mist, background and global ambient color. Move mist render update to BlenderWolrdInfo Reviewers: moguri, brecht Reviewed By: moguri, brecht Differential Revision: https://developer.blender.org/D152 --- .../BlenderRoutines/BL_KetsjiEmbedStart.cpp | 2 +- source/gameengine/Converter/BlenderWorldInfo.cpp | 55 ++++++++---- source/gameengine/Converter/BlenderWorldInfo.h | 32 +++---- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 81 +----------------- source/gameengine/Ketsji/KX_KetsjiEngine.h | 2 - source/gameengine/Ketsji/KX_WorldInfo.h | 11 ++- source/gameengine/Rasterizer/RAS_IRasterizer.h | 10 +-- .../RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp | 97 +++++----------------- .../RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h | 21 ++--- source/gameengine/VideoTexture/ImageRender.cpp | 2 +- 10 files changed, 94 insertions(+), 219 deletions(-) diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 511b61528f8..1a198920919 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -446,7 +446,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c rasterizer->SetEyeSeparation(scene->gm.eyeseparation); } - rasterizer->SetBackColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 0.0f); + rasterizer->SetBackColor(scene->gm.framing.col); } if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME) diff --git a/source/gameengine/Converter/BlenderWorldInfo.cpp b/source/gameengine/Converter/BlenderWorldInfo.cpp index 5f476949616..40293d7479b 100644 --- a/source/gameengine/Converter/BlenderWorldInfo.cpp +++ b/source/gameengine/Converter/BlenderWorldInfo.cpp @@ -33,6 +33,8 @@ #include // printf() #include "BlenderWorldInfo.h" +#include "KX_PythonInit.h" +#include "GPU_material.h" /* This little block needed for linking to Blender... */ #ifdef WIN32 @@ -40,23 +42,7 @@ #endif /* This list includes only data type definitions */ -#include "DNA_object_types.h" -#include "DNA_material_types.h" -#include "DNA_image_types.h" -#include "DNA_lamp_types.h" -#include "DNA_group_types.h" -#include "DNA_scene_types.h" -#include "DNA_camera_types.h" -#include "DNA_property_types.h" -#include "DNA_text_types.h" -#include "DNA_sensor_types.h" -#include "DNA_controller_types.h" -#include "DNA_actuator_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_view3d_types.h" #include "DNA_world_types.h" -#include "DNA_screen_types.h" #include "BLI_math.h" @@ -65,7 +51,7 @@ /* end of blender include block */ -BlenderWorldInfo::BlenderWorldInfo(struct Scene *blenderscene, struct World *blenderworld) +BlenderWorldInfo::BlenderWorldInfo(Scene *blenderscene, World *blenderworld) { if (blenderworld) { m_hasworld = true; @@ -212,3 +198,38 @@ void BlenderWorldInfo::setAmbientColor(float r, float g, float b) m_ambientcolor[1] = g; m_ambientcolor[2] = b; } + +void BlenderWorldInfo::UpdateBackGround() +{ + if (m_hasworld) { + RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer(); + + if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) { + m_rasterizer->SetBackColor(m_backgroundcolor); + GPU_horizon_update_color(m_backgroundcolor); + } + } +} + +void BlenderWorldInfo::UpdateWorldSettings() +{ + if (m_hasworld) { + RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer(); + + if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) { + m_rasterizer->SetAmbientColor(m_ambientcolor); + GPU_ambient_update_color(m_ambientcolor); + + if (m_hasmist) { + m_rasterizer->SetFog(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_mistcolor); + GPU_mist_update_values(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_mistcolor); + m_rasterizer->EnableFog(true); + GPU_mist_update_enable(true); + } + else { + m_rasterizer->EnableFog(false); + GPU_mist_update_enable(false); + } + } + } +} diff --git a/source/gameengine/Converter/BlenderWorldInfo.h b/source/gameengine/Converter/BlenderWorldInfo.h index 4184d428808..395e8f723aa 100644 --- a/source/gameengine/Converter/BlenderWorldInfo.h +++ b/source/gameengine/Converter/BlenderWorldInfo.h @@ -31,37 +31,33 @@ #ifndef __BLENDERWORLDINFO_H__ #define __BLENDERWORLDINFO_H__ -#include "MT_CmMatrix4x4.h" #include "KX_WorldInfo.h" +#include "KX_KetsjiEngine.h" +#include "RAS_IRasterizer.h" + +struct Scene; +struct World; +const class KX_KetsjiEngine; +const class RAS_IRasterizer; class BlenderWorldInfo : public KX_WorldInfo { bool m_hasworld; - float m_backgroundcolor[3]; - bool m_hasmist; short m_misttype; float m_miststart; float m_mistdistance; float m_mistintensity; float m_mistcolor[3]; - + float m_backgroundcolor[3]; float m_ambientcolor[3]; public: - BlenderWorldInfo(struct Scene *blenderscene, struct World *blenderworld); + BlenderWorldInfo(Scene *blenderscene, World *blenderworld); ~BlenderWorldInfo(); bool hasWorld(); bool hasMist(); - float getBackColorRed(); - float getBackColorGreen(); - float getBackColorBlue(); - - float getAmbientColorRed(); - float getAmbientColorGreen(); - float getAmbientColorBlue(); - short getMistType(); float getMistStart(); float getMistDistance(); @@ -69,7 +65,12 @@ public: float getMistColorRed(); float getMistColorGreen(); float getMistColorBlue(); - + float getBackColorRed(); + float getBackColorGreen(); + float getBackColorBlue(); + float getAmbientColorRed(); + float getAmbientColorGreen(); + float getAmbientColorBlue(); void setBackColor(float r, float g, float b); void setUseMist(bool enable); void setMistType(short type); @@ -78,7 +79,8 @@ public: void setMistIntensity(float intensity); void setMistColor(float r, float g, float b); void setAmbientColor(float r, float g, float b); - + void UpdateBackGround(); + void UpdateWorldSettings(); #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:BlenderWorldInfo") diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 2907371267a..6c2e34d92f8 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -80,8 +80,6 @@ #include "KX_NavMeshObject.h" -#include "GPU_material.h" - #define DEFAULT_LOGIC_TIC_RATE 60.0 //#define DEFAULT_PHYSICS_TIC_RATE 60.0 @@ -317,7 +315,7 @@ void KX_KetsjiEngine::RenderDome() KX_Camera* cam = scene->GetActiveCamera(); // pass the scene's worldsettings to the rasterizer - SetWorldSettings(scene->GetWorldInfo()); + scene->GetWorldInfo()->UpdateWorldSettings(); // shadow buffers if (i == 0) { @@ -477,7 +475,7 @@ void KX_KetsjiEngine::ClearFrame() if (doclear) { KX_Scene* firstscene = *m_scenes.begin(); - SetBackGround(firstscene->GetWorldInfo()); + firstscene->GetWorldInfo()->UpdateBackGround(); m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(), clearvp.GetRight(), clearvp.GetTop()); @@ -827,7 +825,7 @@ void KX_KetsjiEngine::Render() KX_Scene* scene = *sceneit; KX_Camera* cam = scene->GetActiveCamera(); // pass the scene's worldsettings to the rasterizer - SetWorldSettings(scene->GetWorldInfo()); + scene->GetWorldInfo()->UpdateWorldSettings(); // this is now done incrementatlly in KX_Scene::CalculateVisibleMeshes //scene->UpdateMeshTransformations(); @@ -884,7 +882,7 @@ void KX_KetsjiEngine::Render() KX_Camera* cam = scene->GetActiveCamera(); // pass the scene's worldsettings to the rasterizer - SetWorldSettings(scene->GetWorldInfo()); + scene->GetWorldInfo()->UpdateWorldSettings(); if (scene->IsClearingZBuffer()) m_rasterizer->ClearDepthBuffer(); @@ -964,77 +962,6 @@ const STR_String& KX_KetsjiEngine::GetExitString() return m_exitstring; } - -void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi) -{ - if (wi->hasWorld()) - { - if (m_rasterizer->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) - { - m_rasterizer->SetBackColor( - wi->getBackColorRed(), - wi->getBackColorGreen(), - wi->getBackColorBlue(), - 0.0 - ); - - float horicolor[] = {wi->getBackColorRed(), wi->getBackColorGreen(), wi->getBackColorBlue()}; - GPU_horizon_update_color(horicolor); - } - } -} - - - -void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi) -{ - if (wi->hasWorld()) - { - if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) - { - m_rasterizer->SetAmbientColor( - wi->getAmbientColorRed(), - wi->getAmbientColorGreen(), - wi->getAmbientColorBlue() - ); - - float ambcolor[] = {wi->getAmbientColorRed(), wi->getAmbientColorGreen(), wi->getAmbientColorBlue()}; - GPU_ambient_update_color(ambcolor); - - if (wi->hasMist()) - { - m_rasterizer->SetFog( - wi->getMistType(), - wi->getMistStart(), - wi->getMistDistance(), - wi->getMistIntensity(), - wi->getMistColorRed(), - wi->getMistColorGreen(), - wi->getMistColorBlue() - ); - - float mistcolor[] = {wi->getMistColorRed(), wi->getMistColorGreen(), wi->getMistColorBlue()}; - GPU_mist_update_values( - wi->getMistType(), - wi->getMistStart(), - wi->getMistDistance(), - wi->getMistIntensity(), - mistcolor - ); - - m_rasterizer->EnableFog(true); - GPU_mist_update_enable(true); - } - else { - m_rasterizer->EnableFog(false); - GPU_mist_update_enable(false); - } - } - } -} - - - void KX_KetsjiEngine::EnableCameraOverride(const STR_String& forscene) { m_overrideCam = true; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index e18b203b675..4392769ed02 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -205,14 +205,12 @@ private: void PostRenderScene(KX_Scene* scene); void RenderDebugProperties(); void RenderShadowBuffers(KX_Scene *scene); - void SetBackGround(KX_WorldInfo* worldinfo); public: KX_KetsjiEngine(class KX_ISystem* system); virtual ~KX_KetsjiEngine(); // set the devices and stuff. the client must take care of creating these - void SetWorldSettings(KX_WorldInfo* worldinfo); void SetKeyboardDevice(SCA_IInputDevice* keyboarddevice); void SetMouseDevice(SCA_IInputDevice* mousedevice); void SetNetworkDevice(NG_NetworkDeviceInterface* networkdevice); diff --git a/source/gameengine/Ketsji/KX_WorldInfo.h b/source/gameengine/Ketsji/KX_WorldInfo.h index f90a4ff6b6d..a6f93dd80ba 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.h +++ b/source/gameengine/Ketsji/KX_WorldInfo.h @@ -57,9 +57,6 @@ public: virtual bool hasWorld() = 0; virtual bool hasMist() = 0; - virtual float getBackColorRed() = 0; - virtual float getBackColorGreen() = 0; - virtual float getBackColorBlue() = 0; virtual short getMistType() = 0; virtual float getMistStart() = 0; virtual float getMistDistance() = 0; @@ -67,11 +64,12 @@ public: virtual float getMistColorRed() = 0; virtual float getMistColorGreen() = 0; virtual float getMistColorBlue() = 0; - + virtual float getBackColorRed() = 0; + virtual float getBackColorGreen() = 0; + virtual float getBackColorBlue() = 0; virtual float getAmbientColorRed() = 0; virtual float getAmbientColorGreen() = 0; virtual float getAmbientColorBlue() = 0; - virtual void setUseMist(bool enable) = 0; virtual void setMistType(short) = 0; virtual void setMistStart(float) = 0; @@ -80,7 +78,8 @@ public: virtual void setMistColor(float, float, float) = 0; virtual void setBackColor(float, float, float) = 0; virtual void setAmbientColor(float,float,float) = 0; - + virtual void UpdateBackGround() = 0; + virtual void UpdateWorldSettings() = 0; #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:KX_WorldInfo") diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index 22ffcd48739..aadecd56992 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -297,15 +297,11 @@ public: /** * Fog */ - virtual void SetFog(short type, float start, float dist, float intensity, float r, float g, float b) = 0; - virtual void SetFogColor(float r, float g,float b) = 0; - virtual void SetFogStart(float start) = 0; - virtual void SetFogEnd(float end) = 0; + virtual void SetFog(short type, float start, float dist, float intensity, float color[3]) = 0; virtual void DisplayFog() = 0; virtual void EnableFog(bool enable) = 0; - virtual bool IsFogEnabled() = 0; - virtual void SetBackColor(float red, float green, float blue, float alpha) = 0; + virtual void SetBackColor(float color[3]) = 0; /** * \param drawingmode = KX_BOUNDINGBOX, KX_WIREFRAME, KX_SOLID, KX_SHADED or KX_TEXTURED. @@ -380,7 +376,7 @@ public: */ virtual void SetEmissive(float eX, float eY, float eZ, float e) = 0; - virtual void SetAmbientColor(float red, float green, float blue) = 0; + virtual void SetAmbientColor(float color[3]) = 0; virtual void SetAmbient(float factor) = 0; /** diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 9269640afa3..f47f56541ba 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -194,109 +194,52 @@ bool RAS_OpenGLRasterizer::Init() } -void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue) +void RAS_OpenGLRasterizer::SetAmbientColor(float color[3]) { - m_ambr = red; - m_ambg = green; - m_ambb = blue; + m_ambr = color[0]; + m_ambg = color[1]; + m_ambb = color[2]; } - void RAS_OpenGLRasterizer::SetAmbient(float factor) { - float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f }; + float ambient[] = {m_ambr * factor, m_ambg * factor, m_ambb * factor, 1.0f}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); } - -void RAS_OpenGLRasterizer::SetBackColor(float red, - float green, - float blue, - float alpha) -{ - m_redback = red; - m_greenback = green; - m_blueback = blue; - m_alphaback = alpha; -} - - - -void RAS_OpenGLRasterizer::SetFogColor(float r, - float g, - float b) -{ - m_fogr = r; - m_fogg = g; - m_fogb = b; -} - - - -void RAS_OpenGLRasterizer::SetFogStart(float start) -{ - m_fogstart = start; -} - - - -void RAS_OpenGLRasterizer::SetFogEnd(float fogend) +void RAS_OpenGLRasterizer::SetBackColor(float color[3]) { - m_fogdist = fogend; + m_redback = color[0]; + m_greenback = color[1]; + m_blueback = color[2]; + m_alphaback = 1.0f; } - - -void RAS_OpenGLRasterizer::SetFog(short type, - float start, - float dist, - float intensity, - float r, - float g, - float b) +void RAS_OpenGLRasterizer::SetFog(short type, float start, float dist, float intensity, float color[3]) { - m_fogtype = type; - m_fogstart = start; - m_fogdist = dist; - m_fogintensity = intensity; - m_fogr = r; - m_fogg = g; - m_fogb = b; + float params[4] = {color[0], color[1], color[2], 1.0f}; + glFogi(GL_FOG_MODE, GL_LINEAR); + glFogf(GL_FOG_DENSITY, intensity / 10.0f); + glFogf(GL_FOG_START, start); + glFogf(GL_FOG_END, start + dist); + glFogfv(GL_FOG_COLOR, params); } - - void RAS_OpenGLRasterizer::EnableFog(bool enable) { m_fogenabled = enable; } -bool RAS_OpenGLRasterizer::IsFogEnabled() -{ - return m_fogenabled; -} - - void RAS_OpenGLRasterizer::DisplayFog() { - if ((m_drawingmode >= KX_SOLID) && m_fogenabled) - { - float params[4] = {m_fogr, m_fogg, m_fogb, 1.0f}; - glFogi(GL_FOG_MODE, GL_LINEAR); - glFogf(GL_FOG_DENSITY, m_fogintensity / 10.0f); - glFogf(GL_FOG_START, m_fogstart); - glFogf(GL_FOG_END, m_fogstart + m_fogdist); - glFogfv(GL_FOG_COLOR, params); + if ((m_drawingmode >= KX_SOLID) && m_fogenabled) { glEnable(GL_FOG); - } - else - { + } + else { glDisable(GL_FOG); } } - - bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat) { return mat.Activate(this, m_materialCachingInfo); diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 48023f9786c..b034315e3d6 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -80,14 +80,7 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer /* fogging vars */ bool m_fogenabled; - short m_fogtype; - float m_fogstart; - float m_fogdist; - float m_fogintensity; - float m_fogr; - float m_fogg; - float m_fogb; - + float m_redback; float m_greenback; float m_blueback; @@ -200,16 +193,12 @@ public: virtual const MT_Point3& GetCameraPosition(); virtual bool GetCameraOrtho(); - virtual void SetFog(short type, float start, float dist, float intensity, float r, float g, float b); - virtual void SetFogColor(float r, float g, float b); - virtual void SetFogStart(float fogstart); - virtual void SetFogEnd(float fogend); + virtual void SetFog(short type, float start, float dist, float intensity, float color[3]); virtual void EnableFog(bool enable); virtual void DisplayFog(); - virtual bool IsFogEnabled(); - virtual void SetBackColor(float red, float green, float blue, float alpha); - + virtual void SetBackColor(float color[3]); + virtual void SetDrawingMode(int drawingmode); virtual int GetDrawingMode(); @@ -229,7 +218,7 @@ public: virtual void SetDiffuse(float difX, float difY, float difZ, float diffuse); virtual void SetEmissive(float eX, float eY, float eZ, float e); - virtual void SetAmbientColor(float red, float green, float blue); + virtual void SetAmbientColor(float color[3]); virtual void SetAmbient(float factor); virtual void SetPolygonOffset(float mult, float add); diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 57b2e85845c..9feb6141cc4 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -200,7 +200,7 @@ void ImageRender::Render() m_canvas->ClearColor(m_background[0], m_background[1], m_background[2], m_background[3]); m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER); m_rasterizer->BeginFrame(m_engine->GetClockTime()); - m_engine->SetWorldSettings(m_scene->GetWorldInfo()); + m_scene->GetWorldInfo()->UpdateWorldSettings(); m_rasterizer->SetAuxilaryClientInfo(m_scene); m_rasterizer->DisplayFog(); // matrix calculation, don't apply any of the stereo mode -- cgit v1.2.3 From ce40fb9ab2616abefb79b12c3972e550b1df4660 Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Mon, 23 Mar 2015 23:56:46 +0100 Subject: BGE: World color management fix This patch will fix the color management for the mist and global ambient color. It will remove the old "Color Management" switch in the BGE "Render > Shading" panel and will use the "Display Device" setting in the "Scene > Color Management" panel instead. Reviewers: moguri, brecht Reviewed By: brecht Differential Revision: https://developer.blender.org/D154 --- release/scripts/startup/bl_ui/properties_game.py | 1 - source/blender/gpu/intern/gpu_material.c | 2 +- source/blender/makesrna/intern/rna_color.c | 1 + .../Converter/BL_BlenderDataConversion.cpp | 2 +- source/gameengine/Converter/BlenderWorldInfo.cpp | 40 +++++++++++++++------- source/gameengine/Converter/BlenderWorldInfo.h | 4 +++ 6 files changed, 35 insertions(+), 15 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py index 8ef9a083104..84ad2426aa0 100644 --- a/release/scripts/startup/bl_ui/properties_game.py +++ b/release/scripts/startup/bl_ui/properties_game.py @@ -397,7 +397,6 @@ class RENDER_PT_game_shading(RenderButtonsPanel, Panel): col.prop(gs, "use_glsl_lights", text="Lights") col.prop(gs, "use_glsl_shaders", text="Shaders") col.prop(gs, "use_glsl_shadows", text="Shadows") - col.prop(gs, "use_glsl_color_management", text="Color Management") col = split.column() col.prop(gs, "use_glsl_ramps", text="Ramps") diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 480972d161f..4d46ef3af7b 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -452,7 +452,7 @@ bool GPU_material_do_color_management(GPUMaterial *mat) if (!BKE_scene_check_color_management_enabled(mat->scene)) return false; - return !((mat->scene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT)); + return true; } bool GPU_material_use_new_shading_nodes(GPUMaterial *mat) diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 5e114a51ceb..e6193b31260 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -447,6 +447,7 @@ static void rna_ColorManagedDisplaySettings_display_device_update(Main *UNUSED(b IMB_colormanagement_validate_settings(&scene->display_settings, &scene->view_settings); + DAG_id_tag_update(id, 0); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); } } diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 6e3a321bfdf..3e7e104ed46 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1651,7 +1651,7 @@ static KX_GameObject *gameobject_from_blenderobject( case OB_FONT: { - bool do_color_management = !(blenderscene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT); + bool do_color_management = BKE_scene_check_color_management_enabled(blenderscene); /* font objects have no bounding box */ gameobj = new KX_FontObject(kxscene,KX_Scene::m_callbacks, rendertools, ob, do_color_management); diff --git a/source/gameengine/Converter/BlenderWorldInfo.cpp b/source/gameengine/Converter/BlenderWorldInfo.cpp index 40293d7479b..6daecccf15c 100644 --- a/source/gameengine/Converter/BlenderWorldInfo.cpp +++ b/source/gameengine/Converter/BlenderWorldInfo.cpp @@ -54,21 +54,16 @@ BlenderWorldInfo::BlenderWorldInfo(Scene *blenderscene, World *blenderworld) { if (blenderworld) { + m_do_color_management = BKE_scene_check_color_management_enabled(blenderscene); m_hasworld = true; m_hasmist = ((blenderworld->mode) & WO_MIST ? true : false); m_misttype = blenderworld->mistype; m_miststart = blenderworld->miststa; m_mistdistance = blenderworld->mistdist; m_mistintensity = blenderworld->misi; - copy_v3_v3(m_mistcolor, &blenderworld->horr); - copy_v3_v3(m_backgroundcolor, &blenderworld->horr); - copy_v3_v3(m_ambientcolor, &blenderworld->ambr); - - if (BKE_scene_check_color_management_enabled(blenderscene)) { - linearrgb_to_srgb_v3_v3(m_mistcolor, m_mistcolor); - linearrgb_to_srgb_v3_v3(m_backgroundcolor, m_backgroundcolor); - linearrgb_to_srgb_v3_v3(m_ambientcolor, m_ambientcolor); - } + setMistColor(blenderworld->horr, blenderworld->horg, blenderworld->horb); + setBackColor(blenderworld->horr, blenderworld->horg, blenderworld->horb); + setAmbientColor(blenderworld->ambr, blenderworld->ambg, blenderworld->ambb); } else { m_hasworld = false; @@ -159,6 +154,13 @@ void BlenderWorldInfo::setBackColor(float r, float g, float b) m_backgroundcolor[0] = r; m_backgroundcolor[1] = g; m_backgroundcolor[2] = b; + + if (m_do_color_management) { + linearrgb_to_srgb_v3_v3(m_con_backgroundcolor, m_backgroundcolor); + } + else { + copy_v3_v3(m_con_backgroundcolor, m_backgroundcolor); + } } void BlenderWorldInfo::setMistType(short type) @@ -190,6 +192,13 @@ void BlenderWorldInfo::setMistColor(float r, float g, float b) m_mistcolor[0] = r; m_mistcolor[1] = g; m_mistcolor[2] = b; + + if (m_do_color_management) { + linearrgb_to_srgb_v3_v3(m_con_mistcolor, m_mistcolor); + } + else { + copy_v3_v3(m_con_mistcolor, m_mistcolor); + } } void BlenderWorldInfo::setAmbientColor(float r, float g, float b) @@ -197,6 +206,13 @@ void BlenderWorldInfo::setAmbientColor(float r, float g, float b) m_ambientcolor[0] = r; m_ambientcolor[1] = g; m_ambientcolor[2] = b; + + if (m_do_color_management) { + linearrgb_to_srgb_v3_v3(m_con_ambientcolor, m_ambientcolor); + } + else { + copy_v3_v3(m_con_ambientcolor, m_ambientcolor); + } } void BlenderWorldInfo::UpdateBackGround() @@ -205,7 +221,7 @@ void BlenderWorldInfo::UpdateBackGround() RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer(); if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) { - m_rasterizer->SetBackColor(m_backgroundcolor); + m_rasterizer->SetBackColor(m_con_backgroundcolor); GPU_horizon_update_color(m_backgroundcolor); } } @@ -217,11 +233,11 @@ void BlenderWorldInfo::UpdateWorldSettings() RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer(); if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) { - m_rasterizer->SetAmbientColor(m_ambientcolor); + m_rasterizer->SetAmbientColor(m_con_ambientcolor); GPU_ambient_update_color(m_ambientcolor); if (m_hasmist) { - m_rasterizer->SetFog(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_mistcolor); + m_rasterizer->SetFog(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_con_mistcolor); GPU_mist_update_values(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_mistcolor); m_rasterizer->EnableFog(true); GPU_mist_update_enable(true); diff --git a/source/gameengine/Converter/BlenderWorldInfo.h b/source/gameengine/Converter/BlenderWorldInfo.h index 395e8f723aa..5c1cbd28104 100644 --- a/source/gameengine/Converter/BlenderWorldInfo.h +++ b/source/gameengine/Converter/BlenderWorldInfo.h @@ -51,11 +51,15 @@ class BlenderWorldInfo : public KX_WorldInfo float m_mistcolor[3]; float m_backgroundcolor[3]; float m_ambientcolor[3]; + float m_con_mistcolor[3]; + float m_con_backgroundcolor[3]; + float m_con_ambientcolor[3]; public: BlenderWorldInfo(Scene *blenderscene, World *blenderworld); ~BlenderWorldInfo(); + bool m_do_color_management; bool hasWorld(); bool hasMist(); short getMistType(); -- cgit v1.2.3 From 6c9502a6c1e8637922991171680986f1c9a17f6e Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Tue, 24 Mar 2015 00:19:15 +0100 Subject: BGE: Remove BlenderWorldInfo This patch will remove the BlenderWorldInfo and move the source into KX_WorldInfo. Reviewers: brecht, moguri Reviewed By: brecht, moguri Differential Revision: https://developer.blender.org/D156 --- .../Converter/BL_BlenderDataConversion.cpp | 4 +- source/gameengine/Converter/BlenderWorldInfo.cpp | 251 --------------------- source/gameengine/Converter/BlenderWorldInfo.h | 94 -------- source/gameengine/Converter/CMakeLists.txt | 2 - .../Converter/KX_BlenderSceneConverter.cpp | 2 +- source/gameengine/Ketsji/KX_WorldInfo.cpp | 212 +++++++++++++++++ source/gameengine/Ketsji/KX_WorldInfo.h | 75 +++--- 7 files changed, 262 insertions(+), 378 deletions(-) delete mode 100644 source/gameengine/Converter/BlenderWorldInfo.cpp delete mode 100644 source/gameengine/Converter/BlenderWorldInfo.h diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 3e7e104ed46..de5e27baf58 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -98,7 +98,7 @@ #include "BLI_utildefines.h" #include "BLI_listbase.h" -#include "BlenderWorldInfo.h" +#include "KX_WorldInfo.h" #include "KX_KetsjiEngine.h" #include "KX_BlenderSceneConverter.h" @@ -2342,7 +2342,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, sumolist->Release(); // convert world - KX_WorldInfo* worldinfo = new BlenderWorldInfo(blenderscene, blenderscene->world); + KX_WorldInfo* worldinfo = new KX_WorldInfo(blenderscene, blenderscene->world); converter->RegisterWorldInfo(worldinfo); kxscene->SetWorldInfo(worldinfo); diff --git a/source/gameengine/Converter/BlenderWorldInfo.cpp b/source/gameengine/Converter/BlenderWorldInfo.cpp deleted file mode 100644 index 6daecccf15c..00000000000 --- a/source/gameengine/Converter/BlenderWorldInfo.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can [0]istribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file gameengine/Converter/BlenderWorldInfo.cpp - * \ingroup bgeconv - */ - - -#include // printf() - -#include "BlenderWorldInfo.h" -#include "KX_PythonInit.h" -#include "GPU_material.h" - -/* This little block needed for linking to Blender... */ -#ifdef WIN32 -#include "BLI_winstuff.h" -#endif - -/* This list includes only data type definitions */ -#include "DNA_world_types.h" - -#include "BLI_math.h" - -#include "BKE_global.h" -#include "BKE_scene.h" -/* end of blender include block */ - - -BlenderWorldInfo::BlenderWorldInfo(Scene *blenderscene, World *blenderworld) -{ - if (blenderworld) { - m_do_color_management = BKE_scene_check_color_management_enabled(blenderscene); - m_hasworld = true; - m_hasmist = ((blenderworld->mode) & WO_MIST ? true : false); - m_misttype = blenderworld->mistype; - m_miststart = blenderworld->miststa; - m_mistdistance = blenderworld->mistdist; - m_mistintensity = blenderworld->misi; - setMistColor(blenderworld->horr, blenderworld->horg, blenderworld->horb); - setBackColor(blenderworld->horr, blenderworld->horg, blenderworld->horb); - setAmbientColor(blenderworld->ambr, blenderworld->ambg, blenderworld->ambb); - } - else { - m_hasworld = false; - } -} - -BlenderWorldInfo::~BlenderWorldInfo() -{ -} - -bool BlenderWorldInfo::hasWorld() -{ - return m_hasworld; -} - -bool BlenderWorldInfo::hasMist() -{ - return m_hasmist; -} - -float BlenderWorldInfo::getBackColorRed() -{ - return m_backgroundcolor[0]; -} - -float BlenderWorldInfo::getBackColorGreen() -{ - return m_backgroundcolor[1]; -} - -float BlenderWorldInfo::getBackColorBlue() -{ - return m_backgroundcolor[2]; -} - -float BlenderWorldInfo::getAmbientColorRed() -{ - return m_ambientcolor[0]; -} - -float BlenderWorldInfo::getAmbientColorGreen() -{ - return m_ambientcolor[1]; -} - -float BlenderWorldInfo::getAmbientColorBlue() -{ - return m_ambientcolor[2]; -} - -short BlenderWorldInfo::getMistType() -{ - return m_misttype; -} - -float BlenderWorldInfo::getMistStart() -{ - return m_miststart; -} - -float BlenderWorldInfo::getMistDistance() -{ - return m_mistdistance; -} - -float BlenderWorldInfo::getMistIntensity() -{ - return m_mistintensity; -} - -float BlenderWorldInfo::getMistColorRed() -{ - return m_mistcolor[0]; -} - -float BlenderWorldInfo::getMistColorGreen() -{ - return m_mistcolor[1]; -} - -float BlenderWorldInfo::getMistColorBlue() -{ - return m_mistcolor[2]; -} - -void BlenderWorldInfo::setBackColor(float r, float g, float b) -{ - m_backgroundcolor[0] = r; - m_backgroundcolor[1] = g; - m_backgroundcolor[2] = b; - - if (m_do_color_management) { - linearrgb_to_srgb_v3_v3(m_con_backgroundcolor, m_backgroundcolor); - } - else { - copy_v3_v3(m_con_backgroundcolor, m_backgroundcolor); - } -} - -void BlenderWorldInfo::setMistType(short type) -{ - m_misttype = type; -} - -void BlenderWorldInfo::setUseMist(bool enable) -{ - m_hasmist = enable; -} - -void BlenderWorldInfo::setMistStart(float d) -{ - m_miststart = d; -} - -void BlenderWorldInfo::setMistDistance(float d) -{ - m_mistdistance = d; -} - -void BlenderWorldInfo::setMistIntensity(float intensity) -{ - m_mistintensity = intensity; -} -void BlenderWorldInfo::setMistColor(float r, float g, float b) -{ - m_mistcolor[0] = r; - m_mistcolor[1] = g; - m_mistcolor[2] = b; - - if (m_do_color_management) { - linearrgb_to_srgb_v3_v3(m_con_mistcolor, m_mistcolor); - } - else { - copy_v3_v3(m_con_mistcolor, m_mistcolor); - } -} - -void BlenderWorldInfo::setAmbientColor(float r, float g, float b) -{ - m_ambientcolor[0] = r; - m_ambientcolor[1] = g; - m_ambientcolor[2] = b; - - if (m_do_color_management) { - linearrgb_to_srgb_v3_v3(m_con_ambientcolor, m_ambientcolor); - } - else { - copy_v3_v3(m_con_ambientcolor, m_ambientcolor); - } -} - -void BlenderWorldInfo::UpdateBackGround() -{ - if (m_hasworld) { - RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer(); - - if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) { - m_rasterizer->SetBackColor(m_con_backgroundcolor); - GPU_horizon_update_color(m_backgroundcolor); - } - } -} - -void BlenderWorldInfo::UpdateWorldSettings() -{ - if (m_hasworld) { - RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer(); - - if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) { - m_rasterizer->SetAmbientColor(m_con_ambientcolor); - GPU_ambient_update_color(m_ambientcolor); - - if (m_hasmist) { - m_rasterizer->SetFog(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_con_mistcolor); - GPU_mist_update_values(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_mistcolor); - m_rasterizer->EnableFog(true); - GPU_mist_update_enable(true); - } - else { - m_rasterizer->EnableFog(false); - GPU_mist_update_enable(false); - } - } - } -} diff --git a/source/gameengine/Converter/BlenderWorldInfo.h b/source/gameengine/Converter/BlenderWorldInfo.h deleted file mode 100644 index 5c1cbd28104..00000000000 --- a/source/gameengine/Converter/BlenderWorldInfo.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file BlenderWorldInfo.h - * \ingroup bgeconv - */ - -#ifndef __BLENDERWORLDINFO_H__ -#define __BLENDERWORLDINFO_H__ -#include "KX_WorldInfo.h" -#include "KX_KetsjiEngine.h" -#include "RAS_IRasterizer.h" - -struct Scene; -struct World; -const class KX_KetsjiEngine; -const class RAS_IRasterizer; - -class BlenderWorldInfo : public KX_WorldInfo -{ - bool m_hasworld; - bool m_hasmist; - short m_misttype; - float m_miststart; - float m_mistdistance; - float m_mistintensity; - float m_mistcolor[3]; - float m_backgroundcolor[3]; - float m_ambientcolor[3]; - float m_con_mistcolor[3]; - float m_con_backgroundcolor[3]; - float m_con_ambientcolor[3]; - -public: - BlenderWorldInfo(Scene *blenderscene, World *blenderworld); - ~BlenderWorldInfo(); - - bool m_do_color_management; - bool hasWorld(); - bool hasMist(); - short getMistType(); - float getMistStart(); - float getMistDistance(); - float getMistIntensity(); - float getMistColorRed(); - float getMistColorGreen(); - float getMistColorBlue(); - float getBackColorRed(); - float getBackColorGreen(); - float getBackColorBlue(); - float getAmbientColorRed(); - float getAmbientColorGreen(); - float getAmbientColorBlue(); - void setBackColor(float r, float g, float b); - void setUseMist(bool enable); - void setMistType(short type); - void setMistStart(float d); - void setMistDistance(float d); - void setMistIntensity(float intensity); - void setMistColor(float r, float g, float b); - void setAmbientColor(float r, float g, float b); - void UpdateBackGround(); - void UpdateWorldSettings(); - -#ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("GE:BlenderWorldInfo") -#endif -}; - -#endif /* __BLENDERWORLDINFO_H__ */ diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt index 9721149314f..6d681dd166e 100644 --- a/source/gameengine/Converter/CMakeLists.txt +++ b/source/gameengine/Converter/CMakeLists.txt @@ -74,7 +74,6 @@ set(SRC BL_ShapeActionActuator.cpp BL_ShapeDeformer.cpp BL_SkinDeformer.cpp - BlenderWorldInfo.cpp KX_BlenderScalarInterpolator.cpp KX_BlenderSceneConverter.cpp KX_ConvertActuators.cpp @@ -96,7 +95,6 @@ set(SRC BL_ShapeActionActuator.h BL_ShapeDeformer.h BL_SkinDeformer.h - BlenderWorldInfo.h KX_BlenderScalarInterpolator.h KX_BlenderSceneConverter.h KX_ConvertActuators.h diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 09cc74d717f..21c8f39f782 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -58,7 +58,7 @@ #include "KX_LibLoadStatus.h" #include "KX_BlenderScalarInterpolator.h" #include "BL_BlenderDataConversion.h" -#include "BlenderWorldInfo.h" +#include "KX_WorldInfo.h" /* This little block needed for linking to Blender... */ #ifdef WIN32 diff --git a/source/gameengine/Ketsji/KX_WorldInfo.cpp b/source/gameengine/Ketsji/KX_WorldInfo.cpp index 444d6b0771b..a094bffd77a 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.cpp +++ b/source/gameengine/Ketsji/KX_WorldInfo.cpp @@ -31,8 +31,220 @@ #include "KX_WorldInfo.h" +#include "KX_PythonInit.h" +#include "GPU_material.h" + +/* This little block needed for linking to Blender... */ +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + +/* This list includes only data type definitions */ +#include "DNA_scene_types.h" +#include "DNA_world_types.h" + +#include "BLI_math.h" + +#include "BKE_global.h" +#include "BKE_scene.h" +/* end of blender include block */ + + +KX_WorldInfo::KX_WorldInfo(Scene *blenderscene, World *blenderworld) +{ + if (blenderworld) { + m_do_color_management = BKE_scene_check_color_management_enabled(blenderscene); + m_hasworld = true; + m_hasmist = ((blenderworld->mode) & WO_MIST ? true : false); + m_misttype = blenderworld->mistype; + m_miststart = blenderworld->miststa; + m_mistdistance = blenderworld->mistdist; + m_mistintensity = blenderworld->misi; + setMistColor(blenderworld->horr, blenderworld->horg, blenderworld->horb); + setBackColor(blenderworld->horr, blenderworld->horg, blenderworld->horb); + setAmbientColor(blenderworld->ambr, blenderworld->ambg, blenderworld->ambb); + } + else { + m_hasworld = false; + } +} KX_WorldInfo::~KX_WorldInfo() { } +bool KX_WorldInfo::hasWorld() +{ + return m_hasworld; +} + +bool KX_WorldInfo::hasMist() +{ + return m_hasmist; +} + +float KX_WorldInfo::getBackColorRed() +{ + return m_backgroundcolor[0]; +} + +float KX_WorldInfo::getBackColorGreen() +{ + return m_backgroundcolor[1]; +} + +float KX_WorldInfo::getBackColorBlue() +{ + return m_backgroundcolor[2]; +} + +float KX_WorldInfo::getAmbientColorRed() +{ + return m_ambientcolor[0]; +} + +float KX_WorldInfo::getAmbientColorGreen() +{ + return m_ambientcolor[1]; +} + +float KX_WorldInfo::getAmbientColorBlue() +{ + return m_ambientcolor[2]; +} + +short KX_WorldInfo::getMistType() +{ + return m_misttype; +} + +float KX_WorldInfo::getMistStart() +{ + return m_miststart; +} + +float KX_WorldInfo::getMistDistance() +{ + return m_mistdistance; +} + +float KX_WorldInfo::getMistIntensity() +{ + return m_mistintensity; +} + +float KX_WorldInfo::getMistColorRed() +{ + return m_mistcolor[0]; +} + +float KX_WorldInfo::getMistColorGreen() +{ + return m_mistcolor[1]; +} + +float KX_WorldInfo::getMistColorBlue() +{ + return m_mistcolor[2]; +} + +void KX_WorldInfo::setBackColor(float r, float g, float b) +{ + m_backgroundcolor[0] = r; + m_backgroundcolor[1] = g; + m_backgroundcolor[2] = b; + + if (m_do_color_management) { + linearrgb_to_srgb_v3_v3(m_con_backgroundcolor, m_backgroundcolor); + } + else { + copy_v3_v3(m_con_backgroundcolor, m_backgroundcolor); + } +} + +void KX_WorldInfo::setMistType(short type) +{ + m_misttype = type; +} + +void KX_WorldInfo::setUseMist(bool enable) +{ + m_hasmist = enable; +} + +void KX_WorldInfo::setMistStart(float d) +{ + m_miststart = d; +} + +void KX_WorldInfo::setMistDistance(float d) +{ + m_mistdistance = d; +} + +void KX_WorldInfo::setMistIntensity(float intensity) +{ + m_mistintensity = intensity; +} +void KX_WorldInfo::setMistColor(float r, float g, float b) +{ + m_mistcolor[0] = r; + m_mistcolor[1] = g; + m_mistcolor[2] = b; + + if (m_do_color_management) { + linearrgb_to_srgb_v3_v3(m_con_mistcolor, m_mistcolor); + } + else { + copy_v3_v3(m_con_mistcolor, m_mistcolor); + } +} + +void KX_WorldInfo::setAmbientColor(float r, float g, float b) +{ + m_ambientcolor[0] = r; + m_ambientcolor[1] = g; + m_ambientcolor[2] = b; + + if (m_do_color_management) { + linearrgb_to_srgb_v3_v3(m_con_ambientcolor, m_ambientcolor); + } + else { + copy_v3_v3(m_con_ambientcolor, m_ambientcolor); + } +} + +void KX_WorldInfo::UpdateBackGround() +{ + if (m_hasworld) { + RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer(); + + if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) { + m_rasterizer->SetBackColor(m_con_backgroundcolor); + GPU_horizon_update_color(m_backgroundcolor); + } + } +} + +void KX_WorldInfo::UpdateWorldSettings() +{ + if (m_hasworld) { + RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer(); + + if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) { + m_rasterizer->SetAmbientColor(m_con_ambientcolor); + GPU_ambient_update_color(m_ambientcolor); + + if (m_hasmist) { + m_rasterizer->SetFog(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_con_mistcolor); + GPU_mist_update_values(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_mistcolor); + m_rasterizer->EnableFog(true); + GPU_mist_update_enable(true); + } + else { + m_rasterizer->EnableFog(false); + GPU_mist_update_enable(false); + } + } + } +} diff --git a/source/gameengine/Ketsji/KX_WorldInfo.h b/source/gameengine/Ketsji/KX_WorldInfo.h index a6f93dd80ba..4abcfb98892 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.h +++ b/source/gameengine/Ketsji/KX_WorldInfo.h @@ -33,15 +33,34 @@ #define __KX_WORLDINFO_H__ #include "MT_Scalar.h" +#include "KX_KetsjiEngine.h" +#include "RAS_IRasterizer.h" #ifdef WITH_CXX_GUARDEDALLOC #include "MEM_guardedalloc.h" #endif -class MT_CmMatrix4x4; +struct Scene; +struct World; +const class KX_KetsjiEngine; +const class RAS_IRasterizer; class KX_WorldInfo { + bool m_do_color_management; + bool m_hasworld; + bool m_hasmist; + short m_misttype; + float m_miststart; + float m_mistdistance; + float m_mistintensity; + float m_mistcolor[3]; + float m_backgroundcolor[3]; + float m_ambientcolor[3]; + float m_con_mistcolor[3]; + float m_con_backgroundcolor[3]; + float m_con_ambientcolor[3]; + public: /** * Mist options @@ -52,34 +71,34 @@ public: KX_MIST_INV_QUADRATIC, }; - KX_WorldInfo() {} - virtual ~KX_WorldInfo(); + KX_WorldInfo(Scene *blenderscene, World *blenderworld); + ~KX_WorldInfo(); - virtual bool hasWorld() = 0; - virtual bool hasMist() = 0; - virtual short getMistType() = 0; - virtual float getMistStart() = 0; - virtual float getMistDistance() = 0; - virtual float getMistIntensity() = 0; - virtual float getMistColorRed() = 0; - virtual float getMistColorGreen() = 0; - virtual float getMistColorBlue() = 0; - virtual float getBackColorRed() = 0; - virtual float getBackColorGreen() = 0; - virtual float getBackColorBlue() = 0; - virtual float getAmbientColorRed() = 0; - virtual float getAmbientColorGreen() = 0; - virtual float getAmbientColorBlue() = 0; - virtual void setUseMist(bool enable) = 0; - virtual void setMistType(short) = 0; - virtual void setMistStart(float) = 0; - virtual void setMistDistance(float) = 0; - virtual void setMistIntensity(float) = 0; - virtual void setMistColor(float, float, float) = 0; - virtual void setBackColor(float, float, float) = 0; - virtual void setAmbientColor(float,float,float) = 0; - virtual void UpdateBackGround() = 0; - virtual void UpdateWorldSettings() = 0; + bool hasWorld(); + bool hasMist(); + short getMistType(); + float getMistStart(); + float getMistDistance(); + float getMistIntensity(); + float getMistColorRed(); + float getMistColorGreen(); + float getMistColorBlue(); + float getBackColorRed(); + float getBackColorGreen(); + float getBackColorBlue(); + float getAmbientColorRed(); + float getAmbientColorGreen(); + float getAmbientColorBlue(); + void setUseMist(bool enable); + void setMistType(short type); + void setMistStart(float d); + void setMistDistance(float d); + void setMistIntensity(float intensity); + void setMistColor(float r, float g, float b); + void setBackColor(float r, float g, float b); + void setAmbientColor(float r, float g, float b); + void UpdateBackGround(); + void UpdateWorldSettings(); #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:KX_WorldInfo") -- cgit v1.2.3 From fd22a92939dc937216f50d1350a63de872e0a6be Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Tue, 24 Mar 2015 00:23:40 +0100 Subject: BGE: Add new world API KX_WorldInfo (KX_Scene) This Patch will add a the world API (mist, background, ambient) to KX_WorldInfo. The new API uses now attributes. Reviewers: campbellbarton, moguri Reviewed By: moguri Subscribers: klauser, brecht Differential Revision: https://developer.blender.org/D157 --- doc/python_api/rst/bge.render.rst | 35 +-- .../rst/bge_types/bge.types.KX_Scene.rst | 6 + .../rst/bge_types/bge.types.KX_WorldInfo.rst | 87 ++++++ source/gameengine/Ketsji/KX_PythonInit.cpp | 10 +- source/gameengine/Ketsji/KX_PythonInitTypes.cpp | 3 + source/gameengine/Ketsji/KX_Scene.cpp | 14 + source/gameengine/Ketsji/KX_Scene.h | 1 + source/gameengine/Ketsji/KX_WorldInfo.cpp | 303 +++++++++++++++++++++ source/gameengine/Ketsji/KX_WorldInfo.h | 26 +- 9 files changed, 463 insertions(+), 22 deletions(-) create mode 100644 doc/python_api/rst/bge_types/bge.types.KX_WorldInfo.rst diff --git a/doc/python_api/rst/bge.render.rst b/doc/python_api/rst/bge.render.rst index 09d16f4b2ed..2d47244bf7a 100644 --- a/doc/python_api/rst/bge.render.rst +++ b/doc/python_api/rst/bge.render.rst @@ -89,15 +89,15 @@ Constants .. data:: KX_MIST_QUADRATIC - Type of quadratic attenuation used to fade mist. + Type of quadratic attenuation used to fade mist. (Deprecated: use KX_WorldInfo.KX_MIST_QUADRATIC) .. data:: KX_MIST_LINEAR - Type of linear attenuation used to fade mist. + Type of linear attenuation used to fade mist. (Deprecated: use KX_WorldInfo.KX_MIST_LINEAR) .. data:: KX_MIST_INV_QUADRATIC - Type of inverse quadratic attenuation used to fade mist. + Type of inverse quadratic attenuation used to fade mist. (Deprecated: use KX_WorldInfo.KX_MIST_INV_QUADRATIC) ********* @@ -173,50 +173,51 @@ Functions .. function:: setBackgroundColor(rgba) - Sets the window background color. - + Sets the window background color. (Deprecated: use KX_WorldInfo.background_color) + :type rgba: list [r, g, b, a] .. function:: setAmbientColor(rgb) - Sets the color of ambient light. - + Sets the color of ambient light. (Deprecated: use KX_WorldInfo.ambient_color) + :type rgb: list [r, g, b] .. function:: setMistColor(rgb) - Sets the mist color. - + Sets the mist color. (Deprecated: use KX_WorldInfo.mist_color) + :type rgb: list [r, g, b] .. function:: setMistType(mode) - Sets the mist attenuation type. + Sets the mist attenuation type. (Deprecated: use KX_WorldInfo.mist_type) :type mode: KX_MIST_QUADRATIC, KX_MIST_LINEAR, KX_MIST_INV_QUADRATIC .. function:: setMistStart(start) - Sets the mist start value. Objects further away than start will have mist applied to them. - + Sets the mist start value. Objects further away than start will have mist applied to them. + (Deprecated: use KX_WorldInfo.mist_start) + :type start: float .. function:: setMistEnd(end) Sets the mist end value. Objects further away from this will be colored solid with - the color set by setMistColor(). - + the color set by setMistColor(). (Deprecated: use KX_WorldInfo.mist_distance) + :type end: float .. function:: setMistIntensity(intensity) - Sets the mist intensity value. + Sets the mist intensity value. (Deprecated: use KX_WorldInfo.mist_intensity) :type start: float @@ -225,12 +226,12 @@ Functions Disables mist. - .. note:: Deprecated use setUseMist(). + .. note:: Deprecated: use KX_WorldInfo.mist_enable. .. function:: setUseMist(enable) - Disable or enable the mist. + Disable or enable the mist. (Deprecated: use KX_WorldInfo.mist_enable) :type enable: boolean diff --git a/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst b/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst index fc5ba357add..255ff95ad37 100644 --- a/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst +++ b/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst @@ -83,6 +83,12 @@ base class --- :class:`PyObjectPlus` This can be set directly from python to avoid using the :class:`KX_SceneActuator`. + .. attribute:: world + + The current active world, (read-only). + + :type: :class:`KX_WorldInfo` + .. attribute:: suspended True if the scene is suspended, (read-only). diff --git a/doc/python_api/rst/bge_types/bge.types.KX_WorldInfo.rst b/doc/python_api/rst/bge_types/bge.types.KX_WorldInfo.rst new file mode 100644 index 00000000000..ffc24b4e6c5 --- /dev/null +++ b/doc/python_api/rst/bge_types/bge.types.KX_WorldInfo.rst @@ -0,0 +1,87 @@ +KX_WordlInfo(PyObjectPlus) +============================= + +.. module:: bge.types + +base class --- :class:`PyObjectPlus` + +.. class:: KX_WorldInfo(PyObjectPlus) + + A wolrd object. + + .. code-block:: python + + # Set the mist color to red. + import bge + + sce = bge.logic.getCurrentScene() + + sce.world.mist_color = [1.0, 0.0, 0.0] + +********* +Constants +********* + + .. data:: KX_MIST_QUADRATIC + + Type of quadratic attenuation used to fade mist. + + .. data:: KX_MIST_LINEAR + + Type of linear attenuation used to fade mist. + + .. data:: KX_MIST_INV_QUADRATIC + + Type of inverse quadratic attenuation used to fade mist. + +********** +Attributes +********** + + .. attribute:: mist_enable + + Return the state of the mist. + + :type: bool + + .. attribute:: mist_start + + The mist start point. + + :type: float + + .. attribute:: mist_distance + + The mist distance fom the start point to reach 100% mist. + + :type: float + + .. attribute:: mist_intensity + + The mist intensity. + + :type: float + + .. attribute:: mist_type + + The type of mist - must be KX_MIST_QUADRATIC, KX_MIST_LINEAR or KX_MIST_INV_QUADRATIC + + .. attribute:: mist_color + + The color of the mist. Black = [0.0, 0.0, 0.0], White = [1.0, 1.0, 1.0]. + Mist and background color sould always set to the same color. + + :type: :class:`mathutils.Vector` + + .. attribute:: background_color + + The color of the background. Black = [0.0, 0.0, 0.0], White = [1.0, 1.0, 1.0]. + Mist and background color sould always set to the same color. + + :type: :class:`mathutils.Vector` + + .. attribute:: ambient_color + + The color of the ambient light. Black = [0.0, 0.0, 0.0], White = [1.0, 1.0, 1.0]. + + :type: :class:`mathutils.Vector` diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 8fd38db4a2a..b3fba745e96 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -1039,6 +1039,7 @@ static PyObject *gPySetBackgroundColor(PyObject *, PyObject *value) return NULL; } + ShowDeprecationWarning("setBackgroundColor()", "KX_WorldInfo.background_color"); wi->setBackColor((float)vec[0], (float)vec[1], (float)vec[2]); Py_RETURN_NONE; @@ -1056,6 +1057,7 @@ static PyObject *gPySetMistColor(PyObject *, PyObject *value) return NULL; } + ShowDeprecationWarning("setMistColor()", "KX_WorldInfo.mist_color"); wi->setMistColor((float)vec[0], (float)vec[1], (float)vec[2]); Py_RETURN_NONE; @@ -1068,7 +1070,7 @@ static PyObject *gPyDisableMist(PyObject *) PyErr_SetString(PyExc_RuntimeError, "bge.render.DisableMist(), World not available"); return NULL; } - ShowDeprecationWarning("DisableMist()", "setUseMist(false)"); + ShowDeprecationWarning("DisableMist()", "KX_WorldInfo.mist_enable = False"); wi->setUseMist(false); Py_RETURN_NONE; @@ -1086,6 +1088,7 @@ static PyObject *gPySetUseMist(PyObject *, PyObject *args) return NULL; } + ShowDeprecationWarning("setUseMist()", "KX_WorldInfo.mist_enable"); wi->setUseMist(enable); Py_RETURN_NONE; @@ -1109,6 +1112,7 @@ static PyObject *gPySetMistType(PyObject *, PyObject *args) return NULL; } + ShowDeprecationWarning("setMistType()", "KX_WorldInfo.mist_type"); wi->setMistType(type); Py_RETURN_NONE; @@ -1126,6 +1130,7 @@ static PyObject *gPySetMistStart(PyObject *, PyObject *args) return NULL; } + ShowDeprecationWarning("setMistStart()", "KX_WorldInfo.mist_start"); wi->setMistStart(miststart); Py_RETURN_NONE; @@ -1143,6 +1148,7 @@ static PyObject *gPySetMistEnd(PyObject *, PyObject *args) return NULL; } + ShowDeprecationWarning("setMistEnd()", "KX_WorldInfo.mist_distance"); wi->setMistDistance(mistdist); Py_RETURN_NONE; @@ -1161,6 +1167,7 @@ static PyObject *gPySetMistIntensity(PyObject *, PyObject *args) return NULL; } + ShowDeprecationWarning("setMistIntensity()", "KX_WorldInfo.mist_intensity"); wi->setMistIntensity(intensity); Py_RETURN_NONE; @@ -1178,6 +1185,7 @@ static PyObject *gPySetAmbientColor(PyObject *, PyObject *value) return NULL; } + ShowDeprecationWarning("setAmbientColor()", "KX_WorldInfo.ambient_color"); wi->setAmbientColor((float)vec[0], (float)vec[1], (float)vec[2]); Py_RETURN_NONE; diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp index 828fd62f205..b3511e4e61a 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp @@ -40,6 +40,7 @@ #include "BL_ArmatureConstraint.h" #include "BL_ArmatureObject.h" #include "BL_ArmatureChannel.h" +#include "KX_WorldInfo.h" #include "KX_ArmatureSensor.h" #include "KX_BlenderMaterial.h" #include "KX_CameraActuator.h" @@ -231,6 +232,7 @@ PyMODINIT_FUNC initGameTypesPythonBinding(void) PyType_Ready_Attr(dict, KX_SCA_EndObjectActuator, init_getset); PyType_Ready_Attr(dict, KX_SCA_ReplaceMeshActuator, init_getset); PyType_Ready_Attr(dict, KX_Scene, init_getset); + PyType_Ready_Attr(dict, KX_WorldInfo, init_getset); PyType_Ready_Attr(dict, KX_NavMeshObject, init_getset); PyType_Ready_Attr(dict, KX_SceneActuator, init_getset); PyType_Ready_Attr(dict, KX_SoundActuator, init_getset); @@ -279,6 +281,7 @@ PyMODINIT_FUNC initGameTypesPythonBinding(void) /* Init mathutils callbacks */ KX_GameObject_Mathutils_Callback_Init(); KX_ObjectActuator_Mathutils_Callback_Init(); + KX_WorldInfo_Mathutils_Callback_Init(); #endif return m; diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index e26fdaa4898..193a72ebd2a 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -2341,6 +2341,19 @@ PyObject *KX_Scene::pyattr_get_lights(void *self_v, const KX_PYATTRIBUTE_DEF *at return self->GetLightList()->GetProxy(); } +PyObject *KX_Scene::pyattr_get_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self = static_cast(self_v); + KX_WorldInfo *world = self->GetWorldInfo(); + + if (world->GetName() != "") { + return world->GetProxy(); + } + else { + Py_RETURN_NONE; + } +} + PyObject *KX_Scene::pyattr_get_cameras(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { /* With refcounts in this case... @@ -2464,6 +2477,7 @@ PyAttributeDef KX_Scene::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("objectsInactive", KX_Scene, pyattr_get_objects_inactive), KX_PYATTRIBUTE_RO_FUNCTION("lights", KX_Scene, pyattr_get_lights), KX_PYATTRIBUTE_RO_FUNCTION("cameras", KX_Scene, pyattr_get_cameras), + KX_PYATTRIBUTE_RO_FUNCTION("world", KX_Scene, pyattr_get_world), KX_PYATTRIBUTE_RW_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera), KX_PYATTRIBUTE_RW_FUNCTION("pre_draw", KX_Scene, pyattr_get_drawing_callback_pre, pyattr_set_drawing_callback_pre), KX_PYATTRIBUTE_RW_FUNCTION("post_draw", KX_Scene, pyattr_get_drawing_callback_post, pyattr_set_drawing_callback_post), diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index a031be78e92..93e764851a9 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -624,6 +624,7 @@ public: static PyObject* pyattr_get_objects_inactive(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_lights(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_cameras(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_world(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_active_camera(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_WorldInfo.cpp b/source/gameengine/Ketsji/KX_WorldInfo.cpp index a094bffd77a..b07aa26cf91 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.cpp +++ b/source/gameengine/Ketsji/KX_WorldInfo.cpp @@ -32,6 +32,8 @@ #include "KX_WorldInfo.h" #include "KX_PythonInit.h" +#include "KX_PyMath.h" +#include "RAS_IRasterizer.h" #include "GPU_material.h" /* This little block needed for linking to Blender... */ @@ -53,6 +55,7 @@ KX_WorldInfo::KX_WorldInfo(Scene *blenderscene, World *blenderworld) { if (blenderworld) { + m_name = blenderworld->id.name + 2; m_do_color_management = BKE_scene_check_color_management_enabled(blenderscene); m_hasworld = true; m_hasmist = ((blenderworld->mode) & WO_MIST ? true : false); @@ -73,6 +76,11 @@ KX_WorldInfo::~KX_WorldInfo() { } +const STR_String& KX_WorldInfo::GetName() +{ + return m_name; +} + bool KX_WorldInfo::hasWorld() { return m_hasworld; @@ -248,3 +256,298 @@ void KX_WorldInfo::UpdateWorldSettings() } } } + +#ifdef WITH_PYTHON + +/* ------------------------------------------------------------------------- + * Python functions + * ------------------------------------------------------------------------- */ +PyObject *KX_WorldInfo::py_repr(void) +{ + return PyUnicode_From_STR_String(GetName()); +} + +/* ------------------------------------------------------------------------- + * Python Integration Hooks + * ------------------------------------------------------------------------- */ +PyTypeObject KX_WorldInfo::Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "KX_WorldInfo", + sizeof(PyObjectPlus_Proxy), + 0, + py_base_dealloc, + 0, + 0, + 0, + 0, + py_base_repr, + 0,0,0,0,0,0,0,0,0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new +}; + +PyMethodDef KX_WorldInfo::Methods[] = { + {NULL,NULL} /* Sentinel */ +}; + +PyAttributeDef KX_WorldInfo::Attributes[] = { + KX_PYATTRIBUTE_BOOL_RW("mist_enable", KX_WorldInfo, m_hasmist), + KX_PYATTRIBUTE_FLOAT_RW("mist_start", 0.0f, 10000.0f, KX_WorldInfo, m_miststart), + KX_PYATTRIBUTE_FLOAT_RW("mist_distance", 0.001f, 10000.0f, KX_WorldInfo, m_mistdistance), + KX_PYATTRIBUTE_FLOAT_RW("mist_intensity", 0.0f, 1.0f, KX_WorldInfo, m_mistintensity), + KX_PYATTRIBUTE_SHORT_RW("mist_type", 0, 2, true, KX_WorldInfo, m_misttype), + KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_QUADRATIC", KX_WorldInfo, pyattr_get_mist_typeconst), + KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_LINEAR", KX_WorldInfo, pyattr_get_mist_typeconst), + KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_INV_QUADRATIC", KX_WorldInfo, pyattr_get_mist_typeconst), + KX_PYATTRIBUTE_RW_FUNCTION("mist_color", KX_WorldInfo, pyattr_get_mist_color, pyattr_set_mist_color), + KX_PYATTRIBUTE_RW_FUNCTION("background_color", KX_WorldInfo, pyattr_get_back_color, pyattr_set_back_color), + KX_PYATTRIBUTE_RW_FUNCTION("ambient_color", KX_WorldInfo, pyattr_get_ambient_color, pyattr_set_ambient_color), + { NULL } /* Sentinel */ +}; + +/* Attribute get/set functions */ + +#ifdef USE_MATHUTILS + +/*----------------------mathutils callbacks ----------------------------*/ + +/* subtype */ +#define MATHUTILS_VEC_CB_MIST_COLOR 1 +#define MATHUTILS_VEC_CB_BACK_COLOR 2 +#define MATHUTILS_VEC_CB_AMBIENT_COLOR 3 + +static unsigned char mathutils_world_vector_cb_index = -1; /* index for our callbacks */ + +static int mathutils_world_generic_check(BaseMathObject *bmo) +{ + KX_WorldInfo *self = static_castBGE_PROXY_REF(bmo->cb_user); + if (self == NULL) + return -1; + + return 0; +} + +static int mathutils_world_vector_get(BaseMathObject *bmo, int subtype) +{ + KX_WorldInfo *self = static_castBGE_PROXY_REF(bmo->cb_user); + if (self == NULL) + return -1; + + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + copy_v3_v3(bmo->data, self->m_mistcolor); + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + copy_v3_v3(bmo->data, self->m_backgroundcolor); + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + copy_v3_v3(bmo->data, self->m_ambientcolor); + break; + default: + return -1; + } + return 0; +} + +static int mathutils_world_vector_set(BaseMathObject *bmo, int subtype) +{ + KX_WorldInfo *self = static_castBGE_PROXY_REF(bmo->cb_user); + + if (self == NULL) + return -1; + + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + self->setMistColor(bmo->data[0], bmo->data[1], bmo->data[2]); + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + self->setBackColor(bmo->data[0], bmo->data[1], bmo->data[2]); + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + self->setAmbientColor(bmo->data[0], bmo->data[1], bmo->data[2]); + break; + default: + return -1; + } + return 0; +} + +static int mathutils_world_vector_get_index(BaseMathObject *bmo, int subtype, int index) +{ + KX_WorldInfo *self = static_castBGE_PROXY_REF(bmo->cb_user); + + if (self == NULL) + return -1; + + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + { + const float *color = self->m_mistcolor; + bmo->data[index] = color[index]; + } + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + { + const float *color = self->m_backgroundcolor; + bmo->data[index] = color[index]; + } + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + { + const float *color = self->m_ambientcolor; + bmo->data[index] = color[index]; + } + break; + default: + return -1; + } + return 0; +} + +static int mathutils_world_vector_set_index(BaseMathObject *bmo, int subtype, int index) +{ + KX_WorldInfo *self = static_castBGE_PROXY_REF(bmo->cb_user); + + if (self == NULL) + return -1; + + float color[4]; + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + copy_v3_v3(color, self->m_mistcolor); + color[index] = bmo->data[index]; + self->setMistColor(color[0], color[1], color[2]); + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + copy_v3_v3(color, self->m_backgroundcolor); + color[index] = bmo->data[index]; + self->setBackColor(color[0], color[1], color[2]); + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + copy_v3_v3(color, self->m_ambientcolor); + color[index] = bmo->data[index]; + self->setAmbientColor(color[0], color[1], color[2]); + break; + default: + return -1; + } + return 0; +} + +static Mathutils_Callback mathutils_world_vector_cb = { + mathutils_world_generic_check, + mathutils_world_vector_get, + mathutils_world_vector_set, + mathutils_world_vector_get_index, + mathutils_world_vector_set_index +}; + +void KX_WorldInfo_Mathutils_Callback_Init() +{ + // register mathutils callbacks, ok to run more than once. + mathutils_world_vector_cb_index = Mathutils_RegisterCallback(&mathutils_world_vector_cb); +} +#endif // USE_MATHUTILS + + +PyObject *KX_WorldInfo::pyattr_get_mist_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + PyObject *retvalue; + + const char* type = attrdef->m_name; + + if (!strcmp(type, "KX_MIST_QUADRATIC")) { + retvalue = PyLong_FromLong(KX_MIST_QUADRATIC); + } + else if (!strcmp(type, "KX_MIST_LINEAR")) { + retvalue = PyLong_FromLong(KX_MIST_LINEAR); + } + else if (!strcmp(type, "KX_MIST_INV_QUADRATIC")) { + retvalue = PyLong_FromLong(KX_MIST_INV_QUADRATIC); + } + else { + /* should never happen */ + PyErr_SetString(PyExc_TypeError, "invalid mist type"); + retvalue = NULL; + } + + return retvalue; +} + +PyObject *KX_WorldInfo::pyattr_get_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ +#ifdef USE_MATHUTILS + return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_MIST_COLOR); +#else + KX_WorldInfo *self = static_cast(self_v); + return PyObjectFrom(MT_Vector3(self->m_mistcolor)); +#endif +} + +int KX_WorldInfo::pyattr_set_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_WorldInfo *self = static_cast(self_v); + + MT_Vector3 color; + if (PyVecTo(value, color)) + { + self->setMistColor(color[0], color[1], color[2]); + return PY_SET_ATTR_SUCCESS; + } + return PY_SET_ATTR_FAIL; +} + +PyObject *KX_WorldInfo::pyattr_get_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + +#ifdef USE_MATHUTILS + return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_BACK_COLOR); +#else + KX_WorldInfo *self = static_cast(self_v); + return PyObjectFrom(MT_Vector3(self->m_backgroundcolor)); +#endif +} + +int KX_WorldInfo::pyattr_set_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_WorldInfo *self = static_cast(self_v); + + MT_Vector3 color; + if (PyVecTo(value, color)) + { + self->setBackColor(color[0], color[1], color[2]); + return PY_SET_ATTR_SUCCESS; + } + return PY_SET_ATTR_FAIL; +} + +PyObject *KX_WorldInfo::pyattr_get_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ +#ifdef USE_MATHUTILS + return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_AMBIENT_COLOR); +#else + KX_WorldInfo *self = static_cast(self_v); + return PyObjectFrom(MT_Vector3(self->m_ambientcolor)); +#endif +} + +int KX_WorldInfo::pyattr_set_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_WorldInfo *self = static_cast(self_v); + + MT_Vector3 color; + if (PyVecTo(value, color)) + { + self->setAmbientColor(color[0], color[1], color[2]); + return PY_SET_ATTR_SUCCESS; + } + return PY_SET_ATTR_FAIL; +} + +#endif /* WITH_PYTHON */ diff --git a/source/gameengine/Ketsji/KX_WorldInfo.h b/source/gameengine/Ketsji/KX_WorldInfo.h index 4abcfb98892..830f12de6b0 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.h +++ b/source/gameengine/Ketsji/KX_WorldInfo.h @@ -34,19 +34,24 @@ #include "MT_Scalar.h" #include "KX_KetsjiEngine.h" -#include "RAS_IRasterizer.h" +#include "PyObjectPlus.h" #ifdef WITH_CXX_GUARDEDALLOC #include "MEM_guardedalloc.h" #endif +#ifdef USE_MATHUTILS +void KX_WorldInfo_Mathutils_Callback_Init(void); +#endif + struct Scene; struct World; -const class KX_KetsjiEngine; -const class RAS_IRasterizer; -class KX_WorldInfo +class KX_WorldInfo : public PyObjectPlus { + Py_Header + + STR_String m_name; bool m_do_color_management; bool m_hasworld; bool m_hasmist; @@ -74,6 +79,7 @@ public: KX_WorldInfo(Scene *blenderscene, World *blenderworld); ~KX_WorldInfo(); + const STR_String &GetName(); bool hasWorld(); bool hasMist(); short getMistType(); @@ -100,6 +106,18 @@ public: void UpdateBackGround(); void UpdateWorldSettings(); +#ifdef WITH_PYTHON + /* attributes */ + static PyObject *pyattr_get_mist_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + virtual PyObject *py_repr(void); +#endif + #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:KX_WorldInfo") #endif -- cgit v1.2.3 From ee579684617c1a9868b2c75cfb5d32efe26c1198 Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Tue, 24 Mar 2015 00:27:45 +0100 Subject: BGE: Remove old world bge.render API This patch can be used to remove the old world bge.render API if the new world API D157 is used. If the new world API is applied we can remove the old API because the old has newer worked. The patch keep the two old working methods for backward compatibility. Reviewers: campbellbarton, moguri Reviewed By: campbellbarton, moguri Subscribers: brecht Differential Revision: https://developer.blender.org/D158 --- doc/python_api/rst/bge.render.rst | 70 ------------- source/gameengine/Ketsji/KX_PythonInit.cpp | 159 ----------------------------- source/gameengine/Ketsji/KX_WorldInfo.cpp | 70 ------------- source/gameengine/Ketsji/KX_WorldInfo.h | 14 --- 4 files changed, 313 deletions(-) diff --git a/doc/python_api/rst/bge.render.rst b/doc/python_api/rst/bge.render.rst index 2d47244bf7a..d185a5d05aa 100644 --- a/doc/python_api/rst/bge.render.rst +++ b/doc/python_api/rst/bge.render.rst @@ -87,18 +87,6 @@ Constants Right eye being used during stereoscopic rendering. -.. data:: KX_MIST_QUADRATIC - - Type of quadratic attenuation used to fade mist. (Deprecated: use KX_WorldInfo.KX_MIST_QUADRATIC) - -.. data:: KX_MIST_LINEAR - - Type of linear attenuation used to fade mist. (Deprecated: use KX_WorldInfo.KX_MIST_LINEAR) - -.. data:: KX_MIST_INV_QUADRATIC - - Type of inverse quadratic attenuation used to fade mist. (Deprecated: use KX_WorldInfo.KX_MIST_INV_QUADRATIC) - ********* Functions @@ -178,64 +166,6 @@ Functions :type rgba: list [r, g, b, a] -.. function:: setAmbientColor(rgb) - - Sets the color of ambient light. (Deprecated: use KX_WorldInfo.ambient_color) - - :type rgb: list [r, g, b] - - -.. function:: setMistColor(rgb) - - Sets the mist color. (Deprecated: use KX_WorldInfo.mist_color) - - :type rgb: list [r, g, b] - - -.. function:: setMistType(mode) - - Sets the mist attenuation type. (Deprecated: use KX_WorldInfo.mist_type) - - :type mode: KX_MIST_QUADRATIC, KX_MIST_LINEAR, KX_MIST_INV_QUADRATIC - - -.. function:: setMistStart(start) - - Sets the mist start value. Objects further away than start will have mist applied to them. - (Deprecated: use KX_WorldInfo.mist_start) - - :type start: float - - -.. function:: setMistEnd(end) - - Sets the mist end value. Objects further away from this will be colored solid with - the color set by setMistColor(). (Deprecated: use KX_WorldInfo.mist_distance) - - :type end: float - - -.. function:: setMistIntensity(intensity) - - Sets the mist intensity value. (Deprecated: use KX_WorldInfo.mist_intensity) - - :type start: float - -.. function:: disableMist() - - - Disables mist. - - .. note:: Deprecated: use KX_WorldInfo.mist_enable. - - -.. function:: setUseMist(enable) - - Disable or enable the mist. (Deprecated: use KX_WorldInfo.mist_enable) - - :type enable: boolean - - .. function:: setEyeSeparation(eyesep) Sets the eye separation for stereo mode. Usually Focal Length/30 provides a confortable value. diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index b3fba745e96..074cbd9937e 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -1045,152 +1045,6 @@ static PyObject *gPySetBackgroundColor(PyObject *, PyObject *value) Py_RETURN_NONE; } -static PyObject *gPySetMistColor(PyObject *, PyObject *value) -{ - MT_Vector3 vec; - if (!PyVecTo(value, vec)) - return NULL; - - KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); - if (!wi->hasWorld()) { - PyErr_SetString(PyExc_RuntimeError, "bge.render.setMistColor(color), World not available"); - return NULL; - } - - ShowDeprecationWarning("setMistColor()", "KX_WorldInfo.mist_color"); - wi->setMistColor((float)vec[0], (float)vec[1], (float)vec[2]); - - Py_RETURN_NONE; -} - -static PyObject *gPyDisableMist(PyObject *) -{ - KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); - if (!wi->hasWorld()) { - PyErr_SetString(PyExc_RuntimeError, "bge.render.DisableMist(), World not available"); - return NULL; - } - ShowDeprecationWarning("DisableMist()", "KX_WorldInfo.mist_enable = False"); - wi->setUseMist(false); - - Py_RETURN_NONE; -} - -static PyObject *gPySetUseMist(PyObject *, PyObject *args) -{ - int enable; - if (!PyArg_ParseTuple(args,"i:setUseMist",&enable)) - return NULL; - - KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); - if (!wi->hasWorld()) { - PyErr_SetString(PyExc_RuntimeError, "bge.render.setUseMist(enable), World not available"); - return NULL; - } - - ShowDeprecationWarning("setUseMist()", "KX_WorldInfo.mist_enable"); - wi->setUseMist(enable); - - Py_RETURN_NONE; -} - -static PyObject *gPySetMistType(PyObject *, PyObject *args) -{ - short type; - - if (!PyArg_ParseTuple(args,"i:setMistType",&type)) - return NULL; - - if (type < 0 || type > 2) { - PyErr_SetString(PyExc_ValueError, "Rasterizer.setMistType(int): Mist type is not known"); - return NULL; - } - - KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); - if (!wi->hasWorld()) { - PyErr_SetString(PyExc_RuntimeError, "bge.render.setMistType(int), World not available"); - return NULL; - } - - ShowDeprecationWarning("setMistType()", "KX_WorldInfo.mist_type"); - wi->setMistType(type); - - Py_RETURN_NONE; -} - -static PyObject *gPySetMistStart(PyObject *, PyObject *args) -{ - float miststart; - if (!PyArg_ParseTuple(args,"f:setMistStart",&miststart)) - return NULL; - - KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); - if (!wi->hasWorld()) { - PyErr_SetString(PyExc_RuntimeError, "bge.render.setMistStart(float), World not available"); - return NULL; - } - - ShowDeprecationWarning("setMistStart()", "KX_WorldInfo.mist_start"); - wi->setMistStart(miststart); - - Py_RETURN_NONE; -} - -static PyObject *gPySetMistEnd(PyObject *, PyObject *args) -{ - float mistdist; - if (!PyArg_ParseTuple(args,"f:setMistEnd",&mistdist)) - return NULL; - - KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); - if (!wi->hasWorld()) { - PyErr_SetString(PyExc_RuntimeError, "bge.render.setMistEnd(float), World not available"); - return NULL; - } - - ShowDeprecationWarning("setMistEnd()", "KX_WorldInfo.mist_distance"); - wi->setMistDistance(mistdist); - - Py_RETURN_NONE; -} - -static PyObject *gPySetMistIntensity(PyObject *, PyObject *args) -{ - - float intensity; - if (!PyArg_ParseTuple(args,"f:setMistIntensity",&intensity)) - return NULL; - - KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); - if (!wi->hasWorld()) { - PyErr_SetString(PyExc_RuntimeError, "bge.render.setMistIntensity(float), World not available"); - return NULL; - } - - ShowDeprecationWarning("setMistIntensity()", "KX_WorldInfo.mist_intensity"); - wi->setMistIntensity(intensity); - - Py_RETURN_NONE; -} - -static PyObject *gPySetAmbientColor(PyObject *, PyObject *value) -{ - MT_Vector3 vec; - if (!PyVecTo(value, vec)) - return NULL; - - KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); - if (!wi->hasWorld()) { - PyErr_SetString(PyExc_RuntimeError, "bge.render.setAmbientColor(color), World not available"); - return NULL; - } - - ShowDeprecationWarning("setAmbientColor()", "KX_WorldInfo.ambient_color"); - wi->setAmbientColor((float)vec[0], (float)vec[1], (float)vec[2]); - - Py_RETURN_NONE; -} - static PyObject *gPyMakeScreenshot(PyObject *, PyObject *args) { char* filename; @@ -1567,14 +1421,6 @@ static struct PyMethodDef rasterizer_methods[] = { {"setMousePosition",(PyCFunction) gPySetMousePosition, METH_VARARGS, "setMousePosition(int x,int y)"}, {"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_O,"set Background Color (rgb)"}, - {"setAmbientColor",(PyCFunction)gPySetAmbientColor,METH_O,"set Ambient Color (rgb)"}, - {"disableMist",(PyCFunction)gPyDisableMist,METH_NOARGS,"turn off mist"}, - {"setUseMist",(PyCFunction)gPySetUseMist,METH_VARARGS,"enable or disable mist"}, - {"setMistColor",(PyCFunction)gPySetMistColor,METH_O,"set Mist Color (rgb)"}, - {"setMistType",(PyCFunction)gPySetMistType,METH_VARARGS,"set mist type (short type)"}, - {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start"}, - {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End"}, - {"setMistIntensity",(PyCFunction)gPySetMistIntensity,METH_VARARGS,"set mist intensity (float intensity)"}, {"enableMotionBlur",(PyCFunction)gPyEnableMotionBlur,METH_VARARGS,"enable motion blur"}, {"disableMotionBlur",(PyCFunction)gPyDisableMotionBlur,METH_NOARGS,"disable motion blur"}, @@ -2421,11 +2267,6 @@ PyMODINIT_FUNC initRasterizerPythonBinding() KX_MACRO_addTypesToDict(d, LEFT_EYE, RAS_IRasterizer::RAS_STEREO_LEFTEYE); KX_MACRO_addTypesToDict(d, RIGHT_EYE, RAS_IRasterizer::RAS_STEREO_RIGHTEYE); - /* KX_WorldInfo mist types */ - KX_MACRO_addTypesToDict(d, KX_MIST_QUADRATIC, KX_WorldInfo::KX_MIST_QUADRATIC); - KX_MACRO_addTypesToDict(d, KX_MIST_LINEAR, KX_WorldInfo::KX_MIST_LINEAR); - KX_MACRO_addTypesToDict(d, KX_MIST_INV_QUADRATIC, KX_WorldInfo::KX_MIST_INV_QUADRATIC); - // XXXX Add constants here // Check for errors diff --git a/source/gameengine/Ketsji/KX_WorldInfo.cpp b/source/gameengine/Ketsji/KX_WorldInfo.cpp index b07aa26cf91..e4bf439501f 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.cpp +++ b/source/gameengine/Ketsji/KX_WorldInfo.cpp @@ -86,76 +86,6 @@ bool KX_WorldInfo::hasWorld() return m_hasworld; } -bool KX_WorldInfo::hasMist() -{ - return m_hasmist; -} - -float KX_WorldInfo::getBackColorRed() -{ - return m_backgroundcolor[0]; -} - -float KX_WorldInfo::getBackColorGreen() -{ - return m_backgroundcolor[1]; -} - -float KX_WorldInfo::getBackColorBlue() -{ - return m_backgroundcolor[2]; -} - -float KX_WorldInfo::getAmbientColorRed() -{ - return m_ambientcolor[0]; -} - -float KX_WorldInfo::getAmbientColorGreen() -{ - return m_ambientcolor[1]; -} - -float KX_WorldInfo::getAmbientColorBlue() -{ - return m_ambientcolor[2]; -} - -short KX_WorldInfo::getMistType() -{ - return m_misttype; -} - -float KX_WorldInfo::getMistStart() -{ - return m_miststart; -} - -float KX_WorldInfo::getMistDistance() -{ - return m_mistdistance; -} - -float KX_WorldInfo::getMistIntensity() -{ - return m_mistintensity; -} - -float KX_WorldInfo::getMistColorRed() -{ - return m_mistcolor[0]; -} - -float KX_WorldInfo::getMistColorGreen() -{ - return m_mistcolor[1]; -} - -float KX_WorldInfo::getMistColorBlue() -{ - return m_mistcolor[2]; -} - void KX_WorldInfo::setBackColor(float r, float g, float b) { m_backgroundcolor[0] = r; diff --git a/source/gameengine/Ketsji/KX_WorldInfo.h b/source/gameengine/Ketsji/KX_WorldInfo.h index 830f12de6b0..64304e594cc 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.h +++ b/source/gameengine/Ketsji/KX_WorldInfo.h @@ -81,20 +81,6 @@ public: const STR_String &GetName(); bool hasWorld(); - bool hasMist(); - short getMistType(); - float getMistStart(); - float getMistDistance(); - float getMistIntensity(); - float getMistColorRed(); - float getMistColorGreen(); - float getMistColorBlue(); - float getBackColorRed(); - float getBackColorGreen(); - float getBackColorBlue(); - float getAmbientColorRed(); - float getAmbientColorGreen(); - float getAmbientColorBlue(); void setUseMist(bool enable); void setMistType(short type); void setMistStart(float d); -- cgit v1.2.3 From 22e222563a763d488d4943f28104dc452a651e34 Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Tue, 24 Mar 2015 00:31:31 +0100 Subject: Blender world value viewport update This patch will update the 3D viewport if a word value has changed. This patch does not depends on an other patch, but should applied after https://developer.blender.org/D151 otherwise the the word value viewport update is be slow. Reviewers: brecht Reviewed By: brecht Subscribers: thelasthope, darkxiv Differential Revision: https://developer.blender.org/D159 --- source/blender/makesrna/intern/rna_world.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c index 721cbaf21c7..a206fb2d0a6 100644 --- a/source/blender/makesrna/intern/rna_world.c +++ b/source/blender/makesrna/intern/rna_world.c @@ -403,13 +403,13 @@ static void rna_def_world_mist(BlenderRNA *brna) prop = RNA_def_property(srna, "use_mist", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", WO_MIST); RNA_def_property_ui_text(prop, "Use Mist", "Occlude objects with the environment color as they are further away"); - RNA_def_property_update(prop, 0, "rna_World_draw_update"); + RNA_def_property_update(prop, 0, "rna_World_draw_mist_update"); prop = RNA_def_property(srna, "intensity", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "misi"); RNA_def_property_range(prop, 0, 1); RNA_def_property_ui_text(prop, "Minimum", "Overall minimum intensity of the mist effect"); - RNA_def_property_update(prop, 0, "rna_World_update"); + RNA_def_property_update(prop, 0, "rna_World_draw_mist_update"); prop = RNA_def_property(srna, "start", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "miststa"); @@ -435,7 +435,7 @@ static void rna_def_world_mist(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "mistype"); RNA_def_property_enum_items(prop, falloff_items); RNA_def_property_ui_text(prop, "Falloff", "Type of transition used to fade mist"); - RNA_def_property_update(prop, 0, "rna_World_update"); + RNA_def_property_update(prop, 0, "rna_World_draw_mist_update"); } void RNA_def_world(BlenderRNA *brna) @@ -460,8 +460,7 @@ void RNA_def_world(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Horizon Color", "Color at the horizon"); /* RNA_def_property_update(prop, 0, "rna_World_update"); */ /* render-only uses this */ - RNA_def_property_update(prop, NC_WORLD | ND_WORLD_DRAW, "rna_World_update"); - + RNA_def_property_update(prop, 0, "rna_World_draw_mist_update"); prop = RNA_def_property(srna, "zenith_color", PROP_FLOAT, PROP_COLOR); RNA_def_property_float_sdna(prop, NULL, "zenr"); @@ -473,7 +472,7 @@ void RNA_def_world(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "ambr"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Ambient Color", "Ambient color of the world"); - RNA_def_property_update(prop, 0, "rna_World_update"); + RNA_def_property_update(prop, 0, "rna_World_draw_mist_update"); /* exp, range */ prop = RNA_def_property(srna, "exposure", PROP_FLOAT, PROP_NONE); -- cgit v1.2.3 From a93f346ff45a4ee68a45347036f135e75700caca Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Mar 2015 15:08:52 +1100 Subject: Cleanup: unused function --- source/blender/makesrna/intern/rna_world.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c index a206fb2d0a6..3f55ad9c668 100644 --- a/source/blender/makesrna/intern/rna_world.c +++ b/source/blender/makesrna/intern/rna_world.c @@ -92,6 +92,7 @@ static void rna_World_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR WM_main_add_notifier(NC_WORLD | ND_WORLD, wo); } +#if 0 static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { World *wo = ptr->id.data; @@ -99,6 +100,7 @@ static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi DAG_id_tag_update(&wo->id, 0); WM_main_add_notifier(NC_WORLD | ND_WORLD_DRAW, wo); } +#endif /* so camera mist limits redraw */ static void rna_World_draw_mist_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) -- cgit v1.2.3 From 3bb7e14618cb928d43fecf0a8930a1edd85dde3e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Mar 2015 15:05:27 +1100 Subject: UI: remove UI_BTYPE_SEARCH_MENU_UNLINK Internal change only, use UI_BTYPE_SEARCH_MENU with an unlink flag instead. They are really the same button type, one just happens to have the option to unlink. --- source/blender/editors/include/UI_interface.h | 2 +- source/blender/editors/interface/interface.c | 13 ++++--- .../blender/editors/interface/interface_handlers.c | 41 +++++++++++++--------- .../blender/editors/interface/interface_layout.c | 5 ++- .../blender/editors/interface/interface_regions.c | 6 ++-- .../blender/editors/interface/interface_widgets.c | 7 ++-- 6 files changed, 41 insertions(+), 33 deletions(-) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 4542627277a..02ae098dc2e 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -185,6 +185,7 @@ enum { UI_BUT_HAS_SEP_CHAR = (1 << 27), /* but->str contains UI_SEP_CHAR, used for key shortcuts */ UI_BUT_TIP_FORCE = (1 << 28), /* force show tooltips when holding option/alt if U's USER_TOOLTIPS is off */ UI_BUT_TEXTEDIT_UPDATE = (1 << 29), /* when widget is in textedit mode, update value on each char stroke */ + UI_BUT_SEARCH_UNLINK = (1 << 30), /* show unlink for search button */ }; #define UI_PANEL_WIDTH 340 @@ -279,7 +280,6 @@ typedef enum { UI_BTYPE_WAVEFORM = (49 << 9), UI_BTYPE_VECTORSCOPE = (50 << 9), UI_BTYPE_PROGRESS_BAR = (51 << 9), - UI_BTYPE_SEARCH_MENU_UNLINK = (52 << 9), UI_BTYPE_NODE_SOCKET = (53 << 9), UI_BTYPE_SEPR = (54 << 9), UI_BTYPE_SEPR_LINE = (55 << 9), diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 48a7cf4ecf3..5714a40d508 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1930,7 +1930,7 @@ void ui_but_value_set(uiBut *but, double value) int ui_but_string_get_max_length(uiBut *but) { - if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) + if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) return but->hardmax; else return UI_MAX_DRAW_STR; @@ -2031,7 +2031,7 @@ static float ui_get_but_step_unit(uiBut *but, float step_default) */ void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision) { - if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { PropertyType type; const char *buf = NULL; int buf_len; @@ -2073,7 +2073,7 @@ void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int BLI_strncpy(str, but->poin, maxlen); return; } - else if (ELEM(but->type, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + else if (but->type == UI_BTYPE_SEARCH_MENU) { /* string */ BLI_strncpy(str, but->poin, maxlen); return; @@ -2194,7 +2194,7 @@ static void ui_but_string_free_internal(uiBut *but) bool ui_but_string_set(bContext *C, uiBut *but, const char *str) { - if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { if (RNA_property_editable(&but->rnapoin, but->rnaprop)) { PropertyType type; @@ -2246,7 +2246,7 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) return true; } - else if (ELEM(but->type, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + else if (but->type == UI_BTYPE_SEARCH_MENU) { /* string */ BLI_strncpy(but->poin, str, but->hardmax); return true; @@ -2754,7 +2754,6 @@ void ui_but_update(uiBut *but) case UI_BTYPE_TEXT: case UI_BTYPE_SEARCH_MENU: - case UI_BTYPE_SEARCH_MENU_UNLINK: if (!but->editstr) { char str[UI_MAX_DRAW_STR]; @@ -3139,7 +3138,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_TEXT, UI_BTYPE_LABEL, UI_BTYPE_BLOCK, UI_BTYPE_BUT_MENU, UI_BTYPE_SEARCH_MENU, - UI_BTYPE_PROGRESS_BAR, UI_BTYPE_SEARCH_MENU_UNLINK)) + UI_BTYPE_PROGRESS_BAR)) { but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT); } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 68a69c4cd4e..dc8018cd11e 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -413,7 +413,7 @@ bool ui_but_is_editable_as_text(const uiBut *but) { return ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, - UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK); + UI_BTYPE_SEARCH_MENU); } @@ -1629,7 +1629,6 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton ui_apply_but_BUT(C, but, data); break; case UI_BTYPE_TEXT: - case UI_BTYPE_SEARCH_MENU_UNLINK: case UI_BTYPE_SEARCH_MENU: ui_apply_but_TEX(C, but, data); break; @@ -1732,13 +1731,13 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB for (wmd = drags->first; wmd; wmd = wmd->next) { if (wmd->type == WM_DRAG_ID) { /* align these types with UI_but_active_drop_name */ - if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { ID *id = (ID *)wmd->poin; button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); BLI_strncpy(data->str, id->name + 2, data->maxlen); - if (ELEM(but->type, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (ELEM(but->type, UI_BTYPE_SEARCH_MENU)) { but->changed = true; ui_searchbox_update(C, data->searchbox, but, true); } @@ -1879,7 +1878,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, } /* text/string and ID data */ - else if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + else if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { uiHandleButtonData *active_data = but->active; if (but->poin == NULL && but->rnapoin.data == NULL) { @@ -1899,7 +1898,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, else BLI_strncpy(active_data->str, buf_paste, active_data->maxlen); - if (ELEM(but->type, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (but->type == UI_BTYPE_SEARCH_MENU) { /* else uiSearchboxData.active member is not updated [#26856] */ but->changed = true; ui_searchbox_update(C, data->searchbox, but, true); @@ -2092,7 +2091,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con BLI_strncpy(origstr, but->editstr, data->maxlen); - if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { if (but->flag & UI_HAS_ICON) { startx += UI_DPI_ICON_SIZE / aspect; } @@ -2539,7 +2538,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) but->selend = len; /* optional searchbox */ - if (ELEM(but->type, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (but->type == UI_BTYPE_SEARCH_MENU) { data->searchbox = ui_searchbox_create(C, data->region, but); ui_searchbox_update(C, data->searchbox, but, true); /* true = reset */ } @@ -6331,7 +6330,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * WM_operator_name_call(C, "UI_OT_eyedropper_color", WM_OP_INVOKE_DEFAULT, NULL); return WM_UI_HANDLER_BREAK; } - else if (but->type == UI_BTYPE_SEARCH_MENU_UNLINK) { + else if ((but->type == UI_BTYPE_SEARCH_MENU) && + (but->flag & UI_BUT_SEARCH_UNLINK)) + { if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_POINTER) { StructRNA *type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop); const short idcode = RNA_type_to_ID_code(type); @@ -6488,11 +6489,16 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * break; case UI_BTYPE_TEXT: case UI_BTYPE_SEARCH_MENU: + if ((but->type == UI_BTYPE_SEARCH_MENU) && + (but->flag & UI_BUT_SEARCH_UNLINK)) + { + retval = ui_do_but_SEARCH_UNLINK(C, block, but, data, event); + if (retval & WM_UI_HANDLER_BREAK) { + break; + } + } retval = ui_do_but_TEX(C, block, but, data, event); break; - case UI_BTYPE_SEARCH_MENU_UNLINK: - retval = ui_do_but_SEARCH_UNLINK(C, block, but, data, event); - break; case UI_BTYPE_MENU: case UI_BTYPE_BLOCK: case UI_BTYPE_PULLDOWN: @@ -6731,7 +6737,7 @@ bool UI_but_active_drop_name(bContext *C) uiBut *but = ui_but_find_active_in_region(ar); if (but) { - if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) + if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) return 1; } @@ -6848,9 +6854,10 @@ static bool ui_but_is_interactive(const uiBut *but, const bool labeledit) bool ui_but_is_search_unlink_visible(const uiBut *but) { - BLI_assert(but->type == UI_BTYPE_SEARCH_MENU_UNLINK); + BLI_assert(but->type == UI_BTYPE_SEARCH_MENU); return ((but->editstr == NULL) && - (but->drawstr[0] != '\0')); + (but->drawstr[0] != '\0') && + (but->flag & UI_BUT_SEARCH_UNLINK)); } /* x and y are only used in case event is NULL... */ @@ -7131,7 +7138,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA copy_v2_fl(data->ungrab_mval, FLT_MAX); #endif - if (ELEM(but->type, UI_BTYPE_CURVE, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (ELEM(but->type, UI_BTYPE_CURVE, UI_BTYPE_SEARCH_MENU)) { /* XXX curve is temp */ } else { @@ -9106,7 +9113,7 @@ static int ui_handle_menus_recursive( /* now handle events for our own menu */ if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) { - const bool do_but_search = (but && ELEM(but->type, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)); + const bool do_but_search = (but && (but->type == UI_BTYPE_SEARCH_MENU)); if (submenu && submenu->menuretval) { const bool do_ret_out_parent = (submenu->menuretval & UI_RETURN_OUT_PARENT) != 0; retval = ui_handle_menu_return_submenu(C, event, menu); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 44c1ed474d5..eeda7a2c390 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -1573,11 +1573,14 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN /* turn button into search button */ if (searchprop) { - but->type = RNA_property_is_unlink(prop) ? UI_BTYPE_SEARCH_MENU_UNLINK : UI_BTYPE_SEARCH_MENU; + but->type = UI_BTYPE_SEARCH_MENU; but->hardmax = MAX2(but->hardmax, 256.0f); but->rnasearchpoin = *searchptr; but->rnasearchprop = searchprop; but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT; + if (RNA_property_is_unlink(prop)) { + but->flag |= UI_BUT_SEARCH_UNLINK; + } if (RNA_property_type(prop) == PROP_ENUM) { /* XXX, this will have a menu string, diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 8d7330c4dd7..7cb9dca78bf 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -394,7 +394,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) data->totline++; } - if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { /* better not show the value of a password */ if ((but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD)) == 0) { /* full string */ @@ -815,7 +815,7 @@ static void ui_searchbox_select(bContext *C, ARegion *ar, uiBut *but, int step) } else { /* only let users step into an 'unset' state for unlink buttons */ - data->active = (but->type == UI_BTYPE_SEARCH_MENU_UNLINK) ? -1 : 0; + data->active = (but->flag & UI_BUT_SEARCH_UNLINK) ? -1 : 0; } } @@ -886,7 +886,7 @@ bool ui_searchbox_apply(uiBut *but, ARegion *ar) return true; } - else if (but->type == UI_BTYPE_SEARCH_MENU_UNLINK) { + else if (but->flag & UI_BUT_SEARCH_UNLINK) { /* It is valid for _UNLINK flavor to have no active element (it's a valid way to unlink). */ but->editstr[0] = '\0'; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 0b3684ff755..d95e9035207 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -873,7 +873,7 @@ static void widget_draw_icon(const uiBut *but, BIFIconID icon, float alpha, cons if (but->drawflag & UI_BUT_ICON_LEFT) { if (but->block->flag & UI_BLOCK_LOOP) { - if (ELEM(but->type, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) + if (but->type == UI_BTYPE_SEARCH_MENU) xs = rect->xmin + 4.0f * ofs; else xs = rect->xmin + ofs; @@ -1542,7 +1542,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB } /* unlink icon for this button type */ - if ((but->type == UI_BTYPE_SEARCH_MENU_UNLINK) && ui_but_is_search_unlink_visible(but)) { + if ((but->type == UI_BTYPE_SEARCH_MENU) && ui_but_is_search_unlink_visible(but)) { rcti temp = *rect; temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f); @@ -3651,8 +3651,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct case UI_BTYPE_TEXT: wt = widget_type(UI_WTYPE_NAME); break; - - case UI_BTYPE_SEARCH_MENU_UNLINK: + case UI_BTYPE_SEARCH_MENU: wt = widget_type(UI_WTYPE_NAME); if (but->block->flag & UI_BLOCK_LOOP) -- cgit v1.2.3 From 4560570f8ac91b7ce349c8c1079caaf1f21848bf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Mar 2015 17:02:34 +1100 Subject: Fix for building blender as a Python module Installation didn't work on debian distro's now install into PYTHON_SITE_PACKAGES (which is detected and can be configured). --- CMakeLists.txt | 4 +- build_files/cmake/Modules/FindPythonLibsUnix.cmake | 11 +++++ source/creator/CMakeLists.txt | 56 ++++++++++------------ 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 21efa668292..100d00b2032 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -201,7 +201,7 @@ set(WITH_PYTHON_SECURITY ON CACHE BOOL "ON" FORCE) # temp force on. option(WITH_PYTHON_SAFETY "Enable internal API error checking to track invalid data to prevent crash on access (at the expense of some effeciency, only enable for development)." OFF) mark_as_advanced(WITH_PYTHON_SAFETY) -option(WITH_PYTHON_MODULE "Enable building as a python module which runs without a user interface, like running regular blender in background mode (experimental, only enable for development)" OFF) +option(WITH_PYTHON_MODULE "Enable building as a python module which runs without a user interface, like running regular blender in background mode (experimental, only enable for development), installs to PYTHON_SITE_PACKAGES" OFF) if(APPLE) option(WITH_PYTHON_FRAMEWORK "Enable building using the Python available in the framework (OSX only)" OFF) endif() @@ -617,6 +617,8 @@ endif() # may as well build python module without a UI if(WITH_PYTHON_MODULE) set(WITH_HEADLESS ON) + # building as a Python module wont use /usr/shared + set(WITH_INSTALL_PORTABLE ON) endif() if(NOT WITH_PYTHON) diff --git a/build_files/cmake/Modules/FindPythonLibsUnix.cmake b/build_files/cmake/Modules/FindPythonLibsUnix.cmake index 1fb27e7898c..555ca4cf0a0 100644 --- a/build_files/cmake/Modules/FindPythonLibsUnix.cmake +++ b/build_files/cmake/Modules/FindPythonLibsUnix.cmake @@ -14,6 +14,7 @@ # PYTHON_INCLUDE_CONFIG_DIRS # PYTHON_LIBRARIES # PYTHON_LIBPATH, Used for installation +# PYTHON_SITE_PACKAGES, Used for installation (as a Python module) # PYTHON_LINKFLAGS # PYTHON_ROOT_DIR, The base directory to search for Python. # This can also be an environment variable. @@ -187,6 +188,15 @@ IF(PYTHONLIBSUNIX_FOUND) SET(PYTHON_INCLUDE_DIRS ${PYTHON_INCLUDE_DIR} ${PYTHON_INCLUDE_CONFIG_DIR}) SET(PYTHON_LIBRARIES ${PYTHON_LIBRARY}) + FIND_FILE(PYTHON_SITE_PACKAGES + NAMES + # debian specific + dist-packages + site-packages + HINTS + ${PYTHON_LIBPATH}/python${PYTHON_VERSION} + ) + # we need this for installation # XXX No more valid with debian-like py3.4 packages... # GET_FILENAME_COMPONENT(PYTHON_LIBPATH ${PYTHON_LIBRARY} PATH) @@ -200,4 +210,5 @@ MARK_AS_ADVANCED( PYTHON_INCLUDE_CONFIG_DIR PYTHON_LIBRARY PYTHON_LIBPATH + PYTHON_SITE_PACKAGES ) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 1557cc08182..b9044e64ddd 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -261,11 +261,11 @@ endif() # Platform Specific Var: TARGETDIR_VER if(UNIX AND NOT APPLE) - if(WITH_INSTALL_PORTABLE) - set(TARGETDIR_VER ${BLENDER_VERSION}) + if(WITH_PYTHON_MODULE) + set(TARGETDIR_VER ${PYTHON_SITE_PACKAGES}/${BLENDER_VERSION}) else() - if(WITH_PYTHON_MODULE) - set(TARGETDIR_VER ${PYTHON_LIBPATH}/python${PYTHON_VERSION}/site-packages/${BLENDER_VERSION}) + if(WITH_INSTALL_PORTABLE) + set(TARGETDIR_VER ${BLENDER_VERSION}) else() set(TARGETDIR_VER share/blender/${BLENDER_VERSION}) endif() @@ -407,22 +407,24 @@ if(UNIX AND NOT APPLE) endif() # there are a few differences between portable and system install - if(WITH_INSTALL_PORTABLE) - if(WITH_PYTHON_MODULE) - # pass - else() - if(WITH_DOC_MANPAGE) - install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/blender.1 - DESTINATION "." - ) - endif() - endif() + if(WITH_PYTHON_MODULE) + install( + TARGETS blender + LIBRARY DESTINATION ${PYTHON_SITE_PACKAGES} + ) + # none of the other files are needed currently + elseif(WITH_INSTALL_PORTABLE) install( TARGETS blender DESTINATION "." ) + if(WITH_DOC_MANPAGE) + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/blender.1 + DESTINATION "." + ) + endif() install( FILES ${CMAKE_SOURCE_DIR}/release/freedesktop/blender.desktop @@ -437,26 +439,18 @@ if(UNIX AND NOT APPLE) ) set(BLENDER_TEXT_FILES_DESTINATION ".") - else() # main blender binary - if(WITH_PYTHON_MODULE) - install( - TARGETS blender - LIBRARY DESTINATION ${PYTHON_LIBPATH}/python${PYTHON_VERSION}/site-packages - ) - else() + install( + TARGETS blender + DESTINATION bin + ) + if(WITH_DOC_MANPAGE) + # manpage only with 'blender' binary install( - TARGETS blender - DESTINATION bin + FILES ${CMAKE_CURRENT_BINARY_DIR}/blender.1 + DESTINATION share/man/man1 ) - if(WITH_DOC_MANPAGE) - # manpage only with 'blender' binary - install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/blender.1 - DESTINATION share/man/man1 - ) - endif() endif() # misc files -- cgit v1.2.3 From 3030e2d1cb1aaec554a409e44170b890d073c661 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Mar 2015 19:09:51 +1100 Subject: CMake: tweak recent py module changes support installing portable builds to CMAKE_INSTALL_PREFIX --- CMakeLists.txt | 4 +--- source/creator/CMakeLists.txt | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 100d00b2032..2ce183e220f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -201,7 +201,7 @@ set(WITH_PYTHON_SECURITY ON CACHE BOOL "ON" FORCE) # temp force on. option(WITH_PYTHON_SAFETY "Enable internal API error checking to track invalid data to prevent crash on access (at the expense of some effeciency, only enable for development)." OFF) mark_as_advanced(WITH_PYTHON_SAFETY) -option(WITH_PYTHON_MODULE "Enable building as a python module which runs without a user interface, like running regular blender in background mode (experimental, only enable for development), installs to PYTHON_SITE_PACKAGES" OFF) +option(WITH_PYTHON_MODULE "Enable building as a python module which runs without a user interface, like running regular blender in background mode (experimental, only enable for development), installs to PYTHON_SITE_PACKAGES (or CMAKE_INSTALL_PREFIX if WITH_INSTALL_PORTABLE is enabled)." OFF) if(APPLE) option(WITH_PYTHON_FRAMEWORK "Enable building using the Python available in the framework (OSX only)" OFF) endif() @@ -617,8 +617,6 @@ endif() # may as well build python module without a UI if(WITH_PYTHON_MODULE) set(WITH_HEADLESS ON) - # building as a Python module wont use /usr/shared - set(WITH_INSTALL_PORTABLE ON) endif() if(NOT WITH_PYTHON) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index b9044e64ddd..193737e9822 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -262,7 +262,11 @@ endif() if(UNIX AND NOT APPLE) if(WITH_PYTHON_MODULE) - set(TARGETDIR_VER ${PYTHON_SITE_PACKAGES}/${BLENDER_VERSION}) + if(WITH_INSTALL_PORTABLE) + set(TARGETDIR_VER ${BLENDER_VERSION}) + else() + set(TARGETDIR_VER ${PYTHON_SITE_PACKAGES}/${BLENDER_VERSION}) + endif() else() if(WITH_INSTALL_PORTABLE) set(TARGETDIR_VER ${BLENDER_VERSION}) @@ -408,10 +412,17 @@ if(UNIX AND NOT APPLE) # there are a few differences between portable and system install if(WITH_PYTHON_MODULE) - install( - TARGETS blender - LIBRARY DESTINATION ${PYTHON_SITE_PACKAGES} - ) + if(WITH_INSTALL_PORTABLE) + install( + TARGETS blender + DESTINATION "." + ) + else() + install( + TARGETS blender + LIBRARY DESTINATION ${PYTHON_SITE_PACKAGES} + ) + endif() # none of the other files are needed currently elseif(WITH_INSTALL_PORTABLE) install( -- cgit v1.2.3 From cf365275c21e24f7653c3843b0d3f2a169101f2a Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 24 Mar 2015 09:57:11 +0100 Subject: Fix T44089: All addons do not use same default for orientations. Transformed 'OrientationHelper' class into 'orientation_helper_factory' function, which returns an OrientationHelper customized class with specified default axes. --- release/scripts/modules/bpy_extras/io_utils.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py index 81de0d7c6f0..1dc6f5b2b2c 100644 --- a/release/scripts/modules/bpy_extras/io_utils.py +++ b/release/scripts/modules/bpy_extras/io_utils.py @@ -21,7 +21,7 @@ __all__ = ( "ExportHelper", "ImportHelper", - "OrientationHelper", + "orientation_helper_factory", "axis_conversion", "axis_conversion_ensure", "create_derived_objects", @@ -117,13 +117,14 @@ class ImportHelper: return _check_axis_conversion(self) -class OrientationHelper: +def orientation_helper_factory(name, axis_forward='Y', axis_up='Z'): + members = {} def _update_axis_forward(self, context): if self.axis_forward[-1] == self.axis_up[-1]: self.axis_up = self.axis_up[0:-1] + 'XYZ'[('XYZ'.index(self.axis_up[-1]) + 1) % 3] - axis_forward = EnumProperty( + members['axis_forward'] = EnumProperty( name="Forward", items=(('X', "X Forward", ""), ('Y', "Y Forward", ""), @@ -132,7 +133,7 @@ class OrientationHelper: ('-Y', "-Y Forward", ""), ('-Z', "-Z Forward", ""), ), - default='-Z', + default=axis_forward, update=_update_axis_forward, ) @@ -140,7 +141,7 @@ class OrientationHelper: if self.axis_up[-1] == self.axis_forward[-1]: self.axis_forward = self.axis_forward[0:-1] + 'XYZ'[('XYZ'.index(self.axis_forward[-1]) + 1) % 3] - axis_up = EnumProperty( + members['axis_up'] = EnumProperty( name="Up", items=(('X', "X Up", ""), ('Y', "Y Up", ""), @@ -149,10 +150,12 @@ class OrientationHelper: ('-Y', "-Y Up", ""), ('-Z', "-Z Up", ""), ), - default='Y', + default=axis_up, update=_update_axis_up, ) + return type(name, (object,), members) + # Axis conversion function, not pretty LUT # use lookup table to convert between any axis -- cgit v1.2.3 From 0f0e080a267c5c4fc7bd18566be28dd01ffb9499 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 24 Mar 2015 14:03:14 +0500 Subject: Fix T44110: Plane track doesn't work when built with scons For some reason recent change in avoiding non-aligned eigen vectors was behaving differently for cmake and scons. Made it a bit different now by storing scalars. This is more robust approach anyway, because it's not really guaranteed Mat.col() gives a pointer inside data, depending on column-major vs. row-major storage. This is to be backported to 2.74 branch. --- extern/libmv/libmv/multiview/homography.cc | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/extern/libmv/libmv/multiview/homography.cc b/extern/libmv/libmv/multiview/homography.cc index a7679c33bbf..346acb3afd9 100644 --- a/extern/libmv/libmv/multiview/homography.cc +++ b/extern/libmv/libmv/multiview/homography.cc @@ -179,8 +179,12 @@ void GetNormalizedPoints(const Mat &original_points, class HomographySymmetricGeometricCostFunctor { public: HomographySymmetricGeometricCostFunctor(const Vec2 &x, - const Vec2 &y) - : x_(x), y_(y) { } + const Vec2 &y) { + xx_ = x(0); + xy_ = x(1); + yx_ = y(0); + yy_ = y(1); + } template bool operator()(const T *homography_parameters, T *residuals) const { @@ -189,8 +193,8 @@ class HomographySymmetricGeometricCostFunctor { Mat3 H(homography_parameters); - Vec3 x(T(x_(0)), T(x_(1)), T(1.0)); - Vec3 y(T(y_(0)), T(y_(1)), T(1.0)); + Vec3 x(T(xx_), T(xy_), T(1.0)); + Vec3 y(T(yx_), T(yy_), T(1.0)); Vec3 H_x = H * x; Vec3 Hinv_y = H.inverse() * y; @@ -199,18 +203,19 @@ class HomographySymmetricGeometricCostFunctor { Hinv_y /= Hinv_y(2); // This is a forward error. - residuals[0] = H_x(0) - T(y_(0)); - residuals[1] = H_x(1) - T(y_(1)); + residuals[0] = H_x(0) - T(yx_); + residuals[1] = H_x(1) - T(yy_); // This is a backward error. - residuals[2] = Hinv_y(0) - T(x_(0)); - residuals[3] = Hinv_y(1) - T(x_(1)); + residuals[2] = Hinv_y(0) - T(xx_); + residuals[3] = Hinv_y(1) - T(xy_); return true; } - const Vec2 &x_; - const Vec2 &y_; + // TODO(sergey): Think of better naming. + double xx_, xy_; + double yx_, yy_; }; // Termination checking callback used for homography estimation. -- cgit v1.2.3 From 4685092fd8e40d523ccd6d4d2b7efe491823f07f Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 24 Mar 2015 10:58:57 +0100 Subject: Fix T44102: Mirrored objects render black with Blender Internal and Autosmooth. Normals are not vertices, we cannot apply matrix's scale to them... --- source/blender/render/intern/source/convertblender.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 2ebcb76e3d1..e900d29aa19 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -577,6 +577,17 @@ static void autosmooth(Render *UNUSED(re), ObjectRen *obr, float mat[4][4], shor VlakRen *vlr; int a, totvert; + float rot[3][3]; + + /* Note: For normals, we only want rotation, not scaling component. + * Negative scales (aka mirroring) give wrong results, see T44102. */ + if (lnors) { + float mat3[3][3], size[3]; + + copy_m3_m4(mat3, mat); + mat3_to_rot_size(rot, size, mat3); + } + if (obr->totvert == 0) return; @@ -611,9 +622,8 @@ static void autosmooth(Render *UNUSED(re), ObjectRen *obr, float mat[4][4], shor ver = RE_findOrAddVert(obr, a); mul_m4_v3(mat, ver->co); if (lnors) { - mul_mat3_m4_v3(mat, ver->n); + mul_m3_v3(rot, ver->n); negate_v3(ver->n); - normalize_v3(ver->n); } } for (a = 0; a < obr->totvlak; a++) { -- cgit v1.2.3 From 765fd7044b2bb65d844c2c705d30c858d9930da1 Mon Sep 17 00:00:00 2001 From: Ines Almeida Date: Tue, 24 Mar 2015 10:17:22 +0000 Subject: Updating python API documentation for function bge.render.makeScreenshot --- doc/python_api/rst/bge.render.rst | 80 ++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/doc/python_api/rst/bge.render.rst b/doc/python_api/rst/bge.render.rst index d185a5d05aa..651693b7a8a 100644 --- a/doc/python_api/rst/bge.render.rst +++ b/doc/python_api/rst/bge.render.rst @@ -66,7 +66,7 @@ Constants .. data:: KX_BLENDER_GLSL_MATERIAL Materials approximating blender materials with GLSL. - + .. DATA:: VSYNC_OFF Disables vsync @@ -95,47 +95,49 @@ Functions .. function:: getWindowWidth() Gets the width of the window (in pixels) - + :rtype: integer .. function:: getWindowHeight() Gets the height of the window (in pixels) - + :rtype: integer .. function:: setWindowSize(width, height) Set the width and height of the window (in pixels). This also works for fullscreen applications. - + :type width: integer :type height: integer .. function:: setFullScreen(enable) Set whether or not the window should be fullscreen. - + :type enable: bool .. function:: getFullScreen() Returns whether or not the window is fullscreen. - + :rtype: bool .. function:: makeScreenshot(filename) - Writes a screenshot to the given filename. - - If filename starts with // the image will be saved relative to the current directory. - If the filename contains # it will be replaced with the frame number. - - The standalone player saves .png files. It does not support color space conversion - or gamma correction. - - When run from Blender, makeScreenshot supports all Blender image file formats like PNG, TGA, Jpeg and OpenEXR. - Gamma, Colorspace conversion and Jpeg compression are taken from the Render settings panels. - + Writes an image file with the current displayed frame. + + The image is written to *'filename'*. The path may be absolute (eg. "/home/foo/image") or relative when started with + "//" (eg. "//image"). Note that absolute paths are not portable between platforms. + If the filename contains a "#", it will be replaced by an incremental index so that screenshots can be taken multiple + times without overwriting the previous ones (eg. "image-#"). + + Settings for the image are taken from the render settings (file format and respective settings, gamma and colospace + conversion, etc). The image resolution matches the framebuffer, meaning, the window size and aspect ratio. + When running from the standalone player, instead of the embedded player, only PNG files are supported. Additional + color conversions are also not supported. + + :arg filename: path and name of the file to write :type filename: string @@ -147,14 +149,14 @@ Functions .. function:: showMouse(visible) Enables or disables the operating system mouse cursor. - + :type visible: boolean .. function:: setMousePosition(x, y) Sets the mouse cursor position. - + :type x: integer :type y: integer @@ -169,7 +171,7 @@ Functions .. function:: setEyeSeparation(eyesep) Sets the eye separation for stereo mode. Usually Focal Length/30 provides a confortable value. - + :arg eyesep: The distance between the left and right eye. :type eyesep: float @@ -177,21 +179,21 @@ Functions .. function:: getEyeSeparation() Gets the current eye separation for stereo mode. - + :rtype: float - + .. function:: setFocalLength(focallength) Sets the focal length for stereo mode. It uses the current camera focal length as initial value. - - :arg focallength: The focal length. + + :arg focallength: The focal length. :type focallength: float .. function:: getFocalLength() Gets the current focal length for stereo mode. - + :rtype: float .. function:: getStereoEye() @@ -206,7 +208,7 @@ Functions .. function:: setMaterialMode(mode) Set the material mode to use for OpenGL rendering. - + :type mode: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL .. note:: Changes will only affect newly created scenes. @@ -215,14 +217,14 @@ Functions .. function:: getMaterialMode(mode) Get the material mode to use for OpenGL rendering. - + :rtype: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL .. function:: setGLSLMaterialSetting(setting, enable) Enables or disables a GLSL material setting. - + :type setting: string (lights, shaders, shadows, ramps, nodes, extra_textures) :type enable: boolean @@ -230,43 +232,43 @@ Functions .. function:: getGLSLMaterialSetting(setting, enable) Get the state of a GLSL material setting. - + :type setting: string (lights, shaders, shadows, ramps, nodes, extra_textures) :rtype: boolean .. function:: setAnisotropicFiltering(level) Set the anisotropic filtering level for textures. - + :arg level: The new anisotropic filtering level to use :type level: integer (must be one of 1, 2, 4, 8, 16) - + .. note:: Changing this value can cause all textures to be recreated, which can be slow. - + .. function:: getAnisotropicFiltering() Get the anisotropic filtering level used for textures. - + :rtype: integer (one of 1, 2, 4, 8, 16) .. function:: setMipmapping(value) Change how to use mipmapping. - + :type value: RAS_MIPMAP_NONE, RAS_MIPMAP_NEAREST, RAS_MIPMAP_LINEAR - + .. note:: Changing this value can cause all textures to be recreated, which can be slow. .. function:: getMipmapping() Get the current mipmapping setting. - + :rtype: RAS_MIPMAP_NONE, RAS_MIPMAP_NEAREST, RAS_MIPMAP_LINEAR - + .. function:: drawLine(fromVec,toVec,color) Draw a line in the 3D scene. - + :arg fromVec: the origin of the line :type fromVec: list [x, y, z] :arg toVec: the end of the line @@ -278,7 +280,7 @@ Functions .. function:: enableMotionBlur(factor) Enable the motion blur effect. - + :arg factor: the ammount of motion blur to display. :type factor: float [0.0 - 1.0] -- cgit v1.2.3 From 7293f6d4863a2f80fa38697f4e55ccdc0aec9e6b Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 24 Mar 2015 12:24:30 +0100 Subject: Cleanup - move proxy storage options to the proxy itself - also will enable more storage options, since seq->flag is running out of space --- release/scripts/startup/bl_ui/space_sequencer.py | 31 +++++++++++++---------- source/blender/blenkernel/intern/sequencer.c | 27 ++++++++++---------- source/blender/blenloader/intern/versioning_250.c | 6 ++++- source/blender/blenloader/intern/versioning_270.c | 26 +++++++++++++++++++ source/blender/makesdna/DNA_sequence_types.h | 13 +++++++--- source/blender/makesrna/intern/rna_sequencer.c | 19 +++++++------- 6 files changed, 81 insertions(+), 41 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 0be1bf0b90a..4f83cc03b10 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -915,42 +915,45 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel): strip = act_strip(context) - flow = layout.column_flow() - flow.prop(strip, "use_proxy_custom_directory") - flow.prop(strip, "use_proxy_custom_file") if strip.proxy: - if strip.use_proxy_custom_directory and not strip.use_proxy_custom_file: - flow.prop(strip.proxy, "directory") - if strip.use_proxy_custom_file: - flow.prop(strip.proxy, "filepath") + proxy = strip.proxy + + flow = layout.column_flow() + flow.prop(proxy, "use_proxy_custom_directory") + flow.prop(proxy, "use_proxy_custom_file") + + if proxy.use_proxy_custom_directory and not proxy.use_proxy_custom_file: + flow.prop(proxy, "directory") + if proxy.use_proxy_custom_file: + flow.prop(proxy, "filepath") layout.label("Enabled Proxies:") enabled = "" row = layout.row() - if (strip.proxy.build_25): + if (proxy.build_25): enabled += "25% " - if (strip.proxy.build_50): + if (proxy.build_50): enabled += "50% " - if (strip.proxy.build_75): + if (proxy.build_75): enabled += "75% " - if (strip.proxy.build_100): + if (proxy.build_100): enabled += "100% " row.label(enabled) - if (strip.proxy.use_overwrite): + if (proxy.use_overwrite): layout.label("Overwrite On") else: layout.label("Overwrite Off") col = layout.column() col.label(text="Build JPEG quality") - col.prop(strip.proxy, "quality") + col.prop(proxy, "quality") if strip.type == 'MOVIE': col = layout.column() col.label(text="Use timecode index:") - col.prop(strip.proxy, "timecode") + col.prop(proxy, "timecode") col = layout.column() col.operator("sequencer.enable_proxies") diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index c45db303467..19120d4da93 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1362,7 +1362,7 @@ static void seq_open_anim_file(Sequence *seq, bool openfile) return; } - if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) { + if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) { char dir[FILE_MAX]; BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); BLI_path_abs(dir, G.main->name); @@ -1377,7 +1377,8 @@ static bool seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char * int frameno; char dir[PROXY_MAXFILE]; - if (!seq->strip->proxy) { + StripProxy *proxy = seq->strip->proxy; + if (!proxy) { return false; } @@ -1389,7 +1390,7 @@ static bool seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char * * have both, a directory full of jpeg files and proxy avis, so * sorry folks, please rebuild your proxies... */ - if (seq->flag & (SEQ_USE_PROXY_CUSTOM_DIR | SEQ_USE_PROXY_CUSTOM_FILE)) { + if (proxy->storage & (SEQ_STORAGE_PROXY_CUSTOM_DIR | SEQ_STORAGE_PROXY_CUSTOM_FILE)) { BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); } else if (seq->type == SEQ_TYPE_IMAGE) { @@ -1399,7 +1400,7 @@ static bool seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char * return false; } - if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { + if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) { BLI_join_dirfile(name, PROXY_MAXFILE, dir, seq->strip->proxy->file); BLI_path_abs(name, G.main->name); @@ -1433,6 +1434,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c IMB_Proxy_Size psize = seq_rendersize_to_proxysize(context->preview_render_size); int size_flags; int render_size = context->preview_render_size; + StripProxy *proxy = seq->strip->proxy; /* dirty hack to distinguish 100% render size from PROXY_100 */ if (render_size == 99) { @@ -1443,32 +1445,31 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c return NULL; } - size_flags = seq->strip->proxy->build_size_flags; + size_flags = proxy->build_size_flags; /* only use proxies, if they are enabled (even if present!) */ if (psize == IMB_PROXY_NONE || ((size_flags & psize) != psize)) { return NULL; } - if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { + if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) { int frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs; - if (seq->strip->proxy->anim == NULL) { + if (proxy->anim == NULL) { if (seq_proxy_get_fname(seq, cfra, render_size, name) == 0) { return NULL; } - seq->strip->proxy->anim = openanim(name, IB_rect, 0, - seq->strip->colorspace_settings.name); + proxy->anim = openanim(name, IB_rect, 0, seq->strip->colorspace_settings.name); } - if (seq->strip->proxy->anim == NULL) { + if (proxy->anim == NULL) { return NULL; } seq_open_anim_file(seq, true); - frameno = IMB_anim_index_get_frame_index(seq->anim, seq->strip->proxy->tc, frameno); + frameno = IMB_anim_index_get_frame_index(seq->anim, proxy->tc, frameno); - return IMB_anim_absolute(seq->strip->proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE); + return IMB_anim_absolute(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE); } if (seq_proxy_get_fname(seq, cfra, render_size, name) == 0) { @@ -1600,7 +1601,7 @@ void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, sho } /* that's why it is called custom... */ - if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { + if (seq->strip->proxy && seq->strip->proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) { return; } diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 4125451ead9..7c148f1a2e9 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -797,13 +797,17 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main) BLI_path_abs(str, main->name); seq->sound = sound_new_file(main, str); } +#define SEQ_USE_PROXY_CUSTOM_DIR (1 << 19) +#define SEQ_USE_PROXY_CUSTOM_FILE (1 << 21) /* don't know, if anybody used that this way, but just in case, upgrade to new way... */ if ((seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) && !(seq->flag & SEQ_USE_PROXY_CUSTOM_DIR)) { BLI_snprintf(seq->strip->proxy->dir, FILE_MAXDIR, "%s/BL_proxy", seq->strip->dir); } - } +#undef SEQ_USE_PROXY_CUSTOM_DIR +#undef SEQ_USE_PROXY_CUSTOM_FILE + } SEQ_END } } diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 9c8db6d6a9b..30070450bde 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -39,6 +39,7 @@ #include "DNA_cloth_types.h" #include "DNA_constraint_types.h" #include "DNA_sdna_types.h" +#include "DNA_sequence_types.h" #include "DNA_space_types.h" #include "DNA_screen_types.h" #include "DNA_object_types.h" @@ -53,6 +54,7 @@ #include "BKE_main.h" #include "BKE_modifier.h" #include "BKE_node.h" +#include "BKE_sequencer.h" #include "BKE_screen.h" #include "BLI_math.h" @@ -700,4 +702,28 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } FOREACH_NODETREE_END } + + if (!DNA_struct_elem_find(fd->filesdna, "Sequence", "char", "storage")) { + Scene *scene; + Sequence *seq; + +#define SEQ_USE_PROXY_CUSTOM_DIR (1 << 19) +#define SEQ_USE_PROXY_CUSTOM_FILE (1 << 21) + + for (scene = main->scene.first; scene; scene = scene->id.next) { + SEQ_BEGIN (scene->ed, seq) { + if (seq->strip && seq->strip->proxy) { + if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) + seq->strip->proxy->storage = SEQ_STORAGE_PROXY_CUSTOM_DIR; + if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) + seq->strip->proxy->storage = SEQ_STORAGE_PROXY_CUSTOM_FILE; + } + } + SEQ_END + + printf("lala\n"); + } +#undef SEQ_USE_PROXY_CUSTOM_DIR +#undef SEQ_USE_PROXY_CUSTOM_FILE + } } diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index c6748cca8e1..34fceaef4c0 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -95,7 +95,8 @@ typedef struct StripProxy { short build_tc_flags; // time code flags (see below) of all tc indices // to build short build_flags; - char pad[6]; + char storage; + char pad[5]; } StripProxy; typedef struct Strip { @@ -354,9 +355,9 @@ enum { SEQ_USE_TRANSFORM = (1 << 16), SEQ_USE_CROP = (1 << 17), /* SEQ_USE_COLOR_BALANCE = (1 << 18), */ /* DEPRECATED */ - SEQ_USE_PROXY_CUSTOM_DIR = (1 << 19), + /* SEQ_USE_PROXY_CUSTOM_DIR = (1 << 19), */ /* DEPRECATED */ - SEQ_USE_PROXY_CUSTOM_FILE = (1 << 21), + /* SEQ_USE_PROXY_CUSTOM_FILE = (1 << 21), */ /* DEPRECATED */ SEQ_USE_EFFECT_DEFAULT_FADE = (1 << 22), SEQ_USE_LINEAR_MODIFIERS = (1 << 23), @@ -372,6 +373,12 @@ enum { SEQ_INVALID_EFFECT = (1 << 31), }; +/* StripProxy->storage */ +enum { + SEQ_STORAGE_PROXY_CUSTOM_FILE = (1 << 1), /* store proxy in custom directory */ + SEQ_STORAGE_PROXY_CUSTOM_DIR = (1 << 2) /* store proxy in custom file */ +}; + #if (DNA_DEPRECATED_GCC_POISON == 1) #pragma GCC poison SEQ_MAKE_PREMUL #endif diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 8ad7d313c1e..1844ce03284 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -1222,6 +1222,15 @@ static void rna_def_strip_proxy(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Timecode", ""); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_tcindex_update"); + prop = RNA_def_property(srna, "use_proxy_custom_directory", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "storage", SEQ_STORAGE_PROXY_CUSTOM_DIR); + RNA_def_property_ui_text(prop, "Proxy Custom Directory", "Use a custom directory to store data"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + + prop = RNA_def_property(srna, "use_proxy_custom_file", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "storage", SEQ_STORAGE_PROXY_CUSTOM_FILE); + RNA_def_property_ui_text(prop, "Proxy Custom File", "Use a custom file to read proxy data from"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); } static void rna_def_color_balance(BlenderRNA *brna) @@ -1702,16 +1711,6 @@ static void rna_def_proxy(StructRNA *srna) prop = RNA_def_property(srna, "proxy", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "strip->proxy"); RNA_def_property_ui_text(prop, "Proxy", ""); - - prop = RNA_def_property(srna, "use_proxy_custom_directory", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_PROXY_CUSTOM_DIR); - RNA_def_property_ui_text(prop, "Proxy Custom Directory", "Use a custom directory to store data"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); - - prop = RNA_def_property(srna, "use_proxy_custom_file", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_PROXY_CUSTOM_FILE); - RNA_def_property_ui_text(prop, "Proxy Custom File", "Use a custom file to read proxy data from"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); } static void rna_def_input(StructRNA *srna) -- cgit v1.2.3 From b714b23443b9d9b127e76f82ade1ecc9d9d51396 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 24 Mar 2015 14:15:03 +0100 Subject: Fix T44092: Maya preset doesn't allow attaching Nodes to Frames via D&D --- release/scripts/presets/keyconfig/maya.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py index 47a7a7c5f5d..d81c4965ccd 100644 --- a/release/scripts/presets/keyconfig/maya.py +++ b/release/scripts/presets/keyconfig/maya.py @@ -1499,11 +1499,9 @@ kmi = km.keymap_items.new('node.group_edit', 'TAB', 'PRESS') kmi = km.keymap_items.new('node.read_renderlayers', 'R', 'PRESS', ctrl=True) kmi = km.keymap_items.new('node.read_fullsamplelayers', 'R', 'PRESS', shift=True) kmi = km.keymap_items.new('node.render_changed', 'Z', 'PRESS') -kmi = km.keymap_items.new('transform.translate', 'W', 'PRESS') -kmi = km.keymap_items.new('transform.translate', 'EVT_TWEAK_A', 'ANY') -kmi.properties.release_confirm = True -kmi = km.keymap_items.new('transform.translate', 'EVT_TWEAK_S', 'ANY') -kmi.properties.release_confirm = True +kmi = km.keymap_items.new('node.translate_attach', 'W', 'PRESS') +kmi = km.keymap_items.new('node.translate_attach', 'EVT_TWEAK_A', 'ANY') +kmi = km.keymap_items.new('node.translate_attach', 'EVT_TWEAK_S', 'ANY') kmi = km.keymap_items.new('transform.rotate', 'E', 'PRESS') kmi = km.keymap_items.new('transform.resize', 'R', 'PRESS') kmi = km.keymap_items.new('node.move_detach_links', 'D', 'PRESS', alt=True) -- cgit v1.2.3 From fa09e152afef314e163f502ae1a0f09aaded2e12 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 24 Mar 2015 19:20:33 +0500 Subject: Code cleanup: r_ prefix vs. _r suffix --- source/blender/render/extern/include/RE_engine.h | 2 +- source/blender/render/intern/source/external_engine.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index bc4c4c54f17..a52244ff87f 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -159,7 +159,7 @@ void RE_engines_exit(void); RenderEngineType *RE_engines_find(const char *idname); -rcti* RE_engine_get_current_tiles(struct Render *re, int *total_tiles_r, bool *needs_free_r); +rcti* RE_engine_get_current_tiles(struct Render *re, int *r_total_tiles, bool *r_needs_free); struct RenderData *RE_engine_get_render_data(struct Render *re); void RE_bake_engine_set_engine_parameters(struct Render *re, struct Main *bmain, struct Scene *scene); diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 653f3f0786a..e56466bdf48 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -368,7 +368,7 @@ void RE_engine_set_error_message(RenderEngine *engine, const char *msg) } } -rcti* RE_engine_get_current_tiles(Render *re, int *total_tiles_r, bool *r_needs_free) +rcti* RE_engine_get_current_tiles(Render *re, int *r_total_tiles, bool *r_needs_free) { static rcti tiles_static[BLENDER_MAX_THREADS]; const int allocation_step = BLENDER_MAX_THREADS; @@ -382,7 +382,7 @@ rcti* RE_engine_get_current_tiles(Render *re, int *total_tiles_r, bool *r_needs_ *r_needs_free = false; if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) { - *total_tiles_r = 0; + *r_total_tiles = 0; BLI_rw_mutex_unlock(&re->partsmutex); return NULL; } @@ -415,7 +415,7 @@ rcti* RE_engine_get_current_tiles(Render *re, int *total_tiles_r, bool *r_needs_ } } BLI_rw_mutex_unlock(&re->partsmutex); - *total_tiles_r = total_tiles; + *r_total_tiles = total_tiles; return tiles; } -- cgit v1.2.3 From f98b84072e1dde2d92c44ab4441068358b8bec97 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 24 Mar 2015 15:48:36 +0100 Subject: Remove redundant shortcuts from keyconfigs These have been deleted recently (cd54f07a3c, fbd4dfb2c, 3f68a0aea) --- release/scripts/presets/keyconfig/3dsmax.py | 3 --- release/scripts/presets/keyconfig/maya.py | 2 -- 2 files changed, 5 deletions(-) diff --git a/release/scripts/presets/keyconfig/3dsmax.py b/release/scripts/presets/keyconfig/3dsmax.py index f85d3b43041..7694e338d68 100644 --- a/release/scripts/presets/keyconfig/3dsmax.py +++ b/release/scripts/presets/keyconfig/3dsmax.py @@ -754,8 +754,6 @@ kmi = km.keymap_items.new('anim.channels_move', 'PAGE_DOWN', 'PRESS', shift=True kmi.properties.direction = 'BOTTOM' kmi = km.keymap_items.new('anim.channels_group', 'G', 'PRESS', ctrl=True) kmi = km.keymap_items.new('anim.channels_ungroup', 'G', 'PRESS', alt=True) -kmi = km.keymap_items.new('anim.channels_visibility_set', 'V', 'PRESS') -kmi = km.keymap_items.new('anim.channels_visibility_toggle', 'V', 'PRESS', shift=True) # Map UV Editor km = kc.keymaps.new('UV Editor', space_type='EMPTY', region_type='WINDOW', modal=False) @@ -1055,7 +1053,6 @@ kmi.properties.name = 'NODE_MT_add' kmi = km.keymap_items.new('node.duplicate_move', 'D', 'PRESS', shift=True) kmi = km.keymap_items.new('node.duplicate_move_keep_inputs', 'D', 'PRESS', shift=True, ctrl=True) kmi = km.keymap_items.new('node.parent_set', 'P', 'PRESS', ctrl=True) -kmi = km.keymap_items.new('node.parent_clear', 'P', 'PRESS', alt=True) kmi = km.keymap_items.new('node.join', 'J', 'PRESS', ctrl=True) kmi = km.keymap_items.new('node.hide_toggle', 'H', 'PRESS') kmi = km.keymap_items.new('node.mute_toggle', 'M', 'PRESS') diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py index d81c4965ccd..28799d1cf67 100644 --- a/release/scripts/presets/keyconfig/maya.py +++ b/release/scripts/presets/keyconfig/maya.py @@ -1137,8 +1137,6 @@ kmi = km.keymap_items.new('anim.channels_move', 'PAGE_UP', 'PRESS', shift=True) kmi.properties.direction = 'TOP' kmi = km.keymap_items.new('anim.channels_move', 'PAGE_DOWN', 'PRESS', shift=True) kmi.properties.direction = 'BOTTOM' -kmi = km.keymap_items.new('anim.channels_visibility_set', 'V', 'PRESS') -kmi = km.keymap_items.new('anim.channels_visibility_toggle', 'V', 'PRESS', shift=True) # Map UV Editor km = kc.keymaps.new('UV Editor', space_type='EMPTY', region_type='WINDOW', modal=False) -- cgit v1.2.3 From 2ba82d5729a5f687537c2c26ca6e53750aef201c Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 24 Mar 2015 15:54:02 +0100 Subject: Cleanup: Remove unwanted debug printf from 7293f6d4863a Sergey said this kindof cleanup is good for commit ratio... noted! ;) --- source/blender/blenloader/intern/versioning_270.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 30070450bde..50cd39352a8 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -720,8 +720,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } SEQ_END - - printf("lala\n"); } #undef SEQ_USE_PROXY_CUSTOM_DIR #undef SEQ_USE_PROXY_CUSTOM_FILE -- cgit v1.2.3 From 41ed59e0ebe23d99f3cc394d03ff629417e6115a Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 24 Mar 2015 21:36:26 +0100 Subject: Minor UI message fix. --- source/blender/makesrna/intern/rna_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index c13d2f9b062..73206ea310c 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -2118,7 +2118,7 @@ static void rna_def_object_lodlevel(BlenderRNA *brna) prop = RNA_def_property(srna, "use_object_hysteresis", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", OB_LOD_USE_HYST); - RNA_def_property_ui_text(prop, "Hysteresis Override", "Override LoD Hysteresis scene setting for this Lod Level"); + RNA_def_property_ui_text(prop, "Hysteresis Override", "Override LoD Hysteresis scene setting for this LoD level"); RNA_def_property_update(prop, NC_OBJECT | ND_LOD, NULL); } -- cgit v1.2.3 From 87cff57207ca05602794e5dd1d7f08cd7818fbb6 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 25 Mar 2015 02:30:43 +0500 Subject: Fix T44123: Cycles SSS renders black in recent builds Issue was introduced in 01ee21f where i didn't notice *_setup() function only doing partial initialization, and some of parameters are expected to be initialized by callee function. This was hitting only some setups, so tests with benchmark scenes didn't unleash issues. Now it should all be fine. This is to go to the 2.74 branch and we actually might re-AHOY. --- intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h | 1 - intern/cycles/kernel/closure/bsdf_diffuse.h | 4 ---- intern/cycles/kernel/closure/bsdf_reflection.h | 2 -- intern/cycles/kernel/closure/bsdf_refraction.h | 2 -- intern/cycles/kernel/closure/bsdf_transparent.h | 2 -- intern/cycles/kernel/closure/bssrdf.h | 1 - intern/cycles/kernel/closure/volume.h | 1 - intern/cycles/kernel/kernel_shader.h | 2 ++ intern/cycles/kernel/osl/osl_shader.cpp | 3 +++ intern/cycles/kernel/svm/svm_closure.h | 8 +++++++- 10 files changed, 12 insertions(+), 14 deletions(-) diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h index 98c1159948a..580f50d5dd6 100644 --- a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h @@ -39,7 +39,6 @@ ccl_device int bsdf_ashikhmin_velvet_setup(ShaderClosure *sc) { float sigma = fmaxf(sc->data0, 0.01f); sc->data0 = 1.0f/(sigma * sigma); /* m_invsigma2 */ - sc->data1 = 0.0f; sc->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID; diff --git a/intern/cycles/kernel/closure/bsdf_diffuse.h b/intern/cycles/kernel/closure/bsdf_diffuse.h index 29725c5b5da..4b29bb096d1 100644 --- a/intern/cycles/kernel/closure/bsdf_diffuse.h +++ b/intern/cycles/kernel/closure/bsdf_diffuse.h @@ -40,8 +40,6 @@ CCL_NAMESPACE_BEGIN ccl_device int bsdf_diffuse_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_DIFFUSE_ID; - sc->data0 = 0.0f; - sc->data1 = 0.0f; return SD_BSDF|SD_BSDF_HAS_EVAL; } @@ -85,8 +83,6 @@ ccl_device int bsdf_diffuse_sample(const ShaderClosure *sc, float3 Ng, float3 I, ccl_device int bsdf_translucent_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_TRANSLUCENT_ID; - sc->data0 = 0.0f; - sc->data1 = 0.0f; return SD_BSDF|SD_BSDF_HAS_EVAL; } diff --git a/intern/cycles/kernel/closure/bsdf_reflection.h b/intern/cycles/kernel/closure/bsdf_reflection.h index d635e734188..303f4c9ce34 100644 --- a/intern/cycles/kernel/closure/bsdf_reflection.h +++ b/intern/cycles/kernel/closure/bsdf_reflection.h @@ -40,8 +40,6 @@ CCL_NAMESPACE_BEGIN ccl_device int bsdf_reflection_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_REFLECTION_ID; - sc->data0 = 0.0f; - sc->data1 = 0.0f; return SD_BSDF; } diff --git a/intern/cycles/kernel/closure/bsdf_refraction.h b/intern/cycles/kernel/closure/bsdf_refraction.h index e339778d7d0..c78a4b67134 100644 --- a/intern/cycles/kernel/closure/bsdf_refraction.h +++ b/intern/cycles/kernel/closure/bsdf_refraction.h @@ -40,8 +40,6 @@ CCL_NAMESPACE_BEGIN ccl_device int bsdf_refraction_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_REFRACTION_ID; - sc->data0 = 0.0f; - sc->data1 = 0.0f; return SD_BSDF; } diff --git a/intern/cycles/kernel/closure/bsdf_transparent.h b/intern/cycles/kernel/closure/bsdf_transparent.h index 78580190f6a..3c2fd8004df 100644 --- a/intern/cycles/kernel/closure/bsdf_transparent.h +++ b/intern/cycles/kernel/closure/bsdf_transparent.h @@ -38,8 +38,6 @@ CCL_NAMESPACE_BEGIN ccl_device int bsdf_transparent_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_TRANSPARENT_ID; - sc->data0 = 0.0f; - sc->data1 = 0.0f; return SD_BSDF|SD_TRANSPARENT; } diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h index 43de6e529ee..b6de2da8c71 100644 --- a/intern/cycles/kernel/closure/bssrdf.h +++ b/intern/cycles/kernel/closure/bssrdf.h @@ -30,7 +30,6 @@ ccl_device int bssrdf_setup(ShaderClosure *sc, ClosureType type) return flag; } else { - sc->data0 = 0.0f; sc->data1 = clamp(sc->data1, 0.0f, 1.0f); /* texture blur */ sc->T.x = clamp(sc->T.x, 0.0f, 1.0f); /* sharpness */ sc->type = type; diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h index 4143980f2cd..439610546e5 100644 --- a/intern/cycles/kernel/closure/volume.h +++ b/intern/cycles/kernel/closure/volume.h @@ -35,7 +35,6 @@ ccl_device int volume_henyey_greenstein_setup(ShaderClosure *sc) /* clamp anisotropy to avoid delta function */ sc->data0 = signf(sc->data0) * min(fabsf(sc->data0), 1.0f - 1e-3f); - sc->data1 = 0.0f; return SD_SCATTER; } diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 0f3b09a9555..17e5db93e2f 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -798,6 +798,8 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, #else sd->closure->weight = make_float3(0.8f, 0.8f, 0.8f); sd->closure->N = sd->N; + sd->closyre->data0 = 0.0f; + sd->closyre->data1 = 0.0f; sd->flag |= bsdf_diffuse_setup(&sd->closure); #endif } diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index ebf72ae11f4..fa6745a17a1 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -267,6 +267,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag, if(fabsf(weight.x) > 0.0f) { sc.weight = make_float3(weight.x, 0.0f, 0.0f); sc.data0 = bssrdf->radius.x; + sc.data1 = 0.0f; sd->flag |= bssrdf_setup(&sc, sc.type); sd->closure[sd->num_closure++] = sc; } @@ -274,6 +275,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag, if(fabsf(weight.y) > 0.0f) { sc.weight = make_float3(0.0f, weight.y, 0.0f); sc.data0 = bssrdf->radius.y; + sc.data1 = 0.0f; sd->flag |= bssrdf_setup(&sc, sc.type); sd->closure[sd->num_closure++] = sc; } @@ -281,6 +283,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag, if(fabsf(weight.z) > 0.0f) { sc.weight = make_float3(0.0f, 0.0f, weight.z); sc.data0 = bssrdf->radius.z; + sc.data1 = 0.0f; sd->flag |= bssrdf_setup(&sc, sc.type); sd->closure[sd->num_closure++] = sc; } diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 07ac7104e68..db9f442083e 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -27,8 +27,11 @@ ccl_device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type sc->data2 = 0.0f; sd->flag |= bsdf_refraction_setup(sc); } - else + else { + sc->data0 = 0.0f; + sc->data1 = 0.0f; sd->flag |= bsdf_reflection_setup(sc); + } } else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) { sc->data0 = roughness; @@ -384,6 +387,8 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * * spawned by transmission from the front */ sc->weight = make_float3(1.0f, 1.0f, 1.0f); sc->N = N; + sc->data0 = 0.0f; + sc->data1 = 0.0f; sd->flag |= bsdf_transparent_setup(sc); } } @@ -529,6 +534,7 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float if(sc) { sc->data0 = param2; /* g */ + sc->data1 = 0.0f; sd->flag |= volume_henyey_greenstein_setup(sc); } break; -- cgit v1.2.3 From 917b8754f9d89b9d0a1488d83e0c5ff308c74e1d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 25 Mar 2015 13:20:37 +0500 Subject: Tracking: Fix one frame memory leak when tracking last frame --- extern/libmv/libmv/autotrack/autotrack.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/extern/libmv/libmv/autotrack/autotrack.cc b/extern/libmv/libmv/autotrack/autotrack.cc index 96a0ef64a50..4c7bdf1fde8 100644 --- a/extern/libmv/libmv/autotrack/autotrack.cc +++ b/extern/libmv/libmv/autotrack/autotrack.cc @@ -154,6 +154,7 @@ bool AutoTrack::TrackMarker(Marker* tracked_marker, frame_accessor_, &tracked_image); if (!tracked_key) { + frame_accessor_->ReleaseImage(reference_key); LG << "Couldn't get frame for tracked marker: " << tracked_marker; return false; } -- cgit v1.2.3 From 8d0b104f4357f5914f3e28d735ebffa1526a598e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 25 Mar 2015 13:46:59 +0500 Subject: Fix T44064: Reroute two-node loop crash Issue was caused by cycles in shader graph confusing it's simplification stage. Now we're ignoring links which are marked as invalid from blender side so we don't run into such cycles and keep graph code simple. --- intern/cycles/blender/blender_shader.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index baf79a78987..5628d96db29 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -951,6 +951,10 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha BL::NodeTree::links_iterator b_link; for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) { + /* Ignore invalid links to avoid unwanted cycles created in graph. */ + if(!b_link->is_valid()) { + continue; + } /* get blender link data */ BL::NodeSocket b_from_sock = b_link->from_socket(); BL::NodeSocket b_to_sock = b_link->to_socket(); -- cgit v1.2.3 From 3eb33b804d48ac4009184722db02ecaa9d71ef21 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 25 Mar 2015 19:46:07 +1100 Subject: Fix T44118: Rotated background image disappears Image clipping didn't take rotation into account. --- source/blender/blenlib/BLI_rect.h | 2 ++ source/blender/blenlib/intern/rct.c | 41 +++++++++++++++++++++++ source/blender/editors/space_view3d/view3d_draw.c | 7 +++- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h index a132ac40206..e0a0b34ac5f 100644 --- a/source/blender/blenlib/BLI_rect.h +++ b/source/blender/blenlib/BLI_rect.h @@ -89,6 +89,8 @@ void BLI_rctf_union(struct rctf *rctf1, const struct rctf *rctf2); void BLI_rcti_rctf_copy(struct rcti *dst, const struct rctf *src); void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src); +void BLI_rctf_rotate_expand(rctf *dst, const rctf *src, const float angle); + void print_rctf(const char *str, const struct rctf *rect); void print_rcti(const char *str, const struct rcti *rect); diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c index 61e5783cd3e..d7ca749b600 100644 --- a/source/blender/blenlib/intern/rct.c +++ b/source/blender/blenlib/intern/rct.c @@ -571,3 +571,44 @@ void print_rcti(const char *str, const rcti *rect) printf("%s: xmin %d, xmax %d, ymin %d, ymax %d (%dx%d)\n", str, rect->xmin, rect->xmax, rect->ymin, rect->ymax, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)); } + + +/* -------------------------------------------------------------------- */ +/* Comprehensive math (float only) */ + +/** \name Rect math functions + * \{ */ + +#define ROTATE_SINCOS(r_vec, mat2, vec) { \ + (r_vec)[0] = (mat2)[1] * (vec)[0] + (+(mat2)[0]) * (vec)[1]; \ + (r_vec)[1] = (mat2)[0] * (vec)[0] + (-(mat2)[1]) * (vec)[1]; \ +} ((void)0) + +/** + * Expand the rectangle to fit a rotated \a src. + */ +void BLI_rctf_rotate_expand(rctf *dst, const rctf *src, const float angle) +{ + const float mat2[2] = {sinf(angle), cosf(angle)}; + const float cent[2] = {BLI_rctf_cent_x(src), BLI_rctf_cent_y(src)}; + float corner[2], corner_rot[2], corder_max[2]; + + ARRAY_SET_ITEMS(corner, src->xmin - cent[0], src->ymax - cent[1]); + ROTATE_SINCOS(corner_rot, mat2, corner); + corder_max[0] = fabsf(corner_rot[0]); + corder_max[1] = fabsf(corner_rot[1]); + + ARRAY_SET_ITEMS(corner, src->xmax - cent[0], src->ymax - cent[1]); + ROTATE_SINCOS(corner_rot, mat2, corner); + corder_max[0] = MAX2(corder_max[0], fabsf(corner_rot[0])); + corder_max[1] = MAX2(corder_max[1], fabsf(corner_rot[1])); + + dst->xmin = cent[0] - corder_max[0]; + dst->xmax = cent[0] + corder_max[0]; + dst->ymin = cent[1] - corder_max[1]; + dst->ymax = cent[1] + corder_max[1]; +} + +#undef ROTATE_SINCOS + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 86916a37d43..a06f6cd515b 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1624,6 +1624,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, ImBuf *ibuf = NULL, *freeibuf, *releaseibuf; void *lock; + rctf clip_rect; Image *ima = NULL; MovieClip *clip = NULL; @@ -1786,8 +1787,12 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, } /* complete clip? */ + BLI_rctf_init(&clip_rect, x1, x2, y1, y2); + if (bgpic->rotation) { + BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation); + } - if (x2 < 0 || y2 < 0 || x1 > ar->winx || y1 > ar->winy) { + if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || clip_rect.ymin > ar->winy) { if (freeibuf) IMB_freeImBuf(freeibuf); if (releaseibuf) -- cgit v1.2.3 From b38b5846bac2b7674d9130e943df76f5f3626d6c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 25 Mar 2015 20:16:27 +1100 Subject: Fix T44124: Crash deleting brush --- source/blender/editors/space_view3d/view3d_draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index a06f6cd515b..e51993ce91f 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -3636,7 +3636,7 @@ static bool is_cursor_visible(Scene *scene) else if (ob->mode & OB_MODE_TEXTURE_PAINT) { const Paint *p = BKE_paint_get_active(scene); - if (p && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) { + if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) { if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) { return true; } -- cgit v1.2.3 From 3cee9d6939c85afd7eabf9fafbcec7859abef9a0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 25 Mar 2015 20:28:17 +1100 Subject: Simplify recent commit --- source/blender/blenlib/intern/rct.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c index d7ca749b600..1edc9002611 100644 --- a/source/blender/blenlib/intern/rct.c +++ b/source/blender/blenlib/intern/rct.c @@ -593,12 +593,14 @@ void BLI_rctf_rotate_expand(rctf *dst, const rctf *src, const float angle) const float cent[2] = {BLI_rctf_cent_x(src), BLI_rctf_cent_y(src)}; float corner[2], corner_rot[2], corder_max[2]; - ARRAY_SET_ITEMS(corner, src->xmin - cent[0], src->ymax - cent[1]); + /* x is same for both corners */ + corner[0] = src->xmax - cent[0]; + corner[1] = src->ymax - cent[1]; ROTATE_SINCOS(corner_rot, mat2, corner); corder_max[0] = fabsf(corner_rot[0]); corder_max[1] = fabsf(corner_rot[1]); - ARRAY_SET_ITEMS(corner, src->xmax - cent[0], src->ymax - cent[1]); + corner[1] *= -1; ROTATE_SINCOS(corner_rot, mat2, corner); corder_max[0] = MAX2(corder_max[0], fabsf(corner_rot[0])); corder_max[1] = MAX2(corder_max[1], fabsf(corner_rot[1])); -- cgit v1.2.3 From 22dfb506229258e293d7ab32a2c495ce93084e9d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 25 Mar 2015 14:48:41 +0500 Subject: Fix T44128: Ray visibility only enables diffuse if glossy is also enabled Issue was caused by accident in c8a9a56 which not only disabled glossy reflection if Glossy visibility is disabled, but also Diffuse reflection. Quite safe and should go to final release branch. --- intern/cycles/kernel/kernel_emission.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 7523105607f..d3cbc5cff06 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -188,7 +188,8 @@ ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg, PathState *st /* use visibility flag to skip lights */ if(ls.shader & SHADER_EXCLUDE_ANY) { if(((ls.shader & SHADER_EXCLUDE_DIFFUSE) && (state->flag & PATH_RAY_DIFFUSE)) || - ((ls.shader & SHADER_EXCLUDE_GLOSSY) && (state->flag & PATH_RAY_REFLECT)) || + ((ls.shader & SHADER_EXCLUDE_GLOSSY) && + ((state->flag & (PATH_RAY_GLOSSY|PATH_RAY_REFLECT)) == (PATH_RAY_GLOSSY|PATH_RAY_REFLECT))) || ((ls.shader & SHADER_EXCLUDE_TRANSMIT) && (state->flag & PATH_RAY_TRANSMIT)) || ((ls.shader & SHADER_EXCLUDE_SCATTER) && (state->flag & PATH_RAY_VOLUME_SCATTER))) continue; @@ -232,7 +233,8 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg, PathState *sta /* use visibility flag to skip lights */ if(shader & SHADER_EXCLUDE_ANY) { if(((shader & SHADER_EXCLUDE_DIFFUSE) && (state->flag & PATH_RAY_DIFFUSE)) || - ((shader & SHADER_EXCLUDE_GLOSSY) && (state->flag & PATH_RAY_REFLECT)) || + ((shader & SHADER_EXCLUDE_GLOSSY) && + ((state->flag & (PATH_RAY_GLOSSY|PATH_RAY_REFLECT)) == (PATH_RAY_GLOSSY|PATH_RAY_REFLECT))) || ((shader & SHADER_EXCLUDE_TRANSMIT) && (state->flag & PATH_RAY_TRANSMIT)) || ((shader & SHADER_EXCLUDE_CAMERA) && (state->flag & PATH_RAY_CAMERA)) || ((shader & SHADER_EXCLUDE_SCATTER) && (state->flag & PATH_RAY_VOLUME_SCATTER))) -- cgit v1.2.3 From a180c8e2ed6ce62e6a15d28a0bb7f60bb58bc0cb Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 25 Mar 2015 12:05:34 +0100 Subject: Allow multiple strips to use the same directory when custom proxy directory is used. This is done by appending the name of the file as extra folder. Existing projects may need to regenerate their proxies but it should be possible now to have all proxies nicely in the same custom folder. Next commits will include operators to copy directory settings between selected strips, making the process faster. --- source/blender/blenkernel/intern/sequencer.c | 22 ++++++++++++++++------ source/blender/imbuf/IMB_imbuf.h | 1 + source/blender/imbuf/intern/indexer.c | 16 ++++++++++------ source/blender/makesdna/DNA_sequence_types.h | 2 +- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 19120d4da93..eb7736fff30 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1364,7 +1364,11 @@ static void seq_open_anim_file(Sequence *seq, bool openfile) if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) { char dir[FILE_MAX]; + char fname[FILE_MAXFILE]; BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); + IMB_anim_get_fname(seq->anim, fname, FILE_MAXFILE); + BLI_path_append(dir, sizeof(dir), fname); + BLI_path_abs(dir, G.main->name); IMB_anim_set_index_dir(seq->anim, dir); @@ -1390,8 +1394,14 @@ static bool seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char * * have both, a directory full of jpeg files and proxy avis, so * sorry folks, please rebuild your proxies... */ - if (proxy->storage & (SEQ_STORAGE_PROXY_CUSTOM_DIR | SEQ_STORAGE_PROXY_CUSTOM_FILE)) { + if ((proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE)) { + BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); + } + else if (seq->anim && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR)) { + char fname[FILE_MAXFILE]; BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); + IMB_anim_get_fname(seq->anim, fname, FILE_MAXFILE); + BLI_path_append(dir, sizeof(dir), fname); } else if (seq->type == SEQ_TYPE_IMAGE) { BLI_snprintf(dir, PROXY_MAXFILE, "%s/BL_proxy", seq->strip->dir); @@ -1402,7 +1412,7 @@ static bool seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char * if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) { BLI_join_dirfile(name, PROXY_MAXFILE, - dir, seq->strip->proxy->file); + dir, proxy->file); BLI_path_abs(name, G.main->name); return true; @@ -1436,15 +1446,15 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c int render_size = context->preview_render_size; StripProxy *proxy = seq->strip->proxy; + if (!(seq->flag & SEQ_USE_PROXY)) { + return NULL; + } + /* dirty hack to distinguish 100% render size from PROXY_100 */ if (render_size == 99) { render_size = 100; } - if (!(seq->flag & SEQ_USE_PROXY)) { - return NULL; - } - size_flags = proxy->build_size_flags; /* only use proxies, if they are enabled (even if present!) */ diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 447a14b95c3..18682302b3a 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -240,6 +240,7 @@ typedef enum IMB_Proxy_Size { /* defaults to BL_proxy within the directory of the animation */ void IMB_anim_set_index_dir(struct anim *anim, const char *dir); +void IMB_anim_get_fname(struct anim *anim, char *file, int size); int IMB_anim_index_get_frame_index(struct anim *anim, IMB_Timecode_Type tc, int position); diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index d0281744830..183159f7d6c 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -374,6 +374,13 @@ static void get_index_dir(struct anim *anim, char *index_dir, size_t index_dir_l } } +void IMB_anim_get_fname(struct anim *anim, char *file, int size) +{ + char fname[FILE_MAXFILE]; + BLI_split_dirfile(anim->name, file, fname, size, sizeof(fname)); + BLI_strncpy(file, fname, size); +} + static void get_proxy_filename(struct anim *anim, IMB_Proxy_Size preview_size, char *fname, bool temp) { @@ -381,8 +388,8 @@ static void get_proxy_filename(struct anim *anim, IMB_Proxy_Size preview_size, int i = IMB_proxy_size_to_array_index(preview_size); char proxy_name[256]; - char proxy_temp_name[256]; char stream_suffix[20]; + const char *name = (temp) ? "proxy_%d%s_part.avi" : "proxy_%d%s.avi"; stream_suffix[0] = 0; @@ -390,15 +397,12 @@ static void get_proxy_filename(struct anim *anim, IMB_Proxy_Size preview_size, BLI_snprintf(stream_suffix, sizeof(stream_suffix), "_st%d", anim->streamindex); } - BLI_snprintf(proxy_name, sizeof(proxy_name), "proxy_%d%s.avi", - (int) (proxy_fac[i] * 100), stream_suffix); - BLI_snprintf(proxy_temp_name, sizeof(proxy_temp_name), "proxy_%d%s_part.avi", + BLI_snprintf(proxy_name, sizeof(proxy_name), name, (int) (proxy_fac[i] * 100), stream_suffix); get_index_dir(anim, index_dir, sizeof(index_dir)); - BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, index_dir, - temp ? proxy_temp_name : proxy_name); + BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, index_dir, proxy_name); } static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc, diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 34fceaef4c0..c4de93efa6b 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -376,7 +376,7 @@ enum { /* StripProxy->storage */ enum { SEQ_STORAGE_PROXY_CUSTOM_FILE = (1 << 1), /* store proxy in custom directory */ - SEQ_STORAGE_PROXY_CUSTOM_DIR = (1 << 2) /* store proxy in custom file */ + SEQ_STORAGE_PROXY_CUSTOM_DIR = (1 << 2), /* store proxy in custom file */ }; #if (DNA_DEPRECATED_GCC_POISON == 1) -- cgit v1.2.3 From 8463e6cb416021d72282e386218118e06226101e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20T=C3=B6nne?= Date: Wed, 25 Mar 2015 12:26:16 +0100 Subject: Fix for crash when using particle emission with clump/roughness curves in a smoke sim. This interaction between sims is totally stupid and must be recoded entirely in some utopian future. --- source/blender/blenkernel/intern/smoke.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 559e1e05f3f..aa8649b1bed 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -66,6 +66,7 @@ #include "BKE_bvhutils.h" #include "BKE_cdderivedmesh.h" #include "BKE_collision.h" +#include "BKE_colortools.h" #include "BKE_constraint.h" #include "BKE_customdata.h" #include "BKE_deform.h" @@ -1239,6 +1240,12 @@ static void emit_from_particles(Object *flow_ob, SmokeDomainSettings *sds, Smoke sim.ob = flow_ob; sim.psys = psys; + /* prepare curvemapping tables */ + if ((psys->part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && psys->part->clumpcurve) + curvemapping_changed_all(psys->part->clumpcurve); + if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve) + curvemapping_changed_all(psys->part->roughcurve); + /* initialize particle cache */ if (psys->part->type == PART_HAIR) { // TODO: PART_HAIR not supported whatsoever -- cgit v1.2.3 From ec03ab021f171bf529746bb440756fbc986b45e7 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 25 Mar 2015 12:36:26 +0100 Subject: Change Enables proxy operator to Copy proxy operator. Allows to change and copy settings much easier, also allows things like directory settings etc to be copied over. --- release/scripts/startup/bl_ui/space_sequencer.py | 26 +++----- .../editors/space_sequencer/sequencer_edit.c | 74 ++++++++-------------- .../editors/space_sequencer/sequencer_intern.h | 2 +- .../editors/space_sequencer/sequencer_ops.c | 2 +- 4 files changed, 36 insertions(+), 68 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 4f83cc03b10..feaef352978 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -926,24 +926,14 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel): flow.prop(proxy, "directory") if proxy.use_proxy_custom_file: flow.prop(proxy, "filepath") - + layout.label("Enabled Proxies:") - enabled = "" - row = layout.row() - if (proxy.build_25): - enabled += "25% " - if (proxy.build_50): - enabled += "50% " - if (proxy.build_75): - enabled += "75% " - if (proxy.build_100): - enabled += "100% " - - row.label(enabled) - if (proxy.use_overwrite): - layout.label("Overwrite On") - else: - layout.label("Overwrite Off") + col = layout.column() + col.prop(proxy, "build_25") + col.prop(proxy, "build_50") + col.prop(proxy, "build_75") + col.prop(proxy, "build_100") + col.prop(proxy, "use_overwrite") col = layout.column() col.label(text="Build JPEG quality") @@ -956,7 +946,7 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel): col.prop(proxy, "timecode") col = layout.column() - col.operator("sequencer.enable_proxies") + col.operator("sequencer.copy_proxy_settings") col.operator("sequencer.rebuild_proxy") diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index aaf398bf3a1..dc37b764f65 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -3473,24 +3473,31 @@ void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER; } -static int sequencer_enable_proxies_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) -{ - return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 5 * UI_UNIT_Y); -} - -static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op) +static int sequencer_copy_proxy_settings_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); Editing *ed = BKE_sequencer_editing_get(scene, false); + Sequence *actseq = ed->act_seq; Sequence *seq; - bool proxy_25 = RNA_boolean_get(op->ptr, "proxy_25"); - bool proxy_50 = RNA_boolean_get(op->ptr, "proxy_50"); - bool proxy_75 = RNA_boolean_get(op->ptr, "proxy_75"); - bool proxy_100 = RNA_boolean_get(op->ptr, "proxy_100"); - bool override = RNA_boolean_get(op->ptr, "override"); + StripProxy *actproxy, *proxy; + bool proxy_25; + bool proxy_50; + bool proxy_75; + bool proxy_100; bool turnon = true; - if (ed == NULL || !(proxy_25 || proxy_50 || proxy_75 || proxy_100)) { + if (ed == NULL || actseq == NULL || !actseq->strip || !actseq->strip->proxy) { + return OPERATOR_CANCELLED; + } + + actproxy = actseq->strip->proxy; + + proxy_25 = (actproxy->build_size_flags & SEQ_PROXY_IMAGE_SIZE_25) != 0; + proxy_50 = (actproxy->build_size_flags & SEQ_PROXY_IMAGE_SIZE_50) != 0; + proxy_75 = (actproxy->build_size_flags & SEQ_PROXY_IMAGE_SIZE_75) != 0; + proxy_100 = (actproxy->build_size_flags & SEQ_PROXY_IMAGE_SIZE_100) != 0; + + if (!(proxy_25 || proxy_50 || proxy_75 || proxy_100)) { turnon = false; } @@ -3503,30 +3510,8 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op) continue; } - if (proxy_25) - seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_25; - else - seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_25; - - if (proxy_50) - seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_50; - else - seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_50; - - if (proxy_75) - seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_75; - else - seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_75; - - if (proxy_100) - seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_100; - else - seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_100; - - if (!override) - seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING; - else - seq->strip->proxy->build_flags &= ~SEQ_PROXY_SKIP_EXISTING; + proxy = seq->strip->proxy; + *proxy = *actproxy; } } } @@ -3537,25 +3522,18 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void SEQUENCER_OT_enable_proxies(wmOperatorType *ot) +void SEQUENCER_OT_copy_proxy_settings(wmOperatorType *ot) { /* identifiers */ - ot->name = "Set Selected Strip Proxies"; - ot->idname = "SEQUENCER_OT_enable_proxies"; - ot->description = "Enable selected proxies on all selected Movie strips"; + ot->name = "Copy Proxy Settings"; + ot->idname = "SEQUENCER_OT_copy_proxy_settings"; + ot->description = "Copy proxy settings of active strip selected strips"; /* api callbacks */ - ot->invoke = sequencer_enable_proxies_invoke; - ot->exec = sequencer_enable_proxies_exec; + ot->exec = sequencer_copy_proxy_settings_exec; /* flags */ ot->flag = OPTYPE_REGISTER; - - RNA_def_boolean(ot->srna, "proxy_25", false, "25%", ""); - RNA_def_boolean(ot->srna, "proxy_50", false, "50%", ""); - RNA_def_boolean(ot->srna, "proxy_75", false, "75%", ""); - RNA_def_boolean(ot->srna, "proxy_100", false, "100%", ""); - RNA_def_boolean(ot->srna, "override", false, "Override", ""); } /* change ops */ diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index 461c72961c2..8db0df51035 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -131,7 +131,7 @@ void SEQUENCER_OT_copy(struct wmOperatorType *ot); void SEQUENCER_OT_paste(struct wmOperatorType *ot); void SEQUENCER_OT_rebuild_proxy(struct wmOperatorType *ot); -void SEQUENCER_OT_enable_proxies(struct wmOperatorType *ot); +void SEQUENCER_OT_copy_proxy_settings(struct wmOperatorType *ot); /* preview specific operators */ void SEQUENCER_OT_view_all_preview(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c index 33a8a1c5b41..29fd2deeb55 100644 --- a/source/blender/editors/space_sequencer/sequencer_ops.c +++ b/source/blender/editors/space_sequencer/sequencer_ops.c @@ -88,7 +88,7 @@ void sequencer_operatortypes(void) WM_operatortype_append(SEQUENCER_OT_view_ghost_border); WM_operatortype_append(SEQUENCER_OT_rebuild_proxy); - WM_operatortype_append(SEQUENCER_OT_enable_proxies); + WM_operatortype_append(SEQUENCER_OT_copy_proxy_settings); WM_operatortype_append(SEQUENCER_OT_change_effect_input); WM_operatortype_append(SEQUENCER_OT_change_effect_type); WM_operatortype_append(SEQUENCER_OT_change_path); -- cgit v1.2.3 From 3d20bf75cbfa2ea6444a68af860b8ef1db5675a8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 26 Feb 2015 14:39:57 +1100 Subject: BKE_mball: split tessellation into its own file this has a lot of its own local structs, functions, better to keep isolated from general metaball selection/library logic. --- source/blender/blenkernel/BKE_mball_tessellate.h | 0 source/blender/blenkernel/CMakeLists.txt | 2 + source/blender/blenkernel/intern/mball.c | 1924 ------------------- .../blender/blenkernel/intern/mball_tessellate.c | 1984 ++++++++++++++++++++ 4 files changed, 1986 insertions(+), 1924 deletions(-) create mode 100644 source/blender/blenkernel/BKE_mball_tessellate.h create mode 100644 source/blender/blenkernel/intern/mball_tessellate.c diff --git a/source/blender/blenkernel/BKE_mball_tessellate.h b/source/blender/blenkernel/BKE_mball_tessellate.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index a826fe26e68..f19c1066766 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -119,6 +119,7 @@ set(SRC intern/mask_rasterize.c intern/material.c intern/mball.c + intern/mball_tessellate.c intern/mesh.c intern/mesh_evaluate.c intern/mesh_mapping.c @@ -233,6 +234,7 @@ set(SRC BKE_mask.h BKE_material.h BKE_mball.h + BKE_mball_tessellate.h BKE_mesh.h BKE_mesh_mapping.h BKE_mesh_remap.h diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index ce20636233a..efc5b23a9d0 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -65,119 +65,6 @@ #include "BKE_object.h" #include "BKE_material.h" -/* Data types */ - -typedef struct vertex { /* surface vertex */ - float co[3]; /* position and surface normal */ - float no[3]; -} VERTEX; - -typedef struct vertices { /* list of vertices in polygonization */ - int count, max; /* # vertices, max # allowed */ - VERTEX *ptr; /* dynamically allocated */ -} VERTICES; - -typedef struct corner { /* corner of a cube */ - int i, j, k; /* (i, j, k) is index within lattice */ - float co[3], value; /* location and function value */ - struct corner *next; -} CORNER; - -typedef struct cube { /* partitioning cell (cube) */ - int i, j, k; /* lattice location of cube */ - CORNER *corners[8]; /* eight corners */ -} CUBE; - -typedef struct cubes { /* linked list of cubes acting as stack */ - CUBE cube; /* a single cube */ - struct cubes *next; /* remaining elements */ -} CUBES; - -typedef struct centerlist { /* list of cube locations */ - int i, j, k; /* cube location */ - struct centerlist *next; /* remaining elements */ -} CENTERLIST; - -typedef struct edgelist { /* list of edges */ - int i1, j1, k1, i2, j2, k2; /* edge corner ids */ - int vid; /* vertex id */ - struct edgelist *next; /* remaining elements */ -} EDGELIST; - -typedef struct intlist { /* list of integers */ - int i; /* an integer */ - struct intlist *next; /* remaining elements */ -} INTLIST; - -typedef struct intlists { /* list of list of integers */ - INTLIST *list; /* a list of integers */ - struct intlists *next; /* remaining elements */ -} INTLISTS; - -/* dividing scene using octal tree makes polygonisation faster */ -typedef struct ml_pointer { - struct ml_pointer *next, *prev; - struct MetaElem *ml; -} ml_pointer; - -typedef struct octal_node { - struct octal_node *nodes[8];/* children of current node */ - struct octal_node *parent; /* parent of current node */ - struct ListBase elems; /* ListBase of MetaElem pointers (ml_pointer) */ - float x_min, y_min, z_min; /* 1st border point */ - float x_max, y_max, z_max; /* 7th border point */ - float x, y, z; /* center of node */ - int pos, neg; /* number of positive and negative MetaElements in the node */ - int count; /* number of MetaElems, which belongs to the node */ -} octal_node; - -typedef struct octal_tree { - struct octal_node *first; /* first node */ - int pos, neg; /* number of positive and negative MetaElements in the scene */ - short depth; /* number of scene subdivision */ -} octal_tree; - -struct pgn_elements { - struct pgn_elements *next, *prev; - char *data; -}; - -typedef struct process { /* parameters, function, storage */ - /* ** old G_mb contents ** */ - float thresh; - int totelem; - MetaElem **mainb; - octal_tree *metaball_tree; - - /* ** old process contents ** */ - - /* what happens here? floats, I think. */ - /* float (*function)(void); */ /* implicit surface function */ - float (*function)(struct process *, float, float, float); - float size, delta; /* cube size, normal delta */ - int bounds; /* cube range within lattice */ - CUBES *cubes; /* active cubes */ - VERTICES vertices; /* surface vertices */ - CENTERLIST **centers; /* cube center hash table */ - CORNER **corners; /* corner value hash table */ - EDGELIST **edges; /* edge and vertex id hash table */ - - /* Runtime things */ - int *indices; - int totindex, curindex; - - int pgn_offset; - struct pgn_elements *pgn_current; - ListBase pgn_list; -} PROCESS; - -/* Forward declarations */ -static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2, MetaBall *mb); -static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k); -static CORNER *setcorner(PROCESS *process, int i, int j, int k); -static void converge(PROCESS *process, const float p1[3], const float p2[3], float v1, float v2, - float p[3], MetaBall *mb, int f); - /* Functions */ void BKE_mball_unlink(MetaBall *mb) @@ -558,1817 +445,6 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis) return basis; } - -/* ******************** ARITH ************************* */ - -/* BASED AT CODE (but mostly rewritten) : - * C code from the article - * "An Implicit Surface Polygonizer" - * by Jules Bloomenthal, jbloom@beauty.gmu.edu - * in "Graphics Gems IV", Academic Press, 1994 - * - * Authored by Jules Bloomenthal, Xerox PARC. - * Copyright (c) Xerox Corporation, 1991. All rights reserved. - * Permission is granted to reproduce, use and distribute this code for - * any and all purposes, provided that this notice appears in all copies. */ - -#define RES 12 /* # converge iterations */ - -#define L 0 /* left direction: -x, -i */ -#define R 1 /* right direction: +x, +i */ -#define B 2 /* bottom direction: -y, -j */ -#define T 3 /* top direction: +y, +j */ -#define N 4 /* near direction: -z, -k */ -#define F 5 /* far direction: +z, +k */ -#define LBN 0 /* left bottom near corner */ -#define LBF 1 /* left bottom far corner */ -#define LTN 2 /* left top near corner */ -#define LTF 3 /* left top far corner */ -#define RBN 4 /* right bottom near corner */ -#define RBF 5 /* right bottom far corner */ -#define RTN 6 /* right top near corner */ -#define RTF 7 /* right top far corner */ - -/* the LBN corner of cube (i, j, k), corresponds with location - * (i-0.5)*size, (j-0.5)*size, (k-0.5)*size) */ - -#define HASHBIT (5) -#define HASHSIZE (size_t)(1 << (3 * HASHBIT)) /*! < hash table size (32768) */ - -#define HASH(i, j, k) ((((( (i) & 31) << 5) | ( (j) & 31)) << 5) | ( (k) & 31) ) - -#define MB_BIT(i, bit) (((i) >> (bit)) & 1) -#define FLIP(i, bit) ((i) ^ 1 << (bit)) /* flip the given bit of i */ - - -/* **************** POLYGONIZATION ************************ */ - -static void calc_mballco(MetaElem *ml, float vec[3]) -{ - if (ml->mat) { - mul_m4_v3((float (*)[4])ml->mat, vec); - } -} - -static float densfunc(MetaElem *ball, float x, float y, float z) -{ - float dist2; - float dvec[3] = {x, y, z}; - - mul_m4_v3((float (*)[4])ball->imat, dvec); - - switch (ball->type) { - case MB_BALL: - /* do nothing */ - break; - case MB_TUBE: - if (dvec[0] > ball->expx) dvec[0] -= ball->expx; - else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; - else dvec[0] = 0.0; - break; - case MB_PLANE: - if (dvec[0] > ball->expx) dvec[0] -= ball->expx; - else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; - else dvec[0] = 0.0; - if (dvec[1] > ball->expy) dvec[1] -= ball->expy; - else if (dvec[1] < -ball->expy) dvec[1] += ball->expy; - else dvec[1] = 0.0; - break; - case MB_ELIPSOID: - dvec[0] /= ball->expx; - dvec[1] /= ball->expy; - dvec[2] /= ball->expz; - break; - case MB_CUBE: - if (dvec[0] > ball->expx) dvec[0] -= ball->expx; - else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; - else dvec[0] = 0.0; - - if (dvec[1] > ball->expy) dvec[1] -= ball->expy; - else if (dvec[1] < -ball->expy) dvec[1] += ball->expy; - else dvec[1] = 0.0; - - if (dvec[2] > ball->expz) dvec[2] -= ball->expz; - else if (dvec[2] < -ball->expz) dvec[2] += ball->expz; - else dvec[2] = 0.0; - break; - - /* *** deprecated, could be removed?, do-versioned at least *** */ - case MB_TUBEX: - if (dvec[0] > ball->len) dvec[0] -= ball->len; - else if (dvec[0] < -ball->len) dvec[0] += ball->len; - else dvec[0] = 0.0; - break; - case MB_TUBEY: - if (dvec[1] > ball->len) dvec[1] -= ball->len; - else if (dvec[1] < -ball->len) dvec[1] += ball->len; - else dvec[1] = 0.0; - break; - case MB_TUBEZ: - if (dvec[2] > ball->len) dvec[2] -= ball->len; - else if (dvec[2] < -ball->len) dvec[2] += ball->len; - else dvec[2] = 0.0; - break; - /* *** end deprecated *** */ - } - - dist2 = 1.0f - (len_squared_v3(dvec) / ball->rad2); - - if ((ball->flag & MB_NEGATIVE) == 0) { - return (dist2 < 0.0f) ? -0.5f : (ball->s * dist2 * dist2 * dist2) - 0.5f; - } - else { - return (dist2 < 0.0f) ? 0.5f : 0.5f - (ball->s * dist2 * dist2 * dist2); - } -} - -static octal_node *find_metaball_octal_node(octal_node *node, float x, float y, float z, short depth) -{ - if (!depth) return node; - - if (z < node->z) { - if (y < node->y) { - if (x < node->x) { - if (node->nodes[0]) - return find_metaball_octal_node(node->nodes[0], x, y, z, depth--); - else - return node; - } - else { - if (node->nodes[1]) - return find_metaball_octal_node(node->nodes[1], x, y, z, depth--); - else - return node; - } - } - else { - if (x < node->x) { - if (node->nodes[3]) - return find_metaball_octal_node(node->nodes[3], x, y, z, depth--); - else - return node; - } - else { - if (node->nodes[2]) - return find_metaball_octal_node(node->nodes[2], x, y, z, depth--); - else - return node; - } - } - } - else { - if (y < node->y) { - if (x < node->x) { - if (node->nodes[4]) - return find_metaball_octal_node(node->nodes[4], x, y, z, depth--); - else - return node; - } - else { - if (node->nodes[5]) - return find_metaball_octal_node(node->nodes[5], x, y, z, depth--); - else - return node; - } - } - else { - if (x < node->x) { - if (node->nodes[7]) - return find_metaball_octal_node(node->nodes[7], x, y, z, depth--); - else - return node; - } - else { - if (node->nodes[6]) - return find_metaball_octal_node(node->nodes[6], x, y, z, depth--); - else - return node; - } - } - } - - /* all cases accounted for */ - BLI_assert(0); -} - -static float metaball(PROCESS *process, float x, float y, float z) -/* float x, y, z; */ -{ - octal_tree *metaball_tree = process->metaball_tree; - struct octal_node *node; - struct ml_pointer *ml_p; - float dens = 0; - int a; - - if (process->totelem > 1) { - node = find_metaball_octal_node(metaball_tree->first, x, y, z, metaball_tree->depth); - if (node) { - for (ml_p = node->elems.first; ml_p; ml_p = ml_p->next) { - dens += densfunc(ml_p->ml, x, y, z); - } - - dens += -0.5f * (metaball_tree->pos - node->pos); - dens += 0.5f * (metaball_tree->neg - node->neg); - } - else { - for (a = 0; a < process->totelem; a++) { - dens += densfunc(process->mainb[a], x, y, z); - } - } - } - else { - dens += densfunc(process->mainb[0], x, y, z); - } - - return process->thresh - dens; -} - -/* ******************************************** */ - -static void accum_mballfaces(PROCESS *process, int i1, int i2, int i3, int i4) -{ - int *newi, *cur; - /* static int i = 0; I would like to delete altogether, but I don't dare to, yet */ - - if (process->totindex == process->curindex) { - process->totindex += 256; - newi = MEM_mallocN(4 * sizeof(int) * process->totindex, "vertindex"); - - if (process->indices) { - memcpy(newi, process->indices, 4 * sizeof(int) * (process->totindex - 256)); - MEM_freeN(process->indices); - } - process->indices = newi; - } - - cur = process->indices + 4 * process->curindex; - - /* displists now support array drawing, we treat tri's as fake quad */ - - cur[0] = i1; - cur[1] = i2; - cur[2] = i3; - if (i4 == 0) - cur[3] = i3; - else - cur[3] = i4; - - process->curindex++; - -} - -/* ******************* MEMORY MANAGEMENT *********************** */ -static void *new_pgn_element(PROCESS *process, int size) -{ - /* during polygonize 1000s of elements are allocated - * and never freed in between. Freeing only done at the end. - */ - int blocksize = 16384; - void *adr; - - if (size > 10000 || size == 0) { - printf("incorrect use of new_pgn_element\n"); - } - else if (size == -1) { - struct pgn_elements *cur = process->pgn_list.first; - while (cur) { - MEM_freeN(cur->data); - cur = cur->next; - } - BLI_freelistN(&process->pgn_list); - - return NULL; - } - - size = 4 * ( (size + 3) / 4); - - if (process->pgn_current) { - if (size + process->pgn_offset < blocksize) { - adr = (void *) (process->pgn_current->data + process->pgn_offset); - process->pgn_offset += size; - return adr; - } - } - - process->pgn_current = MEM_callocN(sizeof(struct pgn_elements), "newpgn"); - process->pgn_current->data = MEM_callocN(blocksize, "newpgn"); - BLI_addtail(&process->pgn_list, process->pgn_current); - - process->pgn_offset = size; - return process->pgn_current->data; -} - -static void freepolygonize(PROCESS *process) -{ - MEM_freeN(process->corners); - MEM_freeN(process->edges); - MEM_freeN(process->centers); - - new_pgn_element(process, -1); - - if (process->vertices.ptr) { - MEM_freeN(process->vertices.ptr); - } -} - -/**** Cubical Polygonization (optional) ****/ - -#define LB 0 /* left bottom edge */ -#define LT 1 /* left top edge */ -#define LN 2 /* left near edge */ -#define LF 3 /* left far edge */ -#define RB 4 /* right bottom edge */ -#define RT 5 /* right top edge */ -#define RN 6 /* right near edge */ -#define RF 7 /* right far edge */ -#define BN 8 /* bottom near edge */ -#define BF 9 /* bottom far edge */ -#define TN 10 /* top near edge */ -#define TF 11 /* top far edge */ - -static INTLISTS *cubetable[256]; - -/* edge: LB, LT, LN, LF, RB, RT, RN, RF, BN, BF, TN, TF */ -static int corner1[12] = { - LBN, LTN, LBN, LBF, RBN, RTN, RBN, RBF, LBN, LBF, LTN, LTF -}; -static int corner2[12] = { - LBF, LTF, LTN, LTF, RBF, RTF, RTN, RTF, RBN, RBF, RTN, RTF -}; -static int leftface[12] = { - B, L, L, F, R, T, N, R, N, B, T, F -}; -/* face on left when going corner1 to corner2 */ -static int rightface[12] = { - L, T, N, L, B, R, R, F, B, F, N, T -}; -/* face on right when going corner1 to corner2 */ - - -/* docube: triangulate the cube directly, without decomposition */ - -static void docube(PROCESS *process, CUBE *cube, MetaBall *mb) -{ - INTLISTS *polys; - CORNER *c1, *c2; - int i, index = 0, count, indexar[8]; - - for (i = 0; i < 8; i++) { - if (cube->corners[i]->value > 0.0f) { - index += (1 << i); - } - } - - for (polys = cubetable[index]; polys; polys = polys->next) { - INTLIST *edges; - - count = 0; - - for (edges = polys->list; edges; edges = edges->next) { - c1 = cube->corners[corner1[edges->i]]; - c2 = cube->corners[corner2[edges->i]]; - - indexar[count] = vertid(process, c1, c2, mb); - count++; - } - if (count > 2) { - switch (count) { - case 3: - accum_mballfaces(process, indexar[2], indexar[1], indexar[0], 0); - break; - case 4: - if (indexar[0] == 0) accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); - else accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); - break; - case 5: - if (indexar[0] == 0) accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); - else accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); - - accum_mballfaces(process, indexar[4], indexar[3], indexar[0], 0); - break; - case 6: - if (indexar[0] == 0) { - accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); - accum_mballfaces(process, indexar[0], indexar[5], indexar[4], indexar[3]); - } - else { - accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); - accum_mballfaces(process, indexar[5], indexar[4], indexar[3], indexar[0]); - } - break; - case 7: - if (indexar[0] == 0) { - accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); - accum_mballfaces(process, indexar[0], indexar[5], indexar[4], indexar[3]); - } - else { - accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); - accum_mballfaces(process, indexar[5], indexar[4], indexar[3], indexar[0]); - } - - accum_mballfaces(process, indexar[6], indexar[5], indexar[0], 0); - - break; - } - } - } -} - - -/* testface: given cube at lattice (i, j, k), and four corners of face, - * if surface crosses face, compute other four corners of adjacent cube - * and add new cube to cube stack */ - -static void testface(PROCESS *process, int i, int j, int k, CUBE *old, int bit, int c1, int c2, int c3, int c4) -{ - CUBE newc; - CUBES *oldcubes = process->cubes; - CORNER *corn1, *corn2, *corn3, *corn4; - int n, pos; - - corn1 = old->corners[c1]; - corn2 = old->corners[c2]; - corn3 = old->corners[c3]; - corn4 = old->corners[c4]; - - pos = corn1->value > 0.0f ? 1 : 0; - - /* test if no surface crossing */ - if ( (corn2->value > 0) == pos && (corn3->value > 0) == pos && (corn4->value > 0) == pos) return; - /* test if cube out of bounds */ - /*if ( abs(i) > p->bounds || abs(j) > p->bounds || abs(k) > p->bounds) return;*/ - /* test if already visited (always as last) */ - if (setcenter(process, process->centers, i, j, k)) { - return; - } - - /* create new cube and add cube to top of stack: */ - process->cubes = (CUBES *) new_pgn_element(process, sizeof(CUBES)); - process->cubes->next = oldcubes; - - newc.i = i; - newc.j = j; - newc.k = k; - for (n = 0; n < 8; n++) newc.corners[n] = NULL; - - newc.corners[FLIP(c1, bit)] = corn1; - newc.corners[FLIP(c2, bit)] = corn2; - newc.corners[FLIP(c3, bit)] = corn3; - newc.corners[FLIP(c4, bit)] = corn4; - - if (newc.corners[0] == NULL) newc.corners[0] = setcorner(process, i, j, k); - if (newc.corners[1] == NULL) newc.corners[1] = setcorner(process, i, j, k + 1); - if (newc.corners[2] == NULL) newc.corners[2] = setcorner(process, i, j + 1, k); - if (newc.corners[3] == NULL) newc.corners[3] = setcorner(process, i, j + 1, k + 1); - if (newc.corners[4] == NULL) newc.corners[4] = setcorner(process, i + 1, j, k); - if (newc.corners[5] == NULL) newc.corners[5] = setcorner(process, i + 1, j, k + 1); - if (newc.corners[6] == NULL) newc.corners[6] = setcorner(process, i + 1, j + 1, k); - if (newc.corners[7] == NULL) newc.corners[7] = setcorner(process, i + 1, j + 1, k + 1); - - process->cubes->cube = newc; -} - -/* setcorner: return corner with the given lattice location - * set (and cache) its function value */ - -static CORNER *setcorner(PROCESS *process, int i, int j, int k) -{ - /* for speed, do corner value caching here */ - CORNER *c; - int index; - - /* does corner exist? */ - index = HASH(i, j, k); - c = process->corners[index]; - - for (; c != NULL; c = c->next) { - if (c->i == i && c->j == j && c->k == k) { - return c; - } - } - - c = (CORNER *) new_pgn_element(process, sizeof(CORNER)); - - c->i = i; - c->co[0] = ((float)i - 0.5f) * process->size; - c->j = j; - c->co[1] = ((float)j - 0.5f) * process->size; - c->k = k; - c->co[2] = ((float)k - 0.5f) * process->size; - c->value = process->function(process, c->co[0], c->co[1], c->co[2]); - - c->next = process->corners[index]; - process->corners[index] = c; - - return c; -} - - -/* nextcwedge: return next clockwise edge from given edge around given face */ - -static int nextcwedge(int edge, int face) -{ - switch (edge) { - case LB: - return (face == L) ? LF : BN; - case LT: - return (face == L) ? LN : TF; - case LN: - return (face == L) ? LB : TN; - case LF: - return (face == L) ? LT : BF; - case RB: - return (face == R) ? RN : BF; - case RT: - return (face == R) ? RF : TN; - case RN: - return (face == R) ? RT : BN; - case RF: - return (face == R) ? RB : TF; - case BN: - return (face == B) ? RB : LN; - case BF: - return (face == B) ? LB : RF; - case TN: - return (face == T) ? LT : RN; - case TF: - return (face == T) ? RT : LF; - } - return 0; -} - - -/* otherface: return face adjoining edge that is not the given face */ - -static int otherface(int edge, int face) -{ - int other = leftface[edge]; - return face == other ? rightface[edge] : other; -} - - -/* makecubetable: create the 256 entry table for cubical polygonization */ - -static void makecubetable(void) -{ - static bool is_done = false; - int i, e, c, done[12], pos[8]; - - if (is_done) return; - is_done = true; - - for (i = 0; i < 256; i++) { - for (e = 0; e < 12; e++) done[e] = 0; - for (c = 0; c < 8; c++) pos[c] = MB_BIT(i, c); - for (e = 0; e < 12; e++) - if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) { - INTLIST *ints = NULL; - INTLISTS *lists = (INTLISTS *) MEM_callocN(sizeof(INTLISTS), "mball_intlist"); - int start = e, edge = e; - - /* get face that is to right of edge from pos to neg corner: */ - int face = pos[corner1[e]] ? rightface[e] : leftface[e]; - - while (1) { - edge = nextcwedge(edge, face); - done[edge] = 1; - if (pos[corner1[edge]] != pos[corner2[edge]]) { - INTLIST *tmp = ints; - - ints = (INTLIST *) MEM_callocN(sizeof(INTLIST), "mball_intlist"); - ints->i = edge; - ints->next = tmp; /* add edge to head of list */ - - if (edge == start) break; - face = otherface(edge, face); - } - } - lists->list = ints; /* add ints to head of table entry */ - lists->next = cubetable[i]; - cubetable[i] = lists; - } - } -} - -void BKE_mball_cubeTable_free(void) -{ - int i; - INTLISTS *lists, *nlists; - INTLIST *ints, *nints; - - for (i = 0; i < 256; i++) { - lists = cubetable[i]; - while (lists) { - nlists = lists->next; - - ints = lists->list; - while (ints) { - nints = ints->next; - MEM_freeN(ints); - ints = nints; - } - - MEM_freeN(lists); - lists = nlists; - } - cubetable[i] = NULL; - } -} - -/**** Storage ****/ - -/* setcenter: set (i, j, k) entry of table[] - * return 1 if already set; otherwise, set and return 0 */ - -static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k) -{ - int index; - CENTERLIST *newc, *l, *q; - - index = HASH(i, j, k); - q = table[index]; - - for (l = q; l != NULL; l = l->next) { - if (l->i == i && l->j == j && l->k == k) return 1; - } - - newc = (CENTERLIST *) new_pgn_element(process, sizeof(CENTERLIST)); - newc->i = i; - newc->j = j; - newc->k = k; - newc->next = q; - table[index] = newc; - - return 0; -} - - -/* setedge: set vertex id for edge */ - -static void setedge(PROCESS *process, - EDGELIST *table[], - int i1, int j1, - int k1, int i2, - int j2, int k2, - int vid) -{ - unsigned int index; - EDGELIST *newe; - - if (i1 > i2 || (i1 == i2 && (j1 > j2 || (j1 == j2 && k1 > k2)))) { - int t = i1; - i1 = i2; - i2 = t; - t = j1; - j1 = j2; - j2 = t; - t = k1; - k1 = k2; - k2 = t; - } - index = HASH(i1, j1, k1) + HASH(i2, j2, k2); - newe = (EDGELIST *) new_pgn_element(process, sizeof(EDGELIST)); - newe->i1 = i1; - newe->j1 = j1; - newe->k1 = k1; - newe->i2 = i2; - newe->j2 = j2; - newe->k2 = k2; - newe->vid = vid; - newe->next = table[index]; - table[index] = newe; -} - - -/* getedge: return vertex id for edge; return -1 if not set */ - -static int getedge(EDGELIST *table[], - int i1, int j1, int k1, - int i2, int j2, int k2) -{ - EDGELIST *q; - - if (i1 > i2 || (i1 == i2 && (j1 > j2 || (j1 == j2 && k1 > k2)))) { - int t = i1; - i1 = i2; - i2 = t; - t = j1; - j1 = j2; - j2 = t; - t = k1; - k1 = k2; - k2 = t; - } - q = table[HASH(i1, j1, k1) + HASH(i2, j2, k2)]; - for (; q != NULL; q = q->next) { - if (q->i1 == i1 && q->j1 == j1 && q->k1 == k1 && - q->i2 == i2 && q->j2 == j2 && q->k2 == k2) - { - return q->vid; - } - } - return -1; -} - - -/**** Vertices ****/ - -#undef R - - - -/* vertid: return index for vertex on edge: - * c1->value and c2->value are presumed of different sign - * return saved index if any; else compute vertex and save */ - -/* addtovertices: add v to sequence of vertices */ - -static void addtovertices(VERTICES *vertices, VERTEX v) -{ - if (vertices->count == vertices->max) { - int i; - VERTEX *newv; - vertices->max = vertices->count == 0 ? 10 : 2 * vertices->count; - newv = (VERTEX *) MEM_callocN(vertices->max * sizeof(VERTEX), "addtovertices"); - - for (i = 0; i < vertices->count; i++) newv[i] = vertices->ptr[i]; - - if (vertices->ptr != NULL) MEM_freeN(vertices->ptr); - vertices->ptr = newv; - } - vertices->ptr[vertices->count++] = v; -} - -/* vnormal: compute unit length surface normal at point */ - -static void vnormal(PROCESS *process, const float point[3], float r_no[3]) -{ - const float delta = 0.2f * process->delta; - const float f = process->function(process, point[0], point[1], point[2]); - - r_no[0] = process->function(process, point[0] + delta, point[1], point[2]) - f; - r_no[1] = process->function(process, point[0], point[1] + delta, point[2]) - f; - r_no[2] = process->function(process, point[0], point[1], point[2] + delta) - f; - -#if 1 - normalize_v3(r_no); -#else - f = normalize_v3(r_no); - - if (0) { - float tvec[3]; - - delta *= 2.0f; - - f = process->function(process, point[0], point[1], point[2]); - - tvec[0] = process->function(process, point[0] + delta, point[1], point[2]) - f; - tvec[1] = process->function(process, point[0], point[1] + delta, point[2]) - f; - tvec[2] = process->function(process, point[0], point[1], point[2] + delta) - f; - - if (normalize_v3(tvec) != 0.0f) { - add_v3_v3(r_no, tvec); - normalize_v3(r_no); - } - } -#endif -} - - -static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2, MetaBall *mb) -{ - VERTEX v; - int vid = getedge(process->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k); - - if (vid != -1) { - return vid; /* previously computed */ - } - - converge(process, c1->co, c2->co, c1->value, c2->value, v.co, mb, 1); /* position */ - vnormal(process, v.co, v.no); - - addtovertices(&process->vertices, v); /* save vertex */ - vid = process->vertices.count - 1; - setedge(process, process->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid); - - return vid; -} - - -/* converge: from two points of differing sign, converge to zero crossing */ -/* watch it: p1 and p2 are used to calculate */ -static void converge(PROCESS *process, const float p1[3], const float p2[3], float v1, float v2, - float p[3], MetaBall *mb, int f) -{ - int i = 0; - float pos[3], neg[3]; - float positive = 0.0f, negative = 0.0f; - float dvec[3]; - - if (v1 < 0) { - copy_v3_v3(pos, p2); - copy_v3_v3(neg, p1); - positive = v2; - negative = v1; - } - else { - copy_v3_v3(pos, p1); - copy_v3_v3(neg, p2); - positive = v1; - negative = v2; - } - - sub_v3_v3v3(dvec, pos, neg); - -/* Approximation by linear interpolation is faster then binary subdivision, - * but it results sometimes (mb->thresh < 0.2) into the strange results */ - if ((mb->thresh > 0.2f) && (f == 1)) { - if ((dvec[1] == 0.0f) && (dvec[2] == 0.0f)) { - p[0] = neg[0] - negative * dvec[0] / (positive - negative); - p[1] = neg[1]; - p[2] = neg[2]; - return; - } - if ((dvec[0] == 0.0f) && (dvec[2] == 0.0f)) { - p[0] = neg[0]; - p[1] = neg[1] - negative * dvec[1] / (positive - negative); - p[2] = neg[2]; - return; - } - if ((dvec[0] == 0.0f) && (dvec[1] == 0.0f)) { - p[0] = neg[0]; - p[1] = neg[1]; - p[2] = neg[2] - negative * dvec[2] / (positive - negative); - return; - } - } - - if ((dvec[1] == 0.0f) && (dvec[2] == 0.0f)) { - p[1] = neg[1]; - p[2] = neg[2]; - while (1) { - if (i++ == RES) return; - p[0] = 0.5f * (pos[0] + neg[0]); - if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[0] = p[0]; - else neg[0] = p[0]; - } - } - - if ((dvec[0] == 0.0f) && (dvec[2] == 0.0f)) { - p[0] = neg[0]; - p[2] = neg[2]; - while (1) { - if (i++ == RES) return; - p[1] = 0.5f * (pos[1] + neg[1]); - if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[1] = p[1]; - else neg[1] = p[1]; - } - } - - if ((dvec[0] == 0.0f) && (dvec[1] == 0.0f)) { - p[0] = neg[0]; - p[1] = neg[1]; - while (1) { - if (i++ == RES) return; - p[2] = 0.5f * (pos[2] + neg[2]); - if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[2] = p[2]; - else neg[2] = p[2]; - } - } - - /* This is necessary to find start point */ - while (1) { - mid_v3_v3v3(&p[0], pos, neg); - - if (i++ == RES) { - return; - } - - if ((process->function(process, p[0], p[1], p[2])) > 0.0f) { - copy_v3_v3(pos, &p[0]); - } - else { - copy_v3_v3(neg, &p[0]); - } - } -} - -/* ************************************** */ -static void add_cube(PROCESS *process, int i, int j, int k, int count) -{ - CUBES *ncube; - int n; - int a, b, c; - - /* hmmm, not only one, but eight cube will be added on the stack - * ... */ - for (a = i - 1; a < i + count; a++) - for (b = j - 1; b < j + count; b++) - for (c = k - 1; c < k + count; c++) { - /* test if cube has been found before */ - if (setcenter(process, process->centers, a, b, c) == 0) { - /* push cube on stack: */ - ncube = (CUBES *) new_pgn_element(process, sizeof(CUBES)); - ncube->next = process->cubes; - process->cubes = ncube; - - ncube->cube.i = a; - ncube->cube.j = b; - ncube->cube.k = c; - - /* set corners of initial cube: */ - for (n = 0; n < 8; n++) - ncube->cube.corners[n] = setcorner(process, a + MB_BIT(n, 2), b + MB_BIT(n, 1), c + MB_BIT(n, 0)); - } - } -} - - -static void find_first_points(PROCESS *process, MetaBall *mb, int a) -{ - MetaElem *ml; - float f; - - ml = process->mainb[a]; - f = 1.0f - (mb->thresh / ml->s); - - /* Skip, when Stiffness of MetaElement is too small ... MetaElement can't be - * visible alone ... but still can influence others MetaElements :-) */ - if (f > 0.0f) { - float IN[3] = {0.0f}, OUT[3] = {0.0f}, in[3] = {0.0f}, out[3]; - int i, j, k, c_i, c_j, c_k; - int index[3] = {1, 0, -1}; - float in_v /*, out_v*/; - float workp[3]; - float dvec[3]; - float tmp_v, workp_v, max_len_sq, nx, ny, nz, max_dim; - - calc_mballco(ml, in); - in_v = process->function(process, in[0], in[1], in[2]); - - for (i = 0; i < 3; i++) { - switch (ml->type) { - case MB_BALL: - OUT[0] = out[0] = IN[0] + index[i] * ml->rad; - break; - case MB_TUBE: - case MB_PLANE: - case MB_ELIPSOID: - case MB_CUBE: - OUT[0] = out[0] = IN[0] + index[i] * (ml->expx + ml->rad); - break; - } - - for (j = 0; j < 3; j++) { - switch (ml->type) { - case MB_BALL: - OUT[1] = out[1] = IN[1] + index[j] * ml->rad; - break; - case MB_TUBE: - case MB_PLANE: - case MB_ELIPSOID: - case MB_CUBE: - OUT[1] = out[1] = IN[1] + index[j] * (ml->expy + ml->rad); - break; - } - - for (k = 0; k < 3; k++) { - out[0] = OUT[0]; - out[1] = OUT[1]; - switch (ml->type) { - case MB_BALL: - case MB_TUBE: - case MB_PLANE: - out[2] = IN[2] + index[k] * ml->rad; - break; - case MB_ELIPSOID: - case MB_CUBE: - out[2] = IN[2] + index[k] * (ml->expz + ml->rad); - break; - } - - calc_mballco(ml, out); - - /*out_v = process->function(out[0], out[1], out[2]);*/ /*UNUSED*/ - - /* find "first points" on Implicit Surface of MetaElemnt ml */ - copy_v3_v3(workp, in); - workp_v = in_v; - max_len_sq = len_squared_v3v3(out, in); - - nx = fabsf((out[0] - in[0]) / process->size); - ny = fabsf((out[1] - in[1]) / process->size); - nz = fabsf((out[2] - in[2]) / process->size); - - max_dim = max_fff(nx, ny, nz); - if (max_dim != 0.0f) { - float len_sq = 0.0f; - - dvec[0] = (out[0] - in[0]) / max_dim; - dvec[1] = (out[1] - in[1]) / max_dim; - dvec[2] = (out[2] - in[2]) / max_dim; - - while (len_sq <= max_len_sq) { - add_v3_v3(workp, dvec); - - /* compute value of implicite function */ - tmp_v = process->function(process, workp[0], workp[1], workp[2]); - /* add cube to the stack, when value of implicite function crosses zero value */ - if ((tmp_v < 0.0f && workp_v >= 0.0f) || (tmp_v > 0.0f && workp_v <= 0.0f)) { - - /* indexes of CUBE, which includes "first point" */ - c_i = (int)floor(workp[0] / process->size); - c_j = (int)floor(workp[1] / process->size); - c_k = (int)floor(workp[2] / process->size); - - /* add CUBE (with indexes c_i, c_j, c_k) to the stack, - * this cube includes found point of Implicit Surface */ - if ((ml->flag & MB_NEGATIVE) == 0) { - add_cube(process, c_i, c_j, c_k, 1); - } - else { - add_cube(process, c_i, c_j, c_k, 2); - } - } - len_sq = len_squared_v3v3(workp, in); - workp_v = tmp_v; - - } - } - } - } - } - } -} - -static void polygonize(PROCESS *process, MetaBall *mb) -{ - CUBE c; - int a; - - process->vertices.count = process->vertices.max = 0; - process->vertices.ptr = NULL; - - /* allocate hash tables and build cube polygon table: */ - process->centers = MEM_callocN(HASHSIZE * sizeof(CENTERLIST *), "mbproc->centers"); - process->corners = MEM_callocN(HASHSIZE * sizeof(CORNER *), "mbproc->corners"); - process->edges = MEM_callocN(2 * HASHSIZE * sizeof(EDGELIST *), "mbproc->edges"); - makecubetable(); - - for (a = 0; a < process->totelem; a++) { - - /* try to find 8 points on the surface for each MetaElem */ - find_first_points(process, mb, a); - } - - /* polygonize all MetaElems of current MetaBall */ - while (process->cubes != NULL) { /* process active cubes till none left */ - c = process->cubes->cube; - - /* polygonize the cube directly: */ - docube(process, &c, mb); - - /* pop current cube from stack */ - process->cubes = process->cubes->next; - - /* test six face directions, maybe add to stack: */ - testface(process, c.i - 1, c.j, c.k, &c, 2, LBN, LBF, LTN, LTF); - testface(process, c.i + 1, c.j, c.k, &c, 2, RBN, RBF, RTN, RTF); - testface(process, c.i, c.j - 1, c.k, &c, 1, LBN, LBF, RBN, RBF); - testface(process, c.i, c.j + 1, c.k, &c, 1, LTN, LTF, RTN, RTF); - testface(process, c.i, c.j, c.k - 1, &c, 0, LBN, LTN, RBN, RTN); - testface(process, c.i, c.j, c.k + 1, &c, 0, LBF, LTF, RBF, RTF); - } -} - -static float init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob) /* return totsize */ -{ - Scene *sce_iter = scene; - Base *base; - Object *bob; - MetaBall *mb; - MetaElem *ml; - float size, totsize, obinv[4][4], obmat[4][4], vec[3]; - //float max = 0.0f; - int a, obnr, zero_size = 0; - char obname[MAX_ID_NAME]; - SceneBaseIter iter; - - copy_m4_m4(obmat, ob->obmat); /* to cope with duplicators from BKE_scene_base_iter_next */ - invert_m4_m4(obinv, ob->obmat); - a = 0; - - BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); - - /* make main array */ - BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL); - while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &bob)) { - - if (bob->type == OB_MBALL) { - zero_size = 0; - ml = NULL; - - if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) { - mb = ob->data; - - if (mb->editelems) ml = mb->editelems->first; - else ml = mb->elems.first; - } - else { - char name[MAX_ID_NAME]; - int nr; - - BLI_split_name_num(name, &nr, bob->id.name + 2, '.'); - if (STREQ(obname, name)) { - mb = bob->data; - - if (mb->editelems) ml = mb->editelems->first; - else ml = mb->elems.first; - } - } - - /* when metaball object has zero scale, then MetaElem to this MetaBall - * will not be put to mainb array */ - if (has_zero_axis_m4(bob->obmat)) { - zero_size = 1; - } - else if (bob->parent) { - struct Object *pob = bob->parent; - while (pob) { - if (has_zero_axis_m4(pob->obmat)) { - zero_size = 1; - break; - } - pob = pob->parent; - } - } - - if (zero_size) { - unsigned int ml_count = 0; - while (ml) { - ml_count++; - ml = ml->next; - } - process->totelem -= ml_count; - } - else { - while (ml) { - if (!(ml->flag & MB_HIDE)) { - int i; - float temp1[4][4], temp2[4][4], temp3[4][4]; - float (*mat)[4] = NULL, (*imat)[4] = NULL; - float max_x, max_y, max_z, min_x, min_y, min_z; - float expx, expy, expz; - - max_x = max_y = max_z = -3.4e38; - min_x = min_y = min_z = 3.4e38; - - /* too big stiffness seems only ugly due to linear interpolation - * no need to have possibility for too big stiffness */ - if (ml->s > 10.0f) ml->s = 10.0f; - - /* Rotation of MetaElem is stored in quat */ - quat_to_mat4(temp3, ml->quat); - - /* Translation of MetaElem */ - unit_m4(temp2); - temp2[3][0] = ml->x; - temp2[3][1] = ml->y; - temp2[3][2] = ml->z; - - mul_m4_m4m4(temp1, temp2, temp3); - - /* make a copy because of duplicates */ - process->mainb[a] = new_pgn_element(process, sizeof(MetaElem)); - *(process->mainb[a]) = *ml; - process->mainb[a]->bb = new_pgn_element(process, sizeof(BoundBox)); - - mat = new_pgn_element(process, 4 * 4 * sizeof(float)); - imat = new_pgn_element(process, 4 * 4 * sizeof(float)); - - /* mat is the matrix to transform from mball into the basis-mball */ - invert_m4_m4(obinv, obmat); - mul_m4_m4m4(temp2, obinv, bob->obmat); - /* MetaBall transformation */ - mul_m4_m4m4(mat, temp2, temp1); - - invert_m4_m4(imat, mat); - - process->mainb[a]->rad2 = ml->rad * ml->rad; - - process->mainb[a]->mat = (float *) mat; - process->mainb[a]->imat = (float *) imat; - - if (!MB_TYPE_SIZE_SQUARED(ml->type)) { - expx = ml->expx; - expy = ml->expy; - expz = ml->expz; - } - else { - expx = ml->expx * ml->expx; - expy = ml->expy * ml->expy; - expz = ml->expz * ml->expz; - } - - /* untransformed Bounding Box of MetaElem */ - /* TODO, its possible the elem type has been changed and the exp* values can use a fallback */ - copy_v3_fl3(process->mainb[a]->bb->vec[0], -expx, -expy, -expz); /* 0 */ - copy_v3_fl3(process->mainb[a]->bb->vec[1], +expx, -expy, -expz); /* 1 */ - copy_v3_fl3(process->mainb[a]->bb->vec[2], +expx, +expy, -expz); /* 2 */ - copy_v3_fl3(process->mainb[a]->bb->vec[3], -expx, +expy, -expz); /* 3 */ - copy_v3_fl3(process->mainb[a]->bb->vec[4], -expx, -expy, +expz); /* 4 */ - copy_v3_fl3(process->mainb[a]->bb->vec[5], +expx, -expy, +expz); /* 5 */ - copy_v3_fl3(process->mainb[a]->bb->vec[6], +expx, +expy, +expz); /* 6 */ - copy_v3_fl3(process->mainb[a]->bb->vec[7], -expx, +expy, +expz); /* 7 */ - - /* transformation of Metalem bb */ - for (i = 0; i < 8; i++) - mul_m4_v3((float (*)[4])mat, process->mainb[a]->bb->vec[i]); - - /* find max and min of transformed bb */ - for (i = 0; i < 8; i++) { - /* find maximums */ - if (process->mainb[a]->bb->vec[i][0] > max_x) max_x = process->mainb[a]->bb->vec[i][0]; - if (process->mainb[a]->bb->vec[i][1] > max_y) max_y = process->mainb[a]->bb->vec[i][1]; - if (process->mainb[a]->bb->vec[i][2] > max_z) max_z = process->mainb[a]->bb->vec[i][2]; - /* find minimums */ - if (process->mainb[a]->bb->vec[i][0] < min_x) min_x = process->mainb[a]->bb->vec[i][0]; - if (process->mainb[a]->bb->vec[i][1] < min_y) min_y = process->mainb[a]->bb->vec[i][1]; - if (process->mainb[a]->bb->vec[i][2] < min_z) min_z = process->mainb[a]->bb->vec[i][2]; - } - - /* create "new" bb, only point 0 and 6, which are - * necessary for octal tree filling */ - process->mainb[a]->bb->vec[0][0] = min_x - ml->rad; - process->mainb[a]->bb->vec[0][1] = min_y - ml->rad; - process->mainb[a]->bb->vec[0][2] = min_z - ml->rad; - - process->mainb[a]->bb->vec[6][0] = max_x + ml->rad; - process->mainb[a]->bb->vec[6][1] = max_y + ml->rad; - process->mainb[a]->bb->vec[6][2] = max_z + ml->rad; - - a++; - } - ml = ml->next; - } - } - } - } - - - /* totsize (= 'manhattan' radius) */ - totsize = 0.0; - for (a = 0; a < process->totelem; a++) { - - vec[0] = process->mainb[a]->x + process->mainb[a]->rad + process->mainb[a]->expx; - vec[1] = process->mainb[a]->y + process->mainb[a]->rad + process->mainb[a]->expy; - vec[2] = process->mainb[a]->z + process->mainb[a]->rad + process->mainb[a]->expz; - - calc_mballco(process->mainb[a], vec); - - size = fabsf(vec[0]); - if (size > totsize) totsize = size; - size = fabsf(vec[1]); - if (size > totsize) totsize = size; - size = fabsf(vec[2]); - if (size > totsize) totsize = size; - - vec[0] = process->mainb[a]->x - process->mainb[a]->rad; - vec[1] = process->mainb[a]->y - process->mainb[a]->rad; - vec[2] = process->mainb[a]->z - process->mainb[a]->rad; - - calc_mballco(process->mainb[a], vec); - - size = fabsf(vec[0]); - if (size > totsize) totsize = size; - size = fabsf(vec[1]); - if (size > totsize) totsize = size; - size = fabsf(vec[2]); - if (size > totsize) totsize = size; - } - - for (a = 0; a < process->totelem; a++) { - process->thresh += densfunc(process->mainb[a], 2.0f * totsize, 2.0f * totsize, 2.0f * totsize); - } - - return totsize; -} - -/* if MetaElem lies in node, then node includes MetaElem pointer (ml_p) - * pointing at MetaElem (ml) - */ -static void fill_metaball_octal_node(octal_node *node, MetaElem *ml, short i) -{ - ml_pointer *ml_p; - - ml_p = MEM_mallocN(sizeof(ml_pointer), "ml_pointer"); - ml_p->ml = ml; - BLI_addtail(&(node->nodes[i]->elems), ml_p); - node->count++; - - if ((ml->flag & MB_NEGATIVE) == 0) { - node->nodes[i]->pos++; - } - else { - node->nodes[i]->neg++; - } -} - -/* Node is subdivided as is illustrated on the following figure: - * - * +------+------+ - * / / /| - * +------+------+ | - * / / /| + - * +------+------+ |/| - * | | | + | - * | | |/| + - * +------+------+ |/ - * | | | + - * | | |/ - * +------+------+ - * - */ -static void subdivide_metaball_octal_node(octal_node *node, float size_x, float size_y, float size_z, short depth) -{ - MetaElem *ml; - ml_pointer *ml_p; - float x, y, z; - int a, i; - - /* create new nodes */ - for (a = 0; a < 8; a++) { - node->nodes[a] = MEM_mallocN(sizeof(octal_node), "octal_node"); - for (i = 0; i < 8; i++) - node->nodes[a]->nodes[i] = NULL; - node->nodes[a]->parent = node; - BLI_listbase_clear(&node->nodes[a]->elems); - node->nodes[a]->count = 0; - node->nodes[a]->neg = 0; - node->nodes[a]->pos = 0; - } - - size_x /= 2; - size_y /= 2; - size_z /= 2; - - /* center of node */ - node->x = x = node->x_min + size_x; - node->y = y = node->y_min + size_y; - node->z = z = node->z_min + size_z; - - /* setting up of border points of new nodes */ - node->nodes[0]->x_min = node->x_min; - node->nodes[0]->y_min = node->y_min; - node->nodes[0]->z_min = node->z_min; - node->nodes[0]->x = node->nodes[0]->x_min + size_x / 2; - node->nodes[0]->y = node->nodes[0]->y_min + size_y / 2; - node->nodes[0]->z = node->nodes[0]->z_min + size_z / 2; - - node->nodes[1]->x_min = x; - node->nodes[1]->y_min = node->y_min; - node->nodes[1]->z_min = node->z_min; - node->nodes[1]->x = node->nodes[1]->x_min + size_x / 2; - node->nodes[1]->y = node->nodes[1]->y_min + size_y / 2; - node->nodes[1]->z = node->nodes[1]->z_min + size_z / 2; - - node->nodes[2]->x_min = x; - node->nodes[2]->y_min = y; - node->nodes[2]->z_min = node->z_min; - node->nodes[2]->x = node->nodes[2]->x_min + size_x / 2; - node->nodes[2]->y = node->nodes[2]->y_min + size_y / 2; - node->nodes[2]->z = node->nodes[2]->z_min + size_z / 2; - - node->nodes[3]->x_min = node->x_min; - node->nodes[3]->y_min = y; - node->nodes[3]->z_min = node->z_min; - node->nodes[3]->x = node->nodes[3]->x_min + size_x / 2; - node->nodes[3]->y = node->nodes[3]->y_min + size_y / 2; - node->nodes[3]->z = node->nodes[3]->z_min + size_z / 2; - - node->nodes[4]->x_min = node->x_min; - node->nodes[4]->y_min = node->y_min; - node->nodes[4]->z_min = z; - node->nodes[4]->x = node->nodes[4]->x_min + size_x / 2; - node->nodes[4]->y = node->nodes[4]->y_min + size_y / 2; - node->nodes[4]->z = node->nodes[4]->z_min + size_z / 2; - - node->nodes[5]->x_min = x; - node->nodes[5]->y_min = node->y_min; - node->nodes[5]->z_min = z; - node->nodes[5]->x = node->nodes[5]->x_min + size_x / 2; - node->nodes[5]->y = node->nodes[5]->y_min + size_y / 2; - node->nodes[5]->z = node->nodes[5]->z_min + size_z / 2; - - node->nodes[6]->x_min = x; - node->nodes[6]->y_min = y; - node->nodes[6]->z_min = z; - node->nodes[6]->x = node->nodes[6]->x_min + size_x / 2; - node->nodes[6]->y = node->nodes[6]->y_min + size_y / 2; - node->nodes[6]->z = node->nodes[6]->z_min + size_z / 2; - - node->nodes[7]->x_min = node->x_min; - node->nodes[7]->y_min = y; - node->nodes[7]->z_min = z; - node->nodes[7]->x = node->nodes[7]->x_min + size_x / 2; - node->nodes[7]->y = node->nodes[7]->y_min + size_y / 2; - node->nodes[7]->z = node->nodes[7]->z_min + size_z / 2; - - ml_p = node->elems.first; - - /* setting up references of MetaElems for new nodes */ - while (ml_p) { - ml = ml_p->ml; - if (ml->bb->vec[0][2] < z) { - if (ml->bb->vec[0][1] < y) { - /* vec[0][0] lies in first octant */ - if (ml->bb->vec[0][0] < x) { - /* ml belongs to the (0)1st node */ - fill_metaball_octal_node(node, ml, 0); - - /* ml belongs to the (3)4th node */ - if (ml->bb->vec[6][1] >= y) { - fill_metaball_octal_node(node, ml, 3); - - /* ml belongs to the (7)8th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 7); - } - } - - /* ml belongs to the (1)2nd node */ - if (ml->bb->vec[6][0] >= x) { - fill_metaball_octal_node(node, ml, 1); - - /* ml belongs to the (5)6th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 5); - } - } - - /* ml belongs to the (2)3th node */ - if ((ml->bb->vec[6][0] >= x) && (ml->bb->vec[6][1] >= y)) { - fill_metaball_octal_node(node, ml, 2); - - /* ml belong to the (6)7th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 6); - } - - } - - /* ml belongs to the (4)5th node too */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 4); - } - - - - } - /* vec[0][0] is in the (1)second octant */ - else { - /* ml belong to the (1)2nd node */ - fill_metaball_octal_node(node, ml, 1); - - /* ml belongs to the (2)3th node */ - if (ml->bb->vec[6][1] >= y) { - fill_metaball_octal_node(node, ml, 2); - - /* ml belongs to the (6)7th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 6); - } - - } - - /* ml belongs to the (5)6th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 5); - } - } - } - else { - /* vec[0][0] is in the (3)4th octant */ - if (ml->bb->vec[0][0] < x) { - /* ml belongs to the (3)4nd node */ - fill_metaball_octal_node(node, ml, 3); - - /* ml belongs to the (7)8th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 7); - } - - - /* ml belongs to the (2)3th node */ - if (ml->bb->vec[6][0] >= x) { - fill_metaball_octal_node(node, ml, 2); - - /* ml belongs to the (6)7th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 6); - } - } - } - - } - - /* vec[0][0] is in the (2)3th octant */ - if ((ml->bb->vec[0][0] >= x) && (ml->bb->vec[0][1] >= y)) { - /* ml belongs to the (2)3th node */ - fill_metaball_octal_node(node, ml, 2); - - /* ml belongs to the (6)7th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 6); - } - } - } - else { - if (ml->bb->vec[0][1] < y) { - /* vec[0][0] lies in (4)5th octant */ - if (ml->bb->vec[0][0] < x) { - /* ml belongs to the (4)5th node */ - fill_metaball_octal_node(node, ml, 4); - - if (ml->bb->vec[6][0] >= x) { - fill_metaball_octal_node(node, ml, 5); - } - - if (ml->bb->vec[6][1] >= y) { - fill_metaball_octal_node(node, ml, 7); - } - - if ((ml->bb->vec[6][0] >= x) && (ml->bb->vec[6][1] >= y)) { - fill_metaball_octal_node(node, ml, 6); - } - } - /* vec[0][0] lies in (5)6th octant */ - else { - fill_metaball_octal_node(node, ml, 5); - - if (ml->bb->vec[6][1] >= y) { - fill_metaball_octal_node(node, ml, 6); - } - } - } - else { - /* vec[0][0] lies in (7)8th octant */ - if (ml->bb->vec[0][0] < x) { - fill_metaball_octal_node(node, ml, 7); - - if (ml->bb->vec[6][0] >= x) { - fill_metaball_octal_node(node, ml, 6); - } - } - - } - - /* vec[0][0] lies in (6)7th octant */ - if ((ml->bb->vec[0][0] >= x) && (ml->bb->vec[0][1] >= y)) { - fill_metaball_octal_node(node, ml, 6); - } - } - ml_p = ml_p->next; - } - - /* free references of MetaElems for curent node (it is not needed anymore) */ - BLI_freelistN(&node->elems); - - depth--; - - if (depth > 0) { - for (a = 0; a < 8; a++) { - if (node->nodes[a]->count > 0) /* if node is not empty, then it is subdivided */ - subdivide_metaball_octal_node(node->nodes[a], size_x, size_y, size_z, depth); - } - } -} - -/* free all octal nodes recursively */ -static void free_metaball_octal_node(octal_node *node) -{ - int a; - for (a = 0; a < 8; a++) { - if (node->nodes[a] != NULL) free_metaball_octal_node(node->nodes[a]); - } - BLI_freelistN(&node->elems); - MEM_freeN(node); -} - -/* If scene include more than one MetaElem, then octree is used */ -static void init_metaball_octal_tree(PROCESS *process, int depth) -{ - struct octal_node *node; - ml_pointer *ml_p; - float size[3]; - int a; - - process->metaball_tree = MEM_mallocN(sizeof(octal_tree), "metaball_octal_tree"); - process->metaball_tree->first = node = MEM_mallocN(sizeof(octal_node), "metaball_octal_node"); - /* maximal depth of octree */ - process->metaball_tree->depth = depth; - - process->metaball_tree->neg = node->neg = 0; - process->metaball_tree->pos = node->pos = 0; - - BLI_listbase_clear(&node->elems); - node->count = 0; - - for (a = 0; a < 8; a++) - node->nodes[a] = NULL; - - node->x_min = node->y_min = node->z_min = FLT_MAX; - node->x_max = node->y_max = node->z_max = -FLT_MAX; - - /* size of octal tree scene */ - for (a = 0; a < process->totelem; a++) { - if (process->mainb[a]->bb->vec[0][0] < node->x_min) node->x_min = process->mainb[a]->bb->vec[0][0]; - if (process->mainb[a]->bb->vec[0][1] < node->y_min) node->y_min = process->mainb[a]->bb->vec[0][1]; - if (process->mainb[a]->bb->vec[0][2] < node->z_min) node->z_min = process->mainb[a]->bb->vec[0][2]; - - if (process->mainb[a]->bb->vec[6][0] > node->x_max) node->x_max = process->mainb[a]->bb->vec[6][0]; - if (process->mainb[a]->bb->vec[6][1] > node->y_max) node->y_max = process->mainb[a]->bb->vec[6][1]; - if (process->mainb[a]->bb->vec[6][2] > node->z_max) node->z_max = process->mainb[a]->bb->vec[6][2]; - - ml_p = MEM_mallocN(sizeof(ml_pointer), "ml_pointer"); - ml_p->ml = process->mainb[a]; - BLI_addtail(&node->elems, ml_p); - - if ((process->mainb[a]->flag & MB_NEGATIVE) == 0) { - /* number of positive MetaElem in scene */ - process->metaball_tree->pos++; - } - else { - /* number of negative MetaElem in scene */ - process->metaball_tree->neg++; - } - } - - /* size of first node */ - size[0] = node->x_max - node->x_min; - size[1] = node->y_max - node->y_min; - size[2] = node->z_max - node->z_min; - - /* first node is subdivided recursively */ - subdivide_metaball_octal_node(node, size[0], size[1], size[2], process->metaball_tree->depth); -} - -static void mball_count(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *basis) -{ - Scene *sce_iter = scene; - Base *base; - Object *ob, *bob = basis; - MetaElem *ml = NULL; - int basisnr, obnr; - char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; - SceneBaseIter iter; - - BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.'); - process->totelem = 0; - - BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL); - while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) { - if (ob->type == OB_MBALL) { - if (ob == bob) { - MetaBall *mb = ob->data; - - /* if bob object is in edit mode, then dynamic list of all MetaElems - * is stored in editelems */ - if (mb->editelems) ml = mb->editelems->first; - /* if bob object is in object mode */ - else ml = mb->elems.first; - } - else { - BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); - - /* object ob has to be in same "group" ... it means, that it has to have - * same base of its name */ - if (STREQ(obname, basisname)) { - MetaBall *mb = ob->data; - - /* if object is in edit mode, then dynamic list of all MetaElems - * is stored in editelems */ - if (mb->editelems) ml = mb->editelems->first; - /* if bob object is in object mode */ - else ml = mb->elems.first; - } - } - - for ( ; ml; ml = ml->next) { - if (!(ml->flag & MB_HIDE)) { - process->totelem++; - } - } - } - } -} - -void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase) -{ - MetaBall *mb; - DispList *dl; - int a, nr_cubes; - float *co, *no, totsize, width; - PROCESS process = {0}; - - mb = ob->data; - - mball_count(eval_ctx, &process, scene, ob); - - if (process.totelem == 0) return; - if ((eval_ctx->mode != DAG_EVAL_RENDER) && (mb->flag == MB_UPDATE_NEVER)) return; - if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_FAST) return; - - process.thresh = mb->thresh; - - /* total number of MetaElems (totelem) is precomputed in find_basis_mball() function */ - process.mainb = MEM_mallocN(sizeof(void *) * process.totelem, "mainb"); - - /* initialize all mainb (MetaElems) */ - totsize = init_meta(eval_ctx, &process, scene, ob); - - /* if scene includes more than one MetaElem, then octal tree optimization is used */ - if ((process.totelem > 1) && (process.totelem <= 64)) init_metaball_octal_tree(&process, 1); - if ((process.totelem > 64) && (process.totelem <= 128)) init_metaball_octal_tree(&process, 2); - if ((process.totelem > 128) && (process.totelem <= 512)) init_metaball_octal_tree(&process, 3); - if ((process.totelem > 512) && (process.totelem <= 1024)) init_metaball_octal_tree(&process, 4); - if (process.totelem > 1024) init_metaball_octal_tree(&process, 5); - - /* don't polygonize metaballs with too high resolution (base mball to small) - * note: Eps was 0.0001f but this was giving problems for blood animation for durian, using 0.00001f */ - if (process.metaball_tree) { - if (ob->size[0] <= 0.00001f * (process.metaball_tree->first->x_max - process.metaball_tree->first->x_min) || - ob->size[1] <= 0.00001f * (process.metaball_tree->first->y_max - process.metaball_tree->first->y_min) || - ob->size[2] <= 0.00001f * (process.metaball_tree->first->z_max - process.metaball_tree->first->z_min)) - { - new_pgn_element(&process, -1); /* free values created by init_meta */ - - MEM_freeN(process.mainb); - - /* free tree */ - free_metaball_octal_node(process.metaball_tree->first); - MEM_freeN(process.metaball_tree); - - return; - } - } - - /* width is size per polygonize cube */ - if (eval_ctx->mode == DAG_EVAL_RENDER) { - width = mb->rendersize; - } - else { - width = mb->wiresize; - if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_HALFRES) { - width *= 2; - } - } - /* nr_cubes is just for safety, minimum is totsize */ - nr_cubes = (int)(0.5f + totsize / width); - - /* init process */ - process.function = metaball; - process.size = width; - process.bounds = nr_cubes; - process.cubes = NULL; - process.delta = width / (float)(RES * RES); - - polygonize(&process, mb); - - MEM_freeN(process.mainb); - - /* free octal tree */ - if (process.totelem > 1) { - free_metaball_octal_node(process.metaball_tree->first); - MEM_freeN(process.metaball_tree); - process.metaball_tree = NULL; - } - - if (process.curindex) { - VERTEX *ptr = process.vertices.ptr; - - dl = MEM_callocN(sizeof(DispList), "mbaldisp"); - BLI_addtail(dispbase, dl); - dl->type = DL_INDEX4; - dl->nr = process.vertices.count; - dl->parts = process.curindex; - - dl->index = process.indices; - process.indices = NULL; - - a = process.vertices.count; - dl->verts = co = MEM_mallocN(sizeof(float[3]) * a, "mballverts"); - dl->nors = no = MEM_mallocN(sizeof(float[3]) * a, "mballnors"); - - for (a = 0; a < process.vertices.count; ptr++, a++, no += 3, co += 3) { - copy_v3_v3(co, ptr->co); - copy_v3_v3(no, ptr->no); - } - } - - freepolygonize(&process); -} - bool BKE_mball_minmax_ex(MetaBall *mb, float min[3], float max[3], float obmat[4][4], const short flag) { diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c new file mode 100644 index 00000000000..b1bef13c449 --- /dev/null +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -0,0 +1,1984 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): Jiri Hnidek . + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/mball_tessellate.c + * \ingroup bke + */ + +#include +#include +#include +#include +#include +#include +#include "MEM_guardedalloc.h" + +#include "DNA_material_types.h" +#include "DNA_object_types.h" +#include "DNA_meta_types.h" +#include "DNA_scene_types.h" + + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_global.h" +#include "BKE_main.h" + +/* #include "BKE_object.h" */ +#include "BKE_animsys.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_scene.h" +#include "BKE_library.h" +#include "BKE_displist.h" +#include "BKE_mball.h" +#include "BKE_object.h" +#include "BKE_material.h" + +/* Data types */ + +typedef struct vertex { /* surface vertex */ + float co[3]; /* position and surface normal */ + float no[3]; +} VERTEX; + +typedef struct vertices { /* list of vertices in polygonization */ + int count, max; /* # vertices, max # allowed */ + VERTEX *ptr; /* dynamically allocated */ +} VERTICES; + +typedef struct corner { /* corner of a cube */ + int i, j, k; /* (i, j, k) is index within lattice */ + float co[3], value; /* location and function value */ + struct corner *next; +} CORNER; + +typedef struct cube { /* partitioning cell (cube) */ + int i, j, k; /* lattice location of cube */ + CORNER *corners[8]; /* eight corners */ +} CUBE; + +typedef struct cubes { /* linked list of cubes acting as stack */ + CUBE cube; /* a single cube */ + struct cubes *next; /* remaining elements */ +} CUBES; + +typedef struct centerlist { /* list of cube locations */ + int i, j, k; /* cube location */ + struct centerlist *next; /* remaining elements */ +} CENTERLIST; + +typedef struct edgelist { /* list of edges */ + int i1, j1, k1, i2, j2, k2; /* edge corner ids */ + int vid; /* vertex id */ + struct edgelist *next; /* remaining elements */ +} EDGELIST; + +typedef struct intlist { /* list of integers */ + int i; /* an integer */ + struct intlist *next; /* remaining elements */ +} INTLIST; + +typedef struct intlists { /* list of list of integers */ + INTLIST *list; /* a list of integers */ + struct intlists *next; /* remaining elements */ +} INTLISTS; + +/* dividing scene using octal tree makes polygonisation faster */ +typedef struct ml_pointer { + struct ml_pointer *next, *prev; + struct MetaElem *ml; +} ml_pointer; + +typedef struct octal_node { + struct octal_node *nodes[8];/* children of current node */ + struct octal_node *parent; /* parent of current node */ + struct ListBase elems; /* ListBase of MetaElem pointers (ml_pointer) */ + float x_min, y_min, z_min; /* 1st border point */ + float x_max, y_max, z_max; /* 7th border point */ + float x, y, z; /* center of node */ + int pos, neg; /* number of positive and negative MetaElements in the node */ + int count; /* number of MetaElems, which belongs to the node */ +} octal_node; + +typedef struct octal_tree { + struct octal_node *first; /* first node */ + int pos, neg; /* number of positive and negative MetaElements in the scene */ + short depth; /* number of scene subdivision */ +} octal_tree; + +struct pgn_elements { + struct pgn_elements *next, *prev; + char *data; +}; + +typedef struct process { /* parameters, function, storage */ + /* ** old G_mb contents ** */ + float thresh; + int totelem; + MetaElem **mainb; + octal_tree *metaball_tree; + + /* ** old process contents ** */ + + /* what happens here? floats, I think. */ + /* float (*function)(void); */ /* implicit surface function */ + float (*function)(struct process *, float, float, float); + float size, delta; /* cube size, normal delta */ + int bounds; /* cube range within lattice */ + CUBES *cubes; /* active cubes */ + VERTICES vertices; /* surface vertices */ + CENTERLIST **centers; /* cube center hash table */ + CORNER **corners; /* corner value hash table */ + EDGELIST **edges; /* edge and vertex id hash table */ + + /* Runtime things */ + int *indices; + int totindex, curindex; + + int pgn_offset; + struct pgn_elements *pgn_current; + ListBase pgn_list; +} PROCESS; + +/* Forward declarations */ +static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2, MetaBall *mb); +static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k); +static CORNER *setcorner(PROCESS *process, int i, int j, int k); +static void converge(PROCESS *process, const float p1[3], const float p2[3], float v1, float v2, + float p[3], MetaBall *mb, int f); + + +/* ******************** ARITH ************************* */ + +/* BASED AT CODE (but mostly rewritten) : + * C code from the article + * "An Implicit Surface Polygonizer" + * by Jules Bloomenthal, jbloom@beauty.gmu.edu + * in "Graphics Gems IV", Academic Press, 1994 + * + * Authored by Jules Bloomenthal, Xerox PARC. + * Copyright (c) Xerox Corporation, 1991. All rights reserved. + * Permission is granted to reproduce, use and distribute this code for + * any and all purposes, provided that this notice appears in all copies. */ + +#define RES 12 /* # converge iterations */ + +#define L 0 /* left direction: -x, -i */ +#define R 1 /* right direction: +x, +i */ +#define B 2 /* bottom direction: -y, -j */ +#define T 3 /* top direction: +y, +j */ +#define N 4 /* near direction: -z, -k */ +#define F 5 /* far direction: +z, +k */ +#define LBN 0 /* left bottom near corner */ +#define LBF 1 /* left bottom far corner */ +#define LTN 2 /* left top near corner */ +#define LTF 3 /* left top far corner */ +#define RBN 4 /* right bottom near corner */ +#define RBF 5 /* right bottom far corner */ +#define RTN 6 /* right top near corner */ +#define RTF 7 /* right top far corner */ + +/* the LBN corner of cube (i, j, k), corresponds with location + * (i-0.5)*size, (j-0.5)*size, (k-0.5)*size) */ + +#define HASHBIT (5) +#define HASHSIZE (size_t)(1 << (3 * HASHBIT)) /*! < hash table size (32768) */ + +#define HASH(i, j, k) ((((( (i) & 31) << 5) | ( (j) & 31)) << 5) | ( (k) & 31) ) + +#define MB_BIT(i, bit) (((i) >> (bit)) & 1) +#define FLIP(i, bit) ((i) ^ 1 << (bit)) /* flip the given bit of i */ + + +/* **************** POLYGONIZATION ************************ */ + +static void calc_mballco(MetaElem *ml, float vec[3]) +{ + if (ml->mat) { + mul_m4_v3((float (*)[4])ml->mat, vec); + } +} + +static float densfunc(MetaElem *ball, float x, float y, float z) +{ + float dist2; + float dvec[3] = {x, y, z}; + + mul_m4_v3((float (*)[4])ball->imat, dvec); + + switch (ball->type) { + case MB_BALL: + /* do nothing */ + break; + case MB_TUBE: + if (dvec[0] > ball->expx) dvec[0] -= ball->expx; + else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; + else dvec[0] = 0.0; + break; + case MB_PLANE: + if (dvec[0] > ball->expx) dvec[0] -= ball->expx; + else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; + else dvec[0] = 0.0; + if (dvec[1] > ball->expy) dvec[1] -= ball->expy; + else if (dvec[1] < -ball->expy) dvec[1] += ball->expy; + else dvec[1] = 0.0; + break; + case MB_ELIPSOID: + dvec[0] /= ball->expx; + dvec[1] /= ball->expy; + dvec[2] /= ball->expz; + break; + case MB_CUBE: + if (dvec[0] > ball->expx) dvec[0] -= ball->expx; + else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; + else dvec[0] = 0.0; + + if (dvec[1] > ball->expy) dvec[1] -= ball->expy; + else if (dvec[1] < -ball->expy) dvec[1] += ball->expy; + else dvec[1] = 0.0; + + if (dvec[2] > ball->expz) dvec[2] -= ball->expz; + else if (dvec[2] < -ball->expz) dvec[2] += ball->expz; + else dvec[2] = 0.0; + break; + + /* *** deprecated, could be removed?, do-versioned at least *** */ + case MB_TUBEX: + if (dvec[0] > ball->len) dvec[0] -= ball->len; + else if (dvec[0] < -ball->len) dvec[0] += ball->len; + else dvec[0] = 0.0; + break; + case MB_TUBEY: + if (dvec[1] > ball->len) dvec[1] -= ball->len; + else if (dvec[1] < -ball->len) dvec[1] += ball->len; + else dvec[1] = 0.0; + break; + case MB_TUBEZ: + if (dvec[2] > ball->len) dvec[2] -= ball->len; + else if (dvec[2] < -ball->len) dvec[2] += ball->len; + else dvec[2] = 0.0; + break; + /* *** end deprecated *** */ + } + + dist2 = 1.0f - (len_squared_v3(dvec) / ball->rad2); + + if ((ball->flag & MB_NEGATIVE) == 0) { + return (dist2 < 0.0f) ? -0.5f : (ball->s * dist2 * dist2 * dist2) - 0.5f; + } + else { + return (dist2 < 0.0f) ? 0.5f : 0.5f - (ball->s * dist2 * dist2 * dist2); + } +} + +static octal_node *find_metaball_octal_node(octal_node *node, float x, float y, float z, short depth) +{ + if (!depth) return node; + + if (z < node->z) { + if (y < node->y) { + if (x < node->x) { + if (node->nodes[0]) + return find_metaball_octal_node(node->nodes[0], x, y, z, depth--); + else + return node; + } + else { + if (node->nodes[1]) + return find_metaball_octal_node(node->nodes[1], x, y, z, depth--); + else + return node; + } + } + else { + if (x < node->x) { + if (node->nodes[3]) + return find_metaball_octal_node(node->nodes[3], x, y, z, depth--); + else + return node; + } + else { + if (node->nodes[2]) + return find_metaball_octal_node(node->nodes[2], x, y, z, depth--); + else + return node; + } + } + } + else { + if (y < node->y) { + if (x < node->x) { + if (node->nodes[4]) + return find_metaball_octal_node(node->nodes[4], x, y, z, depth--); + else + return node; + } + else { + if (node->nodes[5]) + return find_metaball_octal_node(node->nodes[5], x, y, z, depth--); + else + return node; + } + } + else { + if (x < node->x) { + if (node->nodes[7]) + return find_metaball_octal_node(node->nodes[7], x, y, z, depth--); + else + return node; + } + else { + if (node->nodes[6]) + return find_metaball_octal_node(node->nodes[6], x, y, z, depth--); + else + return node; + } + } + } + + /* all cases accounted for */ + BLI_assert(0); +} + +static float metaball(PROCESS *process, float x, float y, float z) +/* float x, y, z; */ +{ + octal_tree *metaball_tree = process->metaball_tree; + struct octal_node *node; + struct ml_pointer *ml_p; + float dens = 0; + int a; + + if (process->totelem > 1) { + node = find_metaball_octal_node(metaball_tree->first, x, y, z, metaball_tree->depth); + if (node) { + for (ml_p = node->elems.first; ml_p; ml_p = ml_p->next) { + dens += densfunc(ml_p->ml, x, y, z); + } + + dens += -0.5f * (metaball_tree->pos - node->pos); + dens += 0.5f * (metaball_tree->neg - node->neg); + } + else { + for (a = 0; a < process->totelem; a++) { + dens += densfunc(process->mainb[a], x, y, z); + } + } + } + else { + dens += densfunc(process->mainb[0], x, y, z); + } + + return process->thresh - dens; +} + +/* ******************************************** */ + +static void accum_mballfaces(PROCESS *process, int i1, int i2, int i3, int i4) +{ + int *newi, *cur; + /* static int i = 0; I would like to delete altogether, but I don't dare to, yet */ + + if (process->totindex == process->curindex) { + process->totindex += 256; + newi = MEM_mallocN(4 * sizeof(int) * process->totindex, "vertindex"); + + if (process->indices) { + memcpy(newi, process->indices, 4 * sizeof(int) * (process->totindex - 256)); + MEM_freeN(process->indices); + } + process->indices = newi; + } + + cur = process->indices + 4 * process->curindex; + + /* displists now support array drawing, we treat tri's as fake quad */ + + cur[0] = i1; + cur[1] = i2; + cur[2] = i3; + if (i4 == 0) + cur[3] = i3; + else + cur[3] = i4; + + process->curindex++; + +} + +/* ******************* MEMORY MANAGEMENT *********************** */ +static void *new_pgn_element(PROCESS *process, int size) +{ + /* during polygonize 1000s of elements are allocated + * and never freed in between. Freeing only done at the end. + */ + int blocksize = 16384; + void *adr; + + if (size > 10000 || size == 0) { + printf("incorrect use of new_pgn_element\n"); + } + else if (size == -1) { + struct pgn_elements *cur = process->pgn_list.first; + while (cur) { + MEM_freeN(cur->data); + cur = cur->next; + } + BLI_freelistN(&process->pgn_list); + + return NULL; + } + + size = 4 * ( (size + 3) / 4); + + if (process->pgn_current) { + if (size + process->pgn_offset < blocksize) { + adr = (void *) (process->pgn_current->data + process->pgn_offset); + process->pgn_offset += size; + return adr; + } + } + + process->pgn_current = MEM_callocN(sizeof(struct pgn_elements), "newpgn"); + process->pgn_current->data = MEM_callocN(blocksize, "newpgn"); + BLI_addtail(&process->pgn_list, process->pgn_current); + + process->pgn_offset = size; + return process->pgn_current->data; +} + +static void freepolygonize(PROCESS *process) +{ + MEM_freeN(process->corners); + MEM_freeN(process->edges); + MEM_freeN(process->centers); + + new_pgn_element(process, -1); + + if (process->vertices.ptr) { + MEM_freeN(process->vertices.ptr); + } +} + +/**** Cubical Polygonization (optional) ****/ + +#define LB 0 /* left bottom edge */ +#define LT 1 /* left top edge */ +#define LN 2 /* left near edge */ +#define LF 3 /* left far edge */ +#define RB 4 /* right bottom edge */ +#define RT 5 /* right top edge */ +#define RN 6 /* right near edge */ +#define RF 7 /* right far edge */ +#define BN 8 /* bottom near edge */ +#define BF 9 /* bottom far edge */ +#define TN 10 /* top near edge */ +#define TF 11 /* top far edge */ + +static INTLISTS *cubetable[256]; + +/* edge: LB, LT, LN, LF, RB, RT, RN, RF, BN, BF, TN, TF */ +static int corner1[12] = { + LBN, LTN, LBN, LBF, RBN, RTN, RBN, RBF, LBN, LBF, LTN, LTF +}; +static int corner2[12] = { + LBF, LTF, LTN, LTF, RBF, RTF, RTN, RTF, RBN, RBF, RTN, RTF +}; +static int leftface[12] = { + B, L, L, F, R, T, N, R, N, B, T, F +}; +/* face on left when going corner1 to corner2 */ +static int rightface[12] = { + L, T, N, L, B, R, R, F, B, F, N, T +}; +/* face on right when going corner1 to corner2 */ + + +/* docube: triangulate the cube directly, without decomposition */ + +static void docube(PROCESS *process, CUBE *cube, MetaBall *mb) +{ + INTLISTS *polys; + CORNER *c1, *c2; + int i, index = 0, count, indexar[8]; + + for (i = 0; i < 8; i++) { + if (cube->corners[i]->value > 0.0f) { + index += (1 << i); + } + } + + for (polys = cubetable[index]; polys; polys = polys->next) { + INTLIST *edges; + + count = 0; + + for (edges = polys->list; edges; edges = edges->next) { + c1 = cube->corners[corner1[edges->i]]; + c2 = cube->corners[corner2[edges->i]]; + + indexar[count] = vertid(process, c1, c2, mb); + count++; + } + if (count > 2) { + switch (count) { + case 3: + accum_mballfaces(process, indexar[2], indexar[1], indexar[0], 0); + break; + case 4: + if (indexar[0] == 0) accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); + else accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); + break; + case 5: + if (indexar[0] == 0) accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); + else accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); + + accum_mballfaces(process, indexar[4], indexar[3], indexar[0], 0); + break; + case 6: + if (indexar[0] == 0) { + accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); + accum_mballfaces(process, indexar[0], indexar[5], indexar[4], indexar[3]); + } + else { + accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); + accum_mballfaces(process, indexar[5], indexar[4], indexar[3], indexar[0]); + } + break; + case 7: + if (indexar[0] == 0) { + accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); + accum_mballfaces(process, indexar[0], indexar[5], indexar[4], indexar[3]); + } + else { + accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); + accum_mballfaces(process, indexar[5], indexar[4], indexar[3], indexar[0]); + } + + accum_mballfaces(process, indexar[6], indexar[5], indexar[0], 0); + + break; + } + } + } +} + + +/* testface: given cube at lattice (i, j, k), and four corners of face, + * if surface crosses face, compute other four corners of adjacent cube + * and add new cube to cube stack */ + +static void testface(PROCESS *process, int i, int j, int k, CUBE *old, int bit, int c1, int c2, int c3, int c4) +{ + CUBE newc; + CUBES *oldcubes = process->cubes; + CORNER *corn1, *corn2, *corn3, *corn4; + int n, pos; + + corn1 = old->corners[c1]; + corn2 = old->corners[c2]; + corn3 = old->corners[c3]; + corn4 = old->corners[c4]; + + pos = corn1->value > 0.0f ? 1 : 0; + + /* test if no surface crossing */ + if ( (corn2->value > 0) == pos && (corn3->value > 0) == pos && (corn4->value > 0) == pos) return; + /* test if cube out of bounds */ + /*if ( abs(i) > p->bounds || abs(j) > p->bounds || abs(k) > p->bounds) return;*/ + /* test if already visited (always as last) */ + if (setcenter(process, process->centers, i, j, k)) { + return; + } + + /* create new cube and add cube to top of stack: */ + process->cubes = (CUBES *) new_pgn_element(process, sizeof(CUBES)); + process->cubes->next = oldcubes; + + newc.i = i; + newc.j = j; + newc.k = k; + for (n = 0; n < 8; n++) newc.corners[n] = NULL; + + newc.corners[FLIP(c1, bit)] = corn1; + newc.corners[FLIP(c2, bit)] = corn2; + newc.corners[FLIP(c3, bit)] = corn3; + newc.corners[FLIP(c4, bit)] = corn4; + + if (newc.corners[0] == NULL) newc.corners[0] = setcorner(process, i, j, k); + if (newc.corners[1] == NULL) newc.corners[1] = setcorner(process, i, j, k + 1); + if (newc.corners[2] == NULL) newc.corners[2] = setcorner(process, i, j + 1, k); + if (newc.corners[3] == NULL) newc.corners[3] = setcorner(process, i, j + 1, k + 1); + if (newc.corners[4] == NULL) newc.corners[4] = setcorner(process, i + 1, j, k); + if (newc.corners[5] == NULL) newc.corners[5] = setcorner(process, i + 1, j, k + 1); + if (newc.corners[6] == NULL) newc.corners[6] = setcorner(process, i + 1, j + 1, k); + if (newc.corners[7] == NULL) newc.corners[7] = setcorner(process, i + 1, j + 1, k + 1); + + process->cubes->cube = newc; +} + +/* setcorner: return corner with the given lattice location + * set (and cache) its function value */ + +static CORNER *setcorner(PROCESS *process, int i, int j, int k) +{ + /* for speed, do corner value caching here */ + CORNER *c; + int index; + + /* does corner exist? */ + index = HASH(i, j, k); + c = process->corners[index]; + + for (; c != NULL; c = c->next) { + if (c->i == i && c->j == j && c->k == k) { + return c; + } + } + + c = (CORNER *) new_pgn_element(process, sizeof(CORNER)); + + c->i = i; + c->co[0] = ((float)i - 0.5f) * process->size; + c->j = j; + c->co[1] = ((float)j - 0.5f) * process->size; + c->k = k; + c->co[2] = ((float)k - 0.5f) * process->size; + c->value = process->function(process, c->co[0], c->co[1], c->co[2]); + + c->next = process->corners[index]; + process->corners[index] = c; + + return c; +} + + +/* nextcwedge: return next clockwise edge from given edge around given face */ + +static int nextcwedge(int edge, int face) +{ + switch (edge) { + case LB: + return (face == L) ? LF : BN; + case LT: + return (face == L) ? LN : TF; + case LN: + return (face == L) ? LB : TN; + case LF: + return (face == L) ? LT : BF; + case RB: + return (face == R) ? RN : BF; + case RT: + return (face == R) ? RF : TN; + case RN: + return (face == R) ? RT : BN; + case RF: + return (face == R) ? RB : TF; + case BN: + return (face == B) ? RB : LN; + case BF: + return (face == B) ? LB : RF; + case TN: + return (face == T) ? LT : RN; + case TF: + return (face == T) ? RT : LF; + } + return 0; +} + + +/* otherface: return face adjoining edge that is not the given face */ + +static int otherface(int edge, int face) +{ + int other = leftface[edge]; + return face == other ? rightface[edge] : other; +} + + +/* makecubetable: create the 256 entry table for cubical polygonization */ + +static void makecubetable(void) +{ + static bool is_done = false; + int i, e, c, done[12], pos[8]; + + if (is_done) return; + is_done = true; + + for (i = 0; i < 256; i++) { + for (e = 0; e < 12; e++) done[e] = 0; + for (c = 0; c < 8; c++) pos[c] = MB_BIT(i, c); + for (e = 0; e < 12; e++) + if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) { + INTLIST *ints = NULL; + INTLISTS *lists = (INTLISTS *) MEM_callocN(sizeof(INTLISTS), "mball_intlist"); + int start = e, edge = e; + + /* get face that is to right of edge from pos to neg corner: */ + int face = pos[corner1[e]] ? rightface[e] : leftface[e]; + + while (1) { + edge = nextcwedge(edge, face); + done[edge] = 1; + if (pos[corner1[edge]] != pos[corner2[edge]]) { + INTLIST *tmp = ints; + + ints = (INTLIST *) MEM_callocN(sizeof(INTLIST), "mball_intlist"); + ints->i = edge; + ints->next = tmp; /* add edge to head of list */ + + if (edge == start) break; + face = otherface(edge, face); + } + } + lists->list = ints; /* add ints to head of table entry */ + lists->next = cubetable[i]; + cubetable[i] = lists; + } + } +} + +void BKE_mball_cubeTable_free(void) +{ + int i; + INTLISTS *lists, *nlists; + INTLIST *ints, *nints; + + for (i = 0; i < 256; i++) { + lists = cubetable[i]; + while (lists) { + nlists = lists->next; + + ints = lists->list; + while (ints) { + nints = ints->next; + MEM_freeN(ints); + ints = nints; + } + + MEM_freeN(lists); + lists = nlists; + } + cubetable[i] = NULL; + } +} + +/**** Storage ****/ + +/* setcenter: set (i, j, k) entry of table[] + * return 1 if already set; otherwise, set and return 0 */ + +static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k) +{ + int index; + CENTERLIST *newc, *l, *q; + + index = HASH(i, j, k); + q = table[index]; + + for (l = q; l != NULL; l = l->next) { + if (l->i == i && l->j == j && l->k == k) return 1; + } + + newc = (CENTERLIST *) new_pgn_element(process, sizeof(CENTERLIST)); + newc->i = i; + newc->j = j; + newc->k = k; + newc->next = q; + table[index] = newc; + + return 0; +} + + +/* setedge: set vertex id for edge */ + +static void setedge(PROCESS *process, + EDGELIST *table[], + int i1, int j1, + int k1, int i2, + int j2, int k2, + int vid) +{ + unsigned int index; + EDGELIST *newe; + + if (i1 > i2 || (i1 == i2 && (j1 > j2 || (j1 == j2 && k1 > k2)))) { + int t = i1; + i1 = i2; + i2 = t; + t = j1; + j1 = j2; + j2 = t; + t = k1; + k1 = k2; + k2 = t; + } + index = HASH(i1, j1, k1) + HASH(i2, j2, k2); + newe = (EDGELIST *) new_pgn_element(process, sizeof(EDGELIST)); + newe->i1 = i1; + newe->j1 = j1; + newe->k1 = k1; + newe->i2 = i2; + newe->j2 = j2; + newe->k2 = k2; + newe->vid = vid; + newe->next = table[index]; + table[index] = newe; +} + + +/* getedge: return vertex id for edge; return -1 if not set */ + +static int getedge(EDGELIST *table[], + int i1, int j1, int k1, + int i2, int j2, int k2) +{ + EDGELIST *q; + + if (i1 > i2 || (i1 == i2 && (j1 > j2 || (j1 == j2 && k1 > k2)))) { + int t = i1; + i1 = i2; + i2 = t; + t = j1; + j1 = j2; + j2 = t; + t = k1; + k1 = k2; + k2 = t; + } + q = table[HASH(i1, j1, k1) + HASH(i2, j2, k2)]; + for (; q != NULL; q = q->next) { + if (q->i1 == i1 && q->j1 == j1 && q->k1 == k1 && + q->i2 == i2 && q->j2 == j2 && q->k2 == k2) + { + return q->vid; + } + } + return -1; +} + + +/**** Vertices ****/ + +#undef R + + + +/* vertid: return index for vertex on edge: + * c1->value and c2->value are presumed of different sign + * return saved index if any; else compute vertex and save */ + +/* addtovertices: add v to sequence of vertices */ + +static void addtovertices(VERTICES *vertices, VERTEX v) +{ + if (vertices->count == vertices->max) { + int i; + VERTEX *newv; + vertices->max = vertices->count == 0 ? 10 : 2 * vertices->count; + newv = (VERTEX *) MEM_callocN(vertices->max * sizeof(VERTEX), "addtovertices"); + + for (i = 0; i < vertices->count; i++) newv[i] = vertices->ptr[i]; + + if (vertices->ptr != NULL) MEM_freeN(vertices->ptr); + vertices->ptr = newv; + } + vertices->ptr[vertices->count++] = v; +} + +/* vnormal: compute unit length surface normal at point */ + +static void vnormal(PROCESS *process, const float point[3], float r_no[3]) +{ + const float delta = 0.2f * process->delta; + const float f = process->function(process, point[0], point[1], point[2]); + + r_no[0] = process->function(process, point[0] + delta, point[1], point[2]) - f; + r_no[1] = process->function(process, point[0], point[1] + delta, point[2]) - f; + r_no[2] = process->function(process, point[0], point[1], point[2] + delta) - f; + +#if 1 + normalize_v3(r_no); +#else + f = normalize_v3(r_no); + + if (0) { + float tvec[3]; + + delta *= 2.0f; + + f = process->function(process, point[0], point[1], point[2]); + + tvec[0] = process->function(process, point[0] + delta, point[1], point[2]) - f; + tvec[1] = process->function(process, point[0], point[1] + delta, point[2]) - f; + tvec[2] = process->function(process, point[0], point[1], point[2] + delta) - f; + + if (normalize_v3(tvec) != 0.0f) { + add_v3_v3(r_no, tvec); + normalize_v3(r_no); + } + } +#endif +} + + +static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2, MetaBall *mb) +{ + VERTEX v; + int vid = getedge(process->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k); + + if (vid != -1) { + return vid; /* previously computed */ + } + + converge(process, c1->co, c2->co, c1->value, c2->value, v.co, mb, 1); /* position */ + vnormal(process, v.co, v.no); + + addtovertices(&process->vertices, v); /* save vertex */ + vid = process->vertices.count - 1; + setedge(process, process->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid); + + return vid; +} + + +/* converge: from two points of differing sign, converge to zero crossing */ +/* watch it: p1 and p2 are used to calculate */ +static void converge(PROCESS *process, const float p1[3], const float p2[3], float v1, float v2, + float p[3], MetaBall *mb, int f) +{ + int i = 0; + float pos[3], neg[3]; + float positive = 0.0f, negative = 0.0f; + float dvec[3]; + + if (v1 < 0) { + copy_v3_v3(pos, p2); + copy_v3_v3(neg, p1); + positive = v2; + negative = v1; + } + else { + copy_v3_v3(pos, p1); + copy_v3_v3(neg, p2); + positive = v1; + negative = v2; + } + + sub_v3_v3v3(dvec, pos, neg); + +/* Approximation by linear interpolation is faster then binary subdivision, + * but it results sometimes (mb->thresh < 0.2) into the strange results */ + if ((mb->thresh > 0.2f) && (f == 1)) { + if ((dvec[1] == 0.0f) && (dvec[2] == 0.0f)) { + p[0] = neg[0] - negative * dvec[0] / (positive - negative); + p[1] = neg[1]; + p[2] = neg[2]; + return; + } + if ((dvec[0] == 0.0f) && (dvec[2] == 0.0f)) { + p[0] = neg[0]; + p[1] = neg[1] - negative * dvec[1] / (positive - negative); + p[2] = neg[2]; + return; + } + if ((dvec[0] == 0.0f) && (dvec[1] == 0.0f)) { + p[0] = neg[0]; + p[1] = neg[1]; + p[2] = neg[2] - negative * dvec[2] / (positive - negative); + return; + } + } + + if ((dvec[1] == 0.0f) && (dvec[2] == 0.0f)) { + p[1] = neg[1]; + p[2] = neg[2]; + while (1) { + if (i++ == RES) return; + p[0] = 0.5f * (pos[0] + neg[0]); + if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[0] = p[0]; + else neg[0] = p[0]; + } + } + + if ((dvec[0] == 0.0f) && (dvec[2] == 0.0f)) { + p[0] = neg[0]; + p[2] = neg[2]; + while (1) { + if (i++ == RES) return; + p[1] = 0.5f * (pos[1] + neg[1]); + if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[1] = p[1]; + else neg[1] = p[1]; + } + } + + if ((dvec[0] == 0.0f) && (dvec[1] == 0.0f)) { + p[0] = neg[0]; + p[1] = neg[1]; + while (1) { + if (i++ == RES) return; + p[2] = 0.5f * (pos[2] + neg[2]); + if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[2] = p[2]; + else neg[2] = p[2]; + } + } + + /* This is necessary to find start point */ + while (1) { + mid_v3_v3v3(&p[0], pos, neg); + + if (i++ == RES) { + return; + } + + if ((process->function(process, p[0], p[1], p[2])) > 0.0f) { + copy_v3_v3(pos, &p[0]); + } + else { + copy_v3_v3(neg, &p[0]); + } + } +} + +/* ************************************** */ +static void add_cube(PROCESS *process, int i, int j, int k, int count) +{ + CUBES *ncube; + int n; + int a, b, c; + + /* hmmm, not only one, but eight cube will be added on the stack + * ... */ + for (a = i - 1; a < i + count; a++) + for (b = j - 1; b < j + count; b++) + for (c = k - 1; c < k + count; c++) { + /* test if cube has been found before */ + if (setcenter(process, process->centers, a, b, c) == 0) { + /* push cube on stack: */ + ncube = (CUBES *) new_pgn_element(process, sizeof(CUBES)); + ncube->next = process->cubes; + process->cubes = ncube; + + ncube->cube.i = a; + ncube->cube.j = b; + ncube->cube.k = c; + + /* set corners of initial cube: */ + for (n = 0; n < 8; n++) + ncube->cube.corners[n] = setcorner(process, a + MB_BIT(n, 2), b + MB_BIT(n, 1), c + MB_BIT(n, 0)); + } + } +} + + +static void find_first_points(PROCESS *process, MetaBall *mb, int a) +{ + MetaElem *ml; + float f; + + ml = process->mainb[a]; + f = 1.0f - (mb->thresh / ml->s); + + /* Skip, when Stiffness of MetaElement is too small ... MetaElement can't be + * visible alone ... but still can influence others MetaElements :-) */ + if (f > 0.0f) { + float IN[3] = {0.0f}, OUT[3] = {0.0f}, in[3] = {0.0f}, out[3]; + int i, j, k, c_i, c_j, c_k; + int index[3] = {1, 0, -1}; + float in_v /*, out_v*/; + float workp[3]; + float dvec[3]; + float tmp_v, workp_v, max_len_sq, nx, ny, nz, max_dim; + + calc_mballco(ml, in); + in_v = process->function(process, in[0], in[1], in[2]); + + for (i = 0; i < 3; i++) { + switch (ml->type) { + case MB_BALL: + OUT[0] = out[0] = IN[0] + index[i] * ml->rad; + break; + case MB_TUBE: + case MB_PLANE: + case MB_ELIPSOID: + case MB_CUBE: + OUT[0] = out[0] = IN[0] + index[i] * (ml->expx + ml->rad); + break; + } + + for (j = 0; j < 3; j++) { + switch (ml->type) { + case MB_BALL: + OUT[1] = out[1] = IN[1] + index[j] * ml->rad; + break; + case MB_TUBE: + case MB_PLANE: + case MB_ELIPSOID: + case MB_CUBE: + OUT[1] = out[1] = IN[1] + index[j] * (ml->expy + ml->rad); + break; + } + + for (k = 0; k < 3; k++) { + out[0] = OUT[0]; + out[1] = OUT[1]; + switch (ml->type) { + case MB_BALL: + case MB_TUBE: + case MB_PLANE: + out[2] = IN[2] + index[k] * ml->rad; + break; + case MB_ELIPSOID: + case MB_CUBE: + out[2] = IN[2] + index[k] * (ml->expz + ml->rad); + break; + } + + calc_mballco(ml, out); + + /*out_v = process->function(out[0], out[1], out[2]);*/ /*UNUSED*/ + + /* find "first points" on Implicit Surface of MetaElemnt ml */ + copy_v3_v3(workp, in); + workp_v = in_v; + max_len_sq = len_squared_v3v3(out, in); + + nx = fabsf((out[0] - in[0]) / process->size); + ny = fabsf((out[1] - in[1]) / process->size); + nz = fabsf((out[2] - in[2]) / process->size); + + max_dim = max_fff(nx, ny, nz); + if (max_dim != 0.0f) { + float len_sq = 0.0f; + + dvec[0] = (out[0] - in[0]) / max_dim; + dvec[1] = (out[1] - in[1]) / max_dim; + dvec[2] = (out[2] - in[2]) / max_dim; + + while (len_sq <= max_len_sq) { + add_v3_v3(workp, dvec); + + /* compute value of implicite function */ + tmp_v = process->function(process, workp[0], workp[1], workp[2]); + /* add cube to the stack, when value of implicite function crosses zero value */ + if ((tmp_v < 0.0f && workp_v >= 0.0f) || (tmp_v > 0.0f && workp_v <= 0.0f)) { + + /* indexes of CUBE, which includes "first point" */ + c_i = (int)floor(workp[0] / process->size); + c_j = (int)floor(workp[1] / process->size); + c_k = (int)floor(workp[2] / process->size); + + /* add CUBE (with indexes c_i, c_j, c_k) to the stack, + * this cube includes found point of Implicit Surface */ + if ((ml->flag & MB_NEGATIVE) == 0) { + add_cube(process, c_i, c_j, c_k, 1); + } + else { + add_cube(process, c_i, c_j, c_k, 2); + } + } + len_sq = len_squared_v3v3(workp, in); + workp_v = tmp_v; + + } + } + } + } + } + } +} + +static void polygonize(PROCESS *process, MetaBall *mb) +{ + CUBE c; + int a; + + process->vertices.count = process->vertices.max = 0; + process->vertices.ptr = NULL; + + /* allocate hash tables and build cube polygon table: */ + process->centers = MEM_callocN(HASHSIZE * sizeof(CENTERLIST *), "mbproc->centers"); + process->corners = MEM_callocN(HASHSIZE * sizeof(CORNER *), "mbproc->corners"); + process->edges = MEM_callocN(2 * HASHSIZE * sizeof(EDGELIST *), "mbproc->edges"); + makecubetable(); + + for (a = 0; a < process->totelem; a++) { + + /* try to find 8 points on the surface for each MetaElem */ + find_first_points(process, mb, a); + } + + /* polygonize all MetaElems of current MetaBall */ + while (process->cubes != NULL) { /* process active cubes till none left */ + c = process->cubes->cube; + + /* polygonize the cube directly: */ + docube(process, &c, mb); + + /* pop current cube from stack */ + process->cubes = process->cubes->next; + + /* test six face directions, maybe add to stack: */ + testface(process, c.i - 1, c.j, c.k, &c, 2, LBN, LBF, LTN, LTF); + testface(process, c.i + 1, c.j, c.k, &c, 2, RBN, RBF, RTN, RTF); + testface(process, c.i, c.j - 1, c.k, &c, 1, LBN, LBF, RBN, RBF); + testface(process, c.i, c.j + 1, c.k, &c, 1, LTN, LTF, RTN, RTF); + testface(process, c.i, c.j, c.k - 1, &c, 0, LBN, LTN, RBN, RTN); + testface(process, c.i, c.j, c.k + 1, &c, 0, LBF, LTF, RBF, RTF); + } +} + +static float init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob) /* return totsize */ +{ + Scene *sce_iter = scene; + Base *base; + Object *bob; + MetaBall *mb; + MetaElem *ml; + float size, totsize, obinv[4][4], obmat[4][4], vec[3]; + //float max = 0.0f; + int a, obnr, zero_size = 0; + char obname[MAX_ID_NAME]; + SceneBaseIter iter; + + copy_m4_m4(obmat, ob->obmat); /* to cope with duplicators from BKE_scene_base_iter_next */ + invert_m4_m4(obinv, ob->obmat); + a = 0; + + BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); + + /* make main array */ + BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL); + while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &bob)) { + + if (bob->type == OB_MBALL) { + zero_size = 0; + ml = NULL; + + if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) { + mb = ob->data; + + if (mb->editelems) ml = mb->editelems->first; + else ml = mb->elems.first; + } + else { + char name[MAX_ID_NAME]; + int nr; + + BLI_split_name_num(name, &nr, bob->id.name + 2, '.'); + if (STREQ(obname, name)) { + mb = bob->data; + + if (mb->editelems) ml = mb->editelems->first; + else ml = mb->elems.first; + } + } + + /* when metaball object has zero scale, then MetaElem to this MetaBall + * will not be put to mainb array */ + if (has_zero_axis_m4(bob->obmat)) { + zero_size = 1; + } + else if (bob->parent) { + struct Object *pob = bob->parent; + while (pob) { + if (has_zero_axis_m4(pob->obmat)) { + zero_size = 1; + break; + } + pob = pob->parent; + } + } + + if (zero_size) { + unsigned int ml_count = 0; + while (ml) { + ml_count++; + ml = ml->next; + } + process->totelem -= ml_count; + } + else { + while (ml) { + if (!(ml->flag & MB_HIDE)) { + int i; + float temp1[4][4], temp2[4][4], temp3[4][4]; + float (*mat)[4] = NULL, (*imat)[4] = NULL; + float max_x, max_y, max_z, min_x, min_y, min_z; + float expx, expy, expz; + + max_x = max_y = max_z = -3.4e38; + min_x = min_y = min_z = 3.4e38; + + /* too big stiffness seems only ugly due to linear interpolation + * no need to have possibility for too big stiffness */ + if (ml->s > 10.0f) ml->s = 10.0f; + + /* Rotation of MetaElem is stored in quat */ + quat_to_mat4(temp3, ml->quat); + + /* Translation of MetaElem */ + unit_m4(temp2); + temp2[3][0] = ml->x; + temp2[3][1] = ml->y; + temp2[3][2] = ml->z; + + mul_m4_m4m4(temp1, temp2, temp3); + + /* make a copy because of duplicates */ + process->mainb[a] = new_pgn_element(process, sizeof(MetaElem)); + *(process->mainb[a]) = *ml; + process->mainb[a]->bb = new_pgn_element(process, sizeof(BoundBox)); + + mat = new_pgn_element(process, 4 * 4 * sizeof(float)); + imat = new_pgn_element(process, 4 * 4 * sizeof(float)); + + /* mat is the matrix to transform from mball into the basis-mball */ + invert_m4_m4(obinv, obmat); + mul_m4_m4m4(temp2, obinv, bob->obmat); + /* MetaBall transformation */ + mul_m4_m4m4(mat, temp2, temp1); + + invert_m4_m4(imat, mat); + + process->mainb[a]->rad2 = ml->rad * ml->rad; + + process->mainb[a]->mat = (float *) mat; + process->mainb[a]->imat = (float *) imat; + + if (!MB_TYPE_SIZE_SQUARED(ml->type)) { + expx = ml->expx; + expy = ml->expy; + expz = ml->expz; + } + else { + expx = ml->expx * ml->expx; + expy = ml->expy * ml->expy; + expz = ml->expz * ml->expz; + } + + /* untransformed Bounding Box of MetaElem */ + /* TODO, its possible the elem type has been changed and the exp* values can use a fallback */ + copy_v3_fl3(process->mainb[a]->bb->vec[0], -expx, -expy, -expz); /* 0 */ + copy_v3_fl3(process->mainb[a]->bb->vec[1], +expx, -expy, -expz); /* 1 */ + copy_v3_fl3(process->mainb[a]->bb->vec[2], +expx, +expy, -expz); /* 2 */ + copy_v3_fl3(process->mainb[a]->bb->vec[3], -expx, +expy, -expz); /* 3 */ + copy_v3_fl3(process->mainb[a]->bb->vec[4], -expx, -expy, +expz); /* 4 */ + copy_v3_fl3(process->mainb[a]->bb->vec[5], +expx, -expy, +expz); /* 5 */ + copy_v3_fl3(process->mainb[a]->bb->vec[6], +expx, +expy, +expz); /* 6 */ + copy_v3_fl3(process->mainb[a]->bb->vec[7], -expx, +expy, +expz); /* 7 */ + + /* transformation of Metalem bb */ + for (i = 0; i < 8; i++) + mul_m4_v3((float (*)[4])mat, process->mainb[a]->bb->vec[i]); + + /* find max and min of transformed bb */ + for (i = 0; i < 8; i++) { + /* find maximums */ + if (process->mainb[a]->bb->vec[i][0] > max_x) max_x = process->mainb[a]->bb->vec[i][0]; + if (process->mainb[a]->bb->vec[i][1] > max_y) max_y = process->mainb[a]->bb->vec[i][1]; + if (process->mainb[a]->bb->vec[i][2] > max_z) max_z = process->mainb[a]->bb->vec[i][2]; + /* find minimums */ + if (process->mainb[a]->bb->vec[i][0] < min_x) min_x = process->mainb[a]->bb->vec[i][0]; + if (process->mainb[a]->bb->vec[i][1] < min_y) min_y = process->mainb[a]->bb->vec[i][1]; + if (process->mainb[a]->bb->vec[i][2] < min_z) min_z = process->mainb[a]->bb->vec[i][2]; + } + + /* create "new" bb, only point 0 and 6, which are + * necessary for octal tree filling */ + process->mainb[a]->bb->vec[0][0] = min_x - ml->rad; + process->mainb[a]->bb->vec[0][1] = min_y - ml->rad; + process->mainb[a]->bb->vec[0][2] = min_z - ml->rad; + + process->mainb[a]->bb->vec[6][0] = max_x + ml->rad; + process->mainb[a]->bb->vec[6][1] = max_y + ml->rad; + process->mainb[a]->bb->vec[6][2] = max_z + ml->rad; + + a++; + } + ml = ml->next; + } + } + } + } + + + /* totsize (= 'manhattan' radius) */ + totsize = 0.0; + for (a = 0; a < process->totelem; a++) { + + vec[0] = process->mainb[a]->x + process->mainb[a]->rad + process->mainb[a]->expx; + vec[1] = process->mainb[a]->y + process->mainb[a]->rad + process->mainb[a]->expy; + vec[2] = process->mainb[a]->z + process->mainb[a]->rad + process->mainb[a]->expz; + + calc_mballco(process->mainb[a], vec); + + size = fabsf(vec[0]); + if (size > totsize) totsize = size; + size = fabsf(vec[1]); + if (size > totsize) totsize = size; + size = fabsf(vec[2]); + if (size > totsize) totsize = size; + + vec[0] = process->mainb[a]->x - process->mainb[a]->rad; + vec[1] = process->mainb[a]->y - process->mainb[a]->rad; + vec[2] = process->mainb[a]->z - process->mainb[a]->rad; + + calc_mballco(process->mainb[a], vec); + + size = fabsf(vec[0]); + if (size > totsize) totsize = size; + size = fabsf(vec[1]); + if (size > totsize) totsize = size; + size = fabsf(vec[2]); + if (size > totsize) totsize = size; + } + + for (a = 0; a < process->totelem; a++) { + process->thresh += densfunc(process->mainb[a], 2.0f * totsize, 2.0f * totsize, 2.0f * totsize); + } + + return totsize; +} + +/* if MetaElem lies in node, then node includes MetaElem pointer (ml_p) + * pointing at MetaElem (ml) + */ +static void fill_metaball_octal_node(octal_node *node, MetaElem *ml, short i) +{ + ml_pointer *ml_p; + + ml_p = MEM_mallocN(sizeof(ml_pointer), "ml_pointer"); + ml_p->ml = ml; + BLI_addtail(&(node->nodes[i]->elems), ml_p); + node->count++; + + if ((ml->flag & MB_NEGATIVE) == 0) { + node->nodes[i]->pos++; + } + else { + node->nodes[i]->neg++; + } +} + +/* Node is subdivided as is illustrated on the following figure: + * + * +------+------+ + * / / /| + * +------+------+ | + * / / /| + + * +------+------+ |/| + * | | | + | + * | | |/| + + * +------+------+ |/ + * | | | + + * | | |/ + * +------+------+ + * + */ +static void subdivide_metaball_octal_node(octal_node *node, float size_x, float size_y, float size_z, short depth) +{ + MetaElem *ml; + ml_pointer *ml_p; + float x, y, z; + int a, i; + + /* create new nodes */ + for (a = 0; a < 8; a++) { + node->nodes[a] = MEM_mallocN(sizeof(octal_node), "octal_node"); + for (i = 0; i < 8; i++) + node->nodes[a]->nodes[i] = NULL; + node->nodes[a]->parent = node; + BLI_listbase_clear(&node->nodes[a]->elems); + node->nodes[a]->count = 0; + node->nodes[a]->neg = 0; + node->nodes[a]->pos = 0; + } + + size_x /= 2; + size_y /= 2; + size_z /= 2; + + /* center of node */ + node->x = x = node->x_min + size_x; + node->y = y = node->y_min + size_y; + node->z = z = node->z_min + size_z; + + /* setting up of border points of new nodes */ + node->nodes[0]->x_min = node->x_min; + node->nodes[0]->y_min = node->y_min; + node->nodes[0]->z_min = node->z_min; + node->nodes[0]->x = node->nodes[0]->x_min + size_x / 2; + node->nodes[0]->y = node->nodes[0]->y_min + size_y / 2; + node->nodes[0]->z = node->nodes[0]->z_min + size_z / 2; + + node->nodes[1]->x_min = x; + node->nodes[1]->y_min = node->y_min; + node->nodes[1]->z_min = node->z_min; + node->nodes[1]->x = node->nodes[1]->x_min + size_x / 2; + node->nodes[1]->y = node->nodes[1]->y_min + size_y / 2; + node->nodes[1]->z = node->nodes[1]->z_min + size_z / 2; + + node->nodes[2]->x_min = x; + node->nodes[2]->y_min = y; + node->nodes[2]->z_min = node->z_min; + node->nodes[2]->x = node->nodes[2]->x_min + size_x / 2; + node->nodes[2]->y = node->nodes[2]->y_min + size_y / 2; + node->nodes[2]->z = node->nodes[2]->z_min + size_z / 2; + + node->nodes[3]->x_min = node->x_min; + node->nodes[3]->y_min = y; + node->nodes[3]->z_min = node->z_min; + node->nodes[3]->x = node->nodes[3]->x_min + size_x / 2; + node->nodes[3]->y = node->nodes[3]->y_min + size_y / 2; + node->nodes[3]->z = node->nodes[3]->z_min + size_z / 2; + + node->nodes[4]->x_min = node->x_min; + node->nodes[4]->y_min = node->y_min; + node->nodes[4]->z_min = z; + node->nodes[4]->x = node->nodes[4]->x_min + size_x / 2; + node->nodes[4]->y = node->nodes[4]->y_min + size_y / 2; + node->nodes[4]->z = node->nodes[4]->z_min + size_z / 2; + + node->nodes[5]->x_min = x; + node->nodes[5]->y_min = node->y_min; + node->nodes[5]->z_min = z; + node->nodes[5]->x = node->nodes[5]->x_min + size_x / 2; + node->nodes[5]->y = node->nodes[5]->y_min + size_y / 2; + node->nodes[5]->z = node->nodes[5]->z_min + size_z / 2; + + node->nodes[6]->x_min = x; + node->nodes[6]->y_min = y; + node->nodes[6]->z_min = z; + node->nodes[6]->x = node->nodes[6]->x_min + size_x / 2; + node->nodes[6]->y = node->nodes[6]->y_min + size_y / 2; + node->nodes[6]->z = node->nodes[6]->z_min + size_z / 2; + + node->nodes[7]->x_min = node->x_min; + node->nodes[7]->y_min = y; + node->nodes[7]->z_min = z; + node->nodes[7]->x = node->nodes[7]->x_min + size_x / 2; + node->nodes[7]->y = node->nodes[7]->y_min + size_y / 2; + node->nodes[7]->z = node->nodes[7]->z_min + size_z / 2; + + ml_p = node->elems.first; + + /* setting up references of MetaElems for new nodes */ + while (ml_p) { + ml = ml_p->ml; + if (ml->bb->vec[0][2] < z) { + if (ml->bb->vec[0][1] < y) { + /* vec[0][0] lies in first octant */ + if (ml->bb->vec[0][0] < x) { + /* ml belongs to the (0)1st node */ + fill_metaball_octal_node(node, ml, 0); + + /* ml belongs to the (3)4th node */ + if (ml->bb->vec[6][1] >= y) { + fill_metaball_octal_node(node, ml, 3); + + /* ml belongs to the (7)8th node */ + if (ml->bb->vec[6][2] >= z) { + fill_metaball_octal_node(node, ml, 7); + } + } + + /* ml belongs to the (1)2nd node */ + if (ml->bb->vec[6][0] >= x) { + fill_metaball_octal_node(node, ml, 1); + + /* ml belongs to the (5)6th node */ + if (ml->bb->vec[6][2] >= z) { + fill_metaball_octal_node(node, ml, 5); + } + } + + /* ml belongs to the (2)3th node */ + if ((ml->bb->vec[6][0] >= x) && (ml->bb->vec[6][1] >= y)) { + fill_metaball_octal_node(node, ml, 2); + + /* ml belong to the (6)7th node */ + if (ml->bb->vec[6][2] >= z) { + fill_metaball_octal_node(node, ml, 6); + } + + } + + /* ml belongs to the (4)5th node too */ + if (ml->bb->vec[6][2] >= z) { + fill_metaball_octal_node(node, ml, 4); + } + + + + } + /* vec[0][0] is in the (1)second octant */ + else { + /* ml belong to the (1)2nd node */ + fill_metaball_octal_node(node, ml, 1); + + /* ml belongs to the (2)3th node */ + if (ml->bb->vec[6][1] >= y) { + fill_metaball_octal_node(node, ml, 2); + + /* ml belongs to the (6)7th node */ + if (ml->bb->vec[6][2] >= z) { + fill_metaball_octal_node(node, ml, 6); + } + + } + + /* ml belongs to the (5)6th node */ + if (ml->bb->vec[6][2] >= z) { + fill_metaball_octal_node(node, ml, 5); + } + } + } + else { + /* vec[0][0] is in the (3)4th octant */ + if (ml->bb->vec[0][0] < x) { + /* ml belongs to the (3)4nd node */ + fill_metaball_octal_node(node, ml, 3); + + /* ml belongs to the (7)8th node */ + if (ml->bb->vec[6][2] >= z) { + fill_metaball_octal_node(node, ml, 7); + } + + + /* ml belongs to the (2)3th node */ + if (ml->bb->vec[6][0] >= x) { + fill_metaball_octal_node(node, ml, 2); + + /* ml belongs to the (6)7th node */ + if (ml->bb->vec[6][2] >= z) { + fill_metaball_octal_node(node, ml, 6); + } + } + } + + } + + /* vec[0][0] is in the (2)3th octant */ + if ((ml->bb->vec[0][0] >= x) && (ml->bb->vec[0][1] >= y)) { + /* ml belongs to the (2)3th node */ + fill_metaball_octal_node(node, ml, 2); + + /* ml belongs to the (6)7th node */ + if (ml->bb->vec[6][2] >= z) { + fill_metaball_octal_node(node, ml, 6); + } + } + } + else { + if (ml->bb->vec[0][1] < y) { + /* vec[0][0] lies in (4)5th octant */ + if (ml->bb->vec[0][0] < x) { + /* ml belongs to the (4)5th node */ + fill_metaball_octal_node(node, ml, 4); + + if (ml->bb->vec[6][0] >= x) { + fill_metaball_octal_node(node, ml, 5); + } + + if (ml->bb->vec[6][1] >= y) { + fill_metaball_octal_node(node, ml, 7); + } + + if ((ml->bb->vec[6][0] >= x) && (ml->bb->vec[6][1] >= y)) { + fill_metaball_octal_node(node, ml, 6); + } + } + /* vec[0][0] lies in (5)6th octant */ + else { + fill_metaball_octal_node(node, ml, 5); + + if (ml->bb->vec[6][1] >= y) { + fill_metaball_octal_node(node, ml, 6); + } + } + } + else { + /* vec[0][0] lies in (7)8th octant */ + if (ml->bb->vec[0][0] < x) { + fill_metaball_octal_node(node, ml, 7); + + if (ml->bb->vec[6][0] >= x) { + fill_metaball_octal_node(node, ml, 6); + } + } + + } + + /* vec[0][0] lies in (6)7th octant */ + if ((ml->bb->vec[0][0] >= x) && (ml->bb->vec[0][1] >= y)) { + fill_metaball_octal_node(node, ml, 6); + } + } + ml_p = ml_p->next; + } + + /* free references of MetaElems for curent node (it is not needed anymore) */ + BLI_freelistN(&node->elems); + + depth--; + + if (depth > 0) { + for (a = 0; a < 8; a++) { + if (node->nodes[a]->count > 0) /* if node is not empty, then it is subdivided */ + subdivide_metaball_octal_node(node->nodes[a], size_x, size_y, size_z, depth); + } + } +} + +/* free all octal nodes recursively */ +static void free_metaball_octal_node(octal_node *node) +{ + int a; + for (a = 0; a < 8; a++) { + if (node->nodes[a] != NULL) free_metaball_octal_node(node->nodes[a]); + } + BLI_freelistN(&node->elems); + MEM_freeN(node); +} + +/* If scene include more than one MetaElem, then octree is used */ +static void init_metaball_octal_tree(PROCESS *process, int depth) +{ + struct octal_node *node; + ml_pointer *ml_p; + float size[3]; + int a; + + process->metaball_tree = MEM_mallocN(sizeof(octal_tree), "metaball_octal_tree"); + process->metaball_tree->first = node = MEM_mallocN(sizeof(octal_node), "metaball_octal_node"); + /* maximal depth of octree */ + process->metaball_tree->depth = depth; + + process->metaball_tree->neg = node->neg = 0; + process->metaball_tree->pos = node->pos = 0; + + BLI_listbase_clear(&node->elems); + node->count = 0; + + for (a = 0; a < 8; a++) + node->nodes[a] = NULL; + + node->x_min = node->y_min = node->z_min = FLT_MAX; + node->x_max = node->y_max = node->z_max = -FLT_MAX; + + /* size of octal tree scene */ + for (a = 0; a < process->totelem; a++) { + if (process->mainb[a]->bb->vec[0][0] < node->x_min) node->x_min = process->mainb[a]->bb->vec[0][0]; + if (process->mainb[a]->bb->vec[0][1] < node->y_min) node->y_min = process->mainb[a]->bb->vec[0][1]; + if (process->mainb[a]->bb->vec[0][2] < node->z_min) node->z_min = process->mainb[a]->bb->vec[0][2]; + + if (process->mainb[a]->bb->vec[6][0] > node->x_max) node->x_max = process->mainb[a]->bb->vec[6][0]; + if (process->mainb[a]->bb->vec[6][1] > node->y_max) node->y_max = process->mainb[a]->bb->vec[6][1]; + if (process->mainb[a]->bb->vec[6][2] > node->z_max) node->z_max = process->mainb[a]->bb->vec[6][2]; + + ml_p = MEM_mallocN(sizeof(ml_pointer), "ml_pointer"); + ml_p->ml = process->mainb[a]; + BLI_addtail(&node->elems, ml_p); + + if ((process->mainb[a]->flag & MB_NEGATIVE) == 0) { + /* number of positive MetaElem in scene */ + process->metaball_tree->pos++; + } + else { + /* number of negative MetaElem in scene */ + process->metaball_tree->neg++; + } + } + + /* size of first node */ + size[0] = node->x_max - node->x_min; + size[1] = node->y_max - node->y_min; + size[2] = node->z_max - node->z_min; + + /* first node is subdivided recursively */ + subdivide_metaball_octal_node(node, size[0], size[1], size[2], process->metaball_tree->depth); +} + +static void mball_count(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *basis) +{ + Scene *sce_iter = scene; + Base *base; + Object *ob, *bob = basis; + MetaElem *ml = NULL; + int basisnr, obnr; + char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; + SceneBaseIter iter; + + BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.'); + process->totelem = 0; + + BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL); + while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) { + if (ob->type == OB_MBALL) { + if (ob == bob) { + MetaBall *mb = ob->data; + + /* if bob object is in edit mode, then dynamic list of all MetaElems + * is stored in editelems */ + if (mb->editelems) ml = mb->editelems->first; + /* if bob object is in object mode */ + else ml = mb->elems.first; + } + else { + BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); + + /* object ob has to be in same "group" ... it means, that it has to have + * same base of its name */ + if (STREQ(obname, basisname)) { + MetaBall *mb = ob->data; + + /* if object is in edit mode, then dynamic list of all MetaElems + * is stored in editelems */ + if (mb->editelems) ml = mb->editelems->first; + /* if bob object is in object mode */ + else ml = mb->elems.first; + } + } + + for ( ; ml; ml = ml->next) { + if (!(ml->flag & MB_HIDE)) { + process->totelem++; + } + } + } + } +} + +void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase) +{ + MetaBall *mb; + DispList *dl; + int a, nr_cubes; + float *co, *no, totsize, width; + PROCESS process = {0}; + + mb = ob->data; + + mball_count(eval_ctx, &process, scene, ob); + + if (process.totelem == 0) return; + if ((eval_ctx->mode != DAG_EVAL_RENDER) && (mb->flag == MB_UPDATE_NEVER)) return; + if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_FAST) return; + + process.thresh = mb->thresh; + + /* total number of MetaElems (totelem) is precomputed in find_basis_mball() function */ + process.mainb = MEM_mallocN(sizeof(void *) * process.totelem, "mainb"); + + /* initialize all mainb (MetaElems) */ + totsize = init_meta(eval_ctx, &process, scene, ob); + + /* if scene includes more than one MetaElem, then octal tree optimization is used */ + if ((process.totelem > 1) && (process.totelem <= 64)) init_metaball_octal_tree(&process, 1); + if ((process.totelem > 64) && (process.totelem <= 128)) init_metaball_octal_tree(&process, 2); + if ((process.totelem > 128) && (process.totelem <= 512)) init_metaball_octal_tree(&process, 3); + if ((process.totelem > 512) && (process.totelem <= 1024)) init_metaball_octal_tree(&process, 4); + if (process.totelem > 1024) init_metaball_octal_tree(&process, 5); + + /* don't polygonize metaballs with too high resolution (base mball to small) + * note: Eps was 0.0001f but this was giving problems for blood animation for durian, using 0.00001f */ + if (process.metaball_tree) { + if (ob->size[0] <= 0.00001f * (process.metaball_tree->first->x_max - process.metaball_tree->first->x_min) || + ob->size[1] <= 0.00001f * (process.metaball_tree->first->y_max - process.metaball_tree->first->y_min) || + ob->size[2] <= 0.00001f * (process.metaball_tree->first->z_max - process.metaball_tree->first->z_min)) + { + new_pgn_element(&process, -1); /* free values created by init_meta */ + + MEM_freeN(process.mainb); + + /* free tree */ + free_metaball_octal_node(process.metaball_tree->first); + MEM_freeN(process.metaball_tree); + + return; + } + } + + /* width is size per polygonize cube */ + if (eval_ctx->mode == DAG_EVAL_RENDER) { + width = mb->rendersize; + } + else { + width = mb->wiresize; + if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_HALFRES) { + width *= 2; + } + } + /* nr_cubes is just for safety, minimum is totsize */ + nr_cubes = (int)(0.5f + totsize / width); + + /* init process */ + process.function = metaball; + process.size = width; + process.bounds = nr_cubes; + process.cubes = NULL; + process.delta = width / (float)(RES * RES); + + polygonize(&process, mb); + + MEM_freeN(process.mainb); + + /* free octal tree */ + if (process.totelem > 1) { + free_metaball_octal_node(process.metaball_tree->first); + MEM_freeN(process.metaball_tree); + process.metaball_tree = NULL; + } + + if (process.curindex) { + VERTEX *ptr = process.vertices.ptr; + + dl = MEM_callocN(sizeof(DispList), "mbaldisp"); + BLI_addtail(dispbase, dl); + dl->type = DL_INDEX4; + dl->nr = process.vertices.count; + dl->parts = process.curindex; + + dl->index = process.indices; + process.indices = NULL; + + a = process.vertices.count; + dl->verts = co = MEM_mallocN(sizeof(float[3]) * a, "mballverts"); + dl->nors = no = MEM_mallocN(sizeof(float[3]) * a, "mballnors"); + + for (a = 0; a < process.vertices.count; ptr++, a++, no += 3, co += 3) { + copy_v3_v3(co, ptr->co); + copy_v3_v3(no, ptr->no); + } + } + + freepolygonize(&process); +} -- cgit v1.2.3 From 7bc8ddc6e2f2da8afde91ef01afee4079e7f9a45 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 25 Mar 2015 22:36:43 +1100 Subject: use BKE_mball_tessellate.h include also remove unused includes --- source/blender/blenkernel/BKE_mball.h | 1 - source/blender/blenkernel/BKE_mball_tessellate.h | 34 ++++++++++++++++++++++ source/blender/blenkernel/intern/displist.c | 1 + source/blender/blenkernel/intern/mball.c | 3 +- .../blender/blenkernel/intern/mball_tessellate.c | 14 +++------ 5 files changed, 40 insertions(+), 13 deletions(-) diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index c021960e730..aa9ba45938e 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -48,7 +48,6 @@ void BKE_mball_make_local(struct MetaBall *mb); void BKE_mball_cubeTable_free(void); -void BKE_mball_polygonize(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase); bool BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2); bool BKE_mball_is_basis(struct Object *ob); struct Object *BKE_mball_basis_find(struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_mball_tessellate.h b/source/blender/blenkernel/BKE_mball_tessellate.h index e69de29bb2d..a3d3e1934b7 100644 --- a/source/blender/blenkernel/BKE_mball_tessellate.h +++ b/source/blender/blenkernel/BKE_mball_tessellate.h @@ -0,0 +1,34 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __BKE_MBALL_TESSELLATE_H__ +#define __BKE_MBALL_TESSELLATE_H__ + +/** \file BKE_mball_tessellate.h + * \ingroup bke + */ +struct EvaluationContext; +struct Object; +struct Scene; + +void BKE_mball_polygonize( + struct EvaluationContext *eval_ctx, struct Scene *scene, + struct Object *ob, struct ListBase *dispbase); + +#endif /* __BKE_MBALL_TESSELLATE_H__ */ diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index dd92a82bed2..e5e751561ec 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -53,6 +53,7 @@ #include "BKE_cdderivedmesh.h" #include "BKE_object.h" #include "BKE_mball.h" +#include "BKE_mball_tessellate.h" #include "BKE_curve.h" #include "BKE_key.h" #include "BKE_anim.h" diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index efc5b23a9d0..25031183545 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -39,6 +39,7 @@ #include #include #include + #include "MEM_guardedalloc.h" #include "DNA_material_types.h" @@ -46,7 +47,6 @@ #include "DNA_meta_types.h" #include "DNA_scene_types.h" - #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -54,7 +54,6 @@ #include "BKE_global.h" #include "BKE_main.h" -/* #include "BKE_object.h" */ #include "BKE_animsys.h" #include "BKE_curve.h" #include "BKE_depsgraph.h" diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c index b1bef13c449..04024943310 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.c +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -33,31 +33,25 @@ #include #include #include + #include "MEM_guardedalloc.h" -#include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_meta_types.h" #include "DNA_scene_types.h" - -#include "BLI_blenlib.h" +#include "BLI_listbase.h" +#include "BLI_path_util.h" #include "BLI_math.h" #include "BLI_utildefines.h" #include "BKE_global.h" -#include "BKE_main.h" -/* #include "BKE_object.h" */ -#include "BKE_animsys.h" -#include "BKE_curve.h" #include "BKE_depsgraph.h" #include "BKE_scene.h" -#include "BKE_library.h" #include "BKE_displist.h" #include "BKE_mball.h" -#include "BKE_object.h" -#include "BKE_material.h" +#include "BKE_mball_tessellate.h" /* own include */ /* Data types */ -- cgit v1.2.3 From 0ef9f61410b8a22905daa38feb49a2f5d1b845e4 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 25 Mar 2015 13:05:52 +0100 Subject: Attempt to fix an error in compilation of geometry shaders in Intel 4000 cards (see T44072) --- source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl index 9f365a0d671..7918122a681 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl @@ -6,7 +6,7 @@ uniform vec2 layerselection; uniform sampler2D cocbuffer; /* initial uv coordinate */ -varying in vec2 uvcoord[]; +varying in vec2 uvcoord[1]; varying out vec2 particlecoord; varying out vec4 color; -- cgit v1.2.3 From 1c329af74cb2720fbb2e24a58ae15046d5c5c957 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 26 Mar 2015 00:10:39 +1100 Subject: Fix T44026: ID prop delete leaves names in _RNA_UI --- release/scripts/modules/rna_prop_ui.py | 13 +++++++++++-- release/scripts/startup/bl_operators/wm.py | 6 +++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/release/scripts/modules/rna_prop_ui.py b/release/scripts/modules/rna_prop_ui.py index f4649453b46..44722fa7162 100644 --- a/release/scripts/modules/rna_prop_ui.py +++ b/release/scripts/modules/rna_prop_ui.py @@ -32,6 +32,13 @@ def rna_idprop_ui_get(item, create=True): return None +def rna_idprop_ui_del(item): + try: + del item['_RNA_UI'] + except KeyError: + pass + + def rna_idprop_ui_prop_get(item, prop, create=True): rna_ui = rna_idprop_ui_get(item, create) @@ -46,7 +53,7 @@ def rna_idprop_ui_prop_get(item, prop, create=True): return rna_ui[prop] -def rna_idprop_ui_prop_clear(item, prop): +def rna_idprop_ui_prop_clear(item, prop, remove=True): rna_ui = rna_idprop_ui_get(item, False) if rna_ui is None: @@ -54,8 +61,10 @@ def rna_idprop_ui_prop_clear(item, prop): try: del rna_ui[prop] - except: + except KeyError: pass + if remove and len(item.keys()) == 1: + rna_idprop_ui_del(item) def rna_idprop_context_value(context, context_member, property_type): diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index a48415caa9b..7ac9fa4a036 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -1296,9 +1296,13 @@ class WM_OT_properties_remove(Operator): property = rna_property def execute(self, context): + from rna_prop_ui import rna_idprop_ui_prop_clear data_path = self.data_path item = eval("context.%s" % data_path) - del item[self.property] + prop = self.property + del item[prop] + rna_idprop_ui_prop_clear(item, prop) + return {'FINISHED'} -- cgit v1.2.3 From 1a866d55acce90406e6430f85f3d88335c4f686d Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 25 Mar 2015 14:43:28 +0100 Subject: Fix crash with computers not supporting high quality depth of field. --- source/blender/gpu/intern/gpu_compositing.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index 6a7805bb614..f850b6fcc55 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -390,7 +390,12 @@ bool GPU_fx_compositor_initialize_passes( /* create textures for dof effect */ if (fx_flag & GPU_FX_FLAG_DOF) { - bool dof_high_quality = (fx_settings->dof->high_quality != 0); + bool dof_high_quality = (fx_settings->dof->high_quality != 0) && + GPU_geometry_shader_support() && GPU_instanced_drawing_support(); + + /* cleanup buffers if quality setting has changed (no need to keep more buffers around than necessary ) */ + if (dof_high_quality != fx->dof_high_quality) + cleanup_fx_dof_buffers(fx); if (dof_high_quality) { fx->dof_downsampled_w = w / 2; @@ -469,7 +474,7 @@ bool GPU_fx_compositor_initialize_passes( } } - fx->dof_high_quality = dof_high_quality && GPU_geometry_shader_support() && GPU_instanced_drawing_support(); + fx->dof_high_quality = dof_high_quality; } else { /* cleanup unnecessary buffers */ -- cgit v1.2.3 From 4fd2f678ea07fcd69dffce10fbfd0b19ccdc3782 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 25 Mar 2015 15:05:36 +0100 Subject: Fix T44133 SSAO in OpenGL rendering from orthographic camera did not work Safe to include in final release --- source/blender/editors/render/render_opengl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 402e72db217..d8da0e9bcda 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -223,7 +223,12 @@ static void screen_opengl_render_apply(OGLRender *oglrender) /*int is_ortho = scene->r.mode & R_ORTHO;*/ camera = v3d->camera; RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat); - is_persp = true; + if (camera->type == OB_CAMERA) { + Camera *cam = camera->data; + is_persp = cam->type == CAM_PERSP; + } + else + is_persp = true; BKE_camera_to_gpu_dof(camera, &fx_settings); } else { -- cgit v1.2.3 From 9fc1a29de35bd9ac453884d106ec5694539f989e Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Wed, 25 Mar 2015 16:56:43 +0100 Subject: Fix 2 typos ( shakin' hands ) --- intern/cycles/kernel/kernel_shader.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 17e5db93e2f..71b2f7469e2 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -798,8 +798,8 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, #else sd->closure->weight = make_float3(0.8f, 0.8f, 0.8f); sd->closure->N = sd->N; - sd->closyre->data0 = 0.0f; - sd->closyre->data1 = 0.0f; + sd->closure->data0 = 0.0f; + sd->closure->data1 = 0.0f; sd->flag |= bsdf_diffuse_setup(&sd->closure); #endif } -- cgit v1.2.3 From d4ac58d04989e8c2e1951a55519cfba53011d494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20T=C3=B6nne?= Date: Wed, 25 Mar 2015 18:34:52 +0100 Subject: =?UTF-8?q?Fix=20T43694,=20by=20Krzysztof=20Re=C4=87ko=20(chrisr),?= =?UTF-8?q?=20reviewed=20in=20D1177.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added some guards to prevent clumping to non existing particles. Also, adjusted threaded child path evaluation, so each child is evaluated once - previously virtual parents were done twice. --- source/blender/blenkernel/BKE_particle.h | 2 +- source/blender/blenkernel/intern/particle.c | 28 ++++++++++++++++++---- .../blenkernel/intern/particle_distribute.c | 2 +- source/blender/blenkernel/intern/particle_system.c | 10 ++++---- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 0f1389bfeec..619c061cea5 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -361,7 +361,7 @@ void psys_get_dupli_path_transform(struct ParticleSimulationData *sim, struct Pa void psys_thread_context_init(struct ParticleThreadContext *ctx, struct ParticleSimulationData *sim); void psys_thread_context_free(struct ParticleThreadContext *ctx); -void psys_tasks_create(struct ParticleThreadContext *ctx, int totpart, struct ParticleTask **r_tasks, int *r_numtasks); +void psys_tasks_create(struct ParticleThreadContext *ctx, int startpart, int endpart, struct ParticleTask **r_tasks, int *r_numtasks); void psys_tasks_free(struct ParticleTask *tasks, int numtasks); void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 291efd03a66..5d553f5deee 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -103,6 +103,8 @@ void psys_init_rng(void) static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex); +static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par, + int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra); extern void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *ptex, const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3], ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t); @@ -1943,9 +1945,11 @@ float *psys_cache_vgroup(DerivedMesh *dm, ParticleSystem *psys, int vgroup) } void psys_find_parents(ParticleSimulationData *sim) { + ParticleSystem *psys = sim->psys; ParticleSettings *part = sim->psys->part; KDTree *tree; ChildParticle *cpa; + ParticleTexture ptex; int p, totparent, totchild = sim->psys->totchild; float co[3], orco[3]; int from = PART_FROM_FACE; @@ -1963,7 +1967,13 @@ void psys_find_parents(ParticleSimulationData *sim) for (p = 0, cpa = sim->psys->child; p < totparent; p++, cpa++) { psys_particle_on_emitter(sim->psmd, from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, 0, 0, 0, orco, 0); - BLI_kdtree_insert(tree, p, orco); + + /* Check if particle doesn't exist because of texture influence. Insert only existing particles into kdtree. */ + get_cpa_texture(sim->psmd->dm, psys, part, psys->particles + cpa->pa[0], p, cpa->num, cpa->fuv, orco, &ptex, PAMAP_DENS | PAMAP_CHILD, psys->cfra); + + if (ptex.exist >= psys_frand(psys, p + 24)) { + BLI_kdtree_insert(tree, p, orco); + } } BLI_kdtree_balance(tree); @@ -2273,7 +2283,7 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp ParticleCacheKey *par = NULL; float par_co[3]; float par_orco[3]; - + if (ctx->totparent) { if (i >= ctx->totparent) { pa = &psys->particles[cpa->parent]; @@ -2284,6 +2294,16 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp else if (cpa->parent >= 0) { pa = &psys->particles[cpa->parent]; par = pcache[cpa->parent]; + + /* If particle is unexisting, try to pick a viable parent from particles used for interpolation. */ + for (k = 0; k < 4 && pa && (pa->flag & PARS_UNEXIST); k++) { + if (cpa->pa[k] >= 0) { + pa = &psys->particles[cpa->pa[k]]; + par = pcache[cpa->pa[k]]; + } + } + + if (pa->flag & PARS_UNEXIST) pa = NULL; } if (pa) { @@ -2353,7 +2373,7 @@ void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupd /* cache parent paths */ ctx.parent_pass = 1; - psys_tasks_create(&ctx, totparent, &tasks_parent, &numtasks_parent); + psys_tasks_create(&ctx, 0, totparent, &tasks_parent, &numtasks_parent); for (i = 0; i < numtasks_parent; ++i) { ParticleTask *task = &tasks_parent[i]; @@ -2364,7 +2384,7 @@ void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupd /* cache child paths */ ctx.parent_pass = 0; - psys_tasks_create(&ctx, totchild, &tasks_child, &numtasks_child); + psys_tasks_create(&ctx, totparent, totchild, &tasks_child, &numtasks_child); for (i = 0; i < numtasks_child; ++i) { ParticleTask *task = &tasks_child[i]; diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 245c2432105..1429d3b1cdc 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -1121,7 +1121,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from) task_pool = BLI_task_pool_create(task_scheduler, &ctx); totpart = (from == PART_FROM_CHILD ? sim->psys->totchild : sim->psys->totpart); - psys_tasks_create(&ctx, totpart, &tasks, &numtasks); + psys_tasks_create(&ctx, 0, totpart, &tasks, &numtasks); for (i = 0; i < numtasks; ++i) { ParticleTask *task = &tasks[i]; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index b7ebcfa9b0b..5a263e24fc4 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -448,24 +448,24 @@ BLI_INLINE int ceil_ii(int a, int b) return (a + b - 1) / b; } -void psys_tasks_create(ParticleThreadContext *ctx, int totpart, ParticleTask **r_tasks, int *r_numtasks) +void psys_tasks_create(ParticleThreadContext *ctx, int startpart, int endpart, ParticleTask **r_tasks, int *r_numtasks) { ParticleTask *tasks; - int numtasks = ceil_ii(totpart, MAX_PARTICLES_PER_TASK); - float particles_per_task = (float)totpart / (float)numtasks, p, pnext; + int numtasks = ceil_ii((endpart - startpart), MAX_PARTICLES_PER_TASK); + float particles_per_task = (float)(endpart - startpart) / (float)numtasks, p, pnext; int i; tasks = MEM_callocN(sizeof(ParticleTask) * numtasks, "ParticleThread"); *r_numtasks = numtasks; *r_tasks = tasks; - p = 0.0f; + p = (float)startpart; for (i = 0; i < numtasks; i++, p = pnext) { pnext = p + particles_per_task; tasks[i].ctx = ctx; tasks[i].begin = (int)p; - tasks[i].end = min_ii((int)pnext, totpart); + tasks[i].end = min_ii((int)pnext, endpart); } } -- cgit v1.2.3 From 5e2cc06518e9d32a625cfd3fce4987c705155bed Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Wed, 25 Mar 2015 14:28:36 -0400 Subject: minor cleanup: alignment --- source/blender/nodes/NOD_static_types.h | 4 ++-- source/blender/nodes/shader/nodes/node_shader_object_info.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 166fa29fca0..6b9a97c0b18 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -71,7 +71,7 @@ DefNode( ShaderNode, SH_NODE_OUTPUT_LAMP, def_sh_output, "OU DefNode( ShaderNode, SH_NODE_OUTPUT_WORLD, def_sh_output, "OUTPUT_WORLD", OutputWorld, "World Output", "" ) DefNode( ShaderNode, SH_NODE_OUTPUT_LINESTYLE, def_sh_output_linestyle,"OUTPUT_LINESTYLE", OutputLineStyle, "Line Style Output", "" ) DefNode( ShaderNode, SH_NODE_FRESNEL, 0, "FRESNEL", Fresnel, "Fresnel", "" ) -DefNode( ShaderNode, SH_NODE_LAYER_WEIGHT, 0, "LAYER_WEIGHT", LayerWeight, "Layer Weight", "" ) +DefNode( ShaderNode, SH_NODE_LAYER_WEIGHT, 0, "LAYER_WEIGHT", LayerWeight, "Layer Weight", "" ) DefNode( ShaderNode, SH_NODE_MIX_SHADER, 0, "MIX_SHADER", MixShader, "Mix Shader", "" ) DefNode( ShaderNode, SH_NODE_ADD_SHADER, 0, "ADD_SHADER", AddShader, "Add Shader", "" ) DefNode( ShaderNode, SH_NODE_ATTRIBUTE, def_sh_attribute, "ATTRIBUTE", Attribute, "Attribute", "" ) @@ -208,7 +208,7 @@ DefNode( CompositorNode, CMP_NODE_KEYINGSCREEN, def_cmp_keyingscreen, "KEYIN DefNode( CompositorNode, CMP_NODE_KEYING, def_cmp_keying, "KEYING", Keying, "Keying", "" ) DefNode( CompositorNode, CMP_NODE_TRACKPOS, def_cmp_trackpos, "TRACKPOS", TrackPos, "Track Position", "" ) DefNode( CompositorNode, CMP_NODE_PIXELATE, 0, "PIXELATE", Pixelate, "Pixelate", "" ) -DefNode( CompositorNode, CMP_NODE_PLANETRACKDEFORM,def_cmp_planetrackdeform,"PLANETRACKDEFORM",PlaneTrackDeform,"Plane Track Deform","" ) +DefNode( CompositorNode, CMP_NODE_PLANETRACKDEFORM,def_cmp_planetrackdeform,"PLANETRACKDEFORM",PlaneTrackDeform,"Plane Track Deform","" ) DefNode( CompositorNode, CMP_NODE_CORNERPIN, 0, "CORNERPIN", CornerPin, "Corner Pin", "" ) DefNode( CompositorNode, CMP_NODE_SUNBEAMS, def_cmp_sunbeams, "SUNBEAMS", SunBeams, "Sun Beams", "" ) diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.c b/source/blender/nodes/shader/nodes/node_shader_object_info.c index a862c621248..d1905246fd4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_object_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_object_info.c @@ -30,10 +30,10 @@ /* **************** OUTPUT ******************** */ static bNodeSocketTemplate sh_node_object_info_out[] = { - { SOCK_VECTOR, 0, N_("Location"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("Object Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("Material Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("Random"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, N_("Location"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_("Object Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_("Material Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_("Random"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -- cgit v1.2.3 From 4dc141f933f632ea00482b294e8c252ac12d21aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20T=C3=B6nne?= Date: Wed, 25 Mar 2015 20:08:12 +0100 Subject: Yet another fix for crashing particles. --- source/blender/editors/space_view3d/drawobject.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index d4d8db6d6c7..808408be694 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -52,6 +52,7 @@ #include "BKE_anim.h" /* for the where_on_path function */ #include "BKE_armature.h" #include "BKE_camera.h" +#include "BKE_colortools.h" #include "BKE_constraint.h" /* for the get_constraint_target function */ #include "BKE_curve.h" #include "BKE_DerivedMesh.h" @@ -4762,6 +4763,12 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if (draw_as == PART_DRAW_NOT) return; + /* prepare curvemapping tables */ + if ((psys->part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && psys->part->clumpcurve) + curvemapping_changed_all(psys->part->clumpcurve); + if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve) + curvemapping_changed_all(psys->part->roughcurve); + /* 2. */ sim.scene = scene; sim.ob = ob; -- cgit v1.2.3 From 581afa9da37e0adaea756c165af11b467e9b8852 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 25 Mar 2015 21:52:54 +0100 Subject: Fix T44121: VSE Preview scaling issue when using proxies and Show Overexposed --- source/blender/editors/space_sequencer/sequencer_draw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index b63c46cba01..c668887e564 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1079,8 +1079,10 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq /* future files may have new scopes we don't catch above */ if (scope) { scopes->reference_ibuf = ibuf; - viewrect[0] = scope->x; - viewrect[1] = scope->y; + if (!scopes->zebra_ibuf) { /* zebra uses viewrect from orig ibuf */ + viewrect[0] = scope->x; + viewrect[1] = scope->y; + } } else { scopes->reference_ibuf = NULL; -- cgit v1.2.3 From 92f305a490802812091da4640df552d77f168844 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 25 Mar 2015 22:15:56 +0100 Subject: A more forward thinking version of previous commit Basically same as 581afa9da37, but I guess we can assume that scopes added in future to the image preview may also want to use the viewrect from the original ibuf. --- source/blender/editors/space_sequencer/sequencer_draw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index c668887e564..ec4ae5a3a62 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1079,7 +1079,10 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq /* future files may have new scopes we don't catch above */ if (scope) { scopes->reference_ibuf = ibuf; - if (!scopes->zebra_ibuf) { /* zebra uses viewrect from orig ibuf */ + if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { + /* scopes drawn in image preview use viewrect from orig ibuf - currently that's only zebra */ + } + else { viewrect[0] = scope->x; viewrect[1] = scope->y; } -- cgit v1.2.3 From 770b109deb6fbaea571901e56f5b9b6742483f69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20M=C3=BCller?= Date: Thu, 26 Mar 2015 14:45:21 +1300 Subject: Fix: AUD_OpenALDevice::getPosition returns negative values Reported by Antony Riakiotakis. The problem was the seeking code. --- intern/audaspace/OpenAL/AUD_OpenALDevice.cpp | 70 +++++++++++++++------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp index d055c131183..c0c77b6f917 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp @@ -276,49 +276,48 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position) alGetSourcei(m_source, AL_SOURCE_STATE, &info); - if(info != AL_PLAYING) - { - if(info == AL_PAUSED) - alSourceStop(m_source); + // we need to stop playing sounds as well to clear the buffers + // this might cause clicks, but fixes a bug regarding position determination + if(info == AL_PAUSED || info == AL_PLAYING) + alSourceStop(m_source); + + alSourcei(m_source, AL_BUFFER, 0); + m_current = 0; - alSourcei(m_source, AL_BUFFER, 0); - m_current = 0; + ALenum err; + if((err = alGetError()) == AL_NO_ERROR) + { + int length; + AUD_DeviceSpecs specs = m_device->m_specs; + specs.specs = m_reader->getSpecs(); + m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs)); - ALenum err; - if((err = alGetError()) == AL_NO_ERROR) + for(int i = 0; i < CYCLE_BUFFERS; i++) { - int length; - AUD_DeviceSpecs specs = m_device->m_specs; - specs.specs = m_reader->getSpecs(); - m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs)); + length = m_device->m_buffersize; + m_reader->read(length, m_eos, m_device->m_buffer.getBuffer()); - for(int i = 0; i < CYCLE_BUFFERS; i++) + if(length == 0) { - length = m_device->m_buffersize; - m_reader->read(length, m_eos, m_device->m_buffer.getBuffer()); - - if(length == 0) - { - // AUD_XXX: TODO: don't fill all buffers and enqueue them later - length = 1; - memset(m_device->m_buffer.getBuffer(), 0, length * AUD_DEVICE_SAMPLE_SIZE(specs)); - } - - alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(), - length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate); - - if(alGetError() != AL_NO_ERROR) - break; + // AUD_XXX: TODO: don't fill all buffers and enqueue them later + length = 1; + memset(m_device->m_buffer.getBuffer(), 0, length * AUD_DEVICE_SAMPLE_SIZE(specs)); } - if(m_loopcount != 0) - m_eos = false; + alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(), + length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate); - alSourceQueueBuffers(m_source, CYCLE_BUFFERS, m_buffers); + if(alGetError() != AL_NO_ERROR) + break; } - alSourceRewind(m_source); + if(m_loopcount != 0) + m_eos = false; + + alSourceQueueBuffers(m_source, CYCLE_BUFFERS, m_buffers); } + + alSourceRewind(m_source); } if(m_status == AUD_STATUS_STOPPED) @@ -343,9 +342,14 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getPosition() if(!m_isBuffered) { + int queued; + + // this usually always returns CYCLE_BUFFERS + alGetSourcei(m_source, AL_BUFFERS_QUEUED, &queued); + AUD_Specs specs = m_reader->getSpecs(); position += (m_reader->getPosition() - m_device->m_buffersize * - CYCLE_BUFFERS) / (float)specs.rate; + queued) / (float)specs.rate; } return position; -- cgit v1.2.3 From b87eaef1f7928bd6f0e937474cf922afa4c07f83 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 26 Mar 2015 16:29:14 +1100 Subject: Fix T44137: bpy.path.is_subdir fails `bpy.path.is_subdir("/abc/def/ghi","/abc/de")` incorrectly returned True --- release/scripts/modules/bpy/path.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py index 25a6c7242e0..0012083ba98 100644 --- a/release/scripts/modules/bpy/path.py +++ b/release/scripts/modules/bpy/path.py @@ -116,7 +116,11 @@ def is_subdir(path, directory): from os.path import normpath, normcase path = normpath(normcase(path)) directory = normpath(normcase(directory)) - return path.startswith(directory) + if len(path) > len(directory): + if path.startswith(directory): + sep = ord(_os.sep) if isinstance(directory, bytes) else _os.sep + return (path[len(directory)] == sep) + return False def clean_name(name, replace="_"): -- cgit v1.2.3 From d97b97460ca9a28027041e5666dbfeb3a5295155 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 26 Mar 2015 09:20:37 +0100 Subject: Fix T44138: Crash in DataTransfer modifier when selecting a source with no loops. Simply check and early return in case we have no source or destination items (verts/edges/loops/polys) available... Also, fix an assert in `BKE_mesh_calc_normals_poly()`, when called with no poly. --- source/blender/blenkernel/intern/data_transfer.c | 40 +++++++++++++++++++++--- source/blender/blenkernel/intern/mesh_evaluate.c | 4 +-- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 8f6d4385b55..da00aecf9c0 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -1157,12 +1157,20 @@ bool BKE_object_data_transfer_dm( const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert; if (!geom_map_init[VDATA]) { - if ((map_vert_mode == MREMAP_MODE_TOPOLOGY) && (num_verts_dst != dm_src->getNumVerts(dm_src))) { + const int num_verts_src = dm_src->getNumVerts(dm_src); + + if ((map_vert_mode == MREMAP_MODE_TOPOLOGY) && (num_verts_dst != num_verts_src)) { BKE_report(reports, RPT_ERROR, "Source and destination meshes do not have the same amount of vertices, " "'Topology' mapping cannot be used in this case"); return changed; } + if (ELEM(0, num_verts_dst, num_verts_src)) { + BKE_report(reports, RPT_ERROR, + "Source or destination meshes do not have any vertices, cannot transfer vertex data"); + return changed; + } + BKE_mesh_remap_calc_verts_from_dm( map_vert_mode, space_transform, max_distance, ray_radius, verts_dst, num_verts_dst, dirty_nors_dst, dm_src, &geom_map[VDATA]); @@ -1197,12 +1205,20 @@ bool BKE_object_data_transfer_dm( const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge; if (!geom_map_init[EDATA]) { - if ((map_edge_mode == MREMAP_MODE_TOPOLOGY) && (num_edges_dst != dm_src->getNumEdges(dm_src))) { + const int num_edges_src = dm_src->getNumEdges(dm_src); + + if ((map_edge_mode == MREMAP_MODE_TOPOLOGY) && (num_edges_dst != num_edges_src)) { BKE_report(reports, RPT_ERROR, "Source and destination meshes do not have the same amount of edges, " "'Topology' mapping cannot be used in this case"); return changed; } + if (ELEM(0, num_edges_dst, num_edges_src)) { + BKE_report(reports, RPT_ERROR, + "Source or destination meshes do not have any edges, cannot transfer edge data"); + return changed; + } + BKE_mesh_remap_calc_edges_from_dm( map_edge_mode, space_transform, max_distance, ray_radius, verts_dst, num_verts_dst, edges_dst, num_edges_dst, dirty_nors_dst, @@ -1248,12 +1264,20 @@ bool BKE_object_data_transfer_dm( MeshRemapIslandsCalc island_callback = data_transfer_get_loop_islands_generator(cddata_type); if (!geom_map_init[LDATA]) { - if ((map_loop_mode == MREMAP_MODE_TOPOLOGY) && (num_loops_dst != dm_src->getNumLoops(dm_src))) { + const int num_loops_src = dm_src->getNumLoops(dm_src); + + if ((map_loop_mode == MREMAP_MODE_TOPOLOGY) && (num_loops_dst != num_loops_src)) { BKE_report(reports, RPT_ERROR, "Source and destination meshes do not have the same amount of face corners, " "'Topology' mapping cannot be used in this case"); return changed; } + if (ELEM(0, num_loops_dst, num_loops_src)) { + BKE_report(reports, RPT_ERROR, + "Source or destination meshes do not have any polygons, cannot transfer loop data"); + return changed; + } + BKE_mesh_remap_calc_loops_from_dm( map_loop_mode, space_transform, max_distance, ray_radius, verts_dst, num_verts_dst, edges_dst, num_edges_dst, @@ -1298,12 +1322,20 @@ bool BKE_object_data_transfer_dm( CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata; if (!geom_map_init[PDATA]) { - if ((map_poly_mode == MREMAP_MODE_TOPOLOGY) && (num_polys_dst != dm_src->getNumPolys(dm_src))) { + const int num_polys_src = dm_src->getNumPolys(dm_src); + + if ((map_poly_mode == MREMAP_MODE_TOPOLOGY) && (num_polys_dst != num_polys_src)) { BKE_report(reports, RPT_ERROR, "Source and destination meshes do not have the same amount of faces, " "'Topology' mapping cannot be used in this case"); return changed; } + if (ELEM(0, num_polys_dst, num_polys_src)) { + BKE_report(reports, RPT_ERROR, + "Source or destination meshes do not have any polygons, cannot transfer poly data"); + return changed; + } + BKE_mesh_remap_calc_polys_from_dm( map_poly_mode, space_transform, max_distance, ray_radius, verts_dst, num_verts_dst, loops_dst, num_loops_dst, diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index 6c835a72a40..ceb9b016ff2 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -226,7 +226,7 @@ void BKE_mesh_calc_normals_poly(MVert *mverts, int numVerts, MLoop *mloop, MPoly MPoly *mp; if (only_face_normals) { - BLI_assert(pnors != NULL); + BLI_assert((pnors != NULL) || (numPolys == 0)); #pragma omp parallel for if (numPolys > BKE_MESH_OMP_LIMIT) for (i = 0; i < numPolys; i++) { @@ -252,12 +252,12 @@ void BKE_mesh_calc_normals_poly(MVert *mverts, int numVerts, MLoop *mloop, MPoly } } - /* following Mesh convention; we use vertex coordinate itself for normal in this case */ for (i = 0; i < numVerts; i++) { MVert *mv = &mverts[i]; float *no = tnorms[i]; if (UNLIKELY(normalize_v3(no) == 0.0f)) { + /* following Mesh convention; we use vertex coordinate itself for normal in this case */ normalize_v3_v3(no, mv->co); } -- cgit v1.2.3 From 828c85a1bf6045dc76d1197635a4b71d897206c3 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 26 Mar 2015 11:35:41 +0100 Subject: sound module: Append functions with BKE (makes it easier to make them out from local functions) --- intern/audaspace/intern/AUD_C-API.cpp | 4 +- source/blender/blenkernel/BKE_sound.h | 86 ++++++++--------- source/blender/blenkernel/intern/blender.c | 2 +- source/blender/blenkernel/intern/packedFile.c | 2 +- source/blender/blenkernel/intern/scene.c | 12 +-- source/blender/blenkernel/intern/sequencer.c | 30 +++--- source/blender/blenkernel/intern/sound.c | 106 ++++++++++----------- source/blender/blenloader/intern/readfile.c | 8 +- source/blender/blenloader/intern/versioning_250.c | 2 +- source/blender/editors/animation/anim_ops.c | 2 +- source/blender/editors/screen/screen_ops.c | 16 ++-- source/blender/editors/sound/sound_ops.c | 10 +- source/blender/editors/space_clip/clip_ops.c | 2 +- source/blender/editors/space_clip/tracking_ops.c | 2 +- source/blender/editors/space_graph/graph_ops.c | 2 +- source/blender/editors/space_image/image_ops.c | 2 +- .../editors/space_sequencer/sequencer_add.c | 2 +- .../editors/space_sequencer/sequencer_edit.c | 10 +- .../editors/space_sequencer/sequencer_preview.c | 2 +- source/blender/makesrna/intern/rna_scene.c | 10 +- source/blender/makesrna/intern/rna_sequencer.c | 10 +- source/blender/makesrna/intern/rna_sequencer_api.c | 8 +- source/blender/makesrna/intern/rna_sound.c | 6 +- source/blender/makesrna/intern/rna_userdef.c | 2 +- .../blender/windowmanager/intern/wm_event_system.c | 4 +- source/blender/windowmanager/intern/wm_files.c | 2 +- source/blender/windowmanager/intern/wm_init_exit.c | 4 +- source/creator/creator.c | 6 +- .../GamePlayer/ghost/GPG_Application.cpp | 6 +- source/gameengine/GamePlayer/ghost/GPG_ghost.cpp | 2 +- 30 files changed, 181 insertions(+), 181 deletions(-) diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp index 45d72ccb50e..78b9279a54a 100644 --- a/intern/audaspace/intern/AUD_C-API.cpp +++ b/intern/audaspace/intern/AUD_C-API.cpp @@ -222,7 +222,7 @@ static PyMethodDef meth_getcdevice[] = { }; extern "C" { -extern void *sound_get_factory(void *sound); +extern void *BKE_sound_get_factory(void *sound); } static PyObject *AUD_getSoundFromPointer(PyObject *self, PyObject *args) @@ -231,7 +231,7 @@ static PyObject *AUD_getSoundFromPointer(PyObject *self, PyObject *args) if (PyArg_Parse(args, "l:_sound_from_pointer", &lptr)) { if (lptr) { - boost::shared_ptr* factory = (boost::shared_ptr*) sound_get_factory((void *) lptr); + boost::shared_ptr* factory = (boost::shared_ptr*) BKE_sound_get_factory((void *) lptr); if (factory) { Factory *obj = (Factory *)Factory_empty(); diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index a4182b8405f..3570751165c 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -46,19 +46,19 @@ typedef struct SoundWaveform { float *data; } SoundWaveform; -void sound_init_once(void); -void sound_exit_once(void); +void BKE_sound_init_once(void); +void BKE_sound_exit_once(void); -void sound_init(struct Main *main); +void BKE_sound_init(struct Main *main); -void sound_init_main(struct Main *bmain); +void BKE_sound_init_main(struct Main *bmain); -void sound_exit(void); +void BKE_sound_exit(void); -void sound_force_device(int device); -int sound_define_from_str(const char *str); +void BKE_sound_force_device(int device); +int BKE_sound_define_from_str(const char *str); -struct bSound *sound_new_file(struct Main *main, const char *filename); +struct bSound *BKE_sound_new_file(struct Main *main, const char *filename); // XXX unused currently #if 0 @@ -67,13 +67,13 @@ struct bSound *sound_new_buffer(struct Main *bmain, struct bSound *source); struct bSound *sound_new_limiter(struct Main *bmain, struct bSound *source, float start, float end); #endif -void sound_delete(struct Main *bmain, struct bSound *sound); +void BKE_sound_delete(struct Main *bmain, struct bSound *sound); -void sound_cache(struct bSound *sound); +void BKE_sound_cache(struct bSound *sound); -void sound_delete_cache(struct bSound *sound); +void BKE_sound_delete_cache(struct bSound *sound); -void sound_load(struct Main *main, struct bSound *sound); +void BKE_sound_load(struct Main *main, struct bSound *sound); void BKE_sound_free(struct bSound *sound); @@ -81,63 +81,63 @@ void BKE_sound_free(struct bSound *sound); AUD_Device *sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume); #endif -void sound_create_scene(struct Scene *scene); +void BKE_sound_create_scene(struct Scene *scene); -void sound_destroy_scene(struct Scene *scene); +void BKE_sound_destroy_scene(struct Scene *scene); -void sound_mute_scene(struct Scene *scene, int muted); +void BKE_sound_mute_scene(struct Scene *scene, int muted); -void sound_update_fps(struct Scene *scene); +void BKE_sound_update_fps(struct Scene *scene); -void sound_update_scene_listener(struct Scene *scene); +void BKE_sound_update_scene_listener(struct Scene *scene); -void *sound_scene_add_scene_sound(struct Scene *scene, struct Sequence *sequence, int startframe, int endframe, int frameskip); -void *sound_scene_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence); +void *BKE_sound_scene_add_scene_sound(struct Scene *scene, struct Sequence *sequence, int startframe, int endframe, int frameskip); +void *BKE_sound_scene_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence); -void *sound_add_scene_sound(struct Scene *scene, struct Sequence *sequence, int startframe, int endframe, int frameskip); -void *sound_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence); +void *BKE_sound_add_scene_sound(struct Scene *scene, struct Sequence *sequence, int startframe, int endframe, int frameskip); +void *BKE_sound_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence); -void sound_remove_scene_sound(struct Scene *scene, void *handle); +void BKE_sound_remove_scene_sound(struct Scene *scene, void *handle); -void sound_mute_scene_sound(void *handle, char mute); +void BKE_sound_mute_scene_sound(void *handle, char mute); -void sound_move_scene_sound(struct Scene *scene, void *handle, int startframe, int endframe, int frameskip); -void sound_move_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence); +void BKE_sound_move_scene_sound(struct Scene *scene, void *handle, int startframe, int endframe, int frameskip); +void BKE_sound_move_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence); -void sound_update_scene_sound(void *handle, struct bSound *sound); +void BKE_sound_update_scene_sound(void *handle, struct bSound *sound); -void sound_set_cfra(int cfra); +void BKE_sound_set_cfra(int cfra); -void sound_set_scene_volume(struct Scene *scene, float volume); +void BKE_sound_set_scene_volume(struct Scene *scene, float volume); -void sound_set_scene_sound_volume(void *handle, float volume, char animated); +void BKE_sound_set_scene_sound_volume(void *handle, float volume, char animated); -void sound_set_scene_sound_pitch(void *handle, float pitch, char animated); +void BKE_sound_set_scene_sound_pitch(void *handle, float pitch, char animated); -void sound_set_scene_sound_pan(void *handle, float pan, char animated); +void BKE_sound_set_scene_sound_pan(void *handle, float pan, char animated); -void sound_update_sequencer(struct Main *main, struct bSound *sound); +void BKE_sound_update_sequencer(struct Main *main, struct bSound *sound); -void sound_play_scene(struct Scene *scene); +void BKE_sound_play_scene(struct Scene *scene); -void sound_stop_scene(struct Scene *scene); +void BKE_sound_stop_scene(struct Scene *scene); -void sound_seek_scene(struct Main *bmain, struct Scene *scene); +void BKE_sound_seek_scene(struct Main *bmain, struct Scene *scene); -float sound_sync_scene(struct Scene *scene); +float BKE_sound_sync_scene(struct Scene *scene); -int sound_scene_playing(struct Scene *scene); +int BKE_sound_scene_playing(struct Scene *scene); -void sound_free_waveform(struct bSound *sound); +void BKE_sound_free_waveform(struct bSound *sound); -void sound_read_waveform(struct bSound *sound, short *stop); +void BKE_sound_read_waveform(struct bSound *sound, short *stop); -void sound_update_scene(struct Main *bmain, struct Scene *scene); +void BKE_sound_update_scene(struct Main *bmain, struct Scene *scene); -void *sound_get_factory(void *sound); +void *BKE_sound_get_factory(void *sound); -float sound_get_length(struct bSound *sound); +float BKE_sound_get_length(struct bSound *sound); -bool sound_is_jack_supported(void); +bool BKE_sound_is_jack_supported(void); #endif /* __BKE_SOUND_H__ */ diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index b6ea780576e..c7b306521c4 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -305,7 +305,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath CTX_data_main_set(C, G.main); - sound_init_main(G.main); + BKE_sound_init_main(G.main); if (bfd->user) { diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 8d56b1247fe..9b429b356b4 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -553,7 +553,7 @@ int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how) freePackedFile(sound->packedfile); sound->packedfile = NULL; - sound_load(bmain, sound); + BKE_sound_load(bmain, sound); ret_value = RET_OK; } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index d2c3f473e11..f51dadf1da6 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -293,7 +293,7 @@ Scene *BKE_scene_copy(Scene *sce, int type) } /* before scene copy */ - sound_create_scene(scen); + BKE_sound_create_scene(scen); /* world */ if (type == SCE_COPY_FULL) { @@ -426,7 +426,7 @@ void BKE_scene_free(Scene *sce) if (sce->fps_info) MEM_freeN(sce->fps_info); - sound_destroy_scene(sce); + BKE_sound_destroy_scene(sce); BKE_color_managed_view_settings_free(&sce->view_settings); } @@ -682,7 +682,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->gm.exitkey = 218; // Blender key code for ESC - sound_create_scene(sce); + BKE_sound_create_scene(sce); /* color management */ colorspace_name = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_SEQUENCER); @@ -1690,7 +1690,7 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc * only objects and scenes. - brecht */ scene_update_tagged_recursive(eval_ctx, bmain, scene, scene); /* update sound system animation (TODO, move to depsgraph) */ - sound_update_scene(bmain, scene); + BKE_sound_update_scene(bmain, scene); /* extra call here to recalc scene animation (for sequencer) */ { @@ -1769,7 +1769,7 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, */ scene_rebuild_rbw_recursive(sce, ctime); - sound_set_cfra(sce->r.cfra); + BKE_sound_set_cfra(sce->r.cfra); /* clear animation overrides */ /* XXX TODO... */ @@ -1814,7 +1814,7 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, /* BKE_object_handle_update() on all objects, groups and sets */ scene_update_tagged_recursive(eval_ctx, bmain, sce, sce); /* update sound system animation (TODO, move to depsgraph) */ - sound_update_scene(bmain, sce); + BKE_sound_update_scene(bmain, sce); scene_depsgraph_hack(eval_ctx, sce, sce); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index eb7736fff30..6fa39e8bbe0 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -205,7 +205,7 @@ static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const bool do_cach ed->act_seq = NULL; if (seq->scene_sound && ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) - sound_remove_scene_sound(scene, seq->scene_sound); + BKE_sound_remove_scene_sound(scene, seq->scene_sound); seq_free_animdata(scene, seq); } @@ -316,7 +316,7 @@ static void seqclipboard_ptr_restore(Main *bmain, ID **id_pt) { id_restore = BLI_findstring(lb, ((bSound *)ID_PT)->name, offsetof(bSound, name)); if (id_restore == NULL) { - id_restore = sound_new_file(bmain, ((bSound *)ID_PT)->name); + id_restore = BKE_sound_new_file(bmain, ((bSound *)ID_PT)->name); (ID_PT)->newid = id_restore; /* reuse next time */ } break; @@ -652,7 +652,7 @@ static void seq_update_sound_bounds_recursive_rec(Scene *scene, Sequence *metase if (seq->start + seq->len - seq->endofs > end) endofs = seq->start + seq->len - end; - sound_move_scene_sound(scene, seq->scene_sound, seq->start + startofs, + BKE_sound_move_scene_sound(scene, seq->scene_sound, seq->start + startofs, seq->start + seq->len - endofs, startofs + seq->anim_startofs); } } @@ -3747,10 +3747,10 @@ void BKE_sequence_sound_init(Scene *scene, Sequence *seq) } else { if (seq->sound) { - seq->scene_sound = sound_add_scene_sound_defaults(scene, seq); + seq->scene_sound = BKE_sound_add_scene_sound_defaults(scene, seq); } if (seq->scene) { - seq->scene_sound = sound_scene_add_scene_sound_defaults(scene, seq); + seq->scene_sound = BKE_sound_scene_add_scene_sound_defaults(scene, seq); } } } @@ -3962,11 +3962,11 @@ void BKE_sequencer_update_sound_bounds(Scene *scene, Sequence *seq) /* We have to take into account start frame of the sequence's scene! */ int startofs = seq->startofs + seq->anim_startofs + seq->scene->r.sfra; - sound_move_scene_sound(scene, seq->scene_sound, seq->startdisp, seq->enddisp, startofs); + BKE_sound_move_scene_sound(scene, seq->scene_sound, seq->startdisp, seq->enddisp, startofs); } } else { - sound_move_scene_sound_defaults(scene, seq); + BKE_sound_move_scene_sound_defaults(scene, seq); } /* mute is set in seq_update_muting_recursive */ } @@ -3991,7 +3991,7 @@ static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, i } else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) { if (seq->scene_sound) { - sound_mute_scene_sound(seq->scene_sound, seqmute); + BKE_sound_mute_scene_sound(seq->scene_sound, seqmute); } } } @@ -4020,7 +4020,7 @@ static void seq_update_sound_recursive(Scene *scene, ListBase *seqbasep, bSound } else if (seq->type == SEQ_TYPE_SOUND_RAM) { if (seq->scene_sound && sound == seq->sound) { - sound_update_scene_sound(seq->scene_sound, sound); + BKE_sound_update_scene_sound(seq->scene_sound, sound); } } } @@ -4353,7 +4353,7 @@ static void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load) if (seq_load->flag & SEQ_LOAD_SOUND_CACHE) { if (seq->sound) - sound_cache(seq->sound); + BKE_sound_cache(seq->sound); } seq_load->tot_success++; @@ -4459,7 +4459,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad AUD_SoundInfo info; - sound = sound_new_file(bmain, seq_load->path); /* handles relative paths */ + sound = BKE_sound_new_file(bmain, seq_load->path); /* handles relative paths */ if (sound == NULL || sound->playback_handle == NULL) { #if 0 @@ -4473,7 +4473,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad info = AUD_getInfo(sound->playback_handle); if (info.specs.channels == AUD_CHANNELS_INVALID) { - sound_delete(bmain, sound); + BKE_sound_delete(bmain, sound); #if 0 if (op) BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); @@ -4498,7 +4498,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); - seq->scene_sound = sound_add_scene_sound(scene, seq, seq_load->start_frame, seq_load->start_frame + seq->len, 0); + seq->scene_sound = BKE_sound_add_scene_sound(scene, seq, seq_load->start_frame, seq_load->start_frame + seq->len, 0); BKE_sequence_calc_disp(scene, seq); @@ -4620,7 +4620,7 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup else if (seq->type == SEQ_TYPE_SCENE) { seqn->strip->stripdata = NULL; if (seq->scene_sound) - seqn->scene_sound = sound_scene_add_scene_sound_defaults(sce_audio, seqn); + seqn->scene_sound = BKE_sound_scene_add_scene_sound_defaults(sce_audio, seqn); } else if (seq->type == SEQ_TYPE_MOVIECLIP) { /* avoid assert */ @@ -4637,7 +4637,7 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup seqn->strip->stripdata = MEM_dupallocN(seq->strip->stripdata); if (seq->scene_sound) - seqn->scene_sound = sound_add_scene_sound_defaults(sce_audio, seqn); + seqn->scene_sound = BKE_sound_add_scene_sound_defaults(sce_audio, seqn); id_us_plus((ID *)seqn->sound); } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index b9d70664874..cc0d0bdcfcc 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -64,7 +64,7 @@ static int sound_cfra; #endif -bSound *sound_new_file(struct Main *bmain, const char *filename) +bSound *BKE_sound_new_file(struct Main *bmain, const char *filename) { bSound *sound = NULL; @@ -87,7 +87,7 @@ bSound *sound_new_file(struct Main *bmain, const char *filename) BLI_strncpy(sound->name, filename, FILE_MAX); /* sound->type = SOUND_TYPE_FILE; */ /* XXX unused currently */ - sound_load(bmain, sound); + BKE_sound_load(bmain, sound); if (!sound->playback_handle) { BKE_libblock_free(bmain, sound); @@ -116,7 +116,7 @@ void BKE_sound_free(bSound *sound) sound->cache = NULL; } - sound_free_waveform(sound); + BKE_sound_free_waveform(sound); if (sound->spinlock) { BLI_spin_end(sound->spinlock); @@ -152,7 +152,7 @@ static void sound_sync_callback(void *data, int mode, float time) } #endif -int sound_define_from_str(const char *str) +int BKE_sound_define_from_str(const char *str) { if (BLI_strcaseeq(str, "NULL")) return AUD_NULL_DEVICE; @@ -166,18 +166,18 @@ int sound_define_from_str(const char *str) return -1; } -void sound_force_device(int device) +void BKE_sound_force_device(int device) { force_device = device; } -void sound_init_once(void) +void BKE_sound_init_once(void) { AUD_initOnce(); - atexit(sound_exit_once); + atexit(BKE_sound_exit_once); } -void sound_init(struct Main *bmain) +void BKE_sound_init(struct Main *bmain) { AUD_DeviceSpecs specs; int device, buffersize; @@ -206,10 +206,10 @@ void sound_init(struct Main *bmain) if (!AUD_init(device, specs, buffersize)) AUD_init(AUD_NULL_DEVICE, specs, buffersize); - sound_init_main(bmain); + BKE_sound_init_main(bmain); } -void sound_init_main(struct Main *bmain) +void BKE_sound_init_main(struct Main *bmain) { #ifdef WITH_JACK AUD_setSyncCallback(sound_sync_callback, bmain); @@ -218,12 +218,12 @@ void sound_init_main(struct Main *bmain) #endif } -void sound_exit(void) +void BKE_sound_exit(void) { AUD_exit(); } -void sound_exit_once(void) +void BKE_sound_exit_once(void) { AUD_exit(); AUD_exitOnce(); @@ -282,7 +282,7 @@ bSound *sound_new_limiter(struct Main *bmain, bSound *source, float start, float } #endif -void sound_delete(struct Main *bmain, bSound *sound) +void BKE_sound_delete(struct Main *bmain, bSound *sound) { if (sound) { BKE_sound_free(sound); @@ -291,7 +291,7 @@ void sound_delete(struct Main *bmain, bSound *sound) } } -void sound_cache(bSound *sound) +void BKE_sound_cache(bSound *sound) { sound->flags |= SOUND_FLAGS_CACHING; if (sound->cache) @@ -304,7 +304,7 @@ void sound_cache(bSound *sound) sound->playback_handle = sound->handle; } -void sound_delete_cache(bSound *sound) +void BKE_sound_delete_cache(bSound *sound) { sound->flags &= ~SOUND_FLAGS_CACHING; if (sound->cache) { @@ -314,7 +314,7 @@ void sound_delete_cache(bSound *sound) } } -void sound_load(struct Main *bmain, bSound *sound) +void BKE_sound_load(struct Main *bmain, bSound *sound) { if (sound) { if (sound->cache) { @@ -328,7 +328,7 @@ void sound_load(struct Main *bmain, bSound *sound) sound->playback_handle = NULL; } - sound_free_waveform(sound); + BKE_sound_free_waveform(sound); /* XXX unused currently */ #if 0 @@ -382,7 +382,7 @@ void sound_load(struct Main *bmain, bSound *sound) else sound->playback_handle = sound->handle; - sound_update_sequencer(bmain, sound); + BKE_sound_update_sequencer(bmain, sound); } } @@ -391,7 +391,7 @@ AUD_Device *sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, return AUD_openMixdownDevice(specs, scene->sound_scene, volume, start / FPS); } -void sound_create_scene(struct Scene *scene) +void BKE_sound_create_scene(struct Scene *scene) { /* should be done in version patch, but this gets called before */ if (scene->r.frs_sec_base == 0) @@ -405,7 +405,7 @@ void sound_create_scene(struct Scene *scene) scene->speaker_handles = NULL; } -void sound_destroy_scene(struct Scene *scene) +void BKE_sound_destroy_scene(struct Scene *scene) { if (scene->sound_scene_handle) AUD_stop(scene->sound_scene_handle); @@ -417,13 +417,13 @@ void sound_destroy_scene(struct Scene *scene) AUD_destroySet(scene->speaker_handles); } -void sound_mute_scene(struct Scene *scene, int muted) +void BKE_sound_mute_scene(struct Scene *scene, int muted) { if (scene->sound_scene) AUD_setSequencerMuted(scene->sound_scene, muted); } -void sound_update_fps(struct Scene *scene) +void BKE_sound_update_fps(struct Scene *scene) { if (scene->sound_scene) AUD_setSequencerFPS(scene->sound_scene, FPS); @@ -431,13 +431,13 @@ void sound_update_fps(struct Scene *scene) BKE_sequencer_refresh_sound_length(scene); } -void sound_update_scene_listener(struct Scene *scene) +void BKE_sound_update_scene_listener(struct Scene *scene) { AUD_updateSequencerData(scene->sound_scene, scene->audio.speed_of_sound, scene->audio.doppler_factor, scene->audio.distance_model); } -void *sound_scene_add_scene_sound(struct Scene *scene, struct Sequence *sequence, +void *BKE_sound_scene_add_scene_sound(struct Scene *scene, struct Sequence *sequence, int startframe, int endframe, int frameskip) { if (scene != sequence->scene) { @@ -448,14 +448,14 @@ void *sound_scene_add_scene_sound(struct Scene *scene, struct Sequence *sequence return NULL; } -void *sound_scene_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence) +void *BKE_sound_scene_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence) { - return sound_scene_add_scene_sound(scene, sequence, + return BKE_sound_scene_add_scene_sound(scene, sequence, sequence->startdisp, sequence->enddisp, sequence->startofs + sequence->anim_startofs); } -void *sound_add_scene_sound(struct Scene *scene, struct Sequence *sequence, int startframe, int endframe, int frameskip) +void *BKE_sound_add_scene_sound(struct Scene *scene, struct Sequence *sequence, int startframe, int endframe, int frameskip) { const double fps = FPS; void *handle = AUD_addSequence(scene->sound_scene, sequence->sound->playback_handle, @@ -467,70 +467,70 @@ void *sound_add_scene_sound(struct Scene *scene, struct Sequence *sequence, int return handle; } -void *sound_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence) +void *BKE_sound_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence) { - return sound_add_scene_sound(scene, sequence, + return BKE_sound_add_scene_sound(scene, sequence, sequence->startdisp, sequence->enddisp, sequence->startofs + sequence->anim_startofs); } -void sound_remove_scene_sound(struct Scene *scene, void *handle) +void BKE_sound_remove_scene_sound(struct Scene *scene, void *handle) { AUD_removeSequence(scene->sound_scene, handle); } -void sound_mute_scene_sound(void *handle, char mute) +void BKE_sound_mute_scene_sound(void *handle, char mute) { AUD_muteSequence(handle, mute); } -void sound_move_scene_sound(struct Scene *scene, void *handle, int startframe, int endframe, int frameskip) +void BKE_sound_move_scene_sound(struct Scene *scene, void *handle, int startframe, int endframe, int frameskip) { const double fps = FPS; AUD_moveSequence(handle, startframe / fps, endframe / fps, frameskip / fps); } -void sound_move_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence) +void BKE_sound_move_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence) { if (sequence->scene_sound) { - sound_move_scene_sound(scene, sequence->scene_sound, + BKE_sound_move_scene_sound(scene, sequence->scene_sound, sequence->startdisp, sequence->enddisp, sequence->startofs + sequence->anim_startofs); } } -void sound_update_scene_sound(void *handle, bSound *sound) +void BKE_sound_update_scene_sound(void *handle, bSound *sound) { AUD_updateSequenceSound(handle, sound->playback_handle); } -void sound_set_cfra(int cfra) +void BKE_sound_set_cfra(int cfra) { sound_cfra = cfra; } -void sound_set_scene_volume(struct Scene *scene, float volume) +void BKE_sound_set_scene_volume(struct Scene *scene, float volume) { AUD_setSequencerAnimData(scene->sound_scene, AUD_AP_VOLUME, CFRA, &volume, (scene->audio.flag & AUDIO_VOLUME_ANIMATED) != 0); } -void sound_set_scene_sound_volume(void *handle, float volume, char animated) +void BKE_sound_set_scene_sound_volume(void *handle, float volume, char animated) { AUD_setSequenceAnimData(handle, AUD_AP_VOLUME, sound_cfra, &volume, animated); } -void sound_set_scene_sound_pitch(void *handle, float pitch, char animated) +void BKE_sound_set_scene_sound_pitch(void *handle, float pitch, char animated) { AUD_setSequenceAnimData(handle, AUD_AP_PITCH, sound_cfra, &pitch, animated); } -void sound_set_scene_sound_pan(void *handle, float pan, char animated) +void BKE_sound_set_scene_sound_pan(void *handle, float pan, char animated) { AUD_setSequenceAnimData(handle, AUD_AP_PANNING, sound_cfra, &pan, animated); } -void sound_update_sequencer(struct Main *main, bSound *sound) +void BKE_sound_update_sequencer(struct Main *main, bSound *sound) { struct Scene *scene; @@ -550,7 +550,7 @@ static void sound_start_play_scene(struct Scene *scene) AUD_setLoop(scene->sound_scene_handle, -1); } -void sound_play_scene(struct Scene *scene) +void BKE_sound_play_scene(struct Scene *scene) { AUD_Status status; const float cur_time = (float)((double)CFRA / FPS); @@ -579,7 +579,7 @@ void sound_play_scene(struct Scene *scene) AUD_unlock(); } -void sound_stop_scene(struct Scene *scene) +void BKE_sound_stop_scene(struct Scene *scene) { if (scene->sound_scene_handle) { AUD_pause(scene->sound_scene_handle); @@ -589,7 +589,7 @@ void sound_stop_scene(struct Scene *scene) } } -void sound_seek_scene(struct Main *bmain, struct Scene *scene) +void BKE_sound_seek_scene(struct Main *bmain, struct Scene *scene) { AUD_Status status; bScreen *screen; @@ -654,7 +654,7 @@ void sound_seek_scene(struct Main *bmain, struct Scene *scene) AUD_unlock(); } -float sound_sync_scene(struct Scene *scene) +float BKE_sound_sync_scene(struct Scene *scene) { if (scene->sound_scene_handle) { if (scene->audio.flag & AUDIO_SYNC) @@ -665,7 +665,7 @@ float sound_sync_scene(struct Scene *scene) return NAN_FLT; } -int sound_scene_playing(struct Scene *scene) +int BKE_sound_scene_playing(struct Scene *scene) { if (scene->audio.flag & AUDIO_SYNC) return AUD_doesPlayback(); @@ -673,7 +673,7 @@ int sound_scene_playing(struct Scene *scene) return -1; } -void sound_free_waveform(bSound *sound) +void BKE_sound_free_waveform(bSound *sound) { SoundWaveform *waveform = sound->waveform; if (waveform) { @@ -686,7 +686,7 @@ void sound_free_waveform(bSound *sound) sound->waveform = NULL; } -void sound_read_waveform(bSound *sound, short *stop) +void BKE_sound_read_waveform(bSound *sound, short *stop) { AUD_SoundInfo info = AUD_getInfo(sound->playback_handle); SoundWaveform *waveform = MEM_mallocN(sizeof(SoundWaveform), "SoundWaveform"); @@ -717,7 +717,7 @@ void sound_read_waveform(bSound *sound, short *stop) return; } - sound_free_waveform(sound); + BKE_sound_free_waveform(sound); BLI_spin_lock(sound->spinlock); sound->waveform = waveform; @@ -725,7 +725,7 @@ void sound_read_waveform(bSound *sound, short *stop) BLI_spin_unlock(sound->spinlock); } -void sound_update_scene(Main *bmain, struct Scene *scene) +void BKE_sound_update_scene(Main *bmain, struct Scene *scene) { Object *ob; Base *base; @@ -806,20 +806,20 @@ void sound_update_scene(Main *bmain, struct Scene *scene) scene->speaker_handles = new_set; } -void *sound_get_factory(void *sound) +void *BKE_sound_get_factory(void *sound) { return ((bSound *)sound)->playback_handle; } /* stupid wrapper because AUD_C-API.h includes Python.h which makesrna doesn't like */ -float sound_get_length(bSound *sound) +float BKE_sound_get_length(bSound *sound) { AUD_SoundInfo info = AUD_getInfo(sound->playback_handle); return info.length; } -bool sound_is_jack_supported(void) +bool BKE_sound_is_jack_supported(void) { return (bool)AUD_isJackSupported(); } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 639ee646a67..b8c3bffae0f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5333,7 +5333,7 @@ static void lib_link_scene(FileData *fd, Main *main) if (seq->scene) { seq->scene = newlibadr(fd, sce->id.lib, seq->scene); if (seq->scene) { - seq->scene_sound = sound_scene_add_scene_sound_defaults(sce, seq); + seq->scene_sound = BKE_sound_scene_add_scene_sound_defaults(sce, seq); } } if (seq->clip) { @@ -5361,7 +5361,7 @@ static void lib_link_scene(FileData *fd, Main *main) } if (seq->sound) { seq->sound->id.us++; - seq->scene_sound = sound_add_scene_sound_defaults(sce, seq); + seq->scene_sound = BKE_sound_add_scene_sound_defaults(sce, seq); } } seq->anim = NULL; @@ -5536,7 +5536,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) sce->customdata_mask_modal = 0; sce->lay_updated = 0; - sound_create_scene(sce); + BKE_sound_create_scene(sce); /* set users to one by default, not in lib-link, this will increase it for compo nodes */ sce->id.us = 1; @@ -6963,7 +6963,7 @@ static void lib_link_sound(FileData *fd, Main *main) sound->id.flag -= LIB_NEED_LINK; sound->ipo = newlibadr_us(fd, sound->id.lib, sound->ipo); // XXX deprecated - old animation system - sound_load(main, sound); + BKE_sound_load(main, sound); } } } diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 7c148f1a2e9..2094aeb1485 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -795,7 +795,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main) char str[FILE_MAX]; BLI_join_dirfile(str, sizeof(str), seq->strip->dir, seq->strip->stripdata->name); BLI_path_abs(str, main->name); - seq->sound = sound_new_file(main, str); + seq->sound = BKE_sound_new_file(main, str); } #define SEQ_USE_PROXY_CUSTOM_DIR (1 << 19) #define SEQ_USE_PROXY_CUSTOM_FILE (1 << 21) diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index cbcbc8743f1..47eafcbaed1 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -107,7 +107,7 @@ static void change_frame_apply(bContext *C, wmOperator *op) SUBFRA = 0.0f; /* do updates */ - sound_seek_scene(bmain, scene); + BKE_sound_seek_scene(bmain, scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 48d39020236..686f601a839 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -2099,7 +2099,7 @@ static int frame_offset_exec(bContext *C, wmOperator *op) areas_do_frame_follow(C, false); - sound_seek_scene(bmain, scene); + BKE_sound_seek_scene(bmain, scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); @@ -2151,7 +2151,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op) areas_do_frame_follow(C, true); - sound_seek_scene(bmain, scene); + BKE_sound_seek_scene(bmain, scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } @@ -2257,7 +2257,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op) else { areas_do_frame_follow(C, true); - sound_seek_scene(bmain, scene); + BKE_sound_seek_scene(bmain, scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); @@ -2319,7 +2319,7 @@ static int marker_jump_exec(bContext *C, wmOperator *op) areas_do_frame_follow(C, true); - sound_seek_scene(bmain, scene); + BKE_sound_seek_scene(bmain, scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); @@ -3435,7 +3435,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv if ((scene->audio.flag & AUDIO_SYNC) && (sad->flag & ANIMPLAY_FLAG_REVERSE) == false && - finite(time = sound_sync_scene(scene))) + finite(time = BKE_sound_sync_scene(scene))) { double newfra = (double)time * FPS; /* give some space here to avoid jumps */ @@ -3510,7 +3510,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } if (sad->flag & ANIMPLAY_FLAG_JUMPED) - sound_seek_scene(bmain, scene); + BKE_sound_seek_scene(bmain, scene); /* since we follow drawflags, we can't send notifier but tag regions ourselves */ ED_update_for_newframe(bmain, scene, 1); @@ -3610,7 +3610,7 @@ int ED_screen_animation_play(bContext *C, int sync, int mode) if (ED_screen_animation_playing(CTX_wm_manager(C))) { /* stop playback now */ ED_screen_animation_timer(C, 0, 0, 0, 0); - sound_stop_scene(scene); + BKE_sound_stop_scene(scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } @@ -3618,7 +3618,7 @@ int ED_screen_animation_play(bContext *C, int sync, int mode) int refresh = SPACE_TIME; /* these settings are currently only available from a menu in the TimeLine */ if (mode == 1) /* XXX only play audio forwards!? */ - sound_play_scene(scene); + BKE_sound_play_scene(scene); ED_screen_animation_timer(C, screen->redraws_flag, refresh, sync, mode); diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index f3c6781b0fa..bce9a375091 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -100,7 +100,7 @@ static int sound_open_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); RNA_string_get(op->ptr, "filepath", path); - sound = sound_new_file(bmain, path); + sound = BKE_sound_new_file(bmain, path); if (!op->customdata) sound_open_init(C, op); @@ -114,7 +114,7 @@ static int sound_open_exec(bContext *C, wmOperator *op) info = AUD_getInfo(sound->playback_handle); if (info.specs.channels == AUD_CHANNELS_INVALID) { - sound_delete(bmain, sound); + BKE_sound_delete(bmain, sound); if (op->customdata) MEM_freeN(op->customdata); BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); return OPERATOR_CANCELLED; @@ -122,11 +122,11 @@ static int sound_open_exec(bContext *C, wmOperator *op) if (RNA_boolean_get(op->ptr, "mono")) { sound->flags |= SOUND_FLAGS_MONO; - sound_load(bmain, sound); + BKE_sound_load(bmain, sound); } if (RNA_boolean_get(op->ptr, "cache")) { - sound_cache(sound); + BKE_sound_cache(sound); } /* hook into UI */ @@ -690,7 +690,7 @@ static int sound_pack_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; sound->packedfile = newPackedFile(op->reports, sound->name, ID_BLEND_PATH(bmain, &sound->id)); - sound_load(bmain, sound); + BKE_sound_load(bmain, sound); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 322825ccc84..17783e1412d 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -912,7 +912,7 @@ static void change_frame_apply(bContext *C, wmOperator *op) SUBFRA = 0.0f; /* do updates */ - sound_seek_scene(CTX_data_main(C), scene); + BKE_sound_seek_scene(CTX_data_main(C), scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 742e58d80dd..c8bea114373 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -3054,7 +3054,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op) if (CFRA != sc->user.framenr) { CFRA = sc->user.framenr; - sound_seek_scene(CTX_data_main(C), scene); + BKE_sound_seek_scene(CTX_data_main(C), scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index da308d0b1f1..b52945297b9 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -88,7 +88,7 @@ static void graphview_cursor_apply(bContext *C, wmOperator *op) */ CFRA = RNA_int_get(op->ptr, "frame"); SUBFRA = 0.f; - sound_seek_scene(bmain, scene); + BKE_sound_seek_scene(bmain, scene); /* set the cursor value */ sipo->cursorVal = RNA_float_get(op->ptr, "value"); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 61667b02140..976c7675371 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -2982,7 +2982,7 @@ static void change_frame_apply(bContext *C, wmOperator *op) SUBFRA = 0.0f; /* do updates */ - sound_seek_scene(CTX_data_main(C), scene); + BKE_sound_seek_scene(CTX_data_main(C), scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 38a01bcd78c..329e6db4cd0 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -287,7 +287,7 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op) BLI_strncpy(seq->name + 2, sce_seq->id.name + 2, sizeof(seq->name) - 2); BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq); - seq->scene_sound = sound_scene_add_scene_sound(scene, seq, start_frame, start_frame + seq->len, 0); + seq->scene_sound = BKE_sound_scene_add_scene_sound(scene, seq, start_frame, start_frame + seq->len, 0); BKE_sequence_calc_disp(scene, seq); BKE_sequencer_sort(scene); diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index dc37b764f65..b45d4277f35 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -3165,7 +3165,7 @@ static void seq_copy_del_sound(Scene *scene, Sequence *seq) } } else if (seq->scene_sound) { - sound_remove_scene_sound(scene, seq->scene_sound); + BKE_sound_remove_scene_sound(scene, seq->scene_sound); seq->scene_sound = NULL; } } @@ -3322,10 +3322,10 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op) } if (seq_act->scene_sound) - sound_remove_scene_sound(scene, seq_act->scene_sound); + BKE_sound_remove_scene_sound(scene, seq_act->scene_sound); if (seq_other->scene_sound) - sound_remove_scene_sound(scene, seq_other->scene_sound); + BKE_sound_remove_scene_sound(scene, seq_other->scene_sound); seq_act->scene_sound = NULL; seq_other->scene_sound = NULL; @@ -3333,8 +3333,8 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op) BKE_sequence_calc(scene, seq_act); BKE_sequence_calc(scene, seq_other); - if (seq_act->sound) sound_add_scene_sound_defaults(scene, seq_act); - if (seq_other->sound) sound_add_scene_sound_defaults(scene, seq_other); + if (seq_act->sound) BKE_sound_add_scene_sound_defaults(scene, seq_act); + if (seq_other->sound) BKE_sound_add_scene_sound_defaults(scene, seq_other); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); diff --git a/source/blender/editors/space_sequencer/sequencer_preview.c b/source/blender/editors/space_sequencer/sequencer_preview.c index c8834d394f5..3f908dc7096 100644 --- a/source/blender/editors/space_sequencer/sequencer_preview.c +++ b/source/blender/editors/space_sequencer/sequencer_preview.c @@ -85,7 +85,7 @@ static void preview_startjob(void *data, short *stop, short *do_update, float *p PreviewJobAudio *preview_next; bSound *sound = previewjb->sound; - sound_read_waveform(sound, stop); + BKE_sound_read_waveform(sound, stop); if (*stop || G.is_break) { BLI_mutex_lock(pj->mutex); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 212f7438265..8cf36367e01 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -538,13 +538,13 @@ static void rna_Scene_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr) static void rna_Scene_fps_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) { - sound_update_fps(scene); + BKE_sound_update_fps(scene); BKE_sequencer_update_sound_bounds_all(scene); } static void rna_Scene_listener_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) { - sound_update_scene_listener(scene); + BKE_sound_update_scene_listener(scene); } static void rna_Scene_volume_set(PointerRNA *ptr, float value) @@ -553,7 +553,7 @@ static void rna_Scene_volume_set(PointerRNA *ptr, float value) scene->audio.volume = value; if (scene->sound_scene) - sound_set_scene_volume(scene, value); + BKE_sound_set_scene_volume(scene, value); } static void rna_Scene_framelen_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) @@ -654,7 +654,7 @@ static void rna_Scene_preview_range_end_frame_set(PointerRNA *ptr, int value) static void rna_Scene_frame_update(Main *bmain, Scene *UNUSED(current_scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->id.data; - sound_seek_scene(bmain, scene); + BKE_sound_seek_scene(bmain, scene); } static PointerRNA rna_Scene_active_keying_set_get(PointerRNA *ptr) @@ -1422,7 +1422,7 @@ static void rna_Scene_use_audio_set(PointerRNA *ptr, int value) else scene->audio.flag &= ~AUDIO_MUTE; - sound_mute_scene(scene, value); + BKE_sound_mute_scene(scene, value); } static int rna_Scene_sync_mode_get(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 1844ce03284..a0756d64d0d 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -577,8 +577,8 @@ static void rna_Sequence_filepath_set(PointerRNA *ptr, const char *value) PointerRNA id_ptr; RNA_id_pointer_create((ID *)seq->sound, &id_ptr); RNA_string_set(&id_ptr, "filepath", value); - sound_load(G.main, seq->sound); - sound_update_scene_sound(seq->scene_sound, seq->sound); + BKE_sound_load(G.main, seq->sound); + BKE_sound_update_scene_sound(seq->scene_sound, seq->sound); } BLI_split_dirfile(value, seq->strip->dir, seq->strip->stripdata->name, sizeof(seq->strip->dir), @@ -633,7 +633,7 @@ static void rna_Sequence_volume_set(PointerRNA *ptr, float value) seq->volume = value; if (seq->scene_sound) - sound_set_scene_sound_volume(seq->scene_sound, value, (seq->flag & SEQ_AUDIO_VOLUME_ANIMATED) != 0); + BKE_sound_set_scene_sound_volume(seq->scene_sound, value, (seq->flag & SEQ_AUDIO_VOLUME_ANIMATED) != 0); } static void rna_Sequence_pitch_set(PointerRNA *ptr, float value) @@ -642,7 +642,7 @@ static void rna_Sequence_pitch_set(PointerRNA *ptr, float value) seq->pitch = value; if (seq->scene_sound) - sound_set_scene_sound_pitch(seq->scene_sound, value, (seq->flag & SEQ_AUDIO_PITCH_ANIMATED) != 0); + BKE_sound_set_scene_sound_pitch(seq->scene_sound, value, (seq->flag & SEQ_AUDIO_PITCH_ANIMATED) != 0); } static void rna_Sequence_pan_set(PointerRNA *ptr, float value) @@ -651,7 +651,7 @@ static void rna_Sequence_pan_set(PointerRNA *ptr, float value) seq->pan = value; if (seq->scene_sound) - sound_set_scene_sound_pan(seq->scene_sound, value, (seq->flag & SEQ_AUDIO_PAN_ANIMATED) != 0); + BKE_sound_set_scene_sound_pan(seq->scene_sound, value, (seq->flag & SEQ_AUDIO_PAN_ANIMATED) != 0); } diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index 351a15c0171..2d3e3c56672 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -158,7 +158,7 @@ static Sequence *rna_Sequences_new_scene(ID *id, Editing *ed, seq = alloc_generic_sequence(ed, name, frame_start, channel, SEQ_TYPE_SCENE, NULL); seq->scene = sce_seq; seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1; - seq->scene_sound = sound_scene_add_scene_sound(scene, seq, frame_start, frame_start + seq->len, 0); + seq->scene_sound = BKE_sound_scene_add_scene_sound(scene, seq, frame_start, frame_start + seq->len, 0); id_us_plus((ID *)sce_seq); BKE_sequence_calc_disp(scene, seq); @@ -225,7 +225,7 @@ static Sequence *rna_Sequences_new_sound(ID *id, Editing *ed, Main *bmain, Repor Scene *scene = (Scene *)id; Sequence *seq; - bSound *sound = sound_new_file(bmain, file); + bSound *sound = BKE_sound_new_file(bmain, file); if (sound == NULL || sound->playback_handle == NULL) { BKE_report(reports, RPT_ERROR, "Sequences.new_sound: unable to open sound file"); @@ -234,9 +234,9 @@ static Sequence *rna_Sequences_new_sound(ID *id, Editing *ed, Main *bmain, Repor seq = alloc_generic_sequence(ed, name, frame_start, channel, SEQ_TYPE_SOUND_RAM, sound->name); seq->sound = sound; - seq->len = ceil((double)sound_get_length(sound) * FPS); + seq->len = ceil((double)BKE_sound_get_length(sound) * FPS); - seq->scene_sound = sound_add_scene_sound(scene, seq, frame_start, frame_start + seq->len, 0); + seq->scene_sound = BKE_sound_add_scene_sound(scene, seq, frame_start, frame_start + seq->len, 0); BKE_sequence_calc_disp(scene, seq); diff --git a/source/blender/makesrna/intern/rna_sound.c b/source/blender/makesrna/intern/rna_sound.c index 4b745c60b5b..25b3475c423 100644 --- a/source/blender/makesrna/intern/rna_sound.c +++ b/source/blender/makesrna/intern/rna_sound.c @@ -42,7 +42,7 @@ static void rna_Sound_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - sound_load(bmain, (bSound *)ptr->data); + BKE_sound_load(bmain, (bSound *)ptr->data); } static int rna_Sound_caching_get(PointerRNA *ptr) @@ -55,9 +55,9 @@ static void rna_Sound_caching_set(PointerRNA *ptr, const int value) { bSound *sound = (bSound *)(ptr->data); if (value) - sound_cache(sound); + BKE_sound_cache(sound); else - sound_delete_cache(sound); + BKE_sound_delete_cache(sound); } static void rna_Sound_caching_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index e60af76851e..beb5ae739b3 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -331,7 +331,7 @@ static PointerRNA rna_UserDef_system_get(PointerRNA *ptr) static void rna_UserDef_audio_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) { - sound_init(bmain); + BKE_sound_init(bmain); } static void rna_Userdef_memcache_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index f1a46826435..e8004297011 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2223,7 +2223,7 @@ void wm_event_do_handlers(bContext *C) Scene *scene = win->screen->scene; if (scene) { - int is_playing_sound = sound_scene_playing(win->screen->scene); + int is_playing_sound = BKE_sound_scene_playing(win->screen->scene); if (is_playing_sound != -1) { bool is_playing_screen; @@ -2240,7 +2240,7 @@ void wm_event_do_handlers(bContext *C) } if (is_playing_sound == 0) { - const float time = sound_sync_scene(scene); + const float time = BKE_sound_sync_scene(scene); if (finite(time)) { int ncfra = time * (float)FPS + 0.5f; if (ncfra != scene->r.cfra) { diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index f5a7ad164d6..697a798ed3c 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -301,7 +301,7 @@ static void wm_init_userdef(bContext *C, const bool from_memory) UI_init_userdef(); MEM_CacheLimiter_set_maximum(((size_t)U.memcachelimit) * 1024 * 1024); - sound_init(bmain); + BKE_sound_init(bmain); /* needed so loading a file from the command line respects user-pref [#26156] */ BKE_BIT_TEST_SET(G.fileflags, U.flag & USER_FILENOUI, G_FILE_NO_UI); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 32a49b6e160..f1f73563dec 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -328,7 +328,7 @@ bool WM_init_game(bContext *C) WM_operator_name_call(C, "VIEW3D_OT_game_start", WM_OP_EXEC_DEFAULT, NULL); - sound_exit(); + BKE_sound_exit(); return true; } @@ -398,7 +398,7 @@ void WM_exit_ext(bContext *C, const bool do_python) { wmWindowManager *wm = C ? CTX_wm_manager(C) : NULL; - sound_exit(); + BKE_sound_exit(); /* first wrap up running stuff, we assume only the active WM is running */ /* modal handlers are on window level freed, others too? */ diff --git a/source/creator/creator.c b/source/creator/creator.c index 9815b3c7211..b2b650419d6 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -811,7 +811,7 @@ static int no_glsl(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(dat static int no_audio(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data)) { - sound_force_device(0); + BKE_sound_force_device(0); return 0; } @@ -822,7 +822,7 @@ static int set_audio(int argc, const char **argv, void *UNUSED(data)) exit(1); } - sound_force_device(sound_define_from_str(argv[1])); + BKE_sound_force_device(BKE_sound_define_from_str(argv[1])); return 1; } @@ -1755,7 +1755,7 @@ int main( /* Initialize ffmpeg if built in, also needed for bg mode if videos are * rendered via ffmpeg */ - sound_init_once(); + BKE_sound_init_once(); init_def_material(); diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 6b69a991968..b8ce67743de 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -636,7 +636,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) if (!m_networkdevice) goto initFailed; - sound_init(m_maggie); + BKE_sound_init(m_maggie); // create a ketsjisystem (only needed for timing and stuff) m_kxsystem = new GPG_System (m_system); @@ -672,7 +672,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) return m_engineInitialized; initFailed: - sound_exit(); + BKE_sound_exit(); delete m_kxsystem; delete m_networkdevice; delete m_mouse; @@ -847,7 +847,7 @@ void GPG_Application::exitEngine() if (!m_engineInitialized) return; - sound_exit(); + BKE_sound_exit(); if (m_ketsjiengine) { stopEngine(); diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 915fe614957..a4c9472df2f 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -517,7 +517,7 @@ int main(int argc, char** argv) // enable fast mipmap generation U.use_gpu_mipmap = 1; - sound_init_once(); + BKE_sound_init_once(); set_free_windowmanager_cb(wm_free); -- cgit v1.2.3 From dc3b869c9aed56bf75955436bdb527df0be933f3 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 26 Mar 2015 11:39:08 +0100 Subject: Missed those last commit --- source/blender/blenkernel/BKE_sound.h | 6 +++--- source/blender/blenkernel/intern/sound.c | 6 +++--- source/blender/blenkernel/intern/writeffmpeg.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 3570751165c..d3919a3a6c0 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -62,9 +62,9 @@ struct bSound *BKE_sound_new_file(struct Main *main, const char *filename); // XXX unused currently #if 0 -struct bSound *sound_new_buffer(struct Main *bmain, struct bSound *source); +struct bSound *BKE_sound_new_buffer(struct Main *bmain, struct bSound *source); -struct bSound *sound_new_limiter(struct Main *bmain, struct bSound *source, float start, float end); +struct bSound *BKE_sound_new_limiter(struct Main *bmain, struct bSound *source, float start, float end); #endif void BKE_sound_delete(struct Main *bmain, struct bSound *sound); @@ -78,7 +78,7 @@ void BKE_sound_load(struct Main *main, struct bSound *sound); void BKE_sound_free(struct bSound *sound); #ifdef __AUD_C_API_H__ -AUD_Device *sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume); +AUD_Device *BKE_sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume); #endif void BKE_sound_create_scene(struct Scene *scene); diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index cc0d0bdcfcc..89be80e5328 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -231,7 +231,7 @@ void BKE_sound_exit_once(void) /* XXX unused currently */ #if 0 -bSound *sound_new_buffer(struct Main *bmain, bSound *source) +bSound *BKE_sound_new_buffer(struct Main *bmain, bSound *source) { bSound *sound = NULL; @@ -255,7 +255,7 @@ bSound *sound_new_buffer(struct Main *bmain, bSound *source) return sound; } -bSound *sound_new_limiter(struct Main *bmain, bSound *source, float start, float end) +bSound *BKE_sound_new_limiter(struct Main *bmain, bSound *source, float start, float end) { bSound *sound = NULL; @@ -386,7 +386,7 @@ void BKE_sound_load(struct Main *bmain, bSound *sound) } } -AUD_Device *sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume) +AUD_Device *BKE_sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume) { return AUD_openMixdownDevice(specs, scene->sound_scene, volume, start / FPS); } diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 128a5da9b68..57a4927e149 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -1111,7 +1111,7 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, } specs.rate = rd->ffcodecdata.audio_mixrate; - audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume); + audio_mixdown_device = BKE_sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume); #ifdef FFMPEG_CODEC_TIME_BASE c->time_base.den = specs.rate; c->time_base.num = 1; -- cgit v1.2.3 From 59132e6481ef1ba43404b7b367e1cbfb94f7df3f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 26 Mar 2015 16:33:20 +0500 Subject: Fix building with audaspace disabled after 828c85a --- source/blender/blenkernel/intern/sound.c | 86 ++++++++++++++++---------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 89be80e5328..4d14b2f22de 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -828,47 +828,47 @@ bool BKE_sound_is_jack_supported(void) #include "BLI_utildefines.h" -int sound_define_from_str(const char *UNUSED(str)) { return -1; } -void sound_force_device(int UNUSED(device)) {} -void sound_init_once(void) {} -void sound_init(struct Main *UNUSED(bmain)) {} -void sound_exit(void) {} -void sound_exit_once(void) {} -void sound_cache(struct bSound *UNUSED(sound)) {} -void sound_delete_cache(struct bSound *UNUSED(sound)) {} -void sound_load(struct Main *UNUSED(bmain), struct bSound *UNUSED(sound)) {} -void sound_create_scene(struct Scene *UNUSED(scene)) {} -void sound_destroy_scene(struct Scene *UNUSED(scene)) {} -void sound_mute_scene(struct Scene *UNUSED(scene), int UNUSED(muted)) {} -void *sound_scene_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence), - int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; } -void *sound_scene_add_scene_sound_defaults(struct Scene *UNUSED(scene), - struct Sequence *UNUSED(sequence)) { return NULL; } -void *sound_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence), int UNUSED(startframe), - int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; } -void *sound_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) { return NULL; } -void sound_remove_scene_sound(struct Scene *UNUSED(scene), void *UNUSED(handle)) {} -void sound_mute_scene_sound(void *UNUSED(handle), char UNUSED(mute)) {} -void sound_move_scene_sound(struct Scene *UNUSED(scene), void *UNUSED(handle), int UNUSED(startframe), - int UNUSED(endframe), int UNUSED(frameskip)) {} -void sound_move_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) {} -void sound_play_scene(struct Scene *UNUSED(scene)) {} -void sound_stop_scene(struct Scene *UNUSED(scene)) {} -void sound_seek_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {} -float sound_sync_scene(struct Scene *UNUSED(scene)) { return NAN_FLT; } -int sound_scene_playing(struct Scene *UNUSED(scene)) { return -1; } -void sound_read_waveform(struct bSound *sound, short *stop) { UNUSED_VARS(sound, stop); } -void sound_init_main(struct Main *UNUSED(bmain)) {} -void sound_set_cfra(int UNUSED(cfra)) {} -void sound_update_sequencer(struct Main *UNUSED(main), struct bSound *UNUSED(sound)) {} -void sound_update_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {} -void sound_update_scene_sound(void *UNUSED(handle), struct bSound *UNUSED(sound)) {} -void sound_update_scene_listener(struct Scene *UNUSED(scene)) {} -void sound_update_fps(struct Scene *UNUSED(scene)) {} -void sound_set_scene_sound_volume(void *UNUSED(handle), float UNUSED(volume), char UNUSED(animated)) {} -void sound_set_scene_sound_pan(void *UNUSED(handle), float UNUSED(pan), char UNUSED(animated)) {} -void sound_set_scene_volume(struct Scene *UNUSED(scene), float UNUSED(volume)) {} -void sound_set_scene_sound_pitch(void *UNUSED(handle), float UNUSED(pitch), char UNUSED(animated)) {} -float sound_get_length(struct bSound *UNUSED(sound)) { return 0; } -bool sound_is_jack_supported(void) { return false; } +int BKE_sound_define_from_str(const char *UNUSED(str)) { return -1; } +void BKE_sound_force_device(int UNUSED(device)) {} +void BKE_sound_init_once(void) {} +void BKE_sound_init(struct Main *UNUSED(bmain)) {} +void BKE_sound_exit(void) {} +void BKE_sound_exit_once(void) {} +void BKE_sound_cache(struct bSound *UNUSED(sound)) {} +void BKE_sound_delete_cache(struct bSound *UNUSED(sound)) {} +void BKE_sound_load(struct Main *UNUSED(bmain), struct bSound *UNUSED(sound)) {} +void BKE_sound_create_scene(struct Scene *UNUSED(scene)) {} +void BKE_sound_destroy_scene(struct Scene *UNUSED(scene)) {} +void BKE_sound_mute_scene(struct Scene *UNUSED(scene), int UNUSED(muted)) {} +void *BKE_sound_scene_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence), + int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; } +void *BKE_sound_scene_add_scene_sound_defaults(struct Scene *UNUSED(scene), + struct Sequence *UNUSED(sequence)) { return NULL; } +void *BKE_sound_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence), int UNUSED(startframe), + int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; } +void *BKE_sound_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) { return NULL; } +void BKE_sound_remove_scene_sound(struct Scene *UNUSED(scene), void *UNUSED(handle)) {} +void BKE_sound_mute_scene_sound(void *UNUSED(handle), char UNUSED(mute)) {} +void BKE_sound_move_scene_sound(struct Scene *UNUSED(scene), void *UNUSED(handle), int UNUSED(startframe), + int UNUSED(endframe), int UNUSED(frameskip)) {} +void BKE_sound_move_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) {} +void BKE_sound_play_scene(struct Scene *UNUSED(scene)) {} +void BKE_sound_stop_scene(struct Scene *UNUSED(scene)) {} +void BKE_sound_seek_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {} +float BKE_sound_sync_scene(struct Scene *UNUSED(scene)) { return NAN_FLT; } +int BKE_sound_scene_playing(struct Scene *UNUSED(scene)) { return -1; } +void BKE_sound_read_waveform(struct bSound *sound, short *stop) { UNUSED_VARS(sound, stop); } +void BKE_sound_init_main(struct Main *UNUSED(bmain)) {} +void BKE_sound_set_cfra(int UNUSED(cfra)) {} +void BKE_sound_update_sequencer(struct Main *UNUSED(main), struct bSound *UNUSED(sound)) {} +void BKE_sound_update_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {} +void BKE_sound_update_scene_sound(void *UNUSED(handle), struct bSound *UNUSED(sound)) {} +void BKE_sound_update_scene_listener(struct Scene *UNUSED(scene)) {} +void BKE_sound_update_fps(struct Scene *UNUSED(scene)) {} +void BKE_sound_set_scene_sound_volume(void *UNUSED(handle), float UNUSED(volume), char UNUSED(animated)) {} +void BKE_sound_set_scene_sound_pan(void *UNUSED(handle), float UNUSED(pan), char UNUSED(animated)) {} +void BKE_sound_set_scene_volume(struct Scene *UNUSED(scene), float UNUSED(volume)) {} +void BKE_sound_set_scene_sound_pitch(void *UNUSED(handle), float UNUSED(pitch), char UNUSED(animated)) {} +float BKE_sound_get_length(struct bSound *UNUSED(sound)) { return 0; } +bool BKE_sound_is_jack_supported(void) { return false; } #endif /* WITH_AUDASPACE */ -- cgit v1.2.3 From f80064f2d24408aa85c84f3c328ef470baf39e7c Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Thu, 26 Mar 2015 13:19:33 +0100 Subject: Fix compiling after sound changes --- source/blender/blenkernel/intern/sound.c | 4 ++-- source/blender/makesrna/intern/rna_userdef.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 4d14b2f22de..6a831d23aea 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -141,9 +141,9 @@ static void sound_sync_callback(void *data, int mode, float time) while (scene) { if (scene->audio.flag & AUDIO_SYNC) { if (mode) - sound_play_scene(scene); + BKE_sound_play_scene(scene); else - sound_stop_scene(scene); + BKE_sound_stop_scene(scene); if (scene->sound_scene_handle) AUD_seek(scene->sound_scene_handle, time); } diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index beb5ae739b3..15a4ef5eaf6 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -548,7 +548,7 @@ static EnumPropertyItem *rna_userdef_audio_device_itemf(bContext *UNUSED(C), Poi #endif #ifdef WITH_JACK - if (sound_is_jack_supported()) { + if (BKE_sound_is_jack_supported()) { RNA_enum_item_add(&item, &totitem, &audio_device_items[index]); } index++; -- cgit v1.2.3 From c0ef4e9b788b8db433bf3e92bd19ee00f86f9866 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 26 Mar 2015 14:49:59 +0100 Subject: Fix T44122, rendering OpenGL preview movie with audio has wrong audio range and extra frames. Issue here is that the movie backend would unconditionally use the start frame of the scene instead of the preview frame. Solved by passing an explicit "preview" argument. Strictly speaking, the preview argument is part of the renderdata struct, that is also passed to the code, but when rendering the final result we want to unconditionally render the full range regardless of the preview setting of the render structure. However, OpenGL rendering does use the preview range so we need to account for that when making those exports. This is also a nice chance to correct the filenames, which still used the full range. --- source/blender/blenkernel/BKE_writeavi.h | 4 +- source/blender/blenkernel/BKE_writeffmpeg.h | 4 +- source/blender/blenkernel/BKE_writeframeserver.h | 2 +- source/blender/blenkernel/intern/writeavi.c | 33 ++++++++------ source/blender/blenkernel/intern/writeffmpeg.c | 26 ++++++++--- .../blender/blenkernel/intern/writeframeserver.c | 2 +- source/blender/editors/render/render_opengl.c | 2 +- source/blender/editors/screen/screendump.c | 2 +- source/blender/quicktime/apple/qtkit_export.m | 50 ++++++++++++++++++---- source/blender/quicktime/quicktime_export.h | 6 +-- source/blender/render/intern/source/pipeline.c | 3 +- 11 files changed, 94 insertions(+), 40 deletions(-) diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h index 78875951ca4..8206c36b895 100644 --- a/source/blender/blenkernel/BKE_writeavi.h +++ b/source/blender/blenkernel/BKE_writeavi.h @@ -43,12 +43,12 @@ struct ReportList; struct Scene; typedef struct bMovieHandle { - int (*start_movie)(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); + int (*start_movie)(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview); int (*append_movie)(struct RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); void (*end_movie)(void); int (*get_next_frame)(struct RenderData *rd, struct ReportList *reports); /* optional */ - void (*get_movie_path)(char *string, struct RenderData *rd); /* optional */ + void (*get_movie_path)(char *string, struct RenderData *rd, bool preview); /* optional */ } bMovieHandle; bMovieHandle *BKE_movie_handle_get(const char imtype); diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h index 703e84b3798..ba6360964d6 100644 --- a/source/blender/blenkernel/BKE_writeffmpeg.h +++ b/source/blender/blenkernel/BKE_writeffmpeg.h @@ -69,11 +69,11 @@ struct RenderData; struct ReportList; struct Scene; -int BKE_ffmpeg_start(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); +int BKE_ffmpeg_start(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview); void BKE_ffmpeg_end(void); int BKE_ffmpeg_append(struct RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); -void BKE_ffmpeg_filepath_get(char *string, struct RenderData *rd); +void BKE_ffmpeg_filepath_get(char *string, struct RenderData *rd, bool preview); void BKE_ffmpeg_preset_set(struct RenderData *rd, int preset); void BKE_ffmpeg_image_type_verify(struct RenderData *rd, struct ImageFormatData *imf); diff --git a/source/blender/blenkernel/BKE_writeframeserver.h b/source/blender/blenkernel/BKE_writeframeserver.h index bdce9abe8ad..b7d601ea769 100644 --- a/source/blender/blenkernel/BKE_writeframeserver.h +++ b/source/blender/blenkernel/BKE_writeframeserver.h @@ -40,7 +40,7 @@ struct RenderData; struct ReportList; struct Scene; -int BKE_frameserver_start(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); +int BKE_frameserver_start(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview); void BKE_frameserver_end(void); int BKE_frameserver_append(struct RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index 85eac1f21ed..b0e23b6b603 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -51,7 +51,7 @@ /* ********************** general blender movie support ***************************** */ static int start_stub(Scene *UNUSED(scene), RenderData *UNUSED(rd), int UNUSED(rectx), int UNUSED(recty), - ReportList *UNUSED(reports)) + ReportList *UNUSED(reports), bool UNUSED(preview)) { return 0; } static void end_stub(void) @@ -65,11 +65,11 @@ static int append_stub(RenderData *UNUSED(rd), int UNUSED(start_frame), int UNUS # include "AVI_avi.h" /* callbacks */ -static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports); +static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview); static void end_avi(void); static int append_avi(RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, ReportList *reports); -static void filepath_avi(char *string, RenderData *rd); +static void filepath_avi(char *string, RenderData *rd, bool preview); #endif /* WITH_AVI */ #ifdef WITH_QUICKTIME @@ -129,9 +129,7 @@ bMovieHandle *BKE_movie_handle_get(const char imtype) #endif /* in case all above are disabled */ - (void)imtype; - - return &mh; + (void)imtype;return &mh; } /* ****************************************************************** */ @@ -141,10 +139,21 @@ bMovieHandle *BKE_movie_handle_get(const char imtype) static AviMovie *avi = NULL; -static void filepath_avi(char *string, RenderData *rd) +static void filepath_avi(char *string, RenderData *rd, bool preview) { + int sfra, efra; + if (string == NULL) return; + if (preview) { + sfra = rd->psfra; + efra = rd->pefra; + } + else { + sfra = rd->sfra; + efra = rd->efra; + } + strcpy(string, rd->pic); BLI_path_abs(string, G.main->name); @@ -152,18 +161,18 @@ static void filepath_avi(char *string, RenderData *rd) if (rd->scemode & R_EXTENSION) { if (!BLI_testextensie(string, ".avi")) { - BLI_path_frame_range(string, rd->sfra, rd->efra, 4); + BLI_path_frame_range(string, sfra, efra, 4); strcat(string, ".avi"); } } else { if (BLI_path_frame_check_chars(string)) { - BLI_path_frame_range(string, rd->sfra, rd->efra, 4); + BLI_path_frame_range(string, sfra, efra, 4); } } } -static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports) +static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview) { int x, y; char name[256]; @@ -173,7 +182,7 @@ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportL (void)scene; /* unused */ - filepath_avi(name, rd); + filepath_avi(name, rd, preview); x = rectx; y = recty; @@ -258,7 +267,7 @@ void BKE_movie_filepath_get(char *string, RenderData *rd) { bMovieHandle *mh = BKE_movie_handle_get(rd->im_format.imtype); if (mh->get_movie_path) - mh->get_movie_path(string, rd); + mh->get_movie_path(string, rd, false); else string[0] = '\0'; } diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 57a4927e149..0717369cde8 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -69,6 +69,7 @@ static int ffmpeg_audio_bitrate = 128; static int ffmpeg_gop_size = 12; static int ffmpeg_autosplit = 0; static int ffmpeg_autosplit_count = 0; +static bool ffmpeg_preview = false; static AVFormatContext *outfile = 0; static AVStream *video_stream = 0; @@ -816,7 +817,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT; /* Determine the correct filename */ - BKE_ffmpeg_filepath_get(name, rd); + BKE_ffmpeg_filepath_get(name, rd, ffmpeg_preview); PRINT("Starting output to %s(ffmpeg)...\n" " Using type=%d, codec=%d, audio_codec=%d,\n" " video_bitrate=%d, audio_bitrate=%d,\n" @@ -1028,15 +1029,25 @@ static void flush_ffmpeg(void) * ********************************************************************** */ /* Get the output filename-- similar to the other output formats */ -void BKE_ffmpeg_filepath_get(char *string, RenderData *rd) +void BKE_ffmpeg_filepath_get(char *string, RenderData *rd, bool preview) { char autosplit[20]; const char **exts = get_file_extensions(rd->ffcodecdata.type); const char **fe = exts; + int sfra, efra; if (!string || !exts) return; + if (preview) { + sfra = rd->psfra; + efra = rd->pefra; + } + else { + sfra = rd->sfra; + efra = rd->efra; + } + strcpy(string, rd->pic); BLI_path_abs(string, G.main->name); @@ -1059,7 +1070,7 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd) if (*fe == NULL) { strcat(string, autosplit); - BLI_path_frame_range(string, rd->sfra, rd->efra, 4); + BLI_path_frame_range(string, sfra, efra, 4); strcat(string, *exts); } else { @@ -1070,18 +1081,19 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd) } else { if (BLI_path_frame_check_chars(string)) { - BLI_path_frame_range(string, rd->sfra, rd->efra, 4); + BLI_path_frame_range(string, sfra, efra, 4); } strcat(string, autosplit); } } -int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports) +int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview) { int success; ffmpeg_autosplit_count = 0; + ffmpeg_preview = preview; success = start_ffmpeg_impl(rd, rectx, recty, reports); #ifdef WITH_AUDASPACE @@ -1111,7 +1123,7 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, } specs.rate = rd->ffcodecdata.audio_mixrate; - audio_mixdown_device = BKE_sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume); + audio_mixdown_device = BKE_sound_mixdown(scene, specs, preview ? rd->psfra : rd->sfra, rd->ffcodecdata.audio_volume); #ifdef FFMPEG_CODEC_TIME_BASE c->time_base.den = specs.rate; c->time_base.num = 1; @@ -1162,7 +1174,7 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i } #ifdef WITH_AUDASPACE - write_audio_frames((frame - rd->sfra) / (((double)rd->frs_sec) / (double)rd->frs_sec_base)); + write_audio_frames((frame - start_frame) / (((double)rd->frs_sec) / (double)rd->frs_sec_base)); #endif return success; } diff --git a/source/blender/blenkernel/intern/writeframeserver.c b/source/blender/blenkernel/intern/writeframeserver.c index ae6b19fb019..9cac86d62bd 100644 --- a/source/blender/blenkernel/intern/writeframeserver.c +++ b/source/blender/blenkernel/intern/writeframeserver.c @@ -110,7 +110,7 @@ static int closesocket(int fd) } #endif -int BKE_frameserver_start(struct Scene *scene, RenderData *UNUSED(rd), int rectx, int recty, ReportList *reports) +int BKE_frameserver_start(struct Scene *scene, RenderData *UNUSED(rd), int rectx, int recty, ReportList *reports, bool UNUSED(preview)) { struct sockaddr_in addr; int arg = 1; diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index d8da0e9bcda..5c8bee07420 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -556,7 +556,7 @@ static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op) oglrender->reports = op->reports; oglrender->mh = BKE_movie_handle_get(scene->r.im_format.imtype); if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { - if (!oglrender->mh->start_movie(scene, &scene->r, oglrender->sizex, oglrender->sizey, oglrender->reports)) { + if (!oglrender->mh->start_movie(scene, &scene->r, oglrender->sizex, oglrender->sizey, oglrender->reports, PRVRANGEON != 0)) { screen_opengl_render_end(C, oglrender); return 0; } diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 9c05f1d4780..330bc7e3395 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -344,7 +344,7 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float rd.frs_sec_base = 1.0f; if (BKE_imtype_is_movie(rd.im_format.imtype)) { - if (!mh->start_movie(sj->scene, &rd, sj->dumpsx, sj->dumpsy, &sj->reports)) { + if (!mh->start_movie(sj->scene, &rd, sj->dumpsx, sj->dumpsy, &sj->reports, false)) { printf("screencast job stopped\n"); return; } diff --git a/source/blender/quicktime/apple/qtkit_export.m b/source/blender/quicktime/apple/qtkit_export.m index cbc76e26aa9..4214fa9ac32 100644 --- a/source/blender/quicktime/apple/qtkit_export.m +++ b/source/blender/quicktime/apple/qtkit_export.m @@ -219,10 +219,21 @@ static NSString *stringWithCodecType(int codecType) return [NSString stringWithCString:str encoding:NSASCIIStringEncoding]; } -void makeqtstring(RenderData *rd, char *string) +void makeqtstring(RenderData *rd, char *string, bool preview) { + int sfra, efra; + char txt[64]; + if (preview) { + sfra = rd->psfra; + efra = rd->pefra; + } + else { + sfra = rd->sfra; + efra = rd->efra; + } + strcpy(string, rd->pic); BLI_path_abs(string, G.main->name); @@ -234,10 +245,21 @@ void makeqtstring(RenderData *rd, char *string) } } -void filepath_qt(char *string, RenderData *rd) +void filepath_qt(char *string, RenderData *rd, bool preview) { + int sfra, efra; + if (string == NULL) return; + if (preview) { + sfra = rd->psfra; + efra = rd->pefra; + } + else { + sfra = rd->sfra; + efra = rd->efra; + } + strcpy(string, rd->pic); BLI_path_abs(string, G.main->name); @@ -245,13 +267,13 @@ void filepath_qt(char *string, RenderData *rd) if (rd->scemode & R_EXTENSION) { if (!BLI_testextensie(string, ".mov")) { - BLI_path_frame_range(string, rd->sfra, rd->efra, 4); + BLI_path_frame_range(string, sfra, efra, 4); strcat(string, ".mov"); } } else { if (BLI_path_frame_check_chars(string)) { - BLI_path_frame_range(string, rd->sfra, rd->efra, 4); + BLI_path_frame_range(string, sfra, efra, 4); } } } @@ -312,16 +334,26 @@ static OSStatus AudioConverterInputCallback(AudioConverterRef inAudioConverter, #pragma mark export functions -int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, ReportList *reports) +int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, ReportList *reports, bool preview) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSError *error; char name[1024]; int success = 1; OSStatus err = noErr; + int sfra, efra; if (qtexport == NULL) qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport"); + if (preview) { + sfra = rd->psfra; + efra = rd->pefra; + } + else { + sfra = rd->sfra; + efra = rd->efra; + } + [QTMovie enterQTKitOnThread]; /* Check first if the QuickTime 7.2.1 initToWritableFile: method is available */ @@ -330,7 +362,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R success = 0; } else { - makeqtstring(rd, name); + makeqtstring(rd, name, preview); qtexport->filename = [[NSString alloc] initWithCString:name encoding:[NSString defaultCStringEncoding]]; qtexport->movie = nil; @@ -591,13 +623,13 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R specs.format = U.audioformat; specs.rate = U.audiorate; qtexport->audioInputDevice = AUD_openReadDevice(specs); - AUD_playDevice(qtexport->audioInputDevice, scene->sound_scene, rd->sfra * rd->frs_sec_base / rd->frs_sec); + AUD_playDevice(qtexport->audioInputDevice, scene->sound_scene, sfra * rd->frs_sec_base / rd->frs_sec); qtexport->audioOutputPktPos = 0; qtexport->audioTotalExportedFrames = 0; qtexport->audioTotalSavedFrames = 0; - qtexport->audioLastFrame = (rd->efra - rd->sfra) * qtexport->audioInputFormat.mSampleRate * rd->frs_sec_base / rd->frs_sec; + qtexport->audioLastFrame = (efra - sfra) * qtexport->audioInputFormat.mSampleRate * rd->frs_sec_base / rd->frs_sec; } } } @@ -654,7 +686,7 @@ int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, in UInt32 audioPacketsConverted; // Upper limit on total exported audio frames for this particular video frame - const UInt64 exportedAudioFrameLimit = (frame - rd->sfra) * qtexport->audioInputFormat.mSampleRate * rd->frs_sec_base / rd->frs_sec; + const UInt64 exportedAudioFrameLimit = (frame - start_frame) * qtexport->audioInputFormat.mSampleRate * rd->frs_sec_base / rd->frs_sec; /* Append audio */ while (qtexport->audioTotalExportedFrames < exportedAudioFrameLimit) { diff --git a/source/blender/quicktime/quicktime_export.h b/source/blender/quicktime/quicktime_export.h index a499cd462b7..6709f87fb1c 100644 --- a/source/blender/quicktime/quicktime_export.h +++ b/source/blender/quicktime/quicktime_export.h @@ -56,10 +56,10 @@ struct ReportList; struct Scene; struct wmOperatorType; -int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); //for movie handle (BKE writeavi.c now) +int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview); //for movie handle (BKE writeavi.c now) int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); void end_qt(void); -void filepath_qt(char *string, struct RenderData *rd); +void filepath_qt(char *string, struct RenderData *rd, bool preview); /*RNA helper functions */ void quicktime_verify_image_type(struct RenderData *rd, struct ImageFormatData *imf); //used by RNA for defaults values init, if needed @@ -76,7 +76,7 @@ int quicktime_rnatmpvalue_from_audiocodectype(int codecType); int quicktime_audiocodecType_from_rnatmpvalue(int rnatmpvalue); void free_qtcomponentdata(void); -void makeqtstring(struct RenderData *rd, char *string); //for playanim.c +void makeqtstring(struct RenderData *rd, char *string, bool preview); //for playanim.c diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index b397db7c31b..fe51696b16c 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -3025,7 +3025,8 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri height = re->recty; } - if (!mh->start_movie(scene, &re->r, width, height, re->reports)) + /* last argument here depends on users really, but no users using preview have been found so far */ + if (!mh->start_movie(scene, &re->r, width, height, re->reports, false)) G.is_break = true; } -- cgit v1.2.3 From d084967627c5d568c87c616cead4f468d9a21887 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 26 Mar 2015 15:44:51 +0100 Subject: Revert "Change Enables proxy operator to Copy proxy operator." This reverts commit ec03ab021f171bf529746bb440756fbc986b45e7. Changing this since it looks like Mattieu does not really like the change. Will be adding another way to tweak the directories --- release/scripts/startup/bl_ui/space_sequencer.py | 26 +++++--- .../editors/space_sequencer/sequencer_edit.c | 74 ++++++++++++++-------- .../editors/space_sequencer/sequencer_intern.h | 2 +- .../editors/space_sequencer/sequencer_ops.c | 2 +- 4 files changed, 68 insertions(+), 36 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index feaef352978..4f83cc03b10 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -926,14 +926,24 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel): flow.prop(proxy, "directory") if proxy.use_proxy_custom_file: flow.prop(proxy, "filepath") - + layout.label("Enabled Proxies:") - col = layout.column() - col.prop(proxy, "build_25") - col.prop(proxy, "build_50") - col.prop(proxy, "build_75") - col.prop(proxy, "build_100") - col.prop(proxy, "use_overwrite") + enabled = "" + row = layout.row() + if (proxy.build_25): + enabled += "25% " + if (proxy.build_50): + enabled += "50% " + if (proxy.build_75): + enabled += "75% " + if (proxy.build_100): + enabled += "100% " + + row.label(enabled) + if (proxy.use_overwrite): + layout.label("Overwrite On") + else: + layout.label("Overwrite Off") col = layout.column() col.label(text="Build JPEG quality") @@ -946,7 +956,7 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel): col.prop(proxy, "timecode") col = layout.column() - col.operator("sequencer.copy_proxy_settings") + col.operator("sequencer.enable_proxies") col.operator("sequencer.rebuild_proxy") diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index b45d4277f35..ad38cb66946 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -3473,31 +3473,24 @@ void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER; } -static int sequencer_copy_proxy_settings_exec(bContext *C, wmOperator *UNUSED(op)) +static int sequencer_enable_proxies_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 5 * UI_UNIT_Y); +} + +static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Editing *ed = BKE_sequencer_editing_get(scene, false); - Sequence *actseq = ed->act_seq; Sequence *seq; - StripProxy *actproxy, *proxy; - bool proxy_25; - bool proxy_50; - bool proxy_75; - bool proxy_100; + bool proxy_25 = RNA_boolean_get(op->ptr, "proxy_25"); + bool proxy_50 = RNA_boolean_get(op->ptr, "proxy_50"); + bool proxy_75 = RNA_boolean_get(op->ptr, "proxy_75"); + bool proxy_100 = RNA_boolean_get(op->ptr, "proxy_100"); + bool override = RNA_boolean_get(op->ptr, "override"); bool turnon = true; - if (ed == NULL || actseq == NULL || !actseq->strip || !actseq->strip->proxy) { - return OPERATOR_CANCELLED; - } - - actproxy = actseq->strip->proxy; - - proxy_25 = (actproxy->build_size_flags & SEQ_PROXY_IMAGE_SIZE_25) != 0; - proxy_50 = (actproxy->build_size_flags & SEQ_PROXY_IMAGE_SIZE_50) != 0; - proxy_75 = (actproxy->build_size_flags & SEQ_PROXY_IMAGE_SIZE_75) != 0; - proxy_100 = (actproxy->build_size_flags & SEQ_PROXY_IMAGE_SIZE_100) != 0; - - if (!(proxy_25 || proxy_50 || proxy_75 || proxy_100)) { + if (ed == NULL || !(proxy_25 || proxy_50 || proxy_75 || proxy_100)) { turnon = false; } @@ -3510,8 +3503,30 @@ static int sequencer_copy_proxy_settings_exec(bContext *C, wmOperator *UNUSED(op continue; } - proxy = seq->strip->proxy; - *proxy = *actproxy; + if (proxy_25) + seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_25; + else + seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_25; + + if (proxy_50) + seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_50; + else + seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_50; + + if (proxy_75) + seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_75; + else + seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_75; + + if (proxy_100) + seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_100; + else + seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_100; + + if (!override) + seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING; + else + seq->strip->proxy->build_flags &= ~SEQ_PROXY_SKIP_EXISTING; } } } @@ -3522,18 +3537,25 @@ static int sequencer_copy_proxy_settings_exec(bContext *C, wmOperator *UNUSED(op return OPERATOR_FINISHED; } -void SEQUENCER_OT_copy_proxy_settings(wmOperatorType *ot) +void SEQUENCER_OT_enable_proxies(wmOperatorType *ot) { /* identifiers */ - ot->name = "Copy Proxy Settings"; - ot->idname = "SEQUENCER_OT_copy_proxy_settings"; - ot->description = "Copy proxy settings of active strip selected strips"; + ot->name = "Set Selected Strip Proxies"; + ot->idname = "SEQUENCER_OT_enable_proxies"; + ot->description = "Enable selected proxies on all selected Movie strips"; /* api callbacks */ - ot->exec = sequencer_copy_proxy_settings_exec; + ot->invoke = sequencer_enable_proxies_invoke; + ot->exec = sequencer_enable_proxies_exec; /* flags */ ot->flag = OPTYPE_REGISTER; + + RNA_def_boolean(ot->srna, "proxy_25", false, "25%", ""); + RNA_def_boolean(ot->srna, "proxy_50", false, "50%", ""); + RNA_def_boolean(ot->srna, "proxy_75", false, "75%", ""); + RNA_def_boolean(ot->srna, "proxy_100", false, "100%", ""); + RNA_def_boolean(ot->srna, "override", false, "Override", ""); } /* change ops */ diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index 8db0df51035..461c72961c2 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -131,7 +131,7 @@ void SEQUENCER_OT_copy(struct wmOperatorType *ot); void SEQUENCER_OT_paste(struct wmOperatorType *ot); void SEQUENCER_OT_rebuild_proxy(struct wmOperatorType *ot); -void SEQUENCER_OT_copy_proxy_settings(struct wmOperatorType *ot); +void SEQUENCER_OT_enable_proxies(struct wmOperatorType *ot); /* preview specific operators */ void SEQUENCER_OT_view_all_preview(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c index 29fd2deeb55..33a8a1c5b41 100644 --- a/source/blender/editors/space_sequencer/sequencer_ops.c +++ b/source/blender/editors/space_sequencer/sequencer_ops.c @@ -88,7 +88,7 @@ void sequencer_operatortypes(void) WM_operatortype_append(SEQUENCER_OT_view_ghost_border); WM_operatortype_append(SEQUENCER_OT_rebuild_proxy); - WM_operatortype_append(SEQUENCER_OT_copy_proxy_settings); + WM_operatortype_append(SEQUENCER_OT_enable_proxies); WM_operatortype_append(SEQUENCER_OT_change_effect_input); WM_operatortype_append(SEQUENCER_OT_change_effect_type); WM_operatortype_append(SEQUENCER_OT_change_path); -- cgit v1.2.3 From 4c7876c7408836fd22e076dc9a4b54216afc6f2e Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 26 Mar 2015 17:54:16 +0100 Subject: New option proxy placement, project directory. There are two per-editor settings now, the Per-Strip setting (default) and the Project setting. The per strip setting basically uses the previous, per-strip options for storing the proxies. The project setting though will use a specified directory for -all- proxies, or the blend file directory if no directory is given. --- release/scripts/startup/bl_ui/space_sequencer.py | 18 ++++++--- source/blender/blenkernel/intern/sequencer.c | 50 ++++++++++++++++++------ source/blender/makesdna/DNA_sequence_types.h | 7 +++- source/blender/makesrna/intern/rna_sequencer.c | 25 +++++++++++- 4 files changed, 80 insertions(+), 20 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 4f83cc03b10..ce1add12f54 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -913,19 +913,25 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel): def draw(self, context): layout = self.layout + sequencer = context.scene.sequence_editor + strip = act_strip(context) if strip.proxy: proxy = strip.proxy flow = layout.column_flow() - flow.prop(proxy, "use_proxy_custom_directory") - flow.prop(proxy, "use_proxy_custom_file") + flow.prop(sequencer, "proxy_storage") + if sequencer.proxy_storage == 'PROJECT': + flow.prop(sequencer, "proxy_dir") + else: + flow.prop(proxy, "use_proxy_custom_directory") + flow.prop(proxy, "use_proxy_custom_file") - if proxy.use_proxy_custom_directory and not proxy.use_proxy_custom_file: - flow.prop(proxy, "directory") - if proxy.use_proxy_custom_file: - flow.prop(proxy, "filepath") + if proxy.use_proxy_custom_directory and not proxy.use_proxy_custom_file: + flow.prop(proxy, "directory") + if proxy.use_proxy_custom_file: + flow.prop(proxy, "filepath") layout.label("Enabled Proxies:") enabled = "" diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 6fa39e8bbe0..ec78e155d98 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1330,7 +1330,7 @@ static double seq_rendersize_to_scale_factor(int size) return 0.25; } -static void seq_open_anim_file(Sequence *seq, bool openfile) +static void seq_open_anim_file(Editing *ed, Sequence *seq, bool openfile) { char name[FILE_MAX]; StripProxy *proxy; @@ -1362,10 +1362,22 @@ static void seq_open_anim_file(Sequence *seq, bool openfile) return; } - if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) { + if ((proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) || + (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE)) + { char dir[FILE_MAX]; char fname[FILE_MAXFILE]; - BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); + + if (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) { + if (ed->proxy_dir[0] == 0) + BLI_strncpy(dir, "//", sizeof(dir)); + else + BLI_strncpy(dir, ed->proxy_dir, sizeof(dir)); + } + else { + BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); + } + IMB_anim_get_fname(seq->anim, fname, FILE_MAXFILE); BLI_path_append(dir, sizeof(dir), fname); @@ -1376,7 +1388,7 @@ static void seq_open_anim_file(Sequence *seq, bool openfile) } -static bool seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char *name) +static bool seq_proxy_get_fname(Editing *ed, Sequence *seq, int cfra, int render_size, char *name) { int frameno; char dir[PROXY_MAXFILE]; @@ -1394,7 +1406,17 @@ static bool seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char * * have both, a directory full of jpeg files and proxy avis, so * sorry folks, please rebuild your proxies... */ - if ((proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE)) { + if (seq->anim && ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) { + char fname[FILE_MAXFILE]; + if (ed->proxy_dir[0] == 0) + BLI_strncpy(dir, "//", sizeof(dir)); + else + BLI_strncpy(dir, ed->proxy_dir, sizeof(dir)); + IMB_anim_get_fname(seq->anim, fname, FILE_MAXFILE); + BLI_path_append(dir, sizeof(dir), fname); + BLI_path_abs(name, G.main->name); + } + else if ((proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE)) { BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); } else if (seq->anim && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR)) { @@ -1410,7 +1432,9 @@ static bool seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char * return false; } - if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) { + if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE && seq->anim && + ed->proxy_storage != SEQ_EDIT_PROXY_DIR_STORAGE) + { BLI_join_dirfile(name, PROXY_MAXFILE, dir, proxy->file); BLI_path_abs(name, G.main->name); @@ -1445,6 +1469,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c int size_flags; int render_size = context->preview_render_size; StripProxy *proxy = seq->strip->proxy; + Editing *ed = context->scene->ed; if (!(seq->flag & SEQ_USE_PROXY)) { return NULL; @@ -1465,7 +1490,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) { int frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs; if (proxy->anim == NULL) { - if (seq_proxy_get_fname(seq, cfra, render_size, name) == 0) { + if (seq_proxy_get_fname(ed, seq, cfra, render_size, name) == 0) { return NULL; } @@ -1475,14 +1500,14 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c return NULL; } - seq_open_anim_file(seq, true); + seq_open_anim_file(context->scene->ed, seq, true); frameno = IMB_anim_index_get_frame_index(seq->anim, proxy->tc, frameno); return IMB_anim_absolute(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE); } - if (seq_proxy_get_fname(seq, cfra, render_size, name) == 0) { + if (seq_proxy_get_fname(ed, seq, cfra, render_size, name) == 0) { return NULL; } @@ -1507,8 +1532,9 @@ static void seq_proxy_build_frame(const SeqRenderData *context, Sequence *seq, i int rectx, recty; int ok; ImBuf *ibuf_tmp, *ibuf; + Editing *ed = context->scene->ed; - if (!seq_proxy_get_fname(seq, cfra, proxy_render_size, name)) { + if (!seq_proxy_get_fname(ed, seq, cfra, proxy_render_size, name)) { return; } @@ -1577,7 +1603,7 @@ SeqIndexBuildContext *BKE_sequencer_proxy_rebuild_context(Main *bmain, Scene *sc context->seq = nseq; if (nseq->type == SEQ_TYPE_MOVIE) { - seq_open_anim_file(nseq, true); + seq_open_anim_file(scene->ed, nseq, true); if (nseq->anim) { context->index_context = IMB_anim_index_rebuild_context(nseq->anim, @@ -2800,7 +2826,7 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *s case SEQ_TYPE_MOVIE: { - seq_open_anim_file(seq, false); + seq_open_anim_file(context->scene->ed, seq, false); if (seq->anim) { IMB_Proxy_Size proxy_size = seq_rendersize_to_proxysize(context->preview_render_size); diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index c4de93efa6b..9a6d8a533b0 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -210,9 +210,10 @@ typedef struct Editing { Sequence *act_seq; char act_imagedir[1024]; /* 1024 = FILE_MAX */ char act_sounddir[1024]; /* 1024 = FILE_MAX */ + char proxy_dir[1024]; /* 1024 = FILE_MAX */ int over_ofs, over_cfra; - int over_flag, pad; + int over_flag, proxy_storage; rctf over_border; } Editing; @@ -327,6 +328,10 @@ typedef struct SequencerScopes { #define SEQ_STRIP_OFSBOTTOM 0.2f #define SEQ_STRIP_OFSTOP 0.8f +/* Editor->proxy_storage */ +/* store proxies in project directory */ +#define SEQ_EDIT_PROXY_DIR_STORAGE 1 + /* SpeedControlVars->flags */ #define SEQ_SPEED_INTEGRATE 1 /* #define SEQ_SPEED_BLEND 2 */ /* DEPRECATED */ diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index a0756d64d0d..231341ef554 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -134,6 +134,14 @@ static void rna_SequenceEditor_sequences_all_begin(CollectionPropertyIterator *i rna_iterator_listbase_begin(iter, &ed->seqbase, NULL); } +static void rna_SequenceEditor_update_cache(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) +{ + Editing *ed = (Editing *) ptr->id.data; + + BKE_sequencer_free_imbuf(scene, &ed->seqbase, false); +} + + static void rna_SequenceEditor_sequences_all_next(CollectionPropertyIterator *iter) { ListBaseIterator *internal = &iter->internal.listbase; @@ -1568,7 +1576,12 @@ static void rna_def_editor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + + static const EnumPropertyItem editing_storage_items[] = { + {0, "PER_STRIP", 0, "Per Strip", "Store proxies using per strip settings"}, + {SEQ_EDIT_PROXY_DIR_STORAGE, "PROJECT", 0, "Project", "Store proxies using project directory"}, + {0, NULL, 0, NULL, NULL} + }; srna = RNA_def_struct(brna, "SequenceEditor", NULL); RNA_def_struct_ui_text(srna, "Sequence Editor", "Sequence editing data for a Scene datablock"); RNA_def_struct_ui_icon(srna, ICON_SEQUENCE); @@ -1616,6 +1629,16 @@ static void rna_def_editor(BlenderRNA *brna) RNA_def_property_int_funcs(prop, "rna_SequenceEditor_overlay_frame_get", "rna_SequenceEditor_overlay_frame_set", NULL); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); + + prop = RNA_def_property(srna, "proxy_storage", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, editing_storage_items); + RNA_def_property_ui_text(prop, "Proxy Storage", "How to store proxies for this project"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, "rna_SequenceEditor_update_cache"); + + prop = RNA_def_property(srna, "proxy_dir", PROP_STRING, PROP_DIRPATH); + RNA_def_property_string_sdna(prop, NULL, "proxy_dir"); + RNA_def_property_ui_text(prop, "Proxy Directory", ""); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, "rna_SequenceEditor_update_cache"); } static void rna_def_filter_video(StructRNA *srna) -- cgit v1.2.3 From d26c18c05ecfd23bb107ac904189b2b50c08ebc0 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 26 Mar 2015 18:25:06 +0100 Subject: Project directory proxies: Use BL_proxy if directory is blank to avoid filling the whole folder with files. --- source/blender/blenkernel/intern/sequencer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index ec78e155d98..1e32c586176 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1370,7 +1370,7 @@ static void seq_open_anim_file(Editing *ed, Sequence *seq, bool openfile) if (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) { if (ed->proxy_dir[0] == 0) - BLI_strncpy(dir, "//", sizeof(dir)); + BLI_strncpy(dir, "//BL_proxy", sizeof(dir)); else BLI_strncpy(dir, ed->proxy_dir, sizeof(dir)); } @@ -1409,7 +1409,7 @@ static bool seq_proxy_get_fname(Editing *ed, Sequence *seq, int cfra, int render if (seq->anim && ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) { char fname[FILE_MAXFILE]; if (ed->proxy_dir[0] == 0) - BLI_strncpy(dir, "//", sizeof(dir)); + BLI_strncpy(dir, "//BL_proxy", sizeof(dir)); else BLI_strncpy(dir, ed->proxy_dir, sizeof(dir)); IMB_anim_get_fname(seq->anim, fname, FILE_MAXFILE); -- cgit v1.2.3 From 6e72f06069ae427a32501676c8b86e9e8c3ddb8c Mon Sep 17 00:00:00 2001 From: Severin Date: Thu, 26 Mar 2015 21:16:43 +0100 Subject: Fix duplicated IME input AFAIK a few IMEs were affected by this so I guess we can now add a few more IMEs to the "officially supported" list. Patch by @randon (thanks again!), minor edits by me. --- intern/ghost/intern/GHOST_SystemWin32.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 27eb387e9f8..038e6a03c7d 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -989,6 +989,10 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, eventHandled = true; ime->UpdateImeWindow(hwnd); ime->UpdateInfo(hwnd); + if (ime->eventImeData.result_len) { + /* remove redundant IME event */ + eventManager->removeTypeEvents(GHOST_kEventImeComposition, window); + } event = processImeEvent( GHOST_kEventImeComposition, window, -- cgit v1.2.3 From 065e5896c4ecda26952770813696ca051ca7cd41 Mon Sep 17 00:00:00 2001 From: Severin Date: Thu, 26 Mar 2015 21:24:01 +0100 Subject: IME: Minor API cleanup --- source/blender/editors/interface/interface_handlers.c | 3 +-- source/blender/editors/interface/interface_intern.h | 2 +- source/blender/editors/interface/interface_widgets.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index dc8018cd11e..6ef414b88ea 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -2476,8 +2476,7 @@ void ui_but_ime_reposition(uiBut *but, int x, int y, bool complete) wm_window_IME_begin(but->active->window, x, y - 4, 0, 0, complete); } -/* should be ui_but_ime_data_get */ -wmIMEData *ui_but_get_ime_data(uiBut *but) +wmIMEData *ui_but_ime_data_get(uiBut *but) { if (but->active && but->active->window) { return but->active->window->ime_data; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 03816a255ad..e337389f781 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -635,7 +635,7 @@ uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new); #ifdef WITH_INPUT_IME void ui_but_ime_reposition(uiBut *but, int x, int y, bool complete); -struct wmIMEData *ui_but_get_ime_data(uiBut *but); +struct wmIMEData *ui_but_ime_data_get(uiBut *but); #endif /* interface_widgets.c */ diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index d95e9035207..1cf78e68315 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1318,7 +1318,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b #ifdef WITH_INPUT_IME /* FIXME, IME is modifying 'const char *drawstr! */ - ime_data = ui_but_get_ime_data(but); + ime_data = ui_but_ime_data_get(but); if (ime_data && ime_data->composite_len) { /* insert composite string into cursor pos */ -- cgit v1.2.3 From c8f95cbb604ce833b759b134b36dd7ea42d69d76 Mon Sep 17 00:00:00 2001 From: Severin Date: Thu, 26 Mar 2015 22:16:00 +0100 Subject: Only enable IME for supported translation contexts For me, weird characters are drawn if IME is enabled but translation is not set to a supported language. Could become an utility function if needed later. --- source/blender/editors/interface/interface_handlers.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 6ef414b88ea..b4f26998c77 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -2446,6 +2446,18 @@ static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const in } #ifdef WITH_INPUT_IME +/* test if the translation context allows IME input - used to + * avoid weird character drawing if IME inputs non-ascii chars */ +static bool ui_ime_is_lang_supported(void) +{ + const char *uilng = BLF_lang_get(); + const bool is_lang_supported = STREQ(uilng, "zh_CN") || + STREQ(uilng, "zh_TW") || + STREQ(uilng, "ja_JP"); + + return ((U.transopts & USER_DOTRANSLATE) && is_lang_supported); +} + /* enable ime, and set up uibut ime data */ static void ui_textedit_ime_begin(wmWindow *win, uiBut *UNUSED(but)) { @@ -2550,7 +2562,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) WM_cursor_modal_set(win, BC_TEXTEDITCURSOR); #ifdef WITH_INPUT_IME - if (is_num_but == false) { + if (is_num_but == false && ui_ime_is_lang_supported()) { ui_textedit_ime_begin(win, but); } #endif -- cgit v1.2.3 From a12b2ec66dbadd3ff06883d80509773139a40262 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Fri, 27 Mar 2015 05:52:28 +0100 Subject: BGE: New isDynamicSuspended python attribute This is a new KX_GameObject attribute that it increments the possibilities of optimization during the game Additionally the unused m_bSuspendDynamics variable is removed. Reviewers: moguri, agoose77, lordloki Reviewed By: agoose77, lordloki Subscribers: agoose77, lordloki Differential Revision: https://developer.blender.org/D1091 --- .../rst/bge_types/bge.types.KX_GameObject.rst | 6 ++++++ source/gameengine/Ketsji/KX_GameObject.cpp | 22 +++++++++++++++++++++- source/gameengine/Ketsji/KX_GameObject.h | 4 +++- .../Physics/Bullet/CcdPhysicsController.h | 5 +++++ .../Physics/common/PHY_IPhysicsController.h | 1 + 5 files changed, 36 insertions(+), 2 deletions(-) diff --git a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst index 8d6996dc401..abf1b8b9707 100644 --- a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst +++ b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst @@ -78,6 +78,12 @@ base class --- :class:`SCA_IObject` The object must have a physics controller for the mass to be applied, otherwise the mass value will be returned as 0.0. + .. attribute:: isDynamicsSuspended + + The object's dynamic state (read-only). + + :type: boolean + .. attribute:: linearDamping The object's linear damping, also known as translational damping. Can be set simultaneously with angular damping using the :py:meth:`setDamping` method. diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index d0c6792cce0..f876afd01c1 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -95,7 +95,6 @@ KX_GameObject::KX_GameObject( m_previousLodLevel(0), m_pBlenderObject(NULL), m_pBlenderGroupObject(NULL), - m_bSuspendDynamics(false), m_bUseObjectColor(false), m_bIsNegativeScaling(false), m_objectColor(1.0, 1.0, 1.0, 1.0), @@ -586,6 +585,13 @@ CValue* KX_GameObject::GetReplica() return replica; } +bool KX_GameObject::IsDynamicsSuspended() const +{ + if (m_pPhysicsController) + return m_pPhysicsController->IsSuspended(); + return false; +} + float KX_GameObject::getLinearDamping() const { if (m_pPhysicsController) @@ -1985,6 +1991,7 @@ PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("scene", KX_GameObject, pyattr_get_scene), KX_PYATTRIBUTE_RO_FUNCTION("life", KX_GameObject, pyattr_get_life), KX_PYATTRIBUTE_RW_FUNCTION("mass", KX_GameObject, pyattr_get_mass, pyattr_set_mass), + KX_PYATTRIBUTE_RO_FUNCTION("isDynamicsSuspended", KX_GameObject, pyattr_get_dynamics_suspended), KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin", KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min), KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax", KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max), KX_PYATTRIBUTE_RW_FUNCTION("visible", KX_GameObject, pyattr_get_visible, pyattr_set_visible), @@ -2398,6 +2405,19 @@ int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrd return PY_SET_ATTR_SUCCESS; } +PyObject* KX_GameObject::pyattr_get_dynamics_suspended(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast(self_v); + + // Only objects with a physics controller can be suspended + if (!self->GetPhysicsController()) { + PyErr_SetString(PyExc_AttributeError, "This object has not Physics Controller"); + return NULL; + } + + return PyBool_FromLong(self->IsDynamicsSuspended()); +} + PyObject *KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self = static_cast(self_v); diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index acc63585749..8f823e728de 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -95,7 +95,6 @@ protected: struct Object* m_pBlenderObject; struct Object* m_pBlenderGroupObject; - bool m_bSuspendDynamics; bool m_bUseObjectColor; bool m_bIsNegativeScaling; MT_Vector4 m_objectColor; @@ -619,6 +618,8 @@ public: return m_bDyna; } + bool IsDynamicsSuspended() const; + /** * Should we record animation for this object? */ @@ -1039,6 +1040,7 @@ public: static PyObject* pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_dynamics_suspended(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 47bc9cdfbd7..56d67ca2f64 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -712,6 +712,11 @@ protected: return GetConstructionInfo().m_bDyna; } + virtual bool IsSuspended() const + { + return m_suspended; + } + virtual bool IsCompound() { return GetConstructionInfo().m_shapeInfo->m_shapeType == PHY_SHAPE_COMPOUND; diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h index 68763be4db9..b6cd480e655 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsController.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h @@ -133,6 +133,7 @@ class PHY_IPhysicsController : public PHY_IController virtual bool IsDynamic() = 0; virtual bool IsCompound() = 0; + virtual bool IsSuspended() const = 0; virtual bool ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject* from_meshobj) = 0; -- cgit v1.2.3 From 408a2a8420c9d918236194007c01e1d3b3ebe13c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 14:38:02 +0500 Subject: Compositor: Improve reports to the interface about what's going on The functionality was got lost when new compositor system was landed and it wasn't always clear what's causing the hicucps. Now it's nicely reported to the stats line. --- .../compositor/intern/COM_ExecutionGroup.cpp | 36 +++------------------- .../blender/compositor/intern/COM_ExecutionGroup.h | 5 --- .../compositor/intern/COM_ExecutionSystem.cpp | 6 ++++ .../blender/compositor/intern/COM_compositor.cpp | 1 + 4 files changed, 12 insertions(+), 36 deletions(-) diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp index 366c97b50c6..a122d5d9988 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp @@ -377,35 +377,6 @@ MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *mem return result; } -void ExecutionGroup::printBackgroundStats(void) -{ - uintptr_t mem_in_use, mmap_in_use, peak_memory; - float megs_used_memory, mmap_used_memory, megs_peak_memory; - double execution_time; - char timestr[64]; - - execution_time = PIL_check_seconds_timer() - this->m_executionStartTime; - - mem_in_use = MEM_get_memory_in_use(); - mmap_in_use = MEM_get_mapped_memory_in_use(); - peak_memory = MEM_get_peak_memory(); - - megs_used_memory = (mem_in_use - mmap_in_use) / (1024.0 * 1024.0); - mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0); - megs_peak_memory = (peak_memory) / (1024.0 * 1024.0); - - fprintf(stdout, "Mem:%.2fM (%.2fM, Peak %.2fM) ", - megs_used_memory, mmap_used_memory, megs_peak_memory); - - BLI_timestr(execution_time, timestr, sizeof(timestr)); - printf("| Elapsed %s ", timestr); - printf("| Tree %s, Tile %u-%u ", this->m_bTree->id.name + 2, - this->m_chunksFinished, this->m_numberOfChunks); - - fputc('\n', stdout); - fflush(stdout); -} - void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memoryBuffers) { if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_SCHEDULED) @@ -430,8 +401,11 @@ void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memo progress /= this->m_numberOfChunks; this->m_bTree->progress(this->m_bTree->prh, progress); - if (G.background) - printBackgroundStats(); + char buf[128]; + BLI_snprintf(buf, sizeof(buf), "Compositing | Tile %d-%d", + this->m_chunksFinished, + this->m_numberOfChunks); + this->m_bTree->stats_draw(this->m_bTree->sdh, buf); } } diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h index 4b6f51c72c0..99365cdd4a8 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.h +++ b/source/blender/compositor/intern/COM_ExecutionGroup.h @@ -346,11 +346,6 @@ public: */ MemoryBuffer *allocateOutputBuffer(int chunkNumber, rcti *rect); - /** - * @brief print execution statistics to stdout when running in a background mode - */ - void printBackgroundStats(void); - /** * @brief after a chunk is executed the needed resources can be freed or unlocked. * @param chunknumber diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index 0667271f4b1..1f8b7654786 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -76,6 +76,8 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, Scene *scene, bNodeTree *editin viewer_border->xmin < viewer_border->xmax && viewer_border->ymin < viewer_border->ymax; + editingtree->stats_draw(editingtree->sdh, (char*)"Compositing | Determining resolution"); + for (index = 0; index < this->m_groups.size(); index++) { resolution[0] = 0; resolution[1] = 0; @@ -124,6 +126,9 @@ void ExecutionSystem::set_operations(const Operations &operations, const Groups void ExecutionSystem::execute() { + const bNodeTree *editingtree = this->m_context.getbNodeTree(); + editingtree->stats_draw(editingtree->sdh, (char*)"Compositing | Initializing execution"); + DebugInfo::execute_started(this); unsigned int order = 0; @@ -178,6 +183,7 @@ void ExecutionSystem::execute() WorkScheduler::finish(); WorkScheduler::stop(); + editingtree->stats_draw(editingtree->sdh, (char*)"Compositing | Deinitializing execution"); for (index = 0; index < this->m_operations.size(); index++) { NodeOperation *operation = this->m_operations[index]; operation->deinitExecution(); diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp index ec9ef6c7e68..3348e7c73d8 100644 --- a/source/blender/compositor/intern/COM_compositor.cpp +++ b/source/blender/compositor/intern/COM_compositor.cpp @@ -77,6 +77,7 @@ void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rende /* set progress bar to 0% and status to init compositing */ editingtree->progress(editingtree->prh, 0.0); + editingtree->stats_draw(editingtree->sdh, (char*)"Compositing"); bool twopass = (editingtree->flag & NTREE_TWO_PASS) > 0 && !rendering; /* initialize execution system */ -- cgit v1.2.3 From e7afba4b293a4e83b62b652f6dc3c16e11c15b06 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 14:41:20 +0500 Subject: Compositor: Cleanup, don't pollute namepace with all symbols from std --- source/blender/compositor/intern/COM_ExecutionGroup.cpp | 4 ++-- source/blender/compositor/intern/COM_ExecutionSystem.h | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp index a122d5d9988..4676f6867c8 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp @@ -238,7 +238,7 @@ void ExecutionGroup::execute(ExecutionSystem *graph) chunkOrders[index].determineDistance(hotspots, 1); } - sort(&chunkOrders[0], &chunkOrders[this->m_numberOfChunks - 1]); + std::sort(&chunkOrders[0], &chunkOrders[this->m_numberOfChunks - 1]); for (index = 0; index < this->m_numberOfChunks; index++) { chunkOrder[index] = chunkOrders[index].getChunkNumber(); } @@ -277,7 +277,7 @@ void ExecutionGroup::execute(ExecutionSystem *graph) chunkOrders[index].determineDistance(hotspots, 9); } - sort(&chunkOrders[0], &chunkOrders[this->m_numberOfChunks]); + std::sort(&chunkOrders[0], &chunkOrders[this->m_numberOfChunks]); for (index = 0; index < this->m_numberOfChunks; index++) { chunkOrder[index] = chunkOrders[index].getChunkNumber(); diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h index ab903206f0a..555964f7b0c 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.h +++ b/source/blender/compositor/intern/COM_ExecutionSystem.h @@ -27,14 +27,11 @@ class ExecutionGroup; #include "DNA_color_types.h" #include "DNA_node_types.h" -#include #include "COM_Node.h" #include "BKE_text.h" #include "COM_ExecutionGroup.h" #include "COM_NodeOperation.h" -using namespace std; - /** * @page execution Execution model * In order to get to an efficient model for execution, several steps are being done. these steps are explained below. -- cgit v1.2.3 From 34c92848a77f75ec678b18ea2b203f05c828afdb Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 27 Mar 2015 11:39:09 +0100 Subject: Use preview option to detect frame range for filename when using ctrl F11. --- .../startup/bl_operators/screen_play_rendered_anim.py | 12 +++++++++++- source/blender/blenkernel/BKE_writeavi.h | 2 +- source/blender/blenkernel/intern/writeavi.c | 4 ++-- source/blender/makesrna/intern/rna_scene_api.c | 6 ++++-- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py index 3a7a9b99cde..5fe74eec709 100644 --- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py +++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py @@ -107,11 +107,21 @@ class PlayRenderedAnim(Operator): del file_a, file_b, frame_tmp file = bpy.path.abspath(file) # expand '//' else: + path_valid = True # works for movies and images - file = rd.frame_path(frame=scene.frame_start) + file = rd.frame_path(frame=scene.frame_start, preview=scene.use_preview_range) file = bpy.path.abspath(file) # expand '//' if not os.path.exists(file): self.report({'WARNING'}, "File %r not found" % file) + path_valid = False + + #one last try for full range if we used preview range + if scene.use_preview_range and not path_valid: + file = rd.frame_path(frame=scene.frame_start, preview=False) + file = bpy.path.abspath(file) # expand '//' + if not os.path.exists(file): + self.report({'WARNING'}, "File %r not found" % file) + cmd = [player_path] # extra options, fps controls etc. diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h index 8206c36b895..bc06be0295a 100644 --- a/source/blender/blenkernel/BKE_writeavi.h +++ b/source/blender/blenkernel/BKE_writeavi.h @@ -52,7 +52,7 @@ typedef struct bMovieHandle { } bMovieHandle; bMovieHandle *BKE_movie_handle_get(const char imtype); -void BKE_movie_filepath_get(char *string, struct RenderData *rd); +void BKE_movie_filepath_get(char *string, struct RenderData *rd, bool preview); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index b0e23b6b603..a86ffacfdbd 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -263,11 +263,11 @@ static void end_avi(void) #endif /* WITH_AVI */ /* similar to BKE_image_path_from_imformat() */ -void BKE_movie_filepath_get(char *string, RenderData *rd) +void BKE_movie_filepath_get(char *string, RenderData *rd, bool preview) { bMovieHandle *mh = BKE_movie_handle_get(rd->im_format.imtype); if (mh->get_movie_path) - mh->get_movie_path(string, rd, false); + mh->get_movie_path(string, rd, preview); else string[0] = '\0'; } diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 36657c8a898..0d8d58eae43 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -119,10 +119,10 @@ static void rna_Scene_update_tagged(Scene *scene) #endif } -static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, char *name) +static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, int preview, char *name) { if (BKE_imtype_is_movie(rd->im_format.imtype)) { - BKE_movie_filepath_get(name, rd); + BKE_movie_filepath_get(name, rd, preview != 0); } else { BKE_image_path_from_imformat( @@ -287,6 +287,8 @@ void RNA_api_scene_render(StructRNA *srna) RNA_def_function_ui_description(func, "Return the absolute path to the filename to be written for a given frame"); RNA_def_int(func, "frame", INT_MIN, INT_MIN, INT_MAX, "", "Frame number to use, if unset the current frame will be used", MINAFRAME, MAXFRAME); + parm = RNA_def_boolean(func, "preview", 0, "Preview", "Use preview range"); + parm = RNA_def_string_file_path(func, "filepath", NULL, FILE_MAX, "File Path", "The resulting filepath from the scenes render settings"); RNA_def_property_flag(parm, PROP_THICK_WRAP); /* needed for string return value */ -- cgit v1.2.3 From 38c4645f0a8f3b3ad39a03b66fea97f402616355 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 27 Mar 2015 22:20:51 +1100 Subject: rename BGE attr from D1091 (match methods) --- doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst | 2 +- source/gameengine/Ketsji/KX_GameObject.cpp | 8 ++++---- source/gameengine/Ketsji/KX_GameObject.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst index abf1b8b9707..b2cfeb5edc7 100644 --- a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst +++ b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst @@ -78,7 +78,7 @@ base class --- :class:`SCA_IObject` The object must have a physics controller for the mass to be applied, otherwise the mass value will be returned as 0.0. - .. attribute:: isDynamicsSuspended + .. attribute:: isSuspendDynamics The object's dynamic state (read-only). diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index f876afd01c1..84916b45ebf 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1991,7 +1991,7 @@ PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("scene", KX_GameObject, pyattr_get_scene), KX_PYATTRIBUTE_RO_FUNCTION("life", KX_GameObject, pyattr_get_life), KX_PYATTRIBUTE_RW_FUNCTION("mass", KX_GameObject, pyattr_get_mass, pyattr_set_mass), - KX_PYATTRIBUTE_RO_FUNCTION("isDynamicsSuspended", KX_GameObject, pyattr_get_dynamics_suspended), + KX_PYATTRIBUTE_RO_FUNCTION("isSuspendDynamics", KX_GameObject, pyattr_get_is_suspend_dynamics), KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin", KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min), KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax", KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max), KX_PYATTRIBUTE_RW_FUNCTION("visible", KX_GameObject, pyattr_get_visible, pyattr_set_visible), @@ -2405,14 +2405,14 @@ int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrd return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_dynamics_suspended(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_is_suspend_dynamics(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self = static_cast(self_v); // Only objects with a physics controller can be suspended if (!self->GetPhysicsController()) { - PyErr_SetString(PyExc_AttributeError, "This object has not Physics Controller"); - return NULL; + PyErr_SetString(PyExc_AttributeError, "This object has not Physics Controller"); + return NULL; } return PyBool_FromLong(self->IsDynamicsSuspended()); diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 8f823e728de..5038feb2d68 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -1040,7 +1040,7 @@ public: static PyObject* pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); - static PyObject* pyattr_get_dynamics_suspended(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_is_suspend_dynamics(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); -- cgit v1.2.3 From 90f645855a8de5d0841435bef4d0620d0a252f13 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 15:41:52 +0500 Subject: GHost: Code cleanup, prepare for strict C++ flags --- intern/ghost/GHOST_IWindow.h | 4 +++- intern/ghost/intern/GHOST_Context.h | 2 +- intern/ghost/intern/GHOST_DisplayManagerX11.cpp | 2 +- intern/ghost/intern/GHOST_System.cpp | 4 ++-- intern/ghost/intern/GHOST_SystemPathsX11.cpp | 2 +- intern/ghost/intern/GHOST_SystemX11.cpp | 6 +++--- intern/ghost/intern/GHOST_SystemX11.h | 2 +- intern/ghost/intern/GHOST_Window.cpp | 2 +- intern/ghost/intern/GHOST_Window.h | 4 ++-- intern/ghost/intern/GHOST_WindowManager.cpp | 2 +- intern/ghost/intern/GHOST_WindowX11.cpp | 6 +++--- 11 files changed, 19 insertions(+), 17 deletions(-) diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index 3f8215dc7c2..649f06749b6 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -323,7 +323,9 @@ public: * \param grab The new grab state of the cursor. * \return Indication of success. */ - virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2]) { return GHOST_kSuccess; } + virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode /*mode*/, + GHOST_Rect * /*bounds*/, + GHOST_TInt32 /*mouse_ungrab_xy*/[2]) { return GHOST_kSuccess; } /** */ virtual GHOST_TSuccess beginFullScreen() const = 0; diff --git a/intern/ghost/intern/GHOST_Context.h b/intern/ghost/intern/GHOST_Context.h index 0dfea867703..18d36c40e9c 100644 --- a/intern/ghost/intern/GHOST_Context.h +++ b/intern/ghost/intern/GHOST_Context.h @@ -99,7 +99,7 @@ public: * \param interval The swap interval to use. * \return A boolean success indicator. */ - virtual GHOST_TSuccess setSwapInterval(int interval) { + virtual GHOST_TSuccess setSwapInterval(int /*interval*/) { return GHOST_kFailure; } diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp index 24289e6b006..e0d54303a6c 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp +++ b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp @@ -171,7 +171,7 @@ getCurrentDisplaySetting( GHOST_TSuccess GHOST_DisplayManagerX11:: setCurrentDisplaySetting( - GHOST_TUns8 display, + GHOST_TUns8 /*display*/, const GHOST_DisplaySetting& setting) { #ifdef WITH_X11_XF86VMODE diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index fef8fda7da3..baa1bdff79a 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -169,7 +169,7 @@ GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting } -GHOST_TSuccess GHOST_System::updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window) +GHOST_TSuccess GHOST_System::updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow ** /*window*/) { GHOST_TSuccess success = GHOST_kFailure; GHOST_ASSERT(m_windowManager, "GHOST_System::updateFullScreen(): invalid window manager"); @@ -371,7 +371,7 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, const } -int GHOST_System::confirmQuit(GHOST_IWindow *window) const +int GHOST_System::confirmQuit(GHOST_IWindow * /*window*/) const { return 1; } diff --git a/intern/ghost/intern/GHOST_SystemPathsX11.cpp b/intern/ghost/intern/GHOST_SystemPathsX11.cpp index e2d9733a9b2..5473e404593 100644 --- a/intern/ghost/intern/GHOST_SystemPathsX11.cpp +++ b/intern/ghost/intern/GHOST_SystemPathsX11.cpp @@ -121,7 +121,7 @@ const GHOST_TUns8 *GHOST_SystemPathsX11::getBinaryDir() const return NULL; } -void GHOST_SystemPathsX11::addToSystemRecentFiles(const char *filename) const +void GHOST_SystemPathsX11::addToSystemRecentFiles(const char * /*filename*/) const { /* XXXXX TODO: Implementation for X11 if possible */ diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 241ce9728cc..7a4fb254ce7 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -329,7 +329,7 @@ createWindow(const STR_String& title, } #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING) -static void destroyIMCallback(XIM xim, XPointer ptr, XPointer data) +static void destroyIMCallback(XIM /*xim*/, XPointer ptr, XPointer /*data*/) { GHOST_PRINT("XIM server died\n"); @@ -1882,7 +1882,7 @@ GHOST_TSuccess GHOST_SystemX11::pushDragDropEvent(GHOST_TEventType eventType, * Basically it will not crash blender now if you have a X device that * is configured but not plugged in. */ -int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent) +int GHOST_X11_ApplicationErrorHandler(Display * /*display*/, XErrorEvent *theEvent) { fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n", theEvent->error_code, theEvent->request_code); @@ -1891,7 +1891,7 @@ int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent) return 0; } -int GHOST_X11_ApplicationIOErrorHandler(Display *display) +int GHOST_X11_ApplicationIOErrorHandler(Display * /*display*/) { fprintf(stderr, "Ignoring Xlib error: error IO\n"); diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index 4004bda11cb..a5c1329c4c0 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -271,7 +271,7 @@ public: /** * \see GHOST_ISystem */ - int toggleConsole(int action) { + int toggleConsole(int /*action*/) { return 0; } diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp index dd6154a42bb..71fa260f0f2 100644 --- a/intern/ghost/intern/GHOST_Window.cpp +++ b/intern/ghost/intern/GHOST_Window.cpp @@ -46,7 +46,7 @@ GHOST_Window::GHOST_Window( GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, const bool wantStereoVisual, - const bool exclusive, + const bool /*exclusive*/, const GHOST_TUns16 wantNumOfAASamples) : m_drawingContextType(GHOST_kDrawingContextTypeNone), m_cursorVisible(true), diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index b78a690fcad..d894a30bf25 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -182,7 +182,7 @@ public: * Sets the progress bar value displayed in the window/application icon * \param progress The progress % (0.0 to 1.0) */ - virtual GHOST_TSuccess setProgressBar(float progress) { + virtual GHOST_TSuccess setProgressBar(float /*progress*/) { return GHOST_kFailure; } @@ -329,7 +329,7 @@ protected: * Sets the cursor grab on the window using * native window system calls. */ - virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) { + virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode /*mode*/) { return GHOST_kSuccess; } diff --git a/intern/ghost/intern/GHOST_WindowManager.cpp b/intern/ghost/intern/GHOST_WindowManager.cpp index 1f20e01ca73..83490cecce5 100644 --- a/intern/ghost/intern/GHOST_WindowManager.cpp +++ b/intern/ghost/intern/GHOST_WindowManager.cpp @@ -121,7 +121,7 @@ GHOST_IWindow *GHOST_WindowManager::getFullScreenWindow(void) const GHOST_TSuccess GHOST_WindowManager::beginFullScreen(GHOST_IWindow *window, - bool stereoVisual) + bool /*stereoVisual*/) { GHOST_TSuccess success = GHOST_kFailure; GHOST_ASSERT(window, "GHOST_WindowManager::beginFullScreen(): invalid window"); diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 613b4dfe4be..a2d7303243a 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -561,7 +561,7 @@ GHOST_WindowX11( } #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING) -static void destroyICCallback(XIC xic, XPointer ptr, XPointer data) +static void destroyICCallback(XIC /*xic*/, XPointer ptr, XPointer /*data*/) { GHOST_PRINT("XIM input context destroyed\n"); @@ -1536,8 +1536,8 @@ setWindowCustomCursorShape( int sizey, int hotX, int hotY, - int fg_color, - int bg_color) + int /*fg_color*/, + int /*bg_color*/) { Colormap colormap = DefaultColormap(m_display, m_visualInfo->screen); Pixmap bitmap_pix, mask_pix; -- cgit v1.2.3 From 3f4219a694a0f9061cb4e337a5b0c91cf61b84ed Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 15:43:47 +0500 Subject: OpenColorIO: Code cleanup, prepare for strict C++ flags --- intern/opencolorio/fallback_impl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc index 7ba540a7d77..1124e7fd8ab 100644 --- a/intern/opencolorio/fallback_impl.cc +++ b/intern/opencolorio/fallback_impl.cc @@ -190,7 +190,7 @@ OCIO_ConstLookRcPtr *FallbackImpl::configGetLook(OCIO_ConstConfigRcPtr * /*confi return NULL; } -const char *FallbackImpl::lookGetProcessSpace(OCIO_ConstLookRcPtr *look) +const char *FallbackImpl::lookGetProcessSpace(OCIO_ConstLookRcPtr * /*look*/) { return NULL; } -- cgit v1.2.3 From 232c2d382e4218f89f5c689e1982626b20fd54d2 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 15:45:37 +0500 Subject: Dualcon: Code cleanup, prepare for strict C++ flags --- intern/dualcon/intern/Projections.cpp | 2 +- intern/dualcon/intern/dualcon_c_api.cpp | 2 +- intern/dualcon/intern/octree.cpp | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/intern/dualcon/intern/Projections.cpp b/intern/dualcon/intern/Projections.cpp index e85589e3ff5..601812e1e21 100644 --- a/intern/dualcon/intern/Projections.cpp +++ b/intern/dualcon/intern/Projections.cpp @@ -158,7 +158,7 @@ static void create_projection_axes(int64_t axes[NUM_AXES][3], const int64_t tri[ /** * Construction from a cube (axes aligned) and triangle */ -CubeTriangleIsect::CubeTriangleIsect(int64_t cube[2][3], int64_t tri[3][3], int64_t error, int triind) +CubeTriangleIsect::CubeTriangleIsect(int64_t cube[2][3], int64_t tri[3][3], int64_t /*error*/, int triind) { int i; inherit = new TriangleProjection; diff --git a/intern/dualcon/intern/dualcon_c_api.cpp b/intern/dualcon/intern/dualcon_c_api.cpp index 6c3ec4dcc3b..a6715394942 100644 --- a/intern/dualcon/intern/dualcon_c_api.cpp +++ b/intern/dualcon/intern/dualcon_c_api.cpp @@ -174,7 +174,7 @@ float getBoundingBox(float origin[3]) } /* output */ -void getNextVertex(float v[3]) +void getNextVertex(float /*v*/[3]) { /* not used */ } diff --git a/intern/dualcon/intern/octree.cpp b/intern/dualcon/intern/octree.cpp index bd7194cf3fd..da8638ebc4f 100644 --- a/intern/dualcon/intern/octree.cpp +++ b/intern/dualcon/intern/octree.cpp @@ -1448,7 +1448,7 @@ Node *Octree::locateCell(InternalNode *node, int st[3], int len, int ori[3], int return (Node *)node; } -void Octree::checkElement(PathElement *ele) +void Octree::checkElement(PathElement * /*ele*/) { /* if(ele != NULL && locateLeafCheck(ele->pos) != ele->node) { @@ -1797,7 +1797,7 @@ void Octree::clearProcessBits(Node *node, int height) } } -int Octree::floodFill(LeafNode *leaf, int st[3], int len, int height, int threshold) +int Octree::floodFill(LeafNode *leaf, int st[3], int len, int /*height*/, int threshold) { int i, j; int maxtotal = 0; @@ -2317,7 +2317,7 @@ void Octree::generateMinimizer(Node *node, int st[3], int len, int height, int& } } -void Octree::processEdgeWrite(Node *node[4], int depth[4], int maxdep, int dir) +void Octree::processEdgeWrite(Node *node[4], int /*depth*/[4], int /*maxdep*/, int dir) { //int color = 0; @@ -2553,7 +2553,7 @@ void Octree::cellProcContour(Node *node, int leaf, int depth) } -void Octree::processEdgeParity(LeafNode *node[4], int depth[4], int maxdep, int dir) +void Octree::processEdgeParity(LeafNode *node[4], int /*depth*/[4], int /*maxdep*/, int dir) { int con = 0; for (int i = 0; i < 4; i++) { -- cgit v1.2.3 From 585dd261208e7b92035f32909399330cadaa36d5 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 15:47:55 +0500 Subject: Cycles: Code cleanup, prepare for strict C++ flags --- intern/cycles/blender/blender_camera.cpp | 12 ++++++------ intern/cycles/blender/blender_curves.cpp | 22 +++++++++++----------- intern/cycles/blender/blender_python.cpp | 25 +++++++++++++------------ intern/cycles/blender/blender_session.cpp | 16 ++++++++-------- intern/cycles/blender/blender_shader.cpp | 10 +++++----- intern/cycles/blender/blender_sync.h | 2 +- intern/cycles/bvh/bvh_binning.cpp | 8 ++++---- intern/cycles/device/device.h | 18 ++++++++++++------ intern/cycles/device/device_cpu.cpp | 10 ++++++---- intern/cycles/device/device_cuda.cpp | 6 +++--- intern/cycles/device/device_opencl.cpp | 13 ++++++++----- intern/cycles/kernel/CMakeLists.txt | 1 - intern/cycles/render/background.cpp | 2 +- intern/cycles/render/bake.cpp | 7 +++++-- intern/cycles/render/camera.cpp | 4 ++-- intern/cycles/render/curves.cpp | 10 +++++++--- intern/cycles/render/film.cpp | 8 +++++--- intern/cycles/render/image.cpp | 4 +++- intern/cycles/render/integrator.cpp | 2 +- intern/cycles/render/light.cpp | 2 +- intern/cycles/render/mesh.cpp | 5 ++++- intern/cycles/render/nodes.cpp | 16 ++++++++-------- intern/cycles/render/object.cpp | 6 ++++-- intern/cycles/render/osl.cpp | 2 +- intern/cycles/render/particles.cpp | 2 +- intern/cycles/render/shader.cpp | 5 ++++- intern/cycles/render/svm.cpp | 4 ++-- intern/cycles/render/tile.cpp | 1 + intern/cycles/util/util_task.cpp | 2 +- 29 files changed, 128 insertions(+), 97 deletions(-) diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index dee9ee09fc6..da10ede858d 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -72,7 +72,7 @@ struct BlenderCamera { Transform matrix; }; -static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings b_render, BL::Scene b_scene) +static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings b_render) { memset(bcam, 0, sizeof(BlenderCamera)); @@ -380,7 +380,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int void BlenderSync::sync_camera(BL::RenderSettings b_render, BL::Object b_override, int width, int height) { BlenderCamera bcam; - blender_camera_init(&bcam, b_render, b_scene); + blender_camera_init(&bcam, b_render); /* pixel aspect */ bcam.pixelaspect.x = b_render.pixel_aspect_x(); @@ -501,7 +501,7 @@ static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_ /* get viewport viewplane */ BlenderCamera view_bcam; - blender_camera_init(&view_bcam, b_render, b_scene); + blender_camera_init(&view_bcam, b_render); blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true); blender_camera_viewplane(&view_bcam, width, height, @@ -509,7 +509,7 @@ static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_ /* get camera viewplane */ BlenderCamera cam_bcam; - blender_camera_init(&cam_bcam, b_render, b_scene); + blender_camera_init(&cam_bcam, b_render); blender_camera_from_object(&cam_bcam, b_ob, true); blender_camera_viewplane(&cam_bcam, cam_bcam.full_width, cam_bcam.full_height, @@ -601,14 +601,14 @@ static void blender_camera_border(BlenderCamera *bcam, BL::RenderSettings b_rend void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) { BlenderCamera bcam; - blender_camera_init(&bcam, b_scene.render(), b_scene); + blender_camera_init(&bcam, b_scene.render()); blender_camera_from_view(&bcam, b_scene, b_v3d, b_rv3d, width, height); blender_camera_border(&bcam, b_scene.render(), b_scene, b_v3d, b_rv3d, width, height); blender_camera_sync(scene->camera, &bcam, width, height); } -BufferParams BlenderSync::get_buffer_params(BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height) +BufferParams BlenderSync::get_buffer_params(BL::RenderSettings b_render, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height) { BufferParams params; bool use_border = false; diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 72023d7e69b..2ab4e68f967 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -44,8 +44,8 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData); void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotCam, bool is_ortho); void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resolution); -void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata); -void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata); +void ExportCurveTriangleUV(ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata); +void ExportCurveTriangleVcol(ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata); ParticleCurveData::ParticleCurveData() { @@ -322,7 +322,7 @@ bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par return true; } -static void set_resolution(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, BL::Scene *scene, bool render) +static void set_resolution(BL::Object *b_ob, BL::Scene *scene, bool render) { BL::Object::modifiers_iterator b_mod; for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) { @@ -629,7 +629,7 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData) } } -static void ExportCurveSegmentsMotion(Scene *scene, Mesh *mesh, ParticleCurveData *CData, int time_index) +static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int time_index) { VLOG(1) << "Exporting curve motion segments for mesh " << mesh->name << ", time index " << time_index; @@ -705,7 +705,7 @@ static void ExportCurveSegmentsMotion(Scene *scene, Mesh *mesh, ParticleCurveDat } } -void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata) +void ExportCurveTriangleUV(ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata) { if(uvdata == NULL) return; @@ -750,7 +750,7 @@ void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset } } -void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata) +void ExportCurveTriangleVcol(ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata) { if(cdata == NULL) return; @@ -886,7 +886,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool ParticleCurveData CData; if(!preview) - set_resolution(mesh, &b_mesh, &b_ob, &b_scene, true); + set_resolution(&b_ob, &b_scene, true); ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview); @@ -917,7 +917,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool } else { if(motion) - ExportCurveSegmentsMotion(scene, mesh, &CData, time_index); + ExportCurveSegmentsMotion(mesh, &CData, time_index); else ExportCurveSegments(scene, mesh, &CData); } @@ -966,7 +966,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool uchar4 *cdata = attr_vcol->data_uchar4(); - ExportCurveTriangleVcol(mesh, &CData, tri_num * 3, used_res, cdata); + ExportCurveTriangleVcol(&CData, tri_num * 3, used_res, cdata); } else { Attribute *attr_vcol = mesh->curve_attributes.add( @@ -1009,7 +1009,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool float3 *uv = attr_uv->data_float3(); - ExportCurveTriangleUV(mesh, &CData, tri_num * 3, used_res, uv); + ExportCurveTriangleUV(&CData, tri_num * 3, used_res, uv); } else { if(active_render) @@ -1032,7 +1032,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool } if(!preview) - set_resolution(mesh, &b_mesh, &b_ob, &b_scene, false); + set_resolution(&b_ob, &b_scene, false); mesh->compute_bounds(); } diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 292af14c63a..7e5893e5663 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -25,6 +25,7 @@ #include "util_md5.h" #include "util_opengl.h" #include "util_path.h" +#include "util_types.h" #ifdef WITH_OSL #include "osl.h" @@ -70,7 +71,7 @@ static const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce) return ""; } -static PyObject *init_func(PyObject *self, PyObject *args) +static PyObject *init_func(PyObject * /*self*/, PyObject *args) { PyObject *path, *user_path; int headless; @@ -90,7 +91,7 @@ static PyObject *init_func(PyObject *self, PyObject *args) Py_RETURN_NONE; } -static PyObject *create_func(PyObject *self, PyObject *args) +static PyObject *create_func(PyObject * /*self*/, PyObject *args) { PyObject *pyengine, *pyuserpref, *pydata, *pyscene, *pyregion, *pyv3d, *pyrv3d; int preview_osl; @@ -162,14 +163,14 @@ static PyObject *create_func(PyObject *self, PyObject *args) return PyLong_FromVoidPtr(session); } -static PyObject *free_func(PyObject *self, PyObject *value) +static PyObject *free_func(PyObject * /*self*/, PyObject *value) { delete (BlenderSession*)PyLong_AsVoidPtr(value); Py_RETURN_NONE; } -static PyObject *render_func(PyObject *self, PyObject *value) +static PyObject *render_func(PyObject * /*self*/, PyObject *value) { BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(value); @@ -183,7 +184,7 @@ static PyObject *render_func(PyObject *self, PyObject *value) } /* pixel_array and result passed as pointers */ -static PyObject *bake_func(PyObject *self, PyObject *args) +static PyObject *bake_func(PyObject * /*self*/, PyObject *args) { PyObject *pysession, *pyobject; PyObject *pypixel_array, *pyresult; @@ -214,7 +215,7 @@ static PyObject *bake_func(PyObject *self, PyObject *args) Py_RETURN_NONE; } -static PyObject *draw_func(PyObject *self, PyObject *args) +static PyObject *draw_func(PyObject * /*self*/, PyObject *args) { PyObject *pysession, *pyv3d, *pyrv3d; @@ -234,7 +235,7 @@ static PyObject *draw_func(PyObject *self, PyObject *args) Py_RETURN_NONE; } -static PyObject *reset_func(PyObject *self, PyObject *args) +static PyObject *reset_func(PyObject * /*self*/, PyObject *args) { PyObject *pysession, *pydata, *pyscene; @@ -260,7 +261,7 @@ static PyObject *reset_func(PyObject *self, PyObject *args) Py_RETURN_NONE; } -static PyObject *sync_func(PyObject *self, PyObject *value) +static PyObject *sync_func(PyObject * /*self*/, PyObject *value) { BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(value); @@ -273,7 +274,7 @@ static PyObject *sync_func(PyObject *self, PyObject *value) Py_RETURN_NONE; } -static PyObject *available_devices_func(PyObject *self, PyObject *args) +static PyObject *available_devices_func(PyObject * /*self*/, PyObject * /*args*/) { vector& devices = Device::available_devices(); PyObject *ret = PyTuple_New(devices.size()); @@ -288,7 +289,7 @@ static PyObject *available_devices_func(PyObject *self, PyObject *args) #ifdef WITH_OSL -static PyObject *osl_update_node_func(PyObject *self, PyObject *args) +static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args) { PyObject *pynodegroup, *pynode; const char *filepath = NULL; @@ -464,7 +465,7 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) Py_RETURN_TRUE; } -static PyObject *osl_compile_func(PyObject *self, PyObject *args) +static PyObject *osl_compile_func(PyObject * /*self*/, PyObject *args) { const char *inputfile = NULL, *outputfile = NULL; @@ -479,7 +480,7 @@ static PyObject *osl_compile_func(PyObject *self, PyObject *args) } #endif -static PyObject *system_info_func(PyObject *self, PyObject *value) +static PyObject *system_info_func(PyObject * /*self*/, PyObject * /*value*/) { string system_info = Device::device_capabilities(); return PyUnicode_FromString(system_info.c_str()); diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index e61203d807a..4ff1d7713dc 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -133,7 +133,7 @@ void BlenderSession::create_session() } /* set buffer parameters */ - BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height); session->reset(buffer_params, session_params.samples); b_engine.use_highlight_tiles(session_params.progressive_refine == false); @@ -186,7 +186,7 @@ void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_) sync->sync_integrator(); sync->sync_camera(b_render, b_engine.camera_override(), width, height); - BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, PointerRNA_NULL, PointerRNA_NULL, scene->camera, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, PointerRNA_NULL, PointerRNA_NULL, scene->camera, width, height); session->reset(buffer_params, session_params.samples); b_engine.use_highlight_tiles(session_params.progressive_refine == false); @@ -411,7 +411,7 @@ void BlenderSession::render() /* get buffer parameters */ SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); - BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height); /* render each layer */ BL::RenderSettings r = b_scene.render(); @@ -511,7 +511,7 @@ static void populate_bake_data(BakeData *data, BL::BakePixel pixel_array, const } } -void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, const size_t num_pixels, const int depth, float result[]) +void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, const size_t num_pixels, const int /*depth*/, float result[]) { ShaderEvalType shader_type = get_shader_type(pass_type); size_t object_index = OBJECT_NONE; @@ -543,7 +543,7 @@ void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::Bake /* get buffer parameters */ SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); - BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height); scene->bake_manager->set_shader_limit((size_t)b_engine.tile_x(), (size_t)b_engine.tile_y()); scene->bake_manager->set_baking(true); @@ -692,7 +692,7 @@ void BlenderSession::synchronize() /* reset if needed */ if(scene->need_reset()) { - BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height); session->reset(buffer_params, session_params.samples); /* reset time */ @@ -747,7 +747,7 @@ bool BlenderSession::draw(int w, int h) /* reset if requested */ if(reset) { SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); - BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height); bool session_pause = BlenderSync::get_session_pause(b_scene, background); if(session_pause == false) { @@ -764,7 +764,7 @@ bool BlenderSession::draw(int w, int h) update_status_progress(); /* draw */ - BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height); DeviceDrawParams draw_params; if(session->params.display_buffer_linear) { diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 5628d96db29..32a4117e908 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -106,7 +106,7 @@ static ShaderSocketType convert_socket_type(BL::NodeSocket b_socket) } } -static void set_default_value(ShaderInput *input, BL::Node b_node, BL::NodeSocket b_sock, BL::BlendData b_data, BL::ID b_id) +static void set_default_value(ShaderInput *input, BL::NodeSocket b_sock, BL::BlendData b_data, BL::ID b_id) { /* copy values for non linked inputs */ switch(input->type) { @@ -514,7 +514,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen script_node->input_names.push_back(ustring(b_input->name())); ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(), convert_socket_type(*b_input)); - set_default_value(input, b_node, *b_input, b_data, b_ntree); + set_default_value(input, *b_input, b_data, b_ntree); } BL::Node::outputs_iterator b_output; @@ -868,7 +868,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha input_map[b_input->ptr.data] = proxy->inputs[0]; - set_default_value(proxy->inputs[0], *b_node, *b_input, b_data, b_ntree); + set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree); } for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { ProxyNode *proxy = new ProxyNode(convert_socket_type(*b_output)); @@ -906,7 +906,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha input_map[b_input->ptr.data] = proxy->inputs[0]; - set_default_value(proxy->inputs[0], *b_node, *b_input, b_data, b_ntree); + set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree); } } } @@ -933,7 +933,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha } input_map[b_input->ptr.data] = input; - set_default_value(input, *b_node, *b_input, b_data, b_ntree); + set_default_value(input, *b_input, b_data, b_ntree); } for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { ShaderOutput *output = node_find_output_by_name(node, *b_node, *b_output); diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 6a320ac8085..2c2e41fbca2 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -68,7 +68,7 @@ public: BL::Scene b_scene, bool background); static bool get_session_pause(BL::Scene b_scene, bool background); - static BufferParams get_buffer_params(BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height); + static BufferParams get_buffer_params(BL::RenderSettings b_render, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height); private: /* sync */ diff --git a/intern/cycles/bvh/bvh_binning.cpp b/intern/cycles/bvh/bvh_binning.cpp index bd37ffbcf38..db96490a36f 100644 --- a/intern/cycles/bvh/bvh_binning.cpp +++ b/intern/cycles/bvh/bvh_binning.cpp @@ -29,10 +29,10 @@ CCL_NAMESPACE_BEGIN /* SSE replacements */ -__forceinline void prefetch_L1 (const void* ptr) { } -__forceinline void prefetch_L2 (const void* ptr) { } -__forceinline void prefetch_L3 (const void* ptr) { } -__forceinline void prefetch_NTA(const void* ptr) { } +__forceinline void prefetch_L1 (const void* /*ptr*/) { } +__forceinline void prefetch_L2 (const void* /*ptr*/) { } +__forceinline void prefetch_L3 (const void* /*ptr*/) { } +__forceinline void prefetch_NTA(const void* /*ptr*/) { } template __forceinline float extract(const int4& b) { return b[src]; } diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 7c17f7f4112..18fc707beab 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -106,9 +106,15 @@ public: virtual void const_copy_to(const char *name, void *host, size_t size) = 0; /* texture memory */ - virtual void tex_alloc(const char *name, device_memory& mem, - InterpolationType interpolation = INTERPOLATION_NONE, bool periodic = false) {}; - virtual void tex_free(device_memory& mem) {}; + virtual void tex_alloc(const char * /*name*/, + device_memory& /*mem*/, + InterpolationType interpolation = INTERPOLATION_NONE, + bool periodic = false) + { + (void)interpolation; /* Ignored. */ + (void)periodic; /* Ignored. */ + }; + virtual void tex_free(device_memory& /*mem*/) {}; /* pixel memory */ virtual void pixels_alloc(device_memory& mem); @@ -119,7 +125,7 @@ public: virtual void *osl_memory() { return NULL; } /* load/compile kernels, must be called before adding tasks */ - virtual bool load_kernels(bool experimental) { return true; } + virtual bool load_kernels(bool /*experimental*/) { return true; } /* tasks */ virtual int get_split_task_count(DeviceTask& task) = 0; @@ -138,8 +144,8 @@ public: #endif /* multi device */ - virtual void map_tile(Device *sub_device, RenderTile& tile) {} - virtual int device_number(Device *sub_device) { return 0; } + virtual void map_tile(Device * /*sub_device*/, RenderTile& /*tile*/) {} + virtual int device_number(Device * /*sub_device*/) { return 0; } /* static */ static Device *create(DeviceInfo& info, Stats &stats, bool background = true); diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 9abcf9167d5..70277c5aa48 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -75,19 +75,21 @@ public: task_pool.stop(); } - void mem_alloc(device_memory& mem, MemoryType type) + void mem_alloc(device_memory& mem, MemoryType /*type*/) { mem.device_pointer = mem.data_pointer; mem.device_size = mem.memory_size(); stats.mem_alloc(mem.device_size); } - void mem_copy_to(device_memory& mem) + void mem_copy_to(device_memory& /*mem*/) { /* no-op */ } - void mem_copy_from(device_memory& mem, int y, int w, int h, int elem) + void mem_copy_from(device_memory& /*mem*/, + int /*y*/, int /*w*/, int /*h*/, + int /*elem*/) { /* no-op */ } @@ -111,7 +113,7 @@ public: kernel_const_copy(&kernel_globals, name, host, size); } - void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic) + void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool /*periodic*/) { kernel_tex_copy(&kernel_globals, name, mem.data_pointer, mem.data_width, mem.data_height, mem.data_depth, interpolation); mem.device_pointer = mem.data_pointer; diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 79a1a2b7fe1..407f72034b3 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -185,7 +185,7 @@ public: cuda_assert(cuCtxDestroy(cuContext)); } - bool support_device(bool experimental) + bool support_device(bool /*experimental*/) { int major, minor; cuDeviceComputeCapability(&major, &minor, cuDevId); @@ -344,7 +344,7 @@ public: return (result == CUDA_SUCCESS); } - void mem_alloc(device_memory& mem, MemoryType type) + void mem_alloc(device_memory& mem, MemoryType /*type*/) { cuda_push_context(); CUdeviceptr device_pointer; @@ -999,7 +999,7 @@ public: } }; - int get_split_task_count(DeviceTask& task) + int get_split_task_count(DeviceTask& /*task*/) { return 1; } diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index a5bf35a63c8..f11c94245d5 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -505,7 +505,7 @@ public: } static void CL_CALLBACK context_notify_callback(const char *err_info, - const void *private_info, size_t cb, void *user_data) + const void * /*private_info*/, size_t /*cb*/, void *user_data) { char name[256]; clGetDeviceInfo((cl_device_id)user_data, CL_DEVICE_NAME, sizeof(name), &name, NULL); @@ -596,7 +596,7 @@ public: return true; } - bool build_kernel(const string& kernel_path, const string *debug_src = NULL) + bool build_kernel(const string& /*kernel_path*/, const string *debug_src = NULL) { string build_options = opencl_kernel_build_options(platform_name, debug_src); @@ -675,7 +675,7 @@ public: return md5.get_hex(); } - bool load_kernels(bool experimental) + bool load_kernels(bool /*experimental*/) { /* verify if device was initialized */ if(!device_initialized) { @@ -854,7 +854,10 @@ public: mem_copy_to(*i->second); } - void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic) + void tex_alloc(const char *name, + device_memory& mem, + InterpolationType /*interpolation*/, + bool /*periodic*/) { mem_alloc(mem, MEM_READ_ONLY); mem_copy_to(mem); @@ -1092,7 +1095,7 @@ public: } }; - int get_split_task_count(DeviceTask& task) + int get_split_task_count(DeviceTask& /*task*/) { return 1; } diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index a25eb3f5b50..1e3eb6bca54 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -1,4 +1,3 @@ - set(INC . ../util diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp index f5e51f2e159..5fd7bd8f16f 100644 --- a/intern/cycles/render/background.cpp +++ b/intern/cycles/render/background.cpp @@ -93,7 +93,7 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene need_update = false; } -void Background::device_free(Device *device, DeviceScene *dscene) +void Background::device_free(Device * /*device*/, DeviceScene * /*dscene*/) { } diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp index 1e8c1ac8bc9..c5201366bb2 100644 --- a/intern/cycles/render/bake.cpp +++ b/intern/cycles/render/bake.cpp @@ -221,7 +221,10 @@ bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progre return true; } -void BakeManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) +void BakeManager::device_update(Device * /*device*/, + DeviceScene * /*dscene*/, + Scene * /*scene*/, + Progress& progress) { if(!need_update) return; @@ -231,7 +234,7 @@ void BakeManager::device_update(Device *device, DeviceScene *dscene, Scene *scen need_update = false; } -void BakeManager::device_free(Device *device, DeviceScene *dscene) +void BakeManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/) { } diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index ea9b853d454..74648a71fe0 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -284,7 +284,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) previous_need_motion = need_motion; } -void Camera::device_update_volume(Device *device, +void Camera::device_update_volume(Device * /*device*/, DeviceScene *dscene, Scene *scene) { @@ -306,7 +306,7 @@ void Camera::device_update_volume(Device *device, need_device_update = false; } -void Camera::device_free(Device *device, DeviceScene *dscene) +void Camera::device_free(Device * /*device*/, DeviceScene * /*dscene*/) { /* nothing to free, only writing to constant memory */ } diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp index 80dc6434cde..f671eb19cae 100644 --- a/intern/cycles/render/curves.cpp +++ b/intern/cycles/render/curves.cpp @@ -103,7 +103,10 @@ CurveSystemManager::~CurveSystemManager() { } -void CurveSystemManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) +void CurveSystemManager::device_update(Device *device, + DeviceScene *dscene, + Scene * /*scene*/, + Progress& progress) { if(!need_update) return; @@ -144,7 +147,8 @@ void CurveSystemManager::device_update(Device *device, DeviceScene *dscene, Scen need_update = false; } -void CurveSystemManager::device_free(Device *device, DeviceScene *dscene) +void CurveSystemManager::device_free(Device * /*device*/, + DeviceScene * /*dscene*/) { } @@ -174,7 +178,7 @@ bool CurveSystemManager::modified_mesh(const CurveSystemManager& CurveSystemMana use_curves == CurveSystemManager.use_curves); } -void CurveSystemManager::tag_update(Scene *scene) +void CurveSystemManager::tag_update(Scene * /*scene*/) { need_update = true; } diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index c6d12928dd4..b23678dea44 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -187,7 +187,7 @@ bool Pass::contains(const vector& passes, PassType type) /* Pixel Filter */ -static float filter_func_box(float v, float width) +static float filter_func_box(float /*v*/, float /*width*/) { return 1.0f; } @@ -424,7 +424,9 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) need_update = false; } -void Film::device_free(Device *device, DeviceScene *dscene, Scene *scene) +void Film::device_free(Device * /*device*/, + DeviceScene * /*dscene*/, + Scene *scene) { if(filter_table_offset != TABLE_OFFSET_INVALID) { scene->lookup_tables->remove_table(filter_table_offset); @@ -459,7 +461,7 @@ void Film::tag_passes_update(Scene *scene, const vector& passes_) passes = passes_; } -void Film::tag_update(Scene *scene) +void Film::tag_update(Scene * /*scene*/) { need_update = true; } diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 61a0a81d51d..6e63b433709 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -791,7 +791,9 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress& need_update = false; } -void ImageManager::device_pack_images(Device *device, DeviceScene *dscene, Progress& progess) +void ImageManager::device_pack_images(Device *device, + DeviceScene *dscene, + Progress& /*progess*/) { /* for OpenCL, we pack all image textures inside a single big texture, and * will do our own interpolation in the kernel */ diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index 17c50ca826f..465d7ea02c6 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -216,7 +216,7 @@ bool Integrator::modified(const Integrator& integrator) sample_all_lights_indirect == integrator.sample_all_lights_indirect); } -void Integrator::tag_update(Scene *scene) +void Integrator::tag_update(Scene * /*scene*/) { need_update = true; } diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index b6c7b379a7e..08ee8eddc07 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -699,7 +699,7 @@ void LightManager::device_free(Device *device, DeviceScene *dscene) dscene->light_background_conditional_cdf.clear(); } -void LightManager::tag_update(Scene *scene) +void LightManager::tag_update(Scene * /*scene*/) { need_update = true; } diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 9c7310d4a05..4ec5312e9a3 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -1124,7 +1124,10 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene * dscene->data.bvh.use_qbvh = scene->params.use_qbvh; } -void MeshManager::device_update_flags(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) +void MeshManager::device_update_flags(Device * /*device*/, + DeviceScene * /*dscene*/, + Scene * scene, + Progress& /*progress*/) { if(!need_update && !need_flags_update) { return; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 7a39811cacd..b41f4b511b3 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1507,11 +1507,11 @@ ProxyNode::ProxyNode(ShaderSocketType type_) add_output("Output", type); } -void ProxyNode::compile(SVMCompiler& compiler) +void ProxyNode::compile(SVMCompiler& /*compiler*/) { } -void ProxyNode::compile(OSLCompiler& compiler) +void ProxyNode::compile(OSLCompiler& /*compiler*/) { } @@ -1587,7 +1587,7 @@ void BsdfNode::compile(SVMCompiler& compiler) compile(compiler, NULL, NULL); } -void BsdfNode::compile(OSLCompiler& compiler) +void BsdfNode::compile(OSLCompiler& /*compiler*/) { assert(0); } @@ -2078,7 +2078,7 @@ void VolumeNode::compile(SVMCompiler& compiler) compile(compiler, NULL, NULL); } -void VolumeNode::compile(OSLCompiler& compiler) +void VolumeNode::compile(OSLCompiler& /*compiler*/) { assert(0); } @@ -2916,7 +2916,7 @@ AddClosureNode::AddClosureNode() add_output("Closure", SHADER_SOCKET_CLOSURE); } -void AddClosureNode::compile(SVMCompiler& compiler) +void AddClosureNode::compile(SVMCompiler& /*compiler*/) { /* handled in the SVM compiler */ } @@ -2939,7 +2939,7 @@ MixClosureNode::MixClosureNode() add_output("Closure", SHADER_SOCKET_CLOSURE); } -void MixClosureNode::compile(SVMCompiler& compiler) +void MixClosureNode::compile(SVMCompiler& /*compiler*/) { /* handled in the SVM compiler */ } @@ -2977,7 +2977,7 @@ void MixClosureWeightNode::compile(SVMCompiler& compiler) weight1_out->stack_offset, weight2_out->stack_offset)); } -void MixClosureWeightNode::compile(OSLCompiler& compiler) +void MixClosureWeightNode::compile(OSLCompiler& /*compiler*/) { assert(0); } @@ -4122,7 +4122,7 @@ OSLScriptNode::OSLScriptNode() special_type = SHADER_SPECIAL_TYPE_SCRIPT; } -void OSLScriptNode::compile(SVMCompiler& compiler) +void OSLScriptNode::compile(SVMCompiler& /*compiler*/) { /* doesn't work for SVM, obviously ... */ } diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 1225125b57e..840f706f23b 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -402,8 +402,10 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc } } -void ObjectManager::device_update_flags(Device *device, DeviceScene *dscene, - Scene *scene, Progress& progress) +void ObjectManager::device_update_flags(Device *device, + DeviceScene *dscene, + Scene *scene, + Progress& /*progress*/) { if(!need_update && !need_flags_update) return; diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 9d6f412d9ce..a0f6c368a9c 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -67,7 +67,7 @@ OSLShaderManager::~OSLShaderManager() texture_system_free(); } -void OSLShaderManager::reset(Scene *scene) +void OSLShaderManager::reset(Scene * /*scene*/) { shading_system_free(); shading_system_init(); diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp index f2f154cdab4..f6a89d7a10c 100644 --- a/intern/cycles/render/particles.cpp +++ b/intern/cycles/render/particles.cpp @@ -111,7 +111,7 @@ void ParticleSystemManager::device_free(Device *device, DeviceScene *dscene) dscene->particles.clear(); } -void ParticleSystemManager::tag_update(Scene *scene) +void ParticleSystemManager::tag_update(Scene * /*scene*/) { need_update = true; } diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 5899c562f72..81a7b787885 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -321,7 +321,10 @@ void ShaderManager::device_update_shaders_used(Scene *scene) scene->shaders[light->shader]->used = true; } -void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) +void ShaderManager::device_update_common(Device *device, + DeviceScene *dscene, + Scene *scene, + Progress& /*progress*/) { device->tex_free(dscene->shader_flag); dscene->shader_flag.clear(); diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 2e3abfcffb9..f5264debd8b 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -39,7 +39,7 @@ SVMShaderManager::~SVMShaderManager() { } -void SVMShaderManager::reset(Scene *scene) +void SVMShaderManager::reset(Scene * /*scene*/) { } @@ -354,7 +354,7 @@ uint SVMCompiler::attribute(AttributeStandard std) return shader_manager->get_attribute_id(std); } -bool SVMCompiler::node_skip_input(ShaderNode *node, ShaderInput *input) +bool SVMCompiler::node_skip_input(ShaderNode * /*node*/, ShaderInput *input) { /* nasty exception .. */ if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->name == ustring("bump")) diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 675f49ec300..b1cad98a852 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -28,6 +28,7 @@ TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, i tile_size = tile_size_; tile_order = tile_order_; start_resolution = start_resolution_; + num_samples = num_samples_; num_devices = num_devices_; preserve_tile_device = preserve_tile_device_; background = background_; diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp index e43b26ddfe2..d56553d1d4a 100644 --- a/intern/cycles/util/util_task.cpp +++ b/intern/cycles/util/util_task.cpp @@ -237,7 +237,7 @@ bool TaskScheduler::thread_wait_pop(Entry& entry) return true; } -void TaskScheduler::thread_run(int thread_id) +void TaskScheduler::thread_run(int /*thread_id*/) { Entry entry; -- cgit v1.2.3 From 2ada3512a27eb66d05da669268dc3bb2cd0a1e16 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 15:49:07 +0500 Subject: Compositor: Code cleanup, prepare for strict C++ flags --- .../compositor/intern/COM_ExecutionGroup.cpp | 3 ++- .../blender/compositor/intern/COM_NodeOperation.h | 22 ++++++++++++++-------- .../compositor/intern/COM_NodeOperationBuilder.cpp | 3 ++- .../intern/COM_SingleThreadedOperation.cpp | 2 +- .../blender/compositor/intern/COM_SocketReader.h | 18 ++++++++++++------ .../compositor/intern/COM_WorkScheduler.cpp | 5 ++++- .../blender/compositor/nodes/COM_AlphaOverNode.cpp | 2 +- .../compositor/nodes/COM_BokehImageNode.cpp | 2 +- .../compositor/nodes/COM_BrightnessNode.cpp | 2 +- .../compositor/nodes/COM_ChannelMatteNode.cpp | 2 +- .../compositor/nodes/COM_ChromaMatteNode.cpp | 2 +- .../compositor/nodes/COM_ColorBalanceNode.cpp | 2 +- .../compositor/nodes/COM_ColorCorrectionNode.cpp | 2 +- .../compositor/nodes/COM_ColorCurveNode.cpp | 2 +- .../compositor/nodes/COM_ColorMatteNode.cpp | 2 +- source/blender/compositor/nodes/COM_ColorNode.cpp | 2 +- .../blender/compositor/nodes/COM_ColorRampNode.cpp | 2 +- .../compositor/nodes/COM_ColorSpillNode.cpp | 2 +- .../blender/compositor/nodes/COM_ColorToBWNode.cpp | 2 +- .../compositor/nodes/COM_CombineColorNode.cpp | 8 ++++---- .../compositor/nodes/COM_ConvertAlphaNode.cpp | 2 +- .../blender/compositor/nodes/COM_CornerPinNode.cpp | 2 +- source/blender/compositor/nodes/COM_CropNode.cpp | 2 +- .../blender/compositor/nodes/COM_DespeckleNode.cpp | 2 +- .../compositor/nodes/COM_DifferenceMatteNode.cpp | 2 +- .../compositor/nodes/COM_DistanceMatteNode.cpp | 2 +- .../compositor/nodes/COM_DoubleEdgeMaskNode.cpp | 2 +- source/blender/compositor/nodes/COM_FilterNode.cpp | 2 +- source/blender/compositor/nodes/COM_FlipNode.cpp | 2 +- source/blender/compositor/nodes/COM_GammaNode.cpp | 2 +- source/blender/compositor/nodes/COM_GlareNode.cpp | 2 +- .../nodes/COM_HueSaturationValueCorrectNode.cpp | 2 +- .../nodes/COM_HueSaturationValueNode.cpp | 2 +- .../blender/compositor/nodes/COM_InpaintNode.cpp | 2 +- source/blender/compositor/nodes/COM_InvertNode.cpp | 2 +- .../compositor/nodes/COM_LensDistortionNode.cpp | 2 +- .../compositor/nodes/COM_LuminanceMatteNode.cpp | 2 +- .../blender/compositor/nodes/COM_MapRangeNode.cpp | 2 +- source/blender/compositor/nodes/COM_MapUVNode.cpp | 2 +- .../blender/compositor/nodes/COM_MapValueNode.cpp | 2 +- source/blender/compositor/nodes/COM_MathNode.cpp | 2 +- source/blender/compositor/nodes/COM_MixNode.cpp | 2 +- source/blender/compositor/nodes/COM_NormalNode.cpp | 2 +- .../blender/compositor/nodes/COM_NormalizeNode.cpp | 2 +- .../blender/compositor/nodes/COM_PixelateNode.cpp | 2 +- source/blender/compositor/nodes/COM_RotateNode.cpp | 2 +- .../compositor/nodes/COM_SeparateColorNode.cpp | 8 ++++---- .../blender/compositor/nodes/COM_SetAlphaNode.cpp | 2 +- .../compositor/nodes/COM_SocketProxyNode.cpp | 4 ++-- .../blender/compositor/nodes/COM_SunBeamsNode.cpp | 2 +- source/blender/compositor/nodes/COM_SwitchNode.cpp | 2 +- .../blender/compositor/nodes/COM_TonemapNode.cpp | 2 +- .../blender/compositor/nodes/COM_TransformNode.cpp | 2 +- source/blender/compositor/nodes/COM_ValueNode.cpp | 2 +- .../compositor/nodes/COM_VectorCurveNode.cpp | 2 +- .../compositor/nodes/COM_ViewLevelsNode.cpp | 2 +- .../operations/COM_AntiAliasOperation.cpp | 4 ++-- .../operations/COM_BlurBaseOperation.cpp | 2 +- .../compositor/operations/COM_BlurBaseOperation.h | 2 +- .../operations/COM_BokehBlurOperation.cpp | 4 ++-- .../operations/COM_BokehImageOperation.cpp | 4 ++-- .../operations/COM_CalculateMeanOperation.cpp | 6 ++++-- .../COM_CalculateStandardDeviationOperation.cpp | 4 +++- .../operations/COM_CompositorOperation.cpp | 2 +- .../operations/COM_CompositorOperation.h | 2 +- .../COM_ConvolutionEdgeFilterOperation.cpp | 2 +- .../operations/COM_ConvolutionFilterOperation.cpp | 2 +- .../operations/COM_DespeckleOperation.cpp | 2 +- .../operations/COM_DilateErodeOperation.cpp | 10 +++++----- .../operations/COM_DirectionalBlurOperation.cpp | 6 +++--- .../operations/COM_DisplaceOperation.cpp | 2 +- .../operations/COM_DoubleEdgeMaskOperation.cpp | 2 +- .../operations/COM_FastGaussianBlurOperation.cpp | 4 ++-- .../operations/COM_GaussianAlphaXBlurOperation.cpp | 2 +- .../operations/COM_GaussianAlphaYBlurOperation.cpp | 2 +- .../operations/COM_GaussianBokehBlurOperation.cpp | 4 ++-- .../operations/COM_GaussianXBlurOperation.cpp | 6 ++---- .../operations/COM_GaussianYBlurOperation.cpp | 6 ++---- .../operations/COM_GlareBaseOperation.cpp | 2 +- .../compositor/operations/COM_ImageOperation.cpp | 4 ++-- .../compositor/operations/COM_InpaintOperation.cpp | 4 ++-- .../operations/COM_KeyingScreenOperation.cpp | 4 ++-- .../compositor/operations/COM_MapUVOperation.cpp | 2 +- .../compositor/operations/COM_MaskOperation.cpp | 3 ++- .../operations/COM_MovieClipAttributeOperation.cpp | 4 +++- .../operations/COM_MovieClipOperation.cpp | 2 +- .../operations/COM_MovieDistortionOperation.cpp | 2 +- .../operations/COM_MultilayerImageOperation.cpp | 4 ++-- .../operations/COM_NormalizeOperation.cpp | 4 ++-- .../operations/COM_OutputFileOperation.cpp | 4 ++-- .../operations/COM_OutputFileOperation.h | 4 ++-- .../operations/COM_PlaneDistortCommonOperation.cpp | 4 ++-- .../operations/COM_PlaneTrackOperation.cpp | 2 +- .../compositor/operations/COM_PreviewOperation.cpp | 2 +- .../compositor/operations/COM_PreviewOperation.h | 2 +- .../COM_ProjectorLensDistortionOperation.cpp | 2 +- .../operations/COM_ReadBufferOperation.cpp | 2 +- .../compositor/operations/COM_RenderLayersProg.cpp | 4 ++-- .../compositor/operations/COM_ScaleOperation.cpp | 2 +- .../COM_ScreenLensDistortionOperation.cpp | 4 ++-- .../operations/COM_SetColorOperation.cpp | 4 +++- .../operations/COM_SetSamplerOperation.cpp | 2 +- .../operations/COM_SetValueOperation.cpp | 4 +++- .../operations/COM_SetVectorOperation.cpp | 4 +++- .../compositor/operations/COM_SplitOperation.cpp | 2 +- .../operations/COM_SunBeamsOperation.cpp | 2 +- .../compositor/operations/COM_TextureOperation.cpp | 2 +- .../compositor/operations/COM_TonemapOperation.cpp | 4 ++-- .../operations/COM_TrackPositionOperation.cpp | 4 +++- .../operations/COM_TranslateOperation.cpp | 2 +- .../COM_VariableSizeBokehBlurOperation.cpp | 4 ++-- .../operations/COM_VectorBlurOperation.cpp | 2 +- .../compositor/operations/COM_ViewerOperation.cpp | 2 +- .../compositor/operations/COM_ViewerOperation.h | 2 +- .../operations/COM_WriteBufferOperation.cpp | 4 ++-- 115 files changed, 193 insertions(+), 165 deletions(-) diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp index 4676f6867c8..ca4f5c38f36 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp @@ -433,7 +433,8 @@ void ExecutionGroup::determineChunkRect(rcti *rect, const unsigned int chunkNumb determineChunkRect(rect, xChunk, yChunk); } -MemoryBuffer *ExecutionGroup::allocateOutputBuffer(int chunkNumber, rcti *rect) +MemoryBuffer *ExecutionGroup::allocateOutputBuffer(int /*chunkNumber*/, + rcti *rect) { // we asume that this method is only called from complex execution groups. NodeOperation *operation = this->getOutputOperation(); diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h index d9c16615fb6..7c87524b4b3 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.h +++ b/source/blender/compositor/intern/COM_NodeOperation.h @@ -161,7 +161,7 @@ public: * * @return bool the result of this method */ - virtual bool isOutputOperation(bool rendering) const { return false; } + virtual bool isOutputOperation(bool /*rendering*/) const { return false; } virtual int isSingleThreaded() { return false; } @@ -175,7 +175,8 @@ public: * @param chunkNumber the chunkNumber to be calculated * @param memoryBuffers all input MemoryBuffer's needed */ - virtual void executeRegion(rcti *rect, unsigned int chunkNumber) {} + virtual void executeRegion(rcti * /*rect*/, + unsigned int /*chunkNumber*/) {} /** * @brief when a chunk is executed by an OpenCLDevice, this method is called @@ -189,8 +190,11 @@ public: * @param memoryBuffers all input MemoryBuffer's needed * @param outputBuffer the outputbuffer to write to */ - virtual void executeOpenCLRegion(OpenCLDevice *device, rcti *rect, - unsigned int chunkNumber, MemoryBuffer **memoryBuffers, MemoryBuffer *outputBuffer) {} + virtual void executeOpenCLRegion(OpenCLDevice * /*device*/, + rcti * /*rect*/, + unsigned int /*chunkNumber*/, + MemoryBuffer ** /*memoryBuffers*/, + MemoryBuffer * /*outputBuffer*/) {} /** * @brief custom handle to add new tasks to the OpenCL command queue in order to execute a chunk on an GPUDevice @@ -204,10 +208,12 @@ public: * @param clMemToCleanUp all created cl_mem references must be added to this list. Framework will clean this after execution * @param clKernelsToCleanUp all created cl_kernel references must be added to this list. Framework will clean this after execution */ - virtual void executeOpenCL(OpenCLDevice *device, - MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, - MemoryBuffer **inputMemoryBuffers, list *clMemToCleanUp, - list *clKernelsToCleanUp) {} + virtual void executeOpenCL(OpenCLDevice * /*device*/, + MemoryBuffer * /*outputMemoryBuffer*/, + cl_mem /*clOutputBuffer*/, + MemoryBuffer ** /*inputMemoryBuffers*/, + list * /*clMemToCleanUp*/, + list * /*clKernelsToCleanUp*/) {} virtual void deinitExecution(); bool isResolutionSet() { diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp index 45105bade08..aed60f5fca8 100644 --- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp +++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp @@ -459,7 +459,8 @@ WriteBufferOperation *NodeOperationBuilder::find_attached_write_buffer_operation return NULL; } -void NodeOperationBuilder::add_input_buffers(NodeOperation *operation, NodeOperationInput *input) +void NodeOperationBuilder::add_input_buffers(NodeOperation * /*operation*/, + NodeOperationInput *input) { if (!input->isConnected()) return; diff --git a/source/blender/compositor/intern/COM_SingleThreadedOperation.cpp b/source/blender/compositor/intern/COM_SingleThreadedOperation.cpp index c300a85bfa3..b17f5d6b429 100644 --- a/source/blender/compositor/intern/COM_SingleThreadedOperation.cpp +++ b/source/blender/compositor/intern/COM_SingleThreadedOperation.cpp @@ -33,7 +33,7 @@ void SingleThreadedOperation::initExecution() initMutex(); } -void SingleThreadedOperation::executePixel(float output[4], int x, int y, void *data) +void SingleThreadedOperation::executePixel(float output[4], int x, int y, void * /*data*/) { this->m_cachedInstance->readNoCheck(output, x, y); } diff --git a/source/blender/compositor/intern/COM_SocketReader.h b/source/blender/compositor/intern/COM_SocketReader.h index c996ef5bbeb..7ba208ebbf6 100644 --- a/source/blender/compositor/intern/COM_SocketReader.h +++ b/source/blender/compositor/intern/COM_SocketReader.h @@ -63,7 +63,10 @@ protected: * @param y the y-coordinate of the pixel to calculate in image space * @param inputBuffers chunks that can be read by their ReadBufferOperation. */ - virtual void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) {} + virtual void executePixelSampled(float /*output*/[4], + float /*x*/, + float /*y*/, + PixelSampler /*sampler*/) { } /** * @brief calculate a single pixel @@ -74,7 +77,7 @@ protected: * @param inputBuffers chunks that can be read by their ReadBufferOperation. * @param chunkData chunk specific data a during execution time. */ - virtual void executePixel(float output[4], int x, int y, void *chunkData) { + virtual void executePixel(float output[4], int x, int y, void * /*chunkData*/) { executePixelSampled(output, x, y, COM_PS_NEAREST); } @@ -88,7 +91,10 @@ protected: * @param dy * @param inputBuffers chunks that can be read by their ReadBufferOperation. */ - virtual void executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2], PixelSampler sampler) {} + virtual void executePixelFiltered(float /*output*/[4], + float /*x*/, float /*y*/, + float /*dx*/[2], float /*dy*/[2], + PixelSampler /*sampler*/) {} public: inline void readSampled(float result[4], float x, float y, PixelSampler sampler) { @@ -101,12 +107,12 @@ public: executePixelFiltered(result, x, y, dx, dy, sampler); } - virtual void *initializeTileData(rcti *rect) { return 0; } - virtual void deinitializeTileData(rcti *rect, void *data) {} + virtual void *initializeTileData(rcti * /*rect*/) { return 0; } + virtual void deinitializeTileData(rcti * /*rect*/, void * /*data*/) {} virtual ~SocketReader() {} - virtual MemoryBuffer *getInputMemoryBuffer(MemoryBuffer **memoryBuffers) { return 0; } + virtual MemoryBuffer *getInputMemoryBuffer(MemoryBuffer ** /*memoryBuffers*/) { return 0; } inline const unsigned int getWidth() const { return this->m_width; } inline const unsigned int getHeight() const { return this->m_height; } diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp index 673920ef84a..fc6ea1299cf 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.cpp +++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp @@ -276,7 +276,10 @@ bool WorkScheduler::hasGPUDevices() #endif } -static void CL_CALLBACK clContextError(const char *errinfo, const void *private_info, size_t cb, void *user_data) +static void CL_CALLBACK clContextError(const char *errinfo, + const void * /*private_info*/, + size_t /*cb*/, + void * /*user_data*/) { printf("OPENCL error: %s\n", errinfo); } diff --git a/source/blender/compositor/nodes/COM_AlphaOverNode.cpp b/source/blender/compositor/nodes/COM_AlphaOverNode.cpp index 0306d636c8b..e9b99b6aaf1 100644 --- a/source/blender/compositor/nodes/COM_AlphaOverNode.cpp +++ b/source/blender/compositor/nodes/COM_AlphaOverNode.cpp @@ -30,7 +30,7 @@ #include "COM_SetValueOperation.h" #include "DNA_material_types.h" // the ramp types -void AlphaOverNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void AlphaOverNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *color1Socket = this->getInputSocket(1); NodeInput *color2Socket = this->getInputSocket(2); diff --git a/source/blender/compositor/nodes/COM_BokehImageNode.cpp b/source/blender/compositor/nodes/COM_BokehImageNode.cpp index c75e9b16336..7b7cfc812aa 100644 --- a/source/blender/compositor/nodes/COM_BokehImageNode.cpp +++ b/source/blender/compositor/nodes/COM_BokehImageNode.cpp @@ -29,7 +29,7 @@ BokehImageNode::BokehImageNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void BokehImageNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void BokehImageNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { BokehImageOperation *operation = new BokehImageOperation(); operation->setData((NodeBokehImage *)this->getbNode()->storage); diff --git a/source/blender/compositor/nodes/COM_BrightnessNode.cpp b/source/blender/compositor/nodes/COM_BrightnessNode.cpp index e684b569945..053f286c66e 100644 --- a/source/blender/compositor/nodes/COM_BrightnessNode.cpp +++ b/source/blender/compositor/nodes/COM_BrightnessNode.cpp @@ -29,7 +29,7 @@ BrightnessNode::BrightnessNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void BrightnessNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void BrightnessNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { BrightnessOperation *operation = new BrightnessOperation(); converter.addOperation(operation); diff --git a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp index f356c74cd49..b04f86dea08 100644 --- a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp @@ -30,7 +30,7 @@ ChannelMatteNode::ChannelMatteNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void ChannelMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void ChannelMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { bNode *node = this->getbNode(); diff --git a/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp b/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp index 90de9358587..6324ca9a3ca 100644 --- a/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp @@ -30,7 +30,7 @@ ChromaMatteNode::ChromaMatteNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void ChromaMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void ChromaMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { bNode *editorsnode = getbNode(); diff --git a/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp b/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp index fc0df046e86..a531493d486 100644 --- a/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp @@ -32,7 +32,7 @@ ColorBalanceNode::ColorBalanceNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void ColorBalanceNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void ColorBalanceNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { bNode *node = this->getbNode(); NodeColorBalance *n = (NodeColorBalance *)node->storage; diff --git a/source/blender/compositor/nodes/COM_ColorCorrectionNode.cpp b/source/blender/compositor/nodes/COM_ColorCorrectionNode.cpp index 728b51b8dc1..e926d131c1a 100644 --- a/source/blender/compositor/nodes/COM_ColorCorrectionNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorCorrectionNode.cpp @@ -29,7 +29,7 @@ ColorCorrectionNode::ColorCorrectionNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void ColorCorrectionNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void ColorCorrectionNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { bNode *editorNode = getbNode(); diff --git a/source/blender/compositor/nodes/COM_ColorCurveNode.cpp b/source/blender/compositor/nodes/COM_ColorCurveNode.cpp index 6dc936302f4..5a4dc79e6b2 100644 --- a/source/blender/compositor/nodes/COM_ColorCurveNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorCurveNode.cpp @@ -29,7 +29,7 @@ ColorCurveNode::ColorCurveNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void ColorCurveNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void ColorCurveNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { if (this->getInputSocket(2)->isLinked() || this->getInputSocket(3)->isLinked()) { ColorCurveOperation *operation = new ColorCurveOperation(); diff --git a/source/blender/compositor/nodes/COM_ColorMatteNode.cpp b/source/blender/compositor/nodes/COM_ColorMatteNode.cpp index def3b18e0fe..f7c20894087 100644 --- a/source/blender/compositor/nodes/COM_ColorMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorMatteNode.cpp @@ -30,7 +30,7 @@ ColorMatteNode::ColorMatteNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void ColorMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void ColorMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { bNode *editorsnode = getbNode(); diff --git a/source/blender/compositor/nodes/COM_ColorNode.cpp b/source/blender/compositor/nodes/COM_ColorNode.cpp index 4106cb64798..c3770e79dea 100644 --- a/source/blender/compositor/nodes/COM_ColorNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorNode.cpp @@ -29,7 +29,7 @@ ColorNode::ColorNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void ColorNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void ColorNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { SetColorOperation *operation = new SetColorOperation(); NodeOutput *output = this->getOutputSocket(0); diff --git a/source/blender/compositor/nodes/COM_ColorRampNode.cpp b/source/blender/compositor/nodes/COM_ColorRampNode.cpp index a61ddffbf35..1feaa88bebb 100644 --- a/source/blender/compositor/nodes/COM_ColorRampNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorRampNode.cpp @@ -32,7 +32,7 @@ ColorRampNode::ColorRampNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void ColorRampNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void ColorRampNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *inputSocket = this->getInputSocket(0); NodeOutput *outputSocket = this->getOutputSocket(0); diff --git a/source/blender/compositor/nodes/COM_ColorSpillNode.cpp b/source/blender/compositor/nodes/COM_ColorSpillNode.cpp index 82454ba7979..c3a911e830b 100644 --- a/source/blender/compositor/nodes/COM_ColorSpillNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorSpillNode.cpp @@ -29,7 +29,7 @@ ColorSpillNode::ColorSpillNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void ColorSpillNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void ColorSpillNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { bNode *editorsnode = getbNode(); diff --git a/source/blender/compositor/nodes/COM_ColorToBWNode.cpp b/source/blender/compositor/nodes/COM_ColorToBWNode.cpp index a1616a61b4b..f09c6bac3ee 100644 --- a/source/blender/compositor/nodes/COM_ColorToBWNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorToBWNode.cpp @@ -30,7 +30,7 @@ ColorToBWNode::ColorToBWNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void ColorToBWNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void ColorToBWNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *colorSocket = this->getInputSocket(0); NodeOutput *valueSocket = this->getOutputSocket(0); diff --git a/source/blender/compositor/nodes/COM_CombineColorNode.cpp b/source/blender/compositor/nodes/COM_CombineColorNode.cpp index c7a3baf809d..a39e946fe5f 100644 --- a/source/blender/compositor/nodes/COM_CombineColorNode.cpp +++ b/source/blender/compositor/nodes/COM_CombineColorNode.cpp @@ -72,17 +72,17 @@ void CombineColorNode::convertToOperations(NodeConverter &converter, const Compo } -NodeOperation *CombineRGBANode::getColorConverter(const CompositorContext &context) const +NodeOperation *CombineRGBANode::getColorConverter(const CompositorContext &/*context*/) const { return NULL; /* no conversion needed */ } -NodeOperation *CombineHSVANode::getColorConverter(const CompositorContext &context) const +NodeOperation *CombineHSVANode::getColorConverter(const CompositorContext &/*context*/) const { return new ConvertHSVToRGBOperation(); } -NodeOperation *CombineYCCANode::getColorConverter(const CompositorContext &context) const +NodeOperation *CombineYCCANode::getColorConverter(const CompositorContext &/*context*/) const { ConvertYCCToRGBOperation *operation = new ConvertYCCToRGBOperation(); bNode *editorNode = this->getbNode(); @@ -90,7 +90,7 @@ NodeOperation *CombineYCCANode::getColorConverter(const CompositorContext &conte return operation; } -NodeOperation *CombineYUVANode::getColorConverter(const CompositorContext &context) const +NodeOperation *CombineYUVANode::getColorConverter(const CompositorContext &/*context*/) const { return new ConvertYUVToRGBOperation(); } diff --git a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp index ba31ed6e89c..fbf5dbb6253 100644 --- a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp +++ b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp @@ -23,7 +23,7 @@ #include "COM_ConvertOperation.h" #include "COM_ExecutionSystem.h" -void ConvertAlphaNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void ConvertAlphaNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeOperation *operation = NULL; bNode *node = this->getbNode(); diff --git a/source/blender/compositor/nodes/COM_CornerPinNode.cpp b/source/blender/compositor/nodes/COM_CornerPinNode.cpp index ea9f22f2840..5e4e463595a 100644 --- a/source/blender/compositor/nodes/COM_CornerPinNode.cpp +++ b/source/blender/compositor/nodes/COM_CornerPinNode.cpp @@ -28,7 +28,7 @@ CornerPinNode::CornerPinNode(bNode *editorNode) : Node(editorNode) { } -void CornerPinNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void CornerPinNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *input_image = this->getInputSocket(0); /* note: socket order differs between UI node and operations: diff --git a/source/blender/compositor/nodes/COM_CropNode.cpp b/source/blender/compositor/nodes/COM_CropNode.cpp index 6c3dc93481b..ee148f41c68 100644 --- a/source/blender/compositor/nodes/COM_CropNode.cpp +++ b/source/blender/compositor/nodes/COM_CropNode.cpp @@ -29,7 +29,7 @@ CropNode::CropNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void CropNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void CropNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { bNode *node = getbNode(); NodeTwoXYs *cropSettings = (NodeTwoXYs *)node->storage; diff --git a/source/blender/compositor/nodes/COM_DespeckleNode.cpp b/source/blender/compositor/nodes/COM_DespeckleNode.cpp index bac6337374f..a21885bf42d 100644 --- a/source/blender/compositor/nodes/COM_DespeckleNode.cpp +++ b/source/blender/compositor/nodes/COM_DespeckleNode.cpp @@ -29,7 +29,7 @@ DespeckleNode::DespeckleNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void DespeckleNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void DespeckleNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { bNode *editorNode = this->getbNode(); NodeInput *inputSocket = this->getInputSocket(0); diff --git a/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp b/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp index 8870badab09..2cb0e2301ac 100644 --- a/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp @@ -30,7 +30,7 @@ DifferenceMatteNode::DifferenceMatteNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void DifferenceMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void DifferenceMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *inputSocket = this->getInputSocket(0); NodeInput *inputSocket2 = this->getInputSocket(1); diff --git a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp index 704c704c500..5f3feda5de7 100644 --- a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp @@ -31,7 +31,7 @@ DistanceMatteNode::DistanceMatteNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void DistanceMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void DistanceMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { bNode *editorsnode = getbNode(); NodeChroma *storage = (NodeChroma *)editorsnode->storage; diff --git a/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.cpp b/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.cpp index 1f80eeadf83..c67abb1ab99 100644 --- a/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.cpp +++ b/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.cpp @@ -29,7 +29,7 @@ DoubleEdgeMaskNode::DoubleEdgeMaskNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void DoubleEdgeMaskNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void DoubleEdgeMaskNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { DoubleEdgeMaskOperation *operation; bNode *bnode = this->getbNode(); diff --git a/source/blender/compositor/nodes/COM_FilterNode.cpp b/source/blender/compositor/nodes/COM_FilterNode.cpp index 9f3a7ae795c..7493f24ba6b 100644 --- a/source/blender/compositor/nodes/COM_FilterNode.cpp +++ b/source/blender/compositor/nodes/COM_FilterNode.cpp @@ -32,7 +32,7 @@ FilterNode::FilterNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void FilterNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void FilterNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *inputSocket = this->getInputSocket(0); NodeInput *inputImageSocket = this->getInputSocket(1); diff --git a/source/blender/compositor/nodes/COM_FlipNode.cpp b/source/blender/compositor/nodes/COM_FlipNode.cpp index 1dbcc97143e..0177dc7017a 100644 --- a/source/blender/compositor/nodes/COM_FlipNode.cpp +++ b/source/blender/compositor/nodes/COM_FlipNode.cpp @@ -30,7 +30,7 @@ FlipNode::FlipNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void FlipNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void FlipNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *inputSocket = this->getInputSocket(0); NodeOutput *outputSocket = this->getOutputSocket(0); diff --git a/source/blender/compositor/nodes/COM_GammaNode.cpp b/source/blender/compositor/nodes/COM_GammaNode.cpp index 046cd9e9a0d..bf24bee55d3 100644 --- a/source/blender/compositor/nodes/COM_GammaNode.cpp +++ b/source/blender/compositor/nodes/COM_GammaNode.cpp @@ -29,7 +29,7 @@ GammaNode::GammaNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void GammaNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void GammaNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { GammaOperation *operation = new GammaOperation(); converter.addOperation(operation); diff --git a/source/blender/compositor/nodes/COM_GlareNode.cpp b/source/blender/compositor/nodes/COM_GlareNode.cpp index 0429a1a80cf..7afe1510ae4 100644 --- a/source/blender/compositor/nodes/COM_GlareNode.cpp +++ b/source/blender/compositor/nodes/COM_GlareNode.cpp @@ -36,7 +36,7 @@ GlareNode::GlareNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void GlareNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void GlareNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { bNode *node = this->getbNode(); NodeGlare *glare = (NodeGlare *)node->storage; diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp b/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp index 003bc91edd3..e159886bb46 100644 --- a/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp +++ b/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp @@ -36,7 +36,7 @@ HueSaturationValueCorrectNode::HueSaturationValueCorrectNode(bNode *editorNode) /* pass */ } -void HueSaturationValueCorrectNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void HueSaturationValueCorrectNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *valueSocket = this->getInputSocket(0); NodeInput *colorSocket = this->getInputSocket(1); diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp index cdec1250c6e..29c296a896d 100644 --- a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp +++ b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp @@ -35,7 +35,7 @@ HueSaturationValueNode::HueSaturationValueNode(bNode *editorNode) : Node(editorN /* pass */ } -void HueSaturationValueNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void HueSaturationValueNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *valueSocket = this->getInputSocket(0); NodeInput *colorSocket = this->getInputSocket(1); diff --git a/source/blender/compositor/nodes/COM_InpaintNode.cpp b/source/blender/compositor/nodes/COM_InpaintNode.cpp index 1371cdb5f1d..9e78625684d 100644 --- a/source/blender/compositor/nodes/COM_InpaintNode.cpp +++ b/source/blender/compositor/nodes/COM_InpaintNode.cpp @@ -31,7 +31,7 @@ InpaintNode::InpaintNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void InpaintNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void InpaintNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { bNode *editorNode = this->getbNode(); diff --git a/source/blender/compositor/nodes/COM_InvertNode.cpp b/source/blender/compositor/nodes/COM_InvertNode.cpp index ed4a21132ca..da499d66c2c 100644 --- a/source/blender/compositor/nodes/COM_InvertNode.cpp +++ b/source/blender/compositor/nodes/COM_InvertNode.cpp @@ -30,7 +30,7 @@ InvertNode::InvertNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void InvertNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void InvertNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { InvertOperation *operation = new InvertOperation(); bNode *node = this->getbNode(); diff --git a/source/blender/compositor/nodes/COM_LensDistortionNode.cpp b/source/blender/compositor/nodes/COM_LensDistortionNode.cpp index 32db452e6c2..3d3cc841715 100644 --- a/source/blender/compositor/nodes/COM_LensDistortionNode.cpp +++ b/source/blender/compositor/nodes/COM_LensDistortionNode.cpp @@ -30,7 +30,7 @@ LensDistortionNode::LensDistortionNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void LensDistortionNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void LensDistortionNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { bNode *editorNode = this->getbNode(); NodeLensDist *data = (NodeLensDist *)editorNode->storage; diff --git a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp index e23ec243ff4..382296a7f3a 100644 --- a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp @@ -30,7 +30,7 @@ LuminanceMatteNode::LuminanceMatteNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void LuminanceMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void LuminanceMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { bNode *editorsnode = getbNode(); NodeInput *inputSocket = this->getInputSocket(0); diff --git a/source/blender/compositor/nodes/COM_MapRangeNode.cpp b/source/blender/compositor/nodes/COM_MapRangeNode.cpp index 2c164cfad32..148ca00205c 100644 --- a/source/blender/compositor/nodes/COM_MapRangeNode.cpp +++ b/source/blender/compositor/nodes/COM_MapRangeNode.cpp @@ -30,7 +30,7 @@ MapRangeNode::MapRangeNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void MapRangeNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void MapRangeNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *valueSocket = this->getInputSocket(0); NodeInput *sourceMinSocket = this->getInputSocket(1); diff --git a/source/blender/compositor/nodes/COM_MapUVNode.cpp b/source/blender/compositor/nodes/COM_MapUVNode.cpp index 25ca7b8b8c6..ec38e23ec07 100644 --- a/source/blender/compositor/nodes/COM_MapUVNode.cpp +++ b/source/blender/compositor/nodes/COM_MapUVNode.cpp @@ -28,7 +28,7 @@ MapUVNode::MapUVNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void MapUVNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void MapUVNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { bNode *node = this->getbNode(); diff --git a/source/blender/compositor/nodes/COM_MapValueNode.cpp b/source/blender/compositor/nodes/COM_MapValueNode.cpp index d7ee4e6a38b..f04c6a2d316 100644 --- a/source/blender/compositor/nodes/COM_MapValueNode.cpp +++ b/source/blender/compositor/nodes/COM_MapValueNode.cpp @@ -30,7 +30,7 @@ MapValueNode::MapValueNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void MapValueNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void MapValueNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { TexMapping *storage = (TexMapping *)this->getbNode()->storage; diff --git a/source/blender/compositor/nodes/COM_MathNode.cpp b/source/blender/compositor/nodes/COM_MathNode.cpp index 4cd6964ed3b..eb6bb2caf56 100644 --- a/source/blender/compositor/nodes/COM_MathNode.cpp +++ b/source/blender/compositor/nodes/COM_MathNode.cpp @@ -24,7 +24,7 @@ #include "COM_MathBaseOperation.h" #include "COM_ExecutionSystem.h" -void MathNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void MathNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { MathBaseOperation *operation = NULL; diff --git a/source/blender/compositor/nodes/COM_MixNode.cpp b/source/blender/compositor/nodes/COM_MixNode.cpp index 89010d0e861..0607d6d6705 100644 --- a/source/blender/compositor/nodes/COM_MixNode.cpp +++ b/source/blender/compositor/nodes/COM_MixNode.cpp @@ -34,7 +34,7 @@ MixNode::MixNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void MixNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void MixNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *valueSocket = this->getInputSocket(0); NodeInput *color1Socket = this->getInputSocket(1); diff --git a/source/blender/compositor/nodes/COM_NormalNode.cpp b/source/blender/compositor/nodes/COM_NormalNode.cpp index d7c3fd11844..26da61cb9e7 100644 --- a/source/blender/compositor/nodes/COM_NormalNode.cpp +++ b/source/blender/compositor/nodes/COM_NormalNode.cpp @@ -31,7 +31,7 @@ NormalNode::NormalNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void NormalNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void NormalNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *inputSocket = this->getInputSocket(0); NodeOutput *outputSocket = this->getOutputSocket(0); diff --git a/source/blender/compositor/nodes/COM_NormalizeNode.cpp b/source/blender/compositor/nodes/COM_NormalizeNode.cpp index f6e919c168f..a13fcd2a301 100644 --- a/source/blender/compositor/nodes/COM_NormalizeNode.cpp +++ b/source/blender/compositor/nodes/COM_NormalizeNode.cpp @@ -28,7 +28,7 @@ NormalizeNode::NormalizeNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void NormalizeNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void NormalizeNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NormalizeOperation *operation = new NormalizeOperation(); converter.addOperation(operation); diff --git a/source/blender/compositor/nodes/COM_PixelateNode.cpp b/source/blender/compositor/nodes/COM_PixelateNode.cpp index da3cd74e771..fe806dbf307 100644 --- a/source/blender/compositor/nodes/COM_PixelateNode.cpp +++ b/source/blender/compositor/nodes/COM_PixelateNode.cpp @@ -30,7 +30,7 @@ PixelateNode::PixelateNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void PixelateNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void PixelateNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *inputSocket = this->getInputSocket(0); NodeOutput *outputSocket = this->getOutputSocket(0); diff --git a/source/blender/compositor/nodes/COM_RotateNode.cpp b/source/blender/compositor/nodes/COM_RotateNode.cpp index c5fe88b3636..6fd7e357775 100644 --- a/source/blender/compositor/nodes/COM_RotateNode.cpp +++ b/source/blender/compositor/nodes/COM_RotateNode.cpp @@ -31,7 +31,7 @@ RotateNode::RotateNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void RotateNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void RotateNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *inputSocket = this->getInputSocket(0); NodeInput *inputDegreeSocket = this->getInputSocket(1); diff --git a/source/blender/compositor/nodes/COM_SeparateColorNode.cpp b/source/blender/compositor/nodes/COM_SeparateColorNode.cpp index a6fa9065364..780ce73d340 100644 --- a/source/blender/compositor/nodes/COM_SeparateColorNode.cpp +++ b/source/blender/compositor/nodes/COM_SeparateColorNode.cpp @@ -96,17 +96,17 @@ void SeparateColorNode::convertToOperations(NodeConverter &converter, const Comp } -NodeOperation *SeparateRGBANode::getColorConverter(const CompositorContext &context) const +NodeOperation *SeparateRGBANode::getColorConverter(const CompositorContext &/*context*/) const { return NULL; /* no conversion needed */ } -NodeOperation *SeparateHSVANode::getColorConverter(const CompositorContext &context) const +NodeOperation *SeparateHSVANode::getColorConverter(const CompositorContext &/*context*/) const { return new ConvertRGBToHSVOperation(); } -NodeOperation *SeparateYCCANode::getColorConverter(const CompositorContext &context) const +NodeOperation *SeparateYCCANode::getColorConverter(const CompositorContext &/*context*/) const { ConvertRGBToYCCOperation *operation = new ConvertRGBToYCCOperation(); bNode *editorNode = this->getbNode(); @@ -114,7 +114,7 @@ NodeOperation *SeparateYCCANode::getColorConverter(const CompositorContext &cont return operation; } -NodeOperation *SeparateYUVANode::getColorConverter(const CompositorContext &context) const +NodeOperation *SeparateYUVANode::getColorConverter(const CompositorContext &/*context*/) const { return new ConvertRGBToYUVOperation(); } diff --git a/source/blender/compositor/nodes/COM_SetAlphaNode.cpp b/source/blender/compositor/nodes/COM_SetAlphaNode.cpp index 22ddd5bb157..32c03c695be 100644 --- a/source/blender/compositor/nodes/COM_SetAlphaNode.cpp +++ b/source/blender/compositor/nodes/COM_SetAlphaNode.cpp @@ -24,7 +24,7 @@ #include "COM_SetAlphaOperation.h" #include "COM_ExecutionSystem.h" -void SetAlphaNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void SetAlphaNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { SetAlphaOperation *operation = new SetAlphaOperation(); diff --git a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp index 17b00af16d8..465a94e8335 100644 --- a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp +++ b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp @@ -46,7 +46,7 @@ SocketProxyNode::SocketProxyNode(bNode *editorNode, bNodeSocket *editorInput, bN this->addOutputSocket(dt, editorOutput); } -void SocketProxyNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void SocketProxyNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeOperationOutput *proxy_output = converter.addInputProxy(getInputSocket(0), m_use_conversion); converter.mapOutputSocket(getOutputSocket(), proxy_output); @@ -68,7 +68,7 @@ SocketBufferNode::SocketBufferNode(bNode *editorNode, bNodeSocket *editorInput, this->addOutputSocket(dt, editorOutput); } -void SocketBufferNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void SocketBufferNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeOutput *output = this->getOutputSocket(0); NodeInput *input = this->getInputSocket(0); diff --git a/source/blender/compositor/nodes/COM_SunBeamsNode.cpp b/source/blender/compositor/nodes/COM_SunBeamsNode.cpp index ed14acabf36..7cf3c90c786 100644 --- a/source/blender/compositor/nodes/COM_SunBeamsNode.cpp +++ b/source/blender/compositor/nodes/COM_SunBeamsNode.cpp @@ -27,7 +27,7 @@ SunBeamsNode::SunBeamsNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void SunBeamsNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void SunBeamsNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *inputSocket = this->getInputSocket(0); NodeOutput *outputSocket = this->getOutputSocket(0); diff --git a/source/blender/compositor/nodes/COM_SwitchNode.cpp b/source/blender/compositor/nodes/COM_SwitchNode.cpp index 10f0ee3821d..eb854983d4c 100644 --- a/source/blender/compositor/nodes/COM_SwitchNode.cpp +++ b/source/blender/compositor/nodes/COM_SwitchNode.cpp @@ -27,7 +27,7 @@ SwitchNode::SwitchNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void SwitchNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void SwitchNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { bool condition = this->getbNode()->custom1; diff --git a/source/blender/compositor/nodes/COM_TonemapNode.cpp b/source/blender/compositor/nodes/COM_TonemapNode.cpp index 5ac73b9f9c2..961139d4855 100644 --- a/source/blender/compositor/nodes/COM_TonemapNode.cpp +++ b/source/blender/compositor/nodes/COM_TonemapNode.cpp @@ -29,7 +29,7 @@ TonemapNode::TonemapNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void TonemapNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void TonemapNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeTonemap *data = (NodeTonemap *)this->getbNode()->storage; diff --git a/source/blender/compositor/nodes/COM_TransformNode.cpp b/source/blender/compositor/nodes/COM_TransformNode.cpp index f1d5771bab3..148409a6427 100644 --- a/source/blender/compositor/nodes/COM_TransformNode.cpp +++ b/source/blender/compositor/nodes/COM_TransformNode.cpp @@ -33,7 +33,7 @@ TransformNode::TransformNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void TransformNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void TransformNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *imageInput = this->getInputSocket(0); NodeInput *xInput = this->getInputSocket(1); diff --git a/source/blender/compositor/nodes/COM_ValueNode.cpp b/source/blender/compositor/nodes/COM_ValueNode.cpp index 62a312da67c..c75d9296807 100644 --- a/source/blender/compositor/nodes/COM_ValueNode.cpp +++ b/source/blender/compositor/nodes/COM_ValueNode.cpp @@ -29,7 +29,7 @@ ValueNode::ValueNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void ValueNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void ValueNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { SetValueOperation *operation = new SetValueOperation(); NodeOutput *output = this->getOutputSocket(0); diff --git a/source/blender/compositor/nodes/COM_VectorCurveNode.cpp b/source/blender/compositor/nodes/COM_VectorCurveNode.cpp index 197b2c8bd0c..7222a018fa0 100644 --- a/source/blender/compositor/nodes/COM_VectorCurveNode.cpp +++ b/source/blender/compositor/nodes/COM_VectorCurveNode.cpp @@ -29,7 +29,7 @@ VectorCurveNode::VectorCurveNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void VectorCurveNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void VectorCurveNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { VectorCurveOperation *operation = new VectorCurveOperation(); operation->setCurveMapping((CurveMapping *)this->getbNode()->storage); diff --git a/source/blender/compositor/nodes/COM_ViewLevelsNode.cpp b/source/blender/compositor/nodes/COM_ViewLevelsNode.cpp index 30f51794e8d..06f12ccc559 100644 --- a/source/blender/compositor/nodes/COM_ViewLevelsNode.cpp +++ b/source/blender/compositor/nodes/COM_ViewLevelsNode.cpp @@ -31,7 +31,7 @@ ViewLevelsNode::ViewLevelsNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void ViewLevelsNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +void ViewLevelsNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { NodeInput *input = this->getInputSocket(0); if (input->isLinked()) { diff --git a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp index b25e2281467..2e60c2d3e42 100644 --- a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp +++ b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp @@ -45,7 +45,7 @@ void AntiAliasOperation::initExecution() NodeOperation::initMutex(); } -void AntiAliasOperation::executePixel(float output[4], int x, int y, void *data) +void AntiAliasOperation::executePixel(float output[4], int x, int y, void * /*data*/) { if (y < 0 || (unsigned int)y >= this->m_height || x < 0 || (unsigned int)x >= this->m_width) { output[0] = 0.0f; @@ -66,7 +66,7 @@ void AntiAliasOperation::deinitExecution() NodeOperation::deinitMutex(); } -bool AntiAliasOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool AntiAliasOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) { rcti imageInput; if (this->m_buffer) { diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp index d5aafc7c2ae..cbf9bb211c1 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp @@ -92,7 +92,7 @@ float *BlurBaseOperation::make_gausstab(float rad, int size) } #ifdef __SSE2__ -__m128 *BlurBaseOperation::convert_gausstab_sse(const float *gausstab, float rad, int size) +__m128 *BlurBaseOperation::convert_gausstab_sse(const float *gausstab, int size) { int n = 2 * size + 1; __m128 *gausstab_sse = (__m128 *) MEM_mallocN_aligned(sizeof(__m128) * n, 16, "gausstab sse"); diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.h b/source/blender/compositor/operations/COM_BlurBaseOperation.h index e97dd4d766d..f9f37479c56 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.h +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.h @@ -39,7 +39,7 @@ protected: BlurBaseOperation(DataType data_type); float *make_gausstab(float rad, int size); #ifdef __SSE2__ - __m128 *convert_gausstab_sse(const float *gaustab, float rad, int size); + __m128 *convert_gausstab_sse(const float *gaustab, int size); #endif float *make_dist_fac_inverse(float rad, int size, int falloff); diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp index 22f6fc33a0d..189483708b5 100644 --- a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp @@ -45,7 +45,7 @@ BokehBlurOperation::BokehBlurOperation() : NodeOperation() this->m_inputBoundingBoxReader = NULL; } -void *BokehBlurOperation::initializeTileData(rcti *rect) +void *BokehBlurOperation::initializeTileData(rcti * /*rect*/) { lockMutex(); if (!this->m_sizeavailable) { @@ -194,7 +194,7 @@ bool BokehBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBuffe void BokehBlurOperation::executeOpenCL(OpenCLDevice *device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list *clMemToCleanUp, - list *clKernelsToCleanUp) + list * /*clKernelsToCleanUp*/) { cl_kernel kernel = device->COM_clCreateKernel("bokehBlurKernel", NULL); if (!this->m_sizeavailable) { diff --git a/source/blender/compositor/operations/COM_BokehImageOperation.cpp b/source/blender/compositor/operations/COM_BokehImageOperation.cpp index 6617fc62ab8..18846f2a2c5 100644 --- a/source/blender/compositor/operations/COM_BokehImageOperation.cpp +++ b/source/blender/compositor/operations/COM_BokehImageOperation.cpp @@ -85,7 +85,7 @@ float BokehImageOperation::isInsideBokeh(float distance, float x, float y) } return insideBokeh; } -void BokehImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void BokehImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { float shift = this->m_data->lensshift; float shift2 = shift / 2.0f; @@ -116,7 +116,7 @@ void BokehImageOperation::deinitExecution() } } -void BokehImageOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void BokehImageOperation::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) { resolution[0] = COM_BLUR_BOKEH_PIXELS; resolution[1] = COM_BLUR_BOKEH_PIXELS; diff --git a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp index 54b0e37c791..32395f44ef1 100644 --- a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp +++ b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp @@ -44,7 +44,9 @@ void CalculateMeanOperation::initExecution() NodeOperation::initMutex(); } -void CalculateMeanOperation::executePixel(float output[4], int x, int y, void *data) +void CalculateMeanOperation::executePixel(float output[4], + int /*x*/, int /*y*/, + void */*data*/) { output[0] = this->m_result; } @@ -55,7 +57,7 @@ void CalculateMeanOperation::deinitExecution() NodeOperation::deinitMutex(); } -bool CalculateMeanOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool CalculateMeanOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) { rcti imageInput; if (this->m_iscalculated) { diff --git a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp index 32c5fc1adc7..6b238e53d7b 100644 --- a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp +++ b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp @@ -33,7 +33,9 @@ CalculateStandardDeviationOperation::CalculateStandardDeviationOperation() : Cal /* pass */ } -void CalculateStandardDeviationOperation::executePixel(float output[4], int x, int y, void *data) +void CalculateStandardDeviationOperation::executePixel(float output[4], + int /*x*/, int /*y*/, + void * /*data*/) { output[0] = this->m_standardDeviation; } diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp index e3438bcbd15..ffef81d0323 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.cpp +++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp @@ -125,7 +125,7 @@ void CompositorOperation::deinitExecution() } -void CompositorOperation::executeRegion(rcti *rect, unsigned int tileNumber) +void CompositorOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/) { float color[8]; // 7 is enough float *buffer = this->m_outputBuffer; diff --git a/source/blender/compositor/operations/COM_CompositorOperation.h b/source/blender/compositor/operations/COM_CompositorOperation.h index 771c32ffd12..447d74131b3 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.h +++ b/source/blender/compositor/operations/COM_CompositorOperation.h @@ -81,7 +81,7 @@ public: void executeRegion(rcti *rect, unsigned int tileNumber); void setSceneName(const char *sceneName) { BLI_strncpy(this->m_sceneName, sceneName, sizeof(this->m_sceneName)); } void setRenderData(const RenderData *rd) { this->m_rd = rd; } - bool isOutputOperation(bool rendering) const { return this->isActiveCompositorOutput(); } + bool isOutputOperation(bool /*rendering*/) const { return this->isActiveCompositorOutput(); } void initExecution(); void deinitExecution(); const CompositorPriority getRenderPriority() const { return COM_PRIORITY_MEDIUM; } diff --git a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp index 657126d458c..e1ada9a8c39 100644 --- a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp @@ -28,7 +28,7 @@ ConvolutionEdgeFilterOperation::ConvolutionEdgeFilterOperation() : ConvolutionFi /* pass */ } -void ConvolutionEdgeFilterOperation::executePixel(float output[4], int x, int y, void *data) +void ConvolutionEdgeFilterOperation::executePixel(float output[4], int x, int y, void * /*data*/) { float in1[4], in2[4], res1[4] = {0.0}, res2[4] = {0.0}; diff --git a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp index 553a9827ffa..699db11d56e 100644 --- a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp @@ -69,7 +69,7 @@ void ConvolutionFilterOperation::deinitExecution() } -void ConvolutionFilterOperation::executePixel(float output[4], int x, int y, void *data) +void ConvolutionFilterOperation::executePixel(float output[4], int x, int y, void * /*data*/) { float in1[4]; float in2[4]; diff --git a/source/blender/compositor/operations/COM_DespeckleOperation.cpp b/source/blender/compositor/operations/COM_DespeckleOperation.cpp index 186c17845f3..1a827aae67e 100644 --- a/source/blender/compositor/operations/COM_DespeckleOperation.cpp +++ b/source/blender/compositor/operations/COM_DespeckleOperation.cpp @@ -52,7 +52,7 @@ BLI_INLINE int color_diff(const float a[3], const float b[3], const float thresh (fabsf(a[2] - b[2]) > threshold)); } -void DespeckleOperation::executePixel(float output[4], int x, int y, void *data) +void DespeckleOperation::executePixel(float output[4], int x, int y, void * /*data*/) { float w = 0.0f; float color_org[4]; diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp index 6d15ef3395b..fc3ec7dd11a 100644 --- a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp +++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp @@ -56,7 +56,7 @@ void DilateErodeThresholdOperation::initExecution() } } -void *DilateErodeThresholdOperation::initializeTileData(rcti *rect) +void *DilateErodeThresholdOperation::initializeTileData(rcti * /*rect*/) { void *buffer = this->m_inputProgram->initializeTileData(NULL); return buffer; @@ -180,7 +180,7 @@ void DilateDistanceOperation::initExecution() } } -void *DilateDistanceOperation::initializeTileData(rcti *rect) +void *DilateDistanceOperation::initializeTileData(rcti * /*rect*/) { void *buffer = this->m_inputProgram->initializeTileData(NULL); return buffer; @@ -238,7 +238,7 @@ bool DilateDistanceOperation::determineDependingAreaOfInterest(rcti *input, Read void DilateDistanceOperation::executeOpenCL(OpenCLDevice *device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list *clMemToCleanUp, - list *clKernelsToCleanUp) + list * /*clKernelsToCleanUp*/) { cl_kernel dilateKernel = device->COM_clCreateKernel("dilateKernel", NULL); @@ -295,7 +295,7 @@ void ErodeDistanceOperation::executePixel(float output[4], int x, int y, void *d void ErodeDistanceOperation::executeOpenCL(OpenCLDevice *device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list *clMemToCleanUp, - list *clKernelsToCleanUp) + list * /*clKernelsToCleanUp*/) { cl_kernel erodeKernel = device->COM_clCreateKernel("erodeKernel", NULL); @@ -446,7 +446,7 @@ void DilateStepOperation::deinitExecution() this->m_inputProgram = NULL; } -void DilateStepOperation::deinitializeTileData(rcti *rect, void *data) +void DilateStepOperation::deinitializeTileData(rcti * /*rect*/, void *data) { tile_info *tile = (tile_info *)data; MEM_freeN(tile->buffer); diff --git a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp index 962a95ebd05..732e731fadf 100644 --- a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp @@ -66,7 +66,7 @@ void DirectionalBlurOperation::initExecution() } -void DirectionalBlurOperation::executePixel(float output[4], int x, int y, void *data) +void DirectionalBlurOperation::executePixel(float output[4], int x, int y, void * /*data*/) { const int iterations = pow(2.0f, this->m_data->iter); float col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; @@ -104,7 +104,7 @@ void DirectionalBlurOperation::executePixel(float output[4], int x, int y, void void DirectionalBlurOperation::executeOpenCL(OpenCLDevice *device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list *clMemToCleanUp, - list *clKernelsToCleanUp) + list * /*clKernelsToCleanUp*/) { cl_kernel directionalBlurKernel = device->COM_clCreateKernel("directionalBlurKernel", NULL); @@ -132,7 +132,7 @@ void DirectionalBlurOperation::deinitExecution() this->m_inputProgram = NULL; } -bool DirectionalBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool DirectionalBlurOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) { rcti newInput; diff --git a/source/blender/compositor/operations/COM_DisplaceOperation.cpp b/source/blender/compositor/operations/COM_DisplaceOperation.cpp index 7dacc3239c5..643ecf9708c 100644 --- a/source/blender/compositor/operations/COM_DisplaceOperation.cpp +++ b/source/blender/compositor/operations/COM_DisplaceOperation.cpp @@ -49,7 +49,7 @@ void DisplaceOperation::initExecution() this->m_height_x4 = this->getHeight() * 4; } -void DisplaceOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void DisplaceOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { float xy[2] = { x, y }; float uv[2], deriv[2][2]; diff --git a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp index 234a61a4c41..76afedf4b2a 100644 --- a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp +++ b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp @@ -1237,7 +1237,7 @@ DoubleEdgeMaskOperation::DoubleEdgeMaskOperation() : NodeOperation() this->setComplex(true); } -bool DoubleEdgeMaskOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool DoubleEdgeMaskOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) { if (this->m_cachedInstance == NULL) { rcti newInput; diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp index 08f520e4271..968319b3f46 100644 --- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp @@ -37,7 +37,7 @@ void FastGaussianBlurOperation::executePixel(float output[4], int x, int y, void newData->read(output, x, y); } -bool FastGaussianBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool FastGaussianBlurOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) { rcti newInput; rcti sizeInput; @@ -257,7 +257,7 @@ void FastGaussianBlurValueOperation::executePixel(float output[4], int x, int y, newData->read(output, x, y); } -bool FastGaussianBlurValueOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool FastGaussianBlurValueOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) { rcti newInput; diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp index dde57ab640f..cbe41076b2a 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp @@ -36,7 +36,7 @@ GaussianAlphaXBlurOperation::GaussianAlphaXBlurOperation() : BlurBaseOperation(C this->m_falloff = -1; /* intentionally invalid, so we can detect uninitialized values */ } -void *GaussianAlphaXBlurOperation::initializeTileData(rcti *rect) +void *GaussianAlphaXBlurOperation::initializeTileData(rcti * /*rect*/) { lockMutex(); if (!this->m_sizeavailable) { diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp index bb5b3c044af..30563e8cc45 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp @@ -36,7 +36,7 @@ GaussianAlphaYBlurOperation::GaussianAlphaYBlurOperation() : BlurBaseOperation(C this->m_falloff = -1; /* intentionally invalid, so we can detect uninitialized values */ } -void *GaussianAlphaYBlurOperation::initializeTileData(rcti *rect) +void *GaussianAlphaYBlurOperation::initializeTileData(rcti * /*rect*/) { lockMutex(); if (!this->m_sizeavailable) { diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp index dbad51c4329..37d59229e50 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp @@ -32,7 +32,7 @@ GaussianBokehBlurOperation::GaussianBokehBlurOperation() : BlurBaseOperation(COM this->m_gausstab = NULL; } -void *GaussianBokehBlurOperation::initializeTileData(rcti *rect) +void *GaussianBokehBlurOperation::initializeTileData(rcti * /*rect*/) { lockMutex(); if (!this->m_sizeavailable) { @@ -205,7 +205,7 @@ GaussianBlurReferenceOperation::GaussianBlurReferenceOperation() : BlurBaseOpera this->m_maintabs = NULL; } -void *GaussianBlurReferenceOperation::initializeTileData(rcti *rect) +void *GaussianBlurReferenceOperation::initializeTileData(rcti * /*rect*/) { void *buffer = getInputOperation(0)->initializeTileData(NULL); return buffer; diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp index 0838d281de7..29ed4334412 100644 --- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp @@ -38,7 +38,7 @@ GaussianXBlurOperation::GaussianXBlurOperation() : BlurBaseOperation(COM_DT_COLO this->m_filtersize = 0; } -void *GaussianXBlurOperation::initializeTileData(rcti *rect) +void *GaussianXBlurOperation::initializeTileData(rcti * /*rect*/) { lockMutex(); if (!this->m_sizeavailable) { @@ -63,7 +63,6 @@ void GaussianXBlurOperation::initExecution() this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); #ifdef __SSE2__ this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab, - rad, m_filtersize); #endif } @@ -79,7 +78,6 @@ void GaussianXBlurOperation::updateGauss() this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); #ifdef __SSE2__ this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab, - rad, m_filtersize); #endif } @@ -128,7 +126,7 @@ void GaussianXBlurOperation::executePixel(float output[4], int x, int y, void *d void GaussianXBlurOperation::executeOpenCL(OpenCLDevice *device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list *clMemToCleanUp, - list *clKernelsToCleanUp) + list * /*clKernelsToCleanUp*/) { cl_kernel gaussianXBlurOperationKernel = device->COM_clCreateKernel("gaussianXBlurOperationKernel", NULL); cl_int filter_size = this->m_filtersize; diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp index 6172f954087..4b55333c08c 100644 --- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp @@ -38,7 +38,7 @@ GaussianYBlurOperation::GaussianYBlurOperation() : BlurBaseOperation(COM_DT_COLO this->m_filtersize = 0; } -void *GaussianYBlurOperation::initializeTileData(rcti *rect) +void *GaussianYBlurOperation::initializeTileData(rcti * /*rect*/) { lockMutex(); if (!this->m_sizeavailable) { @@ -62,7 +62,6 @@ void GaussianYBlurOperation::initExecution() this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); #ifdef __SSE2__ this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab, - rad, m_filtersize); #endif } @@ -78,7 +77,6 @@ void GaussianYBlurOperation::updateGauss() this->m_gausstab = BlurBaseOperation::make_gausstab(rad, m_filtersize); #ifdef __SSE2__ this->m_gausstab_sse = BlurBaseOperation::convert_gausstab_sse(this->m_gausstab, - rad, m_filtersize); #endif } @@ -130,7 +128,7 @@ void GaussianYBlurOperation::executePixel(float output[4], int x, int y, void *d void GaussianYBlurOperation::executeOpenCL(OpenCLDevice *device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list *clMemToCleanUp, - list *clKernelsToCleanUp) + list * /*clKernelsToCleanUp*/) { cl_kernel gaussianYBlurOperationKernel = device->COM_clCreateKernel("gaussianYBlurOperationKernel", NULL); cl_int filter_size = this->m_filtersize; diff --git a/source/blender/compositor/operations/COM_GlareBaseOperation.cpp b/source/blender/compositor/operations/COM_GlareBaseOperation.cpp index 98919f1b161..1acbd2ae090 100644 --- a/source/blender/compositor/operations/COM_GlareBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareBaseOperation.cpp @@ -55,7 +55,7 @@ MemoryBuffer *GlareBaseOperation::createMemoryBuffer(rcti *rect2) return result; } -bool GlareBaseOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool GlareBaseOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) { if (isCached()) { return false; diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp index 2733c483146..624fdf8b626 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.cpp +++ b/source/blender/compositor/operations/COM_ImageOperation.cpp @@ -96,7 +96,7 @@ void BaseImageOperation::deinitExecution() BKE_image_release_ibuf(this->m_image, this->m_buffer, NULL); } -void BaseImageOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void BaseImageOperation::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) { ImBuf *stackbuf = getImBuf(); @@ -170,7 +170,7 @@ void ImageAlphaOperation::executePixelSampled(float output[4], float x, float y, } } -void ImageDepthOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void ImageDepthOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { if (this->m_depthBuffer == NULL) { output[0] = 0.0f; diff --git a/source/blender/compositor/operations/COM_InpaintOperation.cpp b/source/blender/compositor/operations/COM_InpaintOperation.cpp index 18611c051d3..43b7b30319d 100644 --- a/source/blender/compositor/operations/COM_InpaintOperation.cpp +++ b/source/blender/compositor/operations/COM_InpaintOperation.cpp @@ -241,7 +241,7 @@ void *InpaintSimpleOperation::initializeTileData(rcti *rect) return this->m_cached_buffer; } -void InpaintSimpleOperation::executePixel(float output[4], int x, int y, void *data) +void InpaintSimpleOperation::executePixel(float output[4], int x, int y, void * /*data*/) { this->clamp_xy(x, y); copy_v4_v4(output, this->get_pixel(x, y)); @@ -268,7 +268,7 @@ void InpaintSimpleOperation::deinitExecution() this->m_cached_buffer_ready = false; } -bool InpaintSimpleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool InpaintSimpleOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) { if (this->m_cached_buffer_ready) { return false; diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp index 1633d2a2f1d..dd87578ea78 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp @@ -267,7 +267,7 @@ void *KeyingScreenOperation::initializeTileData(rcti *rect) return tile_data; } -void KeyingScreenOperation::deinitializeTileData(rcti *rect, void *data) +void KeyingScreenOperation::deinitializeTileData(rcti * /*rect*/, void *data) { TileData *tile_data = (TileData *) data; @@ -278,7 +278,7 @@ void KeyingScreenOperation::deinitializeTileData(rcti *rect, void *data) MEM_freeN(tile_data); } -void KeyingScreenOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void KeyingScreenOperation::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) { resolution[0] = 0; resolution[1] = 0; diff --git a/source/blender/compositor/operations/COM_MapUVOperation.cpp b/source/blender/compositor/operations/COM_MapUVOperation.cpp index bb8fe825c68..ffa48ce3956 100644 --- a/source/blender/compositor/operations/COM_MapUVOperation.cpp +++ b/source/blender/compositor/operations/COM_MapUVOperation.cpp @@ -41,7 +41,7 @@ void MapUVOperation::initExecution() this->m_inputUVProgram = this->getInputSocketReader(1); } -void MapUVOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MapUVOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { float xy[2] = { x, y }; float uv[2], deriv[2][2], alpha; diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp index 8c8ba93327d..220b4e908a6 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.cpp +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -1,4 +1,5 @@ /* + * Copyright 2012, Blender Foundation. * * This program is free software; you can redistribute it and/or @@ -127,7 +128,7 @@ void MaskOperation::determineResolution(unsigned int resolution[2], unsigned int } } -void MaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { const float xy[2] = { (x * this->m_maskWidthInv) + this->m_mask_px_ofs[0], diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp index 447ca1bb4f6..040a0315d69 100644 --- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp @@ -33,7 +33,9 @@ MovieClipAttributeOperation::MovieClipAttributeOperation() : NodeOperation() this->m_attribute = MCA_X; } -void MovieClipAttributeOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MovieClipAttributeOperation::executePixelSampled(float output[4], + float /*x*/, float /*y*/, + PixelSampler /*sampler*/) { if (!this->m_valueSet) { float loc[2], scale, angle; diff --git a/source/blender/compositor/operations/COM_MovieClipOperation.cpp b/source/blender/compositor/operations/COM_MovieClipOperation.cpp index 133b6d520eb..1e4821f0cd3 100644 --- a/source/blender/compositor/operations/COM_MovieClipOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieClipOperation.cpp @@ -71,7 +71,7 @@ void MovieClipBaseOperation::deinitExecution() } } -void MovieClipBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void MovieClipBaseOperation::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) { resolution[0] = 0; resolution[1] = 0; diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp index 50fabb09dbb..4f34d7fb150 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp @@ -121,7 +121,7 @@ void MovieDistortionOperation::deinitExecution() } -void MovieDistortionOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MovieDistortionOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { if (this->m_cache != NULL) { diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp index 23fba5a7999..513140e2f62 100644 --- a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp +++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp @@ -74,7 +74,7 @@ void MultilayerColorOperation::executePixelSampled(float output[4], float x, flo } } -void MultilayerValueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MultilayerValueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { if (this->m_imageFloatBuffer == NULL) { output[0] = 0.0f; @@ -91,7 +91,7 @@ void MultilayerValueOperation::executePixelSampled(float output[4], float x, flo } } -void MultilayerVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MultilayerVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { if (this->m_imageFloatBuffer == NULL) { output[0] = 0.0f; diff --git a/source/blender/compositor/operations/COM_NormalizeOperation.cpp b/source/blender/compositor/operations/COM_NormalizeOperation.cpp index e0b5893ffbb..504470f1a7e 100644 --- a/source/blender/compositor/operations/COM_NormalizeOperation.cpp +++ b/source/blender/compositor/operations/COM_NormalizeOperation.cpp @@ -60,7 +60,7 @@ void NormalizeOperation::deinitExecution() NodeOperation::deinitMutex(); } -bool NormalizeOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool NormalizeOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) { rcti imageInput; if (this->m_cachedInstance) return false; @@ -118,7 +118,7 @@ void *NormalizeOperation::initializeTileData(rcti *rect) return this->m_cachedInstance; } -void NormalizeOperation::deinitializeTileData(rcti *rect, void *data) +void NormalizeOperation::deinitializeTileData(rcti * /*rect*/, void * /*data*/) { /* pass */ } diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp index 2f92351c00d..b1c90a6355f 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp +++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp @@ -118,7 +118,7 @@ void OutputSingleLayerOperation::initExecution() this->m_outputBuffer = init_buffer(this->getWidth(), this->getHeight(), this->m_datatype); } -void OutputSingleLayerOperation::executeRegion(rcti *rect, unsigned int tileNumber) +void OutputSingleLayerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/) { write_buffer_rect(rect, this->m_tree, this->m_imageInput, this->m_outputBuffer, this->getWidth(), this->m_datatype); } @@ -194,7 +194,7 @@ void OutputOpenExrMultiLayerOperation::initExecution() } } -void OutputOpenExrMultiLayerOperation::executeRegion(rcti *rect, unsigned int tileNumber) +void OutputOpenExrMultiLayerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/) { for (unsigned int i = 0; i < this->m_layers.size(); ++i) { OutputOpenExrLayer &layer = this->m_layers[i]; diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h index 03278c5b149..af16f186d9d 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.h +++ b/source/blender/compositor/operations/COM_OutputFileOperation.h @@ -52,7 +52,7 @@ public: const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings); void executeRegion(rcti *rect, unsigned int tileNumber); - bool isOutputOperation(bool rendering) const { return true; } + bool isOutputOperation(bool /*rendering*/) const { return true; } void initExecution(); void deinitExecution(); const CompositorPriority getRenderPriority() const { return COM_PRIORITY_LOW; } @@ -91,7 +91,7 @@ public: void add_layer(const char *name, DataType datatype, bool use_layer); void executeRegion(rcti *rect, unsigned int tileNumber); - bool isOutputOperation(bool rendering) const { return true; } + bool isOutputOperation(bool /*rendering*/) const { return true; } void initExecution(); void deinitExecution(); const CompositorPriority getRenderPriority() const { return COM_PRIORITY_LOW; } diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp index 8133f392ac6..d7d1c9c0c93 100644 --- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp @@ -100,7 +100,7 @@ void PlaneDistortWarpImageOperation::deinitExecution() this->m_pixelReader = NULL; } -void PlaneDistortWarpImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void PlaneDistortWarpImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { float uv[2]; float deriv[2][2]; @@ -194,7 +194,7 @@ void PlaneDistortMaskOperation::initExecution() BLI_jitter_init(m_jitter, m_osa); } -void PlaneDistortMaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void PlaneDistortMaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { float point[2]; int inside_counter = 0; diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp index 03205130a74..a56aa0cbaa6 100644 --- a/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp @@ -71,7 +71,7 @@ void PlaneTrackCommon::readCornersFromTrack(float corners[4][2], float frame) } } -void PlaneTrackCommon::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void PlaneTrackCommon::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) { resolution[0] = 0; resolution[1] = 0; diff --git a/source/blender/compositor/operations/COM_PreviewOperation.cpp b/source/blender/compositor/operations/COM_PreviewOperation.cpp index 69290cd7c3c..aa667884de6 100644 --- a/source/blender/compositor/operations/COM_PreviewOperation.cpp +++ b/source/blender/compositor/operations/COM_PreviewOperation.cpp @@ -85,7 +85,7 @@ void PreviewOperation::deinitExecution() this->m_input = NULL; } -void PreviewOperation::executeRegion(rcti *rect, unsigned int tileNumber) +void PreviewOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/) { int offset; float color[4]; diff --git a/source/blender/compositor/operations/COM_PreviewOperation.h b/source/blender/compositor/operations/COM_PreviewOperation.h index 3e97acec7bb..5da7a25ac5d 100644 --- a/source/blender/compositor/operations/COM_PreviewOperation.h +++ b/source/blender/compositor/operations/COM_PreviewOperation.h @@ -45,7 +45,7 @@ public: PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings); void verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key); - bool isOutputOperation(bool rendering) const { return !G.background; } + bool isOutputOperation(bool /*rendering*/) const { return !G.background; } void initExecution(); void deinitExecution(); const CompositorPriority getRenderPriority() const; diff --git a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp index 7f6079c55aa..02d1809efbb 100644 --- a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp @@ -40,7 +40,7 @@ void ProjectorLensDistortionOperation::initExecution() this->m_inputProgram = this->getInputSocketReader(0); } -void *ProjectorLensDistortionOperation::initializeTileData(rcti *rect) +void *ProjectorLensDistortionOperation::initializeTileData(rcti * /*rect*/) { updateDispersion(); void *buffer = this->m_inputProgram->initializeTileData(NULL); diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp index ad4084a7092..bf0f24e06be 100644 --- a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp @@ -32,7 +32,7 @@ ReadBufferOperation::ReadBufferOperation(DataType datatype) : NodeOperation() this->m_buffer = NULL; } -void *ReadBufferOperation::initializeTileData(rcti *rect) +void *ReadBufferOperation::initializeTileData(rcti * /*rect*/) { return m_buffer; } diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp index 409fa68bacf..defbc2ab57f 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp +++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp @@ -179,7 +179,7 @@ void RenderLayersBaseProg::deinitExecution() this->m_inputBuffer = NULL; } -void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) { Scene *sce = this->getScene(); Render *re = (sce) ? RE_GetRender(sce->id.name) : NULL; @@ -269,7 +269,7 @@ RenderLayersDepthProg::RenderLayersDepthProg() : RenderLayersBaseProg(SCE_PASS_Z this->addOutputSocket(COM_DT_VALUE); } -void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { int ix = x; int iy = y; diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cpp b/source/blender/compositor/operations/COM_ScaleOperation.cpp index 23e8ce86fd9..117ae743ee7 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.cpp +++ b/source/blender/compositor/operations/COM_ScaleOperation.cpp @@ -279,7 +279,7 @@ bool ScaleFixedSizeOperation::determineDependingAreaOfInterest(rcti *input, Read return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } -void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) { unsigned int nr[2]; nr[0] = this->m_newWidth; diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp index ad9b761da45..acd76fa79a8 100644 --- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp @@ -70,7 +70,7 @@ void ScreenLensDistortionOperation::initExecution() } } -void *ScreenLensDistortionOperation::initializeTileData(rcti *rect) +void *ScreenLensDistortionOperation::initializeTileData(rcti * /*rect*/) { void *buffer = this->m_inputProgram->initializeTileData(NULL); @@ -208,7 +208,7 @@ void ScreenLensDistortionOperation::determineUV(float result[6], float x, float get_delta(uv_dot, m_k4[2], uv, result + 4); } -bool ScreenLensDistortionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool ScreenLensDistortionOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) { rcti newInputValue; newInputValue.xmin = 0; diff --git a/source/blender/compositor/operations/COM_SetColorOperation.cpp b/source/blender/compositor/operations/COM_SetColorOperation.cpp index 94a863e628b..1a362bc55e2 100644 --- a/source/blender/compositor/operations/COM_SetColorOperation.cpp +++ b/source/blender/compositor/operations/COM_SetColorOperation.cpp @@ -27,7 +27,9 @@ SetColorOperation::SetColorOperation() : NodeOperation() this->addOutputSocket(COM_DT_COLOR); } -void SetColorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void SetColorOperation::executePixelSampled(float output[4], + float /*x*/, float /*y*/, + PixelSampler /*sampler*/) { copy_v4_v4(output, this->m_color); } diff --git a/source/blender/compositor/operations/COM_SetSamplerOperation.cpp b/source/blender/compositor/operations/COM_SetSamplerOperation.cpp index be72ffd0336..7057ecb14c1 100644 --- a/source/blender/compositor/operations/COM_SetSamplerOperation.cpp +++ b/source/blender/compositor/operations/COM_SetSamplerOperation.cpp @@ -37,7 +37,7 @@ void SetSamplerOperation::deinitExecution() this->m_reader = NULL; } -void SetSamplerOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void SetSamplerOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { this->m_reader->readSampled(output, x, y, this->m_sampler); } diff --git a/source/blender/compositor/operations/COM_SetValueOperation.cpp b/source/blender/compositor/operations/COM_SetValueOperation.cpp index 51e09a63051..b6cfb760a98 100644 --- a/source/blender/compositor/operations/COM_SetValueOperation.cpp +++ b/source/blender/compositor/operations/COM_SetValueOperation.cpp @@ -27,7 +27,9 @@ SetValueOperation::SetValueOperation() : NodeOperation() this->addOutputSocket(COM_DT_VALUE); } -void SetValueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void SetValueOperation::executePixelSampled(float output[4], + float /*x*/, float /*y*/, + PixelSampler /*sampler*/) { output[0] = this->m_value; } diff --git a/source/blender/compositor/operations/COM_SetVectorOperation.cpp b/source/blender/compositor/operations/COM_SetVectorOperation.cpp index 769eaf1d2ed..1b0327683a9 100644 --- a/source/blender/compositor/operations/COM_SetVectorOperation.cpp +++ b/source/blender/compositor/operations/COM_SetVectorOperation.cpp @@ -28,7 +28,9 @@ SetVectorOperation::SetVectorOperation() : NodeOperation() this->addOutputSocket(COM_DT_VECTOR); } -void SetVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void SetVectorOperation::executePixelSampled(float output[4], + float /*x*/, float /*y*/, + PixelSampler /*sampler*/) { output[0] = this->m_x; output[1] = this->m_y; diff --git a/source/blender/compositor/operations/COM_SplitOperation.cpp b/source/blender/compositor/operations/COM_SplitOperation.cpp index 367c7eefa25..cd2166591bc 100644 --- a/source/blender/compositor/operations/COM_SplitOperation.cpp +++ b/source/blender/compositor/operations/COM_SplitOperation.cpp @@ -56,7 +56,7 @@ void SplitOperation::deinitExecution() this->m_image2Input = NULL; } -void SplitOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void SplitOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { int perc = this->m_xSplit ? this->m_splitPercentage * this->getWidth() / 100.0f : this->m_splitPercentage * this->getHeight() / 100.0f; bool image1 = this->m_xSplit ? x > perc : y > perc; diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp index 0ca687ea162..a681583809c 100644 --- a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp +++ b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp @@ -293,7 +293,7 @@ static void accumulate_line(MemoryBuffer *input, float output[4], const float co } } -void *SunBeamsOperation::initializeTileData(rcti *rect) +void *SunBeamsOperation::initializeTileData(rcti * /*rect*/) { void *buffer = getInputOperation(0)->initializeTileData(NULL); return buffer; diff --git a/source/blender/compositor/operations/COM_TextureOperation.cpp b/source/blender/compositor/operations/COM_TextureOperation.cpp index 1b0485afb8d..2ff6cc047c6 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.cpp +++ b/source/blender/compositor/operations/COM_TextureOperation.cpp @@ -117,7 +117,7 @@ void TextureBaseOperation::executePixelSampled(float output[4], float x, float y } } -MemoryBuffer *TextureBaseOperation::createMemoryBuffer(rcti *rect2) +MemoryBuffer *TextureBaseOperation::createMemoryBuffer(rcti * /*rect2*/) { int height = getHeight(); int width = getWidth(); diff --git a/source/blender/compositor/operations/COM_TonemapOperation.cpp b/source/blender/compositor/operations/COM_TonemapOperation.cpp index 54ba218b802..c581d115a2f 100644 --- a/source/blender/compositor/operations/COM_TonemapOperation.cpp +++ b/source/blender/compositor/operations/COM_TonemapOperation.cpp @@ -97,7 +97,7 @@ void TonemapOperation::deinitExecution() NodeOperation::deinitMutex(); } -bool TonemapOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool TonemapOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) { rcti imageInput; @@ -150,7 +150,7 @@ void *TonemapOperation::initializeTileData(rcti *rect) return this->m_cachedInstance; } -void TonemapOperation::deinitializeTileData(rcti *rect, void *data) +void TonemapOperation::deinitializeTileData(rcti * /*rect*/, void * /*data*/) { /* pass */ } diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp index a76e0866d0d..ca169d03fbc 100644 --- a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp +++ b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp @@ -102,7 +102,9 @@ void TrackPositionOperation::initExecution() } } -void TrackPositionOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void TrackPositionOperation::executePixelSampled(float output[4], + float /*x*/, float /*y*/, + PixelSampler /*sampler*/) { output[0] = this->m_markerPos[this->m_axis] - this->m_relativePos[this->m_axis]; diff --git a/source/blender/compositor/operations/COM_TranslateOperation.cpp b/source/blender/compositor/operations/COM_TranslateOperation.cpp index 191388a42fb..fcf99a10a73 100644 --- a/source/blender/compositor/operations/COM_TranslateOperation.cpp +++ b/source/blender/compositor/operations/COM_TranslateOperation.cpp @@ -52,7 +52,7 @@ void TranslateOperation::deinitExecution() } -void TranslateOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void TranslateOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { ensureDelta(); diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp index 6e4caeef613..e4883d91bc3 100644 --- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp @@ -89,7 +89,7 @@ void *VariableSizeBokehBlurOperation::initializeTileData(rcti *rect) return data; } -void VariableSizeBokehBlurOperation::deinitializeTileData(rcti *rect, void *data) +void VariableSizeBokehBlurOperation::deinitializeTileData(rcti * /*rect*/, void *data) { VariableSizeBokehBlurTileData *result = (VariableSizeBokehBlurTileData *)data; delete result; @@ -187,7 +187,7 @@ void VariableSizeBokehBlurOperation::executePixel(float output[4], int x, int y, void VariableSizeBokehBlurOperation::executeOpenCL(OpenCLDevice *device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list *clMemToCleanUp, - list *clKernelsToCleanUp) + list * /*clKernelsToCleanUp*/) { cl_kernel defocusKernel = device->COM_clCreateKernel("defocusKernel", NULL); diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp index 8dc06ef07d7..36f06e92436 100644 --- a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp @@ -91,7 +91,7 @@ void *VectorBlurOperation::initializeTileData(rcti *rect) return this->m_cachedInstance; } -bool VectorBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool VectorBlurOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output) { if (this->m_cachedInstance == NULL) { rcti newInput; diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp index 53c0acd781a..da2706a2244 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp @@ -80,7 +80,7 @@ void ViewerOperation::deinitExecution() this->m_outputBuffer = NULL; } -void ViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber) +void ViewerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/) { float *buffer = this->m_outputBuffer; float *depthbuffer = this->m_depthBuffer; diff --git a/source/blender/compositor/operations/COM_ViewerOperation.h b/source/blender/compositor/operations/COM_ViewerOperation.h index dcc7ffa3730..a17375c2de9 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.h +++ b/source/blender/compositor/operations/COM_ViewerOperation.h @@ -53,7 +53,7 @@ public: void initExecution(); void deinitExecution(); void executeRegion(rcti *rect, unsigned int tileNumber); - bool isOutputOperation(bool rendering) const { if (G.background) return false; return isActiveViewerOutput(); } + bool isOutputOperation(bool /*rendering*/) const { if (G.background) return false; return isActiveViewerOutput(); } void setImage(Image *image) { this->m_image = image; } void setImageUser(ImageUser *imageUser) { this->m_imageUser = imageUser; } const bool isActiveViewerOutput() const { return this->m_active; } diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp index fccff2a33bf..b3c1c00804e 100644 --- a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp @@ -57,7 +57,7 @@ void WriteBufferOperation::deinitExecution() this->m_memoryProxy->free(); } -void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber) +void WriteBufferOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/) { MemoryBuffer *memoryBuffer = this->m_memoryProxy->getBuffer(); float *buffer = memoryBuffer->getBuffer(); @@ -110,7 +110,7 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber) memoryBuffer->setCreatedState(); } -void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device, rcti *rect, unsigned int chunkNumber, +void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device, rcti * /*rect*/, unsigned int /*chunkNumber*/, MemoryBuffer **inputMemoryBuffers, MemoryBuffer *outputBuffer) { float *outputFloatBuffer = outputBuffer->getBuffer(); -- cgit v1.2.3 From 13358d049e2de813d4dc83c41c3f87f5fae3c3a1 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 15:50:18 +0500 Subject: Freestyle: Code cleanup, prepare for strict C++ flags --- .../freestyle/intern/application/AppView.cpp | 2 +- .../blender/freestyle/intern/application/AppView.h | 4 ++-- .../freestyle/intern/application/Controller.cpp | 6 ++--- .../blender_interface/BlenderStrokeRenderer.cpp | 2 +- .../intern/blender_interface/FRS_freestyle.cpp | 4 ++-- .../freestyle/intern/geometry/GeomUtils.cpp | 2 +- source/blender/freestyle/intern/geometry/Grid.h | 6 ++--- .../freestyle/intern/image/ImagePyramid.cpp | 2 +- .../intern/python/BPy_ContextFunctions.cpp | 18 +++++++------- .../freestyle/intern/python/BPy_Freestyle.cpp | 8 +++---- .../intern/python/BPy_IntegrationType.cpp | 2 +- .../freestyle/intern/python/BPy_Operators.cpp | 28 +++++++++++----------- .../intern/python/BPy_UnaryFunction0D.cpp | 2 +- .../intern/python/BPy_UnaryFunction1D.cpp | 2 +- .../intern/python/Interface0D/BPy_ViewVertex.cpp | 4 ++-- .../Interface0D/CurvePoint/BPy_StrokeVertex.cpp | 8 +++---- .../intern/python/Interface1D/BPy_FEdge.cpp | 2 +- .../python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp | 8 +++---- .../blender/freestyle/intern/stroke/Predicates1D.h | 4 ++-- source/blender/freestyle/intern/stroke/Stroke.cpp | 4 ++-- .../blender/freestyle/intern/view_map/BoxGrid.cpp | 4 ++-- .../freestyle/intern/view_map/Interface1D.cpp | 4 ++-- .../blender/freestyle/intern/view_map/Silhouette.h | 4 ++-- .../freestyle/intern/view_map/SphericalGrid.cpp | 4 ++-- .../blender/freestyle/intern/view_map/ViewMap.cpp | 4 ++-- .../freestyle/intern/view_map/ViewMapBuilder.cpp | 6 ++--- .../freestyle/intern/view_map/ViewMapBuilder.h | 2 +- .../intern/winged_edge/WingedEdgeBuilder.cpp | 12 +++++----- 28 files changed, 79 insertions(+), 79 deletions(-) diff --git a/source/blender/freestyle/intern/application/AppView.cpp b/source/blender/freestyle/intern/application/AppView.cpp index ae202412c09..9de426b91ab 100644 --- a/source/blender/freestyle/intern/application/AppView.cpp +++ b/source/blender/freestyle/intern/application/AppView.cpp @@ -58,7 +58,7 @@ extern "C" { namespace Freestyle { -AppView::AppView(const char *iName) +AppView::AppView(const char * /*iName*/) { _Fovy = DEG2RADF(30.0f); _ModelRootNode = new NodeDrawingStyle; diff --git a/source/blender/freestyle/intern/application/AppView.h b/source/blender/freestyle/intern/application/AppView.h index 14101909ca1..6338ace53c0 100644 --- a/source/blender/freestyle/intern/application/AppView.h +++ b/source/blender/freestyle/intern/application/AppView.h @@ -100,12 +100,12 @@ public: _SilhouetteRootNode->AddChild(iSilhouette); } - inline void Add2DSilhouette(NodeGroup *iSilhouette) + inline void Add2DSilhouette(NodeGroup * /*iSilhouette*/) { //_pFENode->AddChild(iSilhouette); } - inline void Add2DVisibleSilhouette(NodeGroup *iVSilhouette) + inline void Add2DVisibleSilhouette(NodeGroup * /*iVSilhouette*/) { //_pVisibleSilhouetteNode->AddChild(iVSilhouette); } diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp index 8d9b1a4fb52..add7420b89a 100644 --- a/source/blender/freestyle/intern/application/Controller.cpp +++ b/source/blender/freestyle/intern/application/Controller.cpp @@ -933,7 +933,7 @@ void Controller::InsertStyleModule(unsigned index, const char *iName, struct Tex _Canvas->InsertStyleModule(index, sm); } -void Controller::AddStyleModule(const char *iFileName) +void Controller::AddStyleModule(const char * /*iFileName*/) { //_pStyleWindow->Add(iFileName); } @@ -1003,7 +1003,7 @@ void Controller::toggleEdgeTesselationNature(Nature::EdgeNature iNature) ComputeViewMap(); } -void Controller::setModelsDir(const string& dir) +void Controller::setModelsDir(const string& /*dir*/) { //_current_dirs->setValue("models/dir", dir); } @@ -1015,7 +1015,7 @@ string Controller::getModelsDir() const return dir; } -void Controller::setModulesDir(const string& dir) +void Controller::setModulesDir(const string& /*dir*/) { //_current_dirs->setValue("modules/dir", dir); } diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index f304e8ae9bd..0e8f6222c8c 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -950,7 +950,7 @@ Object *BlenderStrokeRenderer::NewMesh() const return ob; } -Render *BlenderStrokeRenderer::RenderScene(Render *re, bool render) +Render *BlenderStrokeRenderer::RenderScene(Render * /*re*/, bool render) { Camera *camera = (Camera *)freestyle_scene->camera->data; if (camera->clipend < _z) diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 32b4c5455a7..d1285cf2c18 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -87,7 +87,7 @@ int freestyle_viewport[4]; // current scene Scene *freestyle_scene; -static void load_post_callback(struct Main *main, struct ID *id, void *arg) +static void load_post_callback(struct Main * /*main*/, struct ID * /*id*/, void * /*arg*/) { lineset_copied = false; } @@ -645,7 +645,7 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render) return freestyle_render; } -void FRS_finish_stroke_rendering(Render *re) +void FRS_finish_stroke_rendering(Render * /*re*/) { // clear canvas controller->Clear(); diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.cpp b/source/blender/freestyle/intern/geometry/GeomUtils.cpp index a750cf2f7cf..3eb92c559fe 100644 --- a/source/blender/freestyle/intern/geometry/GeomUtils.cpp +++ b/source/blender/freestyle/intern/geometry/GeomUtils.cpp @@ -495,7 +495,7 @@ bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin an real t0, real t1, real& tmin, // I0 = orig + tmin * dir is the first intersection real& tmax, // I1 = orig + tmax * dir is the second intersection - real epsilon) + real /*epsilon*/) { float tymin, tymax, tzmin, tzmax; Vec3r inv_direction(1.0 / dir[0], 1.0 / dir[1], 1.0 / dir[2]); diff --git a/source/blender/freestyle/intern/geometry/Grid.h b/source/blender/freestyle/intern/geometry/Grid.h index c1d04f6b4cc..62c0e58232a 100644 --- a/source/blender/freestyle/intern/geometry/Grid.h +++ b/source/blender/freestyle/intern/geometry/Grid.h @@ -97,11 +97,11 @@ class GridVisitor public: virtual ~GridVisitor() {}; //soc - virtual void discoverCell(Cell *cell) {} + virtual void discoverCell(Cell * /*cell*/) {} - virtual void examineOccluder(Polygon3r *occ) {} + virtual void examineOccluder(Polygon3r * /*occ*/) {} - virtual void finishCell(Cell *cell) {} + virtual void finishCell(Cell * /*cell*/) {} virtual bool stop() { return false; diff --git a/source/blender/freestyle/intern/image/ImagePyramid.cpp b/source/blender/freestyle/intern/image/ImagePyramid.cpp index 251f47bc44c..b81f8303945 100644 --- a/source/blender/freestyle/intern/image/ImagePyramid.cpp +++ b/source/blender/freestyle/intern/image/ImagePyramid.cpp @@ -42,7 +42,7 @@ ImagePyramid::ImagePyramid(const GrayImage& level0, unsigned nbLevels) } #endif -ImagePyramid::ImagePyramid(const ImagePyramid& iBrother) +ImagePyramid::ImagePyramid(const ImagePyramid& /*iBrother*/) { if (!_levels.empty()) { for (vector::iterator im = _levels.begin(), imend = _levels.end(); im != imend; ++im) { diff --git a/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp index ad54a81f156..50d82656819 100644 --- a/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp +++ b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp @@ -46,7 +46,7 @@ static char ContextFunctions_get_time_stamp___doc__[] = " :rtype: int\n"; static PyObject * -ContextFunctions_get_time_stamp(PyObject *self) +ContextFunctions_get_time_stamp(PyObject * /*self*/) { return PyLong_FromLong(ContextFunctions::GetTimeStampCF()); } @@ -60,7 +60,7 @@ static char ContextFunctions_get_canvas_width___doc__[] = " :rtype: int\n"; static PyObject * -ContextFunctions_get_canvas_width(PyObject *self) +ContextFunctions_get_canvas_width(PyObject * /*self*/) { return PyLong_FromLong(ContextFunctions::GetCanvasWidthCF()); } @@ -74,7 +74,7 @@ static char ContextFunctions_get_canvas_height___doc__[] = " :rtype: int\n"; static PyObject * -ContextFunctions_get_canvas_height(PyObject *self) +ContextFunctions_get_canvas_height(PyObject * /*self*/) { return PyLong_FromLong(ContextFunctions::GetCanvasHeightCF()); } @@ -88,7 +88,7 @@ static char ContextFunctions_get_border___doc__[] = " :rtype: tuple\n"; static PyObject * -ContextFunctions_get_border(PyObject *self) +ContextFunctions_get_border(PyObject * /*self*/) { BBox border(ContextFunctions::GetBorderCF()); PyObject *v = PyTuple_New(4); @@ -117,7 +117,7 @@ static char ContextFunctions_load_map___doc__[] = " :type sigma: float\n"; static PyObject * -ContextFunctions_load_map(PyObject *self, PyObject *args, PyObject *kwds) +ContextFunctions_load_map(PyObject * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"file_name", "map_name", "num_levels", "sigma", NULL}; char *fileName, *mapName; @@ -150,7 +150,7 @@ static char ContextFunctions_read_map_pixel___doc__[] = " :rtype: float\n"; static PyObject * -ContextFunctions_read_map_pixel(PyObject *self, PyObject *args, PyObject *kwds) +ContextFunctions_read_map_pixel(PyObject * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"map_name", "level", "x", "y", NULL}; char *mapName; @@ -180,7 +180,7 @@ static char ContextFunctions_read_complete_view_map_pixel___doc__[] = " :rtype: float\n"; static PyObject * -ContextFunctions_read_complete_view_map_pixel(PyObject *self, PyObject *args, PyObject *kwds) +ContextFunctions_read_complete_view_map_pixel(PyObject * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"level", "x", "y", NULL}; int level; @@ -212,7 +212,7 @@ static char ContextFunctions_read_directional_view_map_pixel___doc__[] = " :rtype: float\n"; static PyObject * -ContextFunctions_read_directional_view_map_pixel(PyObject *self, PyObject *args, PyObject *kwds) +ContextFunctions_read_directional_view_map_pixel(PyObject * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"orientation", "level", "x", "y", NULL}; int orientation, level; @@ -232,7 +232,7 @@ static char ContextFunctions_get_selected_fedge___doc__[] = " :rtype: :class:`FEdge`\n"; static PyObject * -ContextFunctions_get_selected_fedge(PyObject *self) +ContextFunctions_get_selected_fedge(PyObject * /*self*/) { FEdge *fe = ContextFunctions::GetSelectedFEdgeCF(); if (fe) diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp index 487a473b7bd..d22632040f4 100644 --- a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp +++ b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp @@ -72,7 +72,7 @@ static char Freestyle_getCurrentScene___doc__[] = " :return: The current scene.\n" " :rtype: :class:`bpy.types.Scene`\n"; -static PyObject *Freestyle_getCurrentScene(PyObject *self) +static PyObject *Freestyle_getCurrentScene(PyObject * /*self*/) { if (!freestyle_scene) { PyErr_SetString(PyExc_TypeError, "current scene not available"); @@ -126,7 +126,7 @@ static char Freestyle_blendRamp___doc__[] = " :return: Blended color in RGB format.\n" " :rtype: :class:`mathutils.Vector`\n"; -static PyObject *Freestyle_blendRamp(PyObject *self, PyObject *args) +static PyObject *Freestyle_blendRamp(PyObject * /*self*/, PyObject *args) { PyObject *obj1, *obj2; char *s; @@ -170,7 +170,7 @@ static char Freestyle_evaluateColorRamp___doc__[] = " :return: color in RGBA format.\n" " :rtype: :class:`mathutils.Vector`\n"; -static PyObject *Freestyle_evaluateColorRamp(PyObject *self, PyObject *args) +static PyObject *Freestyle_evaluateColorRamp(PyObject * /*self*/, PyObject *args) { BPy_StructRNA *py_srna; ColorBand *coba; @@ -207,7 +207,7 @@ static char Freestyle_evaluateCurveMappingF___doc__[] = " :return: Mapped output value.\n" " :rtype: float\n"; -static PyObject *Freestyle_evaluateCurveMappingF(PyObject *self, PyObject *args) +static PyObject *Freestyle_evaluateCurveMappingF(PyObject * /*self*/, PyObject *args) { BPy_StructRNA *py_srna; CurveMapping *cumap; diff --git a/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp index 7a3624f248e..0db25753caa 100644 --- a/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp +++ b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp @@ -63,7 +63,7 @@ PyDoc_STRVAR(Integrator_integrate_doc, " :class:`UnaryFunction0DUnsigned` type.\n" " :rtype: int or float"); -static PyObject * Integrator_integrate(PyObject *self, PyObject *args, PyObject *kwds) +static PyObject * Integrator_integrate(PyObject * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"func", "it", "it_end", "integration_type", NULL}; PyObject *obj1, *obj4 = 0; diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp index 57ec15f4150..a214fc444c7 100644 --- a/source/blender/freestyle/intern/python/BPy_Operators.cpp +++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp @@ -76,7 +76,7 @@ PyDoc_STRVAR(Operators_select_doc, " :arg pred: The predicate expressing this condition.\n" " :type pred: :class:`UnaryPredicate1D`"); -static PyObject *Operators_select(BPy_Operators *self, PyObject *args, PyObject *kwds) +static PyObject *Operators_select(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"pred", NULL}; PyObject *obj = 0; @@ -135,7 +135,7 @@ PyDoc_STRVAR(Operators_chain_doc, " stopping condition.\n" " :type pred: :class:`UnaryPredicate1D`"); -static PyObject *Operators_chain(BPy_Operators *self, PyObject *args, PyObject *kwds) +static PyObject *Operators_chain(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"it", "pred", "modifier", NULL}; PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0; @@ -224,7 +224,7 @@ PyDoc_STRVAR(Operators_bidirectional_chain_doc, " contains the chaining rule.\n" " :type it: :class:`ChainingIterator`"); -static PyObject *Operators_bidirectional_chain(BPy_Operators *self, PyObject *args, PyObject *kwds) +static PyObject *Operators_bidirectional_chain(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"it", "pred", NULL}; PyObject *obj1 = 0, *obj2 = 0; @@ -304,7 +304,7 @@ PyDoc_STRVAR(Operators_sequential_split_doc, " resolution.)\n" " :type sampling: float"); -static PyObject *Operators_sequential_split(BPy_Operators *self, PyObject *args, PyObject *kwds) +static PyObject *Operators_sequential_split(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist_1[] = {"starting_pred", "stopping_pred", "sampling", NULL}; static const char *kwlist_2[] = {"pred", "sampling", NULL}; @@ -411,7 +411,7 @@ PyDoc_STRVAR(Operators_recursive_split_doc, " resolution.)\n" " :type sampling: float"); -static PyObject *Operators_recursive_split(BPy_Operators *self, PyObject *args, PyObject *kwds) +static PyObject *Operators_recursive_split(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist_1[] = {"func", "pred_1d", "sampling", NULL}; static const char *kwlist_2[] = {"func", "pred_0d", "pred_1d", "sampling", NULL}; @@ -486,7 +486,7 @@ PyDoc_STRVAR(Operators_sort_doc, " :arg pred: The binary predicate used for the comparison.\n" " :type pred: :class:`BinaryPredicate1D`"); -static PyObject *Operators_sort(BPy_Operators *self, PyObject *args, PyObject *kwds) +static PyObject *Operators_sort(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"pred", NULL}; PyObject *obj = 0; @@ -517,7 +517,7 @@ PyDoc_STRVAR(Operators_create_doc, " :arg shaders: The list of shaders used to shade the strokes.\n" " :type shaders: list of :class:`StrokeShader` objects"); -static PyObject *Operators_create(BPy_Operators *self, PyObject *args, PyObject *kwds) +static PyObject *Operators_create(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"pred", "shaders", NULL}; PyObject *obj1 = 0, *obj2 = 0; @@ -558,7 +558,7 @@ PyDoc_STRVAR(Operators_reset_doc, " :arg delete_strokes: Delete the strokes that are currently stored.\n" " :type delete_strokes: bool\n"); -static PyObject *Operators_reset(BPy_Operators *self, PyObject *args, PyObject *kwds) +static PyObject *Operators_reset(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"delete_strokes", NULL}; PyObject *obj1 = 0; @@ -583,7 +583,7 @@ PyDoc_STRVAR(Operators_get_viewedge_from_index_doc, " :return: The ViewEdge object.\n" " :rtype: :class:`ViewEdge`"); -static PyObject *Operators_get_viewedge_from_index(BPy_Operators *self, PyObject *args, PyObject *kwds) +static PyObject *Operators_get_viewedge_from_index(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"i", NULL}; unsigned int i; @@ -607,7 +607,7 @@ PyDoc_STRVAR(Operators_get_chain_from_index_doc, " :return: The Chain object.\n" " :rtype: :class:`Chain`"); -static PyObject *Operators_get_chain_from_index(BPy_Operators *self, PyObject *args, PyObject *kwds) +static PyObject *Operators_get_chain_from_index(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"i", NULL}; unsigned int i; @@ -631,7 +631,7 @@ PyDoc_STRVAR(Operators_get_stroke_from_index_doc, " :return: The Stroke object.\n" " :rtype: :class:`Stroke`"); -static PyObject *Operators_get_stroke_from_index(BPy_Operators *self, PyObject *args, PyObject *kwds) +static PyObject *Operators_get_stroke_from_index(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"i", NULL}; unsigned int i; @@ -653,7 +653,7 @@ PyDoc_STRVAR(Operators_get_view_edges_size_doc, " :return: The number of ViewEdges.\n" " :rtype: int"); -static PyObject *Operators_get_view_edges_size(BPy_Operators *self) +static PyObject *Operators_get_view_edges_size(BPy_Operators * /*self*/) { return PyLong_FromLong(Operators::getViewEdgesSize()); } @@ -666,7 +666,7 @@ PyDoc_STRVAR(Operators_get_chains_size_doc, " :return: The number of Chains.\n" " :rtype: int"); -static PyObject *Operators_get_chains_size(BPy_Operators *self) +static PyObject *Operators_get_chains_size(BPy_Operators * /*self*/) { return PyLong_FromLong(Operators::getChainsSize()); } @@ -679,7 +679,7 @@ PyDoc_STRVAR(Operators_get_strokes_size_doc, " :return: The number of Strokes.\n" " :rtype: int"); -static PyObject *Operators_get_strokes_size(BPy_Operators *self) +static PyObject *Operators_get_strokes_size(BPy_Operators * /*self*/) { return PyLong_FromLong(Operators::getStrokesSize()); } diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp index be20febba2b..0941efe9df5 100644 --- a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp +++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp @@ -93,7 +93,7 @@ static void UnaryFunction0D___dealloc__(BPy_UnaryFunction0D *self) Py_TYPE(self)->tp_free((PyObject *)self); } -static PyObject *UnaryFunction0D___repr__(BPy_UnaryFunction0D *self) +static PyObject *UnaryFunction0D___repr__(BPy_UnaryFunction0D * /*self*/) { return PyUnicode_FromString("UnaryFunction0D"); } diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp index b88d609e48d..1b82c7777c7 100644 --- a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp +++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp @@ -87,7 +87,7 @@ static void UnaryFunction1D___dealloc__(BPy_UnaryFunction1D *self) Py_TYPE(self)->tp_free((PyObject *)self); } -static PyObject *UnaryFunction1D___repr__(BPy_UnaryFunction1D *self) +static PyObject *UnaryFunction1D___repr__(BPy_UnaryFunction1D * /*self*/) { return PyUnicode_FromString("UnaryFunction1D"); } diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp index 5e2130ac8e7..f8d0b34d6a9 100644 --- a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp @@ -49,7 +49,7 @@ PyDoc_STRVAR(ViewVertex_doc, "Thus, this class can be specialized into two classes, the\n" ":class:`TVertex` class and the :class:`NonTVertex` class."); -static int ViewVertex_init(BPy_ViewVertex *self, PyObject *args, PyObject *kwds) +static int ViewVertex_init(BPy_ViewVertex * /*self*/, PyObject * /*args*/, PyObject * /*kwds*/) { PyErr_SetString(PyExc_TypeError, "cannot instantiate abstract class"); return -1; @@ -82,7 +82,7 @@ PyDoc_STRVAR(ViewVertex_edges_end_doc, " :return: An orientedViewEdgeIterator pointing after the last ViewEdge.\n" " :rtype: :class:`orientedViewEdgeIterator`"); -static PyObject *ViewVertex_edges_end(BPy_ViewVertex *self) +static PyObject *ViewVertex_edges_end(BPy_ViewVertex * /*self*/) { #if 0 ViewVertexInternal::orientedViewEdgeIterator ove_it(self->vv->edgesEnd()); diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp index ae4fe0764b6..ba773d4f4cf 100644 --- a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp @@ -166,7 +166,7 @@ static int StrokeVertex_mathutils_check(BaseMathObject *bmo) return 0; } -static int StrokeVertex_mathutils_get(BaseMathObject *bmo, int subtype) +static int StrokeVertex_mathutils_get(BaseMathObject *bmo, int /*subtype*/) { BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user; bmo->data[0] = (float)self->sv->x(); @@ -174,7 +174,7 @@ static int StrokeVertex_mathutils_get(BaseMathObject *bmo, int subtype) return 0; } -static int StrokeVertex_mathutils_set(BaseMathObject *bmo, int subtype) +static int StrokeVertex_mathutils_set(BaseMathObject *bmo, int /*subtype*/) { BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user; self->sv->setX((real)bmo->data[0]); @@ -182,7 +182,7 @@ static int StrokeVertex_mathutils_set(BaseMathObject *bmo, int subtype) return 0; } -static int StrokeVertex_mathutils_get_index(BaseMathObject *bmo, int subtype, int index) +static int StrokeVertex_mathutils_get_index(BaseMathObject *bmo, int /*subtype*/, int index) { BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user; switch (index) { @@ -194,7 +194,7 @@ static int StrokeVertex_mathutils_get_index(BaseMathObject *bmo, int subtype, in return 0; } -static int StrokeVertex_mathutils_set_index(BaseMathObject *bmo, int subtype, int index) +static int StrokeVertex_mathutils_set_index(BaseMathObject *bmo, int /*subtype*/, int index) { BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user; switch (index) { diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp index 7592508902b..4c9e0630d40 100644 --- a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp @@ -100,7 +100,7 @@ static int FEdge_init(BPy_FEdge *self, PyObject *args, PyObject *kwds) /*----------------------FEdge sequence protocol ----------------------------*/ -static Py_ssize_t FEdge_sq_length(BPy_FEdge *self) +static Py_ssize_t FEdge_sq_length(BPy_FEdge * /*self*/) { return 2; } diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp index a2079c7d685..cf893ad9481 100644 --- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp @@ -99,7 +99,7 @@ static int FEdgeSmooth_mathutils_check(BaseMathObject *bmo) return 0; } -static int FEdgeSmooth_mathutils_get(BaseMathObject *bmo, int subtype) +static int FEdgeSmooth_mathutils_get(BaseMathObject *bmo, int /*subtype*/) { BPy_FEdgeSmooth *self = (BPy_FEdgeSmooth *)bmo->cb_user; Vec3r p(self->fes->normal()); @@ -109,7 +109,7 @@ static int FEdgeSmooth_mathutils_get(BaseMathObject *bmo, int subtype) return 0; } -static int FEdgeSmooth_mathutils_set(BaseMathObject *bmo, int subtype) +static int FEdgeSmooth_mathutils_set(BaseMathObject *bmo, int /*subtype*/) { BPy_FEdgeSmooth *self = (BPy_FEdgeSmooth *)bmo->cb_user; Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]); @@ -117,7 +117,7 @@ static int FEdgeSmooth_mathutils_set(BaseMathObject *bmo, int subtype) return 0; } -static int FEdgeSmooth_mathutils_get_index(BaseMathObject *bmo, int subtype, int index) +static int FEdgeSmooth_mathutils_get_index(BaseMathObject *bmo, int /*subtype*/, int index) { BPy_FEdgeSmooth *self = (BPy_FEdgeSmooth *)bmo->cb_user; Vec3r p(self->fes->normal()); @@ -125,7 +125,7 @@ static int FEdgeSmooth_mathutils_get_index(BaseMathObject *bmo, int subtype, int return 0; } -static int FEdgeSmooth_mathutils_set_index(BaseMathObject *bmo, int subtype, int index) +static int FEdgeSmooth_mathutils_set_index(BaseMathObject *bmo, int /*subtype*/, int index) { BPy_FEdgeSmooth *self = (BPy_FEdgeSmooth *)bmo->cb_user; Vec3r p(self->fes->normal()); diff --git a/source/blender/freestyle/intern/stroke/Predicates1D.h b/source/blender/freestyle/intern/stroke/Predicates1D.h index 46efeae9f12..05fc043822f 100644 --- a/source/blender/freestyle/intern/stroke/Predicates1D.h +++ b/source/blender/freestyle/intern/stroke/Predicates1D.h @@ -471,7 +471,7 @@ public: } /*! The () operator. */ - int operator()(Interface1D& i1, Interface1D& i2) + int operator()(Interface1D& /*i1*/, Interface1D& /*i2*/) { result = true; return 0; @@ -490,7 +490,7 @@ public: } /*! The () operator. */ - int operator()(Interface1D& i1, Interface1D& i2) + int operator()(Interface1D& /*i1*/, Interface1D& /*i2*/) { result = false; return 0; diff --git a/source/blender/freestyle/intern/stroke/Stroke.cpp b/source/blender/freestyle/intern/stroke/Stroke.cpp index 244b20f6b89..b4a3646edef 100644 --- a/source/blender/freestyle/intern/stroke/Stroke.cpp +++ b/source/blender/freestyle/intern/stroke/Stroke.cpp @@ -752,12 +752,12 @@ Interface0DIterator Stroke::verticesEnd() return ret; } -Interface0DIterator Stroke::pointsBegin(float t) +Interface0DIterator Stroke::pointsBegin(float /*t*/) { return verticesBegin(); // FIXME } -Interface0DIterator Stroke::pointsEnd(float t) +Interface0DIterator Stroke::pointsEnd(float /*t*/) { return verticesEnd(); } diff --git a/source/blender/freestyle/intern/view_map/BoxGrid.cpp b/source/blender/freestyle/intern/view_map/BoxGrid.cpp index f770bf6843f..de60cc3812f 100644 --- a/source/blender/freestyle/intern/view_map/BoxGrid.cpp +++ b/source/blender/freestyle/intern/view_map/BoxGrid.cpp @@ -71,7 +71,7 @@ void BoxGrid::Cell::indexPolygons() // Iterator ////////////////// -BoxGrid::Iterator::Iterator (BoxGrid& grid, Vec3r& center, real epsilon) +BoxGrid::Iterator::Iterator (BoxGrid& grid, Vec3r& center, real /*epsilon*/) : _target(grid.transform(center)), _foundOccludee(false) { // Find target cell @@ -122,7 +122,7 @@ BoxGrid::BoxGrid(OccluderSource& source, GridDensityProvider& density, ViewMap * BoxGrid::~BoxGrid() {} -void BoxGrid::assignCells (OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap) +void BoxGrid::assignCells (OccluderSource& /*source*/, GridDensityProvider& density, ViewMap *viewMap) { _cellSize = density.cellSize(); _cellsX = density.cellsX(); diff --git a/source/blender/freestyle/intern/view_map/Interface1D.cpp b/source/blender/freestyle/intern/view_map/Interface1D.cpp index 985310e52b5..f4abad11479 100644 --- a/source/blender/freestyle/intern/view_map/Interface1D.cpp +++ b/source/blender/freestyle/intern/view_map/Interface1D.cpp @@ -42,13 +42,13 @@ Interface0DIterator Interface1D::verticesEnd() return Interface0DIterator(); } -Interface0DIterator Interface1D::pointsBegin(float t) +Interface0DIterator Interface1D::pointsBegin(float /*t*/) { PyErr_SetString(PyExc_TypeError, "method pointsBegin() not properly overridden"); return Interface0DIterator(); } -Interface0DIterator Interface1D::pointsEnd(float t) +Interface0DIterator Interface1D::pointsEnd(float /*t*/) { PyErr_SetString(PyExc_TypeError, "method pointsEnd() not properly overridden"); return Interface0DIterator(); diff --git a/source/blender/freestyle/intern/view_map/Silhouette.h b/source/blender/freestyle/intern/view_map/Silhouette.h index 94b00157ccd..a80fea0342f 100644 --- a/source/blender/freestyle/intern/view_map/Silhouette.h +++ b/source/blender/freestyle/intern/view_map/Silhouette.h @@ -1122,12 +1122,12 @@ Interface0DIterator FEdge::verticesEnd() return ret; } -Interface0DIterator FEdge::pointsBegin(float t) +Interface0DIterator FEdge::pointsBegin(float /*t*/) { return verticesBegin(); } -Interface0DIterator FEdge::pointsEnd(float t) +Interface0DIterator FEdge::pointsEnd(float /*t*/) { return verticesEnd(); } diff --git a/source/blender/freestyle/intern/view_map/SphericalGrid.cpp b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp index 60ad7daea0a..fedd5767e32 100644 --- a/source/blender/freestyle/intern/view_map/SphericalGrid.cpp +++ b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp @@ -72,7 +72,7 @@ void SphericalGrid::Cell::indexPolygons() // Iterator ////////////////// -SphericalGrid::Iterator::Iterator(SphericalGrid& grid, Vec3r& center, real epsilon) +SphericalGrid::Iterator::Iterator(SphericalGrid& grid, Vec3r& center, real /*epsilon*/) : _target(SphericalGrid::Transform::sphericalProjection(center)), _foundOccludee(false) { // Find target cell @@ -120,7 +120,7 @@ SphericalGrid::SphericalGrid(OccluderSource& source, GridDensityProvider& densit SphericalGrid::~SphericalGrid() {} -void SphericalGrid::assignCells(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap) +void SphericalGrid::assignCells(OccluderSource& /*source*/, GridDensityProvider& density, ViewMap *viewMap) { _cellSize = density.cellSize(); _cellsX = density.cellsX(); diff --git a/source/blender/freestyle/intern/view_map/ViewMap.cpp b/source/blender/freestyle/intern/view_map/ViewMap.cpp index 6bb0082e379..52769413e79 100644 --- a/source/blender/freestyle/intern/view_map/ViewMap.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMap.cpp @@ -701,12 +701,12 @@ Interface0DIterator ViewEdge::verticesEnd() return ret; } -Interface0DIterator ViewEdge::pointsBegin(float t) +Interface0DIterator ViewEdge::pointsBegin(float /*t*/) { return verticesBegin(); } -Interface0DIterator ViewEdge::pointsEnd(float t) +Interface0DIterator ViewEdge::pointsEnd(float /*t*/) { return verticesEnd(); } diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp index 8adc2fa66fd..932c23698dc 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp @@ -56,7 +56,7 @@ static const Global &_global = G; using namespace std; template -static void findOccludee(FEdge *fe, G& grid, I& occluders, real epsilon, WFace **oaWFace, +static void findOccludee(FEdge *fe, G& /*grid*/, I& occluders, real epsilon, WFace **oaWFace, Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector& faceVertices) { WFace *face = NULL; @@ -169,7 +169,7 @@ static void findOccludee(FEdge *fe, G& grid, I& occluders, real epsilon, WFace * } template -static void findOccludee(FEdge *fe, G& grid, real epsilon, ViewEdge *ve, WFace **oaFace) +static void findOccludee(FEdge *fe, G& grid, real epsilon, ViewEdge * /*ve*/, WFace **oaFace) { Vec3r A; Vec3r edge; @@ -205,7 +205,7 @@ static void findOccludee(FEdge *fe, G& grid, real epsilon, ViewEdge *ve, WFace * // computeVisibility takes a pointer to foundOccluders, instead of using a reference, // so that computeVeryFastVisibility can skip the AddOccluders step with minimal overhead. template -static int computeVisibility(ViewMap *viewMap, FEdge *fe, G& grid, real epsilon, ViewEdge *ve, WFace **oaWFace, +static int computeVisibility(ViewMap *viewMap, FEdge *fe, G& grid, real epsilon, ViewEdge * /*ve*/, WFace **oaWFace, set *foundOccluders) { int qi = 0; diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.h b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h index 08b2fde8f31..36497bf8d22 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.h +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h @@ -145,7 +145,7 @@ public: * The viewport. 4 real array: origin.x, origin.y, width, length */ inline void setTransform(const real iModelViewMatrix[4][4], const real iProjectionMatrix[4][4], - const int iViewport[4], real iFocalLength, real iAspect, real iFovy) + const int iViewport[4], real iFocalLength, real /*iAspect*/, real /*iFovy*/) { _orthographicProjection = (iProjectionMatrix[3][3] != 0.0); SilhouetteGeomEngine::setTransform(iModelViewMatrix, iProjectionMatrix, iViewport, iFocalLength); diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp index c9f2f3badab..df990a3468f 100644 --- a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp +++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp @@ -221,7 +221,7 @@ void WingedEdgeBuilder::buildWVertices(WShape& shape, const real *vertices, unsi } } -void WingedEdgeBuilder::buildTriangleStrip(const real *vertices, const real *normals, vector& iMaterials, +void WingedEdgeBuilder::buildTriangleStrip(const real * /*vertices*/, const real *normals, vector& /*iMaterials*/, const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, const unsigned *tindices, const unsigned nvertices) @@ -296,15 +296,15 @@ void WingedEdgeBuilder::buildTriangleStrip(const real *vertices, const real *nor } } -void WingedEdgeBuilder::buildTriangleFan(const real *vertices, const real *normals, vector& iMaterials, - const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, - const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, - const unsigned *tindices, const unsigned nvertices) +void WingedEdgeBuilder::buildTriangleFan(const real * /*vertices*/, const real * /*normals*/, vector& /*iMaterials*/, + const real * /*texCoords*/, const IndexedFaceSet::FaceEdgeMark * /*iFaceEdgeMarks*/, + const unsigned * /*vindices*/, const unsigned * /*nindices*/, const unsigned * /*mindices*/, + const unsigned * /*tindices*/, const unsigned /*nvertices*/) { // Nothing to be done } -void WingedEdgeBuilder::buildTriangles(const real *vertices, const real *normals, vector& iMaterials, +void WingedEdgeBuilder::buildTriangles(const real * /*vertices*/, const real *normals, vector& /*iMaterials*/, const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, const unsigned *tindices, const unsigned nvertices) -- cgit v1.2.3 From 4393b605795e3df89addd82e2492b0bdf166d707 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 15:51:21 +0500 Subject: ImBuf: Code cleanup, prepare for strict C++ flags --- source/blender/imbuf/intern/dds/dds_api.cpp | 2 +- source/blender/imbuf/intern/oiio/openimageio_api.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index a6d53ffac96..45d9fa2ac59 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -47,7 +47,7 @@ extern "C" { #include "IMB_colormanagement.h" #include "IMB_colormanagement_intern.h" -int imb_save_dds(struct ImBuf *ibuf, const char *name, int flags) +int imb_save_dds(struct ImBuf *ibuf, const char *name, int /*flags*/) { return(0); /* todo: finish this function */ diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp index 6e3f97a4902..7728183d3b6 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp +++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp @@ -182,7 +182,7 @@ int imb_is_a_photoshop(const char *filename) return BLI_testextensie_array(filename, photoshop_extension); } -int imb_save_photoshop(struct ImBuf *ibuf, const char *name, int flags) +int imb_save_photoshop(struct ImBuf *ibuf, const char * /*name*/, int flags) { if (flags & IB_mem) { std::cerr << __func__ << ": Photoshop PSD-save: Create PSD in memory" -- cgit v1.2.3 From 052ebd65645d9ecb30293881986b55a66b31bfe4 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 15:53:10 +0500 Subject: C++ RNA API: Code cleanup, prepare for strict C++ flags --- source/blender/makesrna/intern/makesrna.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 5f8639358b7..adeee302463 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -3763,7 +3763,7 @@ static const char *cpp_classes = "" "\n" "class DefaultCollectionFunctions {\n" "public:\n" -" DefaultCollectionFunctions(const PointerRNA &p) {}\n" +" DefaultCollectionFunctions(const PointerRNA & /*p*/) {}\n" "};\n" "\n" "\n"; -- cgit v1.2.3 From 061e73a27054dce12463f17ea565f4271be63c43 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 15:53:56 +0500 Subject: Physics: Code cleanup, prepare for strict C++ flags --- source/blender/physics/intern/hair_volume.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/physics/intern/hair_volume.cpp b/source/blender/physics/intern/hair_volume.cpp index b07af1d201c..d79cf7d8c31 100644 --- a/source/blender/physics/intern/hair_volume.cpp +++ b/source/blender/physics/intern/hair_volume.cpp @@ -594,7 +594,7 @@ BLI_INLINE float hair_volume_density_divergence(float density, float target_dens return 0.0f; } -bool BPH_hair_volume_solve_divergence(HairGrid *grid, float dt, float target_density, float target_strength) +bool BPH_hair_volume_solve_divergence(HairGrid *grid, float /*dt*/, float target_density, float target_strength) { const float flowfac = grid->cellsize; const float inv_flowfac = 1.0f / grid->cellsize; -- cgit v1.2.3 From 6cd82dbf57244a754c30039192d5dceaeead0bd7 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 15:55:58 +0500 Subject: CMake: Enable strict flags for C++ --- CMakeLists.txt | 9 +++++++++ build_files/cmake/macros.cmake | 14 ++++++++++++++ intern/audaspace/CMakeLists.txt | 2 ++ intern/cycles/kernel/CMakeLists.txt | 2 ++ source/blender/ikplugin/CMakeLists.txt | 2 ++ source/gameengine/CMakeLists.txt | 2 ++ 6 files changed, 31 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ce183e220f..68f248ab818 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2550,6 +2550,15 @@ if(CMAKE_COMPILER_IS_GNUCC) ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_MISSING_INCLUDE_DIRS -Wmissing-include-dirs) ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero) ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_TYPE_LIMITS -Wtype-limits) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ERROR_RETURN_TYPE -Werror=return-type) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ERROR_DECLARATION_AFTER_STATEMENT -Werror=declaration-after-statement) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ERROR_IMPLICIT_FUNCTION_DECLARATION -Werror=implicit-function-declaration) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_POINTER_ARITH -Wpointer-arith) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNUSED_PARAMETER -Wunused-parameter) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_WRITE_STRINGS -Wwrite-strings) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNDEF -Wundef) # gcc 4.2 gives annoying warnings on every file with this if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3") diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index b266602fa63..e23d2c6a07c 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -961,6 +961,20 @@ macro(remove_strict_flags) endmacro() +macro(remove_extra_strict_flags) + if(CMAKE_COMPILER_IS_GNUCC) + remove_cc_flag("-Wunused-parameter") + endif() + + if(CMAKE_C_COMPILER_ID MATCHES "Clang") + remove_cc_flag("-Wunused-parameter") + endif() + + if(MSVC) + # TODO + endif() +endmacro() + # note, we can only append flags on a single file so we need to negate the options. # at the moment we cant shut up ffmpeg deprecations, so use this, but will # probably add more removals here. diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt index 21a42553935..5b810493663 100644 --- a/intern/audaspace/CMakeLists.txt +++ b/intern/audaspace/CMakeLists.txt @@ -19,6 +19,8 @@ # # ***** END LGPL LICENSE BLOCK ***** +remove_extra_strict_flags() + set(INC . FX diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 1e3eb6bca54..fd690234bc1 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -1,3 +1,5 @@ +remove_extra_strict_flags() + set(INC . ../util diff --git a/source/blender/ikplugin/CMakeLists.txt b/source/blender/ikplugin/CMakeLists.txt index 139dbd32349..8991e113410 100644 --- a/source/blender/ikplugin/CMakeLists.txt +++ b/source/blender/ikplugin/CMakeLists.txt @@ -23,6 +23,8 @@ # # ***** END GPL LICENSE BLOCK ***** +remove_extra_strict_flags() + set(INC . ../blenkernel diff --git a/source/gameengine/CMakeLists.txt b/source/gameengine/CMakeLists.txt index cf7895e98ea..62523175f46 100644 --- a/source/gameengine/CMakeLists.txt +++ b/source/gameengine/CMakeLists.txt @@ -23,6 +23,8 @@ # # ***** END GPL LICENSE BLOCK ***** +remove_extra_strict_flags() + # there are too many inter-includes so best define here if(WITH_PYTHON) blender_include_dirs_sys("${PYTHON_INCLUDE_DIRS}") -- cgit v1.2.3 From 3366b30bf1fbd8a70cb3413186db747a494e130b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 16:47:11 +0500 Subject: Compositor: Code cleanup, debug mode is now fine with strict flags --- source/blender/compositor/intern/COM_Debug.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/compositor/intern/COM_Debug.cpp b/source/blender/compositor/intern/COM_Debug.cpp index 3b3ab5082c5..a7b464cde29 100644 --- a/source/blender/compositor/intern/COM_Debug.cpp +++ b/source/blender/compositor/intern/COM_Debug.cpp @@ -213,7 +213,7 @@ int DebugInfo::graphviz_legend_color(const char *name, const char *color, char * return len; } -int DebugInfo::graphviz_legend_line(const char *name, const char *color, const char *style, char *str, int maxlen) +int DebugInfo::graphviz_legend_line(const char * /*name*/, const char * /*color*/, const char * /*style*/, char *str, int maxlen) { /* XXX TODO */ int len = 0; @@ -221,7 +221,7 @@ int DebugInfo::graphviz_legend_line(const char *name, const char *color, const c return len; } -int DebugInfo::graphviz_legend_group(const char *name, const char *color, const char *style, char *str, int maxlen) +int DebugInfo::graphviz_legend_group(const char *name, const char *color, const char * /*style*/, char *str, int maxlen) { int len = 0; len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "%s
\r\n", name, color); -- cgit v1.2.3 From 8af5390968a1c6971ba2e8b4f7621d4b8344fce8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 17:25:12 +0500 Subject: Fix T44149: Compositing : Node Groups do not work correctly Input constants are to be connected before removing proxies, otherwise node groups might give totally different result. This is a regression and to be put into final release. --- source/blender/compositor/intern/COM_NodeOperationBuilder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp index aed60f5fca8..e899b7b14fd 100644 --- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp +++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp @@ -101,12 +101,12 @@ void NodeOperationBuilder::convertToOperations(ExecutionSystem *system) } } + add_operation_input_constants(); + resolve_proxies(); add_datatype_conversions(); - add_operation_input_constants(); - determineResolutions(); /* surround complex ops with read/write buffer */ -- cgit v1.2.3 From da170d9dc3dd84f1b77f737a94d5863b0d67dd21 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 17:38:10 +0500 Subject: Compositor: Fix heap overflow when copying previews --- source/blender/blenkernel/intern/node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index c7010e42aac..ac79e13ac83 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1418,7 +1418,7 @@ static void node_preview_sync(bNodePreview *to, bNodePreview *from) if (to->rect && from->rect) { int xsize = to->xsize; int ysize = to->ysize; - memcpy(to->rect, from->rect, 4 * xsize + xsize * ysize * sizeof(char) * 4); + memcpy(to->rect, from->rect, xsize * ysize * sizeof(char) * 4); } } -- cgit v1.2.3 From d84cc6a18fb5d1e9248fb08cd288dc62d4bdcd14 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 18:21:39 +0500 Subject: Compositor: Followup to previous stats commit No need to mark tree for localization, it was never done and it all just worked. We can save some CPU ticks by skipping doing this. --- source/blender/editors/space_node/node_edit.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index f79d6e26f22..6547aa97bd2 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -162,13 +162,12 @@ static int compo_breakjob(void *cjv) ); } -/* called by compo, wmJob sends notifier, old compositor system only */ +/* called by compo, wmJob sends notifier */ static void compo_statsdrawjob(void *cjv, char *UNUSED(str)) { CompoJob *cj = cjv; *(cj->do_update) = true; - cj->need_sync = true; } /* called by compo, wmJob sends notifier */ -- cgit v1.2.3 From 1c2f1ff7251ba563e98b617aa6417c832cb7159a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 18:23:11 +0500 Subject: Compositor: Cleanup, remove unused need_sync parameter --- source/blender/editors/space_node/node_edit.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 6547aa97bd2..b8b8d5f53b8 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -93,7 +93,6 @@ typedef struct CompoJob { const short *stop; short *do_update; float *progress; - short need_sync; int recalc_flags; } CompoJob; @@ -201,17 +200,8 @@ static void compo_initjob(void *cjv) } /* called before redraw notifiers, it moves finished previews over */ -static void compo_updatejob(void *cjv) +static void compo_updatejob(void *UNUSED(cjv)) { - CompoJob *cj = cjv; - - if (cj->need_sync) { - /* was used by old compositor system only */ - ntreeLocalSync(cj->localtree, cj->ntree); - - cj->need_sync = false; - } - WM_main_add_notifier(NC_SCENE | ND_COMPO_RESULT, NULL); } -- cgit v1.2.3 From 74e8e14cced7698748c5e4018347438748c499ab Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 18:44:11 +0500 Subject: Makesrna: Fix function prototypes for struct used RNA_def_struct_sdna_from Previously makesrna would have generated code expecting DNA structure from RNA_def_struct_sdna_from() to be passed to it. This was wrong because actual PointerRNA points to a "parent" structure, making it impossible to add functions to certain RNA structures. It so far never needed and we didn't notice this issue, but it's needed for some ongoing development now. --- source/blender/makesrna/intern/makesrna.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index adeee302463..829a70ef166 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -2027,7 +2027,8 @@ static void rna_def_struct_function_call_impl_cpp(FILE *f, StructRNA *srna, Func if ((func->flag & FUNC_NO_SELF) == 0) { WRITE_COMMA; - if (dsrna->dnaname) fprintf(f, "(::%s *) this->ptr.data", dsrna->dnaname); + if (dsrna->dnafromprop) fprintf(f, "(::%s *) this->ptr.data", dsrna->dnafromname); + else if (dsrna->dnaname) fprintf(f, "(::%s *) this->ptr.data", dsrna->dnaname); else fprintf(f, "(::%s *) this->ptr.data", srna->identifier); } else if (func->flag & FUNC_USE_SELF_TYPE) { @@ -2222,7 +2223,8 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA } if ((func->flag & FUNC_NO_SELF) == 0) { - if (dsrna->dnaname) fprintf(f, "\tstruct %s *_self;\n", dsrna->dnaname); + if (dsrna->dnafromprop) fprintf(f, "\tstruct %s *_self;\n", dsrna->dnafromname); + else if (dsrna->dnaname) fprintf(f, "\tstruct %s *_self;\n", dsrna->dnaname); else fprintf(f, "\tstruct %s *_self;\n", srna->identifier); } else if (func->flag & FUNC_USE_SELF_TYPE) { @@ -2274,7 +2276,8 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA } if ((func->flag & FUNC_NO_SELF) == 0) { - if (dsrna->dnaname) fprintf(f, "\t_self = (struct %s *)_ptr->data;\n", dsrna->dnaname); + if (dsrna->dnafromprop) fprintf(f, "\t_self = (struct %s *)_ptr->data;\n", dsrna->dnafromname); + else if (dsrna->dnaname) fprintf(f, "\t_self = (struct %s *)_ptr->data;\n", dsrna->dnaname); else fprintf(f, "\t_self = (struct %s *)_ptr->data;\n", srna->identifier); } else if (func->flag & FUNC_USE_SELF_TYPE) { @@ -2675,7 +2678,8 @@ static void rna_generate_static_parameter_prototypes(FILE *f, StructRNA *srna, F if ((func->flag & FUNC_NO_SELF) == 0) { if (!first) fprintf(f, ", "); - if (dsrna->dnaname) fprintf(f, "struct %s *_self", dsrna->dnaname); + if (dsrna->dnafromprop) fprintf(f, "struct %s *_self", dsrna->dnafromname); + else if (dsrna->dnaname) fprintf(f, "struct %s *_self", dsrna->dnaname); else fprintf(f, "struct %s *_self", srna->identifier); first = 0; } -- cgit v1.2.3 From 7b7eac921102414f1a9afbb04c79a3386b5cd805 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 27 Mar 2015 15:00:01 +0100 Subject: Add profiling prints for audio synch to detect how continuous our frame progression is --- source/blender/editors/screen/screen_ops.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 686f601a839..a192a501177 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -3413,10 +3413,17 @@ static int match_region_with_redraws(int spacetype, int regiontype, int redraws) return 0; } +//#define PROFILE_AUDIO_SYNCH + static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { bScreen *screen = CTX_wm_screen(C); +#ifdef PROFILE_AUDIO_SYNCH + static int old_frame = 0; + int newfra_int; +#endif + if (screen->animtimer && screen->animtimer == event->customdata) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -3438,11 +3445,24 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv finite(time = BKE_sound_sync_scene(scene))) { double newfra = (double)time * FPS; + /* give some space here to avoid jumps */ if (newfra + 0.5 > scene->r.cfra && newfra - 0.5 < scene->r.cfra) scene->r.cfra++; else scene->r.cfra = newfra + 0.5; + +#ifdef PROFILE_AUDIO_SYNCH + newfra_int = scene->r.cfra; + if (newfra_int < old_frame) { + printf("back jump detected, frame %d!\n", newfra_int); + } + else if (newfra_int > old_frame + 1) { + printf("forward jump detected, frame %d!\n", newfra_int); + } + fflush(stdout); + old_frame = newfra_int; +#endif } else { if (sync) { -- cgit v1.2.3 From 7cbb659400a647d6450470b054ac77518fd40c6a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 27 Mar 2015 22:43:19 +1100 Subject: Use squared dist /w comparisons (mask, edge-slide) --- source/blender/editors/mask/mask_add.c | 14 +++++++------- source/blender/editors/transform/transform.c | 18 +++++++++--------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index cb47adbe73e..2dae9561d4e 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -72,7 +72,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, MaskLayer *masklay, *point_masklay; MaskSpline *point_spline; MaskSplinePoint *point = NULL; - float dist = FLT_MAX, co[2]; + float dist_best_sq = FLT_MAX, co[2]; int width, height; float u; float scalex, scaley; @@ -123,7 +123,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, } for (j = 0; j < tot_point - 1; j++) { - float cur_dist, a[2], b[2]; + float dist_sq, a[2], b[2]; a[0] = points[2 * j] * scalex; a[1] = points[2 * j + 1] * scaley; @@ -131,16 +131,16 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, b[0] = points[2 * j + 2] * scalex; b[1] = points[2 * j + 3] * scaley; - cur_dist = dist_to_line_segment_v2(co, a, b); + dist_sq = dist_squared_to_line_segment_v2(co, a, b); - if (cur_dist < dist) { + if (dist_sq < dist_best_sq) { if (tangent) sub_v2_v2v2(tangent, &diff_points[2 * j + 2], &diff_points[2 * j]); point_masklay = masklay; point_spline = spline; point = use_deform ? &spline->points[(cur_point - spline->points_deform)] : cur_point; - dist = cur_dist; + dist_best_sq = dist_sq; u = (float)j / tot_point; } } @@ -154,7 +154,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, } } - if (point && dist < threshold) { + if (point && dist_best_sq < threshold) { if (masklay_r) *masklay_r = point_masklay; @@ -174,7 +174,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, } if (score_r) { - *score_r = dist; + *score_r = dist_best_sq; } return true; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index f4cb8f724bb..8b2bc3bee4d 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -5668,7 +5668,7 @@ static bool createEdgeSlideVerts(TransInfo *t) float projectMat[4][4]; float mval[2] = {(float)t->mval[0], (float)t->mval[1]}; float mval_start[2], mval_end[2]; - float mval_dir[3], maxdist, (*loop_dir)[3], *loop_maxdist; + float mval_dir[3], dist_best_sq, (*loop_dir)[3], *loop_maxdist; int numsel, i, j, loop_nr, l_nr; int use_btree_disp; @@ -5995,7 +5995,7 @@ static bool createEdgeSlideVerts(TransInfo *t) /* find mouse vectors, the global one, and one per loop in case we have * multiple loops selected, in case they are oriented different */ zero_v3(mval_dir); - maxdist = -1.0f; + dist_best_sq = -1.0f; loop_dir = MEM_callocN(sizeof(float) * 3 * loop_nr, "sv loop_dir"); loop_maxdist = MEM_mallocN(sizeof(float) * loop_nr, "sv loop_maxdist"); @@ -6005,7 +6005,7 @@ static bool createEdgeSlideVerts(TransInfo *t) if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { BMIter iter2; BMEdge *e2; - float d; + float dist_sq; /* search cross edges for visible edge to the mouse cursor, * then use the shared vertex to calculate screen vector*/ @@ -6043,19 +6043,19 @@ static bool createEdgeSlideVerts(TransInfo *t) } /* global direction */ - d = dist_to_line_segment_v2(mval, sco_b, sco_a); - if ((maxdist == -1.0f) || + dist_sq = dist_squared_to_line_segment_v2(mval, sco_b, sco_a); + if ((dist_best_sq == -1.0f) || /* intentionally use 2d size on 3d vector */ - (d < maxdist && (len_squared_v2v2(sco_b, sco_a) > 0.1f))) + (dist_sq < dist_best_sq && (len_squared_v2v2(sco_b, sco_a) > 0.1f))) { - maxdist = d; + dist_best_sq = dist_sq; sub_v3_v3v3(mval_dir, sco_b, sco_a); } /* per loop direction */ l_nr = sv_array[j].loop_nr; - if (loop_maxdist[l_nr] == -1.0f || d < loop_maxdist[l_nr]) { - loop_maxdist[l_nr] = d; + if (loop_maxdist[l_nr] == -1.0f || dist_sq < loop_maxdist[l_nr]) { + loop_maxdist[l_nr] = dist_sq; sub_v3_v3v3(loop_dir[l_nr], sco_b, sco_a); } } -- cgit v1.2.3 From 267904dd3cf10a6618ab6d79c49ac99aceb268b0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 28 Mar 2015 00:59:14 +1100 Subject: Cleanup: gpencil headers --- source/blender/editors/gpencil/drawgpencil.c | 2 -- source/blender/editors/gpencil/gpencil_ops.c | 2 -- source/blender/editors/gpencil/gpencil_select.c | 13 ------------- source/blender/editors/gpencil/gpencil_utils.c | 16 ---------------- 4 files changed, 33 deletions(-) diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 55224b87c59..c2072d30310 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -61,8 +61,6 @@ #include "UI_resources.h" -#include "gpencil_intern.h" - /* ************************************************** */ /* GREASE PENCIL DRAWING */ diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index 3fae208a2e2..5970a9497a0 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -34,8 +34,6 @@ #include "BLI_sys_types.h" -#include "BLI_blenlib.h" - #include "BKE_context.h" #include "DNA_gpencil_types.h" diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 9ba77a4244e..98bce3030a5 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -35,28 +35,17 @@ #include "MEM_guardedalloc.h" -#include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_lasso.h" #include "BLI_utildefines.h" #include "DNA_gpencil_types.h" -#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" -#include "DNA_space_types.h" -#include "DNA_view3d_types.h" #include "BKE_context.h" -#include "BKE_curve.h" -#include "BKE_depsgraph.h" -#include "BKE_global.h" #include "BKE_gpencil.h" -#include "BKE_library.h" -#include "BKE_object.h" #include "BKE_report.h" -#include "BKE_scene.h" -#include "BKE_screen.h" #include "UI_interface.h" @@ -69,8 +58,6 @@ #include "UI_view2d.h" #include "ED_gpencil.h" -#include "ED_view3d.h" -#include "ED_keyframing.h" #include "gpencil_intern.h" diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 289cbc568d2..425983397e0 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -32,35 +32,19 @@ #include #include -#include "MEM_guardedalloc.h" - #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "DNA_gpencil_types.h" -#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_view3d_types.h" #include "BKE_context.h" -#include "BKE_global.h" -#include "BKE_gpencil.h" -#include "BKE_library.h" -#include "BKE_object.h" -#include "BKE_report.h" -#include "BKE_scene.h" -#include "BKE_screen.h" - -#include "UI_interface.h" #include "WM_api.h" -#include "WM_types.h" - -#include "RNA_access.h" -#include "RNA_define.h" #include "UI_view2d.h" -- cgit v1.2.3 From d18e8ad1f369eae933f87cbe698391e1855d8b65 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 28 Mar 2015 01:05:24 +1100 Subject: Cleanup: view3d headers --- source/blender/editors/space_view3d/drawanimviz.c | 1 - source/blender/editors/space_view3d/drawsimdebug.c | 7 ------- source/blender/editors/space_view3d/drawvolume.c | 2 -- source/blender/editors/space_view3d/view3d_buttons.c | 1 - source/blender/editors/space_view3d/view3d_edit.c | 3 --- source/blender/editors/space_view3d/view3d_snap.c | 5 ----- 6 files changed, 19 deletions(-) diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c index d8b18140cde..d753ad68fcc 100644 --- a/source/blender/editors/space_view3d/drawanimviz.c +++ b/source/blender/editors/space_view3d/drawanimviz.c @@ -51,7 +51,6 @@ #include "BIF_gl.h" -#include "ED_armature.h" #include "ED_keyframes_draw.h" diff --git a/source/blender/editors/space_view3d/drawsimdebug.c b/source/blender/editors/space_view3d/drawsimdebug.c index 6113bfd4143..46320ba6763 100644 --- a/source/blender/editors/space_view3d/drawsimdebug.c +++ b/source/blender/editors/space_view3d/drawsimdebug.c @@ -29,28 +29,21 @@ * \ingroup spview3d */ -#include "MEM_guardedalloc.h" - #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_view3d_types.h" #include "DNA_object_types.h" -#include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_ghash.h" #include "BKE_effect.h" -#include "BKE_global.h" -#include "BKE_modifier.h" #include "view3d_intern.h" #include "BIF_gl.h" -#include "BIF_glutil.h" -#include "UI_resources.h" static void draw_sim_debug_elements(SimDebugData *debug_data, float imat[4][4]) { diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index a220e1e39b0..92883f28836 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -48,8 +48,6 @@ #include "GPU_extensions.h" -#include "ED_mesh.h" - #include "view3d_intern.h" // own include struct GPUTexture; diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 88f43ab340f..87fe29325bc 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -68,7 +68,6 @@ #include "RNA_access.h" #include "ED_armature.h" -#include "ED_gpencil.h" #include "ED_mesh.h" #include "ED_screen.h" diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index ddb96f9aefc..671fc682409 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -28,7 +28,6 @@ * \ingroup spview3d */ - #include #include #include @@ -38,7 +37,6 @@ #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "DNA_camera_types.h" #include "MEM_guardedalloc.h" @@ -75,7 +73,6 @@ #include "ED_transform.h" #include "ED_mesh.h" #include "ED_view3d.h" -#include "ED_sculpt.h" #include "UI_resources.h" diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 0608c35129d..8bb84d00c83 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -31,9 +31,7 @@ #include "DNA_armature_types.h" -#include "DNA_curve_types.h" #include "DNA_object_types.h" -#include "DNA_meta_types.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" @@ -43,11 +41,9 @@ #include "BKE_armature.h" #include "BKE_context.h" #include "BKE_depsgraph.h" -#include "BKE_lattice.h" #include "BKE_main.h" #include "BKE_mball.h" #include "BKE_object.h" -#include "BKE_editmesh.h" #include "BKE_tracking.h" #include "WM_api.h" @@ -60,7 +56,6 @@ #include "ED_transverts.h" #include "ED_keyframing.h" #include "ED_screen.h" -#include "ED_curve.h" #include "view3d_intern.h" -- cgit v1.2.3 From 3d305b5a37e8d9a8b986d13cb210dce547fcc020 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Mar 2015 19:09:41 +0500 Subject: Cycles: Code cleanup, make strict flags happy about disabled OSL --- intern/cycles/blender/blender_shader.cpp | 3 +++ intern/cycles/render/mesh.cpp | 4 ++++ intern/cycles/render/osl.cpp | 36 ++++++++++++++++---------------- intern/cycles/render/shader.cpp | 2 ++ 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 32a4117e908..7a656360bd3 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -543,6 +543,9 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen node = script_node; } +#else + (void)b_data; + (void)b_ntree; #endif } else if (b_node.is_a(&RNA_ShaderNodeTexImage)) { diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 4ec5312e9a3..c220a126f1a 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -653,6 +653,10 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector Date: Sat, 28 Mar 2015 02:36:00 +1100 Subject: Cleanup: use const char for stats arg --- source/blender/compositor/intern/COM_ExecutionSystem.cpp | 2 +- source/blender/editors/space_node/node_edit.c | 2 +- source/blender/makesdna/DNA_node_types.h | 2 +- source/blender/render/intern/source/pipeline.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index 1f8b7654786..0466fbedb0a 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -76,7 +76,7 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, Scene *scene, bNodeTree *editin viewer_border->xmin < viewer_border->xmax && viewer_border->ymin < viewer_border->ymax; - editingtree->stats_draw(editingtree->sdh, (char*)"Compositing | Determining resolution"); + editingtree->stats_draw(editingtree->sdh, "Compositing | Determining resolution"); for (index = 0; index < this->m_groups.size(); index++) { resolution[0] = 0; diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index b8b8d5f53b8..27af4e7490b 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -162,7 +162,7 @@ static int compo_breakjob(void *cjv) } /* called by compo, wmJob sends notifier */ -static void compo_statsdrawjob(void *cjv, char *UNUSED(str)) +static void compo_statsdrawjob(void *cjv, const char *UNUSED(str)) { CompoJob *cj = cjv; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index f08b3ea9590..de1c9237a50 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -383,7 +383,7 @@ typedef struct bNodeTree { /* callbacks */ void (*progress)(void *, float progress); - void (*stats_draw)(void *, char *str); + void (*stats_draw)(void *, const char *str); int (*test_break)(void *); void (*update_draw)(void *); void *tbh, *prh, *sdh, *udh; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index fe51696b16c..b18edd4c61e 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1956,7 +1956,7 @@ static void ntree_render_scenes(Render *re) } /* bad call... need to think over proper method still */ -static void render_composit_stats(void *UNUSED(arg), char *str) +static void render_composit_stats(void *UNUSED(arg), const char *str) { R.i.infostr = str; R.stats_draw(R.sdh, &R.i); -- cgit v1.2.3 From 6f43e1dfef3e5632976529a6f678292b15bd5a0c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 28 Mar 2015 03:32:56 +1100 Subject: Cleanup: win32 mixed declare/statements in main() Make it a more clear where declarations end (ifdef's all over made it a bit confusing). --- source/creator/creator.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/source/creator/creator.c b/source/creator/creator.c index b2b650419d6..5b4f828842e 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1559,13 +1559,13 @@ char **environ = NULL; * or exit when running in background mode. */ int main( - int argc, + int argc, #ifdef WIN32 const char **UNUSED(argv_c) #else const char **argv #endif - ) + ) { bContext *C; SYS_SystemHandle syshandle; @@ -1574,6 +1574,14 @@ int main( bArgs *ba; #endif +#ifdef WIN32 + char **argv; + int argv_num; +#endif + + /* --- end declarations --- */ + + #ifdef WIN32 /* FMA3 support in the 2013 CRT is broken on Vista and Windows 7 RTM (fixed in SP1). Just disable it. */ # if defined(_MSC_VER) && _MSC_VER >= 1800 && defined(_M_X64) @@ -1584,16 +1592,15 @@ int main( /* NOTE: cannot use guardedalloc malloc here, as it's not yet initialized * (it depends on the args passed in, which is what we're getting here!) */ - wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc); - char **argv = malloc(argc * sizeof(char *)); - int argci = 0; - - for (argci = 0; argci < argc; argci++) { - argv[argci] = alloc_utf_8_from_16(argv_16[argci], 0); + { + wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc); + argv = malloc(argc * sizeof(char *)); + for (argv_num = 0; argv_num < argc; argv_num++) { + argv[argv_num] = alloc_utf_8_from_16(argv_16[argv_num], 0); + } + LocalFree(argv_16); } - - LocalFree(argv_16); -#endif +#endif /* WIN32 */ /* NOTE: Special exception for guarded allocator type switch: * we need to perform switch from lock-free to fully @@ -1661,7 +1668,7 @@ int main( setCallbacks(); #if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE) -/* patch to ignore argument finder gives us (pid?) */ + /* patch to ignore argument finder gives us (pid?) */ if (argc == 2 && STREQLEN(argv[1], "-psn_", 5)) { extern int GHOST_HACK_getFirstFile(char buf[]); static char firstfilebuf[512]; @@ -1819,8 +1826,8 @@ int main( #endif #ifdef WIN32 - while (argci) { - free(argv[--argci]); + while (argv_num) { + free(argv[--argv_num]); } free(argv); argv = NULL; -- cgit v1.2.3 From 5ff132182dbb089111cba3a80fa3a8eeb6009ec3 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 28 Mar 2015 00:15:15 +0500 Subject: Cycles: Code cleanup, spaces around keywords This inconsistency drove me totally crazy, it's really confusing when it's inconsistent especially when you work on both Cycles and Blender sides. Shouldn;t cause merge PITA, it's whitespace changes only, Git should be able to merge it nicely. --- intern/cycles/app/cycles_server.cpp | 2 +- intern/cycles/app/cycles_standalone.cpp | 4 +- intern/cycles/app/cycles_xml.cpp | 28 +-- intern/cycles/blender/blender_camera.cpp | 2 +- intern/cycles/blender/blender_curves.cpp | 16 +- intern/cycles/blender/blender_mesh.cpp | 2 +- intern/cycles/blender/blender_object.cpp | 2 +- intern/cycles/blender/blender_particles.cpp | 2 +- intern/cycles/blender/blender_python.cpp | 6 +- intern/cycles/blender/blender_session.cpp | 12 +- intern/cycles/blender/blender_shader.cpp | 210 ++++++++++----------- intern/cycles/blender/blender_sync.cpp | 2 +- intern/cycles/blender/blender_util.h | 8 +- intern/cycles/bvh/bvh.cpp | 8 +- intern/cycles/bvh/bvh_build.cpp | 4 +- intern/cycles/bvh/bvh_split.cpp | 2 +- intern/cycles/device/device_cpu.cpp | 4 +- intern/cycles/device/device_cuda.cpp | 10 +- intern/cycles/device/device_network.cpp | 2 +- intern/cycles/device/device_opencl.cpp | 6 +- intern/cycles/device/device_task.cpp | 2 +- intern/cycles/kernel/closure/bssrdf.h | 2 +- intern/cycles/kernel/geom/geom_curve.h | 34 ++-- intern/cycles/kernel/geom/geom_primitive.h | 2 +- .../cycles/kernel/geom/geom_triangle_intersect.h | 8 +- intern/cycles/kernel/kernel.cpp | 4 +- intern/cycles/kernel/kernel_bake.h | 4 +- intern/cycles/kernel/kernel_jitter.h | 2 +- intern/cycles/kernel/kernel_volume.h | 2 +- intern/cycles/kernel/osl/osl_services.cpp | 146 +++++++------- intern/cycles/kernel/osl/osl_shader.cpp | 42 ++--- intern/cycles/kernel/svm/svm_blackbody.h | 8 +- intern/cycles/kernel/svm/svm_brightness.h | 2 +- intern/cycles/kernel/svm/svm_camera.h | 6 +- intern/cycles/kernel/svm/svm_closure.h | 6 +- intern/cycles/kernel/svm/svm_gamma.h | 8 +- intern/cycles/kernel/svm/svm_hsv.h | 2 +- intern/cycles/kernel/svm/svm_image.h | 2 +- intern/cycles/kernel/svm/svm_invert.h | 2 +- intern/cycles/kernel/svm/svm_normal.h | 4 +- intern/cycles/kernel/svm/svm_sepcomb_hsv.h | 8 +- intern/cycles/kernel/svm/svm_sepcomb_vector.h | 8 +- intern/cycles/kernel/svm/svm_texture.h | 24 +-- intern/cycles/kernel/svm/svm_vector_transform.h | 4 +- intern/cycles/kernel/svm/svm_wavelength.h | 2 +- intern/cycles/kernel/svm/svm_wireframe.h | 12 +- intern/cycles/render/attribute.cpp | 2 +- intern/cycles/render/blackbody.cpp | 4 +- intern/cycles/render/camera.cpp | 4 +- intern/cycles/render/mesh.cpp | 14 +- intern/cycles/render/nodes.cpp | 16 +- intern/cycles/render/object.cpp | 10 +- intern/cycles/render/osl.cpp | 4 +- intern/cycles/render/session.cpp | 4 +- intern/cycles/render/sky_model.cpp | 6 +- intern/cycles/render/tile.cpp | 2 +- intern/cycles/subd/subd_mesh.cpp | 6 +- intern/cycles/util/util_aligned_malloc.cpp | 2 +- intern/cycles/util/util_atomic.h | 4 +- intern/cycles/util/util_hash.h | 2 +- intern/cycles/util/util_math.h | 2 +- intern/cycles/util/util_simd.h | 6 +- intern/cycles/util/util_time.cpp | 2 +- 63 files changed, 384 insertions(+), 384 deletions(-) diff --git a/intern/cycles/app/cycles_server.cpp b/intern/cycles/app/cycles_server.cpp index 3d5b237eec1..6522b4cde52 100644 --- a/intern/cycles/app/cycles_server.cpp +++ b/intern/cycles/app/cycles_server.cpp @@ -66,7 +66,7 @@ int main(int argc, const char **argv) exit(EXIT_FAILURE); } - if (debug) { + if(debug) { util_logging_start(); util_logging_verbosity_set(verbosity); } diff --git a/intern/cycles/app/cycles_standalone.cpp b/intern/cycles/app/cycles_standalone.cpp index 42c339f56e5..72bd6350fb1 100644 --- a/intern/cycles/app/cycles_standalone.cpp +++ b/intern/cycles/app/cycles_standalone.cpp @@ -124,7 +124,7 @@ static void scene_init() xml_read_file(options.scene, options.filepath.c_str()); /* Camera width/height override? */ - if (!(options.width == 0 || options.height == 0)) { + if(!(options.width == 0 || options.height == 0)) { options.scene->camera->width = options.width; options.scene->camera->height = options.height; } @@ -367,7 +367,7 @@ static void options_parse(int argc, const char **argv) exit(EXIT_FAILURE); } - if (debug) { + if(debug) { util_logging_start(); util_logging_verbosity_set(verbosity); } diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 05e34387eb7..2b99dfe6feb 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -225,21 +225,21 @@ static ShaderSocketType xml_read_socket_type(pugi::xml_node node, const char *na if(attr) { string value = attr.value(); - if (string_iequals(value, "float")) + if(string_iequals(value, "float")) return SHADER_SOCKET_FLOAT; - else if (string_iequals(value, "int")) + else if(string_iequals(value, "int")) return SHADER_SOCKET_INT; - else if (string_iequals(value, "color")) + else if(string_iequals(value, "color")) return SHADER_SOCKET_COLOR; - else if (string_iequals(value, "vector")) + else if(string_iequals(value, "vector")) return SHADER_SOCKET_VECTOR; - else if (string_iequals(value, "point")) + else if(string_iequals(value, "point")) return SHADER_SOCKET_POINT; - else if (string_iequals(value, "normal")) + else if(string_iequals(value, "normal")) return SHADER_SOCKET_NORMAL; - else if (string_iequals(value, "closure color")) + else if(string_iequals(value, "closure color")) return SHADER_SOCKET_CLOSURE; - else if (string_iequals(value, "string")) + else if(string_iequals(value, "string")) return SHADER_SOCKET_STRING; else fprintf(stderr, "Unknown shader socket type \"%s\" for attribute \"%s\".\n", value.c_str(), name); @@ -419,25 +419,25 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug * Socket names must be stored in the extra lists instead. */ /* read input values */ for(pugi::xml_node param = node.first_child(); param; param = param.next_sibling()) { - if (string_iequals(param.name(), "input")) { + if(string_iequals(param.name(), "input")) { string name; - if (!xml_read_string(&name, param, "name")) + if(!xml_read_string(&name, param, "name")) continue; ShaderSocketType type = xml_read_socket_type(param, "type"); - if (type == SHADER_SOCKET_UNDEFINED) + if(type == SHADER_SOCKET_UNDEFINED) continue; osl->input_names.push_back(ustring(name)); osl->add_input(osl->input_names.back().c_str(), type); } - else if (string_iequals(param.name(), "output")) { + else if(string_iequals(param.name(), "output")) { string name; - if (!xml_read_string(&name, param, "name")) + if(!xml_read_string(&name, param, "name")) continue; ShaderSocketType type = xml_read_socket_type(param, "type"); - if (type == SHADER_SOCKET_UNDEFINED) + if(type == SHADER_SOCKET_UNDEFINED) continue; osl->output_names.push_back(ustring(name)); diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index da10ede858d..5b3e666e7c7 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -303,7 +303,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int &cam->viewplane, &aspectratio, &sensor_size); /* panorama sensor */ - if (bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) { + if(bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) { float fit_xratio = (float)bcam->full_width*bcam->pixelaspect.x; float fit_yratio = (float)bcam->full_height*bcam->pixelaspect.y; bool horizontal_fit; diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 2ab4e68f967..91963ac3fe3 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -152,7 +152,7 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par continue; int ren_step = (1 << draw_step) + 1; - if (b_part.kink() == BL::ParticleSettings::kink_SPIRAL) + if(b_part.kink() == BL::ParticleSettings::kink_SPIRAL) ren_step += b_part.kink_extra_steps(); PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles"); @@ -233,10 +233,10 @@ bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Parti int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f); int totcurves = totchild; - if (b_part.child_type() == 0) + if(b_part.child_type() == 0) totcurves += totparts; - if (totcurves == 0) + if(totcurves == 0) continue; int pa_no = 0; @@ -287,10 +287,10 @@ bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f); int totcurves = totchild; - if (b_part.child_type() == 0) + if(b_part.child_type() == 0) totcurves += totparts; - if (totcurves == 0) + if(totcurves == 0) continue; int pa_no = 0; @@ -326,7 +326,7 @@ static void set_resolution(BL::Object *b_ob, BL::Scene *scene, bool render) { BL::Object::modifiers_iterator b_mod; for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) { - if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && ((b_mod->show_viewport()) || (b_mod->show_render()))) { + if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && ((b_mod->show_viewport()) || (b_mod->show_render()))) { BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr); BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr); b_psys.set_resolution(*scene, *b_ob, (render)? 2: 1); @@ -513,7 +513,7 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resol ybasis = normalize(cross(xbasis, v2)); - for (; subv <= 1; subv++) { + for(; subv <= 1; subv++) { float3 ickey_loc = make_float3(0.0f,0.0f,0.0f); float time = 0.0f; @@ -581,7 +581,7 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData) } } - if (num_curves > 0) { + if(num_curves > 0) { VLOG(1) << "Exporting curve segments for mesh " << mesh->name; } diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index c70ffea39c3..ce2d2700901 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -302,7 +302,7 @@ static void attr_create_uv_map(Scene *scene, BL::Mesh b_mesh, const vector& nverts) { - if (b_mesh.tessface_uv_textures.length() != 0) { + if(b_mesh.tessface_uv_textures.length() != 0) { BL::Mesh::tessface_uv_textures_iterator l; for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) { diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index e827d46223b..7364a8b170a 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -356,7 +356,7 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P object->random_id ^= hash_int(hash_string(b_parent.name().c_str())); /* dupli texture coordinates */ - if (b_dupli_ob) { + if(b_dupli_ob) { object->dupli_generated = 0.5f*get_float3(b_dupli_ob.orco()) - make_float3(0.5f, 0.5f, 0.5f); object->dupli_uv = get_float2(b_dupli_ob.uv()); } diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index 2785cfa9634..6d799e6e10e 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -76,7 +76,7 @@ bool BlenderSync::sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Ob psys->particles.push_back(pa); - if (object->particle_index != psys->particles.size() - 1) + if(object->particle_index != psys->particles.size() - 1) scene->object_manager->tag_update(scene); object->particle_system = psys; object->particle_index = psys->particles.size() - 1; diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 7e5893e5663..b9521090c93 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -391,7 +391,7 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args) /* find socket socket */ BL::NodeSocket b_sock(PointerRNA_NULL); - if (param->isoutput) { + if(param->isoutput) { b_sock = b_node.outputs[param->name.string()]; /* remove if type no longer matches */ if(b_sock && b_sock.bl_idname() != socket_type) { @@ -445,7 +445,7 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args) removed = false; - for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) { + for(b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) { if(used_sockets.find(b_input->ptr.data) == used_sockets.end()) { b_node.inputs.remove(*b_input); removed = true; @@ -453,7 +453,7 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args) } } - for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) { + for(b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) { if(used_sockets.find(b_output->ptr.data) == used_sockets.end()) { b_node.outputs.remove(*b_output); removed = true; diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 4ff1d7713dc..ee6ec7ac2c1 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -353,7 +353,7 @@ void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_upda BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str()); /* can happen if the intersected rectangle gives 0 width or height */ - if (b_rr.ptr.data == NULL) { + if(b_rr.ptr.data == NULL) { return; } @@ -366,10 +366,10 @@ void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_upda BL::RenderLayer b_rlay = *b_single_rlay; - if (do_update_only) { + if(do_update_only) { /* update only needed */ - if (rtile.sample != 0) { + if(rtile.sample != 0) { /* sample would be zero at initial tile update, which is only needed * to tag tile form blender side as IN PROGRESS for proper highlight * no buffers should be sent to blender yet @@ -397,7 +397,7 @@ void BlenderSession::update_render_tile(RenderTile& rtile) * be updated in blender side * would need to be investigated a bit further, but for now shall be fine */ - if (!b_engine.is_preview()) + if(!b_engine.is_preview()) do_write_update_render_tile(rtile, true); else do_write_update_render_tile(rtile, false); @@ -601,7 +601,7 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::Re vector pixels(params.width*params.height*4); - if (!do_update_only) { + if(!do_update_only) { /* copy each pass */ BL::RenderLayer::passes_iterator b_iter; @@ -869,7 +869,7 @@ void BlenderSession::update_status_progress() last_progress = progress; } - if (session->progress.get_error()) { + if(session->progress.get_error()) { string error = session->progress.get_error_message(); if(error != last_error) { /* TODO(sergey): Currently C++ RNA API doesn't let us to diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 7a656360bd3..dda06616ac6 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -184,48 +184,48 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen ShaderNode *node = NULL; /* existing blender nodes */ - if (b_node.is_a(&RNA_ShaderNodeRGBCurve)) { + if(b_node.is_a(&RNA_ShaderNodeRGBCurve)) { BL::ShaderNodeRGBCurve b_curve_node(b_node); RGBCurvesNode *curves = new RGBCurvesNode(); curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, true); node = curves; } - if (b_node.is_a(&RNA_ShaderNodeVectorCurve)) { + if(b_node.is_a(&RNA_ShaderNodeVectorCurve)) { BL::ShaderNodeVectorCurve b_curve_node(b_node); VectorCurvesNode *curves = new VectorCurvesNode(); curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, false); node = curves; } - else if (b_node.is_a(&RNA_ShaderNodeValToRGB)) { + else if(b_node.is_a(&RNA_ShaderNodeValToRGB)) { RGBRampNode *ramp = new RGBRampNode(); BL::ShaderNodeValToRGB b_ramp_node(b_node); colorramp_to_array(b_ramp_node.color_ramp(), ramp->ramp, RAMP_TABLE_SIZE); ramp->interpolate = b_ramp_node.color_ramp().interpolation() != BL::ColorRamp::interpolation_CONSTANT; node = ramp; } - else if (b_node.is_a(&RNA_ShaderNodeRGB)) { + else if(b_node.is_a(&RNA_ShaderNodeRGB)) { ColorNode *color = new ColorNode(); color->value = get_node_output_rgba(b_node, "Color"); node = color; } - else if (b_node.is_a(&RNA_ShaderNodeValue)) { + else if(b_node.is_a(&RNA_ShaderNodeValue)) { ValueNode *value = new ValueNode(); value->value = get_node_output_value(b_node, "Value"); node = value; } - else if (b_node.is_a(&RNA_ShaderNodeCameraData)) { + else if(b_node.is_a(&RNA_ShaderNodeCameraData)) { node = new CameraNode(); } - else if (b_node.is_a(&RNA_ShaderNodeInvert)) { + else if(b_node.is_a(&RNA_ShaderNodeInvert)) { node = new InvertNode(); } - else if (b_node.is_a(&RNA_ShaderNodeGamma)) { + else if(b_node.is_a(&RNA_ShaderNodeGamma)) { node = new GammaNode(); } - else if (b_node.is_a(&RNA_ShaderNodeBrightContrast)) { + else if(b_node.is_a(&RNA_ShaderNodeBrightContrast)) { node = new BrightContrastNode(); } - else if (b_node.is_a(&RNA_ShaderNodeMixRGB)) { + else if(b_node.is_a(&RNA_ShaderNodeMixRGB)) { BL::ShaderNodeMixRGB b_mix_node(b_node); MixNode *mix = new MixNode(); mix->type = MixNode::type_enum[b_mix_node.blend_type()]; @@ -236,44 +236,44 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen mix->use_clamp = b_mix_node.use_clamp(); node = mix; } - else if (b_node.is_a(&RNA_ShaderNodeSeparateRGB)) { + else if(b_node.is_a(&RNA_ShaderNodeSeparateRGB)) { node = new SeparateRGBNode(); } - else if (b_node.is_a(&RNA_ShaderNodeCombineRGB)) { + else if(b_node.is_a(&RNA_ShaderNodeCombineRGB)) { node = new CombineRGBNode(); } - else if (b_node.is_a(&RNA_ShaderNodeSeparateHSV)) { + else if(b_node.is_a(&RNA_ShaderNodeSeparateHSV)) { node = new SeparateHSVNode(); } - else if (b_node.is_a(&RNA_ShaderNodeCombineHSV)) { + else if(b_node.is_a(&RNA_ShaderNodeCombineHSV)) { node = new CombineHSVNode(); } - else if (b_node.is_a(&RNA_ShaderNodeSeparateXYZ)) { + else if(b_node.is_a(&RNA_ShaderNodeSeparateXYZ)) { node = new SeparateXYZNode(); } - else if (b_node.is_a(&RNA_ShaderNodeCombineXYZ)) { + else if(b_node.is_a(&RNA_ShaderNodeCombineXYZ)) { node = new CombineXYZNode(); } - else if (b_node.is_a(&RNA_ShaderNodeHueSaturation)) { + else if(b_node.is_a(&RNA_ShaderNodeHueSaturation)) { node = new HSVNode(); } - else if (b_node.is_a(&RNA_ShaderNodeRGBToBW)) { + else if(b_node.is_a(&RNA_ShaderNodeRGBToBW)) { node = new ConvertNode(SHADER_SOCKET_COLOR, SHADER_SOCKET_FLOAT); } - else if (b_node.is_a(&RNA_ShaderNodeMath)) { + else if(b_node.is_a(&RNA_ShaderNodeMath)) { BL::ShaderNodeMath b_math_node(b_node); MathNode *math = new MathNode(); math->type = MathNode::type_enum[b_math_node.operation()]; math->use_clamp = b_math_node.use_clamp(); node = math; } - else if (b_node.is_a(&RNA_ShaderNodeVectorMath)) { + else if(b_node.is_a(&RNA_ShaderNodeVectorMath)) { BL::ShaderNodeVectorMath b_vector_math_node(b_node); VectorMathNode *vmath = new VectorMathNode(); vmath->type = VectorMathNode::type_enum[b_vector_math_node.operation()]; node = vmath; } - else if (b_node.is_a(&RNA_ShaderNodeVectorTransform)) { + else if(b_node.is_a(&RNA_ShaderNodeVectorTransform)) { BL::ShaderNodeVectorTransform b_vector_transform_node(b_node); VectorTransformNode *vtransform = new VectorTransformNode(); vtransform->type = VectorTransformNode::type_enum[b_vector_transform_node.type()]; @@ -281,7 +281,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen vtransform->convert_to = VectorTransformNode::convert_space_enum[b_vector_transform_node.convert_to()]; node = vtransform; } - else if (b_node.is_a(&RNA_ShaderNodeNormal)) { + else if(b_node.is_a(&RNA_ShaderNodeNormal)) { BL::Node::outputs_iterator out_it; b_node.outputs.begin(out_it); @@ -289,7 +289,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen norm->direction = get_node_output_vector(b_node, "Normal"); node = norm; } - else if (b_node.is_a(&RNA_ShaderNodeMapping)) { + else if(b_node.is_a(&RNA_ShaderNodeMapping)) { BL::ShaderNodeMapping b_mapping_node(b_node); MappingNode *mapping = new MappingNode(); @@ -297,31 +297,31 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen node = mapping; } - else if (b_node.is_a(&RNA_ShaderNodeFresnel)) { + else if(b_node.is_a(&RNA_ShaderNodeFresnel)) { node = new FresnelNode(); } - else if (b_node.is_a(&RNA_ShaderNodeLayerWeight)) { + else if(b_node.is_a(&RNA_ShaderNodeLayerWeight)) { node = new LayerWeightNode(); } - else if (b_node.is_a(&RNA_ShaderNodeAddShader)) { + else if(b_node.is_a(&RNA_ShaderNodeAddShader)) { node = new AddClosureNode(); } - else if (b_node.is_a(&RNA_ShaderNodeMixShader)) { + else if(b_node.is_a(&RNA_ShaderNodeMixShader)) { node = new MixClosureNode(); } - else if (b_node.is_a(&RNA_ShaderNodeAttribute)) { + else if(b_node.is_a(&RNA_ShaderNodeAttribute)) { BL::ShaderNodeAttribute b_attr_node(b_node); AttributeNode *attr = new AttributeNode(); attr->attribute = b_attr_node.attribute_name(); node = attr; } - else if (b_node.is_a(&RNA_ShaderNodeBackground)) { + else if(b_node.is_a(&RNA_ShaderNodeBackground)) { node = new BackgroundNode(); } - else if (b_node.is_a(&RNA_ShaderNodeHoldout)) { + else if(b_node.is_a(&RNA_ShaderNodeHoldout)) { node = new HoldoutNode(); } - else if (b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) { + else if(b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) { BL::ShaderNodeBsdfAnisotropic b_aniso_node(b_node); AnisotropicBsdfNode *aniso = new AnisotropicBsdfNode(); @@ -340,10 +340,10 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen node = aniso; } - else if (b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) { + else if(b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) { node = new DiffuseBsdfNode(); } - else if (b_node.is_a(&RNA_ShaderNodeSubsurfaceScattering)) { + else if(b_node.is_a(&RNA_ShaderNodeSubsurfaceScattering)) { BL::ShaderNodeSubsurfaceScattering b_subsurface_node(b_node); SubsurfaceScatteringNode *subsurface = new SubsurfaceScatteringNode(); @@ -359,7 +359,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen node = subsurface; } - else if (b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) { + else if(b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) { BL::ShaderNodeBsdfGlossy b_glossy_node(b_node); GlossyBsdfNode *glossy = new GlossyBsdfNode(); @@ -379,7 +379,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen } node = glossy; } - else if (b_node.is_a(&RNA_ShaderNodeBsdfGlass)) { + else if(b_node.is_a(&RNA_ShaderNodeBsdfGlass)) { BL::ShaderNodeBsdfGlass b_glass_node(b_node); GlassBsdfNode *glass = new GlassBsdfNode(); switch(b_glass_node.distribution()) { @@ -395,7 +395,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen } node = glass; } - else if (b_node.is_a(&RNA_ShaderNodeBsdfRefraction)) { + else if(b_node.is_a(&RNA_ShaderNodeBsdfRefraction)) { BL::ShaderNodeBsdfRefraction b_refraction_node(b_node); RefractionBsdfNode *refraction = new RefractionBsdfNode(); switch(b_refraction_node.distribution()) { @@ -411,7 +411,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen } node = refraction; } - else if (b_node.is_a(&RNA_ShaderNodeBsdfToon)) { + else if(b_node.is_a(&RNA_ShaderNodeBsdfToon)) { BL::ShaderNodeBsdfToon b_toon_node(b_node); ToonBsdfNode *toon = new ToonBsdfNode(); switch(b_toon_node.component()) { @@ -424,7 +424,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen } node = toon; } - else if (b_node.is_a(&RNA_ShaderNodeBsdfHair)) { + else if(b_node.is_a(&RNA_ShaderNodeBsdfHair)) { BL::ShaderNodeBsdfHair b_hair_node(b_node); HairBsdfNode *hair = new HairBsdfNode(); switch(b_hair_node.component()) { @@ -437,64 +437,64 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen } node = hair; } - else if (b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) { + else if(b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) { node = new TranslucentBsdfNode(); } - else if (b_node.is_a(&RNA_ShaderNodeBsdfTransparent)) { + else if(b_node.is_a(&RNA_ShaderNodeBsdfTransparent)) { node = new TransparentBsdfNode(); } - else if (b_node.is_a(&RNA_ShaderNodeBsdfVelvet)) { + else if(b_node.is_a(&RNA_ShaderNodeBsdfVelvet)) { node = new VelvetBsdfNode(); } - else if (b_node.is_a(&RNA_ShaderNodeEmission)) { + else if(b_node.is_a(&RNA_ShaderNodeEmission)) { node = new EmissionNode(); } - else if (b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) { + else if(b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) { node = new AmbientOcclusionNode(); } - else if (b_node.is_a(&RNA_ShaderNodeVolumeScatter)) { + else if(b_node.is_a(&RNA_ShaderNodeVolumeScatter)) { node = new ScatterVolumeNode(); } - else if (b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) { + else if(b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) { node = new AbsorptionVolumeNode(); } - else if (b_node.is_a(&RNA_ShaderNodeNewGeometry)) { + else if(b_node.is_a(&RNA_ShaderNodeNewGeometry)) { node = new GeometryNode(); } - else if (b_node.is_a(&RNA_ShaderNodeWireframe)) { + else if(b_node.is_a(&RNA_ShaderNodeWireframe)) { BL::ShaderNodeWireframe b_wireframe_node(b_node); WireframeNode *wire = new WireframeNode(); wire->use_pixel_size = b_wireframe_node.use_pixel_size(); node = wire; } - else if (b_node.is_a(&RNA_ShaderNodeWavelength)) { + else if(b_node.is_a(&RNA_ShaderNodeWavelength)) { node = new WavelengthNode(); } - else if (b_node.is_a(&RNA_ShaderNodeBlackbody)) { + else if(b_node.is_a(&RNA_ShaderNodeBlackbody)) { node = new BlackbodyNode(); } - else if (b_node.is_a(&RNA_ShaderNodeLightPath)) { + else if(b_node.is_a(&RNA_ShaderNodeLightPath)) { node = new LightPathNode(); } - else if (b_node.is_a(&RNA_ShaderNodeLightFalloff)) { + else if(b_node.is_a(&RNA_ShaderNodeLightFalloff)) { node = new LightFalloffNode(); } - else if (b_node.is_a(&RNA_ShaderNodeObjectInfo)) { + else if(b_node.is_a(&RNA_ShaderNodeObjectInfo)) { node = new ObjectInfoNode(); } - else if (b_node.is_a(&RNA_ShaderNodeParticleInfo)) { + else if(b_node.is_a(&RNA_ShaderNodeParticleInfo)) { node = new ParticleInfoNode(); } - else if (b_node.is_a(&RNA_ShaderNodeHairInfo)) { + else if(b_node.is_a(&RNA_ShaderNodeHairInfo)) { node = new HairInfoNode(); } - else if (b_node.is_a(&RNA_ShaderNodeBump)) { + else if(b_node.is_a(&RNA_ShaderNodeBump)) { BL::ShaderNodeBump b_bump_node(b_node); BumpNode *bump = new BumpNode(); bump->invert = b_bump_node.invert(); node = bump; } - else if (b_node.is_a(&RNA_ShaderNodeScript)) { + else if(b_node.is_a(&RNA_ShaderNodeScript)) { #ifdef WITH_OSL if(scene->shader_manager->use_osl()) { /* create script node */ @@ -510,7 +510,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen * Socket names must be stored in the extra lists instead. */ BL::Node::inputs_iterator b_input; - for (b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) { + for(b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) { script_node->input_names.push_back(ustring(b_input->name())); ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(), convert_socket_type(*b_input)); @@ -519,7 +519,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen BL::Node::outputs_iterator b_output; - for (b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) { + for(b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) { script_node->output_names.push_back(ustring(b_output->name())); script_node->add_output(script_node->output_names.back().c_str(), convert_socket_type(*b_output)); @@ -548,7 +548,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen (void)b_ntree; #endif } - else if (b_node.is_a(&RNA_ShaderNodeTexImage)) { + else if(b_node.is_a(&RNA_ShaderNodeTexImage)) { BL::ShaderNodeTexImage b_image_node(b_node); BL::Image b_image(b_image_node.image()); ImageTextureNode *image = new ImageTextureNode(); @@ -581,7 +581,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen image->use_alpha = b_image.use_alpha(); /* TODO(sergey): Does not work properly when we change builtin type. */ - if (b_image.is_updated()) { + if(b_image.is_updated()) { scene->image_manager->tag_reload_image(image->filename, image->builtin_data, (InterpolationType)b_image_node.interpolation()); @@ -594,7 +594,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping()); node = image; } - else if (b_node.is_a(&RNA_ShaderNodeTexEnvironment)) { + else if(b_node.is_a(&RNA_ShaderNodeTexEnvironment)) { BL::ShaderNodeTexEnvironment b_env_node(b_node); BL::Image b_image(b_env_node.image()); EnvironmentTextureNode *env = new EnvironmentTextureNode(); @@ -618,7 +618,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen env->use_alpha = b_image.use_alpha(); /* TODO(sergey): Does not work properly when we change builtin type. */ - if (b_image.is_updated()) { + if(b_image.is_updated()) { scene->image_manager->tag_reload_image(env->filename, env->builtin_data, INTERPOLATION_LINEAR); @@ -629,41 +629,41 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping()); node = env; } - else if (b_node.is_a(&RNA_ShaderNodeTexGradient)) { + else if(b_node.is_a(&RNA_ShaderNodeTexGradient)) { BL::ShaderNodeTexGradient b_gradient_node(b_node); GradientTextureNode *gradient = new GradientTextureNode(); gradient->type = GradientTextureNode::type_enum[(int)b_gradient_node.gradient_type()]; get_tex_mapping(&gradient->tex_mapping, b_gradient_node.texture_mapping()); node = gradient; } - else if (b_node.is_a(&RNA_ShaderNodeTexVoronoi)) { + else if(b_node.is_a(&RNA_ShaderNodeTexVoronoi)) { BL::ShaderNodeTexVoronoi b_voronoi_node(b_node); VoronoiTextureNode *voronoi = new VoronoiTextureNode(); voronoi->coloring = VoronoiTextureNode::coloring_enum[(int)b_voronoi_node.coloring()]; get_tex_mapping(&voronoi->tex_mapping, b_voronoi_node.texture_mapping()); node = voronoi; } - else if (b_node.is_a(&RNA_ShaderNodeTexMagic)) { + else if(b_node.is_a(&RNA_ShaderNodeTexMagic)) { BL::ShaderNodeTexMagic b_magic_node(b_node); MagicTextureNode *magic = new MagicTextureNode(); magic->depth = b_magic_node.turbulence_depth(); get_tex_mapping(&magic->tex_mapping, b_magic_node.texture_mapping()); node = magic; } - else if (b_node.is_a(&RNA_ShaderNodeTexWave)) { + else if(b_node.is_a(&RNA_ShaderNodeTexWave)) { BL::ShaderNodeTexWave b_wave_node(b_node); WaveTextureNode *wave = new WaveTextureNode(); wave->type = WaveTextureNode::type_enum[(int)b_wave_node.wave_type()]; get_tex_mapping(&wave->tex_mapping, b_wave_node.texture_mapping()); node = wave; } - else if (b_node.is_a(&RNA_ShaderNodeTexChecker)) { + else if(b_node.is_a(&RNA_ShaderNodeTexChecker)) { BL::ShaderNodeTexChecker b_checker_node(b_node); CheckerTextureNode *checker = new CheckerTextureNode(); get_tex_mapping(&checker->tex_mapping, b_checker_node.texture_mapping()); node = checker; } - else if (b_node.is_a(&RNA_ShaderNodeTexBrick)) { + else if(b_node.is_a(&RNA_ShaderNodeTexBrick)) { BL::ShaderNodeTexBrick b_brick_node(b_node); BrickTextureNode *brick = new BrickTextureNode(); brick->offset = b_brick_node.offset(); @@ -673,20 +673,20 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen get_tex_mapping(&brick->tex_mapping, b_brick_node.texture_mapping()); node = brick; } - else if (b_node.is_a(&RNA_ShaderNodeTexNoise)) { + else if(b_node.is_a(&RNA_ShaderNodeTexNoise)) { BL::ShaderNodeTexNoise b_noise_node(b_node); NoiseTextureNode *noise = new NoiseTextureNode(); get_tex_mapping(&noise->tex_mapping, b_noise_node.texture_mapping()); node = noise; } - else if (b_node.is_a(&RNA_ShaderNodeTexMusgrave)) { + else if(b_node.is_a(&RNA_ShaderNodeTexMusgrave)) { BL::ShaderNodeTexMusgrave b_musgrave_node(b_node); MusgraveTextureNode *musgrave = new MusgraveTextureNode(); musgrave->type = MusgraveTextureNode::type_enum[(int)b_musgrave_node.musgrave_type()]; get_tex_mapping(&musgrave->tex_mapping, b_musgrave_node.texture_mapping()); node = musgrave; } - else if (b_node.is_a(&RNA_ShaderNodeTexCoord)) { + else if(b_node.is_a(&RNA_ShaderNodeTexCoord)) { BL::ShaderNodeTexCoord b_tex_coord_node(b_node); TextureCoordinateNode *tex_coord = new TextureCoordinateNode(); tex_coord->from_dupli = b_tex_coord_node.from_dupli(); @@ -696,7 +696,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen } node = tex_coord; } - else if (b_node.is_a(&RNA_ShaderNodeTexSky)) { + else if(b_node.is_a(&RNA_ShaderNodeTexSky)) { BL::ShaderNodeTexSky b_sky_node(b_node); SkyTextureNode *sky = new SkyTextureNode(); sky->type = SkyTextureNode::type_enum[(int)b_sky_node.sky_type()]; @@ -706,14 +706,14 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen get_tex_mapping(&sky->tex_mapping, b_sky_node.texture_mapping()); node = sky; } - else if (b_node.is_a(&RNA_ShaderNodeNormalMap)) { + else if(b_node.is_a(&RNA_ShaderNodeNormalMap)) { BL::ShaderNodeNormalMap b_normal_map_node(b_node); NormalMapNode *nmap = new NormalMapNode(); nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()]; nmap->attribute = b_normal_map_node.uv_map(); node = nmap; } - else if (b_node.is_a(&RNA_ShaderNodeTangent)) { + else if(b_node.is_a(&RNA_ShaderNodeTangent)) { BL::ShaderNodeTangent b_tangent_node(b_node); TangentNode *tangent = new TangentNode(); tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()]; @@ -721,7 +721,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen tangent->attribute = b_tangent_node.uv_map(); node = tangent; } - else if (b_node.is_a(&RNA_ShaderNodeUVMap)) { + else if(b_node.is_a(&RNA_ShaderNodeUVMap)) { BL::ShaderNodeUVMap b_uvmap_node(b_node); UVMapNode *uvm = new UVMapNode(); uvm->attribute = b_uvmap_node.uv_map(); @@ -737,7 +737,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen static bool node_use_modified_socket_name(ShaderNode *node) { - if (node->special_type == SHADER_SPECIAL_TYPE_SCRIPT) + if(node->special_type == SHADER_SPECIAL_TYPE_SCRIPT) return false; return true; @@ -747,14 +747,14 @@ static ShaderInput *node_find_input_by_name(ShaderNode *node, BL::Node b_node, B { string name = b_socket.name(); - if (node_use_modified_socket_name(node)) { + if(node_use_modified_socket_name(node)) { BL::Node::inputs_iterator b_input; bool found = false; int counter = 0, total = 0; - for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) { - if (b_input->name() == name) { - if (!found) + for(b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) { + if(b_input->name() == name) { + if(!found) counter++; total++; } @@ -764,10 +764,10 @@ static ShaderInput *node_find_input_by_name(ShaderNode *node, BL::Node b_node, B } /* rename if needed */ - if (name == "Shader") + if(name == "Shader") name = "Closure"; - if (total > 1) + if(total > 1) name = string_printf("%s%d", name.c_str(), counter); } @@ -778,14 +778,14 @@ static ShaderOutput *node_find_output_by_name(ShaderNode *node, BL::Node b_node, { string name = b_socket.name(); - if (node_use_modified_socket_name(node)) { + if(node_use_modified_socket_name(node)) { BL::Node::outputs_iterator b_output; bool found = false; int counter = 0, total = 0; - for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) { - if (b_output->name() == name) { - if (!found) + for(b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) { + if(b_output->name() == name) { + if(!found) counter++; total++; } @@ -795,10 +795,10 @@ static ShaderOutput *node_find_output_by_name(ShaderNode *node, BL::Node b_node, } /* rename if needed */ - if (name == "Shader") + if(name == "Shader") name = "Closure"; - if (total > 1) + if(total > 1) name = string_printf("%s%d", name.c_str(), counter); } @@ -821,7 +821,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha BL::ShaderNode output_node(PointerRNA_NULL); for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) { - if (is_output_node(*b_node)) { + if(is_output_node(*b_node)) { BL::ShaderNodeOutputMaterial b_output_node(*b_node); if(b_output_node.is_active_output()) { @@ -837,10 +837,10 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha /* add nodes */ for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) { - if (b_node->mute() || b_node->is_a(&RNA_NodeReroute)) { + if(b_node->mute() || b_node->is_a(&RNA_NodeReroute)) { /* replace muted node with internal links */ BL::Node::internal_links_iterator b_link; - for (b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); ++b_link) { + for(b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); ++b_link) { ProxyNode *proxy = new ProxyNode(convert_socket_type(b_link->to_socket())); input_map[b_link->from_socket().ptr.data] = proxy->inputs[0]; @@ -849,10 +849,10 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha graph->add(proxy); } } - else if (b_node->is_a(&RNA_ShaderNodeGroup) || b_node->is_a(&RNA_NodeCustomGroup)) { + else if(b_node->is_a(&RNA_ShaderNodeGroup) || b_node->is_a(&RNA_NodeCustomGroup)) { BL::ShaderNodeTree b_group_ntree(PointerRNA_NULL); - if (b_node->is_a(&RNA_ShaderNodeGroup)) + if(b_node->is_a(&RNA_ShaderNodeGroup)) b_group_ntree = BL::ShaderNodeTree(((BL::NodeGroup)(*b_node)).node_tree()); else b_group_ntree = BL::ShaderNodeTree(((BL::NodeCustomGroup)(*b_node)).node_tree()); @@ -883,28 +883,28 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha output_map[b_output->ptr.data] = proxy->outputs[0]; } - if (b_group_ntree) + if(b_group_ntree) add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_proxy_input_map, group_proxy_output_map); } - else if (b_node->is_a(&RNA_NodeGroupInput)) { + else if(b_node->is_a(&RNA_NodeGroupInput)) { /* map each socket to a proxy node */ for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { ProxyMap::const_iterator proxy_it = proxy_input_map.find(b_output->identifier()); - if (proxy_it != proxy_input_map.end()) { + if(proxy_it != proxy_input_map.end()) { ProxyNode *proxy = proxy_it->second; output_map[b_output->ptr.data] = proxy->outputs[0]; } } } - else if (b_node->is_a(&RNA_NodeGroupOutput)) { + else if(b_node->is_a(&RNA_NodeGroupOutput)) { BL::NodeGroupOutput b_output_node(*b_node); /* only the active group output is used */ - if (b_output_node.is_active_output()) { + if(b_output_node.is_active_output()) { /* map each socket to a proxy node */ for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { ProxyMap::const_iterator proxy_it = proxy_output_map.find(b_input->identifier()); - if (proxy_it != proxy_output_map.end()) { + if(proxy_it != proxy_output_map.end()) { ProxyNode *proxy = proxy_it->second; input_map[b_input->ptr.data] = proxy->inputs[0]; @@ -917,8 +917,8 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha else { ShaderNode *node = NULL; - if (is_output_node(*b_node)) { - if (b_node->ptr.data == output_node.ptr.data) { + if(is_output_node(*b_node)) { + if(b_node->ptr.data == output_node.ptr.data) { node = graph->output(); } } @@ -930,7 +930,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha /* map node sockets for linking */ for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { ShaderInput *input = node_find_input_by_name(node, *b_node, *b_input); - if (!input) { + if(!input) { /* XXX should not happen, report error? */ continue; } @@ -940,7 +940,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha } for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { ShaderOutput *output = node_find_output_by_name(node, *b_node, *b_output); - if (!output) { + if(!output) { /* XXX should not happen, report error? */ continue; } @@ -966,10 +966,10 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha ShaderInput *input = 0; PtrOutputMap::iterator output_it = output_map.find(b_from_sock.ptr.data); - if (output_it != output_map.end()) + if(output_it != output_map.end()) output = output_it->second; PtrInputMap::iterator input_it = input_map.find(b_to_sock.ptr.data); - if (input_it != input_map.end()) + if(input_it != input_map.end()) input = input_it->second; /* either node may be NULL when the node was not exported, typically diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 985a3cd3d5a..2ed61860066 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -111,7 +111,7 @@ bool BlenderSync::sync_recalc() if(b_ob->is_updated_data()) { BL::Object::particle_systems_iterator b_psys; - for (b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) + for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) particle_system_map.set_recalc(*b_ob); } } diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index 9f7181cc564..cb50680160c 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -43,8 +43,8 @@ void python_thread_state_restore(void **python_thread_state); static inline BL::Mesh object_to_mesh(BL::BlendData data, BL::Object object, BL::Scene scene, bool apply_modifiers, bool render, bool calc_undeformed) { BL::Mesh me = data.meshes.new_from_object(scene, object, apply_modifiers, (render)? 2: 1, false, calc_undeformed); - if ((bool)me) { - if (me.use_auto_smooth()) { + if((bool)me) { + if(me.use_auto_smooth()) { me.calc_normals_split(); } me.calc_tessface(true); @@ -310,7 +310,7 @@ static inline string get_string(PointerRNA& ptr, const char *name) char cstrbuf[1024]; char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf)); string str(cstr); - if (cstr != cstrbuf) + if(cstr != cstrbuf) MEM_freeN(cstr); return str; @@ -388,7 +388,7 @@ static inline BL::SmokeDomainSettings object_smoke_domain_find(BL::Object b_ob) BL::Object::modifiers_iterator b_mod; for(b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) { - if (b_mod->is_a(&RNA_SmokeModifier)) { + if(b_mod->is_a(&RNA_SmokeModifier)) { BL::SmokeModifier b_smd(*b_mod); if(b_smd.smoke_type() == BL::SmokeModifier::smoke_type_DOMAIN) diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index 9fa602f0952..f2777c4a15b 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -638,7 +638,7 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility size_t steps = mesh->motion_steps - 1; float4 *key_steps = attr->data_float4(); - for (size_t i = 0; i < steps; i++) + for(size_t i = 0; i < steps; i++) curve.bounds_grow(k, key_steps + i*mesh_size, bbox); } } @@ -660,7 +660,7 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility size_t steps = mesh->motion_steps - 1; float3 *vert_steps = attr->data_float3(); - for (size_t i = 0; i < steps; i++) + for(size_t i = 0; i < steps; i++) triangle.bounds_grow(vert_steps + i*mesh_size, bbox); } } @@ -877,7 +877,7 @@ void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility) size_t steps = mesh->motion_steps - 1; float4 *key_steps = attr->data_float4(); - for (size_t i = 0; i < steps; i++) + for(size_t i = 0; i < steps; i++) curve.bounds_grow(k, key_steps + i*mesh_size, bbox); } } @@ -899,7 +899,7 @@ void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility) size_t steps = mesh->motion_steps - 1; float3 *vert_steps = attr->data_float3(); - for (size_t i = 0; i < steps; i++) + for(size_t i = 0; i < steps; i++) triangle.bounds_grow(vert_steps + i*mesh_size, bbox); } } diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index 4ce8f787169..cb389b78049 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -42,7 +42,7 @@ ccl_device_inline int bitscan(int value) { assert(value != 0); int bit = 0; - while (value >>= 1) { + while(value >>= 1) { ++bit; } return bit; @@ -136,7 +136,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, size_t steps = mesh->motion_steps - 1; float4 *key_steps = curve_attr_mP->data_float4(); - for (size_t i = 0; i < steps; i++) + for(size_t i = 0; i < steps; i++) curve.bounds_grow(k, key_steps + i*mesh_size, bounds); type = PRIMITIVE_MOTION_CURVE; diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp index 07c35c08c18..2290c4143ad 100644 --- a/intern/cycles/bvh/bvh_split.cpp +++ b/intern/cycles/bvh/bvh_split.cpp @@ -253,7 +253,7 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH Object *ob = builder->objects[ref.prim_object()]; const Mesh *mesh = ob->mesh; - if (ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) { + if(ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) { const int *inds = mesh->triangles[ref.prim_index()].v; const float3 *verts = &mesh->verts[0]; const float3* v1 = &verts[inds[2]]; diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 70277c5aa48..148e52e2c86 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -209,7 +209,7 @@ public: int end_sample = tile.start_sample + tile.num_samples; for(int sample = start_sample; sample < end_sample; sample++) { - if (task.get_cancel() || task_pool.canceled()) { + if(task.get_cancel() || task_pool.canceled()) { if(task.need_finish_queue == false) break; } @@ -370,7 +370,7 @@ public: int get_split_task_count(DeviceTask& task) { - if (task.type == DeviceTask::SHADER) + if(task.type == DeviceTask::SHADER) return task.get_subtask_count(TaskScheduler::num_threads(), 256); else return task.get_subtask_count(TaskScheduler::num_threads()); diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 407f72034b3..5afeb896ac8 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -331,7 +331,7 @@ public: string cubin_data; CUresult result; - if (path_read_text(cubin, cubin_data)) + if(path_read_text(cubin, cubin_data)) result = cuModuleLoadData(&cuModule, cubin_data.c_str()); else result = CUDA_ERROR_FILE_NOT_FOUND; @@ -483,7 +483,7 @@ public: if(interpolation == INTERPOLATION_CLOSEST) { cuda_assert(cuTexRefSetFilterMode(texref, CU_TR_FILTER_MODE_POINT)); } - else if (interpolation == INTERPOLATION_LINEAR) { + else if(interpolation == INTERPOLATION_LINEAR) { cuda_assert(cuTexRefSetFilterMode(texref, CU_TR_FILTER_MODE_LINEAR)); } else {/* CUBIC and SMART are unsupported for CUDA */ @@ -966,7 +966,7 @@ public: int end_sample = tile.start_sample + tile.num_samples; for(int sample = start_sample; sample < end_sample; sample++) { - if (task->get_cancel()) { + if(task->get_cancel()) { if(task->need_finish_queue == false) break; } @@ -1035,12 +1035,12 @@ bool device_cuda_init(void) static bool initialized = false; static bool result = false; - if (initialized) + if(initialized) return result; initialized = true; int cuew_result = cuewInit(); - if (cuew_result == CUEW_SUCCESS) { + if(cuew_result == CUEW_SUCCESS) { VLOG(1) << "CUEW initialization succeeded"; if(CUDADevice::have_precompiled_kernels()) { VLOG(1) << "Found precompiled kernels"; diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp index 4733482bf4e..20df2434a4a 100644 --- a/intern/cycles/device/device_network.cpp +++ b/intern/cycles/device/device_network.cpp @@ -269,7 +269,7 @@ public: lock.unlock(); TileList::iterator it = tile_list_find(the_tiles, tile); - if (it != the_tiles.end()) { + if(it != the_tiles.end()) { tile.buffers = it->buffers; the_tiles.erase(it); } diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index f11c94245d5..a77a6aaceb2 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -423,7 +423,7 @@ public: int num_base = 0; int total_devices = 0; - for (int platform = 0; platform < num_platforms; platform++) { + for(int platform = 0; platform < num_platforms; platform++) { cl_uint num_devices; if(opencl_error(clGetDeviceIDs(platforms[platform], opencl_device_type(), 0, NULL, &num_devices))) @@ -1125,7 +1125,7 @@ bool device_opencl_init(void) { static bool initialized = false; static bool result = false; - if (initialized) + if(initialized) return result; initialized = true; @@ -1160,7 +1160,7 @@ void device_opencl_info(vector& devices) /* devices are numbered consecutively across platforms */ int num_base = 0; - for (int platform = 0; platform < num_platforms; platform++, num_base += num_devices) { + for(int platform = 0; platform < num_platforms; platform++, num_base += num_devices) { num_devices = 0; if(clGetDeviceIDs(platform_ids[platform], opencl_device_type(), 0, NULL, &num_devices) != CL_SUCCESS || num_devices == 0) continue; diff --git a/intern/cycles/device/device_task.cpp b/intern/cycles/device/device_task.cpp index 2fe2f334176..d527540f300 100644 --- a/intern/cycles/device/device_task.cpp +++ b/intern/cycles/device/device_task.cpp @@ -111,7 +111,7 @@ void DeviceTask::update_progress(RenderTile *rtile) if(update_tile_sample) { double current_time = time_dt(); - if (current_time - last_update_time >= 1.0) { + if(current_time - last_update_time >= 1.0) { update_tile_sample(*rtile); last_update_time = current_time; diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h index b6de2da8c71..b2848262001 100644 --- a/intern/cycles/kernel/closure/bssrdf.h +++ b/intern/cycles/kernel/closure/bssrdf.h @@ -157,7 +157,7 @@ ccl_device float bssrdf_cubic_quintic_root_find(float xi) float x = 0.25f; int i; - for (i = 0; i < max_iteration_count; i++) { + for(i = 0; i < max_iteration_count; i++) { float x2 = x*x; float x3 = x2*x; float nx = (1.0f - x); diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h index ac6c6ec4929..c13858fc461 100644 --- a/intern/cycles/kernel/geom/geom_curve.h +++ b/intern/cycles/kernel/geom/geom_curve.h @@ -442,12 +442,12 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect float r_ext = mw_extension + r_curr; float coverage = 1.0f; - if (bminz - r_curr > isect->t || bmaxz + r_curr < epsilon || bminx > r_ext|| bmaxx < -r_ext|| bminy > r_ext|| bmaxy < -r_ext) { + if(bminz - r_curr > isect->t || bmaxz + r_curr < epsilon || bminx > r_ext|| bmaxx < -r_ext|| bminy > r_ext|| bmaxy < -r_ext) { /* the bounding box does not overlap the square centered at O */ tree += level; level = tree & -tree; } - else if (level == 1) { + else if(level == 1) { /* the maximum recursion depth is reached. * check if dP0.(Q-P0)>=0 and dPn.(Pn-Q)>=0. @@ -459,7 +459,7 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect if(flags & CURVE_KN_RIBBONS) { float3 tg = (p_en - p_st); float w = tg.x * tg.x + tg.y * tg.y; - if (w == 0) { + if(w == 0) { tree++; level = tree & -tree; continue; @@ -474,17 +474,17 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect float3 p_curr = ((curve_coef[3] * u + curve_coef[2]) * u + curve_coef[1]) * u + curve_coef[0]; float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1]; - if (dot(tg, dp_st)< 0) + if(dot(tg, dp_st)< 0) dp_st *= -1; - if (dot(dp_st, -p_st) + p_curr.z * dp_st.z < 0) { + if(dot(dp_st, -p_st) + p_curr.z * dp_st.z < 0) { tree++; level = tree & -tree; continue; } float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1]; - if (dot(tg, dp_en) < 0) + if(dot(tg, dp_en) < 0) dp_en *= -1; - if (dot(dp_en, p_en) - p_curr.z * dp_en.z < 0) { + if(dot(dp_en, p_en) - p_curr.z * dp_en.z < 0) { tree++; level = tree & -tree; continue; @@ -500,13 +500,13 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect float d0 = d - r_curr; float d1 = d + r_curr; float inv_mw_extension = 1.0f/mw_extension; - if (d0 >= 0) + if(d0 >= 0) coverage = (min(d1 * inv_mw_extension, 1.0f) - min(d0 * inv_mw_extension, 1.0f)) * 0.5f; else // inside coverage = (min(d1 * inv_mw_extension, 1.0f) + min(-d0 * inv_mw_extension, 1.0f)) * 0.5f; } - if (p_curr.x * p_curr.x + p_curr.y * p_curr.y >= r_ext * r_ext || p_curr.z <= epsilon || isect->t < p_curr.z) { + if(p_curr.x * p_curr.x + p_curr.y * p_curr.y >= r_ext * r_ext || p_curr.z <= epsilon || isect->t < p_curr.z) { tree++; level = tree & -tree; continue; @@ -548,7 +548,7 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect float tb = 2*(tdif.z - tg.z*(tdifz + gd*(tdifz*gd + or1))); float tc = dot(tdif,tdif) - tdifz * tdifz * (1 + gd*gd) - or1*or1 - 2*or1*tdifz*gd; float td = tb*tb - 4*cyla*tc; - if (td < 0.0f) { + if(td < 0.0f) { tree++; level = tree & -tree; continue; @@ -559,10 +559,10 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect t = tcentre + correction; float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1]; - if (dot(tg, dp_st)< 0) + if(dot(tg, dp_st)< 0) dp_st *= -1; float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1]; - if (dot(tg, dp_en) < 0) + if(dot(tg, dp_en) < 0) dp_en *= -1; if(flags & CURVE_KN_BACKFACING && (dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f)) { @@ -570,7 +570,7 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect t = tcentre + correction; } - if (dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f) { + if(dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f) { tree++; level = tree & -tree; continue; @@ -777,7 +777,7 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec float tc = dot3(tdif, tdif) - tdifz*tdifz - tdifma*tdifma; float td = tb*tb - 4*a*tc; - if (td < 0.0f) + if(td < 0.0f) return false; float rootd = 0.0f; @@ -818,7 +818,7 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec if(t > 0.0f && t < isect->t && z >= 0 && z <= l) { - if (flags & CURVE_KN_ENCLOSEFILTER) { + if(flags & CURVE_KN_ENCLOSEFILTER) { float enc_ratio = 1.01f; if((difz > -r1 * enc_ratio) && (dot3(dif_second, tg) < r2 * enc_ratio)) { float a2 = 1.0f - (dirz*dirz*(1 + gd*gd*enc_ratio*enc_ratio)); @@ -984,7 +984,7 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con sd->v = 0.0f; #endif - if (flag & CURVE_KN_TRUETANGENTGNORMAL) { + if(flag & CURVE_KN_TRUETANGENTGNORMAL) { sd->Ng = -(D - tg * dot(tg, D)); sd->Ng = normalize(sd->Ng); } @@ -995,7 +995,7 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con sd->Ng = (dif - tg * sd->u * l) / (P_curve[0].w + sd->u * l * gd); /* adjustment for changing radius */ - if (gd != 0.0f) { + if(gd != 0.0f) { sd->Ng = sd->Ng - gd * tg; sd->Ng = normalize(sd->Ng); } diff --git a/intern/cycles/kernel/geom/geom_primitive.h b/intern/cycles/kernel/geom/geom_primitive.h index b52ec7ef1b2..d2543c5943e 100644 --- a/intern/cycles/kernel/geom/geom_primitive.h +++ b/intern/cycles/kernel/geom/geom_primitive.h @@ -194,7 +194,7 @@ ccl_device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd) /* camera motion, for perspective/orthographic motion.pre/post will be a * world-to-raster matrix, for panorama it's world-to-camera */ - if (kernel_data.cam.type != CAMERA_PANORAMA) { + if(kernel_data.cam.type != CAMERA_PANORAMA) { tfm = kernel_data.cam.worldtoraster; motion_center = transform_perspective(&tfm, center); diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index c9e30a451da..983e4ad90b9 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -155,8 +155,8 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg, */ const float T = (U * A_kz + V * B_kz + W * C_kz) * Sz; const float sign_T = xor_signmast(T, sign_mask); - if ((sign_T < 0.0f) || - (sign_T > isect->t * xor_signmast(det, sign_mask))) + if((sign_T < 0.0f) || + (sign_T > isect->t * xor_signmast(det, sign_mask))) { return false; } @@ -254,8 +254,8 @@ ccl_device_inline void triangle_intersect_subsurface( const float Cz = Sz * C_kz; const float T = U * Az + V * Bz + W * Cz; - if ((xor_signmast(T, sign_mask) < 0.0f) || - (xor_signmast(T, sign_mask) > tmax * xor_signmast(det, sign_mask))) + if((xor_signmast(T, sign_mask) < 0.0f) || + (xor_signmast(T, sign_mask) > tmax * xor_signmast(det, sign_mask))) { return; } diff --git a/intern/cycles/kernel/kernel.cpp b/intern/cycles/kernel/kernel.cpp index 013eeff57fa..a7eaa758f5d 100644 --- a/intern/cycles/kernel/kernel.cpp +++ b/intern/cycles/kernel/kernel.cpp @@ -55,7 +55,7 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t int id = atoi(name + strlen("__tex_image_float_")); int array_index = id; - if (array_index >= 0 && array_index < MAX_FLOAT_IMAGES) { + if(array_index >= 0 && array_index < MAX_FLOAT_IMAGES) { tex = &kg->texture_float_images[array_index]; } @@ -70,7 +70,7 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t int id = atoi(name + strlen("__tex_image_")); int array_index = id - MAX_FLOAT_IMAGES; - if (array_index >= 0 && array_index < MAX_BYTE_IMAGES) { + if(array_index >= 0 && array_index < MAX_BYTE_IMAGES) { tex = &kg->texture_byte_images[array_index]; } diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index 20d7a143c67..7790b9caa5a 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -57,7 +57,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian /* sample subsurface scattering */ if((is_combined || is_sss_sample) && (sd->flag & SD_BSSRDF)) { /* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */ - if (kernel_path_subsurface_scatter(kg, sd, &L_sample, &state, &rng, &ray, &throughput)) + if(kernel_path_subsurface_scatter(kg, sd, &L_sample, &state, &rng, &ray, &throughput)) is_sss_sample = true; } #endif @@ -259,7 +259,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, /* data passes */ case SHADER_EVAL_NORMAL: { - if ((sd.flag & SD_HAS_BUMP)) { + if((sd.flag & SD_HAS_BUMP)) { shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN); } diff --git a/intern/cycles/kernel/kernel_jitter.h b/intern/cycles/kernel/kernel_jitter.h index 6953f005ea9..9ba41635b9e 100644 --- a/intern/cycles/kernel/kernel_jitter.h +++ b/intern/cycles/kernel/kernel_jitter.h @@ -128,7 +128,7 @@ ccl_device_inline uint cmj_permute(uint i, uint l, uint p) i *= 0xc860a3df; i &= w; i ^= i >> 5; - } while (i >= l); + } while(i >= l); return (i + p) % l; } diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index 0300e1d4c7f..5e34b7ee85e 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -627,7 +627,7 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta step_size = kernel_data.integrator.volume_step_size; /* compute exact steps in advance for malloc */ max_steps = max((int)ceilf(ray->t/step_size), 1); - if (max_steps > global_max_steps) { + if(max_steps > global_max_steps) { max_steps = global_max_steps; step_size = ray->t / (float)max_steps; } diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 1f6015d0d6b..22f48ee57f0 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -138,12 +138,12 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result { /* this is only used for shader and object space, we don't really have * a concept of shader space, so we just use object space for both. */ - if (xform) { + if(xform) { const ShaderData *sd = (const ShaderData *)xform; KernelGlobals *kg = sd->osl_globals; int object = sd->object; - if (object != OBJECT_NONE) { + if(object != OBJECT_NONE) { #ifdef __OBJECT_MOTION__ Transform tfm; @@ -168,12 +168,12 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 { /* this is only used for shader and object space, we don't really have * a concept of shader space, so we just use object space for both. */ - if (xform) { + if(xform) { const ShaderData *sd = (const ShaderData *)xform; KernelGlobals *kg = sd->osl_globals; int object = sd->object; - if (object != OBJECT_NONE) { + if(object != OBJECT_NONE) { #ifdef __OBJECT_MOTION__ Transform itfm; @@ -198,27 +198,27 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result { KernelGlobals *kg = kernel_globals; - if (from == u_ndc) { + if(from == u_ndc) { Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc)); COPY_MATRIX44(&result, &tfm); return true; } - else if (from == u_raster) { + else if(from == u_raster) { Transform tfm = transform_transpose(kernel_data.cam.rastertoworld); COPY_MATRIX44(&result, &tfm); return true; } - else if (from == u_screen) { + else if(from == u_screen) { Transform tfm = transform_transpose(kernel_data.cam.screentoworld); COPY_MATRIX44(&result, &tfm); return true; } - else if (from == u_camera) { + else if(from == u_camera) { Transform tfm = transform_transpose(kernel_data.cam.cameratoworld); COPY_MATRIX44(&result, &tfm); return true; } - else if (from == u_world) { + else if(from == u_world) { result.makeIdentity(); return true; } @@ -230,27 +230,27 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 { KernelGlobals *kg = kernel_globals; - if (to == u_ndc) { + if(to == u_ndc) { Transform tfm = transform_transpose(kernel_data.cam.worldtondc); COPY_MATRIX44(&result, &tfm); return true; } - else if (to == u_raster) { + else if(to == u_raster) { Transform tfm = transform_transpose(kernel_data.cam.worldtoraster); COPY_MATRIX44(&result, &tfm); return true; } - else if (to == u_screen) { + else if(to == u_screen) { Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen); COPY_MATRIX44(&result, &tfm); return true; } - else if (to == u_camera) { + else if(to == u_camera) { Transform tfm = transform_transpose(kernel_data.cam.worldtocamera); COPY_MATRIX44(&result, &tfm); return true; } - else if (to == u_world) { + else if(to == u_world) { result.makeIdentity(); return true; } @@ -262,11 +262,11 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result { /* this is only used for shader and object space, we don't really have * a concept of shader space, so we just use object space for both. */ - if (xform) { + if(xform) { const ShaderData *sd = (const ShaderData *)xform; int object = sd->object; - if (object != OBJECT_NONE) { + if(object != OBJECT_NONE) { #ifdef __OBJECT_MOTION__ Transform tfm = sd->ob_tfm; #else @@ -287,11 +287,11 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 { /* this is only used for shader and object space, we don't really have * a concept of shader space, so we just use object space for both. */ - if (xform) { + if(xform) { const ShaderData *sd = (const ShaderData *)xform; int object = sd->object; - if (object != OBJECT_NONE) { + if(object != OBJECT_NONE) { #ifdef __OBJECT_MOTION__ Transform tfm = sd->ob_itfm; #else @@ -312,22 +312,22 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result { KernelGlobals *kg = kernel_globals; - if (from == u_ndc) { + if(from == u_ndc) { Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc)); COPY_MATRIX44(&result, &tfm); return true; } - else if (from == u_raster) { + else if(from == u_raster) { Transform tfm = transform_transpose(kernel_data.cam.rastertoworld); COPY_MATRIX44(&result, &tfm); return true; } - else if (from == u_screen) { + else if(from == u_screen) { Transform tfm = transform_transpose(kernel_data.cam.screentoworld); COPY_MATRIX44(&result, &tfm); return true; } - else if (from == u_camera) { + else if(from == u_camera) { Transform tfm = transform_transpose(kernel_data.cam.cameratoworld); COPY_MATRIX44(&result, &tfm); return true; @@ -340,22 +340,22 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 { KernelGlobals *kg = kernel_globals; - if (to == u_ndc) { + if(to == u_ndc) { Transform tfm = transform_transpose(kernel_data.cam.worldtondc); COPY_MATRIX44(&result, &tfm); return true; } - else if (to == u_raster) { + else if(to == u_raster) { Transform tfm = transform_transpose(kernel_data.cam.worldtoraster); COPY_MATRIX44(&result, &tfm); return true; } - else if (to == u_screen) { + else if(to == u_screen) { Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen); COPY_MATRIX44(&result, &tfm); return true; } - else if (to == u_camera) { + else if(to == u_camera) { Transform tfm = transform_transpose(kernel_data.cam.worldtocamera); COPY_MATRIX44(&result, &tfm); return true; @@ -373,8 +373,8 @@ bool OSLRenderServices::get_array_attribute(OSL::ShaderGlobals *sg, bool derivat static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val) { - if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || - type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) + if(type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || + type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { float *fval = (float *)val; @@ -382,7 +382,7 @@ static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, v fval[1] = f[0].y; fval[2] = f[0].z; - if (derivatives) { + if(derivatives) { fval[3] = f[1].x; fval[4] = f[1].y; fval[5] = f[1].z; @@ -398,7 +398,7 @@ static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, v float *fval = (float *)val; fval[0] = average(f[0]); - if (derivatives) { + if(derivatives) { fval[1] = average(f[1]); fval[2] = average(f[2]); } @@ -422,15 +422,15 @@ static bool set_attribute_float3(float3 f, TypeDesc type, bool derivatives, void static bool set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val) { - if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || - type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) + if(type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || + type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { float *fval = (float *)val; fval[0] = f[0]; fval[1] = f[1]; fval[2] = f[2]; - if (derivatives) { + if(derivatives) { fval[3] = f[1]; fval[4] = f[1]; fval[5] = f[1]; @@ -446,7 +446,7 @@ static bool set_attribute_float(float f[3], TypeDesc type, bool derivatives, voi float *fval = (float *)val; fval[0] = f[0]; - if (derivatives) { + if(derivatives) { fval[1] = f[1]; fval[2] = f[2]; } @@ -474,7 +474,7 @@ static bool set_attribute_int(int i, TypeDesc type, bool derivatives, void *val) int *ival = (int *)val; ival[0] = i; - if (derivatives) { + if(derivatives) { ival[1] = 0; ival[2] = 0; } @@ -491,7 +491,7 @@ static bool set_attribute_string(ustring str, TypeDesc type, bool derivatives, v ustring *sval = (ustring *)val; sval[0] = str; - if (derivatives) { + if(derivatives) { sval[1] = OSLRenderServices::u_empty; sval[2] = OSLRenderServices::u_empty; } @@ -521,7 +521,7 @@ static bool set_attribute_float3_3(float3 P[3], TypeDesc type, bool derivatives, if(type.arraylen > 3) memset(fval + 3*3, 0, sizeof(float)*3*(type.arraylen - 3)); - if (derivatives) + if(derivatives) memset(fval + type.arraylen*3, 0, sizeof(float)*2*3*type.arraylen); return true; @@ -544,15 +544,15 @@ static bool set_attribute_matrix(const Transform& tfm, TypeDesc type, void *val) static bool get_mesh_element_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr, const TypeDesc& type, bool derivatives, void *val) { - if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || - attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) + if(attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || + attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) { float3 fval[3]; fval[0] = primitive_attribute_float3(kg, sd, attr.elem, attr.offset, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); return set_attribute_float3(fval, type, derivatives, val); } - else if (attr.type == TypeDesc::TypeFloat) { + else if(attr.type == TypeDesc::TypeFloat) { float fval[3]; fval[0] = primitive_attribute_float(kg, sd, attr.elem, attr.offset, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); @@ -566,7 +566,7 @@ static bool get_mesh_element_attribute(KernelGlobals *kg, const ShaderData *sd, static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr, const TypeDesc& type, bool derivatives, void *val) { - if (attr.type == TypeDesc::TypeMatrix) { + if(attr.type == TypeDesc::TypeMatrix) { Transform tfm = primitive_attribute_matrix(kg, sd, attr.offset); return set_attribute_matrix(tfm, type, val); } @@ -580,7 +580,7 @@ static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivat size_t datasize = attr.value.datasize(); memcpy(val, attr.value.data(), datasize); - if (derivatives) + if(derivatives) memset((char *)val + datasize, 0, datasize * 2); } @@ -590,80 +590,80 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD /* todo: turn this into hash table? */ /* Object Attributes */ - if (name == u_object_location) { + if(name == u_object_location) { float3 f = object_location(kg, sd); return set_attribute_float3(f, type, derivatives, val); } - else if (name == u_object_index) { + else if(name == u_object_index) { float f = object_pass_id(kg, sd->object); return set_attribute_float(f, type, derivatives, val); } - else if (name == u_geom_dupli_generated) { + else if(name == u_geom_dupli_generated) { float3 f = object_dupli_generated(kg, sd->object); return set_attribute_float3(f, type, derivatives, val); } - else if (name == u_geom_dupli_uv) { + else if(name == u_geom_dupli_uv) { float3 f = object_dupli_uv(kg, sd->object); return set_attribute_float3(f, type, derivatives, val); } - else if (name == u_material_index) { + else if(name == u_material_index) { float f = shader_pass_id(kg, sd); return set_attribute_float(f, type, derivatives, val); } - else if (name == u_object_random) { + else if(name == u_object_random) { float f = object_random_number(kg, sd->object); return set_attribute_float(f, type, derivatives, val); } /* Particle Attributes */ - else if (name == u_particle_index) { + else if(name == u_particle_index) { int particle_id = object_particle_id(kg, sd->object); float f = particle_index(kg, particle_id); return set_attribute_float(f, type, derivatives, val); } - else if (name == u_particle_age) { + else if(name == u_particle_age) { int particle_id = object_particle_id(kg, sd->object); float f = particle_age(kg, particle_id); return set_attribute_float(f, type, derivatives, val); } - else if (name == u_particle_lifetime) { + else if(name == u_particle_lifetime) { int particle_id = object_particle_id(kg, sd->object); float f = particle_lifetime(kg, particle_id); return set_attribute_float(f, type, derivatives, val); } - else if (name == u_particle_location) { + else if(name == u_particle_location) { int particle_id = object_particle_id(kg, sd->object); float3 f = particle_location(kg, particle_id); return set_attribute_float3(f, type, derivatives, val); } #if 0 /* unsupported */ - else if (name == u_particle_rotation) { + else if(name == u_particle_rotation) { int particle_id = object_particle_id(kg, sd->object); float4 f = particle_rotation(kg, particle_id); return set_attribute_float4(f, type, derivatives, val); } #endif - else if (name == u_particle_size) { + else if(name == u_particle_size) { int particle_id = object_particle_id(kg, sd->object); float f = particle_size(kg, particle_id); return set_attribute_float(f, type, derivatives, val); } - else if (name == u_particle_velocity) { + else if(name == u_particle_velocity) { int particle_id = object_particle_id(kg, sd->object); float3 f = particle_velocity(kg, particle_id); return set_attribute_float3(f, type, derivatives, val); } - else if (name == u_particle_angular_velocity) { + else if(name == u_particle_angular_velocity) { int particle_id = object_particle_id(kg, sd->object); float3 f = particle_angular_velocity(kg, particle_id); return set_attribute_float3(f, type, derivatives, val); } /* Geometry Attributes */ - else if (name == u_geom_numpolyvertices) { + else if(name == u_geom_numpolyvertices) { return set_attribute_int(3, type, derivatives, val); } - else if ((name == u_geom_trianglevertices || name == u_geom_polyvertices) + else if((name == u_geom_trianglevertices || name == u_geom_polyvertices) #ifdef __HAIR__ && sd->type & PRIMITIVE_ALL_TRIANGLE) #else @@ -689,21 +689,21 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD ustring object_name = kg->osl->object_names[sd->object]; return set_attribute_string(object_name, type, derivatives, val); } - else if (name == u_is_smooth) { + else if(name == u_is_smooth) { float f = ((sd->shader & SHADER_SMOOTH_NORMAL) != 0); return set_attribute_float(f, type, derivatives, val); } #ifdef __HAIR__ /* Hair Attributes */ - else if (name == u_is_curve) { + else if(name == u_is_curve) { float f = (sd->type & PRIMITIVE_ALL_CURVE) != 0; return set_attribute_float(f, type, derivatives, val); } - else if (name == u_curve_thickness) { + else if(name == u_curve_thickness) { float f = curve_thickness(kg, sd); return set_attribute_float(f, type, derivatives, val); } - else if (name == u_curve_tangent_normal) { + else if(name == u_curve_tangent_normal) { float3 f = curve_tangent_normal(kg, sd); return set_attribute_float3(f, type, derivatives, val); } @@ -715,22 +715,22 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD bool OSLRenderServices::get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, TypeDesc type, bool derivatives, void *val) { - if (name == u_path_ray_length) { + if(name == u_path_ray_length) { /* Ray Length */ float f = sd->ray_length; return set_attribute_float(f, type, derivatives, val); } - else if (name == u_path_ray_depth) { + else if(name == u_path_ray_depth) { /* Ray Depth */ int f = sd->ray_depth; return set_attribute_int(f, type, derivatives, val); } - else if (name == u_path_transparent_depth) { + else if(name == u_path_transparent_depth) { /* Transparent Ray Depth */ int f = sd->transparent_depth; return set_attribute_int(f, type, derivatives, val); } - else if (name == u_ndc) { + else if(name == u_ndc) { /* NDC coordinates with special exception for otho */ OSLThreadData *tdata = kg->osl_tdata; OSL::ShaderGlobals *globals = &tdata->globals; @@ -762,7 +762,7 @@ bool OSLRenderServices::get_background_attribute(KernelGlobals *kg, ShaderData * bool OSLRenderServices::get_attribute(OSL::ShaderGlobals *sg, bool derivatives, ustring object_name, TypeDesc type, ustring name, void *val) { - if (sg->renderstate == NULL) + if(sg->renderstate == NULL) return false; ShaderData *sd = (ShaderData *)(sg->renderstate); @@ -777,10 +777,10 @@ bool OSLRenderServices::get_attribute(ShaderData *sd, bool derivatives, ustring int object; /* lookup of attribute on another object */ - if (object_name != u_empty) { + if(object_name != u_empty) { OSLGlobals::ObjectNameMap::iterator it = kg->osl->object_name_map.find(object_name); - if (it == kg->osl->object_name_map.end()) + if(it == kg->osl->object_name_map.end()) return false; object = it->second; @@ -790,7 +790,7 @@ bool OSLRenderServices::get_attribute(ShaderData *sd, bool derivatives, ustring object = sd->object; is_curve = (sd->type & PRIMITIVE_ALL_CURVE) != 0; - if (object == OBJECT_NONE) + if(object == OBJECT_NONE) return get_background_attribute(kg, sd, name, type, derivatives, val); } @@ -799,10 +799,10 @@ bool OSLRenderServices::get_attribute(ShaderData *sd, bool derivatives, ustring OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object]; OSLGlobals::AttributeMap::iterator it = attribute_map.find(name); - if (it != attribute_map.end()) { + if(it != attribute_map.end()) { const OSLGlobals::Attribute& attr = it->second; - if (attr.elem != ATTR_ELEMENT_OBJECT) { + if(attr.elem != ATTR_ELEMENT_OBJECT) { /* triangle and vertex attributes */ if(get_mesh_element_attribute(kg, sd, attr, type, derivatives, val)) return true; @@ -819,7 +819,7 @@ bool OSLRenderServices::get_attribute(ShaderData *sd, bool derivatives, ustring /* not found in attribute, check standard object info */ bool is_std_object_attribute = get_object_standard_attribute(kg, sd, name, type, derivatives, val); - if (is_std_object_attribute) + if(is_std_object_attribute) return true; return get_background_attribute(kg, sd, name, type, derivatives, val); diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index fa6745a17a1..8cfe0cbcbd4 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -146,11 +146,11 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag, /* OSL gives us a closure tree, we flatten it into arrays per * closure type, for evaluation, sampling, etc later on. */ - if (closure->type == OSL::ClosureColor::COMPONENT) { + if(closure->type == OSL::ClosureColor::COMPONENT) { OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure; CClosurePrimitive *prim = (CClosurePrimitive *)comp->data(); - if (prim) { + if(prim) { ShaderClosure sc; #ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS @@ -296,11 +296,11 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag, } } } - else if (closure->type == OSL::ClosureColor::MUL) { + else if(closure->type == OSL::ClosureColor::MUL) { OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; flatten_surface_closure_tree(sd, path_flag, mul->closure, TO_FLOAT3(mul->weight) * weight); } - else if (closure->type == OSL::ClosureColor::ADD) { + else if(closure->type == OSL::ClosureColor::ADD) { OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure; flatten_surface_closure_tree(sd, path_flag, add->closureA, weight); flatten_surface_closure_tree(sd, path_flag, add->closureB, weight); @@ -319,11 +319,11 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, int path_flag, S OSL::ShadingContext *octx = tdata->context[(int)ctx]; int shader = sd->shader & SHADER_MASK; - if (kg->osl->surface_state[shader]) + if(kg->osl->surface_state[shader]) ss->execute(*octx, *(kg->osl->surface_state[shader]), *globals); /* flatten closure tree */ - if (globals->Ci) + if(globals->Ci) flatten_surface_closure_tree(sd, path_flag, globals->Ci); } @@ -335,23 +335,23 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure) * is only one supported closure type at the moment, which has no evaluation * functions, so we just sum the weights */ - if (closure->type == OSL::ClosureColor::COMPONENT) { + if(closure->type == OSL::ClosureColor::COMPONENT) { OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure; CClosurePrimitive *prim = (CClosurePrimitive *)comp->data(); - if (prim && prim->category == CClosurePrimitive::Background) + if(prim && prim->category == CClosurePrimitive::Background) #ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS return TO_FLOAT3(comp->w); #else return make_float3(1.0f, 1.0f, 1.0f); #endif } - else if (closure->type == OSL::ClosureColor::MUL) { + else if(closure->type == OSL::ClosureColor::MUL) { OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure); } - else if (closure->type == OSL::ClosureColor::ADD) { + else if(closure->type == OSL::ClosureColor::ADD) { OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure; return flatten_background_closure_tree(add->closureA) + @@ -372,11 +372,11 @@ float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_fl OSL::ShaderGlobals *globals = &tdata->globals; OSL::ShadingContext *octx = tdata->context[(int)ctx]; - if (kg->osl->background_state) + if(kg->osl->background_state) ss->execute(*octx, *(kg->osl->background_state), *globals); /* return background color immediately */ - if (globals->Ci) + if(globals->Ci) return flatten_background_closure_tree(globals->Ci); return make_float3(0.0f, 0.0f, 0.0f); @@ -390,11 +390,11 @@ static void flatten_volume_closure_tree(ShaderData *sd, /* OSL gives us a closure tree, we flatten it into arrays per * closure type, for evaluation, sampling, etc later on. */ - if (closure->type == OSL::ClosureColor::COMPONENT) { + if(closure->type == OSL::ClosureColor::COMPONENT) { OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure; CClosurePrimitive *prim = (CClosurePrimitive *)comp->data(); - if (prim) { + if(prim) { ShaderClosure sc; #ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS @@ -451,11 +451,11 @@ static void flatten_volume_closure_tree(ShaderData *sd, } } } - else if (closure->type == OSL::ClosureColor::MUL) { + else if(closure->type == OSL::ClosureColor::MUL) { OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight); } - else if (closure->type == OSL::ClosureColor::ADD) { + else if(closure->type == OSL::ClosureColor::ADD) { OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure; flatten_volume_closure_tree(sd, add->closureA, weight); flatten_volume_closure_tree(sd, add->closureB, weight); @@ -474,11 +474,11 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, int path_flag, Sh OSL::ShadingContext *octx = tdata->context[(int)ctx]; int shader = sd->shader & SHADER_MASK; - if (kg->osl->volume_state[shader]) + if(kg->osl->volume_state[shader]) ss->execute(*octx, *(kg->osl->volume_state[shader]), *globals); /* flatten closure tree */ - if (globals->Ci) + if(globals->Ci) flatten_volume_closure_tree(sd, globals->Ci); } @@ -496,7 +496,7 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderConte OSL::ShadingContext *octx = tdata->context[(int)ctx]; int shader = sd->shader & SHADER_MASK; - if (kg->osl->displacement_state[shader]) + if(kg->osl->displacement_state[shader]) ss->execute(*octx, *(kg->osl->displacement_state[shader]), *globals); /* get back position */ @@ -523,7 +523,7 @@ float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const CBSDFClosure *bsdf = (CBSDFClosure *)sc->prim; float3 bsdf_eval; - if (dot(sd->Ng, omega_in) >= 0.0f) + if(dot(sd->Ng, omega_in) >= 0.0f) bsdf_eval = bsdf->eval_reflect(sd->I, omega_in, pdf); else bsdf_eval = bsdf->eval_transmit(sd->I, omega_in, pdf); @@ -551,7 +551,7 @@ int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, ustring stdname(std::string("geom:") + std::string(Attribute::standard_name((AttributeStandard)id))); OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname); - if (it != attr_map.end()) { + if(it != attr_map.end()) { const OSLGlobals::Attribute &osl_attr = it->second; *elem = osl_attr.elem; diff --git a/intern/cycles/kernel/svm/svm_blackbody.h b/intern/cycles/kernel/svm/svm_blackbody.h index 1e40e868e14..b2ff97d71e6 100644 --- a/intern/cycles/kernel/svm/svm_blackbody.h +++ b/intern/cycles/kernel/svm/svm_blackbody.h @@ -42,11 +42,11 @@ ccl_device void svm_node_blackbody(KernelGlobals *kg, ShaderData *sd, float *sta /* Input */ float temperature = stack_load_float(stack, temperature_offset); - if (temperature < BB_DRAPER) { + if(temperature < BB_DRAPER) { /* just return very very dim red */ color_rgb = make_float3(1.0e-6f,0.0f,0.0f); } - else if (temperature <= BB_MAX_TABLE_RANGE) { + else if(temperature <= BB_MAX_TABLE_RANGE) { /* This is the overall size of the table */ const int lookuptablesize = 956; const float lookuptablenormalize = 1.0f/956.0f; @@ -74,10 +74,10 @@ ccl_device void svm_node_blackbody(KernelGlobals *kg, ShaderData *sd, float *sta /* Luminance */ float l = linear_rgb_to_gray(color_rgb); - if (l != 0.0f) + if(l != 0.0f) color_rgb /= l; - if (stack_valid(col_offset)) + if(stack_valid(col_offset)) stack_store_float3(stack, col_offset, color_rgb); } diff --git a/intern/cycles/kernel/svm/svm_brightness.h b/intern/cycles/kernel/svm/svm_brightness.h index 631bd1825ee..e4d545a00ae 100644 --- a/intern/cycles/kernel/svm/svm_brightness.h +++ b/intern/cycles/kernel/svm/svm_brightness.h @@ -32,7 +32,7 @@ ccl_device void svm_node_brightness(ShaderData *sd, float *stack, uint in_color, color.y = max(a*color.y + b, 0.0f); color.z = max(a*color.z + b, 0.0f); - if (stack_valid(out_color)) + if(stack_valid(out_color)) stack_store_float3(stack, out_color, color); } diff --git a/intern/cycles/kernel/svm/svm_camera.h b/intern/cycles/kernel/svm/svm_camera.h index e03745cb331..90249dfd978 100644 --- a/intern/cycles/kernel/svm/svm_camera.h +++ b/intern/cycles/kernel/svm/svm_camera.h @@ -27,13 +27,13 @@ ccl_device void svm_node_camera(KernelGlobals *kg, ShaderData *sd, float *stack, zdepth = vector.z; distance = len(vector); - if (stack_valid(out_vector)) + if(stack_valid(out_vector)) stack_store_float3(stack, out_vector, normalize(vector)); - if (stack_valid(out_zdepth)) + if(stack_valid(out_zdepth)) stack_store_float(stack, out_zdepth, zdepth); - if (stack_valid(out_distance)) + if(stack_valid(out_distance)) stack_store_float(stack, out_distance, distance); } diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index db9f442083e..8afdb73fb38 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -331,9 +331,9 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->data2 = 0.0f; - if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID) + if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID) sd->flag |= bsdf_microfacet_beckmann_aniso_setup(sc); - else if (type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID) + else if(type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID) sd->flag |= bsdf_microfacet_ggx_aniso_setup(sc); else sd->flag |= bsdf_ashikhmin_shirley_aniso_setup(sc); @@ -365,7 +365,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->data1 = param2; sc->data2 = 0.0f; - if (type == CLOSURE_BSDF_DIFFUSE_TOON_ID) + if(type == CLOSURE_BSDF_DIFFUSE_TOON_ID) sd->flag |= bsdf_diffuse_toon_setup(sc); else sd->flag |= bsdf_glossy_toon_setup(sc); diff --git a/intern/cycles/kernel/svm/svm_gamma.h b/intern/cycles/kernel/svm/svm_gamma.h index 8bc59b9c673..b645ff3f0f9 100644 --- a/intern/cycles/kernel/svm/svm_gamma.h +++ b/intern/cycles/kernel/svm/svm_gamma.h @@ -21,14 +21,14 @@ ccl_device void svm_node_gamma(ShaderData *sd, float *stack, uint in_gamma, uint float3 color = stack_load_float3(stack, in_color); float gamma = stack_load_float(stack, in_gamma); - if (color.x > 0.0f) + if(color.x > 0.0f) color.x = powf(color.x, gamma); - if (color.y > 0.0f) + if(color.y > 0.0f) color.y = powf(color.y, gamma); - if (color.z > 0.0f) + if(color.z > 0.0f) color.z = powf(color.z, gamma); - if (stack_valid(out_color)) + if(stack_valid(out_color)) stack_store_float3(stack, out_color, color); } diff --git a/intern/cycles/kernel/svm/svm_hsv.h b/intern/cycles/kernel/svm/svm_hsv.h index eeb4ba25e91..4f3f5d5f091 100644 --- a/intern/cycles/kernel/svm/svm_hsv.h +++ b/intern/cycles/kernel/svm/svm_hsv.h @@ -51,7 +51,7 @@ ccl_device void svm_node_hsv(KernelGlobals *kg, ShaderData *sd, float *stack, ui color.y = max(color.y, 0.0f); color.z = max(color.z, 0.0f); - if (stack_valid(out_color_offset)) + if(stack_valid(out_color_offset)) stack_store_float3(stack, out_color_offset, color); } diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index 4de69479bd9..e927d46d404 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -65,7 +65,7 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, float4 r; int ix, iy, nix, niy; - if (interpolation == INTERPOLATION_CLOSEST) { + if(interpolation == INTERPOLATION_CLOSEST) { svm_image_texture_frac(x*width, &ix); svm_image_texture_frac(y*height, &iy); diff --git a/intern/cycles/kernel/svm/svm_invert.h b/intern/cycles/kernel/svm/svm_invert.h index 152b49174e0..5ce858e2e5d 100644 --- a/intern/cycles/kernel/svm/svm_invert.h +++ b/intern/cycles/kernel/svm/svm_invert.h @@ -30,7 +30,7 @@ ccl_device void svm_node_invert(ShaderData *sd, float *stack, uint in_fac, uint color.y = invert(color.y, factor); color.z = invert(color.z, factor); - if (stack_valid(out_color)) + if(stack_valid(out_color)) stack_store_float3(stack, out_color, color); } diff --git a/intern/cycles/kernel/svm/svm_normal.h b/intern/cycles/kernel/svm/svm_normal.h index 67b5321e0de..53abef71012 100644 --- a/intern/cycles/kernel/svm/svm_normal.h +++ b/intern/cycles/kernel/svm/svm_normal.h @@ -28,10 +28,10 @@ ccl_device void svm_node_normal(KernelGlobals *kg, ShaderData *sd, float *stack, direction.z = __int_as_float(node1.z); direction = normalize(direction); - if (stack_valid(out_normal_offset)) + if(stack_valid(out_normal_offset)) stack_store_float3(stack, out_normal_offset, direction); - if (stack_valid(out_dot_offset)) + if(stack_valid(out_dot_offset)) stack_store_float(stack, out_dot_offset, dot(direction, normalize(normal))); } diff --git a/intern/cycles/kernel/svm/svm_sepcomb_hsv.h b/intern/cycles/kernel/svm/svm_sepcomb_hsv.h index 68f9fea02f0..6f51b163756 100644 --- a/intern/cycles/kernel/svm/svm_sepcomb_hsv.h +++ b/intern/cycles/kernel/svm/svm_sepcomb_hsv.h @@ -28,7 +28,7 @@ ccl_device void svm_node_combine_hsv(KernelGlobals *kg, ShaderData *sd, float *s /* Combine, and convert back to RGB */ float3 color = hsv_to_rgb(make_float3(hue, saturation, value)); - if (stack_valid(color_out)) + if(stack_valid(color_out)) stack_store_float3(stack, color_out, color); } @@ -42,11 +42,11 @@ ccl_device void svm_node_separate_hsv(KernelGlobals *kg, ShaderData *sd, float * /* Convert to HSV */ color = rgb_to_hsv(color); - if (stack_valid(hue_out)) + if(stack_valid(hue_out)) stack_store_float(stack, hue_out, color.x); - if (stack_valid(saturation_out)) + if(stack_valid(saturation_out)) stack_store_float(stack, saturation_out, color.y); - if (stack_valid(value_out)) + if(stack_valid(value_out)) stack_store_float(stack, value_out, color.z); } diff --git a/intern/cycles/kernel/svm/svm_sepcomb_vector.h b/intern/cycles/kernel/svm/svm_sepcomb_vector.h index 7a5a69f6dff..63570dd6942 100644 --- a/intern/cycles/kernel/svm/svm_sepcomb_vector.h +++ b/intern/cycles/kernel/svm/svm_sepcomb_vector.h @@ -22,7 +22,7 @@ ccl_device void svm_node_combine_vector(ShaderData *sd, float *stack, uint in_of { float vector = stack_load_float(stack, in_offset); - if (stack_valid(out_offset)) + if(stack_valid(out_offset)) stack_store_float(stack, out_offset+vector_index, vector); } @@ -30,10 +30,10 @@ ccl_device void svm_node_separate_vector(ShaderData *sd, float *stack, uint ivec { float3 vector = stack_load_float3(stack, ivector_offset); - if (stack_valid(out_offset)) { - if (vector_index == 0) + if(stack_valid(out_offset)) { + if(vector_index == 0) stack_store_float(stack, out_offset, vector.x); - else if (vector_index == 1) + else if(vector_index == 1) stack_store_float(stack, out_offset, vector.y); else stack_store_float(stack, out_offset, vector.z); diff --git a/intern/cycles/kernel/svm/svm_texture.h b/intern/cycles/kernel/svm/svm_texture.h index c5dc213c82d..2e06bbe8499 100644 --- a/intern/cycles/kernel/svm/svm_texture.h +++ b/intern/cycles/kernel/svm/svm_texture.h @@ -129,9 +129,9 @@ ccl_device float voronoi_F1_distance(float3 p) #ifndef __KERNEL_SSE2__ int ix = floor_to_int(p.x), iy = floor_to_int(p.y), iz = floor_to_int(p.z); - for (int xx = -1; xx <= 1; xx++) { - for (int yy = -1; yy <= 1; yy++) { - for (int zz = -1; zz <= 1; zz++) { + for(int xx = -1; xx <= 1; xx++) { + for(int yy = -1; yy <= 1; yy++) { + for(int zz = -1; zz <= 1; zz++) { float3 ip = make_float3(ix + xx, iy + yy, iz + zz); float3 vp = ip + cellnoise_color(ip); float d = len_squared(p - vp); @@ -143,9 +143,9 @@ ccl_device float voronoi_F1_distance(float3 p) ssef vec_p = load4f(p); ssei xyzi = quick_floor_sse(vec_p); - for (int xx = -1; xx <= 1; xx++) { - for (int yy = -1; yy <= 1; yy++) { - for (int zz = -1; zz <= 1; zz++) { + for(int xx = -1; xx <= 1; xx++) { + for(int yy = -1; yy <= 1; yy++) { + for(int zz = -1; zz <= 1; zz++) { ssef ip = ssef(xyzi + ssei(xx, yy, zz, 0)); ssef vp = ip + cellnoise_color(ip); float d = len_squared<1, 1, 1, 0>(vec_p - vp); @@ -167,9 +167,9 @@ ccl_device float3 voronoi_F1_color(float3 p) float3 pa; int ix = floor_to_int(p.x), iy = floor_to_int(p.y), iz = floor_to_int(p.z); - for (int xx = -1; xx <= 1; xx++) { - for (int yy = -1; yy <= 1; yy++) { - for (int zz = -1; zz <= 1; zz++) { + for(int xx = -1; xx <= 1; xx++) { + for(int yy = -1; yy <= 1; yy++) { + for(int zz = -1; zz <= 1; zz++) { float3 ip = make_float3(ix + xx, iy + yy, iz + zz); float3 vp = ip + cellnoise_color(ip); float d = len_squared(p - vp); @@ -187,9 +187,9 @@ ccl_device float3 voronoi_F1_color(float3 p) ssef pa, vec_p = load4f(p); ssei xyzi = quick_floor_sse(vec_p); - for (int xx = -1; xx <= 1; xx++) { - for (int yy = -1; yy <= 1; yy++) { - for (int zz = -1; zz <= 1; zz++) { + for(int xx = -1; xx <= 1; xx++) { + for(int yy = -1; yy <= 1; yy++) { + for(int zz = -1; zz <= 1; zz++) { ssef ip = ssef(xyzi + ssei(xx, yy, zz, 0)); ssef vp = ip + cellnoise_color(ip); float d = len_squared<1, 1, 1, 0>(vec_p - vp); diff --git a/intern/cycles/kernel/svm/svm_vector_transform.h b/intern/cycles/kernel/svm/svm_vector_transform.h index a16786f3ed3..4e92f27acdb 100644 --- a/intern/cycles/kernel/svm/svm_vector_transform.h +++ b/intern/cycles/kernel/svm/svm_vector_transform.h @@ -45,7 +45,7 @@ ccl_device void svm_node_vector_transform(KernelGlobals *kg, ShaderData *sd, flo else in = transform_point(&tfm, in); } - else if (to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT && is_object) { + else if(to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT && is_object) { if(is_direction) object_inverse_dir_transform(kg, sd, &in); else @@ -54,7 +54,7 @@ ccl_device void svm_node_vector_transform(KernelGlobals *kg, ShaderData *sd, flo } /* From camera */ - else if (from == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA) { + else if(from == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA) { if(to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD || to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT) { tfm = kernel_data.cam.cameratoworld; if(is_direction) diff --git a/intern/cycles/kernel/svm/svm_wavelength.h b/intern/cycles/kernel/svm/svm_wavelength.h index 9e57c470c0f..57030f3979d 100644 --- a/intern/cycles/kernel/svm/svm_wavelength.h +++ b/intern/cycles/kernel/svm/svm_wavelength.h @@ -77,7 +77,7 @@ ccl_device void svm_node_wavelength(ShaderData *sd, float *stack, uint wavelengt int i = float_to_int(ii); float3 color; - if (i < 0 || i >= 80) { + if(i < 0 || i >= 80) { color = make_float3(0.0f, 0.0f, 0.0f); } else { diff --git a/intern/cycles/kernel/svm/svm_wireframe.h b/intern/cycles/kernel/svm/svm_wireframe.h index 42fe3e8e429..eaa17f8ce57 100644 --- a/intern/cycles/kernel/svm/svm_wireframe.h +++ b/intern/cycles/kernel/svm/svm_wireframe.h @@ -41,9 +41,9 @@ ccl_device float wireframe(KernelGlobals *kg, float3 *P) { #ifdef __HAIR__ - if (sd->prim != PRIM_NONE && sd->type & PRIMITIVE_ALL_TRIANGLE) + if(sd->prim != PRIM_NONE && sd->type & PRIMITIVE_ALL_TRIANGLE) #else - if (sd->prim != PRIM_NONE) + if(sd->prim != PRIM_NONE) #endif { float3 Co[3]; @@ -76,7 +76,7 @@ ccl_device float wireframe(KernelGlobals *kg, // other half. And take the square for fast comparison pixelwidth *= 0.5f * size; pixelwidth *= pixelwidth; - for (int i = 0; i < np; i++) { + for(int i = 0; i < np; i++) { int i2 = i ? i - 1 : np - 1; float3 dir = *P - Co[i]; float3 edge = Co[i] - Co[i2]; @@ -84,7 +84,7 @@ ccl_device float wireframe(KernelGlobals *kg, // At this point dot(crs, crs) / dot(edge, edge) is // the square of area / length(edge) == square of the // distance to the edge. - if (dot(crs, crs) < (dot(edge, edge) * pixelwidth)) + if(dot(crs, crs) < (dot(edge, edge) * pixelwidth)) return 1.0f; } } @@ -113,12 +113,12 @@ ccl_device void svm_node_wireframe(KernelGlobals *kg, float3 Px = sd->P - sd->dP.dx; f += (f - wireframe(kg, sd, size, pixel_size, &Px)) / len(sd->dP.dx); } - else if (bump_offset == NODE_BUMP_OFFSET_DY) { + else if(bump_offset == NODE_BUMP_OFFSET_DY) { float3 Py = sd->P - sd->dP.dy; f += (f - wireframe(kg, sd, size, pixel_size, &Py)) / len(sd->dP.dy); } - if (stack_valid(out_fac)) + if(stack_valid(out_fac)) stack_store_float(stack, out_fac, f); } diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index 656420f5dbc..6e94459da55 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -52,7 +52,7 @@ void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_) void Attribute::reserve(int numverts, int numtris, int numsteps, int numcurves, int numkeys, bool resize) { - if (resize) { + if(resize) { buffer.resize(buffer_size(numverts, numtris, numsteps, numcurves, numkeys), 0); } else { diff --git a/intern/cycles/render/blackbody.cpp b/intern/cycles/render/blackbody.cpp index 04e6eaf5373..9f77f69a964 100644 --- a/intern/cycles/render/blackbody.cpp +++ b/intern/cycles/render/blackbody.cpp @@ -99,14 +99,14 @@ vector blackbody_table_build() float X, Y, Z; /* ToDo: bring this back to what OSL does with the lastTemperature limit ? */ - for (int i = 0; i <= 317; ++i) { + for(int i = 0; i <= 317; ++i) { double Temperature = pow((double)i, (double)BB_TABLE_XPOWER) * (double)BB_TABLE_SPACING + (double)BB_DRAPER; X = 0; Y = 0; Z = 0; /* from OSL "spectrum_to_XYZ" */ - for (int n = 0; n < 81; ++n) { + for(int n = 0; n < 81; ++n) { float lambda = 380.0f + 5.0f * n; double wlm = lambda * 1e-9f; // Wavelength in meters // N.B. spec_intens returns result in W/m^2 but it's a differential, diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 74648a71fe0..80101a81bfd 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -179,7 +179,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) update(); - if (previous_need_motion != need_motion) { + if(previous_need_motion != need_motion) { /* scene's motion model could have been changed since previous device * camera update this could happen for example in case when one render * layer has got motion pass and another not */ @@ -368,7 +368,7 @@ float3 Camera::transform_raster_to_world(float raster_x, float raster_y) */ P += nearclip * D / Pclip.z; } - else if (type == CAMERA_ORTHOGRAPHIC) { + else if(type == CAMERA_ORTHOGRAPHIC) { D = make_float3(0.0f, 0.0f, 1.0f); /* TODO(sergey): Aperture support? */ P = transform_perspective(&rastertocamera, diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index c220a126f1a..1d453164aa8 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -210,11 +210,11 @@ void Mesh::compute_bounds() bnds.grow(float4_to_float3(curve_keys[i]), curve_keys[i].w); Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - if (use_motion_blur && attr) { + if(use_motion_blur && attr) { size_t steps_size = verts.size() * (motion_steps - 1); float3 *vert_steps = attr->data_float3(); - for (size_t i = 0; i < steps_size; i++) + for(size_t i = 0; i < steps_size; i++) bnds.grow(vert_steps[i]); } @@ -223,7 +223,7 @@ void Mesh::compute_bounds() size_t steps_size = curve_keys.size() * (motion_steps - 1); float3 *key_steps = curve_attr->data_float3(); - for (size_t i = 0; i < steps_size; i++) + for(size_t i = 0; i < steps_size; i++) bnds.grow(key_steps[i]); } @@ -237,19 +237,19 @@ void Mesh::compute_bounds() for(size_t i = 0; i < curve_keys_size; i++) bnds.grow_safe(float4_to_float3(curve_keys[i]), curve_keys[i].w); - if (use_motion_blur && attr) { + if(use_motion_blur && attr) { size_t steps_size = verts.size() * (motion_steps - 1); float3 *vert_steps = attr->data_float3(); - for (size_t i = 0; i < steps_size; i++) + for(size_t i = 0; i < steps_size; i++) bnds.grow_safe(vert_steps[i]); } - if (use_motion_blur && curve_attr) { + if(use_motion_blur && curve_attr) { size_t steps_size = curve_keys.size() * (motion_steps - 1); float3 *key_steps = curve_attr->data_float3(); - for (size_t i = 0; i < steps_size; i++) + for(size_t i = 0; i < steps_size; i++) bnds.grow_safe(key_steps[i]); } } diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index b41f4b511b3..a62634efa42 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -227,7 +227,7 @@ void ImageTextureNode::attributes(Shader *shader, AttributeRequestSet *attribute #ifdef WITH_PTEX /* todo: avoid loading other texture coordinates when using ptex, * and hide texture coordinate socket in the UI */ - if (shader->has_surface && string_endswith(filename, ".ptx")) { + if(shader->has_surface && string_endswith(filename, ".ptx")) { /* ptex */ attributes->add(ATTR_STD_PTEX_FACE_ID); attributes->add(ATTR_STD_PTEX_UV); @@ -417,7 +417,7 @@ ShaderNode *EnvironmentTextureNode::clone() const void EnvironmentTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes) { #ifdef WITH_PTEX - if (shader->has_surface && string_endswith(filename, ".ptx")) { + if(shader->has_surface && string_endswith(filename, ".ptx")) { /* ptex */ attributes->add(ATTR_STD_PTEX_FACE_ID); attributes->add(ATTR_STD_PTEX_UV); @@ -632,7 +632,7 @@ static void sky_texture_precompute_new(SunSky *sunsky, float3 dir, float turbidi sky_state = arhosek_xyz_skymodelstate_alloc_init(turbidity, ground_albedo, solarElevation); /* Copy values from sky_state to SunSky */ - for (int i = 0; i < 9; ++i) { + for(int i = 0; i < 9; ++i) { sunsky->config_x[i] = (float)sky_state->configs[0][i]; sunsky->config_y[i] = (float)sky_state->configs[1][i]; sunsky->config_z[i] = (float)sky_state->configs[2][i]; @@ -2442,7 +2442,7 @@ void UVMapNode::attributes(Shader *shader, AttributeRequestSet *attributes) if(shader->has_surface) { if(!from_dupli) { if(!output("UV")->links.empty()) { - if (attribute != "") + if(attribute != "") attributes->add(attribute); else attributes->add(ATTR_STD_UV); @@ -2475,7 +2475,7 @@ void UVMapNode::compile(SVMCompiler& compiler) compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, out->stack_offset); } else { - if (attribute != "") + if(attribute != "") attr = compiler.attribute(attribute); else attr = compiler.attribute(ATTR_STD_UV); @@ -3987,7 +3987,7 @@ void RGBCurvesNode::compile(OSLCompiler& compiler) { float ramp[RAMP_TABLE_SIZE][3]; - for (int i = 0; i < RAMP_TABLE_SIZE; ++i) { + for(int i = 0; i < RAMP_TABLE_SIZE; ++i) { ramp[i][0] = curves[i].x; ramp[i][1] = curves[i].y; ramp[i][2] = curves[i].z; @@ -4025,7 +4025,7 @@ void VectorCurvesNode::compile(OSLCompiler& compiler) { float ramp[RAMP_TABLE_SIZE][3]; - for (int i = 0; i < RAMP_TABLE_SIZE; ++i) { + for(int i = 0; i < RAMP_TABLE_SIZE; ++i) { ramp[i][0] = curves[i].x; ramp[i][1] = curves[i].y; ramp[i][2] = curves[i].z; @@ -4075,7 +4075,7 @@ void RGBRampNode::compile(OSLCompiler& compiler) float ramp_color[RAMP_TABLE_SIZE][3]; float ramp_alpha[RAMP_TABLE_SIZE]; - for (int i = 0; i < RAMP_TABLE_SIZE; ++i) { + for(int i = 0; i < RAMP_TABLE_SIZE; ++i) { ramp_color[i][0] = ramp[i].x; ramp_color[i][1] = ramp[i].y; ramp_color[i][2] = ramp[i].z; diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 840f706f23b..a1d0439c0d7 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -104,11 +104,11 @@ void Object::apply_transform(bool apply_to_motion) if(apply_to_motion) { Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - if (attr) { + if(attr) { size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1); float3 *vert_steps = attr->data_float3(); - for (size_t i = 0; i < steps_size; i++) + for(size_t i = 0; i < steps_size; i++) vert_steps[i] = transform_point(&tfm, vert_steps[i]); } @@ -119,7 +119,7 @@ void Object::apply_transform(bool apply_to_motion) size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1); float3 *normal_steps = attr_N->data_float3(); - for (size_t i = 0; i < steps_size; i++) + for(size_t i = 0; i < steps_size; i++) normal_steps[i] = normalize(transform_direction(&ntfm, normal_steps[i])); } } @@ -146,12 +146,12 @@ void Object::apply_transform(bool apply_to_motion) if(apply_to_motion) { Attribute *curve_attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - if (curve_attr) { + if(curve_attr) { /* apply transform to motion curve keys */ size_t steps_size = mesh->curve_keys.size() * (mesh->motion_steps - 1); float4 *key_steps = curve_attr->data_float4(); - for (size_t i = 0; i < steps_size; i++) { + for(size_t i = 0; i < steps_size; i++) { float3 co = transform_point(&tfm, float4_to_float3(key_steps[i])); float radius = key_steps[i].w * scalar; diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 41844ae219f..679d54d1d1e 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -414,7 +414,7 @@ string OSLCompiler::compatible_name(ShaderNode *node, ShaderInput *input) /* if output exists with the same name, add "In" suffix */ foreach(ShaderOutput *output, node->outputs) { - if (strcmp(input->name, output->name)==0) { + if(strcmp(input->name, output->name)==0) { sname += "In"; break; } @@ -434,7 +434,7 @@ string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output) /* if input exists with the same name, add "Out" suffix */ foreach(ShaderInput *input, node->inputs) { - if (strcmp(input->name, output->name)==0) { + if(strcmp(input->name, output->name)==0) { sname += "Out"; break; } diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 99826aa4349..65b73eb2ad3 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -889,9 +889,9 @@ bool Session::update_progressive_refine(bool cancel) double current_time = time_dt(); - if (current_time - last_update_time < params.progressive_update_timeout) { + if(current_time - last_update_time < params.progressive_update_timeout) { /* if last sample was processed, we need to write buffers anyway */ - if (!write) + if(!write) return false; } diff --git a/intern/cycles/render/sky_model.cpp b/intern/cycles/render/sky_model.cpp index adb07d9e288..f5fac6be3ed 100644 --- a/intern/cycles/render/sky_model.cpp +++ b/intern/cycles/render/sky_model.cpp @@ -312,7 +312,7 @@ double arhosekskymodel_radiance( { int low_wl = (int)((wavelength - 320.0) / 40.0); - if ( low_wl < 0 || low_wl >= 11 ) + if( low_wl < 0 || low_wl >= 11 ) return 0.0f; double interp = fmod((wavelength - 320.0 ) / 40.0, 1.0); @@ -326,12 +326,12 @@ double arhosekskymodel_radiance( * state->radiances[low_wl] * state->emission_correction_factor_sky[low_wl]; - if ( interp < 1e-6 ) + if( interp < 1e-6 ) return val_low; double result = ( 1.0 - interp ) * val_low; - if ( low_wl+1 < 11 ) + if( low_wl+1 < 11 ) { result += interp diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index b1cad98a852..7e68ce84d94 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -235,7 +235,7 @@ bool TileManager::next_tile(Tile& tile, int device) { list::iterator tile_it; - if (background) + if(background) tile_it = next_background_tile(device, tile_order); else tile_it = next_viewport_tile(device); diff --git a/intern/cycles/subd/subd_mesh.cpp b/intern/cycles/subd/subd_mesh.cpp index 0db20656f39..17a730e5efe 100644 --- a/intern/cycles/subd/subd_mesh.cpp +++ b/intern/cycles/subd/subd_mesh.cpp @@ -109,8 +109,8 @@ public: evalctrl.EvalLimitSample(coords, evalctx, 0); *P_ = make_float3(P[0], P[1], P[2]); - if (dPdu_) *dPdu_ = make_float3(dPdv[0], dPdv[1], dPdv[2]); - if (dPdv_) *dPdv_ = make_float3(dPdu[0], dPdu[1], dPdu[2]); + if(dPdu_) *dPdu_ = make_float3(dPdv[0], dPdv[1], dPdv[2]); + if(dPdv_) *dPdv_ = make_float3(dPdu[0], dPdu[1], dPdu[2]); /* optimize: skip evaluating derivatives when not needed */ /* todo: swapped derivatives, different winding convention? */ @@ -234,7 +234,7 @@ bool OpenSubdMesh::finish() void OpenSubdMesh::tessellate(DiagSplit *split) { - if (num_ptex_faces == 0) + if(num_ptex_faces == 0) return; const int level = 3; diff --git a/intern/cycles/util/util_aligned_malloc.cpp b/intern/cycles/util/util_aligned_malloc.cpp index 9ff857e3543..b161a55c15e 100644 --- a/intern/cycles/util/util_aligned_malloc.cpp +++ b/intern/cycles/util/util_aligned_malloc.cpp @@ -55,7 +55,7 @@ void *util_aligned_malloc(size_t size, int alignment) return malloc(size); #elif defined(__FreeBSD__) || defined(__NetBSD__) void *result; - if (posix_memalign(&result, alignment, size)) { + if(posix_memalign(&result, alignment, size)) { /* Non-zero means allocation error * either no allocation or bad alignment value. */ diff --git a/intern/cycles/util/util_atomic.h b/intern/cycles/util/util_atomic.h index 7bbd97b8667..fa0d35e1034 100644 --- a/intern/cycles/util/util_atomic.h +++ b/intern/cycles/util/util_atomic.h @@ -23,8 +23,8 @@ ATOMIC_INLINE void atomic_update_max_z(size_t *maximum_value, size_t value) { size_t prev_value = *maximum_value; - while (prev_value < value) { - if (atomic_cas_z(maximum_value, prev_value, value) != prev_value) { + while(prev_value < value) { + if(atomic_cas_z(maximum_value, prev_value, value) != prev_value) { break; } } diff --git a/intern/cycles/util/util_hash.h b/intern/cycles/util/util_hash.h index bbbedc22a47..3ff2802b46d 100644 --- a/intern/cycles/util/util_hash.h +++ b/intern/cycles/util/util_hash.h @@ -53,7 +53,7 @@ static inline uint hash_string(const char *str) { uint i = 0, c; - while ((c = *str++)) + while((c = *str++)) i = i * 37 + c; return i; diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index a4d49681a38..6208608a233 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -1461,7 +1461,7 @@ ccl_device_inline float2 map_to_tube(const float3 co) { float len, u, v; len = sqrtf(co.x * co.x + co.y * co.y); - if (len > 0.0f) { + if(len > 0.0f) { u = (1.0f - (atan2f(co.x / len, co.y / len) / M_PI_F)) * 0.5f; v = (co.x + 1.0f) * 0.5f; } diff --git a/intern/cycles/util/util_simd.h b/intern/cycles/util/util_simd.h index 625f26c1316..7c15199d4e1 100644 --- a/intern/cycles/util/util_simd.h +++ b/intern/cycles/util/util_simd.h @@ -133,7 +133,7 @@ __forceinline int clz(const int x) #if defined(__KERNEL_AVX2__) return _lzcnt_u32(x); #else - if (UNLIKELY(x == 0)) return 32; + if(UNLIKELY(x == 0)) return 32; return 31 - __bsr(x); #endif } @@ -286,7 +286,7 @@ __forceinline int clz(const int x) #if defined(__KERNEL_AVX2__) return _lzcnt_u32(x); #else - if (UNLIKELY(x == 0)) return 32; + if(UNLIKELY(x == 0)) return 32; return 31 - __bsr(x); #endif } @@ -358,7 +358,7 @@ __forceinline __m128i _mm_mullo_epi32( __m128i value, __m128i input ) { char* _r = (char*)(&rvalue + 1); char* _v = (char*)(& value + 1); char* _i = (char*)(& input + 1); - for ( ssize_t i = -16 ; i != 0 ; i += 4 ) *((int32*)(_r + i)) = *((int32*)(_v + i))* *((int32*)(_i + i)); + for( ssize_t i = -16 ; i != 0 ; i += 4 ) *((int32*)(_r + i)) = *((int32*)(_v + i))* *((int32*)(_i + i)); return rvalue; } diff --git a/intern/cycles/util/util_time.cpp b/intern/cycles/util/util_time.cpp index 9668b0f9882..964f9f1a7af 100644 --- a/intern/cycles/util/util_time.cpp +++ b/intern/cycles/util/util_time.cpp @@ -71,7 +71,7 @@ void time_sleep(double t) /* get microseconds */ int us = (int)(t * 1e6); - if (us > 0) + if(us > 0) usleep(us); } -- cgit v1.2.3 From e1bcc2d77989453c95cc3fdbd017371748bf8ea7 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 28 Mar 2015 00:28:37 +0500 Subject: Cycles: Code cleanyp, sky model For as long as code stays in official folders it should follow our code style. --- intern/cycles/render/sky_model.cpp | 433 ++++++++++++++++------------------ intern/cycles/render/sky_model.h | 296 +++++++++++------------ intern/cycles/render/sky_model_data.h | 29 +-- 3 files changed, 362 insertions(+), 396 deletions(-) diff --git a/intern/cycles/render/sky_model.cpp b/intern/cycles/render/sky_model.cpp index f5fac6be3ed..c8a5dbe55e0 100644 --- a/intern/cycles/render/sky_model.cpp +++ b/intern/cycles/render/sky_model.cpp @@ -4,7 +4,7 @@ This source is published under the following 3-clause BSD license. Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie All rights reserved. -Redistribution and use in source and binary forms, with or without +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright @@ -12,8 +12,8 @@ modification, are permitted provided that the following conditions are met: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * None of the names of the contributors may be used to endorse or promote - products derived from this software without specific prior written + * None of the names of the contributors may be used to endorse or promote + products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND @@ -40,24 +40,24 @@ and the 2013 IEEE CG&A paper "Adding a Solar Radiance Function to the Hosek Skylight Model" - both by + both by Lukas Hosek and Alexander Wilkie Charles University in Prague, Czech Republic Version: 1.4a, February 22nd, 2013 - + Version history: 1.4a February 22nd, 2013 - Removed unnecessary and counter-intuitive solar radius parameters + Removed unnecessary and counter-intuitive solar radius parameters from the interface of the colourspace sky dome initialisation functions. 1.4 February 11th, 2013 Fixed a bug which caused the relative brightness of the solar disc - and the sky dome to be off by a factor of about 6. The sun was too - bright: this affected both normal and alien sun scenarios. The + and the sky dome to be off by a factor of about 6. The sun was too + bright: this affected both normal and alien sun scenarios. The coefficients of the solar radiance function were changed to fix this. 1.3 January 21st, 2013 (not released to the public) @@ -81,7 +81,7 @@ Version history: the result of a simple conversion from spectral data via the CIE 2 degree standard observer matching functions. Therefore, after multiplication with 683 lm / W, the Y channel now corresponds to luminance in lm. - + 1.0 May 11th, 2012 Initial release. @@ -110,7 +110,7 @@ CCL_NAMESPACE_BEGIN // Some macro definitions that occur elsewhere in ART, and that have to be // replicated to make this a stand-alone module. -#ifndef MATH_PI +#ifndef MATH_PI #define MATH_PI 3.141592653589793 #endif @@ -138,250 +138,231 @@ typedef const double *ArHosekSkyModel_Radiance_Dataset; // internal functions static void ArHosekSkyModel_CookConfiguration( - ArHosekSkyModel_Dataset dataset, - ArHosekSkyModelConfiguration config, - double turbidity, - double albedo, - double solar_elevation - ) + ArHosekSkyModel_Dataset dataset, + ArHosekSkyModelConfiguration config, + double turbidity, + double albedo, + double solar_elevation) { - const double * elev_matrix; - - int int_turbidity = (int)turbidity; - double turbidity_rem = turbidity - (double)int_turbidity; - - solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0)); - - // alb 0 low turb - - elev_matrix = dataset + ( 9 * 6 * (int_turbidity-1) ); - - - for( unsigned int i = 0; i < 9; ++i ) - { - //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; - config[i] = - (1.0-albedo) * (1.0 - turbidity_rem) - * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] + - 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] + - 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] + - 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] + - 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] + - pow(solar_elevation, 5.0) * elev_matrix[i+45]); - } + const double * elev_matrix; - // alb 1 low turb - elev_matrix = dataset + (9*6*10 + 9*6*(int_turbidity-1)); - for(unsigned int i = 0; i < 9; ++i) - { - //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; - config[i] += - (albedo) * (1.0 - turbidity_rem) - * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] + - 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] + - 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] + - 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] + - 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] + - pow(solar_elevation, 5.0) * elev_matrix[i+45]); - } + int int_turbidity = (int)turbidity; + double turbidity_rem = turbidity - (double)int_turbidity; - if(int_turbidity == 10) - return; - - // alb 0 high turb - elev_matrix = dataset + (9*6*(int_turbidity)); - for(unsigned int i = 0; i < 9; ++i) - { - //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; - config[i] += - (1.0-albedo) * (turbidity_rem) - * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] + - 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] + - 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] + - 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] + - 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] + - pow(solar_elevation, 5.0) * elev_matrix[i+45]); - } + solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0)); + + // alb 0 low turb - // alb 1 high turb - elev_matrix = dataset + (9*6*10 + 9*6*(int_turbidity)); - for(unsigned int i = 0; i < 9; ++i) - { - //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; - config[i] += - (albedo) * (turbidity_rem) - * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] + - 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] + - 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] + - 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] + - 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] + - pow(solar_elevation, 5.0) * elev_matrix[i+45]); + elev_matrix = dataset + ( 9 * 6 * (int_turbidity-1)); + + for(unsigned int i = 0; i < 9; ++i) { + //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; + config[i] = + (1.0-albedo) * (1.0 - turbidity_rem) + * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] + + 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] + + 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] + + 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] + + 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] + + pow(solar_elevation, 5.0) * elev_matrix[i+45]); } + + // alb 1 low turb + elev_matrix = dataset + (9*6*10 + 9*6*(int_turbidity-1)); + for(unsigned int i = 0; i < 9; ++i) { + //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; + config[i] += + (albedo) * (1.0 - turbidity_rem) + * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] + + 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] + + 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] + + 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] + + 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] + + pow(solar_elevation, 5.0) * elev_matrix[i+45]); + } + + if(int_turbidity == 10) + return; + + // alb 0 high turb + elev_matrix = dataset + (9*6*(int_turbidity)); + for(unsigned int i = 0; i < 9; ++i) { + //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; + config[i] += + (1.0-albedo) * (turbidity_rem) + * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] + + 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] + + 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] + + 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] + + 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] + + pow(solar_elevation, 5.0) * elev_matrix[i+45]); + } + + // alb 1 high turb + elev_matrix = dataset + (9*6*10 + 9*6*(int_turbidity)); + for(unsigned int i = 0; i < 9; ++i) { + //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; + config[i] += + (albedo) * (turbidity_rem) + * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] + + 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] + + 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] + + 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] + + 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] + + pow(solar_elevation, 5.0) * elev_matrix[i+45]); + } } static double ArHosekSkyModel_CookRadianceConfiguration( - ArHosekSkyModel_Radiance_Dataset dataset, - double turbidity, - double albedo, - double solar_elevation - ) + ArHosekSkyModel_Radiance_Dataset dataset, + double turbidity, + double albedo, + double solar_elevation) { - const double* elev_matrix; - - int int_turbidity = (int)turbidity; - double turbidity_rem = turbidity - (double)int_turbidity; - double res; - solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0)); - - // alb 0 low turb - elev_matrix = dataset + (6*(int_turbidity-1)); - //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; - res = (1.0-albedo) * (1.0 - turbidity_rem) * - ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] + - 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] + - 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] + - 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] + - 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] + - pow(solar_elevation, 5.0) * elev_matrix[5]); - - // alb 1 low turb - elev_matrix = dataset + (6*10 + 6*(int_turbidity-1)); - //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; - res += (albedo) * (1.0 - turbidity_rem) * - ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] + - 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] + - 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] + - 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] + - 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] + - pow(solar_elevation, 5.0) * elev_matrix[5]); - if(int_turbidity == 10) - return res; - - // alb 0 high turb - elev_matrix = dataset + (6*(int_turbidity)); - //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; - res += (1.0-albedo) * (turbidity_rem) * - ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] + - 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] + - 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] + - 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] + - 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] + - pow(solar_elevation, 5.0) * elev_matrix[5]); - - // alb 1 high turb - elev_matrix = dataset + (6*10 + 6*(int_turbidity)); - //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; - res += (albedo) * (turbidity_rem) * - ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] + - 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] + - 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] + - 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] + - 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] + - pow(solar_elevation, 5.0) * elev_matrix[5]); - return res; + const double* elev_matrix; + + int int_turbidity = (int)turbidity; + double turbidity_rem = turbidity - (double)int_turbidity; + double res; + solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0)); + + // alb 0 low turb + elev_matrix = dataset + (6*(int_turbidity-1)); + //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; + res = (1.0-albedo) * (1.0 - turbidity_rem) * + ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] + + 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] + + 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] + + 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] + + 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] + + pow(solar_elevation, 5.0) * elev_matrix[5]); + + // alb 1 low turb + elev_matrix = dataset + (6*10 + 6*(int_turbidity-1)); + //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; + res += (albedo) * (1.0 - turbidity_rem) * + ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] + + 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] + + 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] + + 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] + + 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] + + pow(solar_elevation, 5.0) * elev_matrix[5]); + if(int_turbidity == 10) + return res; + + // alb 0 high turb + elev_matrix = dataset + (6*(int_turbidity)); + //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; + res += (1.0-albedo) * (turbidity_rem) * + ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] + + 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] + + 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] + + 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] + + 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] + + pow(solar_elevation, 5.0) * elev_matrix[5]); + + // alb 1 high turb + elev_matrix = dataset + (6*10 + 6*(int_turbidity)); + //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; + res += (albedo) * (turbidity_rem) * + ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] + + 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] + + 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] + + 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] + + 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] + + pow(solar_elevation, 5.0) * elev_matrix[5]); + return res; } static double ArHosekSkyModel_GetRadianceInternal( - ArHosekSkyModelConfiguration configuration, - double theta, - double gamma - ) + ArHosekSkyModelConfiguration configuration, + double theta, + double gamma) { - const double expM = exp(configuration[4] * gamma); - const double rayM = cos(gamma)*cos(gamma); - const double mieM = (1.0 + cos(gamma)*cos(gamma)) / pow((1.0 + configuration[8]*configuration[8] - 2.0*configuration[8]*cos(gamma)), 1.5); - const double zenith = sqrt(cos(theta)); + const double expM = exp(configuration[4] * gamma); + const double rayM = cos(gamma)*cos(gamma); + const double mieM = (1.0 + cos(gamma)*cos(gamma)) / pow((1.0 + configuration[8]*configuration[8] - 2.0*configuration[8]*cos(gamma)), 1.5); + const double zenith = sqrt(cos(theta)); - return (1.0 + configuration[0] * exp(configuration[1] / (cos(theta) + 0.01))) * + return (1.0 + configuration[0] * exp(configuration[1] / (cos(theta) + 0.01))) * (configuration[2] + configuration[3] * expM + configuration[5] * rayM + configuration[6] * mieM + configuration[7] * zenith); } -void arhosekskymodelstate_free( - ArHosekSkyModelState * state - ) +void arhosekskymodelstate_free(ArHosekSkyModelState * state) { - free(state); + free(state); } -double arhosekskymodel_radiance( - ArHosekSkyModelState * state, - double theta, - double gamma, - double wavelength - ) +double arhosekskymodel_radiance(ArHosekSkyModelState *state, + double theta, + double gamma, + double wavelength) { - int low_wl = (int)((wavelength - 320.0) / 40.0); - - if( low_wl < 0 || low_wl >= 11 ) - return 0.0f; - - double interp = fmod((wavelength - 320.0 ) / 40.0, 1.0); - - double val_low = - ArHosekSkyModel_GetRadianceInternal( - state->configs[low_wl], - theta, - gamma - ) - * state->radiances[low_wl] - * state->emission_correction_factor_sky[low_wl]; - - if( interp < 1e-6 ) - return val_low; - - double result = ( 1.0 - interp ) * val_low; - - if( low_wl+1 < 11 ) - { - result += - interp - * ArHosekSkyModel_GetRadianceInternal( - state->configs[low_wl+1], - theta, - gamma - ) - * state->radiances[low_wl+1] - * state->emission_correction_factor_sky[low_wl+1]; - } - - return result; + int low_wl = (int)((wavelength - 320.0) / 40.0); + + if(low_wl < 0 || low_wl >= 11) + return 0.0f; + + double interp = fmod((wavelength - 320.0 ) / 40.0, 1.0); + + double val_low = + ArHosekSkyModel_GetRadianceInternal( + state->configs[low_wl], + theta, + gamma) + * state->radiances[low_wl] + * state->emission_correction_factor_sky[low_wl]; + + if(interp < 1e-6) + return val_low; + + double result = ( 1.0 - interp ) * val_low; + + if(low_wl+1 < 11) { + result += + interp + * ArHosekSkyModel_GetRadianceInternal( + state->configs[low_wl+1], + theta, + gamma) + * state->radiances[low_wl+1] + * state->emission_correction_factor_sky[low_wl+1]; + } + + return result; } // xyz and rgb versions -ArHosekSkyModelState * arhosek_xyz_skymodelstate_alloc_init( - const double turbidity, - const double albedo, - const double elevation - ) +ArHosekSkyModelState * arhosek_xyz_skymodelstate_alloc_init( + const double turbidity, + const double albedo, + const double elevation) { - ArHosekSkyModelState * state = ALLOC(ArHosekSkyModelState); - - state->solar_radius = TERRESTRIAL_SOLAR_RADIUS; - state->turbidity = turbidity; - state->albedo = albedo; - state->elevation = elevation; - - for( unsigned int channel = 0; channel < 3; ++channel ) - { - ArHosekSkyModel_CookConfiguration( - datasetsXYZ[channel], - state->configs[channel], - turbidity, - albedo, - elevation - ); - - state->radiances[channel] = - ArHosekSkyModel_CookRadianceConfiguration( - datasetsXYZRad[channel], - turbidity, - albedo, - elevation - ); + ArHosekSkyModelState * state = ALLOC(ArHosekSkyModelState); + + state->solar_radius = TERRESTRIAL_SOLAR_RADIUS; + state->turbidity = turbidity; + state->albedo = albedo; + state->elevation = elevation; + + for(unsigned int channel = 0; channel < 3; ++channel) { + ArHosekSkyModel_CookConfiguration( + datasetsXYZ[channel], + state->configs[channel], + turbidity, + albedo, + elevation); + + state->radiances[channel] = + ArHosekSkyModel_CookRadianceConfiguration( + datasetsXYZRad[channel], + turbidity, + albedo, + elevation); } - + return state; } diff --git a/intern/cycles/render/sky_model.h b/intern/cycles/render/sky_model.h index 3814543c8b6..237e4e61bf5 100644 --- a/intern/cycles/render/sky_model.h +++ b/intern/cycles/render/sky_model.h @@ -4,7 +4,7 @@ This source is published under the following 3-clause BSD license. Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie All rights reserved. -Redistribution and use in source and binary forms, with or without +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright @@ -12,8 +12,8 @@ modification, are permitted provided that the following conditions are met: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * None of the names of the contributors may be used to endorse or promote - products derived from this software without specific prior written + * None of the names of the contributors may be used to endorse or promote + products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND @@ -41,24 +41,24 @@ and the 2013 IEEE CG&A paper "Adding a Solar Radiance Function to the Hosek Skylight Model" - both by + both by Lukas Hosek and Alexander Wilkie Charles University in Prague, Czech Republic Version: 1.4a, February 22nd, 2013 - + Version history: 1.4a February 22nd, 2013 - Removed unnecessary and counter-intuitive solar radius parameters + Removed unnecessary and counter-intuitive solar radius parameters from the interface of the colourspace sky dome initialisation functions. 1.4 February 11th, 2013 Fixed a bug which caused the relative brightness of the solar disc - and the sky dome to be off by a factor of about 6. The sun was too - bright: this affected both normal and alien sun scenarios. The + and the sky dome to be off by a factor of about 6. The sun was too + bright: this affected both normal and alien sun scenarios. The coefficients of the solar radiance function were changed to fix this. 1.3 January 21st, 2013 (not released to the public) @@ -82,7 +82,7 @@ Version history: the result of a simple conversion from spectral data via the CIE 2 degree standard observer matching functions. Therefore, after multiplication with 683 lm / W, the Y channel now corresponds to luminance in lm. - + 1.0 May 11th, 2012 Initial release. @@ -96,9 +96,9 @@ an updated version of this code has been published! /* This code is taken from ART, a rendering research system written in a -mix of C99 / Objective C. Since ART is not a small system and is intended to -be inter-operable with other libraries, and since C does not have namespaces, -the structures and functions in ART all have to have somewhat wordy +mix of C99 / Objective C. Since ART is not a small system and is intended to +be inter-operable with other libraries, and since C does not have namespaces, +the structures and functions in ART all have to have somewhat wordy canonical names that begin with Ar.../ar..., like those seen in this example. Usage information: @@ -119,7 +119,7 @@ snippet, we assume that 'albedo' is defined as double albedo[num_channels]; -with a ground albedo value between [0,1] for each channel. The solar elevation +with a ground albedo value between [0,1] for each channel. The solar elevation is given in radians. for ( unsigned int i = 0; i < num_channels; i++ ) @@ -130,11 +130,11 @@ is given in radians. solarElevation ); -Note that starting with version 1.3, there is also a second initialisation -function which generates skydome states for different solar emission spectra +Note that starting with version 1.3, there is also a second initialisation +function which generates skydome states for different solar emission spectra and solar radii: 'arhosekskymodelstate_alienworld_alloc_init()'. -See the notes about the "Alien World" functionality provided further down for a +See the notes about the "Alien World" functionality provided further down for a discussion of the usefulness and limits of that second initalisation function. Sky model states that have been initialized with either function behave in a completely identical fashion during use and cleanup. @@ -155,7 +155,7 @@ on the skydome determined via the angles theta and gamma works as follows: gamma, channel_center[i] ); - + The variable "channel_center" is assumed to hold the channel center wavelengths for each of the num_channels samples of the spectrum we are building. @@ -188,114 +188,114 @@ by calling arhosek_rgb_skymodelstate_alloc_init. Solar Radiance Function ----------------------- -For each position on the solar disc, this function returns the entire radiance -one sees - direct emission, as well as in-scattered light in the area of the -solar disc. The latter is important for low solar elevations - nice images of -the setting sun would not be possible without this. This is also the reason why -this function, just like the regular sky dome model evaluation function, needs -access to the sky dome data structures, as these provide information on +For each position on the solar disc, this function returns the entire radiance +one sees - direct emission, as well as in-scattered light in the area of the +solar disc. The latter is important for low solar elevations - nice images of +the setting sun would not be possible without this. This is also the reason why +this function, just like the regular sky dome model evaluation function, needs +access to the sky dome data structures, as these provide information on in-scattered radiance. CAVEAT #1: in this release, this function is only provided in spectral form! RGB/XYZ versions to follow at a later date. -CAVEAT #2: (fixed from release 1.3 onwards) +CAVEAT #2: (fixed from release 1.3 onwards) CAVEAT #3: limb darkening renders the brightness of the solar disc inhomogeneous even for high solar elevations - only taking a single sample at the centre of the sun will yield an incorrect power estimate for the solar disc! Always take multiple random samples across the entire solar disc to estimate its power! - + CAVEAT #4: in this version, the limb darkening calculations still use a fairly - computationally expensive 5th order polynomial that was directly + computationally expensive 5th order polynomial that was directly taken from astronomical literature. For the purposes of Computer - Graphics, this is needlessly accurate, though, and will be replaced + Graphics, this is needlessly accurate, though, and will be replaced by a cheaper approximation in a future release. "Alien World" functionality --------------------------- -The Hosek sky model can be used to roughly (!) predict the appearance of -outdoor scenes on earth-like planets, i.e. planets of a similar size and -atmospheric make-up. Since the spectral version of our model predicts sky dome -luminance patterns and solar radiance independently for each waveband, and -since the intensity of each waveband is solely dependent on the input radiance -from the star that the world in question is orbiting, it is trivial to re-scale +The Hosek sky model can be used to roughly (!) predict the appearance of +outdoor scenes on earth-like planets, i.e. planets of a similar size and +atmospheric make-up. Since the spectral version of our model predicts sky dome +luminance patterns and solar radiance independently for each waveband, and +since the intensity of each waveband is solely dependent on the input radiance +from the star that the world in question is orbiting, it is trivial to re-scale the wavebands to match a different star radiance. -At least in theory, the spectral version of the model has always been capable -of this sort of thing, and the actual sky dome and solar radiance models were +At least in theory, the spectral version of the model has always been capable +of this sort of thing, and the actual sky dome and solar radiance models were actually not altered at all in this release. All we did was to add some support -functionality for doing this more easily with the existing data and functions, +functionality for doing this more easily with the existing data and functions, and to add some explanations. Just use 'arhosekskymodelstate_alienworld_alloc_init()' to initialise the sky -model states (you will have to provide values for star temperature and solar -intensity compared to the terrestrial sun), and do everything else as you +model states (you will have to provide values for star temperature and solar +intensity compared to the terrestrial sun), and do everything else as you did before. -CAVEAT #1: we assume the emission of the star that illuminates the alien world - to be a perfect blackbody emission spectrum. This is never entirely - realistic - real star emission spectra are considerably more complex - than this, mainly due to absorption effects in the outer layers of - stars. However, blackbody spectra are a reasonable first assumption - in a usage scenario like this, where 100% accuracy is simply not - necessary: for rendering purposes, there are likely no visible - differences between a highly accurate solution based on a more +CAVEAT #1: we assume the emission of the star that illuminates the alien world + to be a perfect blackbody emission spectrum. This is never entirely + realistic - real star emission spectra are considerably more complex + than this, mainly due to absorption effects in the outer layers of + stars. However, blackbody spectra are a reasonable first assumption + in a usage scenario like this, where 100% accuracy is simply not + necessary: for rendering purposes, there are likely no visible + differences between a highly accurate solution based on a more involved simulation, and this approximation. CAVEAT #2: we always use limb darkening data from our own sun to provide this - "appearance feature", even for suns of strongly different - temperature. Which is presumably not very realistic, but (as with - the unaltered blackbody spectrum from caveat #1) probably not a bad + "appearance feature", even for suns of strongly different + temperature. Which is presumably not very realistic, but (as with + the unaltered blackbody spectrum from caveat #1) probably not a bad first guess, either. If you need more accuracy than we provide here, please make inquiries with a friendly astro-physicst of your choice. -CAVEAT #3: you have to provide a value for the solar intensity of the star - which illuminates the alien world. For this, please bear in mind - that there is very likely a comparatively tight range of absolute - solar irradiance values for which an earth-like planet with an - atmosphere like the one we assume in our model can exist in the +CAVEAT #3: you have to provide a value for the solar intensity of the star + which illuminates the alien world. For this, please bear in mind + that there is very likely a comparatively tight range of absolute + solar irradiance values for which an earth-like planet with an + atmosphere like the one we assume in our model can exist in the first place! - - Too much irradiance, and the atmosphere probably boils off into - space, too little, it freezes. Which means that stars of - considerably different emission colour than our sun will have to be - fairly different in size from it, to still provide a reasonable and - inhabitable amount of irradiance. Red stars will need to be much - larger than our sun, while white or blue stars will have to be - comparatively tiny. The initialisation function handles this and + + Too much irradiance, and the atmosphere probably boils off into + space, too little, it freezes. Which means that stars of + considerably different emission colour than our sun will have to be + fairly different in size from it, to still provide a reasonable and + inhabitable amount of irradiance. Red stars will need to be much + larger than our sun, while white or blue stars will have to be + comparatively tiny. The initialisation function handles this and computes a plausible solar radius for a given emission spectrum. In terms of absolute radiometric values, you should probably not stray all too far from a solar intensity value of 1.0. -CAVEAT #4: although we now support different solar radii for the actual solar - disc, the sky dome luminance patterns are *not* parameterised by - this value - i.e. the patterns stay exactly the same for different - solar radii! Which is of course not correct. But in our experience, - solar discs up to several degrees in diameter (! - our own sun is - half a degree across) do not cause the luminance patterns on the sky - to change perceptibly. The reason we know this is that we initially - used unrealistically large suns in our brute force path tracer, in - order to improve convergence speeds (which in the beginning were - abysmal). Later, we managed to do the reference renderings much - faster even with realistically small suns, and found that there was - no real difference in skydome appearance anyway. - Conclusion: changing the solar radius should not be over-done, so - close orbits around red supergiants are a no-no. But for the - purposes of getting a fairly credible first impression of what an - alien world with a reasonably sized sun would look like, what we are +CAVEAT #4: although we now support different solar radii for the actual solar + disc, the sky dome luminance patterns are *not* parameterised by + this value - i.e. the patterns stay exactly the same for different + solar radii! Which is of course not correct. But in our experience, + solar discs up to several degrees in diameter (! - our own sun is + half a degree across) do not cause the luminance patterns on the sky + to change perceptibly. The reason we know this is that we initially + used unrealistically large suns in our brute force path tracer, in + order to improve convergence speeds (which in the beginning were + abysmal). Later, we managed to do the reference renderings much + faster even with realistically small suns, and found that there was + no real difference in skydome appearance anyway. + Conclusion: changing the solar radius should not be over-done, so + close orbits around red supergiants are a no-no. But for the + purposes of getting a fairly credible first impression of what an + alien world with a reasonably sized sun would look like, what we are doing here is probably still o.k. -HINT #1: if you want to model the sky of an earth-like planet that orbits - a binary star, just super-impose two of these models with solar +HINT #1: if you want to model the sky of an earth-like planet that orbits + a binary star, just super-impose two of these models with solar intensity of ~0.5 each, and closely spaced solar positions. Light is additive, after all. Tattooine, here we come... :-) P.S. according to Star Wars canon, Tattooine orbits a binary - that is made up of a G and K class star, respectively. - So ~5500K and ~4200K should be good first guesses for their + that is made up of a G and K class star, respectively. + So ~5500K and ~4200K should be good first guesses for their temperature. Just in case you were wondering, after reading the previous paragraph. */ @@ -316,37 +316,37 @@ typedef double ArHosekSkyModelConfiguration[9]; --------------------------- This struct holds the pre-computation data for one particular albedo value. - Most fields are self-explanatory, but users should never directly - manipulate any of them anyway. The only consistent way to manipulate such - structs is via the functions 'arhosekskymodelstate_alloc_init' and + Most fields are self-explanatory, but users should never directly + manipulate any of them anyway. The only consistent way to manipulate such + structs is via the functions 'arhosekskymodelstate_alloc_init' and 'arhosekskymodelstate_free'. - + 'emission_correction_factor_sky' 'emission_correction_factor_sun' - The original model coefficients were fitted against the emission of + The original model coefficients were fitted against the emission of our local sun. If a different solar emission is desired (i.e. if the - model is being used to predict skydome appearance for an earth-like - planet that orbits a different star), these correction factors, which - are determined during the alloc_init step, are applied to each waveband - separately (they default to 1.0 in normal usage). This is the simplest - way to retrofit this sort of capability to the existing model. The - different factors for sky and sun are needed since the solar disc may + model is being used to predict skydome appearance for an earth-like + planet that orbits a different star), these correction factors, which + are determined during the alloc_init step, are applied to each waveband + separately (they default to 1.0 in normal usage). This is the simplest + way to retrofit this sort of capability to the existing model. The + different factors for sky and sun are needed since the solar disc may be of a different size compared to the terrestrial sun. ---------------------------------------------------------------------------- */ typedef struct ArHosekSkyModelState { - ArHosekSkyModelConfiguration configs[11]; - double radiances[11]; - double turbidity; - double solar_radius; - double emission_correction_factor_sky[11]; - double emission_correction_factor_sun[11]; - double albedo; - double elevation; -} + ArHosekSkyModelConfiguration configs[11]; + double radiances[11]; + double turbidity; + double solar_radius; + double emission_correction_factor_sky[11]; + double emission_correction_factor_sun[11]; + double albedo; + double elevation; +} ArHosekSkyModelState; /* ---------------------------------------------------------------------------- @@ -358,11 +358,10 @@ ArHosekSkyModelState; ---------------------------------------------------------------------------- */ -ArHosekSkyModelState * arhosekskymodelstate_alloc_init( - const double solar_elevation, - const double atmospheric_turbidity, - const double ground_albedo - ); +ArHosekSkyModelState *arhosekskymodelstate_alloc_init( + const double solar_elevation, + const double atmospheric_turbidity, + const double ground_albedo); /* ---------------------------------------------------------------------------- @@ -375,78 +374,67 @@ ArHosekSkyModelState * arhosekskymodelstate_alloc_init( 'solar_intensity' controls the overall brightness of the sky, relative to the solar irradiance on Earth. A value of 1.0 yields a sky dome that is, on average over the wavelenghts covered in the model (!), as bright - as the terrestrial sky in radiometric terms. - - Which means that the solar radius has to be adjusted, since the - emissivity of a solar surface with a given temperature is more or less - fixed. So hotter suns have to be smaller to be equally bright as the + as the terrestrial sky in radiometric terms. + + Which means that the solar radius has to be adjusted, since the + emissivity of a solar surface with a given temperature is more or less + fixed. So hotter suns have to be smaller to be equally bright as the terrestrial sun, while cooler suns have to be larger. Note that there are limits to the validity of the luminance patterns of the underlying model: see the discussion above for more on this. In particular, an alien sun with a surface temperature of only 2000 Kelvin has to be very large if it is - to be as bright as the terrestrial sun - so large that the luminance + to be as bright as the terrestrial sun - so large that the luminance patterns are no longer a really good fit in that case. - + If you need information about the solar radius that the model computes - for a given temperature (say, for light source sampling purposes), you - have to query the 'solar_radius' variable of the sky model state returned + for a given temperature (say, for light source sampling purposes), you + have to query the 'solar_radius' variable of the sky model state returned *after* running this function. ---------------------------------------------------------------------------- */ -ArHosekSkyModelState * arhosekskymodelstate_alienworld_alloc_init( - const double solar_elevation, - const double solar_intensity, - const double solar_surface_temperature_kelvin, - const double atmospheric_turbidity, - const double ground_albedo - ); - -void arhosekskymodelstate_free( - ArHosekSkyModelState * state - ); - -double arhosekskymodel_radiance( - ArHosekSkyModelState * state, - double theta, - double gamma, - double wavelength - ); +ArHosekSkyModelState* arhosekskymodelstate_alienworld_alloc_init( + const double solar_elevation, + const double solar_intensity, + const double solar_surface_temperature_kelvin, + const double atmospheric_turbidity, + const double ground_albedo); + +void arhosekskymodelstate_free(ArHosekSkyModelState *state); + +double arhosekskymodel_radiance(ArHosekSkyModelState *state, + double theta, + double gamma, + double wavelength); // CIE XYZ and RGB versions ArHosekSkyModelState * arhosek_xyz_skymodelstate_alloc_init( - const double turbidity, - const double albedo, - const double elevation - ); + const double turbidity, + const double albedo, + const double elevation); ArHosekSkyModelState * arhosek_rgb_skymodelstate_alloc_init( - const double turbidity, - const double albedo, - const double elevation - ); + const double turbidity, + const double albedo, + const double elevation); -double arhosek_tristim_skymodel_radiance( - ArHosekSkyModelState * state, - double theta, - double gamma, - int channel - ); +double arhosek_tristim_skymodel_radiance(ArHosekSkyModelState* state, + double theta, + double gamma, + int channel); // Delivers the complete function: sky + sun, including limb darkening. // Please read the above description before using this - there are several // caveats! -double arhosekskymodel_solar_radiance( - ArHosekSkyModelState * state, - double theta, - double gamma, - double wavelength - ); +double arhosekskymodel_solar_radiance(ArHosekSkyModelState* state, + double theta, + double gamma, + double wavelength); #endif // _SKY_MODEL_H_ diff --git a/intern/cycles/render/sky_model_data.h b/intern/cycles/render/sky_model_data.h index 4171bd12756..e6f3f761532 100644 --- a/intern/cycles/render/sky_model_data.h +++ b/intern/cycles/render/sky_model_data.h @@ -4,7 +4,7 @@ This source is published under the following 3-clause BSD license. Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie All rights reserved. -Redistribution and use in source and binary forms, with or without +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright @@ -12,8 +12,8 @@ modification, are permitted provided that the following conditions are met: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * None of the names of the contributors may be used to endorse or promote - products derived from this software without specific prior written + * None of the names of the contributors may be used to endorse or promote + products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND @@ -41,24 +41,24 @@ and the 2013 IEEE CG&A paper "Adding a Solar Radiance Function to the Hosek Skylight Model" - both by + both by Lukas Hosek and Alexander Wilkie Charles University in Prague, Czech Republic Version: 1.4a, February 22nd, 2013 - + Version history: 1.4a February 22nd, 2013 - Removed unnecessary and counter-intuitive solar radius parameters + Removed unnecessary and counter-intuitive solar radius parameters from the interface of the colourspace sky dome initialisation functions. 1.4 February 11th, 2013 Fixed a bug which caused the relative brightness of the solar disc - and the sky dome to be off by a factor of about 6. The sun was too - bright: this affected both normal and alien sun scenarios. The + and the sky dome to be off by a factor of about 6. The sun was too + bright: this affected both normal and alien sun scenarios. The coefficients of the solar radiance function were changed to fix this. 1.3 January 21st, 2013 (not released to the public) @@ -82,7 +82,7 @@ Version history: the result of a simple conversion from spectral data via the CIE 2 degree standard observer matching functions. Therefore, after multiplication with 683 lm / W, the Y channel now corresponds to luminance in lm. - + 1.0 May 11th, 2012 Initial release. @@ -96,15 +96,14 @@ CCL_NAMESPACE_BEGIN /* -This file contains the coefficient data for the XYZ colour space version of +This file contains the coefficient data for the XYZ colour space version of the model. */ // Uses Sep 9 pattern / Aug 23 mean dataset -static const double datasetXYZ1[] = -{ +static const double datasetXYZ1[] = { // albedo 0, turbidity 1 -1.117001e+000, -1.867262e-001, @@ -3849,15 +3848,13 @@ static const double datasetXYZRad3[] = -static const double* datasetsXYZ[] = -{ +static const double* datasetsXYZ[] = { datasetXYZ1, datasetXYZ2, datasetXYZ3 }; -static const double* datasetsXYZRad[] = -{ +static const double* datasetsXYZRad[] = { datasetXYZRad1, datasetXYZRad2, datasetXYZRad3 -- cgit v1.2.3 From 5498629906c4944d88f26f0c59b13f9387d90d84 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 28 Mar 2015 00:34:16 +0500 Subject: Freestyle: Code cleanup, silence warning in release mode --- source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index dfcc77d3b23..f5f76516d38 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -256,6 +256,7 @@ void BlenderFileLoader::clipTriangle(int numTris, float triCoords[][3], float v1 } } BLI_assert(k == 2 + numTris); + (void)numTris; /* Ignored in release builds. */ } void BlenderFileLoader::addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3], -- cgit v1.2.3 From 469ba8a30a8222fdc0adede1e214b17e9fd1fc4f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 28 Mar 2015 00:46:59 +0500 Subject: Tracking: Code cleanup, missing break statements --- source/blender/blenkernel/intern/tracking_util.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c index 882a6fabef1..56119b732fc 100644 --- a/source/blender/blenkernel/intern/tracking_util.c +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -423,6 +423,7 @@ void tracking_cameraIntrinscisOptionsFromTracking(MovieTracking *tracking, break; default: BLI_assert(!"Unknown distortion model"); + break; } camera_intrinsics_options->image_width = calibration_width; @@ -454,6 +455,7 @@ void tracking_trackingCameraFromIntrinscisOptions(MovieTracking *tracking, break; default: BLI_assert(!"Unknown distortion model"); + break; } } -- cgit v1.2.3 From b7afbaf8ccc315296d2dc824cc8d089108a38558 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 28 Mar 2015 23:22:02 +1300 Subject: Bugfix: Fix for crash when trying to create new action in Shape Key DopeSheet mode When the active object had no shapekey data, trying to create a new action from the Shape Keys mode of the DopeSheet would crash. The segfault here was a silly regression caused by my earlier Action Stashing work. However, the old (pre-Action Stashing) code here also wasn't that great either. While it didn't crash, it would still silently create a new action, even if that could not get assigned/used anywhere. To prevent both of these problems from happening again, I've added additional null checks, as well as beefing up the poll callback here to forbid keyframing --- source/blender/editors/space_action/action_edit.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 76c955d8bca..95066b91725 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -93,11 +93,15 @@ static AnimData *actedit_animdata_from_context(bContext *C) /* Get AnimData block to use */ if (saction->mode == SACTCONT_ACTION) { /* Currently, "Action Editor" means object-level only... */ - adt = ob->adt; + if (ob) { + adt = ob->adt; + } } else if (saction->mode == SACTCONT_SHAPEKEY) { Key *key = BKE_key_from_object(ob); - adt = key->adt; + if (key) { + adt = key->adt; + } } return adt; @@ -180,9 +184,19 @@ static int action_new_poll(bContext *C) if (!(scene->flag & SCE_NLA_EDIT_ON)) { if (ED_operator_action_active(C)) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); + Object *ob = CTX_data_active_object(C); /* For now, actions are only for the active object, and on object and shapekey levels... */ - return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY); + if (saction->mode == SACTCONT_ACTION) { + /* XXX: This assumes that actions are assigned to the active object */ + if (ob) + return true; + } + else if (saction->mode == SACTCONT_SHAPEKEY) { + Key *key = BKE_key_from_object(ob); + if (key) + return true; + } } else if (ED_operator_nla_active(C)) { return true; -- cgit v1.2.3 From 1a5c5ac742679b625d789614ea6807672e522ebb Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 28 Mar 2015 23:48:10 +1300 Subject: Fix T44068: "Layered" option for auto keyframing doesn't "Insert Available Only" is enabled The "Layered" option for auto keyframing will create a new NLA strip if playback reaches the end of the frame range and jumps back again. The idea is that instead of overwriting the keyframes you've already made, it will make a new animation layer. However, this does not work with the "Insert Available Only" option (which can either be set in the User Prefs, or in the active keyingset), as that option needs some existing FCurves to tell what it can insert keyframes into. The "fix" here is to simply not show the offending button in situations where it cannot be used! --- release/scripts/startup/bl_ui/space_time.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py index 27fcf94666a..819c2af4200 100644 --- a/release/scripts/startup/bl_ui/space_time.py +++ b/release/scripts/startup/bl_ui/space_time.py @@ -30,6 +30,7 @@ class TIME_HT_header(Header): scene = context.scene toolsettings = context.tool_settings screen = context.screen + userprefs = context.user_preferences row = layout.row(align=True) row.template_header() @@ -82,7 +83,7 @@ class TIME_HT_header(Header): if toolsettings.use_keyframe_insert_auto: row.prop(toolsettings, "use_keyframe_insert_keyingset", text="", toggle=True) - if screen.is_animation_playing: + if screen.is_animation_playing and not userprefs.edit.use_keyframe_insert_available: subsub = row.row(align=True) subsub.prop(toolsettings, "use_record_with_nla", toggle=True) -- cgit v1.2.3 From 2b4ff142ab542b3ef689e73e18b06f8bfaedf89f Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 24 Jan 2014 15:48:36 +1300 Subject: Fix T36385: Animated Strip-Time doesnt update This commit implements proper evaluation + keyframing support for animating influence and time on NLA Strips (among other properties) by resolving a few long standing issues which prevented the original design for this from working. The original design for animating these properties (and/or some of the other settings on NLA Strips) is that NLA Strips actually have some of their own F-Curves that are used for animating settings which will affect how they are evaluated. As seen in this bug report, the alternative of having these animated as part of the stack (which the strips work above/outside/on-top of) means that glitches can occur. Although one of the original considerations for why this wasn't implemented earlier was that introducing keyframes there isn't so clean cut, and causes UI design issues for how we expose these via the animation editors for editing (NOTE: support for that is still to come). Another concern is that this sets a precedent for how FModifiers might get evaluated. --- source/blender/blenkernel/intern/anim_sys.c | 7 ++-- source/blender/editors/animation/keyframing.c | 48 +++++++++++++++------------ 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index effe32a8079..59cc23ab8a1 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1496,8 +1496,11 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind /* get property to write to */ if (RNA_path_resolve_property(ptr, path, &new_ptr, &prop)) { - /* set value - only for animatable numerical values */ - if (RNA_property_animateable(&new_ptr, prop)) { + /* set value for animatable numerical values only + * HACK: some local F-Curves (e.g. those on NLA Strips) are evaluated + * without an ID provided, which causes the animateable test to fail! + */ + if (RNA_property_animateable(&new_ptr, prop) || (ptr->id.data == NULL)) { int array_len = RNA_property_array_length(&new_ptr, prop); bool written = false; diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 7e2ce4cd3f1..68ef704272d 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1707,33 +1707,39 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) UI_context_active_but_prop_get(C, &ptr, &prop, &index); if ((ptr.id.data && ptr.data && prop) && RNA_property_animateable(&ptr, prop)) { - path = RNA_path_from_ID_to_property(&ptr, prop); - - if (path) { - if (all) { - length = RNA_property_array_length(&ptr, prop); - - if (length) index = 0; - else length = 1; - } - else - length = 1; - - for (a = 0; a < length; a++) - success += insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, cfra, flag); - - MEM_freeN(path); - } - else if (ptr.type == &RNA_NlaStrip) { - /* handle special vars for NLA-strips */ + if (ptr.type == &RNA_NlaStrip) { + /* Handle special properties for NLA Strips, whose F-Curves are stored on the + * strips themselves. These are stored separately or else the properties will + * not have any effect. + */ NlaStrip *strip = (NlaStrip *)ptr.data; FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), flag); success += insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0); } else { - BKE_report(op->reports, RPT_WARNING, - "Failed to resolve path to property, try manually specifying this using a Keying Set instead"); + /* standard properties */ + path = RNA_path_from_ID_to_property(&ptr, prop); + + if (path) { + if (all) { + length = RNA_property_array_length(&ptr, prop); + + if (length) index = 0; + else length = 1; + } + else + length = 1; + + for (a = 0; a < length; a++) + success += insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, cfra, flag); + + MEM_freeN(path); + } + else { + BKE_report(op->reports, RPT_WARNING, + "Failed to resolve path to property, try manually specifying this using a Keying Set instead"); + } } } else { -- cgit v1.2.3 From 59b2316e82a97cecd55a8089cc3fa89003cdbb12 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 24 Jan 2014 16:10:26 +1300 Subject: Code Cleanup / Preemptive Bug Fixing: "action" parameter may get set when it shouldn't be Logically, it makes sense that this parameter only gets used to describe the action that the F-Curve actually belongs to (if it belongs to one). Otherwise, it should not be set at all. --- source/blender/blenkernel/intern/fcurve.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 81321b9dbc2..b46958a0308 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -322,6 +322,7 @@ FCurve *rna_get_fcurve_context_ui(bContext *C, PointerRNA *ptr, PropertyRNA *pro if (animdata) *animdata = NULL; *r_driven = false; + if (action) *action = NULL; /* there must be some RNA-pointer + property combon */ if (prop && tptr.id.data && RNA_property_animateable(&tptr, prop)) { @@ -344,8 +345,12 @@ FCurve *rna_get_fcurve_context_ui(bContext *C, PointerRNA *ptr, PropertyRNA *pro if (path) { /* animation takes priority over drivers */ - if (adt->action && adt->action->curves.first) + if (adt->action && adt->action->curves.first) { fcu = list_find_fcurve(&adt->action->curves, path, rnaindex); + + if (fcu && action) + *action = adt->action; + } /* if not animated, check if driven */ if (!fcu && (adt->drivers.first)) { -- cgit v1.2.3 From fc0a576c3055b6c792c94713261198f81f2737cd Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 24 Jan 2014 17:09:21 +1300 Subject: Keyframes on NLA-Strip F-Curves are detected by RNA buttons too --- source/blender/blenkernel/BKE_fcurve.h | 6 ++-- source/blender/blenkernel/intern/fcurve.c | 38 ++++++++++++++++++++--- source/blender/editors/interface/interface_anim.c | 32 +++++++++++-------- source/blender/makesrna/intern/rna_access.c | 4 +-- 4 files changed, 58 insertions(+), 22 deletions(-) diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 83783946d4f..275ab3f1ebb 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -223,12 +223,12 @@ struct FCurve *id_data_find_fcurve(ID *id, void *data, struct StructRNA *type, c */ int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix, const char *dataName); -/* find an f-curve based on an rna property. */ +/* Find an f-curve based on an rna property. */ struct FCurve *rna_get_fcurve(struct PointerRNA *ptr, struct PropertyRNA *prop, int rnaindex, - struct AnimData **adt, struct bAction **action, bool *r_driven); + struct AnimData **adt, struct bAction **action, bool *r_driven, bool *r_special); /* Same as above, but takes a context data, temp hack needed for complex paths like texture ones. */ struct FCurve *rna_get_fcurve_context_ui(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, - int rnaindex, struct AnimData **adt, struct bAction **action, bool *r_driven); + int rnaindex, struct AnimData **adt, struct bAction **action, bool *r_driven, bool *r_special); /* Binary search algorithm for finding where to 'insert' BezTriple with given frame number. * Returns the index to insert at (data already at that index will be offset if replace is 0) diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index b46958a0308..a9866405827 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -309,19 +309,22 @@ int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix, return matches; } -FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, AnimData **adt, bAction **action, bool *r_driven) +FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, AnimData **adt, + bAction **action, bool *r_driven, bool *r_special) { - return rna_get_fcurve_context_ui(NULL, ptr, prop, rnaindex, adt, action, r_driven); + return rna_get_fcurve_context_ui(NULL, ptr, prop, rnaindex, adt, action, r_driven, r_special); } -FCurve *rna_get_fcurve_context_ui(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int rnaindex, - AnimData **animdata, bAction **action, bool *r_driven) +FCurve *rna_get_fcurve_context_ui(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int rnaindex, AnimData **animdata, + bAction **action, bool *r_driven, bool *r_special) { FCurve *fcu = NULL; PointerRNA tptr = *ptr; if (animdata) *animdata = NULL; *r_driven = false; + *r_special = false; + if (action) *action = NULL; /* there must be some RNA-pointer + property combon */ @@ -343,6 +346,7 @@ FCurve *rna_get_fcurve_context_ui(bContext *C, PointerRNA *ptr, PropertyRNA *pro path = RNA_path_from_ID_to_property(&tptr, prop); } + // XXX: the logic here is duplicated with a function up above if (path) { /* animation takes priority over drivers */ if (adt->action && adt->action->curves.first) { @@ -380,6 +384,32 @@ FCurve *rna_get_fcurve_context_ui(bContext *C, PointerRNA *ptr, PropertyRNA *pro } } } + + /* if we still haven't found anything, check whether it's a "special" property */ + if ((fcu == NULL) && (adt->nla_tracks.first)) { + NlaTrack *nlt; + const char *propname = RNA_property_identifier(prop); + + for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { + NlaStrip *strip; + + if (fcu) + break; + + /* FIXME: need to do recursive search here for correctness, + * but this will do for most use cases (i.e. interactive editing), + * where nested strips can't be easily edited + */ + for (strip = nlt->strips.first; strip; strip = strip->next) { + fcu = list_find_fcurve(&strip->fcurves, propname, rnaindex); + + if (fcu) { + *r_special = true; + break; + } + } + } + } } MEM_SAFE_FREE(path); } diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 24a30ebe3d8..f6757b35462 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -54,13 +54,13 @@ #include "interface_intern.h" -static FCurve *ui_but_get_fcurve(uiBut *but, AnimData **adt, bAction **action, bool *r_driven) +static FCurve *ui_but_get_fcurve(uiBut *but, AnimData **adt, bAction **action, bool *r_driven, bool *r_special) { /* for entire array buttons we check the first component, it's not perfect * but works well enough in typical cases */ int rnaindex = (but->rnaindex == -1) ? 0 : but->rnaindex; - return rna_get_fcurve_context_ui(but->block->evil_C, &but->rnapoin, but->rnaprop, rnaindex, adt, action, r_driven); + return rna_get_fcurve_context_ui(but->block->evil_C, &but->rnapoin, but->rnaprop, rnaindex, adt, action, r_driven, r_special); } void ui_but_anim_flag(uiBut *but, float cfra) @@ -69,11 +69,16 @@ void ui_but_anim_flag(uiBut *but, float cfra) bAction *act; FCurve *fcu; bool driven; - + bool special; + but->flag &= ~(UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN); - - fcu = ui_but_get_fcurve(but, &adt, &act, &driven); - + + /* NOTE: "special" is reserved for special F-Curves stored on the animation data + * itself (which are used to animate properties of the animation data). + * We count those as "animated" too for now + */ + fcu = ui_but_get_fcurve(but, &adt, &act, &driven, &special); + if (fcu) { if (!driven) { but->flag |= UI_BUT_ANIMATED; @@ -98,10 +103,10 @@ bool ui_but_anim_expression_get(uiBut *but, char *str, size_t maxlen) { FCurve *fcu; ChannelDriver *driver; - bool driven; - - fcu = ui_but_get_fcurve(but, NULL, NULL, &driven); - + bool driven, special; + + fcu = ui_but_get_fcurve(but, NULL, NULL, &driven, &special); + if (fcu && driven) { driver = fcu->driver; @@ -118,9 +123,9 @@ bool ui_but_anim_expression_set(uiBut *but, const char *str) { FCurve *fcu; ChannelDriver *driver; - bool driven; + bool driven, special; - fcu = ui_but_get_fcurve(but, NULL, NULL, &driven); + fcu = ui_but_get_fcurve(but, NULL, NULL, &driven, &special); if (fcu && driven) { driver = fcu->driver; @@ -215,8 +220,9 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra) bAction *action; FCurve *fcu; bool driven; + bool special; - fcu = ui_but_get_fcurve(but, NULL, &action, &driven); + fcu = ui_but_get_fcurve(but, NULL, &action, &driven, &special); if (fcu && !driven) { id = but->rnapoin.id.data; diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 06fdf6d3b77..ef798820321 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -1622,7 +1622,7 @@ bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop) bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop) { int len = 1, index; - bool driven; + bool driven, special; if (!prop) return false; @@ -1631,7 +1631,7 @@ bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop) len = RNA_property_array_length(ptr, prop); for (index = 0; index < len; index++) { - if (rna_get_fcurve(ptr, prop, index, NULL, NULL, &driven)) + if (rna_get_fcurve(ptr, prop, index, NULL, NULL, &driven, &special)) return true; } -- cgit v1.2.3 From 90e9a22eaa817dcf5b0008f6c73edeab9a27f99e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 13 Mar 2015 19:05:27 +1300 Subject: Fix for earlier commit - Turning off "animated" influence/time didn't work Reshuffled order that in which NLA Strip's F-Curves vs its automatic settings are evaluated so that the automatic settings can always override the custom settings, since it's not that easy to get things working correctly the other way around. --- source/blender/blenkernel/intern/anim_sys.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 59cc23ab8a1..b4c396d38d2 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1800,12 +1800,6 @@ static float nlastrip_get_influence(NlaStrip *strip, float cframe) /* evaluate the evaluation time and influence for the strip, storing the results in the strip */ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime) { - /* firstly, analytically generate values for influence and time (if applicable) */ - if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) - strip->strip_time = nlastrip_get_frame(strip, ctime, NLATIME_CONVERT_EVAL); - if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0) - strip->influence = nlastrip_get_influence(strip, ctime); - /* now strip's evaluate F-Curves for these settings (if applicable) */ if (strip->fcurves.first) { PointerRNA strip_ptr; @@ -1816,6 +1810,15 @@ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime) /* execute these settings as per normal */ animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, NULL, ctime); } + + /* analytically generate values for influence and time (if applicable) + * - we do this after the F-Curves have been evaluated to override the effects of those + * in case the override has been turned off. + */ + if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) + strip->strip_time = nlastrip_get_frame(strip, ctime, NLATIME_CONVERT_EVAL); + if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0) + strip->influence = nlastrip_get_influence(strip, ctime); /* if user can control the evaluation time (using F-Curves), consider the option which allows this time to be clamped * to lie within extents of the action-clip, so that a steady changing rate of progress through several cycles of the clip -- cgit v1.2.3 From da0d0b2f2091160e9d75015f8931d2bba82c43a0 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 13 Mar 2015 19:22:36 +1300 Subject: Compile fix New parameter added by these fixes did not exist when this call got added --- source/blender/editors/space_outliner/outliner_draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 2c61e69d611..68d7cd8c475 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -202,7 +202,7 @@ static void restrictbutton_recursive_child(bContext *C, Scene *scene, Object *ob RNA_id_pointer_create(&ob->id, &ptr); prop = RNA_struct_find_property(&ptr, rnapropname); - fcu = rna_get_fcurve_context_ui(C, &ptr, prop, 0, NULL, &action, &driven); + fcu = rna_get_fcurve_context_ui(C, &ptr, prop, 0, NULL, &action, &driven, NULL); if (fcu && !driven) { id = ptr.id.data; -- cgit v1.2.3 From 6dac874d68bde7ffb72ce44d9916ceeeeb5fb2a1 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 13 Mar 2015 22:03:26 +1300 Subject: Fix for various small issues which may cause crashes --- source/blender/blenkernel/intern/fcurve.c | 2 +- source/blender/editors/space_outliner/outliner_draw.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index a9866405827..86454576b98 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -386,7 +386,7 @@ FCurve *rna_get_fcurve_context_ui(bContext *C, PointerRNA *ptr, PropertyRNA *pro } /* if we still haven't found anything, check whether it's a "special" property */ - if ((fcu == NULL) && (adt->nla_tracks.first)) { + if ((fcu == NULL) && (adt && adt->nla_tracks.first)) { NlaTrack *nlt; const char *propname = RNA_property_identifier(prop); diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 68d7cd8c475..5a11b9a2395 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -198,11 +198,11 @@ static void restrictbutton_recursive_child(bContext *C, Scene *scene, Object *ob ID *id; bAction *action; FCurve *fcu; - bool driven; + bool driven, special; RNA_id_pointer_create(&ob->id, &ptr); prop = RNA_struct_find_property(&ptr, rnapropname); - fcu = rna_get_fcurve_context_ui(C, &ptr, prop, 0, NULL, &action, &driven, NULL); + fcu = rna_get_fcurve_context_ui(C, &ptr, prop, 0, NULL, &action, &driven, &special); if (fcu && !driven) { id = ptr.id.data; -- cgit v1.2.3 From 8f4c5ff0ecd81a95885939e2fa553f50f1f405fc Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 22 Mar 2015 02:46:51 +1300 Subject: Nla Strip Controls: Added dedicated "Expander" channel to Action/Graph Editors The "Nla Strip Controls" channel is used to house the per-strip FCurves for controlling the strip_time and influence properties. It sits above the active action's first group, at the same level in the hierarchy as other groups. TODO: It looks like a dedicated FCurve channel is needed for these control FCurves, so that we won't accidentally apply NLA mapping or have these FCurves disabled by the path lookups failing. --- .../editors/animation/anim_channels_defines.c | 102 +++++++++++++++++++++ source/blender/editors/animation/anim_filter.c | 70 +++++++++++++- source/blender/editors/include/ED_anim_api.h | 2 + 3 files changed, 172 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 37c40052275..11d68ed6f75 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -908,6 +908,106 @@ static bAnimChannelType ACF_GROUP = acf_group_setting_ptr /* pointer for setting */ }; +/* NLA Control FCurves Expander ----------------------- */ + +/* get backdrop color for nla controls widget */ +static void acf_nla_controls_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3]) +{ + // TODO: give this its own theme setting? + UI_GetThemeColorShade3fv(TH_GROUP, 55, r_color); +} + +/* backdrop for nla controls expander widget */ +static void acf_nla_controls_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) +{ + bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + View2D *v2d = &ac->ar->v2d; + short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0; + short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; + float color[3]; + + /* set backdrop drawing color */ + acf->get_backdrop_color(ac, ale, color); + glColor3fv(color); + + /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ + UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)); + UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5); +} + +/* name for nla controls expander entries */ +static void acf_nla_controls_name(bAnimListElem *ale, char *name) +{ + BLI_strncpy(name, IFACE_("NLA Strip Controls"), ANIM_CHAN_NAME_SIZE); +} + +/* check if some setting exists for this channel */ +static bool acf_nla_controls_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting) +{ + /* for now, all settings are supported, though some are only conditionally */ + switch (setting) { + /* supported */ + case ACHANNEL_SETTING_EXPAND: + return true; + + // TOOD: selected? + + default: /* unsupported */ + return false; + } +} + +/* get the appropriate flag(s) for the setting when it is valid */ +static int acf_nla_controls_setting_flag(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg) +{ + /* clear extra return data first */ + *neg = false; + + switch (setting) { + case ACHANNEL_SETTING_EXPAND: /* expanded */ + *neg = true; + return ADT_NLA_SKEYS_COLLAPSED; + + default: + /* this shouldn't happen */ + return 0; + } +} + +/* get pointer to the setting */ +static void *acf_nla_controls_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type) +{ + AnimData *adt = (AnimData *)ale->data; + + /* all flags are just in adt->flag for now... */ + return GET_ACF_FLAG_PTR(adt->flag, type); +} + +static int acf_nla_controls_icon(bAnimListElem *UNUSED(ale)) +{ + return ICON_NLA; +} + +/* NLA Control FCurves Expander type define */ +static bAnimChannelType ACF_NLACONTROLS = +{ + "NLA Controls Expander", /* type name */ + ACHANNEL_ROLE_EXPANDER, /* role */ + + acf_nla_controls_color, /* backdrop color */ + acf_nla_controls_backdrop, /* backdrop */ + acf_generic_indention_0, /* indent level */ + acf_generic_group_offset, /* offset */ + + acf_nla_controls_name, /* name */ + NULL, /* name prop */ + acf_nla_controls_icon, /* icon */ + + acf_nla_controls_setting_valid, /* has setting */ + acf_nla_controls_setting_flag, /* flag for setting */ + acf_nla_controls_setting_ptr /* pointer for setting */ +}; + /* F-Curve ------------------------------------------- */ /* name for fcurve entries */ @@ -3222,6 +3322,8 @@ static void ANIM_init_channel_typeinfo_data(void) animchannelTypeInfo[type++] = &ACF_GROUP; /* Group */ animchannelTypeInfo[type++] = &ACF_FCURVE; /* F-Curve */ + animchannelTypeInfo[type++] = &ACF_NLACONTROLS; /* NLA Control FCurve Expander */ + animchannelTypeInfo[type++] = &ACF_FILLACTD; /* Object Action Expander */ animchannelTypeInfo[type++] = &ACF_FILLDRIVERS; /* Drivers Expander */ diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index d6daa64a9f2..b5d1de9c7d6 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -423,6 +423,7 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac) * - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA) * - nlaOk: line or block of code to execute for NLA tracks+strips case * - driversOk: line or block of code to execute for Drivers case + * - nlaKeysOk: line or block of code for NLA Strip Keyframes case * - keysOk: line or block of code for Keyframes case * * The checks for the various cases are as follows: @@ -433,9 +434,10 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac) * converted to a new NLA strip, and the filtering options allow this * 2C) allow non-animated datablocks to be included so that datablocks can be added * 3) drivers: include drivers from animdata block (for Drivers mode in Graph Editor) - * 4) normal keyframes: only when there is an active action + * 4A) nla strip keyframes: these are the per-strip controls for time and influence + * 4B) normal keyframes: only when there is an active action */ -#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, keysOk) \ +#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, nlaKeysOk, keysOk) \ { \ if ((id)->adt) { \ if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || !((id)->adt->flag & ADT_CURVES_NOT_VISIBLE)) { \ @@ -456,6 +458,9 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac) } \ } \ else { \ + if (ANIMDATA_HAS_NLA(id)) { \ + nlaKeysOk \ + } \ if (ANIMDATA_HAS_KEYS(id)) { \ keysOk \ } \ @@ -786,6 +791,16 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne ale->adt = BKE_animdata_from_id(data); break; } + case ANIMTYPE_NLACONTROLS: + { + AnimData *adt = (AnimData *)data; + + ale->flag = adt->flag; + + ale->key_data = NULL; + ale->datatype = ALE_NONE; + break; + } case ANIMTYPE_GROUP: { bActionGroup *agrp = (bActionGroup *)data; @@ -1305,6 +1320,52 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop return items; } +/* Include the control FCurves per NLA Strip in the channel list + * NOTE: This is includes the expander too... + */ +static size_t animfilter_nla_controls(ListBase *anim_data, bDopeSheet *ads, AnimData *adt, int filter_mode, ID *owner_id) +{ + ListBase tmp_data = {NULL, NULL}; + size_t tmp_items = 0; + size_t items = 0; + + /* add control curves from each NLA strip... */ + BEGIN_ANIMFILTER_SUBCHANNELS(((adt->flag & ADT_NLA_SKEYS_COLLAPSED) == 0)) + { + NlaTrack *nlt; + NlaStrip *strip; + + /* for now, we only go one level deep - so controls on grouped FCurves are not handled */ + for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { + for (strip = nlt->strips.first; strip; strip = strip->next) { + tmp_items += animfilter_fcurves(&tmp_data, ads, strip->fcurves.first, NULL, filter_mode, owner_id); + } + } + } + END_ANIMFILTER_SUBCHANNELS; + + /* did we find anything? */ + if (tmp_items) { + /* TODO: apply extra tags to indicate the NLA mapping does not apply here! */ + + /* add the expander as a channel first */ + if (filter_mode & ANIMFILTER_LIST_CHANNELS) { + /* currently these channels cannot be selected, so they should be skipped */ + if ((filter_mode & (ANIMFILTER_SEL | ANIMFILTER_UNSEL)) == 0) { + ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_NLACONTROLS, owner_id); + } + } + + /* now add the list of collected channels */ + BLI_movelisttolist(anim_data, &tmp_data); + BLI_assert(BLI_listbase_is_empty(&tmp_data)); + items += tmp_items; + } + + /* return the numebr of items added ot the list */ + return items; +} + /* determine what animation data from AnimData block should get displayed */ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *id, int filter_mode) { @@ -1332,6 +1393,9 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope { /* Drivers */ items += animfilter_fcurves(anim_data, ads, adt->drivers.first, NULL, filter_mode, id); }, + { /* NLA Control Keyframes */ + items += animfilter_nla_controls(anim_data, ads, adt, filter_mode, id); + }, { /* Keyframes */ items += animfilter_action(ac, anim_data, ads, adt->action, filter_mode, id); } @@ -2214,6 +2278,7 @@ static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, b cdata = adt; expanded = EXPANDED_DRVD(adt); }, + { /* NLA Strip Controls - no dedicated channel for now (XXX) */ }, { /* Keyframes */ type = ANIMTYPE_FILLACTD; cdata = adt->action; @@ -2385,6 +2450,7 @@ static size_t animdata_filter_ds_scene(bAnimContext *ac, ListBase *anim_data, bD cdata = adt; expanded = EXPANDED_DRVD(adt); }, + { /* NLA Strip Controls - no dedicated channel for now (XXX) */ }, { /* Keyframes */ type = ANIMTYPE_FILLACTD; cdata = adt->action; diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 50581429700..829ea74f00f 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -141,6 +141,8 @@ typedef enum eAnim_ChannelType { ANIMTYPE_GROUP, ANIMTYPE_FCURVE, + ANIMTYPE_NLACONTROLS, + ANIMTYPE_FILLACTD, ANIMTYPE_FILLDRIVERS, -- cgit v1.2.3 From 67f983ac53e97f154b6710fea8f400a608e27550 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 22 Mar 2015 21:41:45 +1300 Subject: Nla Strip Controls: Added special FCurve type (in the animfiltering code) Using the standard "FCurve" animchannel type didn't work that well for the control FCurves on NLA Strips, as the paths would not resolve correctly, and the indentation was wrong. Also, there would likely be issues down the track with applying NLA mapping. Hence, it's easier to just create a separate type for this case, and adapt the rest of the code to also consider these (todo). --- .../editors/animation/anim_channels_defines.c | 231 +++++++++++++-------- .../blender/editors/animation/anim_channels_edit.c | 9 +- source/blender/editors/animation/anim_filter.c | 34 ++- source/blender/editors/include/ED_anim_api.h | 4 + source/blender/editors/space_action/action_edit.c | 2 +- .../blender/editors/space_action/action_select.c | 4 +- .../editors/transform/transform_conversions.c | 2 +- 7 files changed, 186 insertions(+), 100 deletions(-) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 11d68ed6f75..72aa0c18cb3 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -908,6 +908,115 @@ static bAnimChannelType ACF_GROUP = acf_group_setting_ptr /* pointer for setting */ }; +/* F-Curve ------------------------------------------- */ + +/* name for fcurve entries */ +static void acf_fcurve_name(bAnimListElem *ale, char *name) +{ + getname_anim_fcurve(name, ale->id, ale->data); +} + +/* "name" property for fcurve entries */ +static bool acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop) +{ + FCurve *fcu = (FCurve *)ale->data; + + /* Ctrl-Click Usability Convenience Hack: + * For disabled F-Curves, allow access to the RNA Path + * as our "name" so that user can perform quick fixes + */ + if (fcu->flag & FCURVE_DISABLED) { + RNA_pointer_create(ale->id, &RNA_FCurve, ale->data, ptr); + *prop = RNA_struct_find_property(ptr, "data_path"); + } + else { + /* for "normal" F-Curves - no editable name, but *prop may not be set properly yet... */ + *prop = NULL; + } + + return (*prop != NULL); +} + +/* check if some setting exists for this channel */ +static bool acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting) +{ + FCurve *fcu = (FCurve *)ale->data; + + switch (setting) { + /* unsupported */ + case ACHANNEL_SETTING_SOLO: /* Solo Flag is only for NLA */ + case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */ + return false; + + /* conditionally available */ + case ACHANNEL_SETTING_PROTECT: /* Protection is only valid when there's keyframes */ + if (fcu->bezt) + return true; + else + return false; // NOTE: in this special case, we need to draw ICON_ZOOMOUT + + case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */ + return (ac->spacetype == SPACE_IPO); + + /* always available */ + default: + return true; + } +} + +/* get the appropriate flag(s) for the setting when it is valid */ +static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) +{ + /* clear extra return data first */ + *neg = false; + + switch (setting) { + case ACHANNEL_SETTING_SELECT: /* selected */ + return FCURVE_SELECTED; + + case ACHANNEL_SETTING_MUTE: /* muted */ + return FCURVE_MUTED; + + case ACHANNEL_SETTING_PROTECT: /* protected */ + return FCURVE_PROTECTED; + + case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */ + return FCURVE_VISIBLE; + + default: /* unsupported */ + return 0; + } +} + +/* get pointer to the setting */ +static void *acf_fcurve_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type) +{ + FCurve *fcu = (FCurve *)ale->data; + + /* all flags are just in agrp->flag for now... */ + return GET_ACF_FLAG_PTR(fcu->flag, type); +} + +/* fcurve type define */ +static bAnimChannelType ACF_FCURVE = +{ + "F-Curve", /* type name */ + ACHANNEL_ROLE_CHANNEL, /* role */ + + acf_generic_channel_color, /* backdrop color */ + acf_generic_channel_backdrop, /* backdrop */ + acf_generic_indention_flexible, /* indent level */ // xxx rename this to f-curves only? + acf_generic_group_offset, /* offset */ + + acf_fcurve_name, /* name */ + acf_fcurve_name_prop, /* name prop */ + NULL, /* icon */ + + acf_fcurve_setting_valid, /* has setting */ + acf_fcurve_setting_flag, /* flag for setting */ + acf_fcurve_setting_ptr /* pointer for setting */ +}; + /* NLA Control FCurves Expander ----------------------- */ /* get backdrop color for nla controls widget */ @@ -1008,107 +1117,41 @@ static bAnimChannelType ACF_NLACONTROLS = acf_nla_controls_setting_ptr /* pointer for setting */ }; -/* F-Curve ------------------------------------------- */ -/* name for fcurve entries */ -static void acf_fcurve_name(bAnimListElem *ale, char *name) -{ - getname_anim_fcurve(name, ale->id, ale->data); -} +/* NLA Control F-Curve -------------------------------- */ -/* "name" property for fcurve entries */ -static bool acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop) +/* name for nla control fcurve entries */ +static void acf_nla_curve_name(bAnimListElem *ale, char *name) { - FCurve *fcu = (FCurve *)ale->data; + NlaStrip *strip = ale->owner; + FCurve *fcu = ale->data; + PropertyRNA *prop; - /* Ctrl-Click Usability Convenience Hack: - * For disabled F-Curves, allow access to the RNA Path - * as our "name" so that user can perform quick fixes - */ - if (fcu->flag & FCURVE_DISABLED) { - RNA_pointer_create(ale->id, &RNA_FCurve, ale->data, ptr); - *prop = RNA_struct_find_property(ptr, "data_path"); + /* try to get RNA property that this shortened path (relative to the strip) refers to */ + prop = RNA_struct_type_find_property(&RNA_NlaStrip, fcu->rna_path); + if (prop) { + /* "name" of this strip displays the UI identifier + the name of the NlaStrip */ + BLI_snprintf(name, 256, "%s (%s)", RNA_property_ui_name(prop), strip->name); } else { - /* for "normal" F-Curves - no editable name, but *prop may not be set properly yet... */ - *prop = NULL; - } - - return (*prop != NULL); -} - -/* check if some setting exists for this channel */ -static bool acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting) -{ - FCurve *fcu = (FCurve *)ale->data; - - switch (setting) { - /* unsupported */ - case ACHANNEL_SETTING_SOLO: /* Solo Flag is only for NLA */ - case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */ - return false; - - /* conditionally available */ - case ACHANNEL_SETTING_PROTECT: /* Protection is only valid when there's keyframes */ - if (fcu->bezt) - return true; - else - return false; // NOTE: in this special case, we need to draw ICON_ZOOMOUT - - case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */ - return (ac->spacetype == SPACE_IPO); - - /* always available */ - default: - return true; + /* unknown property... */ + BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index); } } -/* get the appropriate flag(s) for the setting when it is valid */ -static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) -{ - /* clear extra return data first */ - *neg = false; - - switch (setting) { - case ACHANNEL_SETTING_SELECT: /* selected */ - return FCURVE_SELECTED; - - case ACHANNEL_SETTING_MUTE: /* muted */ - return FCURVE_MUTED; - - case ACHANNEL_SETTING_PROTECT: /* protected */ - return FCURVE_PROTECTED; - - case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */ - return FCURVE_VISIBLE; - - default: /* unsupported */ - return 0; - } -} - -/* get pointer to the setting */ -static void *acf_fcurve_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type) -{ - FCurve *fcu = (FCurve *)ale->data; - - /* all flags are just in agrp->flag for now... */ - return GET_ACF_FLAG_PTR(fcu->flag, type); -} -/* fcurve type define */ -static bAnimChannelType ACF_FCURVE = +/* NLA Control F-Curve type define */ +static bAnimChannelType ACF_NLACURVE = { - "F-Curve", /* type name */ + "NLA Control F-Curve", /* type name */ ACHANNEL_ROLE_CHANNEL, /* role */ acf_generic_channel_color, /* backdrop color */ acf_generic_channel_backdrop, /* backdrop */ - acf_generic_indention_flexible, /* indent level */ // xxx rename this to f-curves only? + acf_generic_indention_1, /* indent level */ acf_generic_group_offset, /* offset */ - acf_fcurve_name, /* name */ + acf_nla_curve_name, /* name */ acf_fcurve_name_prop, /* name prop */ NULL, /* icon */ @@ -3323,6 +3366,7 @@ static void ANIM_init_channel_typeinfo_data(void) animchannelTypeInfo[type++] = &ACF_FCURVE; /* F-Curve */ animchannelTypeInfo[type++] = &ACF_NLACONTROLS; /* NLA Control FCurve Expander */ + animchannelTypeInfo[type++] = &ACF_NLACURVE; /* NLA Control FCurve Channel */ animchannelTypeInfo[type++] = &ACF_FILLACTD; /* Object Action Expander */ animchannelTypeInfo[type++] = &ACF_FILLDRIVERS; /* Drivers Expander */ @@ -3593,7 +3637,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float if (ac->sl) { if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) { /* for F-Curves, draw color-preview of curve behind checkbox */ - if (ale->type == ANIMTYPE_FCURVE) { + if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) { FCurve *fcu = (FCurve *)ale->data; /* F-Curve channels need to have a special 'color code' box drawn, which is colored with whatever @@ -3639,7 +3683,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float UI_fontstyle_draw_simple(fstyle, offset, ytext, name); /* draw red underline if channel is disabled */ - if ((ale->type == ANIMTYPE_FCURVE) && (ale->flag & FCURVE_DISABLED)) { + if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE) && (ale->flag & FCURVE_DISABLED)) { /* FIXME: replace hardcoded color here, and check on extents! */ glColor3f(1.0f, 0.0f, 0.0f); glLineWidth(2.0); @@ -3706,7 +3750,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float * (only only F-Curves really can support them for now) * - slider should start before the toggles (if they're visible) to keep a clean line down the side */ - if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_SHAPEKEY)) { + if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_SHAPEKEY)) { /* adjust offset */ offset += SLIDER_WIDTH; } @@ -3895,7 +3939,7 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann //icon = ((enabled) ? ICON_VISIBLE_IPO_ON : ICON_VISIBLE_IPO_OFF); icon = ICON_VISIBLE_IPO_OFF; - if (ale->type == ANIMTYPE_FCURVE) + if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) tooltip = TIP_("F-Curve is visible in Graph Editor for editing"); else tooltip = TIP_("Channels are visible in Graph Editor for editing"); @@ -3930,7 +3974,7 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann //icon = ((enabled) ? ICON_MUTE_IPO_ON : ICON_MUTE_IPO_OFF); icon = ICON_MUTE_IPO_OFF; - if (ale->type == ANIMTYPE_FCURVE) { + if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) { tooltip = TIP_("Does F-Curve contribute to result"); } else if ((ac) && (ac->spacetype == SPACE_NLA) && (ale->type != ANIMTYPE_NLATRACK)) { @@ -4199,7 +4243,7 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle * and wouldn't be able to auto-keyframe... * - slider should start before the toggles (if they're visible) to keep a clean line down the side */ - if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_SHAPEKEY)) { + if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_SHAPEKEY)) { /* adjust offset */ // TODO: make slider width dynamic, so that they can be easier to use when the view is wide enough offset += SLIDER_WIDTH; @@ -4207,7 +4251,12 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle /* need backdrop behind sliders... */ UI_block_emboss_set(block, UI_EMBOSS); - if (ale->id) { /* Slider using RNA Access -------------------- */ + if (ale->owner) { /* Slider using custom RNA Access ---------- */ + if (ale->type == ANIMTYPE_NLACURVE) { + // TODO... + } + } + else if (ale->id) { /* Slider using RNA Access --------------- */ PointerRNA id_ptr, ptr; PropertyRNA *prop; char *rna_path = NULL; diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index d8ad6506186..85a4fd49b73 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -101,6 +101,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat break; } case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: { FCurve *fcu = (FCurve *)ale->data; @@ -157,6 +158,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat break; } case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: { FCurve *fcu = (FCurve *)channel_data; fcu->flag |= FCURVE_ACTIVE; @@ -255,6 +257,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d sel = ACHANNEL_SETFLAG_CLEAR; break; case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: if (ale->flag & FCURVE_SELECTED) sel = ACHANNEL_SETFLAG_CLEAR; break; @@ -339,6 +342,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d break; } case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: { FCurve *fcu = (FCurve *)ale->data; @@ -2727,7 +2731,8 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); break; } - case ANIMTYPE_FCURVE: + case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: { FCurve *fcu = (FCurve *)ale->data; @@ -2744,7 +2749,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, /* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */ if (fcu->flag & FCURVE_SELECTED) - ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE); + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type); notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); break; diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index b5d1de9c7d6..76bede8edaa 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1330,6 +1330,7 @@ static size_t animfilter_nla_controls(ListBase *anim_data, bDopeSheet *ads, Anim size_t items = 0; /* add control curves from each NLA strip... */ + /* NOTE: ANIMTYPE_FCURVES are created here, to avoid duplicating the code needed */ BEGIN_ANIMFILTER_SUBCHANNELS(((adt->flag & ADT_NLA_SKEYS_COLLAPSED) == 0)) { NlaTrack *nlt; @@ -1338,7 +1339,36 @@ static size_t animfilter_nla_controls(ListBase *anim_data, bDopeSheet *ads, Anim /* for now, we only go one level deep - so controls on grouped FCurves are not handled */ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { for (strip = nlt->strips.first; strip; strip = strip->next) { - tmp_items += animfilter_fcurves(&tmp_data, ads, strip->fcurves.first, NULL, filter_mode, owner_id); + ListBase strip_curves = {NULL, NULL}; + size_t strip_items = 0; + + /* create the raw items */ + strip_items += animfilter_fcurves(&strip_curves, ads, strip->fcurves.first, NULL, filter_mode, owner_id); + + /* change their types and add extra data + * - There is no point making a separate copy of animfilter_fcurves for this now/yet, + * unless we later get per-element control curves for other stuff too + */ + if (strip_items) { + bAnimListElem *ale, *ale_n = NULL; + + for (ale = strip_curves.first; ale; ale = ale_n) { + ale_n = ale->next; + + /* change the type to being a FCurve for editing NLA strip controls */ + BLI_assert(ale->type == ANIMTYPE_FCURVE); + + ale->type = ANIMTYPE_NLACURVE; + ale->owner = strip; + + ale->adt = NULL; /* XXX: This way, there are no problems with time mapping errors */ + } + } + + /* add strip curves to the set of channels inside the group being collected */ + BLI_movelisttolist(&tmp_data, &strip_curves); + BLI_assert(BLI_listbase_is_empty(&strip_curves)); + tmp_items += strip_items; } } } @@ -1346,8 +1376,6 @@ static size_t animfilter_nla_controls(ListBase *anim_data, bDopeSheet *ads, Anim /* did we find anything? */ if (tmp_items) { - /* TODO: apply extra tags to indicate the NLA mapping does not apply here! */ - /* add the expander as a channel first */ if (filter_mode & ANIMFILTER_LIST_CHANNELS) { /* currently these channels cannot be selected, so they should be skipped */ diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 829ea74f00f..9b4037ff455 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -116,12 +116,15 @@ typedef struct bAnimListElem { int index; /* for un-named data, the index of the data in its collection */ short update; /* (eAnim_Update_Flags) tag the element for updating */ + short datatype; /* (eAnim_KeyType) type of motion data to expect */ void *key_data; /* motion data - mostly F-Curves, but can be other types too */ struct ID *id; /* ID block that channel is attached to */ struct AnimData *adt; /* source of the animation data attached to ID block (for convenience) */ + + void *owner; /* for per-element F-Curves (e.g. NLA Control Curves), the element that this represents (e.g. NlaStrip) */ } bAnimListElem; @@ -142,6 +145,7 @@ typedef enum eAnim_ChannelType { ANIMTYPE_FCURVE, ANIMTYPE_NLACONTROLS, + ANIMTYPE_NLACURVE, ANIMTYPE_FILLACTD, ANIMTYPE_FILLDRIVERS, diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 95066b91725..0c2575e19f0 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -1156,7 +1156,7 @@ static void duplicate_action_keys(bAnimContext *ac) /* loop through filtered data and delete selected keys */ for (ale = anim_data.first; ale; ale = ale->next) { - if (ale->type == ANIMTYPE_FCURVE) + if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) duplicate_fcurve_keys((FCurve *)ale->key_data); else if (ale->type == ANIMTYPE_GPLAYER) ED_gplayer_frames_duplicate((bGPDlayer *)ale->data); diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index ddfca98a119..0f94baff082 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -1221,11 +1221,11 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_ agrp->flag |= AGRP_SELECTED; ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP); } - else if (ale->type == ANIMTYPE_FCURVE) { + else if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) { FCurve *fcu = ale->data; fcu->flag |= FCURVE_SELECTED; - ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE); + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type); } } } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 2c189b715c4..a74de31491a 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3584,7 +3584,7 @@ static void createTransActionData(bContext *C, TransInfo *t) else cfra = (float)CFRA; - if (ale->type == ANIMTYPE_FCURVE) + if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) count += count_fcurve_keys(ale->key_data, t->frame_side, cfra); else if (ale->type == ANIMTYPE_GPLAYER) count += count_gplayer_frames(ale->data, t->frame_side, cfra); -- cgit v1.2.3 From 182e84da88a8efd708a5423cf043643c62219cad Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 23 Mar 2015 00:01:13 +1300 Subject: Nla Strip Curves: Getting more stuff working * Clicking anywhere on the expander collapses it (like for the gpencil one) * Deleting these curves works now (but has the side effect of turning off the animated influence/time options too, as it is assumed that when those are enabled there is a corresponding fcurve) --- .../blender/editors/animation/anim_channels_edit.c | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 85a4fd49b73..b241d757486 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -1606,6 +1606,27 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op)) ANIM_fcurve_delete_from_animdata(&ac, adt, fcu); break; } + case ANIMTYPE_NLACURVE: + { + /* NLA Control Curve - Deleting it should disable the corresponding setting... */ + NlaStrip *strip = (NlaStrip *)ale->owner; + FCurve *fcu = (FCurve *)ale->data; + + if (STREQ(fcu->rna_path, "strip_time")) { + strip->flag &= ~NLASTRIP_FLAG_USR_TIME; + } + else if (STREQ(fcu->rna_path, "influence")) { + strip->flag &= ~NLASTRIP_FLAG_USR_INFLUENCE; + } + else { + printf("ERROR: Trying to delete NLA Control Curve for unknown property '%s'\n", fcu->rna_path); + } + + /* unlink and free the F-Curve */ + BLI_remlink(&strip->fcurves, fcu); + free_fcurve(fcu); + break; + } case ANIMTYPE_GPLAYER: { /* Grease Pencil layer */ @@ -2772,6 +2793,19 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); break; } + case ANIMTYPE_NLACONTROLS: + { + AnimData *adt = (AnimData *)ale->data; + + /* toggle expand + * - Although the triangle widget already allows this, since there's nothing else that can be done here now, + * let's just use it for easier expand/collapse for now + */ + adt->flag ^= ADT_NLA_SKEYS_COLLAPSED; + + notifierFlags |= (ND_ANIMCHAN | NA_EDITED); + break; + } case ANIMTYPE_GPDATABLOCK: { bGPdata *gpd = (bGPdata *)ale->data; -- cgit v1.2.3 From 34209b59b8bc7556a8c2227b877d9052c30bf37c Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 28 Mar 2015 00:25:20 +1300 Subject: Nla Strip Curves: This works with anim channel rearranging tools now --- .../blender/editors/animation/anim_channels_edit.c | 53 +++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index b241d757486..cf2fa9fffe1 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -851,6 +851,7 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr break; } case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: { FCurve *fcu = (FCurve *)channel; @@ -1195,6 +1196,40 @@ static void rearrange_action_channels(bAnimContext *ac, bAction *act, eRearrange /* ------------------- */ +static void rearrange_nla_control_channels(bAnimContext *ac, AnimData *adt, eRearrangeAnimChan_Mode mode) +{ + ListBase anim_data_visible = {NULL, NULL}; + + NlaTrack *nlt; + NlaStrip *strip; + + /* get rearranging function */ + AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode); + + if (rearrange_func == NULL) + return; + + /* skip if these curves aren't being shown */ + if (adt->flag & ADT_NLA_SKEYS_COLLAPSED) + return; + + /* Filter visible data. */ + rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLACURVE); + + /* we cannot rearrange between strips, but within each strip, we can rearrange those curves */ + for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { + for (strip = nlt->strips.first; strip; strip = strip->next) { + rearrange_animchannel_islands(&strip->fcurves, rearrange_func, mode, ANIMTYPE_NLACURVE, + &anim_data_visible); + } + } + + /* free temp data */ + BLI_freelistN(&anim_data_visible); +} + +/* ------------------- */ + static void rearrange_gpencil_channels(bAnimContext *ac, eRearrangeAnimChan_Mode mode) { ListBase anim_data = {NULL, NULL}; @@ -1282,13 +1317,29 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op) rearrange_driver_channels(&ac, adt, mode); break; + case ANIMCONT_ACTION: /* Single Action only... */ case ANIMCONT_SHAPEKEY: // DOUBLE CHECK ME... - default: /* some collection of actions */ + { if (adt->action) rearrange_action_channels(&ac, adt->action, mode); else if (G.debug & G_DEBUG) printf("Animdata has no action\n"); break; + } + + default: /* DopeSheet/Graph Editor - Some Actions + NLA Control Curves */ + { + /* NLA Control Curves */ + if (adt->nla_tracks.first) + rearrange_nla_control_channels(&ac, adt, mode); + + /* Action */ + if (adt->action) + rearrange_action_channels(&ac, adt->action, mode); + else if (G.debug & G_DEBUG) + printf("Animdata has no action\n"); + break; + } } } -- cgit v1.2.3 From 0ffd7f721e8066545e45ea2eb2766d1186cd2abb Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 28 Mar 2015 17:42:14 +1300 Subject: Nla Strip Keyframes: Sliders in channel list insert keyframes now --- .../editors/animation/anim_channels_defines.c | 56 +++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 72aa0c18cb3..71ace82fac0 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -3917,6 +3917,44 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi MEM_freeN(rna_path); } +/* callback for NLA Control Curve widget sliders - insert keyframes */ +static void achannel_setting_slider_nla_curve_cb(bContext *C, void *UNUSED(id_poin), void *fcu_poin) +{ + /* ID *id = (ID *)id_poin; */ + FCurve *fcu = (FCurve *)fcu_poin; + + PointerRNA ptr; + PropertyRNA *prop; + int index; + + ReportList *reports = CTX_wm_reports(C); + Scene *scene = CTX_data_scene(C); + short flag = 0; + bool done = false; + float cfra; + + /* get current frame - *no* NLA mapping should be done */ + cfra = (float)CFRA; + + /* get flags for keyframing */ + flag = ANIM_get_keyframing_flags(scene, 1); + + /* get pointer and property from the slider - this should all match up with the NlaStrip required... */ + UI_context_active_but_prop_get(C, &ptr, &prop, &index); + + if (fcu && prop) { + /* set the special 'replace' flag if on a keyframe */ + if (fcurve_frame_has_keyframe(fcu, cfra, 0)) + flag |= INSERTKEY_REPLACE; + + /* insert a keyframe for this F-Curve */ + done = insert_keyframe_direct(reports, ptr, prop, fcu, cfra, flag); + + if (done) + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + } +} + /* Draw a widget for some setting */ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChannelType *acf, uiBlock *block, int xpos, int ypos, int setting) @@ -4253,7 +4291,23 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle if (ale->owner) { /* Slider using custom RNA Access ---------- */ if (ale->type == ANIMTYPE_NLACURVE) { - // TODO... + NlaStrip *strip = (NlaStrip *)ale->owner; + FCurve *fcu = (FCurve *)ale->data; + PointerRNA ptr; + PropertyRNA *prop; + + /* create RNA pointers */ + RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, &ptr); + prop = RNA_struct_find_property(&ptr, fcu->rna_path); + + /* create property slider */ + if (prop) { + uiBut *but; + + /* create the slider button, and assign relevant callback to ensure keyframes are inserted... */ + but = uiDefAutoButR(block, &ptr, prop, fcu->array_index, "", ICON_NONE, (int)v2d->cur.xmax - offset, ymid, SLIDER_WIDTH, (int)ymaxc - yminc); + UI_but_func_set(but, achannel_setting_slider_nla_curve_cb, ale->id, ale->data); + } } } else if (ale->id) { /* Slider using RNA Access --------------- */ -- cgit v1.2.3 From 0c5d0422b4fb8b058826db9a7b0f11868aedaa0d Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 29 Mar 2015 02:20:57 +1300 Subject: NLA Strip Keyframes: Insert keyframe tools in Anim Editors work now * Insert Keyframe tool for Dopesheet/Graph Editors needed to be modified to not try to resolve the paths for NLA Control Curves * For now, the poll callback to get the "Active FCurve" also works when given a NLA control curve. They're really the same in most cases, and this should be fine until one of the channels does something funky. --- source/blender/editors/space_action/action_edit.c | 9 +++++++-- source/blender/editors/space_graph/graph_edit.c | 17 +++++++++++------ source/blender/editors/space_graph/graph_utils.c | 9 +++++++-- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 0c2575e19f0..740992a3ad4 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -1082,8 +1082,13 @@ static void insert_action_keys(bAnimContext *ac, short mode) else cfra = (float)CFRA; - /* if there's an id */ - if (ale->id) + /* read value from property the F-Curve represents, or from the curve only? + * - ale->id != NULL: Typically, this means that we have enough info to try resolving the path + * - ale->owner != NULL: If this is set, then the path may not be resolvable from the ID alone, + * so it's easier for now to just read the F-Curve directly. + * (TODO: add the full-blown PointerRNA relative parsing case here...) + */ + if (ale->id && !ale->owner) insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag); else insert_vert_fcurve(fcu, cfra, fcu->curval, 0); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 2944901663b..559eec8fe48 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -498,12 +498,17 @@ static void insert_graph_keys(bAnimContext *ac, short mode) else cfra = (float)CFRA; - /* if there's an id */ - if (ale->id) + /* read value from property the F-Curve represents, or from the curve only? + * - ale->id != NULL: Typically, this means that we have enough info to try resolving the path + * - ale->owner != NULL: If this is set, then the path may not be resolvable from the ID alone, + * so it's easier for now to just read the F-Curve directly. + * (TODO: add the full-blown PointerRNA relative parsing case here...) + */ + if (ale->id && !ale->owner) insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag); else insert_vert_fcurve(fcu, cfra, fcu->curval, 0); - + ale->update |= ANIM_UPDATE_DEFAULT; } @@ -596,12 +601,12 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op) /* insert keyframe on the specified frame + value */ insert_vert_fcurve(fcu, frame, val, 0); - + ale->update |= ANIM_UPDATE_DEPS; - + BLI_listbase_clear(&anim_data); BLI_addtail(&anim_data, ale); - + ANIM_animdata_update(&ac, &anim_data); } else { diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c index eea360ced45..0e56dc817e4 100644 --- a/source/blender/editors/space_graph/graph_utils.c +++ b/source/blender/editors/space_graph/graph_utils.c @@ -210,13 +210,18 @@ int graphop_active_fcurve_poll(bContext *C) if (ale == NULL) return 0; - /* free temp data... */ - has_fcurve = ((ale->data) && (ale->type == ANIMTYPE_FCURVE)); + /* do we have a suitable F-Curves? + * - For most cases, NLA Control Curves are sufficiently similar to NLA curves to serve this role too. + * Under the hood, they are F-Curves too. The only problems which will arise here are if these need to be + * in an Action too (but drivers would then also be affected!) + */ + has_fcurve = ((ale->data) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)); if (has_fcurve) { FCurve *fcu = (FCurve *)ale->data; has_fcurve = (fcu->flag & FCURVE_VISIBLE) != 0; } + /* free temp data... */ MEM_freeN(ale); /* return success */ -- cgit v1.2.3 From b253be1a1964e9ce2684a8fa1d3fa487b1513f19 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 29 Mar 2015 02:45:24 +1300 Subject: Nla Strip Keyframes: Active FCurve Keyframes panel displays names properly now (and doesn't disable the FCurves) --- source/blender/editors/space_graph/graph_buttons.c | 23 ++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index a2b64afdb15..f1e094c31ed 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -165,9 +165,28 @@ static void graph_panel_properties(const bContext *C, Panel *pa) RNA_pointer_create(ale->id, &RNA_FCurve, fcu, &fcu_ptr); /* user-friendly 'name' for F-Curve */ - /* TODO: only show the path if this is invalid? */ col = uiLayoutColumn(layout, false); - icon = getname_anim_fcurve(name, ale->id, fcu); + if (ale->type == ANIMTYPE_FCURVE) { + /* get user-friendly name for F-Curve */ + icon = getname_anim_fcurve(name, ale->id, fcu); + } + else { + /* NLA Control Curve, etc. */ + bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + + /* get name */ + if (acf && acf->name) { + acf->name(ale, name); + } + else { + strcpy(name, IFACE_("")); + icon = ICON_ERROR; + } + + /* icon */ + if (ale->type == ANIMTYPE_NLACURVE) + icon = ICON_NLA; + } uiItemL(col, name, icon); /* RNA-Path Editing - only really should be enabled when things aren't working */ -- cgit v1.2.3 From 7a1e7295a5618f271fcdd9d929982d820b772332 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 29 Mar 2015 03:03:05 +1300 Subject: NLA Strip Keyframes: Nullified the risk that NLA mapping can get applied to NLA Curves --- source/blender/editors/animation/anim_draw.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 0e052279796..c0ac42f3a5d 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -173,10 +173,14 @@ AnimData *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale) if (G.is_rendering) return NULL; /* handling depends on the type of animation-context we've got */ - if (ale) - return ale->adt; - else - return NULL; + if (ale) { + /* NLA Control Curves occur on NLA strips, and shouldn't be subjected to this kind of mapping */ + if (ale->type != ANIMTYPE_NLACURVE) + return ale->adt; + } + + /* cannot handle... */ + return NULL; } /* ------------------- */ -- cgit v1.2.3 From fcc086a92be9659b567a1ae8e91806700784dae9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 29 Mar 2015 01:25:47 +1100 Subject: Cleanup: unused args --- source/blender/editors/animation/anim_channels_defines.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 71ace82fac0..7eb32d4dc45 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -1045,13 +1045,13 @@ static void acf_nla_controls_backdrop(bAnimContext *ac, bAnimListElem *ale, floa } /* name for nla controls expander entries */ -static void acf_nla_controls_name(bAnimListElem *ale, char *name) +static void acf_nla_controls_name(bAnimListElem *UNUSED(ale), char *name) { BLI_strncpy(name, IFACE_("NLA Strip Controls"), ANIM_CHAN_NAME_SIZE); } /* check if some setting exists for this channel */ -static bool acf_nla_controls_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting) +static bool acf_nla_controls_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting) { /* for now, all settings are supported, though some are only conditionally */ switch (setting) { @@ -1067,7 +1067,7 @@ static bool acf_nla_controls_setting_valid(bAnimContext *ac, bAnimListElem *UNUS } /* get the appropriate flag(s) for the setting when it is valid */ -static int acf_nla_controls_setting_flag(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg) +static int acf_nla_controls_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) { /* clear extra return data first */ *neg = false; -- cgit v1.2.3 From 8c1c2b40a2131dc89e57ece3bc3b06c5a46f91d2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 28 Mar 2015 04:34:28 +1100 Subject: Use union for EditBone's Avoids complicated casts accessing as int --- source/blender/editors/armature/armature_add.c | 44 ++++++++++------------ .../blender/editors/armature/armature_relations.c | 2 +- source/blender/editors/armature/armature_select.c | 6 +-- source/blender/editors/armature/armature_utils.c | 20 +++++----- source/blender/editors/include/ED_armature.h | 14 +++++-- .../blender/editors/space_outliner/outliner_tree.c | 6 +-- 6 files changed, 48 insertions(+), 44 deletions(-) diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index 8074182c395..fb94c55f3da 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -283,12 +283,8 @@ static EditBone *get_named_editbone(ListBase *edbo, const char *name) * */ void preEditBoneDuplicate(ListBase *editbones) { - EditBone *eBone; - /* clear temp */ - for (eBone = editbones->first; eBone; eBone = eBone->next) { - eBone->temp = NULL; - } + ED_armature_ebone_listbase_temp_clear(editbones); } /* @@ -328,8 +324,8 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Obj * so, update the constraint to point at the * duplicate of the old subtarget. */ - if (oldtarget->temp) { - newtarget = (EditBone *) oldtarget->temp; + if (oldtarget->temp.ebone) { + newtarget = oldtarget->temp.ebone; BLI_strncpy(ct->subtarget, newtarget->name, sizeof(ct->subtarget)); } } @@ -358,8 +354,8 @@ EditBone *duplicateEditBoneObjects(EditBone *curBone, const char *name, ListBase /* Copy data from old bone to new bone */ memcpy(eBone, curBone, sizeof(EditBone)); - curBone->temp = eBone; - eBone->temp = curBone; + curBone->temp.ebone = eBone; + eBone->temp.ebone = curBone; if (name != NULL) { BLI_strncpy(eBone->name, name, sizeof(eBone->name)); @@ -453,7 +449,7 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op)) if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED)) { - EditBone *ebone = ebone_iter->temp; + EditBone *ebone = ebone_iter->temp.ebone; if (!ebone_iter->parent) { /* If this bone has no parent, @@ -461,11 +457,11 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op)) */ ebone->parent = NULL; } - else if (ebone_iter->parent->temp) { + else if (ebone_iter->parent->temp.ebone) { /* If this bone has a parent that was duplicated, * Set the duplicate->parent to the curBone->parent->temp */ - ebone->parent = (EditBone *)ebone_iter->parent->temp; + ebone->parent = ebone_iter->parent->temp.ebone; } else { /* If this bone has a parent that IS not selected, @@ -483,8 +479,8 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op)) } /* correct the active bone */ - if (arm->act_edbone && arm->act_edbone->temp) { - arm->act_edbone = arm->act_edbone->temp; + if (arm->act_edbone && arm->act_edbone->temp.ebone) { + arm->act_edbone = arm->act_edbone->temp.ebone; } /* Deselect the old bones and select the new ones */ @@ -560,7 +556,7 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) if (ebone) { if ((ebone->flag & BONE_SELECTED) == 0) { /* simple case, we're selected, the other bone isn't! */ - ebone_iter->temp = ebone; + ebone_iter->temp.ebone = ebone; } else { /* complicated - choose which direction to copy */ @@ -590,7 +586,7 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) ebone_dst = ebone; } - ebone_src->temp = ebone_dst; + ebone_src->temp.ebone = ebone_dst; ebone_dst->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); } } @@ -604,7 +600,7 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED) && /* will be set if the mirror bone already exists (no need to make a new one) */ - (ebone_iter->temp == NULL)) + (ebone_iter->temp.ebone == NULL)) { char name_flip[MAX_VGROUP_NAME]; @@ -625,11 +621,11 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) /* Run though the list and fix the pointers */ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) { - if (ebone_iter->temp) { + if (ebone_iter->temp.ebone) { /* copy all flags except for ... */ const int flag_copy = ((int)~0) & ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL); - EditBone *ebone = ebone_iter->temp; + EditBone *ebone = ebone_iter->temp.ebone; /* copy flags incase bone is pre-existing data */ ebone->flag = (ebone->flag & ~flag_copy) | (ebone_iter->flag & flag_copy); @@ -644,8 +640,8 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) else { /* the parent may have been duplicated, if not lookup the mirror parent */ EditBone *ebone_parent = - (ebone_iter->parent->temp ? - ebone_iter->parent->temp : ED_armature_bone_get_mirrored(arm->edbo, ebone_iter->parent)); + (ebone_iter->parent->temp.ebone ? + ebone_iter->parent->temp.ebone : ED_armature_bone_get_mirrored(arm->edbo, ebone_iter->parent)); if (ebone_parent == NULL) { /* If the mirror lookup failed, (but the current bone has a parent) @@ -680,15 +676,15 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) /* New bones will be selected, but some of the bones may already exist */ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) { - EditBone *ebone = ebone_iter->temp; + EditBone *ebone = ebone_iter->temp.ebone; if (ebone && EBONE_SELECTABLE(arm, ebone)) { ED_armature_ebone_select_set(ebone, true); } } /* correct the active bone */ - if (arm->act_edbone && arm->act_edbone->temp) { - arm->act_edbone = arm->act_edbone->temp; + if (arm->act_edbone && arm->act_edbone->temp.ebone) { + arm->act_edbone = arm->act_edbone->temp.ebone; } ED_armature_validate_active(arm); diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index 53989dd783c..4eb2159aee1 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -548,7 +548,7 @@ static void separate_armature_bones(Object *ob, short sel) for (ebo = arm->edbo->first; ebo; ebo = ebo->next) { if (ebo->parent == curbone) { ebo->parent = NULL; - ebo->temp = NULL; /* this is needed to prevent random crashes with in ED_armature_from_edit */ + ebo->temp.p = NULL; /* this is needed to prevent random crashes with in ED_armature_from_edit */ ebo->flag &= ~BONE_CONNECTED; } } diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 720b9b7821a..c89c68ff46d 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -55,8 +55,8 @@ #include "armature_intern.h" /* utility macros fro storing a temp int in the bone (selection flag) */ -#define EBONE_PREV_FLAG_GET(ebone) ((void)0, (GET_INT_FROM_POINTER((ebone)->temp))) -#define EBONE_PREV_FLAG_SET(ebone, val) ((ebone)->temp = SET_INT_IN_POINTER(val)) +#define EBONE_PREV_FLAG_GET(ebone) ((void)0, (ebone)->temp.i) +#define EBONE_PREV_FLAG_SET(ebone, val) ((ebone)->temp.i = val) /* **************** PoseMode & EditMode Selection Buffer Queries *************************** */ @@ -685,7 +685,7 @@ static void armature_select_more_less(Object *ob, bool more) } } } - ebone->temp = NULL; + ebone->temp.p = NULL; } ED_armature_sync_selection(arm->edbo); diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index 97f69d86aee..18351950462 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -488,7 +488,7 @@ static void fix_bonelist_roll(ListBase *bonelist, ListBase *editbonelist) /* Find the associated editbone */ for (ebone = editbonelist->first; ebone; ebone = ebone->next) - if ((Bone *)ebone->temp == curBone) + if (ebone->temp.bone == curBone) break; if (ebone) { @@ -548,7 +548,7 @@ void ED_armature_from_edit(bArmature *arm) /* Copy the bones from the editData into the armature */ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { newBone = MEM_callocN(sizeof(Bone), "bone"); - eBone->temp = newBone; /* Associate the real Bones with the EditBones */ + eBone->temp.bone = newBone; /* Associate the real Bones with the EditBones */ BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name)); copy_v3_v3(newBone->arm_head, eBone->head); @@ -584,9 +584,9 @@ void ED_armature_from_edit(bArmature *arm) /* Fix parenting in a separate pass to ensure ebone->bone connections * are valid at this point */ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { - newBone = (Bone *)eBone->temp; + newBone = eBone->temp.bone; if (eBone->parent) { - newBone->parent = (Bone *)eBone->parent->temp; + newBone->parent = eBone->parent->temp.bone; BLI_addtail(&newBone->parent->childbase, newBone); { @@ -695,24 +695,24 @@ static void ED_armature_ebone_listbase_copy(ListBase *lb_dst, ListBase *lb_src) if (ebone_dst->prop) { ebone_dst->prop = IDP_CopyProperty(ebone_dst->prop); } - ebone_src->temp = ebone_dst; + ebone_src->temp.ebone = ebone_dst; BLI_addtail(lb_dst, ebone_dst); } /* set pointers */ for (ebone_dst = lb_dst->first; ebone_dst; ebone_dst = ebone_dst->next) { if (ebone_dst->parent) { - ebone_dst->parent = ebone_dst->parent->temp; + ebone_dst->parent = ebone_dst->parent->temp.ebone; } } } -static void ED_armature_ebone_listbase_temp_clear(ListBase *lb) +void ED_armature_ebone_listbase_temp_clear(ListBase *lb) { EditBone *ebone; /* be sure they don't hang ever */ for (ebone = lb->first; ebone; ebone = ebone->next) { - ebone->temp = NULL; + ebone->temp.p = NULL; } } @@ -733,7 +733,7 @@ static void undoBones_to_editBones(void *uarmv, void *armv, void *UNUSED(data)) /* active bone */ if (uarm->act_edbone) { ebone = uarm->act_edbone; - arm->act_edbone = ebone->temp; + arm->act_edbone = ebone->temp.ebone; } else { arm->act_edbone = NULL; @@ -755,7 +755,7 @@ static void *editBones_to_undoBones(void *armv, void *UNUSED(obdata)) /* active bone */ if (arm->act_edbone) { ebone = arm->act_edbone; - uarm->act_edbone = ebone->temp; + uarm->act_edbone = ebone->temp.ebone; } ED_armature_ebone_listbase_temp_clear(&uarm->lb); diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index da756422bdb..9345cd83b49 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -59,8 +59,6 @@ typedef struct EditBone { struct EditBone *parent; /* Editbones have a one-way link (i.e. children refer * to parents. This is converted to a two-way link for * normal bones when leaving editmode. */ - void *temp; /* Used to store temporary data */ - char name[64]; /* MAXBONENAME */ float roll; /* Roll along axis. We'll ultimately use the axis/angle method * for determining the transformation matrix of the bone. The axis @@ -83,6 +81,14 @@ typedef struct EditBone { float oldlength; /* for envelope scaling */ short segments; + + /* Used to store temporary data */ + union { + struct EditBone *ebone; + struct Bone *bone; + void *p; + int i; + } temp; } EditBone; #define BONESEL_ROOT (1 << 28) @@ -119,10 +125,12 @@ void ED_keymap_armature(struct wmKeyConfig *keyconf); void ED_armature_from_edit(struct bArmature *arm); void ED_armature_to_edit(struct bArmature *arm); void ED_armature_edit_free(struct bArmature *arm); +void ED_armature_ebone_listbase_temp_clear(struct ListBase *lb); + void ED_armature_deselect_all(struct Object *obedit); void ED_armature_deselect_all_visible(struct Object *obedit); -int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, +int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, short hits, bool extend, bool deselect, bool toggle, bool do_nearest); bool mouse_armature(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); int join_armature_exec(struct bContext *C, struct wmOperator *op); diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 7aac6a7797c..9239d9cb27e 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -769,16 +769,16 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor ten = outliner_add_element(soops, &te->subtree, id, te, TSE_EBONE, a); ten->directdata = ebone; ten->name = ebone->name; - ebone->temp = ten; + ebone->temp.p = ten; } /* make hierarchy */ - ten = arm->edbo->first ? ((EditBone *)arm->edbo->first)->temp : NULL; + ten = arm->edbo->first ? ((EditBone *)arm->edbo->first)->temp.p : NULL; while (ten) { TreeElement *nten = ten->next, *par; ebone = (EditBone *)ten->directdata; if (ebone->parent) { BLI_remlink(&te->subtree, ten); - par = ebone->parent->temp; + par = ebone->parent->temp.p; BLI_addtail(&par->subtree, ten); ten->parent = par; } -- cgit v1.2.3 From 8a183aa26bc34fe441ba1ad3e5f2c307ed54f6b7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 29 Mar 2015 03:16:55 +1100 Subject: Cleanup: use BKE_texture_ prefix --- source/blender/blenkernel/BKE_texture.h | 64 ++++++------ source/blender/blenkernel/intern/brush.c | 6 +- source/blender/blenkernel/intern/texture.c | 110 ++++++++++----------- source/blender/blenloader/intern/versioning_250.c | 4 +- source/blender/blenloader/intern/versioning_260.c | 2 +- source/blender/editors/render/render_preview.c | 2 +- source/blender/editors/render/render_shading.c | 6 +- .../editors/sculpt_paint/paint_image_proj.c | 4 +- source/blender/makesrna/intern/rna_main_api.c | 4 +- source/blender/makesrna/intern/rna_material.c | 4 +- source/blender/makesrna/intern/rna_nodetree.c | 2 +- source/blender/makesrna/intern/rna_texture.c | 6 +- source/blender/makesrna/intern/rna_texture_api.c | 2 +- .../composite/nodes/node_composite_mapValue.c | 2 +- .../nodes/shader/nodes/node_shader_mapping.c | 2 +- .../nodes/shader/nodes/node_shader_tex_brick.c | 4 +- .../nodes/shader/nodes/node_shader_tex_checker.c | 4 +- .../shader/nodes/node_shader_tex_environment.c | 4 +- .../nodes/shader/nodes/node_shader_tex_gradient.c | 4 +- .../nodes/shader/nodes/node_shader_tex_image.c | 4 +- .../nodes/shader/nodes/node_shader_tex_magic.c | 4 +- .../nodes/shader/nodes/node_shader_tex_musgrave.c | 4 +- .../nodes/shader/nodes/node_shader_tex_noise.c | 4 +- .../nodes/shader/nodes/node_shader_tex_sky.c | 4 +- .../nodes/shader/nodes/node_shader_tex_voronoi.c | 4 +- .../nodes/shader/nodes/node_shader_tex_wave.c | 4 +- .../nodes/texture/nodes/node_texture_proc.c | 2 +- source/blender/render/intern/source/envmap.c | 10 +- .../blender/render/intern/source/render_texture.c | 6 +- 29 files changed, 141 insertions(+), 141 deletions(-) diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index 03ddbb706d7..ad485931ee3 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -61,8 +61,6 @@ struct World; #define MAXCOLORBAND 32 -void BKE_texture_free(struct Tex *t); - void init_colorband(struct ColorBand *coba, bool rangetype); struct ColorBand *add_colorband(bool rangetype); bool do_colorband(const struct ColorBand *coba, float in, float out[4]); @@ -71,15 +69,17 @@ struct CBData *colorband_element_add(struct ColorBand *coba, float position); int colorband_element_remove(struct ColorBand *coba, int index); void colorband_update_sort(struct ColorBand *coba); -void default_tex(struct Tex *tex); -struct Tex *add_texture(struct Main *bmain, const char *name); -void tex_set_type(struct Tex *tex, int type); -void default_mtex(struct MTex *mtex); -struct MTex *add_mtex(void); -struct MTex *add_mtex_id(struct ID *id, int slot); -struct Tex *BKE_texture_copy(struct Tex *tex); -struct Tex *localize_texture(struct Tex *tex); -void BKE_texture_make_local(struct Tex *tex); +void BKE_texture_free(struct Tex *tex); +void BKE_texture_default(struct Tex *tex); +struct Tex *BKE_texture_copy(struct Tex *tex); +struct Tex *BKE_texture_add(struct Main *bmain, const char *name); +struct Tex *BKE_texture_localize(struct Tex *tex); +void BKE_texture_make_local(struct Tex *tex); +void BKE_texture_type_set(struct Tex *tex, int type); + +void BKE_texture_mtex_default(struct MTex *mtex); +struct MTex *BKE_texture_mtex_add(void); +struct MTex *BKE_texture_mtex_add_id(struct ID *id, int slot); /* UNUSED */ // void autotexname(struct Tex *tex); @@ -105,32 +105,32 @@ void set_current_particle_texture(struct ParticleSettings *part, struct Tex *tex bool has_current_material_texture(struct Material *ma); -struct TexMapping *add_tex_mapping(int type); -void default_tex_mapping(struct TexMapping *texmap, int type); -void init_tex_mapping(struct TexMapping *texmap); +struct TexMapping *BKE_texture_mapping_add(int type); +void BKE_texture_mapping_default(struct TexMapping *texmap, int type); +void BKE_texture_mapping_init(struct TexMapping *texmap); + +struct ColorMapping *BKE_texture_colormapping_add(void); +void BKE_texture_colormapping_default(struct ColorMapping *colormap); -struct ColorMapping *add_color_mapping(void); -void default_color_mapping(struct ColorMapping *colormap); +void BKE_texture_envmap_free_data(struct EnvMap *env); +void BKE_texture_envmap_free(struct EnvMap *env); +struct EnvMap *BKE_texture_envmap_add(void); +struct EnvMap *BKE_texture_envmap_copy(struct EnvMap *env); -void BKE_free_envmapdata(struct EnvMap *env); -void BKE_free_envmap(struct EnvMap *env); -struct EnvMap *BKE_add_envmap(void); -struct EnvMap *BKE_copy_envmap(struct EnvMap *env); +void BKE_texture_pointdensity_free_data(struct PointDensity *pd); +void BKE_texture_pointdensity_free(struct PointDensity *pd); +struct PointDensity *BKE_texture_pointdensity_add(void); +struct PointDensity *BKE_texture_pointdensity_copy(struct PointDensity *pd); -void BKE_free_pointdensitydata(struct PointDensity *pd); -void BKE_free_pointdensity(struct PointDensity *pd); -struct PointDensity *BKE_add_pointdensity(void); -struct PointDensity *BKE_copy_pointdensity(struct PointDensity *pd); +void BKE_texture_voxeldata_free_data(struct VoxelData *vd); +void BKE_texture_voxeldata_free(struct VoxelData *vd); +struct VoxelData *BKE_texture_voxeldata_add(void); +struct VoxelData *BKE_texture_voxeldata_copy(struct VoxelData *vd); -void BKE_free_voxeldatadata(struct VoxelData *vd); -void BKE_free_voxeldata(struct VoxelData *vd); -struct VoxelData *BKE_add_voxeldata(void); -struct VoxelData *BKE_copy_voxeldata(struct VoxelData *vd); +void BKE_texture_ocean_free(struct OceanTex *ot); +struct OceanTex *BKE_texture_ocean_add(void); +struct OceanTex *BKE_texture_ocean_copy(struct OceanTex *ot); -void BKE_free_oceantex(struct OceanTex *ot); -struct OceanTex *BKE_add_oceantex(void); -struct OceanTex *BKE_copy_oceantex(struct OceanTex *ot); - bool BKE_texture_dependsOnTime(const struct Tex *texture); bool BKE_texture_is_image_user(const struct Tex *tex); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 10d77921515..661bf6e7d76 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -103,8 +103,8 @@ static void brush_defaults(Brush *brush) brush->jitter = 0.0f; /* BRUSH TEXTURE SETTINGS */ - default_mtex(&brush->mtex); - default_mtex(&brush->mask_mtex); + BKE_texture_mtex_default(&brush->mtex); + BKE_texture_mtex_default(&brush->mask_mtex); brush->texture_sample_bias = 0; /* value to added to texture samples */ brush->texture_overlay_alpha = 33; @@ -469,7 +469,7 @@ int BKE_brush_texture_set_nr(Brush *brush, int nr) idtest = (ID *)BLI_findlink(&G.main->tex, nr - 1); if (idtest == NULL) { /* new tex */ if (id) idtest = (ID *)BKE_texture_copy((Tex *)id); - else idtest = (ID *)add_texture(G.main, "Tex"); + else idtest = (ID *)BKE_texture_add(G.main, "Tex"); idtest->us--; } if (idtest != id) { diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 07b1e9e30ac..7e7bcace30d 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -73,16 +73,16 @@ /* ****************** Mapping ******************* */ -TexMapping *add_tex_mapping(int type) +TexMapping *BKE_texture_mapping_add(int type) { TexMapping *texmap = MEM_callocN(sizeof(TexMapping), "TexMapping"); - default_tex_mapping(texmap, type); + BKE_texture_mapping_default(texmap, type); return texmap; } -void default_tex_mapping(TexMapping *texmap, int type) +void BKE_texture_mapping_default(TexMapping *texmap, int type) { memset(texmap, 0, sizeof(TexMapping)); @@ -97,7 +97,7 @@ void default_tex_mapping(TexMapping *texmap, int type) texmap->type = type; } -void init_tex_mapping(TexMapping *texmap) +void BKE_texture_mapping_init(TexMapping *texmap) { float smat[4][4], rmat[4][4], tmat[4][4], proj[4][4], size[3]; @@ -170,16 +170,16 @@ void init_tex_mapping(TexMapping *texmap) } } -ColorMapping *add_color_mapping(void) +ColorMapping *BKE_texture_colormapping_add(void) { ColorMapping *colormap = MEM_callocN(sizeof(ColorMapping), "ColorMapping"); - default_color_mapping(colormap); + BKE_texture_colormapping_default(colormap); return colormap; } -void default_color_mapping(ColorMapping *colormap) +void BKE_texture_colormapping_default(ColorMapping *colormap) { memset(colormap, 0, sizeof(ColorMapping)); @@ -560,10 +560,10 @@ int colorband_element_remove(struct ColorBand *coba, int index) void BKE_texture_free(Tex *tex) { if (tex->coba) MEM_freeN(tex->coba); - if (tex->env) BKE_free_envmap(tex->env); - if (tex->pd) BKE_free_pointdensity(tex->pd); - if (tex->vd) BKE_free_voxeldata(tex->vd); - if (tex->ot) BKE_free_oceantex(tex->ot); + if (tex->env) BKE_texture_envmap_free(tex->env); + if (tex->pd) BKE_texture_pointdensity_free(tex->pd); + if (tex->vd) BKE_texture_voxeldata_free(tex->vd); + if (tex->ot) BKE_texture_ocean_free(tex->ot); BKE_free_animdata((struct ID *)tex); BKE_previewimg_free(&tex->preview); @@ -578,7 +578,7 @@ void BKE_texture_free(Tex *tex) /* ------------------------------------------------------------------------- */ -void default_tex(Tex *tex) +void BKE_texture_default(Tex *tex) { tex->type = TEX_IMAGE; tex->ima = NULL; @@ -657,25 +657,25 @@ void default_tex(Tex *tex) tex->preview = NULL; } -void tex_set_type(Tex *tex, int type) +void BKE_texture_type_set(Tex *tex, int type) { switch (type) { case TEX_VOXELDATA: if (tex->vd == NULL) - tex->vd = BKE_add_voxeldata(); + tex->vd = BKE_texture_voxeldata_add(); break; case TEX_POINTDENSITY: if (tex->pd == NULL) - tex->pd = BKE_add_pointdensity(); + tex->pd = BKE_texture_pointdensity_add(); break; case TEX_ENVMAP: if (tex->env == NULL) - tex->env = BKE_add_envmap(); + tex->env = BKE_texture_envmap_add(); break; case TEX_OCEAN: if (tex->ot == NULL) - tex->ot = BKE_add_oceantex(); + tex->ot = BKE_texture_ocean_add(); break; } @@ -684,20 +684,20 @@ void tex_set_type(Tex *tex, int type) /* ------------------------------------------------------------------------- */ -Tex *add_texture(Main *bmain, const char *name) +Tex *BKE_texture_add(Main *bmain, const char *name) { Tex *tex; tex = BKE_libblock_alloc(bmain, ID_TE, name); - default_tex(tex); + BKE_texture_default(tex); return tex; } /* ------------------------------------------------------------------------- */ -void default_mtex(MTex *mtex) +void BKE_texture_mtex_default(MTex *mtex) { mtex->texco = TEXCO_UV; mtex->mapto = MAP_COL; @@ -767,19 +767,19 @@ void default_mtex(MTex *mtex) /* ------------------------------------------------------------------------- */ -MTex *add_mtex(void) +MTex *BKE_texture_mtex_add(void) { MTex *mtex; - mtex = MEM_callocN(sizeof(MTex), "add_mtex"); + mtex = MEM_callocN(sizeof(MTex), "BKE_texture_mtex_add"); - default_mtex(mtex); + BKE_texture_mtex_default(mtex); return mtex; } /* slot -1 for first free ID */ -MTex *add_mtex_id(ID *id, int slot) +MTex *BKE_texture_mtex_add_id(ID *id, int slot) { MTex **mtex_ar; short act; @@ -820,7 +820,7 @@ MTex *add_mtex_id(ID *id, int slot) ((Material *)id)->septex &= ~(1 << slot); } - mtex_ar[slot] = add_mtex(); + mtex_ar[slot] = BKE_texture_mtex_add(); return mtex_ar[slot]; } @@ -840,10 +840,10 @@ Tex *BKE_texture_copy(Tex *tex) } if (texn->coba) texn->coba = MEM_dupallocN(texn->coba); - if (texn->env) texn->env = BKE_copy_envmap(texn->env); - if (texn->pd) texn->pd = BKE_copy_pointdensity(texn->pd); + if (texn->env) texn->env = BKE_texture_envmap_copy(texn->env); + if (texn->pd) texn->pd = BKE_texture_pointdensity_copy(texn->pd); if (texn->vd) texn->vd = MEM_dupallocN(texn->vd); - if (texn->ot) texn->ot = BKE_copy_oceantex(texn->ot); + if (texn->ot) texn->ot = BKE_texture_ocean_copy(texn->ot); if (tex->preview) texn->preview = BKE_previewimg_copy(tex->preview); if (tex->nodetree) { @@ -861,7 +861,7 @@ Tex *BKE_texture_copy(Tex *tex) } /* texture copy without adding to main dbase */ -Tex *localize_texture(Tex *tex) +Tex *BKE_texture_localize(Tex *tex) { Tex *texn; @@ -871,17 +871,17 @@ Tex *localize_texture(Tex *tex) if (texn->coba) texn->coba = MEM_dupallocN(texn->coba); if (texn->env) { - texn->env = BKE_copy_envmap(texn->env); + texn->env = BKE_texture_envmap_copy(texn->env); id_us_min(&texn->env->ima->id); } - if (texn->pd) texn->pd = BKE_copy_pointdensity(texn->pd); + if (texn->pd) texn->pd = BKE_texture_pointdensity_copy(texn->pd); if (texn->vd) { texn->vd = MEM_dupallocN(texn->vd); if (texn->vd->dataset) texn->vd->dataset = MEM_dupallocN(texn->vd->dataset); } if (texn->ot) { - texn->ot = BKE_copy_oceantex(tex->ot); + texn->ot = BKE_texture_ocean_copy(tex->ot); } texn->preview = NULL; @@ -1132,7 +1132,7 @@ void set_current_lamp_texture(Lamp *la, Tex *newtex) if (newtex) { if (!la->mtex[act]) { - la->mtex[act] = add_mtex(); + la->mtex[act] = BKE_texture_mtex_add(); la->mtex[act]->texco = TEXCO_GLOB; } @@ -1167,7 +1167,7 @@ void set_current_linestyle_texture(FreestyleLineStyle *linestyle, Tex *newtex) if (newtex) { if (!linestyle->mtex[act]) { - linestyle->mtex[act] = add_mtex(); + linestyle->mtex[act] = BKE_texture_mtex_add(); linestyle->mtex[act]->texco = TEXCO_STROKE; } @@ -1296,7 +1296,7 @@ void set_current_material_texture(Material *ma, Tex *newtex) if (newtex) { if (!ma->mtex[act]) { - ma->mtex[act] = add_mtex(); + ma->mtex[act] = BKE_texture_mtex_add(); /* Reset this slot's ON/OFF toggle, for materials, when slot was empty. */ ma->septex &= ~(1 << act); } @@ -1347,7 +1347,7 @@ void set_current_world_texture(World *wo, Tex *newtex) if (newtex) { if (!wo->mtex[act]) { - wo->mtex[act] = add_mtex(); + wo->mtex[act] = BKE_texture_mtex_add(); wo->mtex[act]->texco = TEXCO_VIEW; } @@ -1398,7 +1398,7 @@ void set_current_particle_texture(ParticleSettings *part, Tex *newtex) if (newtex) { if (!part->mtex[act]) { - part->mtex[act] = add_mtex(); + part->mtex[act] = BKE_texture_mtex_add(); part->mtex[act]->texco = TEXCO_ORCO; part->mtex[act]->blendtype = MTEX_MUL; } @@ -1414,7 +1414,7 @@ void set_current_particle_texture(ParticleSettings *part, Tex *newtex) /* ------------------------------------------------------------------------- */ -EnvMap *BKE_add_envmap(void) +EnvMap *BKE_texture_envmap_add(void) { EnvMap *env; @@ -1431,7 +1431,7 @@ EnvMap *BKE_add_envmap(void) /* ------------------------------------------------------------------------- */ -EnvMap *BKE_copy_envmap(EnvMap *env) +EnvMap *BKE_texture_envmap_copy(EnvMap *env) { EnvMap *envn; int a; @@ -1446,7 +1446,7 @@ EnvMap *BKE_copy_envmap(EnvMap *env) /* ------------------------------------------------------------------------- */ -void BKE_free_envmapdata(EnvMap *env) +void BKE_texture_envmap_free_data(EnvMap *env) { unsigned int part; @@ -1460,17 +1460,17 @@ void BKE_free_envmapdata(EnvMap *env) /* ------------------------------------------------------------------------- */ -void BKE_free_envmap(EnvMap *env) +void BKE_texture_envmap_free(EnvMap *env) { - BKE_free_envmapdata(env); + BKE_texture_envmap_free_data(env); MEM_freeN(env); } /* ------------------------------------------------------------------------- */ -PointDensity *BKE_add_pointdensity(void) +PointDensity *BKE_texture_pointdensity_add(void) { PointDensity *pd; @@ -1502,7 +1502,7 @@ PointDensity *BKE_add_pointdensity(void) return pd; } -PointDensity *BKE_copy_pointdensity(PointDensity *pd) +PointDensity *BKE_texture_pointdensity_copy(PointDensity *pd) { PointDensity *pdn; @@ -1514,7 +1514,7 @@ PointDensity *BKE_copy_pointdensity(PointDensity *pd) return pdn; } -void BKE_free_pointdensitydata(PointDensity *pd) +void BKE_texture_pointdensity_free_data(PointDensity *pd) { if (pd->point_tree) { BLI_bvhtree_free(pd->point_tree); @@ -1532,15 +1532,15 @@ void BKE_free_pointdensitydata(PointDensity *pd) curvemapping_free(pd->falloff_curve); /* can be NULL */ } -void BKE_free_pointdensity(PointDensity *pd) +void BKE_texture_pointdensity_free(PointDensity *pd) { - BKE_free_pointdensitydata(pd); + BKE_texture_pointdensity_free_data(pd); MEM_freeN(pd); } /* ------------------------------------------------------------------------- */ -void BKE_free_voxeldatadata(VoxelData *vd) +void BKE_texture_voxeldata_free_data(VoxelData *vd) { if (vd->dataset) { MEM_freeN(vd->dataset); @@ -1549,13 +1549,13 @@ void BKE_free_voxeldatadata(VoxelData *vd) } -void BKE_free_voxeldata(VoxelData *vd) +void BKE_texture_voxeldata_free(VoxelData *vd) { - BKE_free_voxeldatadata(vd); + BKE_texture_voxeldata_free_data(vd); MEM_freeN(vd); } -VoxelData *BKE_add_voxeldata(void) +VoxelData *BKE_texture_voxeldata_add(void) { VoxelData *vd; @@ -1573,7 +1573,7 @@ VoxelData *BKE_add_voxeldata(void) return vd; } -VoxelData *BKE_copy_voxeldata(VoxelData *vd) +VoxelData *BKE_texture_voxeldata_copy(VoxelData *vd) { VoxelData *vdn; @@ -1585,7 +1585,7 @@ VoxelData *BKE_copy_voxeldata(VoxelData *vd) /* ------------------------------------------------------------------------- */ -OceanTex *BKE_add_oceantex(void) +OceanTex *BKE_texture_ocean_add(void) { OceanTex *ot; @@ -1596,14 +1596,14 @@ OceanTex *BKE_add_oceantex(void) return ot; } -OceanTex *BKE_copy_oceantex(struct OceanTex *ot) +OceanTex *BKE_texture_ocean_copy(struct OceanTex *ot) { OceanTex *otn = MEM_dupallocN(ot); return otn; } -void BKE_free_oceantex(struct OceanTex *ot) +void BKE_texture_ocean_free(struct OceanTex *ot) { MEM_freeN(ot); } diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 2094aeb1485..274fc474ade 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -1652,8 +1652,8 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main) /* brush texture changes */ for (brush = main->brush.first; brush; brush = brush->id.next) { - default_mtex(&brush->mtex); - default_mtex(&brush->mask_mtex); + BKE_texture_mtex_default(&brush->mtex); + BKE_texture_mtex_default(&brush->mask_mtex); } for (ma = main->mat.first; ma; ma = ma->id.next) { diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index 10526a191d2..734dc33ea24 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -2096,7 +2096,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main) if (!MAIN_VERSION_ATLEAST(main, 266, 4)) { Brush *brush; for (brush = main->brush.first; brush; brush = brush->id.next) { - default_mtex(&brush->mask_mtex); + BKE_texture_mtex_default(&brush->mask_mtex); if (brush->ob_mode & OB_MODE_TEXTURE_PAINT) { brush->spacing /= 2; diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 99edaff759e..9dbd2e88563 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -423,7 +423,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre Tex *tex = NULL, *origtex = (Tex *)id; if (origtex) { - tex = localize_texture(origtex); + tex = BKE_texture_localize(origtex); sp->texcopy = tex; BLI_addtail(&pr_main->tex, tex); } diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 75b8b8cebde..cf712a653e6 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -450,7 +450,7 @@ static int new_texture_exec(bContext *C, wmOperator *UNUSED(op)) tex = BKE_texture_copy(tex); } else { - tex = add_texture(bmain, DATA_("Texture")); + tex = BKE_texture_add(bmain, DATA_("Texture")); } /* hook into UI */ @@ -1492,7 +1492,7 @@ static int envmap_clear_exec(bContext *C, wmOperator *UNUSED(op)) { Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data; - BKE_free_envmapdata(tex->env); + BKE_texture_envmap_free_data(tex->env); WM_event_add_notifier(C, NC_TEXTURE | NA_EDITED, tex); @@ -1535,7 +1535,7 @@ static int envmap_clear_all_exec(bContext *C, wmOperator *UNUSED(op)) for (tex = bmain->tex.first; tex; tex = tex->id.next) if (tex->env) - BKE_free_envmapdata(tex->env); + BKE_texture_envmap_free_data(tex->env); WM_event_add_notifier(C, NC_TEXTURE | NA_EDITED, tex); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 805c271f2d1..f853fd91491 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -5487,7 +5487,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op) ntreeUpdateTree(CTX_data_main(C), ntree); } else { - MTex *mtex = add_mtex_id(&ma->id, -1); + MTex *mtex = BKE_texture_mtex_add_id(&ma->id, -1); /* successful creation of mtex layer, now create set */ if (mtex) { @@ -5506,7 +5506,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op) } } - mtex->tex = add_texture(bmain, DATA_(layer_type_items[type_id].name)); + mtex->tex = BKE_texture_add(bmain, DATA_(layer_type_items[type_id].name)); mtex->mapto = type; if (mtex->tex) { diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index ed28b0b1255..1d232720fc5 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -461,8 +461,8 @@ static void rna_Main_fonts_remove(Main *bmain, ReportList *reports, PointerRNA * static Tex *rna_Main_textures_new(Main *bmain, const char *name, int type) { - Tex *tex = add_texture(bmain, name); - tex_set_type(tex, type); + Tex *tex = BKE_texture_add(bmain, name); + BKE_texture_type_set(tex, type); id_us_min(&tex->id); return tex; } diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 7a06b647ae3..874e861f75f 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -377,7 +377,7 @@ static EnumPropertyItem *rna_Material_texture_coordinates_itemf(bContext *UNUSED MTex *rna_mtex_texture_slots_add(ID *self_id, struct bContext *C, ReportList *reports) { - MTex *mtex = add_mtex_id(self_id, -1); + MTex *mtex = BKE_texture_mtex_add_id(self_id, -1); if (mtex == NULL) { BKE_reportf(reports, RPT_ERROR, "Maximum number of textures added %d", MAX_MTEX); return NULL; @@ -398,7 +398,7 @@ MTex *rna_mtex_texture_slots_create(ID *self_id, struct bContext *C, ReportList return NULL; } - mtex = add_mtex_id(self_id, index); + mtex = BKE_texture_mtex_add_id(self_id, index); /* for redraw only */ WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C)); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index eb2cb9e9312..90ee9e1d7d9 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -2701,7 +2701,7 @@ static void rna_Image_Node_update_id(Main *UNUSED(bmain), Scene *UNUSED(scene), static void rna_Mapping_Node_update(Main *bmain, Scene *scene, PointerRNA *ptr) { bNode *node = ptr->data; - init_tex_mapping(node->storage); + BKE_texture_mapping_init(node->storage); rna_Node_update(bmain, scene, ptr); } diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index c1882e7767d..726744782ed 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -181,7 +181,7 @@ static void rna_Texture_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *pt static void rna_Texture_mapping_update(Main *bmain, Scene *scene, PointerRNA *ptr) { TexMapping *texmap = ptr->data; - init_tex_mapping(texmap); + BKE_texture_mapping_init(texmap); rna_Texture_update(bmain, scene, ptr); } @@ -222,7 +222,7 @@ static void rna_Texture_type_set(PointerRNA *ptr, int value) { Tex *tex = (Tex *)ptr->data; - tex_set_type(tex, value); + BKE_texture_type_set(tex, value); } void rna_TextureSlot_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) @@ -445,7 +445,7 @@ static void rna_Envmap_update_generic(Main *bmain, Scene *scene, PointerRNA *ptr Tex *tex = ptr->id.data; if (tex->env) { ED_preview_kill_jobs(bmain->wm.first, bmain); - BKE_free_envmapdata(tex->env); + BKE_texture_envmap_free_data(tex->env); } rna_Texture_update(bmain, scene, ptr); } diff --git a/source/blender/makesrna/intern/rna_texture_api.c b/source/blender/makesrna/intern/rna_texture_api.c index acf8333d6dc..a27ba6ea06d 100644 --- a/source/blender/makesrna/intern/rna_texture_api.c +++ b/source/blender/makesrna/intern/rna_texture_api.c @@ -60,7 +60,7 @@ static void clear_envmap(struct EnvMap *env, bContext *C) Main *bmain = CTX_data_main(C); Tex *tex; - BKE_free_envmapdata(env); + BKE_texture_envmap_free_data(env); for (tex = bmain->tex.first; tex; tex = tex->id.next) if (tex->env == env) { diff --git a/source/blender/nodes/composite/nodes/node_composite_mapValue.c b/source/blender/nodes/composite/nodes/node_composite_mapValue.c index 22d16e93879..35096d57a4e 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mapValue.c +++ b/source/blender/nodes/composite/nodes/node_composite_mapValue.c @@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_map_value_out[] = { static void node_composit_init_map_value(bNodeTree *UNUSED(ntree), bNode *node) { - node->storage = add_tex_mapping(TEXMAP_TYPE_POINT); + node->storage = BKE_texture_mapping_add(TEXMAP_TYPE_POINT); } void register_node_type_cmp_map_value(void) diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c index cff4a039602..2af6e19565b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mapping.c +++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c @@ -71,7 +71,7 @@ static void node_shader_exec_mapping(void *UNUSED(data), int UNUSED(thread), bNo static void node_shader_init_mapping(bNodeTree *UNUSED(ntree), bNode *node) { - node->storage = add_tex_mapping(TEXMAP_TYPE_POINT); + node->storage = BKE_texture_mapping_add(TEXMAP_TYPE_POINT); } static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c index f75f6a654d1..569eaf5ff9b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c @@ -51,8 +51,8 @@ static bNodeSocketTemplate sh_node_tex_brick_out[] = { static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexBrick *tex = MEM_callocN(sizeof(NodeTexBrick), "NodeTexBrick"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); - default_color_mapping(&tex->base.color_mapping); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); tex->offset = 0.5f; tex->squash = 1.0f; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c index 30e51c7cb7d..b7498df1706 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c @@ -46,8 +46,8 @@ static bNodeSocketTemplate sh_node_tex_checker_out[] = { static void node_shader_init_tex_checker(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexChecker *tex = MEM_callocN(sizeof(NodeTexChecker), "NodeTexChecker"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); - default_color_mapping(&tex->base.color_mapping); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); node->storage = tex; } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index 8d6a77455bb..2b43667a009 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -42,8 +42,8 @@ static bNodeSocketTemplate sh_node_tex_environment_out[] = { static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexEnvironment *tex = MEM_callocN(sizeof(NodeTexEnvironment), "NodeTexEnvironment"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); - default_color_mapping(&tex->base.color_mapping); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); tex->color_space = SHD_COLORSPACE_COLOR; tex->projection = SHD_PROJ_EQUIRECTANGULAR; tex->iuser.frames = 1; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c index e11591ab5ce..24916e8f013 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c @@ -43,8 +43,8 @@ static bNodeSocketTemplate sh_node_tex_gradient_out[] = { static void node_shader_init_tex_gradient(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexGradient *tex = MEM_callocN(sizeof(NodeTexGradient), "NodeTexGradient"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); - default_color_mapping(&tex->base.color_mapping); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); tex->gradient_type = SHD_BLEND_LINEAR; node->storage = tex; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index 62db5b70891..f87e792399b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -43,8 +43,8 @@ static bNodeSocketTemplate sh_node_tex_image_out[] = { static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexImage *tex = MEM_callocN(sizeof(NodeTexImage), "NodeTexImage"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); - default_color_mapping(&tex->base.color_mapping); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); tex->color_space = SHD_COLORSPACE_COLOR; tex->iuser.frames = 1; tex->iuser.sfra = 1; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c index de2daeb8ee1..80904e376bc 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c @@ -45,8 +45,8 @@ static bNodeSocketTemplate sh_node_tex_magic_out[] = { static void node_shader_init_tex_magic(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexMagic *tex = MEM_callocN(sizeof(NodeTexMagic), "NodeTexMagic"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); - default_color_mapping(&tex->base.color_mapping); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); tex->depth = 2; node->storage = tex; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c index 75566773ea2..825ba7eb3c1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c @@ -49,8 +49,8 @@ static bNodeSocketTemplate sh_node_tex_musgrave_out[] = { static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexMusgrave *tex = MEM_callocN(sizeof(NodeTexMusgrave), "NodeTexMusgrave"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); - default_color_mapping(&tex->base.color_mapping); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); tex->musgrave_type = SHD_MUSGRAVE_FBM; node->storage = tex; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c index 601a31dff00..d806140694e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c @@ -46,8 +46,8 @@ static bNodeSocketTemplate sh_node_tex_noise_out[] = { static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexNoise *tex = MEM_callocN(sizeof(NodeTexNoise), "NodeTexNoise"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); - default_color_mapping(&tex->base.color_mapping); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); node->storage = tex; } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c index 51cca0df851..495c78ca929 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c @@ -42,8 +42,8 @@ static bNodeSocketTemplate sh_node_tex_sky_out[] = { static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexSky *tex = MEM_callocN(sizeof(NodeTexSky), "NodeTexSky"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); - default_color_mapping(&tex->base.color_mapping); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); tex->sun_direction[0] = 0.0f; tex->sun_direction[1] = 0.0f; tex->sun_direction[2] = 1.0f; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c index 5eba5f3f59d..88596a4a72f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c @@ -44,8 +44,8 @@ static bNodeSocketTemplate sh_node_tex_voronoi_out[] = { static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexVoronoi *tex = MEM_callocN(sizeof(NodeTexVoronoi), "NodeTexVoronoi"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); - default_color_mapping(&tex->base.color_mapping); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); tex->coloring = SHD_VORONOI_INTENSITY; node->storage = tex; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c index ef79aac0d32..100510641e8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c @@ -47,8 +47,8 @@ static bNodeSocketTemplate sh_node_tex_wave_out[] = { static void node_shader_init_tex_wave(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexWave *tex = MEM_callocN(sizeof(NodeTexWave), "NodeTexWave"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); - default_color_mapping(&tex->base.color_mapping); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); tex->wave_type = SHD_WAVE_BANDS; node->storage = tex; diff --git a/source/blender/nodes/texture/nodes/node_texture_proc.c b/source/blender/nodes/texture/nodes/node_texture_proc.c index b49ec1fd503..0be5f875a23 100644 --- a/source/blender/nodes/texture/nodes/node_texture_proc.c +++ b/source/blender/nodes/texture/nodes/node_texture_proc.c @@ -286,7 +286,7 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node) Tex *tex = MEM_callocN(sizeof(Tex), "Tex"); node->storage = tex; - default_tex(tex); + BKE_texture_default(tex); tex->type = node->type - TEX_NODE_PROC; if (tex->type == TEX_WOOD) diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index f0268836104..0698f849073 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -70,7 +70,7 @@ static void envmap_split_ima(EnvMap *env, ImBuf *ibuf) BLI_lock_thread(LOCK_IMAGE); if (env->cube[1] == NULL) { - BKE_free_envmapdata(env); + BKE_texture_envmap_free_data(env); dx = ibuf->y; dx /= 2; @@ -511,7 +511,7 @@ static void render_envmap(Render *re, EnvMap *env) } - if (re->test_break(re->tbh)) BKE_free_envmapdata(env); + if (re->test_break(re->tbh)) BKE_texture_envmap_free_data(env); else { if (envre->r.mode & R_OSA) env->ok = ENV_OSA; else env->ok = ENV_NORMAL; @@ -572,13 +572,13 @@ void make_envmaps(Render *re) if (env->ok) { /* free when OSA, and old one isn't OSA */ if ((re->r.mode & R_OSA) && env->ok == ENV_NORMAL) - BKE_free_envmapdata(env); + BKE_texture_envmap_free_data(env); /* free when size larger */ else if (env->lastsize < re->r.size) - BKE_free_envmapdata(env); + BKE_texture_envmap_free_data(env); /* free when env is in recalcmode */ else if (env->recalc) - BKE_free_envmapdata(env); + BKE_texture_envmap_free_data(env); } if (env->ok == 0 && depth == 0) env->recalc = 1; diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index 531c31848a6..df4553978a3 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -116,7 +116,7 @@ static void init_render_texture(Render *re, Tex *tex) if (G.is_rendering && re) { if (re->r.mode & R_ENVMAP) if (tex->env->stype==ENV_ANIM) - BKE_free_envmapdata(tex->env); + BKE_texture_envmap_free_data(tex->env); } } } @@ -3493,7 +3493,7 @@ void render_realtime_texture(ShadeInput *shi, Image *ima) if (firsttime) { for (a=0; atex = localize_texture(cur_tex); + tex= mtex->tex = BKE_texture_localize(cur_tex); /* update texture anims */ BKE_animsys_evaluate_animdata(scene, &tex->id, tex->adt, BKE_scene_frame_get(scene), ADT_RECALC_ANIM); -- cgit v1.2.3 From b1d758ae6b63f1b644c5cb721f131ad1795c2b49 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 29 Mar 2015 03:56:39 +1100 Subject: Cleanup: redundant struct declarations --- source/blender/blenkernel/BKE_DerivedMesh.h | 1 - source/blender/blenkernel/BKE_action.h | 2 -- source/blender/blenkernel/BKE_anim.h | 1 - source/blender/blenkernel/BKE_armature.h | 3 --- source/blender/blenkernel/BKE_blender.h | 1 - source/blender/blenkernel/BKE_brush.h | 3 --- source/blender/blenkernel/BKE_cloth.h | 4 ---- source/blender/blenkernel/BKE_collision.h | 4 ---- source/blender/blenkernel/BKE_context.h | 1 - source/blender/blenkernel/BKE_curve.h | 1 - source/blender/blenkernel/BKE_customdata.h | 1 - source/blender/blenkernel/BKE_deform.h | 1 - source/blender/blenkernel/BKE_depsgraph.h | 1 - source/blender/blenkernel/BKE_displist.h | 5 ----- source/blender/blenkernel/BKE_dynamicpaint.h | 2 -- source/blender/blenkernel/BKE_editmesh.h | 1 - source/blender/blenkernel/BKE_editmesh_bvh.h | 1 - source/blender/blenkernel/BKE_effect.h | 3 --- source/blender/blenkernel/BKE_fluidsim.h | 2 -- source/blender/blenkernel/BKE_font.h | 2 -- source/blender/blenkernel/BKE_global.h | 1 - source/blender/blenkernel/BKE_group.h | 2 -- source/blender/blenkernel/BKE_image.h | 1 - source/blender/blenkernel/BKE_key.h | 1 - source/blender/blenkernel/BKE_material.h | 2 -- source/blender/blenkernel/BKE_mball.h | 1 - source/blender/blenkernel/BKE_mesh.h | 9 --------- source/blender/blenkernel/BKE_mesh_remap.h | 1 - source/blender/blenkernel/BKE_modifier.h | 1 - source/blender/blenkernel/BKE_movieclip.h | 1 - source/blender/blenkernel/BKE_multires.h | 2 -- source/blender/blenkernel/BKE_node.h | 5 ----- source/blender/blenkernel/BKE_object.h | 5 ----- source/blender/blenkernel/BKE_paint.h | 3 --- source/blender/blenkernel/BKE_particle.h | 4 ---- source/blender/blenkernel/BKE_pbvh.h | 1 - source/blender/blenkernel/BKE_rigidbody.h | 1 - source/blender/blenkernel/BKE_sca.h | 1 - source/blender/blenkernel/BKE_scene.h | 3 --- source/blender/blenkernel/BKE_screen.h | 1 - source/blender/blenkernel/BKE_sequencer.h | 2 -- source/blender/blenkernel/BKE_shrinkwrap.h | 1 - source/blender/blenkernel/BKE_sound.h | 2 -- source/blender/blenkernel/BKE_subsurf.h | 2 -- source/blender/blenkernel/BKE_text.h | 1 - source/blender/blenkernel/BKE_texture.h | 2 -- source/blender/blenkernel/BKE_tracking.h | 1 - source/blender/blenkernel/BKE_treehash.h | 1 - source/blender/blenkernel/BKE_writeffmpeg.h | 1 - source/blender/blenlib/BLI_blenlib.h | 1 - source/blender/blenlib/BLI_callbacks.h | 1 - source/blender/blenlib/BLI_fileops.h | 1 - source/blender/blenlib/BLI_path_util.h | 1 - source/blender/blenloader/BLO_readfile.h | 1 - source/blender/blenloader/intern/readfile.h | 2 -- source/blender/collada/DocumentImporter.h | 1 - source/blender/editors/armature/BIF_retarget.h | 1 - source/blender/editors/armature/meshlaplacian.h | 2 -- source/blender/editors/include/ED_anim_api.h | 1 - source/blender/editors/include/ED_armature.h | 4 ---- source/blender/editors/include/ED_curve.h | 3 --- source/blender/editors/include/ED_gpencil.h | 4 ---- source/blender/editors/include/ED_image.h | 2 -- source/blender/editors/include/ED_keyframes_draw.h | 1 - source/blender/editors/include/ED_keyframing.h | 2 -- source/blender/editors/include/ED_lattice.h | 1 - source/blender/editors/include/ED_mask.h | 1 - source/blender/editors/include/ED_mball.h | 1 - source/blender/editors/include/ED_mesh.h | 12 ------------ source/blender/editors/include/ED_node.h | 1 - source/blender/editors/include/ED_object.h | 16 ---------------- source/blender/editors/include/ED_paint.h | 1 - source/blender/editors/include/ED_particle.h | 3 --- source/blender/editors/include/ED_render.h | 3 --- source/blender/editors/include/ED_screen.h | 1 - source/blender/editors/include/ED_sculpt.h | 1 - source/blender/editors/include/ED_transform.h | 4 ---- source/blender/editors/include/ED_util.h | 6 ------ source/blender/editors/include/ED_uvedit.h | 2 -- source/blender/editors/include/UI_interface.h | 7 ------- source/blender/editors/include/UI_interface_icons.h | 6 ------ source/blender/editors/include/UI_resources.h | 1 - source/blender/editors/interface/interface_intern.h | 3 --- source/blender/editors/mask/mask_intern.h | 1 - source/blender/editors/mesh/mesh_intern.h | 5 ----- source/blender/editors/object/object_intern.h | 5 ----- source/blender/editors/render/render_intern.h | 4 ++-- source/blender/editors/screen/screen_intern.h | 2 -- source/blender/editors/sculpt_paint/paint_intern.h | 4 ---- source/blender/editors/sculpt_paint/sculpt_intern.h | 6 ------ source/blender/editors/sound/sound_intern.h | 1 - source/blender/editors/space_action/action_intern.h | 3 --- source/blender/editors/space_buttons/buttons_intern.h | 1 - source/blender/editors/space_console/console_intern.h | 1 - source/blender/editors/space_file/file_intern.h | 1 - source/blender/editors/space_file/filelist.h | 5 ----- source/blender/editors/space_graph/graph_intern.h | 3 --- source/blender/editors/space_image/image_intern.h | 4 ---- source/blender/editors/space_logic/logic_intern.h | 4 ---- source/blender/editors/space_node/node_intern.h | 3 --- source/blender/editors/space_outliner/outliner_intern.h | 2 -- .../blender/editors/space_sequencer/sequencer_intern.h | 1 - source/blender/editors/space_text/text_intern.h | 3 --- source/blender/editors/space_time/time_intern.h | 1 - source/blender/editors/space_view3d/view3d_intern.h | 3 --- source/blender/editors/uvedit/uvedit_intern.h | 5 ----- .../intern/blender_interface/BlenderStyleModule.h | 1 - .../python/StrokeShader/BPy_BlenderTextureShader.h | 1 - source/blender/gpu/GPU_buffers.h | 2 -- source/blender/gpu/GPU_compositing.h | 2 -- source/blender/gpu/GPU_draw.h | 1 + source/blender/gpu/GPU_material.h | 3 --- source/blender/gpu/intern/gpu_codegen.h | 1 - source/blender/ikplugin/BIK_api.h | 1 - source/blender/ikplugin/intern/ikplugin_api.h | 1 - source/blender/imbuf/IMB_colormanagement.h | 4 ---- source/blender/makesdna/DNA_color_types.h | 1 - source/blender/makesdna/DNA_curve_types.h | 1 - source/blender/makesdna/DNA_dynamicpaint_types.h | 1 - source/blender/makesdna/DNA_image_types.h | 1 - source/blender/makesdna/DNA_mesh_types.h | 3 --- source/blender/makesdna/DNA_meshdata_types.h | 2 -- source/blender/makesdna/DNA_node_types.h | 1 - source/blender/makesdna/DNA_object_types.h | 1 - source/blender/makesdna/DNA_screen_types.h | 1 - source/blender/makesdna/DNA_sound_types.h | 1 - source/blender/makesdna/DNA_space_types.h | 7 ------- source/blender/makesdna/DNA_tracking_types.h | 2 -- source/blender/makesdna/DNA_view3d_types.h | 2 -- source/blender/makesdna/DNA_windowmanager_types.h | 3 --- source/blender/makesrna/RNA_types.h | 2 -- source/blender/makesrna/intern/rna_internal.h | 3 --- source/blender/makesrna/intern/rna_internal_types.h | 2 -- source/blender/modifiers/intern/MOD_boolean_util.h | 2 -- source/blender/modifiers/intern/MOD_meshcache_util.h | 2 -- source/blender/modifiers/intern/MOD_util.h | 2 -- source/blender/nodes/NOD_socket.h | 1 - source/blender/physics/intern/implicit.h | 2 -- source/blender/quicktime/quicktime_export.h | 1 - source/blender/render/extern/include/RE_bake.h | 1 + source/blender/render/extern/include/RE_render_ext.h | 2 -- source/blender/render/intern/include/initrender.h | 1 - source/blender/render/intern/include/occlusion.h | 3 --- source/blender/render/intern/include/pixelshading.h | 1 - source/blender/render/intern/include/render_types.h | 2 -- source/blender/render/intern/include/rendercore.h | 3 --- source/blender/render/intern/include/shadbuf.h | 1 - source/blender/render/intern/include/shading.h | 1 - source/blender/render/intern/include/sss.h | 1 - source/blender/render/intern/include/strand.h | 3 --- source/blender/render/intern/include/zbuf.h | 1 - source/blender/windowmanager/WM_api.h | 2 -- source/blender/windowmanager/WM_types.h | 1 - source/blender/windowmanager/wm_window.h | 1 - 154 files changed, 4 insertions(+), 346 deletions(-) diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 236eae29967..836c94b6271 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -97,7 +97,6 @@ struct ColorBand; struct GPUVertexAttribs; struct GPUDrawObject; struct BMEditMesh; -struct ListBase; struct PBVH; /* number of sub-elements each mesh element has (for interpolation) */ diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index f51e0fe6979..6fd490723ab 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -46,8 +46,6 @@ struct bItasc; struct bPoseChannel; struct Main; struct Object; -struct Scene; -struct ID; /* Kernel prototypes */ #ifdef __cplusplus diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index 0d5078bc026..e2b9c66780b 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -35,7 +35,6 @@ struct EvaluationContext; struct Path; struct Object; -struct PartEff; struct Scene; struct ListBase; struct bAnimVizSettings; diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 66e204e51e0..de767d39216 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -36,13 +36,10 @@ struct Bone; struct Main; struct bArmature; -struct bPose; struct bPoseChannel; struct bConstraint; struct Scene; struct Object; -struct MDeformVert; -struct Mesh; struct PoseTree; struct ListBase; diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 98672025028..e4d3fe4868b 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -55,7 +55,6 @@ extern "C" { extern char versionstr[]; /* from blender.c */ -struct ListBase; struct MemFile; struct bContext; struct ReportList; diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 49975fa0276..f8cd51b331d 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -27,14 +27,11 @@ * General operations for brushes. */ -struct ID; struct Brush; struct ImBuf; struct ImagePool; struct Main; -struct rctf; struct Scene; -struct wmOperator; // enum CurveMappingPreset; diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index a7fad85ed42..81621f9d3e7 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -36,15 +36,11 @@ #include "BLI_math_inline.h" struct Object; -struct ListBase; struct Scene; struct MFace; struct DerivedMesh; struct ClothModifierData; struct CollisionModifierData; -struct CollisionTree; -struct VoxelData; -struct PartDeflect; #define DO_INLINE MALWAYS_INLINE diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index b81b8f04817..bdc20324bee 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -43,16 +43,12 @@ #include "BLI_kdopbvh.h" -struct Cloth; -struct ClothModifierData; struct CollisionModifierData; -struct DerivedMesh; struct Group; struct MFace; struct MVert; struct Object; struct Scene; -struct LinkNode; //////////////////////////////////////// // used for collisions in collision.c diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index ae0ef9ce314..f7af3a7f8ec 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -53,7 +53,6 @@ struct StructRNA; struct ToolSettings; struct Image; struct Text; -struct ImBuf; struct EditBone; struct bPoseChannel; struct bGPdata; diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 60cbf8b302e..ec3c0447269 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -33,7 +33,6 @@ * \author nzc */ -struct BevList; struct BezTriple; struct Curve; struct EditNurb; diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 6a0cfefb1c2..ab49270ca64 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -46,7 +46,6 @@ extern "C" { struct BMesh; struct ID; struct CustomData; -struct CustomDataLayer; typedef uint64_t CustomDataMask; /*a data type large enough to hold 1 element from any customdata layer type*/ diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 08312035e40..a45893b00fa 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -39,7 +39,6 @@ struct Object; struct ListBase; struct bDeformGroup; struct MDeformVert; -struct MVert; struct MEdge; struct MLoop; struct MPoly; diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h index 27cf19d7d06..1887a892b2e 100644 --- a/source/blender/blenkernel/BKE_depsgraph.h +++ b/source/blender/blenkernel/BKE_depsgraph.h @@ -48,7 +48,6 @@ struct ID; struct Main; struct Object; struct Scene; -struct ListBase; /* Dependency graph evaluation context * diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index 0afc457f2b5..3b096773d96 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -53,14 +53,9 @@ /* prototypes */ -struct Base; struct Scene; struct Object; -struct Curve; struct ListBase; -struct Material; -struct Bone; -struct Mesh; struct DerivedMesh; struct EvaluationContext; diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h index 1aba72e8cd8..e7384fb1a9c 100644 --- a/source/blender/blenkernel/BKE_dynamicpaint.h +++ b/source/blender/blenkernel/BKE_dynamicpaint.h @@ -27,8 +27,6 @@ * \ingroup bke */ -struct bContext; -struct wmOperator; struct Scene; /* Actual surface point */ diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index f80e03fda9b..d0b94117b23 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -32,7 +32,6 @@ struct BMesh; struct BMLoop; -struct BMFace; struct Mesh; struct Scene; struct DerivedMesh; diff --git a/source/blender/blenkernel/BKE_editmesh_bvh.h b/source/blender/blenkernel/BKE_editmesh_bvh.h index 3ee7dcd94b8..3736efff146 100644 --- a/source/blender/blenkernel/BKE_editmesh_bvh.h +++ b/source/blender/blenkernel/BKE_editmesh_bvh.h @@ -39,7 +39,6 @@ struct BMVert; struct BMLoop; struct BMBVHTree; struct BVHTree; -struct Scene; typedef struct BMBVHTree BMBVHTree; diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index c4c27e1060d..f8fee444d91 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -39,11 +39,8 @@ struct Object; struct Scene; -struct Effect; struct ListBase; -struct Particle; struct Group; -struct RNG; struct ParticleSimulationData; struct ParticleData; struct ParticleKey; diff --git a/source/blender/blenkernel/BKE_fluidsim.h b/source/blender/blenkernel/BKE_fluidsim.h index 433c10b82f1..6501c968abc 100644 --- a/source/blender/blenkernel/BKE_fluidsim.h +++ b/source/blender/blenkernel/BKE_fluidsim.h @@ -34,9 +34,7 @@ struct Object; struct Scene; -struct FluidsimModifierData; struct FluidsimSettings; -struct DerivedMesh; struct MVert; /* old interface */ diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h index e12ce3df476..137670215cc 100644 --- a/source/blender/blenkernel/BKE_font.h +++ b/source/blender/blenkernel/BKE_font.h @@ -40,8 +40,6 @@ extern "C" { struct VFont; struct Object; struct Curve; -struct objfnt; -struct TmpFont; struct CharInfo; struct Main; diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 57003ffc3aa..935a922b3ec 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -45,7 +45,6 @@ extern "C" { /* forwards */ struct Main; -struct Object; typedef struct Global { diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index 820e1ea1494..d856e90a340 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -36,10 +36,8 @@ struct Base; struct EvaluationContext; struct Group; -struct GroupObject; struct Main; struct Object; -struct bAction; struct Scene; void BKE_group_free(struct Group *group); diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 2c9ecef4c2d..3b7ba24d20b 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -39,7 +39,6 @@ extern "C" { struct Image; struct ImBuf; -struct Tex; struct anim; struct Scene; struct Object; diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index 9535b921736..08fa096ab53 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -38,7 +38,6 @@ struct ID; struct ListBase; struct Curve; struct Object; -struct Scene; struct Lattice; struct Mesh; struct WeightsArrayCache; diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 2f20505bea3..56393727d28 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -40,8 +40,6 @@ struct Main; struct Material; struct ID; struct Object; -struct Mesh; -struct MTFace; struct Scene; /* materials */ diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index aa9ba45938e..70f932f3292 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -32,7 +32,6 @@ * \since March 2001 * \author nzc */ -struct EvaluationContext; struct Main; struct MetaBall; struct Object; diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 1f3458c06c2..5cf557a07e5 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -33,13 +33,11 @@ struct ID; struct BoundBox; -struct DispList; struct EdgeHash; struct ListBase; struct LinkNode; struct BLI_Stack; struct MemArena; -struct BMEditMesh; struct BMesh; struct Main; struct Mesh; @@ -49,18 +47,11 @@ struct MFace; struct MEdge; struct MVert; struct MDeformVert; -struct MCol; struct Object; -struct MTFace; -struct VecNor; struct CustomData; struct DerivedMesh; struct Scene; struct MLoopUV; -struct UvVertMap; -struct UvMapVert; -struct UvElementMap; -struct UvElement; struct ReportList; #ifdef __cplusplus diff --git a/source/blender/blenkernel/BKE_mesh_remap.h b/source/blender/blenkernel/BKE_mesh_remap.h index 752270a8120..c6d8da16565 100644 --- a/source/blender/blenkernel/BKE_mesh_remap.h +++ b/source/blender/blenkernel/BKE_mesh_remap.h @@ -28,7 +28,6 @@ struct CustomData; struct DerivedMesh; struct MVert; -struct MeshElemMap; struct MemArena; /* Generic ways to map some geometry elements from a source mesh to a dest one. */ diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 1ec4e23abca..e9223590e9d 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -39,7 +39,6 @@ struct DagNode; struct Object; struct Scene; struct ListBase; -struct LinkNode; struct bArmature; struct Main; struct ModifierData; diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index a4aa58e22f1..2cdd2ec88e0 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -37,7 +37,6 @@ struct Main; struct MovieClip; struct MovieClipScopes; struct MovieClipUser; -struct MovieTrackingTrack; struct MovieDistortion; void BKE_movieclip_free(struct MovieClip *clip); diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 11d81a149b1..627b8d6fdbd 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -34,9 +34,7 @@ enum MultiresModifiedFlags; struct DerivedMesh; -struct GridHidden; struct MDisps; -struct MFace; struct Mesh; struct ModifierData; struct Multires; diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 44ac3b7bb38..ee63771406e 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -62,24 +62,20 @@ struct bNodeTreeExec; struct bNodeExecContext; struct bNodeExecData; struct GPUMaterial; -struct GPUNode; struct GPUNodeStack; struct ID; struct ImBuf; struct ImageFormatData; struct ListBase; struct Main; -struct uiBlock; struct uiLayout; struct MTex; struct PointerRNA; -struct rctf; struct RenderData; struct Scene; struct Tex; struct SpaceNode; struct ARegion; -struct Object; struct ColorManagedViewSettings; struct ColorManagedDisplaySettings; struct bNodeInstanceHash; @@ -978,7 +974,6 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria #define CMP_TRACKPOS_ABSOLUTE_FRAME 3 /* API */ -struct CompBuf; void ntreeCompositExecTree(struct Scene *scene, struct bNodeTree *ntree, struct RenderData *rd, int rendering, int do_previews, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings); void ntreeCompositTagRender(struct Scene *sce); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 1c6f7221bec..0ddc9b0b256 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -37,15 +37,10 @@ struct Base; struct EvaluationContext; struct Scene; struct Object; -struct Camera; struct BoundBox; struct View3D; struct SoftBody; struct BulletSoftBody; -struct Group; -struct bAction; -struct RenderData; -struct rctf; struct MovieClip; struct Main; struct RigidBodyWorld; diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 9076eada312..d5cd1fd5d3e 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -37,12 +37,10 @@ struct BMesh; struct BMFace; struct Brush; struct CurveMapping; -struct MDisps; struct MeshElemMap; struct GridPaintMask; struct Main; struct MFace; -struct MultireModifierData; struct MVert; struct Object; struct Paint; @@ -57,7 +55,6 @@ struct StrokeCache; struct Tex; struct ImagePool; struct UnifiedPaintSettings; -struct wmOperator; enum OverlayFlags; diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 619c061cea5..27eeb09c58c 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -45,10 +45,8 @@ struct ParticleSystemModifierData; struct ParticleSystem; struct ParticleKey; struct ParticleSettings; -struct HairKey; struct Main; -struct Group; struct Object; struct Scene; struct DerivedMesh; @@ -57,12 +55,10 @@ struct MTFace; struct MCol; struct MFace; struct MVert; -struct IpoCurve; struct LatticeDeformData; struct LinkNode; struct KDTree; struct RNG; -struct SurfaceModifierData; struct BVHTreeRay; struct BVHTreeRayHit; struct EdgeHash; diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index c8c693fc342..9276a6e14e9 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -35,7 +35,6 @@ struct CCGKey; struct CustomData; struct DMFlagMat; struct DMGridAdjacency; -struct GHash; struct MFace; struct MVert; struct PBVH; diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h index c946f3ac9e8..0ae240e1f6b 100644 --- a/source/blender/blenkernel/BKE_rigidbody.h +++ b/source/blender/blenkernel/BKE_rigidbody.h @@ -39,7 +39,6 @@ struct RigidBodyOb; struct Scene; struct Object; -struct Group; /* -------------- */ /* Memory Management */ diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h index d598a26fdf9..ebdd159b40c 100644 --- a/source/blender/blenkernel/BKE_sca.h +++ b/source/blender/blenkernel/BKE_sca.h @@ -31,7 +31,6 @@ * \ingroup bke */ -struct Text; struct bSensor; struct Object; struct bController; diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index c191f3805a6..27c89dd3a09 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -39,16 +39,13 @@ extern "C" { struct AviCodecData; struct Base; -struct DisplaySafeAreas; struct EvaluationContext; -struct bglMats; struct Main; struct Object; struct QuicktimeCodecData; struct RenderData; struct SceneRenderLayer; struct Scene; -struct Text; struct UnitSettings; struct Main; diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 29590c52b23..43499933d16 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -47,7 +47,6 @@ struct bContextDataResult; struct bScreen; struct uiLayout; struct uiList; -struct uiMenuItem; struct wmKeyConfig; struct wmNotifier; struct wmWindow; diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 5649e76efe6..a39336bd198 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -38,11 +38,9 @@ struct GSet; struct ImBuf; struct Main; struct Mask; -struct MovieClip; struct Scene; struct Sequence; struct SequenceModifierData; -struct Strip; struct StripElem; struct bSound; diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index 070cd4a9cf0..070f5c762db 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -47,7 +47,6 @@ */ struct Object; -struct Scene; struct DerivedMesh; struct MVert; struct MDeformVert; diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index d3919a3a6c0..819b49da8e9 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -35,9 +35,7 @@ #define SOUND_WAVE_SAMPLES_PER_SECOND 250 -struct PackedFile; struct bSound; -struct ListBase; struct Main; struct Sequence; diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h index 3dae4087866..5190d254306 100644 --- a/source/blender/blenkernel/BKE_subsurf.h +++ b/source/blender/blenkernel/BKE_subsurf.h @@ -41,13 +41,11 @@ struct DerivedMesh; struct MeshElemMap; struct Mesh; struct MPoly; -struct MultiresSubsurf; struct Object; struct PBVH; struct SubsurfModifierData; struct CCGEdge; struct CCGFace; -struct CCGSubsurf; struct CCGVert; struct EdgeHash; struct PBVH; diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 96e88f80464..c5f47ad6cbf 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -40,7 +40,6 @@ extern "C" { struct Main; struct Text; struct TextLine; -struct SpaceText; void BKE_text_free (struct Text *text); void txt_set_undostate (int u); diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index ad485931ee3..4e5214bc364 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -42,9 +42,7 @@ struct Brush; struct ColorBand; struct EnvMap; struct FreestyleLineStyle; -struct HaloRen; struct Lamp; -struct LampRen; struct Main; struct Material; struct MTex; diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index e5fb60cf1b5..ef997446c6c 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -41,7 +41,6 @@ struct MovieTrackingMarker; struct MovieTrackingPlaneTrack; struct MovieTrackingPlaneMarker; struct MovieTracking; -struct MovieTrackingContext; struct MovieTrackingObject; struct MovieClipUser; struct MovieDistortion; diff --git a/source/blender/blenkernel/BKE_treehash.h b/source/blender/blenkernel/BKE_treehash.h index 54deef1ce2f..16ab02c0965 100644 --- a/source/blender/blenkernel/BKE_treehash.h +++ b/source/blender/blenkernel/BKE_treehash.h @@ -27,7 +27,6 @@ */ struct ID; -struct GHash; struct BLI_mempool; struct TreeStoreElem; diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h index ba6360964d6..951fa501f9c 100644 --- a/source/blender/blenkernel/BKE_writeffmpeg.h +++ b/source/blender/blenkernel/BKE_writeffmpeg.h @@ -64,7 +64,6 @@ enum { FFMPEG_PRESET_XVID = 7, }; -struct IDProperty; struct RenderData; struct ReportList; struct Scene; diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index 03b75975af4..06bbf29a223 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -58,7 +58,6 @@ #ifndef __BLI_BLENLIB_H__ #define __BLI_BLENLIB_H__ -struct ListBase; #include diff --git a/source/blender/blenlib/BLI_callbacks.h b/source/blender/blenlib/BLI_callbacks.h index 7cf524749c2..fdffbeb4c8d 100644 --- a/source/blender/blenlib/BLI_callbacks.h +++ b/source/blender/blenlib/BLI_callbacks.h @@ -25,7 +25,6 @@ #ifndef __BLI_CALLBACKS_H__ #define __BLI_CALLBACKS_H__ -struct bContext; struct Main; struct ID; diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index 7898a54002f..01aa5d39b96 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -51,7 +51,6 @@ extern "C" { # define PATH_MAX 4096 #endif -struct gzFile; /* Common */ diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index d99df24aaf7..c35b01e7f55 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -38,7 +38,6 @@ extern "C" { #include "BLI_compiler_attrs.h" struct ListBase; -struct direntry; #ifdef WIN32 #define SEP '\\' diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 419d8c0f137..52a6597c79f 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -42,7 +42,6 @@ struct Main; struct MemFile; struct ReportList; struct Scene; -struct SpaceFile; struct UserDef; struct bContext; struct BHead; diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index 51a68926455..ed22daef9ec 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -38,12 +38,10 @@ struct OldNewMap; struct MemFile; -struct bheadsort; struct ReportList; struct Object; struct PartEff; struct View3D; -struct bNodeTree; struct Key; typedef struct FileData { diff --git a/source/blender/collada/DocumentImporter.h b/source/blender/collada/DocumentImporter.h index 5a7df9a41cf..62f76dbc022 100644 --- a/source/blender/collada/DocumentImporter.h +++ b/source/blender/collada/DocumentImporter.h @@ -51,7 +51,6 @@ -struct Main; struct bContext; /** Importer class. */ diff --git a/source/blender/editors/armature/BIF_retarget.h b/source/blender/editors/armature/BIF_retarget.h index 21e85b6fe89..aa56f847f00 100644 --- a/source/blender/editors/armature/BIF_retarget.h +++ b/source/blender/editors/armature/BIF_retarget.h @@ -40,7 +40,6 @@ struct bContext; struct EditBone; -struct RigJoint; struct RigGraph; struct RigNode; struct RigArc; diff --git a/source/blender/editors/armature/meshlaplacian.h b/source/blender/editors/armature/meshlaplacian.h index 820aedc5467..1412136c1a8 100644 --- a/source/blender/editors/armature/meshlaplacian.h +++ b/source/blender/editors/armature/meshlaplacian.h @@ -29,11 +29,9 @@ //#define RIGID_DEFORM -struct Scene; struct Object; struct Mesh; struct bDeformGroup; -struct MeshDeformModifierData; #ifdef RIGID_DEFORM struct EditMesh; diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 9b4037ff455..1ce285f8190 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -49,7 +49,6 @@ struct Object; struct bDopeSheet; struct bAction; -struct bActionGroup; struct FCurve; struct FModifier; diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 9345cd83b49..35bb12ddaad 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -39,16 +39,12 @@ struct Base; struct bContext; struct Bone; struct bPoseChannel; -struct DerivedMesh; struct IDProperty; struct ListBase; struct MeshDeformModifierData; struct Object; -struct RegionView3D; struct ReportList; struct Scene; -struct SK_Sketch; -struct View3D; struct ViewContext; struct wmKeyConfig; struct wmOperator; diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h index 982e17cfce4..fee3d44b8eb 100644 --- a/source/blender/editors/include/ED_curve.h +++ b/source/blender/editors/include/ED_curve.h @@ -31,13 +31,10 @@ #ifndef __ED_CURVE_H__ #define __ED_CURVE_H__ -struct Base; struct bContext; struct Nurb; struct Object; -struct Scene; struct Text; -struct View3D; struct wmOperator; struct wmKeyConfig; struct Curve; diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index c4f08ca4775..448f2c83aad 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -33,19 +33,15 @@ struct ID; struct ListBase; struct bContext; -struct bScreen; struct ScrArea; struct ARegion; struct View3D; -struct SpaceNode; -struct SpaceSeq; struct Object; struct bGPdata; struct bGPDlayer; struct bGPDframe; struct bGPDstroke; struct PointerRNA; -struct ImBuf; struct wmKeyConfig; diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index 704876e1261..fc42d2b5495 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -31,13 +31,11 @@ #define __ED_IMAGE_H__ struct SpaceImage; -struct Main; struct bContext; struct Image; struct ImageUser; struct ImBuf; struct ToolSettings; -struct uiBlock; struct wmWindowManager; struct ARegion; struct Scene; diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index 0359153317b..7d163da0db0 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -34,7 +34,6 @@ struct bAnimContext; struct AnimData; -struct BezTriple; struct FCurve; struct bDopeSheet; struct bAction; diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index e5b5e79875d..5d76c9e0f6f 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -46,10 +46,8 @@ struct FCurve; struct BezTriple; struct bPoseChannel; -struct bConstraint; struct bContext; -struct wmOperatorType; struct ReportList; struct PointerRNA; diff --git a/source/blender/editors/include/ED_lattice.h b/source/blender/editors/include/ED_lattice.h index 6636319dc9b..6fe1524cb6d 100644 --- a/source/blender/editors/include/ED_lattice.h +++ b/source/blender/editors/include/ED_lattice.h @@ -32,7 +32,6 @@ #define __ED_LATTICE_H__ struct Object; -struct Lattice; void free_editLatt(struct Object *ob); void make_editLatt(struct Object *obedit); diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index 97fd553ea19..1611276ca70 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -34,7 +34,6 @@ struct wmKeyConfig; struct MaskLayer; struct MaskLayerShape; -struct wmEvent; /* mask_edit.c */ void ED_mask_get_size(struct ScrArea *sa, int *width, int *height); diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h index 5e774c63841..05a4ccabd1b 100644 --- a/source/blender/editors/include/ED_mball.h +++ b/source/blender/editors/include/ED_mball.h @@ -32,7 +32,6 @@ #define __ED_MBALL_H__ struct bContext; -struct MetaBall; struct Object; struct wmKeyConfig; diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index ccf97221112..8fb6fcbd0d7 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -40,39 +40,27 @@ struct View3D; struct ARegion; struct bContext; struct wmOperator; -struct wmWindowManager; struct wmKeyConfig; struct ReportList; -struct EditSelection; struct ViewContext; struct bDeformGroup; -struct MDeformWeight; struct MDeformVert; struct Scene; struct Mesh; -struct MFace; -struct MEdge; -struct MVert; -struct MCol; struct UvVertMap; struct UvMapVert; -struct CustomData; struct BMEditMesh; -struct BMEditSelection; struct BMesh; struct BMVert; struct BMLoop; struct BMBVHTree; -struct MLoopCol; struct BMEdge; struct BMFace; struct UvVertMap; struct UvMapVert; struct ToolSettings; -struct Material; struct Object; struct rcti; -struct MeshStatVis; /* editmesh_utils.c */ void EDBM_verts_mirror_cache_begin_ex(struct BMEditMesh *em, const int axis, diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 824c82a0069..b02ebeb650b 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -33,7 +33,6 @@ struct ID; struct Main; -struct Material; struct Scene; struct Tex; struct bContext; diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 3d791839a3c..3b7157bd465 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -35,33 +35,17 @@ extern "C" { #endif -struct BMEdge; -struct BMFace; -struct BMVert; -struct BPoint; struct Base; -struct BezTriple; -struct Curve; -struct EditBone; struct EnumPropertyItem; struct ID; -struct KeyBlock; -struct Lattice; struct Main; -struct Mesh; -struct MetaElem; struct ModifierData; -struct HookModifierData; -struct Nurb; struct Object; struct ReportList; struct Scene; -struct View3D; -struct ViewContext; struct bConstraint; struct bContext; struct bPoseChannel; -struct wmEvent; struct wmKeyConfig; struct wmKeyMap; struct wmOperator; diff --git a/source/blender/editors/include/ED_paint.h b/source/blender/editors/include/ED_paint.h index decd79fcc7b..c3a411a2b97 100644 --- a/source/blender/editors/include/ED_paint.h +++ b/source/blender/editors/include/ED_paint.h @@ -26,7 +26,6 @@ #define __ED_PAINT_H__ struct bContext; -struct RegionView3D; struct wmKeyConfig; struct wmOperator; diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h index f9516f255cf..56a4bfa7e21 100644 --- a/source/blender/editors/include/ED_particle.h +++ b/source/blender/editors/include/ED_particle.h @@ -35,10 +35,7 @@ struct bContext; struct Object; struct ParticleEditSettings; -struct ParticleSystem; -struct RadialControl; struct rcti; -struct wmKeyConfig; struct PTCacheEdit; struct Scene; diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h index 1b1d8d723ee..2bc0566f4a6 100644 --- a/source/blender/editors/include/ED_render.h +++ b/source/blender/editors/include/ED_render.h @@ -37,9 +37,6 @@ struct MTex; struct Render; struct Scene; struct ScrArea; -struct RegionView3D; -struct RenderEngine; -struct View3D; struct wmWindowManager; /* render_ops.c */ diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 8c33395cc49..b4f7d806079 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -42,7 +42,6 @@ struct wmNotifier; struct wmEvent; struct wmKeyConfig; struct bContext; -struct SpaceType; struct Scene; struct bScreen; struct ARegion; diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h index d3b1a824104..6daaac5bb42 100644 --- a/source/blender/editors/include/ED_sculpt.h +++ b/source/blender/editors/include/ED_sculpt.h @@ -34,7 +34,6 @@ struct ARegion; struct bContext; struct Object; struct RegionView3D; -struct Scene; struct ViewContext; struct rcti; diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index a3b4981dad8..478cb927011 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -35,17 +35,14 @@ /* ******************* Registration Function ********************** */ struct ARegion; -struct EnumPropertyItem; struct ListBase; struct Object; struct View3D; struct bContext; -struct uiLayout; struct wmEvent; struct wmKeyConfig; struct wmKeyMap; struct wmOperatorType; -struct wmWindowManager; void transform_keymap_for_space(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap, int spaceid); void transform_operatortypes(void); @@ -109,7 +106,6 @@ enum TfmMode { bool calculateTransformCenter(struct bContext *C, int centerMode, float cent3d[3], float cent2d[2]); struct TransInfo; -struct ScrArea; struct Base; struct Scene; struct Object; diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index e26e03473e0..6fa92e1953d 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -31,15 +31,9 @@ #ifndef __ED_UTIL_H__ #define __ED_UTIL_H__ -struct Scene; -struct Object; struct bContext; -struct ARegion; -struct uiBlock; struct wmOperator; struct wmOperatorType; -struct BMEditMesh; -struct Mesh; /* ed_util.c */ diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 3e8f234e979..535683823bf 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -37,13 +37,11 @@ struct BMFace; struct BMLoop; struct Image; struct ImageUser; -struct MTFace; struct MTexPoly; struct Main; struct Object; struct Scene; struct SpaceImage; -struct bContext; struct bNode; struct wmKeyConfig; diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 02ae098dc2e..814bbf94c79 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -40,14 +40,11 @@ /* Struct Declarations */ struct ID; -struct Main; struct ListBase; struct ARegion; -struct ARegionType; struct ScrArea; struct wmEvent; struct wmWindow; -struct wmWindowManager; struct wmOperator; struct AutoComplete; struct bContext; @@ -58,18 +55,14 @@ struct PointerRNA; struct PropertyRNA; struct ReportList; struct rcti; -struct rctf; struct uiList; struct uiStyle; struct uiFontStyle; struct uiWidgetColors; -struct ColorBand; -struct CurveMapping; struct Image; struct ImageUser; struct wmOperatorType; struct uiWidgetColors; -struct Tex; struct MTex; struct ImBuf; struct bNodeTree; diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index 74927428363..9d190fa81c7 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -34,12 +34,6 @@ struct bContext; struct ID; -struct Image; -struct ImBuf; -struct World; -struct Tex; -struct Lamp; -struct Material; struct PreviewImage; struct PointerRNA; diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 4a484212a63..3923c5c4432 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -301,7 +301,6 @@ enum { /* specific defines per space should have higher define values */ struct bTheme; -struct PointerRNA; struct bThemeState { struct bTheme *theme; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index e337389f781..d7b6824f812 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -40,11 +40,9 @@ struct ARegion; struct bContext; -struct IDProperty; struct uiHandleButtonData; struct wmEvent; struct wmOperatorType; -struct wmWindow; struct wmTimer; struct uiStyle; struct uiWidgetColors; @@ -588,7 +586,6 @@ void ui_popup_block_free(struct bContext *C, uiPopupBlockHandle *handle); int ui_but_menu_step(uiBut *but, int step); -struct AutoComplete; /* interface_panel.c */ extern int ui_handler_panel_region(struct bContext *C, const struct wmEvent *event, struct ARegion *ar); diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index 5cdb224ce21..66a6c75272e 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -34,7 +34,6 @@ struct bContext; struct Mask; -struct wmEvent; struct wmOperatorType; /* internal exports only */ diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 8611872a1a0..c7355120a57 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -34,14 +34,9 @@ #ifndef __MESH_INTERN_H__ #define __MESH_INTERN_H__ -struct BMEdge; struct BMEditMesh; -struct BMFace; -struct BMHeader; struct BMOperator; -struct BMesh; struct EnumPropertyItem; -struct ViewContext; struct bContext; struct wmKeyConfig; struct wmKeyMap; diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 64fddf1b6a1..db040bc2017 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -32,17 +32,12 @@ #define __OBJECT_INTERN_H__ struct wmOperatorType; -struct KeyBlock; -struct Lattice; -struct Curve; struct Object; -struct Mesh; struct bContext; struct StructRNA; struct wmOperator; struct ModifierData; -struct HookModifierData; /* add hook menu */ enum eObject_Hook_Add_Mode { diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h index f9377d576bf..ee0046b49dc 100644 --- a/source/blender/editors/render/render_intern.h +++ b/source/blender/editors/render/render_intern.h @@ -32,9 +32,9 @@ #ifndef __RENDER_INTERN_H__ #define __RENDER_INTERN_H__ +struct bContext; +struct RenderEngine; struct wmOperatorType; -struct RenderResult; -struct Scene; struct ScrArea; /* render_shading.c */ diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h index 79036d3356f..ccb6d5a6dca 100644 --- a/source/blender/editors/screen/screen_intern.h +++ b/source/blender/editors/screen/screen_intern.h @@ -32,8 +32,6 @@ #define __SCREEN_INTERN_H__ /* internal exports only */ -struct wmWindow; -struct Scene; #define AZONESPOT (0.6f * U.widget_unit) #define AZONEFADEIN (5.0f * U.widget_unit) /* when azone is totally visible */ diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 9e558092f73..77059a22de7 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -34,14 +34,11 @@ struct ARegion; struct bContext; -struct bglMats; struct Brush; struct ImagePool; struct ColorSpace; struct ColorManagedDisplay; struct ListBase; -struct Material; -struct Mesh; struct MTex; struct Object; struct PaintStroke; @@ -55,7 +52,6 @@ struct ViewContext; struct wmEvent; struct wmOperator; struct wmOperatorType; -struct ImagePaintState; struct wmWindowManager; struct DMCoNo; enum PaintMode; diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index a61f571fdf6..8f1a4655c37 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -41,14 +41,8 @@ #include "BKE_pbvh.h" struct bContext; -struct Brush; struct KeyBlock; -struct Mesh; -struct MultiresModifierData; struct Object; -struct Scene; -struct Sculpt; -struct SculptStroke; struct SculptUndoNode; int sculpt_mode_poll(struct bContext *C); diff --git a/source/blender/editors/sound/sound_intern.h b/source/blender/editors/sound/sound_intern.h index e8a8ec55ab5..ace173abdee 100644 --- a/source/blender/editors/sound/sound_intern.h +++ b/source/blender/editors/sound/sound_intern.h @@ -32,7 +32,6 @@ #ifndef __SOUND_INTERN_H__ #define __SOUND_INTERN_H__ -struct wmOperatorType; #endif /* __SOUND_INTERN_H__ */ diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index 61d4249ae20..9a19e4a926b 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -35,10 +35,7 @@ struct bContext; struct bAnimContext; struct SpaceAction; struct ARegion; -struct wmWindowManager; struct wmOperatorType; -struct ActKeysInc; -struct bAnimListElem; /* internal exports only */ diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h index f294729ae97..7fc35a6b1e7 100644 --- a/source/blender/editors/space_buttons/buttons_intern.h +++ b/source/blender/editors/space_buttons/buttons_intern.h @@ -34,7 +34,6 @@ #include "DNA_listBase.h" #include "RNA_types.h" -struct ARegion; struct ARegionType; struct ID; struct SpaceButs; diff --git a/source/blender/editors/space_console/console_intern.h b/source/blender/editors/space_console/console_intern.h index a3746e091ce..d8a4a6fd2bb 100644 --- a/source/blender/editors/space_console/console_intern.h +++ b/source/blender/editors/space_console/console_intern.h @@ -31,7 +31,6 @@ struct ConsoleLine; struct wmOperatorType; -struct ReportList; struct bContext; /* console_draw.c */ diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index e7a6cd62a33..f1fd4e2b683 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -59,7 +59,6 @@ bool file_draw_check_exists(SpaceFile *sfile); /* file_ops.h */ struct wmOperatorType; struct wmOperator; -struct wmEvent; void FILE_OT_highlight(struct wmOperatorType *ot); void FILE_OT_select(struct wmOperatorType *ot); void FILE_OT_select_all_toggle(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index 797d54a89b1..44e0a5169fa 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -40,12 +40,7 @@ extern "C" { struct BlendHandle; struct FileList; struct FileSelection; -struct FolderList; -struct Main; -struct ReportList; -struct Scene; struct direntry; -struct rcti; struct wmWindowManager; typedef enum FileSelType { diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index 50412952139..e2fab188fc8 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -32,11 +32,8 @@ #define __GRAPH_INTERN_H__ struct bContext; -struct wmWindowManager; struct bAnimContext; struct bAnimListElem; -struct FCurve; -struct FModifier; struct SpaceIpo; struct ScrArea; struct ARegion; diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h index aecc43f4fdf..6eaad302180 100644 --- a/source/blender/editors/space_image/image_intern.h +++ b/source/blender/editors/space_image/image_intern.h @@ -38,11 +38,7 @@ struct ARegion; struct ARegionType; struct ScrArea; struct SpaceImage; -struct Object; -struct Image; -struct ImBuf; struct wmOperatorType; -struct Scene; struct bNodeTree; /* space_image.c */ diff --git a/source/blender/editors/space_logic/logic_intern.h b/source/blender/editors/space_logic/logic_intern.h index 38b122f64b6..13146621d1b 100644 --- a/source/blender/editors/space_logic/logic_intern.h +++ b/source/blender/editors/space_logic/logic_intern.h @@ -35,12 +35,8 @@ /* internal exports only */ struct bContext; struct ARegion; -struct ARegionType; struct ScrArea; -struct SpaceLogic; -struct Object; struct wmOperatorType; -struct Scene; /* space_logic.c */ struct ARegion *logic_has_buttons_region(struct ScrArea *sa); diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 27c3ab813ae..d49d37c651e 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -42,12 +42,9 @@ struct ARegionType; struct View2D; struct bContext; struct wmWindow; -struct wmWindowManager; -struct wmEvent; struct bNode; struct bNodeSocket; struct bNodeLink; -struct Main; struct wmKeyConfig; /* temp data to pass on to modal */ diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 50fecebb742..b4b73a11a14 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -36,12 +36,10 @@ /* internal exports only */ -struct wmWindowManager; struct wmOperatorType; struct TreeStoreElem; struct bContext; struct Scene; -struct ARegion; struct ID; struct Object; diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index 461c72961c2..b02e254370a 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -45,7 +45,6 @@ struct ARegion; struct ARegionType; struct Scene; struct Main; -struct SequencePreview; /* space_sequencer.c */ struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa); diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h index f577714c480..7ae2617f375 100644 --- a/source/blender/editors/space_text/text_intern.h +++ b/source/blender/editors/space_text/text_intern.h @@ -34,15 +34,12 @@ /* internal exports only */ struct ARegion; -struct ARegionType; struct bContext; -struct ReportList; struct ScrArea; struct SpaceText; struct Text; struct TextLine; struct wmOperatorType; -struct wmWindowManager; /* text_draw.c */ void draw_text_main(struct SpaceText *st, struct ARegion *ar); diff --git a/source/blender/editors/space_time/time_intern.h b/source/blender/editors/space_time/time_intern.h index ce52cbbd65e..ced36b2ac2d 100644 --- a/source/blender/editors/space_time/time_intern.h +++ b/source/blender/editors/space_time/time_intern.h @@ -34,7 +34,6 @@ /* internal exports only */ -struct wmWindowManager; /* time_ops.c */ void time_operatortypes(void); diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index e07d7b3977c..95c0ef92680 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -41,14 +41,11 @@ struct BoundBox; struct DerivedMesh; struct Object; struct SmokeDomainSettings; -struct ViewContext; struct bAnimVizSettings; struct bContext; struct bMotionPath; struct bPoseChannel; -struct bScreen; struct Mesh; -struct SimDebugData; struct wmNDOFMotionData; struct wmOperatorType; struct wmWindowManager; diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index d1fd8d969a4..e028c08091c 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -34,18 +34,13 @@ struct MTexPoly; struct Image; -struct MTFace; struct Object; struct Scene; struct SpaceImage; -struct UvElementMap; struct wmOperatorType; struct BMEditMesh; -struct BMesh; struct BMFace; struct BMLoop; -struct BMEdge; -struct BMVert; /* visibility and selection */ bool uvedit_face_visible_nolocal(struct Scene *scene, struct BMFace *efa); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h index 21776396ebc..2bc43798878 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h +++ b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h @@ -31,7 +31,6 @@ extern "C" { #include "BLI_utildefines.h" // BLI_assert() -struct Scene; struct Text; } diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.h index 46294c07b66..c4fead6a4e4 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.h +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.h @@ -31,7 +31,6 @@ extern "C" { #endif -struct MTex; /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h index 54153cfde5d..8b65666265d 100644 --- a/source/blender/gpu/GPU_buffers.h +++ b/source/blender/gpu/GPU_buffers.h @@ -42,10 +42,8 @@ struct BMesh; struct CCGElem; struct CCGKey; -struct CustomData; struct DMFlagMat; struct DerivedMesh; -struct GHash; struct GSet; struct GPUVertPointLink; struct PBVH; diff --git a/source/blender/gpu/GPU_compositing.h b/source/blender/gpu/GPU_compositing.h index 57d8c0631d6..04e89da00a7 100644 --- a/source/blender/gpu/GPU_compositing.h +++ b/source/blender/gpu/GPU_compositing.h @@ -42,10 +42,8 @@ struct GPUDOFSettings; struct GPUSSAOSettings; struct GPUOffScreen; struct GPUFXSettings; -struct RegionView3D; struct rcti; struct Scene; -struct View3D; enum eGPUFXFlags; /**** Public API *****/ diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 0c0ab1097d3..cc1a63d6256 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -36,6 +36,7 @@ extern "C" { #endif +struct ImBuf; struct Image; struct ImageUser; struct MTFace; diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index e27916e5bf7..b61bdf969cc 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -45,10 +45,7 @@ struct Image; struct ImageUser; struct Material; struct Object; -struct Lamp; struct Image; -struct bNode; -struct LinkNode; struct Scene; struct SceneRenderLayer; struct GPUVertexAttribs; diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index 89bd3a8ee99..c6ed2e3f837 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -43,7 +43,6 @@ struct GPUShader; struct GPUOutput; struct GPUNode; struct GPUVertexAttribs; -struct GPUFrameBuffer; struct PreviewImage; /* Pass Generation diff --git a/source/blender/ikplugin/BIK_api.h b/source/blender/ikplugin/BIK_api.h index 95b1dafd129..177be074897 100644 --- a/source/blender/ikplugin/BIK_api.h +++ b/source/blender/ikplugin/BIK_api.h @@ -41,7 +41,6 @@ extern "C" { struct Object; struct bPoseChannel; struct bPose; -struct bArmature; struct Scene; struct bConstraint; diff --git a/source/blender/ikplugin/intern/ikplugin_api.h b/source/blender/ikplugin/intern/ikplugin_api.h index 53d9da8e614..cd32bf26242 100644 --- a/source/blender/ikplugin/intern/ikplugin_api.h +++ b/source/blender/ikplugin/intern/ikplugin_api.h @@ -40,7 +40,6 @@ extern "C" { struct Object; struct bPoseChannel; -struct bArmature; struct Scene; diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 9407750c039..59df8334099 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -47,10 +47,6 @@ struct ColormanageProcessor; struct EnumPropertyItem; struct ImBuf; struct Main; -struct rcti; -struct PartialBufferUpdateContext; -struct wmWindow; -struct Scene; struct ImageFormatData; struct ColorSpace; diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h index e3731129632..c9a5e056e4a 100644 --- a/source/blender/makesdna/DNA_color_types.h +++ b/source/blender/makesdna/DNA_color_types.h @@ -133,7 +133,6 @@ typedef struct Histogram { float co[2][2]; } Histogram; -struct ImBuf; typedef struct Scopes { int ok; diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 288743d5e2f..205ed7e7380 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -46,7 +46,6 @@ struct Key; struct Material; struct VFont; struct AnimData; -struct SelBox; struct EditFont; struct GHash; diff --git a/source/blender/makesdna/DNA_dynamicpaint_types.h b/source/blender/makesdna/DNA_dynamicpaint_types.h index dece93af122..17553e98817 100644 --- a/source/blender/makesdna/DNA_dynamicpaint_types.h +++ b/source/blender/makesdna/DNA_dynamicpaint_types.h @@ -29,7 +29,6 @@ #define __DNA_DYNAMICPAINT_TYPES_H__ #include "DNA_listBase.h" -struct CurveMapping; struct PaintSurfaceData; /* surface format */ diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index dca1c8330b0..7444abb6d11 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -39,7 +39,6 @@ struct PackedFile; struct Scene; struct anim; -struct ImBuf; struct MovieCache; struct RenderResult; struct GPUTexture; diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 8067fa5db2d..3799de011d4 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -37,7 +37,6 @@ #include "DNA_customdata_types.h" struct AnimData; -struct DerivedMesh; struct Ipo; struct Key; struct MCol; @@ -47,13 +46,11 @@ struct MLoop; struct MLoopCol; struct MLoopUV; struct MPoly; -struct MSticky; struct MTexPoly; struct MVert; struct Material; struct Mesh; struct Multires; -struct OcInfo; typedef struct Mesh { ID id; diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 3304980f964..b76f40c884d 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -35,7 +35,6 @@ #include "DNA_customdata_types.h" #include "DNA_listBase.h" -struct Bone; struct Image; /*tessellation face, see MLoop/MPoly for the real face data*/ @@ -216,7 +215,6 @@ typedef struct MultiresEdge { unsigned int mid; } MultiresEdge; -struct MultiresMapNode; typedef struct MultiresLevel { struct MultiresLevel *next, *prev; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index de1c9237a50..9ab6527daee 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -40,7 +40,6 @@ struct ID; struct ListBase; -struct SpaceNode; struct bNodeLink; struct bNodeType; struct bNodeTreeExec; diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 4cb979c57b7..702d9acfb58 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -48,7 +48,6 @@ struct Ipo; struct BoundBox; struct Path; struct Material; -struct bConstraintChannel; struct PartDeflect; struct SoftBody; struct FluidsimSettings; diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 3e02071c3dd..84ac0c5e792 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -41,7 +41,6 @@ struct SpaceLink; struct ARegion; struct ARegionType; struct PanelType; -struct HeaderType; struct Scene; struct uiLayout; struct wmTimer; diff --git a/source/blender/makesdna/DNA_sound_types.h b/source/blender/makesdna/DNA_sound_types.h index cb132c1b550..811d78d67c2 100644 --- a/source/blender/makesdna/DNA_sound_types.h +++ b/source/blender/makesdna/DNA_sound_types.h @@ -41,7 +41,6 @@ struct Ipo; struct PackedFile; -struct SpaceLink; typedef struct bSound { ID id; diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 69affc74ed7..dff6d3cacb5 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -50,28 +50,21 @@ struct ID; struct Text; struct Script; -struct bSound; -struct ImBuf; struct Image; struct Scopes; struct Histogram; struct SpaceIpo; -struct BlendHandle; struct bNodeTree; -struct uiBlock; struct FileList; struct bGPdata; struct bDopeSheet; struct FileSelectParams; struct FileLayout; -struct bScreen; -struct Scene; struct wmOperator; struct wmTimer; struct MovieClip; struct MovieClipScopes; struct Mask; -struct GHash; struct BLI_mempool; diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index c471cb26892..9888b735b8b 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -43,11 +43,9 @@ /* match-moving data */ struct bGPdata; -struct ImBuf; struct Image; struct MovieReconstructedCamera; struct MovieTrackingCamera; -struct MovieTrackingBundle; struct MovieTrackingMarker; struct MovieTrackingTrack; struct MovieTracking; diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 210deddc854..93e61487000 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -35,9 +35,7 @@ struct ViewDepths; struct Object; struct Image; -struct Tex; struct SpaceLink; -struct Base; struct BoundBox; struct MovieClip; struct MovieClipUser; diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 1a0562ae8c5..919cdb7ea2f 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -49,12 +49,9 @@ struct wmKeyConfig; /* forwards */ struct bContext; -struct wmLocal; struct bScreen; -struct uiBlock; struct wmSubWindow; struct wmTimer; -struct StructRNA; struct PointerRNA; struct ReportList; struct Report; diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index a9c0f591858..0c99769a390 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -37,10 +37,8 @@ extern "C" { struct ParameterList; struct FunctionRNA; struct PropertyRNA; -struct EnumPropertyRNA; struct StructRNA; struct BlenderRNA; -struct IDProperty; struct bContext; struct Main; struct ReportList; diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index da657a70e4e..01303225f38 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -35,16 +35,13 @@ #define RNA_MAGIC ((int)~0) -struct ColorBand; struct ID; struct IDProperty; struct Main; struct Mesh; struct Object; -struct RenderEngine; struct ReportList; struct SDNA; -struct Sequence; /* Data structures used during define */ diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h index 845d76debd2..ba0705b5caa 100644 --- a/source/blender/makesrna/intern/rna_internal_types.h +++ b/source/blender/makesrna/intern/rna_internal_types.h @@ -38,10 +38,8 @@ struct StructRNA; struct PropertyRNA; struct PointerRNA; struct FunctionRNA; -struct ReportList; struct CollectionPropertyIterator; struct bContext; -struct EnumProperty; struct IDProperty; struct GHash; struct Main; diff --git a/source/blender/modifiers/intern/MOD_boolean_util.h b/source/blender/modifiers/intern/MOD_boolean_util.h index 04d76d45652..00d7c37b266 100644 --- a/source/blender/modifiers/intern/MOD_boolean_util.h +++ b/source/blender/modifiers/intern/MOD_boolean_util.h @@ -33,9 +33,7 @@ #ifndef __MOD_BOOLEAN_UTIL_H__ #define __MOD_BOOLEAN_UTIL_H__ -struct Scene; struct Object; -struct Base; struct DerivedMesh; /* Performs a boolean between two mesh objects, it is assumed that both objects diff --git a/source/blender/modifiers/intern/MOD_meshcache_util.h b/source/blender/modifiers/intern/MOD_meshcache_util.h index f3b5f43009d..241806f49e1 100644 --- a/source/blender/modifiers/intern/MOD_meshcache_util.h +++ b/source/blender/modifiers/intern/MOD_meshcache_util.h @@ -27,8 +27,6 @@ #ifndef __MOD_MESHCACHE_UTIL_H__ #define __MOD_MESHCACHE_UTIL_H__ -struct MPoly; -struct MLoop; /* MOD_meshcache_mdd.c */ bool MOD_meshcache_read_mdd_index(FILE *fp, diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h index adb1cf31bbd..5a1f1fc876a 100644 --- a/source/blender/modifiers/intern/MOD_util.h +++ b/source/blender/modifiers/intern/MOD_util.h @@ -31,14 +31,12 @@ /* so modifier types match their defines */ #include "MOD_modifiertypes.h" -struct CustomData; struct DerivedMesh; struct MDeformVert; struct ModifierData; struct Object; struct Scene; struct Tex; -struct TexResult; void modifier_init_texture(const struct Scene *scene, struct Tex *texture); void get_texture_coords(struct MappingInfoModifierData *dmd, struct Object *ob, struct DerivedMesh *dm, diff --git a/source/blender/nodes/NOD_socket.h b/source/blender/nodes/NOD_socket.h index 81230456193..5c8875593e7 100644 --- a/source/blender/nodes/NOD_socket.h +++ b/source/blender/nodes/NOD_socket.h @@ -43,7 +43,6 @@ struct bNodeTree; struct bNode; -struct bNodeStack; struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp, int in_out); diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h index d286d3df1a5..dba1cd11ae0 100644 --- a/source/blender/physics/intern/implicit.h +++ b/source/blender/physics/intern/implicit.h @@ -59,7 +59,6 @@ extern "C" { //#define IMPLICIT_ENABLE_EIGEN_DEBUG struct Implicit_Data; -struct ImplicitSolverInput; typedef struct ImplicitSolverResult { int status; @@ -133,7 +132,6 @@ bool BPH_mass_spring_force_spring_goal(struct Implicit_Data *data, int i, const struct HairGrid; -struct Object; struct VoxelData; #define MAX_HAIR_GRID_RES 256 diff --git a/source/blender/quicktime/quicktime_export.h b/source/blender/quicktime/quicktime_export.h index 6709f87fb1c..360c475fdb5 100644 --- a/source/blender/quicktime/quicktime_export.h +++ b/source/blender/quicktime/quicktime_export.h @@ -54,7 +54,6 @@ struct ImageFormatData; struct RenderData; struct ReportList; struct Scene; -struct wmOperatorType; int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview); //for movie handle (BKE writeavi.c now) int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); diff --git a/source/blender/render/extern/include/RE_bake.h b/source/blender/render/extern/include/RE_bake.h index 481da452529..ffc1246b878 100644 --- a/source/blender/render/extern/include/RE_bake.h +++ b/source/blender/render/extern/include/RE_bake.h @@ -32,6 +32,7 @@ #ifndef __RE_BAKE_H__ #define __RE_BAKE_H__ +struct ImBuf; struct Render; struct Mesh; diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h index d76d16a641e..6adbb6d0e62 100644 --- a/source/blender/render/extern/include/RE_render_ext.h +++ b/source/blender/render/extern/include/RE_render_ext.h @@ -39,10 +39,8 @@ /* called by meshtools */ struct DerivedMesh; struct ImagePool; -struct LinkNode; struct MTex; struct Scene; -struct View3D; /* particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */ int externtex(struct MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool, const bool skip_load_image); diff --git a/source/blender/render/intern/include/initrender.h b/source/blender/render/intern/include/initrender.h index 1f11cdc6729..87e2d2519d5 100644 --- a/source/blender/render/intern/include/initrender.h +++ b/source/blender/render/intern/include/initrender.h @@ -33,7 +33,6 @@ #ifndef __INITRENDER_H__ #define __INITRENDER_H__ -struct Object; /* Functions */ diff --git a/source/blender/render/intern/include/occlusion.h b/source/blender/render/intern/include/occlusion.h index 2f3ac2a7bff..4a70d691436 100644 --- a/source/blender/render/intern/include/occlusion.h +++ b/source/blender/render/intern/include/occlusion.h @@ -35,11 +35,8 @@ struct Render; struct ShadeInput; -struct ShadeResult; struct RenderPart; struct ShadeSample; -struct DerivedMesh; -struct ObjectRen; void make_occ_tree(struct Render *re); void free_occ(struct Render *re); diff --git a/source/blender/render/intern/include/pixelshading.h b/source/blender/render/intern/include/pixelshading.h index faf8c5f54f5..8f23455564f 100644 --- a/source/blender/render/intern/include/pixelshading.h +++ b/source/blender/render/intern/include/pixelshading.h @@ -32,7 +32,6 @@ #ifndef __PIXELSHADING_H__ #define __PIXELSHADING_H__ -struct ImagePool; /** * Render the pixel at (x,y) for object ap. Apply the jitter mask. diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index a53ff302475..0d23c81afb0 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -58,7 +58,6 @@ struct MemArena; struct VertTableNode; struct VlakTableNode; struct GHash; -struct RenderBuckets; struct ObjectInstanceRen; struct RayObject; struct RayFace; @@ -389,7 +388,6 @@ struct halosort { /* ------------------------------------------------------------------------- */ struct Material; -struct MTFace; struct ImagePool; typedef struct RadFace { diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h index 88b639c4ba9..308903c6c6d 100644 --- a/source/blender/render/intern/include/rendercore.h +++ b/source/blender/render/intern/include/rendercore.h @@ -34,14 +34,11 @@ #include "render_types.h" -struct HaloRen; struct ShadeInput; struct ShadeResult; struct World; struct RenderPart; struct RenderLayer; -struct ObjectRen; -struct ListBase; struct RayObject; /* ------------------------------------------------------------------------- */ diff --git a/source/blender/render/intern/include/shadbuf.h b/source/blender/render/intern/include/shadbuf.h index 7c168baada7..ece6902b6b2 100644 --- a/source/blender/render/intern/include/shadbuf.h +++ b/source/blender/render/intern/include/shadbuf.h @@ -34,7 +34,6 @@ #include "render_types.h" -struct ObjectRen; /** * Calculates shadowbuffers for a vector of shadow-giving lamps diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h index 4f6e005d742..11dcc9d9e80 100644 --- a/source/blender/render/intern/include/shading.h +++ b/source/blender/render/intern/include/shading.h @@ -33,7 +33,6 @@ struct RenderLayer; struct PixStr; struct LampRen; struct VlakRen; -struct StrandSegment; struct StrandPoint; struct ObjectInstanceRen; struct Isect; diff --git a/source/blender/render/intern/include/sss.h b/source/blender/render/intern/include/sss.h index 91a8b91e638..0952c6bff65 100644 --- a/source/blender/render/intern/include/sss.h +++ b/source/blender/render/intern/include/sss.h @@ -55,7 +55,6 @@ void scatter_tree_free(ScatterTree *tree); struct Render; struct Material; -struct VlakRen; void make_sss_tree(struct Render *re); void sss_add_points(Render *re, float (*co)[3], float (*color)[3], float *area, int totpoint); diff --git a/source/blender/render/intern/include/strand.h b/source/blender/render/intern/include/strand.h index fdcce687f54..5687ef3c837 100644 --- a/source/blender/render/intern/include/strand.h +++ b/source/blender/render/intern/include/strand.h @@ -34,9 +34,6 @@ struct StrandBuffer; struct ShadeSample; struct StrandPart; struct Render; -struct RenderPart; -struct RenderBuckets; -struct RenderPrimitiveIterator; struct ZSpan; struct ObjectInstanceRen; struct StrandSurface; diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h index ec30c3241ab..cf804d75d70 100644 --- a/source/blender/render/intern/include/zbuf.h +++ b/source/blender/render/intern/include/zbuf.h @@ -36,7 +36,6 @@ struct RenderPart; struct RenderLayer; struct LampRen; -struct VlakRen; struct ListBase; struct ZSpan; struct APixstrand; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index d2abfd419d1..e64d08f38e1 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -53,13 +53,11 @@ struct wmEvent; struct wmEventHandler; struct wmGesture; struct wmJob; -struct wmNotifier; struct wmOperatorType; struct wmOperator; struct rcti; struct PointerRNA; struct PropertyRNA; -struct EnumPropertyItem; struct MenuType; struct wmDropBox; struct wmDrag; diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 0e3e65d2e21..e716cd6b779 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -109,7 +109,6 @@ extern "C" { struct bContext; struct wmEvent; struct wmWindowManager; -struct uiLayout; struct wmOperator; struct ImBuf; diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index 833234b0f13..fc7c9e191b0 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -32,7 +32,6 @@ #ifndef __WM_WINDOW_H__ #define __WM_WINDOW_H__ -struct bScreen; struct wmOperator; /* *************** internal api ************** */ -- cgit v1.2.3 From 44a4b90b4f303912390f5f846c1882ef37d975d1 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Sat, 28 Mar 2015 18:17:54 +0100 Subject: Fix collada compile after BKE cleanup --- source/blender/collada/DocumentImporter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 462b7b6f200..0aff5147060 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -771,9 +771,9 @@ MTex *DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::T return NULL; } - ma->mtex[i] = add_mtex(); + ma->mtex[i] = BKE_texture_mtex_add(); ma->mtex[i]->texco = TEXCO_UV; - ma->mtex[i]->tex = add_texture(G.main, "Texture"); + ma->mtex[i]->tex = BKE_texture_add(G.main, "Texture"); ma->mtex[i]->tex->type = TEX_IMAGE; ma->mtex[i]->tex->ima = uid_image_map[ima_uid]; -- cgit v1.2.3 From 2c5ba414133bdc4f00a818fcf15ec98a9710f631 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 28 Mar 2015 23:40:56 +0500 Subject: Code cleanup: Get rid of set but unused matrix --- source/blender/render/intern/source/pointdensity.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index 1f4726809de..fc1794c65e9 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -112,12 +112,10 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa int total_particles, offset=0; int data_used = point_data_used(pd); float partco[3]; - float obview[4][4]; /* init everything */ if (!psys || !ob || !pd) return; - mul_m4_m4m4(obview, ob->obmat, re->viewinv); /* Just to create a valid rendering context for particles */ psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, 0); -- cgit v1.2.3 From b25c208d5bc7f77fd1176f94528d1dde8914111f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 28 Mar 2015 23:50:36 +0500 Subject: Code cleanup: whitespace, line wrapping --- source/blender/render/intern/source/pointdensity.c | 241 ++++++++++++--------- 1 file changed, 133 insertions(+), 108 deletions(-) diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index fc1794c65e9..9cda5aa97eb 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -1,4 +1,4 @@ -/* +/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -68,25 +68,34 @@ extern struct Render R; static int point_data_used(PointDensity *pd) { int pd_bitflag = 0; - + if (pd->source == TEX_PD_PSYS) { - if ((pd->noise_influence == TEX_PD_NOISE_VEL) || (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) || (pd->color_source == TEX_PD_COLOR_PARTVEL) || (pd->color_source == TEX_PD_COLOR_PARTSPEED)) + if ((pd->noise_influence == TEX_PD_NOISE_VEL) || + (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) || + (pd->color_source == TEX_PD_COLOR_PARTVEL) || + (pd->color_source == TEX_PD_COLOR_PARTSPEED)) + { pd_bitflag |= POINT_DATA_VEL; - if ((pd->noise_influence == TEX_PD_NOISE_AGE) || (pd->color_source == TEX_PD_COLOR_PARTAGE) || (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE)) + } + if ((pd->noise_influence == TEX_PD_NOISE_AGE) || + (pd->color_source == TEX_PD_COLOR_PARTAGE) || + (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE)) + { pd_bitflag |= POINT_DATA_LIFE; + } } - + return pd_bitflag; } -/* additional data stored alongside the point density BVH, - * accessible by point index number to retrieve other information +/* additional data stored alongside the point density BVH, + * accessible by point index number to retrieve other information * such as particle velocity or lifetime */ static void alloc_point_data(PointDensity *pd, int total_particles, int point_data_used) { int data_size = 0; - + if (point_data_used & POINT_DATA_VEL) { /* store 3 channels of velocity data */ data_size += 3; @@ -96,58 +105,63 @@ static void alloc_point_data(PointDensity *pd, int total_particles, int point_da data_size += 1; } - if (data_size) - pd->point_data = MEM_mallocN(sizeof(float)*data_size*total_particles, "particle point data"); + if (data_size) { + pd->point_data = MEM_mallocN(sizeof(float) * data_size * total_particles, + "particle point data"); + } } static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, ParticleSystem *psys) { - DerivedMesh* dm; + DerivedMesh *dm; ParticleKey state; ParticleCacheKey *cache; - ParticleSimulationData sim= {NULL}; - ParticleData *pa=NULL; + ParticleSimulationData sim = {NULL}; + ParticleData *pa = NULL; float cfra = BKE_scene_frame_get(re->scene); int i /*, childexists*/ /* UNUSED */; - int total_particles, offset=0; + int total_particles, offset = 0; int data_used = point_data_used(pd); float partco[3]; - + /* init everything */ - if (!psys || !ob || !pd) return; + if (!psys || !ob || !pd) { + return; + } - /* Just to create a valid rendering context for particles */ psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, 0); - - dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL); - + + dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); + if ( !psys_check_enabled(ob, psys)) { psys_render_restore(ob, psys); return; } - - sim.scene= re->scene; - sim.ob= ob; - sim.psys= psys; + + sim.scene = re->scene; + sim.ob = ob; + sim.psys = psys; /* in case ob->imat isn't up-to-date */ invert_m4_m4(ob->imat, ob->obmat); - - total_particles = psys->totpart+psys->totchild; + + total_particles = psys->totpart + psys->totchild; psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); - + pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6); alloc_point_data(pd, total_particles, data_used); pd->totpoints = total_particles; - if (data_used & POINT_DATA_VEL) offset = pd->totpoints*3; - + if (data_used & POINT_DATA_VEL) { + offset = pd->totpoints * 3; + } + #if 0 /* UNUSED */ if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT)) childexists = 1; #endif - for (i=0, pa=psys->particles; i < total_particles; i++, pa++) { + for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) { if (psys->part->type == PART_HAIR) { /* hair particles */ @@ -173,19 +187,19 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa if (data_used & POINT_DATA_LIFE) { if (i < psys->totpart) { - state.time = (cfra - pa->time)/pa->lifetime; + state.time = (cfra - pa->time) / pa->lifetime; } else { - ChildParticle *cpa= (psys->child + i) - psys->totpart; + ChildParticle *cpa = (psys->child + i) - psys->totpart; float pa_birthtime, pa_dietime; - + state.time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime); } } } copy_v3_v3(partco, state.co); - + if (pd->psys_cache_space == TEX_PD_OBJECTSPACE) mul_m4_v3(ob->imat, partco); else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) { @@ -194,27 +208,27 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa else { /* TEX_PD_WORLDSPACE */ } - + BLI_bvhtree_insert(pd->point_tree, i, partco, 1); - + if (data_used & POINT_DATA_VEL) { - pd->point_data[i*3 + 0] = state.vel[0]; - pd->point_data[i*3 + 1] = state.vel[1]; - pd->point_data[i*3 + 2] = state.vel[2]; + pd->point_data[i * 3 + 0] = state.vel[0]; + pd->point_data[i * 3 + 1] = state.vel[1]; + pd->point_data[i * 3 + 2] = state.vel[2]; } if (data_used & POINT_DATA_LIFE) { pd->point_data[offset + i] = state.time; } } - + BLI_bvhtree_balance(pd->point_tree); dm->release(dm); - + if (psys->lattice_deform_data) { end_latt_deform(psys->lattice_deform_data); psys->lattice_deform_data = NULL; } - + psys_render_restore(ob, psys); } @@ -224,18 +238,20 @@ static void pointdensity_cache_object(Render *re, PointDensity *pd, Object *ob) int i; DerivedMesh *dm; MVert *mvert = NULL; - - dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL); - mvert= dm->getVertArray(dm); /* local object space */ - - pd->totpoints= dm->getNumVerts(dm); - if (pd->totpoints == 0) return; + + dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); + mvert = dm->getVertArray(dm); /* local object space */ + + pd->totpoints = dm->getNumVerts(dm); + if (pd->totpoints == 0) { + return; + } pd->point_tree = BLI_bvhtree_new(pd->totpoints, 0.0, 4, 6); - - for (i=0; i < pd->totpoints; i++, mvert++) { + + for (i = 0; i < pd->totpoints; i++, mvert++) { float co[3]; - + copy_v3_v3(co, mvert->co); switch (pd->ob_cache_space) { @@ -253,7 +269,7 @@ static void pointdensity_cache_object(Render *re, PointDensity *pd, Object *ob) BLI_bvhtree_insert(pd->point_tree, i, co, 1); } - + BLI_bvhtree_balance(pd->point_tree); dm->release(dm); @@ -261,7 +277,7 @@ static void pointdensity_cache_object(Render *re, PointDensity *pd, Object *ob) void cache_pointdensity(Render *re, Tex *tex) { PointDensity *pd = tex->pd; - + if (!pd) return; @@ -269,16 +285,20 @@ void cache_pointdensity(Render *re, Tex *tex) BLI_bvhtree_free(pd->point_tree); pd->point_tree = NULL; } - + if (pd->source == TEX_PD_PSYS) { Object *ob = pd->object; ParticleSystem *psys; - if (!ob || !pd->psys) return; + if (!ob || !pd->psys) { + return; + } + + psys = BLI_findlink(&ob->particlesystem, pd->psys - 1); + if (!psys) { + return; + } - psys= BLI_findlink(&ob->particlesystem, pd->psys-1); - if (!psys) return; - pointdensity_cache_psys(re, pd, ob, psys); } else if (pd->source == TEX_PD_OBJECT) { @@ -293,7 +313,7 @@ static void free_pointdensity(Render *UNUSED(re), Tex *tex) PointDensity *pd = tex->pd; if (!pd) return; - + if (pd->point_tree) { BLI_bvhtree_free(pd->point_tree); pd->point_tree = NULL; @@ -311,19 +331,20 @@ static void free_pointdensity(Render *UNUSED(re), Tex *tex) void make_pointdensities(Render *re) { Tex *tex; - - if (re->scene->r.scemode & R_BUTS_PREVIEW) + + if (re->scene->r.scemode & R_BUTS_PREVIEW) { return; - + } + re->i.infostr = IFACE_("Caching Point Densities"); re->stats_draw(re->sdh, &re->i); - for (tex= re->main->tex.first; tex; tex= tex->id.next) { - if (tex->id.us && tex->type==TEX_POINTDENSITY) { + for (tex = re->main->tex.first; tex != NULL; tex = tex->id.next) { + if (tex->id.us && tex->type == TEX_POINTDENSITY) { cache_pointdensity(re, tex); } } - + re->i.infostr = NULL; re->stats_draw(re->sdh, &re->i); } @@ -331,12 +352,12 @@ void make_pointdensities(Render *re) void free_pointdensities(Render *re) { Tex *tex; - + if (re->scene->r.scemode & R_BUTS_PREVIEW) return; - - for (tex= re->main->tex.first; tex; tex= tex->id.next) { - if (tex->id.us && tex->type==TEX_POINTDENSITY) { + + for (tex = re->main->tex.first; tex != NULL; tex = tex->id.next) { + if (tex->id.us && tex->type == TEX_POINTDENSITY) { free_pointdensity(re, tex); } } @@ -362,20 +383,20 @@ static void accum_density(void *userdata, int index, float squared_dist) PointDensityRangeData *pdr = (PointDensityRangeData *)userdata; const float dist = (pdr->squared_radius - squared_dist) / pdr->squared_radius * 0.5f; float density = 0.0f; - + if (pdr->point_data_used & POINT_DATA_VEL) { - pdr->vec[0] += pdr->point_data[index*3 + 0]; // * density; - pdr->vec[1] += pdr->point_data[index*3 + 1]; // * density; - pdr->vec[2] += pdr->point_data[index*3 + 2]; // * density; + pdr->vec[0] += pdr->point_data[index * 3 + 0]; // * density; + pdr->vec[1] += pdr->point_data[index * 3 + 1]; // * density; + pdr->vec[2] += pdr->point_data[index * 3 + 2]; // * density; } if (pdr->point_data_used & POINT_DATA_LIFE) { *pdr->age += pdr->point_data[pdr->offset + index]; // * density; } - + if (pdr->falloff_type == TEX_PD_FALLOFF_STD) density = dist; else if (pdr->falloff_type == TEX_PD_FALLOFF_SMOOTH) - density = 3.0f*dist*dist - 2.0f*dist*dist*dist; + density = 3.0f * dist * dist - 2.0f * dist * dist * dist; else if (pdr->falloff_type == TEX_PD_FALLOFF_SOFT) density = pow(dist, pdr->softness); else if (pdr->falloff_type == TEX_PD_FALLOFF_CONSTANT) @@ -384,30 +405,30 @@ static void accum_density(void *userdata, int index, float squared_dist) density = sqrtf(dist); else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE) { if (pdr->point_data_used & POINT_DATA_LIFE) - density = dist*MIN2(pdr->point_data[pdr->offset + index], 1.0f); + density = dist * MIN2(pdr->point_data[pdr->offset + index], 1.0f); else density = dist; } else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) { if (pdr->point_data_used & POINT_DATA_VEL) - density = dist*len_v3(pdr->point_data + index*3)*pdr->velscale; + density = dist * len_v3(pdr->point_data + index * 3) * pdr->velscale; else density = dist; } - + if (pdr->density_curve && dist != 0.0f) { curvemapping_initialize(pdr->density_curve); - density = curvemapping_evaluateF(pdr->density_curve, 0, density/dist)*dist; + density = curvemapping_evaluateF(pdr->density_curve, 0, density / dist) * dist; } - + *pdr->density += density; } -static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData *pdr, +static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData *pdr, float *density, float *vec, float *age, struct CurveMapping *density_curve, float velscale) { - pdr->squared_radius = pd->radius*pd->radius; + pdr->squared_radius = pd->radius * pd->radius; pdr->density = density; pdr->point_data = pd->point_data; pdr->falloff_type = pd->falloff_type; @@ -416,7 +437,7 @@ static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData * pdr->softness = pd->falloff_softness; pdr->noise_influence = pd->noise_influence; pdr->point_data_used = point_data_used(pd); - pdr->offset = (pdr->point_data_used & POINT_DATA_VEL)?pd->totpoints*3:0; + pdr->offset = (pdr->point_data_used & POINT_DATA_VEL) ? pd->totpoints * 3 : 0; pdr->density_curve = density_curve; pdr->velscale = velscale; } @@ -427,52 +448,56 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres) int retval = TEX_INT; PointDensity *pd = tex->pd; PointDensityRangeData pdr; - float density=0.0f, age=0.0f, time=0.0f; + float density = 0.0f, age = 0.0f, time = 0.0f; float vec[3] = {0.0f, 0.0f, 0.0f}, co[3]; float col[4]; float turb, noise_fac; - int num=0; - + int num = 0; + texres->tin = 0.0f; - + if ((!pd) || (!pd->point_tree)) return 0; - - init_pointdensityrangedata(pd, &pdr, &density, vec, &age, - (pd->flag&TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : NULL), pd->falloff_speed_scale*0.001f); + + init_pointdensityrangedata(pd, &pdr, &density, vec, &age, + (pd->flag & TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : NULL), + pd->falloff_speed_scale * 0.001f); noise_fac = pd->noise_fac * 0.5f; /* better default */ - + copy_v3_v3(co, texvec); - + if (point_data_used(pd)) { /* does a BVH lookup to find accumulated density and additional point data * * stores particle velocity vector in 'vec', and particle lifetime in 'time' */ num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr); if (num > 0) { age /= num; - mul_v3_fl(vec, 1.0f/num); + mul_v3_fl(vec, 1.0f / num); } - + /* reset */ density = vec[0] = vec[1] = vec[2] = 0.0f; } - + if (pd->flag & TEX_PD_TURBULENCE) { - + if (pd->noise_influence == TEX_PD_NOISE_AGE) { - turb = BLI_gTurbulence(pd->noise_size, texvec[0]+age, texvec[1]+age, texvec[2]+age, pd->noise_depth, 0, pd->noise_basis); + turb = BLI_gTurbulence(pd->noise_size, texvec[0] + age, texvec[1] + age, texvec[2] + age, + pd->noise_depth, 0, pd->noise_basis); } else if (pd->noise_influence == TEX_PD_NOISE_TIME) { time = R.r.cfra / (float)R.r.efra; - turb = BLI_gTurbulence(pd->noise_size, texvec[0]+time, texvec[1]+time, texvec[2]+time, pd->noise_depth, 0, pd->noise_basis); + turb = BLI_gTurbulence(pd->noise_size, texvec[0] + time, texvec[1] + time, texvec[2] + time, + pd->noise_depth, 0, pd->noise_basis); //turb = BLI_turbulence(pd->noise_size, texvec[0]+time, texvec[1]+time, texvec[2]+time, pd->noise_depth); } else { - turb = BLI_gTurbulence(pd->noise_size, texvec[0]+vec[0], texvec[1]+vec[1], texvec[2]+vec[2], pd->noise_depth, 0, pd->noise_basis); + turb = BLI_gTurbulence(pd->noise_size, texvec[0] + vec[0], texvec[1] + vec[1], texvec[2] + vec[2], + pd->noise_depth, 0, pd->noise_basis); } turb -= 0.5f; /* re-center 0.0-1.0 range around 0 to prevent offsetting result */ - + /* now we have an offset coordinate to use for the density lookup */ co[0] = texvec[0] + noise_fac * turb; co[1] = texvec[1] + noise_fac * turb; @@ -483,17 +508,17 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres) num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr); if (num > 0) { age /= num; - mul_v3_fl(vec, 1.0f/num); + mul_v3_fl(vec, 1.0f / num); } - + texres->tin = density; BRICONT; - + if (pd->color_source == TEX_PD_COLOR_CONSTANT) return retval; - + retval |= TEX_RGB; - + switch (pd->color_source) { case TEX_PD_COLOR_PARTAGE: if (pd->coba) { @@ -508,7 +533,7 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres) case TEX_PD_COLOR_PARTSPEED: { float speed = len_v3(vec) * pd->speed_scale; - + if (pd->coba) { if (do_colorband(pd->coba, speed, col)) { texres->talpha = true; @@ -531,9 +556,9 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres) break; } BRICONTRGB; - + return retval; - + #if 0 if (texres->nor!=NULL) { texres->nor[0] = texres->nor[1] = texres->nor[2] = 0.0f; -- cgit v1.2.3 From 94b01931963a725b9a85a767d9bcaa25c2eb550a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 29 Mar 2015 02:14:06 +0500 Subject: Make point density sampling functions a bit easier for re-use Still not ideal but getting closer. Main annoying thing so far is dependency of Render structure for now. It is used to switch particles to render mode and could probably also be eliminated. --- .../blender/render/intern/include/pointdensity.h | 4 +++- source/blender/render/intern/source/pointdensity.c | 28 ++++++++++------------ .../blender/render/intern/source/render_texture.c | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/source/blender/render/intern/include/pointdensity.h b/source/blender/render/intern/include/pointdensity.h index e0c293e2473..1d1e808e8d3 100644 --- a/source/blender/render/intern/include/pointdensity.h +++ b/source/blender/render/intern/include/pointdensity.h @@ -37,10 +37,12 @@ * Make point density kd-trees for all point density textures in the scene */ +struct PointDensity; struct Render; struct TexResult; -void cache_pointdensity(struct Render *re, struct Tex *tex); +void free_pointdensity(struct PointDensity *pd); +void cache_pointdensity(struct Render *re, struct PointDensity *pd); void make_pointdensities(struct Render *re); void free_pointdensities(struct Render *re); int pointdensitytex(struct Tex *tex, const float texvec[3], struct TexResult *texres); diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index 9cda5aa97eb..320ab07dd29 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -233,13 +233,13 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa } -static void pointdensity_cache_object(Render *re, PointDensity *pd, Object *ob) +static void pointdensity_cache_object(Scene *scene, PointDensity *pd, Object *ob) { int i; DerivedMesh *dm; MVert *mvert = NULL; - dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); + dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); mvert = dm->getVertArray(dm); /* local object space */ pd->totpoints = dm->getNumVerts(dm); @@ -274,12 +274,12 @@ static void pointdensity_cache_object(Render *re, PointDensity *pd, Object *ob) dm->release(dm); } -void cache_pointdensity(Render *re, Tex *tex) -{ - PointDensity *pd = tex->pd; - if (!pd) +void cache_pointdensity(Render *re, PointDensity *pd) +{ + if (pd == NULL) { return; + } if (pd->point_tree) { BLI_bvhtree_free(pd->point_tree); @@ -304,15 +304,15 @@ void cache_pointdensity(Render *re, Tex *tex) else if (pd->source == TEX_PD_OBJECT) { Object *ob = pd->object; if (ob && ob->type == OB_MESH) - pointdensity_cache_object(re, pd, ob); + pointdensity_cache_object(re->scene, pd, ob); } } -static void free_pointdensity(Render *UNUSED(re), Tex *tex) +void free_pointdensity(PointDensity *pd) { - PointDensity *pd = tex->pd; - - if (!pd) return; + if (pd == NULL) { + return; + } if (pd->point_tree) { BLI_bvhtree_free(pd->point_tree); @@ -326,8 +326,6 @@ static void free_pointdensity(Render *UNUSED(re), Tex *tex) pd->totpoints = 0; } - - void make_pointdensities(Render *re) { Tex *tex; @@ -341,7 +339,7 @@ void make_pointdensities(Render *re) for (tex = re->main->tex.first; tex != NULL; tex = tex->id.next) { if (tex->id.us && tex->type == TEX_POINTDENSITY) { - cache_pointdensity(re, tex); + cache_pointdensity(re, tex->pd); } } @@ -358,7 +356,7 @@ void free_pointdensities(Render *re) for (tex = re->main->tex.first; tex != NULL; tex = tex->id.next) { if (tex->id.us && tex->type == TEX_POINTDENSITY) { - free_pointdensity(re, tex); + free_pointdensity(tex->pd); } } } diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index df4553978a3..dc8c714bea5 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -3631,7 +3631,7 @@ Material *RE_init_sample_material(Material *orig_mat, Scene *scene) unit_m4(dummy_re.viewmat); unit_m4(dummy_re.winmat); dummy_re.winx = dummy_re.winy = 128; - cache_pointdensity(&dummy_re, tex); + cache_pointdensity(&dummy_re, tex->pd); } /* update image sequences and movies */ -- cgit v1.2.3 From 47c1112e6e09634b8e394102bacc74ca12818a62 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 29 Mar 2015 02:34:44 +0500 Subject: Make internal functions of point density independent from Render --- source/blender/render/intern/source/pointdensity.c | 31 ++++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index 320ab07dd29..3a1f1fbb744 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -111,14 +111,20 @@ static void alloc_point_data(PointDensity *pd, int total_particles, int point_da } } -static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, ParticleSystem *psys) +static void pointdensity_cache_psys(Scene *scene, + PointDensity *pd, + Object *ob, + ParticleSystem *psys, + float viewmat[4][4], + float winmat[4][4], + int winx, int winy) { DerivedMesh *dm; ParticleKey state; ParticleCacheKey *cache; ParticleSimulationData sim = {NULL}; ParticleData *pa = NULL; - float cfra = BKE_scene_frame_get(re->scene); + float cfra = BKE_scene_frame_get(scene); int i /*, childexists*/ /* UNUSED */; int total_particles, offset = 0; int data_used = point_data_used(pd); @@ -130,16 +136,16 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa } /* Just to create a valid rendering context for particles */ - psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, 0); + psys_render_set(ob, psys, viewmat, winmat, winx, winy, 0); - dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); + dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); if ( !psys_check_enabled(ob, psys)) { psys_render_restore(ob, psys); return; } - sim.scene = re->scene; + sim.scene = scene; sim.ob = ob; sim.psys = psys; @@ -275,7 +281,11 @@ static void pointdensity_cache_object(Scene *scene, PointDensity *pd, Object *ob } -void cache_pointdensity(Render *re, PointDensity *pd) +static void cache_pointdensity_ex(Scene *scene, + PointDensity *pd, + float viewmat[4][4], + float winmat[4][4], + int winx, int winy) { if (pd == NULL) { return; @@ -299,15 +309,20 @@ void cache_pointdensity(Render *re, PointDensity *pd) return; } - pointdensity_cache_psys(re, pd, ob, psys); + pointdensity_cache_psys(scene, pd, ob, psys, viewmat, winmat, winx, winy); } else if (pd->source == TEX_PD_OBJECT) { Object *ob = pd->object; if (ob && ob->type == OB_MESH) - pointdensity_cache_object(re->scene, pd, ob); + pointdensity_cache_object(scene, pd, ob); } } +void cache_pointdensity(Render *re, PointDensity *pd) +{ + cache_pointdensity_ex(re->scene, pd, re->viewmat, re->winmat, re->winx, re->winy); +} + void free_pointdensity(PointDensity *pd) { if (pd == NULL) { -- cgit v1.2.3 From 70d9c013257906d3e894907b92e693d1ccebd7fd Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 29 Mar 2015 13:14:59 +0200 Subject: Fix T44162: Outliner: modifier's icons toggle update issue Use same notifier for button callback as the one used in matching outliner operator... --- source/blender/editors/space_outliner/outliner_draw.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 5a11b9a2395..873b5f5319f 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -290,8 +290,7 @@ static void restrictbutton_modifier_cb(bContext *C, void *UNUSED(poin), void *po Object *ob = (Object *)poin2; DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); } static void restrictbutton_bone_visibility_cb(bContext *C, void *poin, void *poin2) -- cgit v1.2.3 From f01456aaa4a87cd76feaef50ec822340197f9eda Mon Sep 17 00:00:00 2001 From: Martijn Berger Date: Sun, 29 Mar 2015 22:12:22 +0200 Subject: Optionally use c++11 stuff instead of boost in cycles where possible. We do and continue to depend on boost though Reviewers: dingto, sergey Reviewed By: sergey Subscribers: #cycles Differential Revision: https://developer.blender.org/D1185 --- intern/cycles/CMakeLists.txt | 21 +++++++++++++++++++++ intern/cycles/SConscript | 12 ++++++++++++ intern/cycles/device/device.h | 4 ++-- intern/cycles/device/device_task.h | 10 +++++----- intern/cycles/render/image.h | 6 +++--- intern/cycles/render/session.h | 4 ++-- intern/cycles/util/util_foreach.h | 8 ++++++-- intern/cycles/util/util_function.h | 25 +++++++++++++++++++++---- intern/cycles/util/util_map.h | 27 ++++++++++++++++++++++++++- intern/cycles/util/util_progress.h | 8 ++++---- intern/cycles/util/util_set.h | 12 +++++++++--- intern/cycles/util/util_task.h | 2 +- intern/cycles/util/util_thread.h | 21 +++++++++++++++++---- 13 files changed, 129 insertions(+), 31 deletions(-) diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 2ba6af48d0d..c4cadfe0bf7 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -152,6 +152,27 @@ add_definitions( -DWITH_MULTI ) +TEST_UNORDERED_MAP_SUPPORT() +if(HAVE_STD_UNORDERED_MAP_HEADER) + if(HAVE_UNORDERED_MAP_IN_STD_NAMESPACE) + add_definitions(-DCYCLES_STD_UNORDERED_MAP) + else() + if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE) + add_definitions(-DCYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) + else() + add_definitions(-DCYCLES_NO_UNORDERED_MAP) + message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)") + endif() + endif() +else() + if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE) + add_definitions(-DCYCLES_TR1_UNORDERED_MAP) + else() + add_definitions(-DCYCLES_NO_UNORDERED_MAP) + message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)") + endif() +endif() + # Logging capabilities using GLog library. if(WITH_CYCLES_LOGGING) add_definitions(-DWITH_CYCLES_LOGGING) diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript index 9cbdb93ce85..79e14ab9a58 100644 --- a/intern/cycles/SConscript +++ b/intern/cycles/SConscript @@ -47,6 +47,18 @@ cxxflags = Split(env['CXXFLAGS']) defs += env['BF_GL_DEFINITIONS'] +if env['WITH_UNORDERED_MAP_SUPPORT']: + if env['UNORDERED_MAP_HEADER'] == 'unordered_map': + if env['UNORDERED_MAP_NAMESPACE'] == 'std': + defs.append('CYCLES_STD_UNORDERED_MAP') + elif env['UNORDERED_MAP_NAMESPACE'] == 'std::tr1': + defs.append('CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE') + elif env['UNORDERED_MAP_NAMESPACE'] == 'std::tr1': + defs.append('CYCLES_TR1_UNORDERED_MAP') +else: + print("-- Replacing unordered_map/set with map/set (warning: slower!)") + defs.append('CYCLES_NO_UNORDERED_MAP') + defs.append('CCL_NAMESPACE_BEGIN=namespace ccl {') defs.append('CCL_NAMESPACE_END=}') diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 18fc707beab..7eb3f6c822b 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -72,8 +72,8 @@ public: /* Device */ struct DeviceDrawParams { - boost::function bind_display_space_shader_cb; - boost::function unbind_display_space_shader_cb; + function bind_display_space_shader_cb; + function unbind_display_space_shader_cb; }; class Device { diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h index 84945bcf9a5..0c23d8971e0 100644 --- a/intern/cycles/device/device_task.h +++ b/intern/cycles/device/device_task.h @@ -57,11 +57,11 @@ public: void update_progress(RenderTile *rtile); - boost::function acquire_tile; - boost::function update_progress_sample; - boost::function update_tile_sample; - boost::function release_tile; - boost::function get_cancel; + function acquire_tile; + function update_progress_sample; + function update_tile_sample; + function release_tile; + function get_cancel; bool need_finish_queue; bool integrator_branched; diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 2f5dcb6efd5..1045b4532e4 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -73,9 +73,9 @@ public: bool need_update; - boost::function builtin_image_info_cb; - boost::function builtin_image_pixels_cb; - boost::function builtin_image_float_pixels_cb; + function builtin_image_info_cb; + function builtin_image_pixels_cb; + function builtin_image_float_pixels_cb; struct Image { string filename; diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index c77652d3722..8b108b0940f 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -125,8 +125,8 @@ public: TileManager tile_manager; Stats stats; - boost::function write_render_tile_cb; - boost::function update_render_tile_cb; + function write_render_tile_cb; + function update_render_tile_cb; Session(const SessionParams& params); ~Session(); diff --git a/intern/cycles/util/util_foreach.h b/intern/cycles/util/util_foreach.h index 065bd33ebd2..4f7337107b3 100644 --- a/intern/cycles/util/util_foreach.h +++ b/intern/cycles/util/util_foreach.h @@ -19,8 +19,12 @@ /* Use Boost to get nice foreach() loops for STL data structures. */ -#include -#define foreach BOOST_FOREACH +#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800) +# define foreach(x, y) for(x : y) +#else +# include +# define foreach BOOST_FOREACH +#endif #endif /* __UTIL_FOREACH_H__ */ diff --git a/intern/cycles/util/util_function.h b/intern/cycles/util/util_function.h index 7a312efaad7..83c07ae06a8 100644 --- a/intern/cycles/util/util_function.h +++ b/intern/cycles/util/util_function.h @@ -17,14 +17,31 @@ #ifndef __UTIL_FUNCTION_H__ #define __UTIL_FUNCTION_H__ -#include -#include +#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800) +# include +#else +# include +# include +#endif CCL_NAMESPACE_BEGIN +#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800) +# define function_bind std::bind +using std::function; +using std::placeholders::_1; +using std::placeholders::_2; +using std::placeholders::_3; +using std::placeholders::_4; +using std::placeholders::_5; +using std::placeholders::_6; +using std::placeholders::_7; +using std::placeholders::_8; +using std::placeholders::_9; +#else using boost::function; -#define function_bind boost::bind - +# define function_bind boost::bind +#endif CCL_NAMESPACE_END #endif /* __UTIL_FUNCTION_H__ */ diff --git a/intern/cycles/util/util_map.h b/intern/cycles/util/util_map.h index 54d6a8d6424..46c2885f8b0 100644 --- a/intern/cycles/util/util_map.h +++ b/intern/cycles/util/util_map.h @@ -18,13 +18,38 @@ #define __UTIL_MAP_H__ #include -#include + +#if defined(CYCLES_TR1_UNORDERED_MAP) +# include +#endif + +#if defined(CYCLES_STD_UNORDERED_MAP) || defined(CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) +# include +#endif + +#if !defined(CYCLES_NO_UNORDERED_MAP) && !defined(CYCLES_TR1_UNORDERED_MAP) && \ + !defined(CYCLES_STD_UNORDERED_MAP) && !defined(CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT +# error One of: CYCLES_NO_UNORDERED_MAP, CYCLES_TR1_UNORDERED_MAP,\ + CYCLES_STD_UNORDERED_MAP, CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT +#endif + CCL_NAMESPACE_BEGIN using std::map; using std::pair; + +#if defined(CYCLES_NO_UNORDERED_MAP) +typedef std::map unordered_map; +#endif + +#if defined(CYCLES_TR1_UNORDERED_MAP) || defined(CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) using std::tr1::unordered_map; +#endif + +#if defined(CYCLES_STD_UNORDERED_MAP) +using std::unordered_map; +#endif CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h index 0ff48630a81..963987487ed 100644 --- a/intern/cycles/util/util_progress.h +++ b/intern/cycles/util/util_progress.h @@ -110,7 +110,7 @@ public: return cancel_message; } - void set_cancel_callback(boost::function function) + void set_cancel_callback(function function) { cancel_cb = function; } @@ -275,7 +275,7 @@ public: } } - void set_update_callback(boost::function function) + void set_update_callback(function function) { update_cb = function; } @@ -283,8 +283,8 @@ public: protected: thread_mutex progress_mutex; thread_mutex update_mutex; - boost::function update_cb; - boost::function cancel_cb; + function update_cb; + function cancel_cb; int tile; /* counter for rendered tiles */ int sample; /* counter of rendered samples, global for all tiles */ diff --git a/intern/cycles/util/util_set.h b/intern/cycles/util/util_set.h index 73a2bf19899..b3cb8dd8af5 100644 --- a/intern/cycles/util/util_set.h +++ b/intern/cycles/util/util_set.h @@ -18,13 +18,19 @@ #define __UTIL_SET_H__ #include -#include - +#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800) +# include +#else +# include +#endif CCL_NAMESPACE_BEGIN using std::set; +#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800) +using std::unordered_set; +#else using std::tr1::unordered_set; - +#endif CCL_NAMESPACE_END #endif /* __UTIL_SET_H__ */ diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h index 8fac12e9987..debcff3b776 100644 --- a/intern/cycles/util/util_task.h +++ b/intern/cycles/util/util_task.h @@ -27,7 +27,7 @@ class Task; class TaskPool; class TaskScheduler; -typedef boost::function TaskRunFunction; +typedef function TaskRunFunction; /* Task * diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h index fbbb9b42e31..9c19235d41d 100644 --- a/intern/cycles/util/util_thread.h +++ b/intern/cycles/util/util_thread.h @@ -17,7 +17,14 @@ #ifndef __UTIL_THREAD_H__ #define __UTIL_THREAD_H__ -#include +#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800) +# include +# include +# include +# include +#else +# include +#endif #include #include @@ -25,18 +32,24 @@ CCL_NAMESPACE_BEGIN +#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800) +typedef std::mutex thread_mutex; +typedef std::unique_lock thread_scoped_lock; +typedef std::condition_variable thread_condition_variable; +#else /* use boost for mutexes */ - typedef boost::mutex thread_mutex; typedef boost::mutex::scoped_lock thread_scoped_lock; typedef boost::condition_variable thread_condition_variable; +#endif /* own pthread based implementation, to avoid boost version conflicts with * dynamically loaded blender plugins */ class thread { public: - thread(boost::function run_cb_) + thread(function run_cb_) + { joined = false; run_cb = run_cb_; @@ -63,7 +76,7 @@ public: } protected: - boost::function run_cb; + function run_cb; pthread_t pthread_id; bool joined; }; -- cgit v1.2.3 From 3204aff6d0a4cddf1e09e659858f9d5e573c84a5 Mon Sep 17 00:00:00 2001 From: Martijn Berger Date: Sun, 29 Mar 2015 22:22:53 +0200 Subject: Fix compilation of cycles network server when logging is enabled --- intern/cycles/app/cycles_server.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/intern/cycles/app/cycles_server.cpp b/intern/cycles/app/cycles_server.cpp index 6522b4cde52..4ef9cd070bb 100644 --- a/intern/cycles/app/cycles_server.cpp +++ b/intern/cycles/app/cycles_server.cpp @@ -24,6 +24,7 @@ #include "util_stats.h" #include "util_string.h" #include "util_task.h" +#include "util_logging.h" using namespace ccl; -- cgit v1.2.3 From ab9d903b992680d6eefb5cfddb61bc24d47f0f63 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 30 Mar 2015 10:44:57 +1100 Subject: Cleanup: single quotes for enums --- release/scripts/startup/bl_operators/object.py | 2 +- release/scripts/startup/bl_ui/properties_data_mesh.py | 4 ++-- release/scripts/startup/bl_ui/properties_physics_smoke.py | 12 ++++++------ release/scripts/startup/bl_ui/space_clip.py | 4 ++-- release/scripts/startup/bl_ui/space_filebrowser.py | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index e3ceeca8abe..3d092e39c2b 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -924,7 +924,7 @@ class LodGenerate(Operator): lod.location.y = ob.location.y + 3.0 * i if i == 1: - modifier = lod.modifiers.new("lod_decimate", "DECIMATE") + modifier = lod.modifiers.new("lod_decimate", 'DECIMATE') else: modifier = lod.modifiers[-1] diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index 8efd14afb47..058f6283619 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -29,8 +29,8 @@ class MESH_MT_vertex_group_specials(Menu): def draw(self, context): layout = self.layout - layout.operator("object.vertex_group_sort", icon='SORTALPHA', text="Sort by Name").sort_type = "NAME" - layout.operator("object.vertex_group_sort", icon='ARMATURE_DATA', text="Sort by Bone Hierarchy").sort_type = "BONE_HIERARCHY" + layout.operator("object.vertex_group_sort", icon='SORTALPHA', text="Sort by Name").sort_type = 'NAME' + layout.operator("object.vertex_group_sort", icon='ARMATURE_DATA', text="Sort by Bone Hierarchy").sort_type = 'BONE_HIERARCHY' layout.operator("object.vertex_group_copy", icon='COPY_ID') layout.operator("object.vertex_group_copy_to_linked", icon='LINK_AREA') layout.operator("object.vertex_group_copy_to_selected", icon='LINK_AREA') diff --git a/release/scripts/startup/bl_ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py index 63268bc6672..85d3c1d7dc4 100644 --- a/release/scripts/startup/bl_ui/properties_physics_smoke.py +++ b/release/scripts/startup/bl_ui/properties_physics_smoke.py @@ -81,12 +81,12 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel): layout.prop(flow, "smoke_flow_type", expand=False) - if flow.smoke_flow_type != "OUTFLOW": + if flow.smoke_flow_type != 'OUTFLOW': split = layout.split() col = split.column() col.label(text="Flow Source:") col.prop(flow, "smoke_flow_source", expand=False, text="") - if flow.smoke_flow_source == "PARTICLES": + if flow.smoke_flow_source == 'PARTICLES': col.label(text="Particle System:") col.prop_search(flow, "particle_system", ob, "particle_systems", text="") col.prop(flow, "use_particle_size", text="Set Size") @@ -103,7 +103,7 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel): sub = sub.column() sub.active = flow.use_initial_velocity sub.prop(flow, "velocity_factor") - if flow.smoke_flow_source == "MESH": + if flow.smoke_flow_source == 'MESH': sub.prop(flow, "velocity_normal") #sub.prop(flow, "velocity_random") @@ -135,7 +135,7 @@ class PHYSICS_PT_smoke_flow_advanced(PhysicButtonsPanel, Panel): @classmethod def poll(cls, context): md = context.smoke - return md and (md.smoke_type == 'FLOW') and (md.flow_settings.smoke_flow_source == "MESH") + return md and (md.smoke_type == 'FLOW') and (md.flow_settings.smoke_flow_source == 'MESH') def draw(self, context): layout = self.layout @@ -151,9 +151,9 @@ class PHYSICS_PT_smoke_flow_advanced(PhysicButtonsPanel, Panel): sub.prop(flow, "noise_texture", text="") sub.label(text="Mapping:") sub.prop(flow, "texture_map_type", expand=False, text="") - if flow.texture_map_type == "UV": + if flow.texture_map_type == 'UV': sub.prop_search(flow, "uv_layer", ob.data, "uv_textures", text="") - if flow.texture_map_type == "AUTO": + if flow.texture_map_type == 'AUTO': sub.prop(flow, "texture_size") sub.prop(flow, "texture_offset") diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index a9fcdea35c7..a7a352f303b 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -1277,8 +1277,8 @@ class CLIP_MT_reconstruction(Menu): layout.operator("clip.set_plane", text="Set Floor").plane = 'FLOOR' layout.operator("clip.set_plane", text="Set Wall").plane = 'WALL' - layout.operator("clip.set_axis", text="Set X Axis").axis = "X" - layout.operator("clip.set_axis", text="Set Y Axis").axis = "Y" + layout.operator("clip.set_axis", text="Set X Axis").axis = 'X' + layout.operator("clip.set_axis", text="Set Y Axis").axis = 'Y' layout.operator("clip.set_scale") diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py index 841e169b080..cf7669e74a4 100644 --- a/release/scripts/startup/bl_ui/space_filebrowser.py +++ b/release/scripts/startup/bl_ui/space_filebrowser.py @@ -44,10 +44,10 @@ class FILEBROWSER_HT_header(Header): row.separator() row = layout.row(align=True) - layout.operator_context = "EXEC_DEFAULT" + layout.operator_context = 'EXEC_DEFAULT' row.operator("file.directory_new", icon='NEWFOLDER') - layout.operator_context = "INVOKE_DEFAULT" + layout.operator_context = 'INVOKE_DEFAULT' params = st.params # can be None when save/reload with a file selector open -- cgit v1.2.3 From dea0e3833f74bf60141b78821c4b3736b4cdc119 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 30 Mar 2015 10:42:40 +1100 Subject: Remove use_invert_vertex_group use_ prefix To match other modifiers. --- release/scripts/startup/bl_ui/properties_data_modifier.py | 2 +- source/blender/makesrna/intern/rna_modifier.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index ec60f1caec8..f22976f5b6d 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -1384,7 +1384,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): row.prop_search(md, "vertex_group", ob, "vertex_groups", text="") sub = row.row(align=True) sub.active = has_vgroup - sub.prop(md, "use_invert_vertex_group", text="", icon='ARROW_LEFTRIGHT') + sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT') if __name__ == "__main__": # only for live edit. diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 656c19e8108..bde8fd73d85 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -4418,7 +4418,7 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna) RNA_def_property_string_funcs(prop, NULL, NULL, "rna_NormalEditModifier_defgrp_name_set"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - prop = RNA_def_property(srna, "use_invert_vertex_group", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "invert_vertex_group", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_NORMALEDIT_INVERT_VGROUP); RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); -- cgit v1.2.3 From 8d1dc22becf22b96ff4095fe0243ec04a9bc61c5 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 30 Mar 2015 00:51:00 -0400 Subject: cleanup: typos in comments, style no functional changes --- source/blender/editors/space_view3d/drawobject.c | 170 ++++++++++++----------- 1 file changed, 86 insertions(+), 84 deletions(-) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 808408be694..1f30d25b0cc 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -598,10 +598,10 @@ void drawaxes(float size, char drawtype) } -/* Function to draw an Image on a empty Object */ +/* Function to draw an Image on an empty Object */ static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4]) { - Image *ima = (Image *)ob->data; + Image *ima = ob->data; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, ob->iuser, NULL); float scale, ofs_x, ofs_y, sca_x, sca_y; @@ -641,7 +641,7 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char sca_y = 1.0f; } - /* Calculate the scale center based on objects origin */ + /* Calculate the scale center based on object's origin */ ofs_x = ob->ima_ofs[0] * ima_x; ofs_y = ob->ima_ofs[1] * ima_y; @@ -944,7 +944,7 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo /* ******************** primitive drawing ******************* */ -/* draws a cube on given the scaling of the cube, assuming that +/* draws a cube given the scaling of the cube, assuming that * all required matrices have been set (used for drawing empties) */ static void drawcube_size(float size) @@ -1026,8 +1026,6 @@ static void drawshadbuflimits(Lamp *la, float mat[4][4]) glPointSize(1.0); } - - static void spotvolume(float lvec[3], float vvec[3], const float inp) { /* camera is at 0,0,0 */ @@ -1036,8 +1034,8 @@ static void spotvolume(float lvec[3], float vvec[3], const float inp) normalize_v3(lvec); normalize_v3(vvec); /* is this the correct vector ? */ - cross_v3_v3v3(temp, vvec, lvec); /* equation for a plane through vvec en lvec */ - cross_v3_v3v3(plane, lvec, temp); /* a plane perpendicular to this, parrallel with lvec */ + cross_v3_v3v3(temp, vvec, lvec); /* equation for a plane through vvec and lvec */ + cross_v3_v3v3(plane, lvec, temp); /* a plane perpendicular to this, parallel with lvec */ /* vectors are exactly aligned, use the X axis, this is arbitrary */ if (normalize_v3(plane) == 0.0f) @@ -1162,7 +1160,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, unsigned char curcol[4]; unsigned char col[4]; - /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */ + /* cone can't be drawn for duplicated lamps, because duplilist would be freed */ /* the moment of view3d_draw_transp() call */ const bool is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object); const bool drawcone = ((dt > OB_WIRE) && @@ -1311,7 +1309,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, x *= y; /* draw the circle/square at the end of the cone */ - glTranslatef(0.0, 0.0, x); + glTranslatef(0.0, 0.0, x); if (la->mode & LA_SQUARE) { float tvec[3]; float z_abs = fabsf(z); @@ -1500,10 +1498,10 @@ static void draw_limit_line(float sta, float end, const short dflag, unsigned in static void draw_focus_cross(float dist, float size) { glBegin(GL_LINES); - glVertex3f(-size, 0.f, -dist); - glVertex3f(size, 0.f, -dist); - glVertex3f(0.f, -size, -dist); - glVertex3f(0.f, size, -dist); + glVertex3f(-size, 0.0f, -dist); + glVertex3f(size, 0.0f, -dist); + glVertex3f(0.0f, -size, -dist); + glVertex3f(0.0f, size, -dist); glEnd(); } @@ -1556,8 +1554,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D BKE_tracking_get_camera_object_matrix(scene, base->object, mat); /* we're compensating camera size for bundles size, - * to make it so bundles are always displayed with the same size - */ + * to make it so bundles are always displayed with the same size */ copy_v3_v3(camera_size, base->object->size); if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) mul_v3_fl(camera_size, tracking_object->scale); @@ -1991,9 +1988,9 @@ static void ensure_curve_cache(Scene *scene, Object *object) * here, we also need to check whether display list is * empty or not. * - * The trick below tries to optimie calls to displist + * The trick below tries to optimize calls to displist * creation for cases curve is empty. Meaning, if the curve - * is empty (without splies) bevel list would also be empty. + * is empty (without splines) bevel list would also be empty. * And the thing is, render thread always leaves bevel list * in a proper state. So if bevel list is here and display * list is not we need to make display list. @@ -2271,8 +2268,7 @@ static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3], BMVert *eve = BM_vert_at_index(data->bm, index); if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) { - /* skin nodes: draw a red circle around the root - * node(s) */ + /* skin nodes: draw a red circle around the root node(s) */ if (data->cd_vskin_offset != -1) { const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset); if (vs->flag & MVERT_SKIN_ROOT) { @@ -2355,7 +2351,7 @@ static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index) else { col = data->baseCol; } - /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */ + /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */ if (col[3] == 0) return DM_DRAW_OPTION_SKIP; @@ -3045,7 +3041,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe } BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { - /* draw selected edges, or edges next to selected verts while draging */ + /* draw selected edges, or edges next to selected verts while dragging */ if (BM_elem_flag_test(eed, BM_ELEM_SELECT) || (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)))) @@ -3107,12 +3103,12 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { BMLoop *l_a, *l_b; if (BM_edge_loop_pair(eed, &l_a, &l_b)) { - /* draw selected edges, or edges next to selected verts while draging */ + /* draw selected edges, or edges next to selected verts while dragging */ if (BM_elem_flag_test(eed, BM_ELEM_SELECT) || (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || BM_elem_flag_test(eed->v2, BM_ELEM_SELECT) || - /* special case, this is useful to show when vertes connected to this edge via a - * face are being transformed */ + /* special case, this is useful to show when verts connected to + * this edge via a face are being transformed */ BM_elem_flag_test(l_a->next->next->v, BM_ELEM_SELECT) || BM_elem_flag_test(l_a->prev->v, BM_ELEM_SELECT) || BM_elem_flag_test(l_b->next->next->v, BM_ELEM_SELECT) || @@ -3418,7 +3414,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, if (em->bm->selected.last) { BMEditSelection *ese = em->bm->selected.last; - /* face is handeled above */ + /* face is handled above */ #if 0 if (ese->type == BM_FACE) { efa_act = (BMFace *)ese->data; @@ -3533,11 +3529,14 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, } else if (efa_act) { /* even if draw faces is off it would be nice to draw the stipple face - * Make all other faces zero alpha except for the active - * */ - /* col4 is only used by WITH_FREESTYLE, but keeping it here spares some #ifdef's... */ - unsigned char col1[4], col2[4], col3[4], col4[4]; - col1[3] = col2[3] = col4[3] = 0; /* don't draw */ + * Make all other faces zero alpha except for the active */ + unsigned char col1[4], col2[4], col3[4]; +#ifdef WITH_FREESTYLE + unsigned char col4[4]; + col4[3] = 0; /* don't draw */ +#endif + col1[3] = col2[3] = 0; /* don't draw */ + UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3); glEnable(GL_BLEND); @@ -3551,7 +3550,6 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, glDisable(GL_BLEND); glDepthMask(1); /* restore write in zbuffer */ - } /* here starts all fancy draw-extra over */ @@ -3734,7 +3732,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D glPointSize(1.0); } else if (dt == OB_WIRE || totface == 0) { - draw_wire = OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff */ + draw_wire = OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff */ } else if (((is_obact && ob->mode & OB_MODE_TEXTURE_PAINT)) || check_object_draw_texture(scene, v3d, dt)) @@ -3776,8 +3774,10 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D else dm->drawFacesGLSL(dm, GPU_enable_material); -// if (BKE_bproperty_object_get(ob, "Text")) -// XXX draw_mesh_text(ob, 1); +#if 0 /* XXX */ + if (BKE_bproperty_object_get(ob, "Text")) + draw_mesh_text(ob, 1); +#endif GPU_disable_material(); glFrontFace(GL_CCW); @@ -3895,7 +3895,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } if ((draw_wire != OBDRAW_WIRE_OFF) && /* draw extra wire */ - /* when overriding with render only, don't bother */ + /* when overriding with render only, don't bother */ (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_SOLID) == 0)) { /* When using wireframe object draw in particle edit mode @@ -3949,7 +3949,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D dm->release(dm); } -/* returns 1 if nothing was drawn, for detecting to draw an object center */ +/* returns true if nothing was drawn, for detecting to draw an object center */ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt, const unsigned char ob_wire_col[4], const short dflag) { @@ -4329,7 +4329,7 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, /** * Only called by #drawDispList - * \return 1 when nothing was drawn + * \return true when nothing was drawn */ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) @@ -4601,7 +4601,7 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix copy_v3_v3(pdd->vd, vec2); pdd->vd += 3; vec[2] = 2.0f * pixsize; - vec[0] = vec[1] = 0.0; + vec[0] = vec[1] = 0.0f; mul_qt_v3(state->rot, vec); if (draw_as == PART_DRAW_AXIS) { copy_v3_v3(vec2, state->co); @@ -4684,7 +4684,7 @@ static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d, if (psys->parent) mul_m4_v3(psys->parent->obmat, state->co); - /* create actiual particle data */ + /* create actual particle data */ if (draw_as == PART_DRAW_BB) { bb->offset[0] = part->bb_offset[0]; bb->offset[1] = part->bb_offset[1]; @@ -4709,16 +4709,17 @@ static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d, draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd); } -/* unified drawing of all new particle systems draw types except dupli ob & group */ -/* mostly tries to use vertex arrays for speed */ - -/* 1. check that everything is ok & updated */ -/* 2. start initializing things */ -/* 3. initialize according to draw type */ -/* 4. allocate drawing data arrays */ -/* 5. start filling the arrays */ -/* 6. draw the arrays */ -/* 7. clean up */ +/* unified drawing of all new particle systems draw types except dupli ob & group + * mostly tries to use vertex arrays for speed + * + * 1. check that everything is ok & updated + * 2. start initializing things + * 3. initialize according to draw type + * 4. allocate drawing data arrays + * 5. start filling the arrays + * 6. draw the arrays + * 7. clean up + */ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, ParticleSystem *psys, const char ob_dt, const short dflag) @@ -4914,7 +4915,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv int create_ndata = 0; if (!pdd) - pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticlDrawData"); + pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticleDrawData"); if (part->draw_as == PART_DRAW_REND && part->trail_count > 1) { tot_vec_size *= part->trail_count; @@ -5076,8 +5077,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv } if (drawn) { - /* additional things to draw for each particle */ - /* (velocity, size and number) */ + /* additional things to draw for each particle + * (velocity, size and number) */ if ((part->draw & PART_DRAW_VEL) && pdd && pdd->vedata) { copy_v3_v3(pdd->ved, state.co); pdd->ved += 3; @@ -5118,8 +5119,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv } if (numstr[0]) { - /* in path drawing state.co is the end point */ - /* use worldspace beause object matrix is already applied */ + /* in path drawing state.co is the end point + * use worldspace because object matrix is already applied */ mul_v3_m4v3(vec_txt, ob->imat, state.co); view3d_cached_text_draw_add(vec_txt, numstr, numstr_len, 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol); @@ -5200,11 +5201,13 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv HairKey *hkey = pa->hair; glVertexPointer(3, GL_FLOAT, sizeof(HairKey), hkey->world_co); - - // XXX use proper theme color here -// UI_ThemeColor(TH_NORMAL); + +#if 0 /* XXX use proper theme color here */ + UI_ThemeColor(TH_NORMAL); +#else glColor3f(0.58f, 0.67f, 1.0f); - +#endif + glDrawArrays(GL_LINE_STRIP, 0, pa->totkey); } } @@ -5353,7 +5356,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { float vec_txt[3]; numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%i", a); - /* use worldspace beause object matrix is already applied */ + /* use worldspace because object matrix is already applied */ mul_v3_m4v3(vec_txt, ob->imat, cache[a]->co); view3d_cached_text_draw_add(vec_txt, numstr, numstr_len, 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol); @@ -5637,7 +5640,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) glShadeModel(GL_FLAT); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); glLineWidth(1.0f); - glPointSize(1.0); + glPointSize(1.0f); } //static void ob_draw_RE_motion(float com[3],float rotscale[3][3],float tw,float th) static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, float ith, float drw_size) @@ -6043,7 +6046,7 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) Nurb *nu; BPoint *bp, *bp1; int a, b, ofs, index; - Curve *cu = (Curve *)ob->data; + Curve *cu = ob->data; index = 0; nu = nurb; @@ -6403,7 +6406,7 @@ static void draw_empty_sphere(float size) static GLuint displist = 0; if (displist == 0) { - GLUquadricObj *qobj; + GLUquadricObj *qobj; displist = glGenLists(1); glNewList(displist, GL_COMPILE); @@ -6439,7 +6442,6 @@ static void draw_empty_cone(float size) GLUquadricObj *qobj = gluNewQuadric(); gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - glPushMatrix(); radius = size; @@ -6456,7 +6458,7 @@ static void draw_empty_cone(float size) static void drawspiral(const float cent[3], float rad, float tmat[4][4], int start) { float vec[3], vx[3], vy[3]; - const float tot_inv = (1.0f / (float)CIRCLE_RESOL); + const float tot_inv = 1.0f / (float)CIRCLE_RESOL; int a; bool inverse = false; float x, y, fac; @@ -6520,8 +6522,7 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta } /* draws a circle on x-z plane given the scaling of the circle, assuming that - * all required matrices have been set (used for drawing empties) - */ + * all required matrices have been set (used for drawing empties) */ static void drawcircle_size(float size) { float x, y; @@ -6529,7 +6530,7 @@ static void drawcircle_size(float size) glBegin(GL_LINE_LOOP); - /* coordinates are: cos(degrees * 11.25) = x, sin(degrees*11.25) = y, 0.0f = z */ + /* coordinates are: cos(degrees * 11.25) = x, sin(degrees * 11.25) = y, 0.0f = z */ for (degrees = 0; degrees < CIRCLE_RESOL; degrees++) { x = cosval[degrees]; y = sinval[degrees]; @@ -6681,8 +6682,10 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, /* calculus here, is reused in PFIELD_FORCE */ invert_m4_m4(imat, rv3d->viewmatob); -// normalize_v3(imat[0]); /* we don't do this because field doesnt scale either... apart from wind! */ -// normalize_v3(imat[1]); +#if 0 + normalize_v3(imat[0]); /* we don't do this because field doesnt scale either... apart from wind! */ + normalize_v3(imat[1]); +#endif if (pd->forcefield == PFIELD_WIND) { float force_val; @@ -7185,7 +7188,7 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_ else { if (ob->flag & OB_FROMGROUP) { if (base->flag & (SELECT + BA_WAS_SEL)) { - /* uses darker active color for non-active + selected*/ + /* uses darker active color for non-active + selected */ theme_id = TH_GROUP_ACTIVE; if (scene->basact != base) { @@ -7445,10 +7448,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (dt >= OB_BOUNDBOX) { dtx = ob->dtx; if (ob->mode & OB_MODE_EDIT) { - // the only 2 extra drawtypes alowed in editmode + /* the only 2 extra drawtypes alowed in editmode */ dtx = dtx & (OB_DRAWWIRE | OB_TEXSPACE); } - } if (!particle_skip_object) { @@ -7506,9 +7508,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) { empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); - -//XXX old animsys if (cu->path) -// curve_draw_speed(scene, ob); +#if 0 /* XXX old animsys */ + if (cu->path) + curve_draw_speed(scene, ob); +#endif } break; case OB_MBALL: @@ -7676,7 +7679,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((md = modifiers_findByType(ob, eModifierType_Smoke)) && (modifier_isEnabled(scene, md, eModifierMode_Realtime))) { SmokeModifierData *smd = (SmokeModifierData *)md; - // draw collision objects + /* draw collision objects */ if ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll) { #if 0 SmokeCollSettings *scs = smd->coll; @@ -7705,7 +7708,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short glDisable(GL_BLEND); glDepthMask(GL_TRUE); if (col) cpack(col); - } #endif } @@ -7727,8 +7729,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short BKE_boundbox_init_from_minmax(&bb, p0, p1); draw_box(bb.vec); - /* draw base resolution bounds */ #if 0 + /* draw base resolution bounds */ BKE_boundbox_init_from_minmax(&bb, sds->p0, sds->p1); draw_box(bb.vec); #endif @@ -7737,15 +7739,15 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* don't show smoke before simulation starts, this could be made an option in the future */ if (smd->domain->fluid && CFRA >= smd->domain->point_cache[0]->startframe) { - // get view vector + /* get view vector */ copy_v3_v3(viewnormal, rv3d->viewinv[2]); invert_m4_m4(ob->imat, ob->obmat); mul_mat3_m4_v3(ob->imat, viewnormal); normalize_v3(viewnormal); /* set dynamic boundaries to draw the volume - * also scale cube to global space to equalize volume slicing on all axises - * (its scaled back before drawing) */ + * also scale cube to global space to equalize volume slicing on all axes + * (it's scaled back before drawing) */ p0[0] = (sds->p0[0] + sds->cell_size[0] * sds->res_min[0] + sds->obj_shift_f[0]) * fabsf(ob->size[0]); p0[1] = (sds->p0[1] + sds->cell_size[1] * sds->res_min[1] + sds->obj_shift_f[1]) * fabsf(ob->size[1]); p0[2] = (sds->p0[2] + sds->cell_size[2] * sds->res_min[2] + sds->obj_shift_f[2]) * fabsf(ob->size[2]); @@ -7945,7 +7947,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_OBJECTSOLVER)) { /* special case for object solver and follow track constraints because they don't fill * constraint targets properly (design limitation -- scene is needed for their target - * but it can't be accessed from get_targets callvack) */ + * but it can't be accessed from get_targets callback) */ Object *camob = NULL; @@ -8202,7 +8204,7 @@ static void bbs_mesh_solid_verts(Scene *scene, Object *ob) static void bbs_mesh_solid_faces(Scene *scene, Object *ob) { DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask); - Mesh *me = (Mesh *)ob->data; + Mesh *me = ob->data; glColor3ub(0, 0, 0); -- cgit v1.2.3 From e47a96463dad63e9d225a23fac1924cca00ed6ca Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 30 Mar 2015 01:25:34 -0400 Subject: cleanup: remove unused code & vars --- source/blender/editors/space_view3d/drawobject.c | 70 +++++------------------- 1 file changed, 14 insertions(+), 56 deletions(-) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 1f30d25b0cc..d11e1045d7f 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -1876,8 +1876,6 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d), Object *UNUSED(ob), int UNUSED(flag)) { - //Speaker *spk = ob->data; - float vec[3]; int i, j; @@ -2334,7 +2332,6 @@ static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVer static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index) { BMEdge *eed; - //unsigned char **cols = userData, *col; drawDMEdgesSel_userData *data = userData; unsigned char *col; @@ -3098,8 +3095,6 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); } - // invert_m4_m4(ob->imat, ob->obmat); // this is already called - BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { BMLoop *l_a, *l_b; if (BM_edge_loop_pair(eed, &l_a, &l_b)) { @@ -3713,7 +3708,6 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D draw_wire = OBDRAW_WIRE_ON_DEPTH; /* draw wire after solid using zoffset and depth buffer adjusment */ } - /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/ totedge = dm->getNumEdges(dm); totface = dm->getNumTessFaces(dm); @@ -5137,7 +5131,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if (draw_as == PART_DRAW_PATH) { ParticleCacheKey **cache, *path; - float /* *cd2=NULL, */ /* UNUSED */ *cdata2 = NULL; + float *cdata2 = NULL; /* setup gl flags */ if (1) { //ob_dt > OB_WIRE) { @@ -5336,7 +5330,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1); } - /* restore & clean up */ if (1) { //ob_dt > OB_WIRE) { if (part->draw_col == PART_DRAW_COL_MAT) @@ -5344,9 +5337,10 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glDisable(GL_COLOR_MATERIAL); } - if (cdata2) + if (cdata2) { MEM_freeN(cdata2); - /* cd2 = */ /* UNUSED */ cdata2 = NULL; + cdata2 = NULL; + } glLineWidth(1.0f); @@ -5642,7 +5636,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) glLineWidth(1.0f); glPointSize(1.0f); } -//static void ob_draw_RE_motion(float com[3],float rotscale[3][3],float tw,float th) + static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, float ith, float drw_size) { float tr[3][3]; @@ -6688,19 +6682,12 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, #endif if (pd->forcefield == PFIELD_WIND) { - float force_val; + float force_val = pd->f_strength; if ((dflag & DRAW_CONSTCOLOR) == 0) { ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); } - //if (has_ipo_code(ob->ipo, OB_PD_FSTR)) - // force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra); - //else - { - force_val = pd->f_strength; - } - unit_m4(tmat); force_val *= 0.1f; drawcircball(GL_LINE_LOOP, vec, size, tmat); @@ -6714,14 +6701,7 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, } else if (pd->forcefield == PFIELD_FORCE) { - float ffall_val; - - //if (has_ipo_code(ob->ipo, OB_PD_FFALL)) - // ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, scene->r.cfra); - //else - { - ffall_val = pd->f_power; - } + float ffall_val = pd->f_power; if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); drawcircball(GL_LINE_LOOP, vec, size, imat); @@ -6731,20 +6711,9 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, drawcircball(GL_LINE_LOOP, vec, size * 2.0f, imat); } else if (pd->forcefield == PFIELD_VORTEX) { - float /*ffall_val,*/ force_val; + float force_val = pd->f_strength; unit_m4(tmat); - //if (has_ipo_code(ob->ipo, OB_PD_FFALL)) - // ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, scene->r.cfra); - //else - // ffall_val = pd->f_power; - - //if (has_ipo_code(ob->ipo, OB_PD_FSTR)) - // force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra); - //else - { - force_val = pd->f_strength; - } if ((dflag & DRAW_CONSTCOLOR) == 0) { ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.7f); @@ -6762,25 +6731,19 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, else if (pd->forcefield == PFIELD_GUIDE && ob->type == OB_CURVE) { Curve *cu = ob->data; if ((cu->flag & CU_PATH) && ob->curve_cache->path && ob->curve_cache->path->data) { - float mindist, guidevec1[4], guidevec2[3]; - - //if (has_ipo_code(ob->ipo, OB_PD_FSTR)) - // mindist = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra); - //else - { - mindist = pd->f_strength; - } + float guidevec1[4], guidevec2[3]; + float mindist = pd->f_strength; if ((dflag & DRAW_CONSTCOLOR) == 0) { ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); } - /*path end*/ + /* path end */ setlinestyle(3); where_on_path(ob, 1.0f, guidevec1, guidevec2, NULL, NULL, NULL); drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat); - /*path beginning*/ + /* path beginning */ setlinestyle(0); where_on_path(ob, 0.0f, guidevec1, guidevec2, NULL, NULL, NULL); drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat); @@ -7508,10 +7471,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) { empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); -#if 0 /* XXX old animsys */ - if (cu->path) - curve_draw_speed(scene, ob); -#endif } break; case OB_MBALL: @@ -7679,9 +7638,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((md = modifiers_findByType(ob, eModifierType_Smoke)) && (modifier_isEnabled(scene, md, eModifierMode_Realtime))) { SmokeModifierData *smd = (SmokeModifierData *)md; +#if 0 /* draw collision objects */ if ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll) { -#if 0 SmokeCollSettings *scs = smd->coll; if (scs->points) { size_t i; @@ -7709,8 +7668,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short glDepthMask(GL_TRUE); if (col) cpack(col); } -#endif } +#endif /* only draw domains */ if (smd->domain) { @@ -7831,7 +7790,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short view3d_cached_text_draw_add(zero, ob->id.name + 2, strlen(ob->id.name + 2), 10, 0, ob_wire_col); } } - /*if (dtx & OB_DRAWIMAGE) drawDispListwire(&ob->disp);*/ if ((dtx & OB_DRAWWIRE) && dt >= OB_SOLID) { if ((dflag & DRAW_CONSTCOLOR) == 0) { draw_wire_extra(scene, rv3d, ob, ob_wire_col); -- cgit v1.2.3 From 786763ca4c10be726bc8293fd3bb93d7d019dbc6 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 30 Mar 2015 02:53:39 -0400 Subject: remove zero translations within draw_emtpy_* These are no-ops. Also const-ified some variables there. --- source/blender/editors/space_view3d/drawobject.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index d11e1045d7f..628fd23e0d5 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -648,9 +648,6 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char glMatrixMode(GL_MODELVIEW); glPushMatrix(); - /* Make sure we are drawing at the origin */ - glTranslatef(0.0f, 0.0f, 0.0f); - /* Calculate Image scale */ scale = (ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y)); @@ -6431,15 +6428,13 @@ static void draw_empty_sphere(float size) /* draw a cone for use as an empty drawtype */ static void draw_empty_cone(float size) { - float cent = 0; - float radius; + const float radius = size; + GLUquadricObj *qobj = gluNewQuadric(); gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); glPushMatrix(); - radius = size; - glTranslatef(cent, cent, cent); glScalef(radius, size * 2.0f, radius); glRotatef(-90.0, 1.0, 0.0, 0.0); gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1); @@ -6668,11 +6663,8 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, PartDeflect *pd = ob->pd; float imat[4][4], tmat[4][4]; float vec[3] = {0.0, 0.0, 0.0}; - float size; - /* scale size of circle etc with the empty drawsize */ - if (ob->type == OB_EMPTY) size = ob->empty_drawsize; - else size = 1.0; + const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f; /* calculus here, is reused in PFIELD_FORCE */ invert_m4_m4(imat, rv3d->viewmatob); -- cgit v1.2.3 From 23c0e46a003c491bbcafc8c42eace83fc95f3974 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 30 Mar 2015 13:05:14 +0500 Subject: Buildbot: Use Clang with OpenMP support for 64bit OSX builds This should make such areas as simulations and sculpting nicely threaded. 32bit will be tried to be supported later. --- build_files/buildbot/config/user-config-mac-x86_64.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build_files/buildbot/config/user-config-mac-x86_64.py b/build_files/buildbot/config/user-config-mac-x86_64.py index ac923f48abe..6a13c80f6ce 100644 --- a/build_files/buildbot/config/user-config-mac-x86_64.py +++ b/build_files/buildbot/config/user-config-mac-x86_64.py @@ -1,5 +1,6 @@ +CC = "../lib/darwin-9.x.universal/clang-omp-3.5/bin/clang" +CXX = "../lib/darwin-9.x.universal/clang-omp-3.5/bin/clang++" MACOSX_ARCHITECTURE = 'x86_64' # valid archs: ppc, i386, ppc64, x86_64 WITH_BF_CYCLES_CUDA_BINARIES = True - -- cgit v1.2.3 From 59740a6c985efbf5369d27a5919e184036d0287a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 30 Mar 2015 13:11:08 +0500 Subject: SCons: cudakernels now depends on some configuration tests --- SConstruct | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/SConstruct b/SConstruct index 52fef2f3b87..7cdc4b35206 100644 --- a/SConstruct +++ b/SConstruct @@ -871,19 +871,21 @@ B.init_lib_dict() ##### END SETUP ########## -if B.targets != ['cudakernels']: - # Put all auto configuration run-time tests here - - from FindSharedPtr import FindSharedPtr - from FindUnorderedMap import FindUnorderedMap - - conf = Configure(env) - old_linkflags = conf.env['LINKFLAGS'] - conf.env.Append(LINKFLAGS=env['PLATFORM_LINKFLAGS']) - FindSharedPtr(conf) - FindUnorderedMap(conf) - conf.env['LINKFLAGS'] = old_linkflags - env = conf.Finish() +## Auto-configuration run-time tests + +from FindSharedPtr import FindSharedPtr +from FindUnorderedMap import FindUnorderedMap + +conf = Configure(env) +old_linkflags = conf.env['LINKFLAGS'] +conf.env.Append(LINKFLAGS=env['PLATFORM_LINKFLAGS']) + +# Put all tests here +FindSharedPtr(conf) +FindUnorderedMap(conf) + +conf.env['LINKFLAGS'] = old_linkflags +env = conf.Finish() # End of auto configuration -- cgit v1.2.3 From 1b327aa2195ff4c4d3f87b303a767cfaea648047 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 30 Mar 2015 10:22:12 +0200 Subject: Fix T44186: Bezier Bevel facto mapping broken when 'start' was set to 'Resolution' and 'end' was not. Trivial, we need totla_length in that case too. Safe to be backported to 2.74. --- source/blender/blenkernel/intern/displist.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index e5e751561ec..9004b5528ca 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -1435,9 +1435,8 @@ static void calc_bevfac_mapping(Curve *cu, BevList *bl, Nurb *nu, return; } - if (ELEM(cu->bevfac1_mapping, - CU_BEVFAC_MAP_SEGMENT, - CU_BEVFAC_MAP_SPLINE)) + if (ELEM(cu->bevfac1_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE) || + ELEM(cu->bevfac2_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE)) { for (i = 0; i < SEGMENTSU(nu); i++) { total_length += bl->seglen[i]; -- cgit v1.2.3 From afbc45ed93c22afcffd4f3aa2078a4e324263045 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 30 Mar 2015 13:55:45 +0500 Subject: Cycles: Attempt to fix osl+scons compilation Defines (and other cflags) are not inherited by scons to the subdirectories, need to take care of them in all nested SConscripts. --- intern/cycles/kernel/osl/SConscript | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/intern/cycles/kernel/osl/SConscript b/intern/cycles/kernel/osl/SConscript index 58b0204a1b9..74ba5e1020c 100644 --- a/intern/cycles/kernel/osl/SConscript +++ b/intern/cycles/kernel/osl/SConscript @@ -44,6 +44,18 @@ defs.append('CCL_NAMESPACE_BEGIN=namespace ccl {') defs.append('CCL_NAMESPACE_END=}') defs.append('WITH_OSL') +if env['WITH_UNORDERED_MAP_SUPPORT']: + if env['UNORDERED_MAP_HEADER'] == 'unordered_map': + if env['UNORDERED_MAP_NAMESPACE'] == 'std': + defs.append('CYCLES_STD_UNORDERED_MAP') + elif env['UNORDERED_MAP_NAMESPACE'] == 'std::tr1': + defs.append('CYCLES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE') + elif env['UNORDERED_MAP_NAMESPACE'] == 'std::tr1': + defs.append('CYCLES_TR1_UNORDERED_MAP') +else: + print("-- Replacing unordered_map/set with map/set (warning: slower!)") + defs.append('CYCLES_NO_UNORDERED_MAP') + if env['WITH_BF_CYCLES_DEBUG']: defs.append('WITH_CYCLES_DEBUG') -- cgit v1.2.3 From 09397ac2c16efd073090f3c553568f4315273fa4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 30 Mar 2015 20:49:13 +1100 Subject: Fix for invalid buffer access on zero-face meshes --- source/blender/blenkernel/intern/cdderivedmesh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 6b7855b7759..1c2c6eb194b 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -786,7 +786,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, if (tottri == 0) { /* avoid buffer problems in following code */ } - if (setDrawOptions == NULL) { + else if (setDrawOptions == NULL) { /* just draw the entire face array */ glDrawArrays(GL_TRIANGLES, 0, (tottri) * 3); } -- cgit v1.2.3 From 131912dc73ddb828a9e393845e12f6d1c4f5d76b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 30 Mar 2015 15:06:20 +0500 Subject: Cycles: Fix compilation error with MSVC after recent C++11 changes --- intern/cycles/blender/blender_session.cpp | 4 ++-- intern/cycles/util/util_function.h | 6 ++++++ intern/cycles/util/util_progress.h | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index ee6ec7ac2c1..4f428bbea57 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -487,8 +487,8 @@ void BlenderSession::render() } /* clear callback */ - session->write_render_tile_cb = NULL; - session->update_render_tile_cb = NULL; + session->write_render_tile_cb = function_null; + session->update_render_tile_cb = function_null; /* free all memory used (host and device), so we wouldn't leave render * engine with extra memory allocated diff --git a/intern/cycles/util/util_function.h b/intern/cycles/util/util_function.h index 83c07ae06a8..33e15939712 100644 --- a/intern/cycles/util/util_function.h +++ b/intern/cycles/util/util_function.h @@ -28,6 +28,11 @@ CCL_NAMESPACE_BEGIN #if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800) # define function_bind std::bind +# ifdef _MSC_VER +# define function_null nullptr +# else +# define function_null NULL +#endif using std::function; using std::placeholders::_1; using std::placeholders::_2; @@ -41,6 +46,7 @@ using std::placeholders::_9; #else using boost::function; # define function_bind boost::bind +# define function_null NULL #endif CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h index 963987487ed..13fce655734 100644 --- a/intern/cycles/util/util_progress.h +++ b/intern/cycles/util/util_progress.h @@ -44,12 +44,12 @@ public: substatus = ""; sync_status = ""; sync_substatus = ""; - update_cb = NULL; + update_cb = function_null; cancel = false; cancel_message = ""; error = false; error_message = ""; - cancel_cb = NULL; + cancel_cb = function_null; } Progress(Progress& progress) -- cgit v1.2.3 From b663f1f1cf203337f165146d22814a4926499b23 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 30 Mar 2015 15:17:09 +0500 Subject: Cycles: Correction to previous commit: non-msvc compilers also should use nullptr --- intern/cycles/util/util_function.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/intern/cycles/util/util_function.h b/intern/cycles/util/util_function.h index 33e15939712..6d0f0b444a9 100644 --- a/intern/cycles/util/util_function.h +++ b/intern/cycles/util/util_function.h @@ -28,11 +28,7 @@ CCL_NAMESPACE_BEGIN #if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800) # define function_bind std::bind -# ifdef _MSC_VER -# define function_null nullptr -# else -# define function_null NULL -#endif +# define function_null nullptr using std::function; using std::placeholders::_1; using std::placeholders::_2; -- cgit v1.2.3 From 268524c0257fe313c3c25b4c3e93913690435bea Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 30 Mar 2015 21:17:07 +1100 Subject: Cleanup: use const for typeinfo --- source/blender/blenkernel/BKE_constraint.h | 4 +- source/blender/blenkernel/BKE_fcurve.h | 4 +- source/blender/blenkernel/BKE_modifier.h | 2 +- source/blender/blenkernel/BKE_sequencer.h | 2 +- source/blender/blenkernel/intern/DerivedMesh.c | 10 ++--- source/blender/blenkernel/intern/armature.c | 2 +- source/blender/blenkernel/intern/constraint.c | 18 ++++---- source/blender/blenkernel/intern/crazyspace.c | 8 ++-- source/blender/blenkernel/intern/depsgraph.c | 12 +++--- source/blender/blenkernel/intern/displist.c | 8 ++-- source/blender/blenkernel/intern/dynamicpaint.c | 2 +- source/blender/blenkernel/intern/fcurve.c | 6 +-- source/blender/blenkernel/intern/fmodifier.c | 20 ++++----- source/blender/blenkernel/intern/lattice.c | 2 +- source/blender/blenkernel/intern/modifier.c | 48 +++++++++++----------- source/blender/blenkernel/intern/multires.c | 4 +- source/blender/blenkernel/intern/object.c | 12 +++--- source/blender/blenkernel/intern/paint.c | 2 +- source/blender/blenkernel/intern/seqmodifier.c | 12 +++--- source/blender/blenkernel/intern/smoke.c | 2 +- source/blender/blenloader/intern/writefile.c | 8 ++-- source/blender/collada/AnimationExporter.cpp | 6 +-- source/blender/editors/animation/fmodifier_ui.c | 4 +- source/blender/editors/armature/armature_add.c | 2 +- source/blender/editors/armature/armature_edit.c | 2 +- source/blender/editors/armature/armature_naming.c | 2 +- .../blender/editors/armature/armature_relations.c | 6 +-- .../editors/armature/editarmature_retarget.c | 4 +- source/blender/editors/armature/pose_select.c | 2 +- .../editors/interface/interface_templates.c | 4 +- source/blender/editors/object/object_constraint.c | 4 +- source/blender/editors/object/object_modifier.c | 16 ++++---- source/blender/editors/sculpt_paint/sculpt.c | 2 +- source/blender/editors/space_clip/tracking_ops.c | 4 +- source/blender/editors/space_graph/graph_edit.c | 2 +- source/blender/editors/space_nla/nla_edit.c | 2 +- source/blender/editors/space_view3d/drawobject.c | 2 +- source/blender/editors/transform/transform.c | 10 ++--- source/blender/makesrna/intern/rna_constraint.c | 2 +- source/blender/makesrna/intern/rna_fcurve.c | 2 +- 40 files changed, 133 insertions(+), 133 deletions(-) diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index 1346feec82c..f3cfb901154 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -108,8 +108,8 @@ typedef struct bConstraintTypeInfo { } bConstraintTypeInfo; /* Function Prototypes for bConstraintTypeInfo's */ -bConstraintTypeInfo *BKE_constraint_typeinfo_get(struct bConstraint *con); -bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type); +const bConstraintTypeInfo *BKE_constraint_typeinfo_get(struct bConstraint *con); +const bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type); /* ---------------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 275ab3f1ebb..443a03a475a 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -172,8 +172,8 @@ typedef enum eFMI_Requirement_Flags { } eFMI_Requirement_Flags; /* Function Prototypes for FModifierTypeInfo's */ -FModifierTypeInfo *fmodifier_get_typeinfo(struct FModifier *fcm); -FModifierTypeInfo *get_fmodifier_typeinfo(int type); +const FModifierTypeInfo *fmodifier_get_typeinfo(struct FModifier *fcm); +const FModifierTypeInfo *get_fmodifier_typeinfo(int type); /* ---------------------- */ diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index e9223590e9d..9c5261c1583 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -312,7 +312,7 @@ typedef struct ModifierTypeInfo { /* Initialize modifier's global data (type info and some common global storages). */ void BKE_modifier_init(void); -ModifierTypeInfo *modifierType_getInfo(ModifierType type); +const ModifierTypeInfo *modifierType_getInfo(ModifierType type); /* Modifier utility calls, do call through type pointer and return * default values if pointer is optional. diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index a39336bd198..84818276e7b 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -433,7 +433,7 @@ typedef struct SequenceModifierTypeInfo { void (*apply) (struct SequenceModifierData *smd, struct ImBuf *ibuf, struct ImBuf *mask); } SequenceModifierTypeInfo; -struct SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type); +const struct SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type); struct SequenceModifierData *BKE_sequence_modifier_new(struct Sequence *seq, const char *name, int type); bool BKE_sequence_modifier_remove(struct Sequence *seq, struct SequenceModifierData *smd); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index bfb5098c5ae..87a00c20d46 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -931,7 +931,7 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, ModifierData *md, int build_shapekey_layers) { Mesh *me = ob->data; - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); DerivedMesh *dm; KeyBlock *kb; @@ -1585,7 +1585,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos /* Apply all leading deforming modifiers */ for (; md; md = md->next, curr = curr->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); md->scene = scene; @@ -1639,7 +1639,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos clothorcodm = NULL; for (; md; md = md->next, curr = curr->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); md->scene = scene; @@ -2000,7 +2000,7 @@ float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *r_numVerts))[3] bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; if (!modifier_isEnabled(scene, md, required_mode)) return 0; @@ -2059,7 +2059,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D curr = datamasks; for (i = 0; md; i++, md = md->next, curr = curr->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); md->scene = scene; diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 6b67a4e5763..f775b67eedb 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1700,7 +1700,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected /* constraints - set target ob pointer to own object */ for (con = pchanw.constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index c38a1239f12..fa8ab14de06 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4318,7 +4318,7 @@ static void constraints_init_typeinfo(void) /* This function should be used for getting the appropriate type-info when only * a constraint type is known */ -bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type) +const bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type) { /* initialize the type-info list? */ if (CTI_INIT) { @@ -4343,7 +4343,7 @@ bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type) /* This function should always be used to get the appropriate type-info, as it * has checks which prevent segfaults in some weird cases. */ -bConstraintTypeInfo *BKE_constraint_typeinfo_get(bConstraint *con) +const bConstraintTypeInfo *BKE_constraint_typeinfo_get(bConstraint *con) { /* only return typeinfo for valid constraints */ if (con) @@ -4373,7 +4373,7 @@ static void con_unlink_refs_cb(bConstraint *UNUSED(con), ID **idpoin, bool is_re void BKE_constraint_free_data_ex(bConstraint *con, bool do_id_user) { if (con->data) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (cti) { /* perform any special freeing constraint may have */ @@ -4447,7 +4447,7 @@ bool BKE_constraint_remove_ex(ListBase *list, Object *ob, bConstraint *con, bool static bConstraint *add_new_constraint_internal(const char *name, short type) { bConstraint *con = MEM_callocN(sizeof(bConstraint), "Constraint"); - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(type); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(type); const char *newName; /* Set up a generic constraint datablock */ @@ -4574,7 +4574,7 @@ void BKE_constraints_id_loop(ListBase *conlist, ConstraintIDFunc func, void *use bConstraint *con; for (con = conlist->first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (cti) { if (cti->id_looper) @@ -4609,7 +4609,7 @@ void BKE_constraints_copy(ListBase *dst, const ListBase *src, bool do_extern) BLI_duplicatelist(dst, src); for (con = dst->first, srccon = src->first; con && srccon; srccon = srccon->next, con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); /* make a new copy of the constraint's data */ con->data = MEM_dupallocN(con->data); @@ -4724,7 +4724,7 @@ bool BKE_constraints_proxylocked_owner(Object *ob, bPoseChannel *pchan) */ void BKE_constraint_target_matrix_get(Scene *scene, bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintOb *cob; bConstraintTarget *ct; @@ -4791,7 +4791,7 @@ void BKE_constraint_target_matrix_get(Scene *scene, bConstraint *con, int index, /* Get the list of targets required for solving a constraint */ void BKE_constraint_targets_for_solving_get(bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (cti && cti->get_constraint_targets) { bConstraintTarget *ct; @@ -4836,7 +4836,7 @@ void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime) /* loop over available constraints, solving and blending them */ for (con = conlist->first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; /* these we can skip completely (invalid constraints...) */ diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index 911bb19a594..392aac13999 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -266,7 +266,7 @@ int editbmesh_get_first_deform_matrices(Scene *scene, Object *ob, BMEditMesh *em * modifiers with on cage editing that are enabled and support computing * deform matrices */ for (i = 0; md && i <= cageIndex; i++, md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); if (!editbmesh_modifier_is_enabled(scene, md, dm)) continue; @@ -322,7 +322,7 @@ int BKE_sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**defo md = modifiers_getVirtualModifierList(ob, &virtualModifierData); for (; md; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue; @@ -343,7 +343,7 @@ int BKE_sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**defo } for (; md; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue; @@ -377,7 +377,7 @@ void BKE_crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[ Mesh *me = (Mesh *)ob->data; for (; md; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue; diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 0451c2239ac..911415621d1 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -512,7 +512,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { for (con = pchan->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -574,7 +574,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc ModifierData *md; for (md = ob->modifiers.first; md; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); if (mti->updateDepgraph) mti->updateDepgraph(md, dag, bmain, scene, ob, node); } @@ -823,7 +823,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc /* object constraints */ for (con = ob->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -2011,7 +2011,7 @@ static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob) if (ob->constraints.first) { bConstraint *con; for (con = ob->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -2532,7 +2532,7 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id) for (obt = bmain->object.first; obt; obt = obt->id.next) { bConstraint *con; for (con = obt->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { @@ -2916,7 +2916,7 @@ void DAG_pose_sort(Object *ob) addtoroot = 0; } for (con = pchan->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 9004b5528ca..336d2c1a59b 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -764,7 +764,7 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, pretessellatePoint = NULL; for (; md; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); if (!modifier_isEnabled(scene, md, required_mode)) continue; @@ -833,7 +833,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb, if (pretessellatePoint) { for (; md; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); md->scene = scene; @@ -934,7 +934,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb, } for (; md; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); ModifierApplyFlag appf = app_flag; md->scene = scene; @@ -1165,7 +1165,7 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *dm_final, orcodm = create_orco_dm(scene, ob); for (; md; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); md->scene = scene; diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 7b7f024d2dc..5c9e516aee9 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -527,7 +527,7 @@ static int subframe_updateObject(Scene *scene, Object *ob, int flags, int parent /* also update constraint targets */ for (con = ob->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; if (cti && cti->get_constraint_targets) { diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 86454576b98..413e34e72a8 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1531,7 +1531,7 @@ static DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = { }; /* Get driver variable typeinfo */ -static DriverVarTypeInfo *get_dvar_typeinfo(int type) +static const DriverVarTypeInfo *get_dvar_typeinfo(int type) { /* check if valid type */ if ((type >= 0) && (type < MAX_DVAR_TYPES)) @@ -1575,7 +1575,7 @@ void driver_free_variable(ChannelDriver *driver, DriverVar *dvar) /* Change the type of driver variable */ void driver_change_variable_type(DriverVar *dvar, int type) { - DriverVarTypeInfo *dvti = get_dvar_typeinfo(type); + const DriverVarTypeInfo *dvti = get_dvar_typeinfo(type); /* sanity check */ if (ELEM(NULL, dvar, dvti)) @@ -1699,7 +1699,7 @@ ChannelDriver *fcurve_copy_driver(ChannelDriver *driver) /* Evaluate a Driver Variable to get a value that contributes to the final */ float driver_get_variable_value(ChannelDriver *driver, DriverVar *dvar) { - DriverVarTypeInfo *dvti; + const DriverVarTypeInfo *dvti; /* sanity check */ if (ELEM(NULL, driver, dvar)) diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index af0db5e1c47..396a260c3b8 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -1040,7 +1040,7 @@ static void fmods_init_typeinfo(void) /* This function should be used for getting the appropriate type-info when only * a F-Curve modifier type is known */ -FModifierTypeInfo *get_fmodifier_typeinfo(int type) +const FModifierTypeInfo *get_fmodifier_typeinfo(int type) { /* initialize the type-info list? */ if (FMI_INIT) { @@ -1065,7 +1065,7 @@ FModifierTypeInfo *get_fmodifier_typeinfo(int type) /* This function should always be used to get the appropriate type-info, as it * has checks which prevent segfaults in some weird cases. */ -FModifierTypeInfo *fmodifier_get_typeinfo(FModifier *fcm) +const FModifierTypeInfo *fmodifier_get_typeinfo(FModifier *fcm) { /* only return typeinfo for valid modifiers */ if (fcm) @@ -1079,7 +1079,7 @@ FModifierTypeInfo *fmodifier_get_typeinfo(FModifier *fcm) /* Add a new F-Curve Modifier to the given F-Curve of a certain type */ FModifier *add_fmodifier(ListBase *modifiers, int type) { - FModifierTypeInfo *fmi = get_fmodifier_typeinfo(type); + const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(type); FModifier *fcm; /* sanity checks */ @@ -1119,7 +1119,7 @@ FModifier *add_fmodifier(ListBase *modifiers, int type) /* Make a copy of the specified F-Modifier */ FModifier *copy_fmodifier(FModifier *src) { - FModifierTypeInfo *fmi = fmodifier_get_typeinfo(src); + const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(src); FModifier *dst; /* sanity check */ @@ -1153,7 +1153,7 @@ void copy_fmodifiers(ListBase *dst, ListBase *src) BLI_duplicatelist(dst, src); for (fcm = dst->first, srcfcm = src->first; fcm && srcfcm; srcfcm = srcfcm->next, fcm = fcm->next) { - FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); + const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); /* make a new copy of the F-Modifier's data */ fcm->data = MEM_dupallocN(fcm->data); @@ -1167,7 +1167,7 @@ void copy_fmodifiers(ListBase *dst, ListBase *src) /* Remove and free the given F-Modifier from the given stack */ bool remove_fmodifier(ListBase *modifiers, FModifier *fcm) { - FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); + const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); /* sanity check */ if (fcm == NULL) @@ -1266,7 +1266,7 @@ bool list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype) /* find the first mdifier fitting these criteria */ for (fcm = modifiers->first; fcm; fcm = fcm->next) { - FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); + const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); short mOk = 1, aOk = 1; /* by default 1, so that when only one test, won't fail */ /* check if applicable ones are fullfilled */ @@ -1296,7 +1296,7 @@ FModifierStackStorage *evaluate_fmodifiers_storage_new(ListBase *modifiers) } for (fcm = modifiers->last; fcm; fcm = fcm->prev) { - FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); + const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); if (fmi == NULL) { continue; @@ -1410,7 +1410,7 @@ float evaluate_time_fmodifiers(FModifierStackStorage *storage, ListBase *modifie * (such as multiple 'stepped' modifiers in sequence, causing different stepping rates) */ for (fcm = modifiers->last; fcm; fcm = fcm->prev) { - FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); + const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); if (fmi == NULL) continue; @@ -1458,7 +1458,7 @@ void evaluate_value_fmodifiers(FModifierStackStorage *storage, ListBase *modifie /* evaluate modifiers */ for (fcm = modifiers->first; fcm; fcm = fcm->next) { - FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); + const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); if (fmi == NULL) continue; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 11409297a85..4cf99dc173c 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -1069,7 +1069,7 @@ void BKE_lattice_modifiers_calc(Scene *scene, Object *ob) } for (; md; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); md->scene = scene; diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 42247d866e4..1f6d40dafa3 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -101,7 +101,7 @@ void BKE_modifier_init(void) virtualModifierCommonData.smd.modifier.mode |= eModifierMode_Virtual; } -ModifierTypeInfo *modifierType_getInfo(ModifierType type) +const ModifierTypeInfo *modifierType_getInfo(ModifierType type) { /* type unsigned, no need to check < 0 */ if (type < NUM_MODIFIER_TYPES && modifier_types[type]->name[0] != '\0') { @@ -116,7 +116,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) ModifierData *modifier_new(int type) { - ModifierTypeInfo *mti = modifierType_getInfo(type); + const ModifierTypeInfo *mti = modifierType_getInfo(type); ModifierData *md = MEM_callocN(mti->structSize, mti->structName); /* note, this name must be made unique later */ @@ -135,7 +135,7 @@ ModifierData *modifier_new(int type) void modifier_free(ModifierData *md) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); if (mti->freeData) mti->freeData(md); if (md->error) MEM_freeN(md->error); @@ -146,7 +146,7 @@ void modifier_free(ModifierData *md) bool modifier_unique_name(ListBase *modifiers, ModifierData *md) { if (modifiers && md) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); return BLI_uniquename(modifiers, md, DATA_(mti->name), '.', offsetof(ModifierData, name), sizeof(md->name)); } @@ -155,14 +155,14 @@ bool modifier_unique_name(ListBase *modifiers, ModifierData *md) bool modifier_dependsOnTime(ModifierData *md) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); return mti->dependsOnTime && mti->dependsOnTime(md); } bool modifier_supportsMapping(ModifierData *md) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); return (mti->type == eModifierTypeType_OnlyDeform || (mti->flags & eModifierTypeFlag_SupportsMapping)); @@ -170,7 +170,7 @@ bool modifier_supportsMapping(ModifierData *md) bool modifier_isPreview(ModifierData *md) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); /* Constructive modifiers are highly likely to also modify data like vgroups or vcol! */ if (!((mti->flags & eModifierTypeFlag_UsesPreview) || (mti->type == eModifierTypeType_Constructive))) { @@ -221,7 +221,7 @@ void modifiers_foreachObjectLink(Object *ob, ObjectWalkFunc walk, ModifierData *md = ob->modifiers.first; for (; md; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); if (mti->foreachObjectLink) mti->foreachObjectLink(md, ob, walk, userData); @@ -233,7 +233,7 @@ void modifiers_foreachIDLink(Object *ob, IDWalkFunc walk, void *userData) ModifierData *md = ob->modifiers.first; for (; md; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); if (mti->foreachIDLink) mti->foreachIDLink(md, ob, walk, userData); else if (mti->foreachObjectLink) { @@ -249,7 +249,7 @@ void modifiers_foreachTexLink(Object *ob, TexWalkFunc walk, void *userData) ModifierData *md = ob->modifiers.first; for (; md; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); if (mti->foreachTexLink) mti->foreachTexLink(md, ob, walk, userData); @@ -261,7 +261,7 @@ void modifiers_foreachTexLink(Object *ob, TexWalkFunc walk, void *userData) */ void modifier_copyData_generic(const ModifierData *md_src, ModifierData *md_dst) { - ModifierTypeInfo *mti = modifierType_getInfo(md_src->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md_src->type); const size_t data_size = sizeof(ModifierData); const char *md_src_data = ((const char *)md_src) + data_size; char *md_dst_data = ((char *)md_dst) + data_size; @@ -271,7 +271,7 @@ void modifier_copyData_generic(const ModifierData *md_src, ModifierData *md_dst) void modifier_copyData(ModifierData *md, ModifierData *target) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); target->mode = md->mode; @@ -282,7 +282,7 @@ void modifier_copyData(ModifierData *md, ModifierData *target) bool modifier_supportsCage(struct Scene *scene, ModifierData *md) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); md->scene = scene; @@ -293,7 +293,7 @@ bool modifier_supportsCage(struct Scene *scene, ModifierData *md) bool modifier_couldBeCage(struct Scene *scene, ModifierData *md) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); md->scene = scene; @@ -305,13 +305,13 @@ bool modifier_couldBeCage(struct Scene *scene, ModifierData *md) bool modifier_isSameTopology(ModifierData *md) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); return ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical); } bool modifier_isNonGeometrical(ModifierData *md) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); return (mti->type == eModifierTypeType_NonGeometrical); } @@ -353,7 +353,7 @@ int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *r_lastPossibleC /* Find the last modifier acting on the cage. */ for (i = 0; md; i++, md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); bool supports_mapping; md->scene = scene; @@ -411,7 +411,7 @@ bool modifiers_isParticleEnabled(Object *ob) bool modifier_isEnabled(struct Scene *scene, ModifierData *md, int required_mode) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); md->scene = scene; @@ -432,7 +432,7 @@ CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, Object *ob, ModifierDat /* build a list of modifier data requirements in reverse order */ for (; md; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); curr = MEM_callocN(sizeof(CDMaskLink), "CDMaskLink"); @@ -626,7 +626,7 @@ bool modifiers_usesArmature(Object *ob, bArmature *arm) bool modifier_isCorrectableDeformed(ModifierData *md) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); return (mti->deformMatricesEM != NULL); } @@ -736,7 +736,7 @@ struct DerivedMesh *modwrap_applyModifier( struct DerivedMesh *dm, ModifierApplyFlag flag) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { @@ -751,7 +751,7 @@ struct DerivedMesh *modwrap_applyModifierEM( DerivedMesh *dm, ModifierApplyFlag flag) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { @@ -766,7 +766,7 @@ void modwrap_deformVerts( float (*vertexCos)[3], int numVerts, ModifierApplyFlag flag) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { @@ -780,7 +780,7 @@ void modwrap_deformVertsEM( struct BMEditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 220d0f7c604..4ac96405fbf 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -280,7 +280,7 @@ static MDisps *multires_mdisps_initialize_hidden(Mesh *me, int level) DerivedMesh *get_multires_dm(Scene *scene, MultiresModifierData *mmd, Object *ob) { ModifierData *md = (ModifierData *)mmd; - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); DerivedMesh *tdm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); DerivedMesh *dm; @@ -429,7 +429,7 @@ int multiresModifier_reshape(Scene *scene, MultiresModifierData *mmd, Object *ds int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mmd, Object *ob, ModifierData *md) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); DerivedMesh *dm, *ndm; int numVerts, result; float (*deformedVerts)[3]; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 174fb38aada..b3607d38014 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -234,7 +234,7 @@ void BKE_object_modifier_hook_reset(Object *ob, HookModifierData *hmd) bool BKE_object_support_modifier_type_check(Object *ob, int modifier_type) { - ModifierTypeInfo *mti; + const ModifierTypeInfo *mti; mti = modifierType_getInfo(modifier_type); @@ -531,7 +531,7 @@ void BKE_object_unlink(Object *ob) bPoseChannel *pchan; for (pchan = obt->pose->chanbase.first; pchan; pchan = pchan->next) { for (con = pchan->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -562,7 +562,7 @@ void BKE_object_unlink(Object *ob) sca_remove_ob_poin(obt, ob); for (con = obt->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -1408,7 +1408,7 @@ static void copy_object_pose(Object *obn, Object *ob) chan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE); for (con = chan->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -2221,7 +2221,7 @@ static void give_parvert(Object *par, int nr, float vec[3]) md != NULL; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); /* TODO(sergey): Check for disabled modifiers. */ if (mti->type != eModifierTypeType_OnlyDeform && md->next != NULL) { use_special_ss_case = false; @@ -3674,7 +3674,7 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob) md && (flag != (eModifierMode_Render | eModifierMode_Realtime)); md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); bool can_deform = mti->type == eModifierTypeType_OnlyDeform || is_modifier_animated; diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index c3c88389e11..07b3893c545 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -720,7 +720,7 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob) /* exception for shape keys because we can edit those */ for (; md; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue; if (ELEM(md->type, eModifierType_ShapeKey, eModifierType_Multires)) continue; diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index b9d096f1346..f543a9f4c65 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -563,7 +563,7 @@ static void sequence_modifier_type_info_init(void) #undef INIT_TYPE } -SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type) +const SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type) { if (!modifierTypesInit) { sequence_modifier_type_info_init(); @@ -576,7 +576,7 @@ SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type) SequenceModifierData *BKE_sequence_modifier_new(Sequence *seq, const char *name, int type) { SequenceModifierData *smd; - SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(type); + const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(type); smd = MEM_callocN(smti->struct_size, "sequence modifier"); @@ -623,7 +623,7 @@ void BKE_sequence_modifier_clear(Sequence *seq) void BKE_sequence_modifier_free(SequenceModifierData *smd) { - SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); if (smti && smti->free_data) { smti->free_data(smd); @@ -634,7 +634,7 @@ void BKE_sequence_modifier_free(SequenceModifierData *smd) void BKE_sequence_modifier_unique_name(Sequence *seq, SequenceModifierData *smd) { - SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); BLI_uniquename(&seq->modifiers, smd, CTX_DATA_(BLF_I18NCONTEXT_ID_SEQUENCE, smti->name), '.', offsetof(SequenceModifierData, name), sizeof(smd->name)); @@ -656,7 +656,7 @@ ImBuf *BKE_sequence_modifier_apply_stack(const SeqRenderData *context, Sequence } for (smd = seq->modifiers.first; smd; smd = smd->next) { - SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); /* could happen if modifier is being removed or not exists in current version of blender */ if (!smti) @@ -692,7 +692,7 @@ void BKE_sequence_modifier_list_copy(Sequence *seqn, Sequence *seq) for (smd = seq->modifiers.first; smd; smd = smd->next) { SequenceModifierData *smdn; - SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); smdn = MEM_dupallocN(smd); diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index aa8649b1bed..770ef4c2493 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -972,7 +972,7 @@ static bool subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int /* also update constraint targets */ for (con = ob->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; if (cti && cti->get_constraint_targets) { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 1156d3f30f0..bc1bc9c7759 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -597,7 +597,7 @@ static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers) /* Modifiers */ for (fcm= fmodifiers->first; fcm; fcm= fcm->next) { - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + const FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); /* Write the specific data */ if (fmi && fcm->data) { @@ -1404,7 +1404,7 @@ static void write_constraints(WriteData *wd, ListBase *conlist) bConstraint *con; for (con=conlist->first; con; con=con->next) { - bConstraintTypeInfo *cti= BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti= BKE_constraint_typeinfo_get(con); /* Write the specific data */ if (cti && con->data) { @@ -1500,7 +1500,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) if (modbase == NULL) return; for (md=modbase->first; md; md= md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); if (mti == NULL) return; writestruct(wd, DATA, mti->structName, 1, md); @@ -2287,7 +2287,7 @@ static void write_sequence_modifiers(WriteData *wd, ListBase *modbase) SequenceModifierData *smd; for (smd = modbase->first; smd; smd = smd->next) { - SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); if (smti) { writestruct(wd, DATA, smti->struct_name, 1, smd); diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp index de4e29a7d48..7bea0b70c95 100644 --- a/source/blender/collada/AnimationExporter.cpp +++ b/source/blender/collada/AnimationExporter.cpp @@ -185,7 +185,7 @@ void AnimationExporter::make_anim_frames_from_targets(Object *ob, std::vectorfirst; con; con = con->next) { ListBase targets = {NULL, NULL}; - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (!validateConstraints(con)) continue; @@ -1526,7 +1526,7 @@ void AnimationExporter::sample_animation(float *v, std::vector &frames, i bool AnimationExporter::validateConstraints(bConstraint *con) { bool valid = true; - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); /* these we can skip completely (invalid constraints...) */ if (cti == NULL) valid = false; if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) valid = false; @@ -1545,7 +1545,7 @@ void AnimationExporter::calc_ob_mat_at_time(Object *ob, float ctime , float mat[ for (con = (bConstraint *)conlist->first; con; con = con->next) { ListBase targets = {NULL, NULL}; - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (cti && cti->get_constraint_targets) { bConstraintTarget *ct; diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index bcdad1c93ad..2c0018b000d 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -78,7 +78,7 @@ static void validate_fmodifier_cb(bContext *UNUSED(C), void *fcm_v, void *UNUSED(arg)) { FModifier *fcm = (FModifier *)fcm_v; - FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); + const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); /* call the verify callback on the modifier if applicable */ if (fmi && fmi->verify_data) @@ -555,7 +555,7 @@ static void draw_modifier__stepped(uiLayout *layout, ID *id, FModifier *fcm, sho void ANIM_uiTemplate_fmodifier_draw(uiLayout *layout, ID *id, ListBase *modifiers, FModifier *fcm) { - FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); + const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); uiLayout *box, *row, *sub, *col; uiBlock *block; uiBut *but; diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index fb94c55f3da..e3a69a89a57 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -308,7 +308,7 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Obj /* does this constraint have a subtarget in * this armature? */ - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index 29b7872f304..d4df77753eb 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -1264,7 +1264,7 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op)) } else { for (con = pchan->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index a8b5f888597..177fb6c9118 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -104,7 +104,7 @@ static void constraint_bone_name_fix(Object *ob, ListBase *conlist, const char * bConstraintTarget *ct; for (curcon = conlist->first; curcon; curcon = curcon->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon); ListBase targets = {NULL, NULL}; /* constraint targets */ diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index 4eb2159aee1..ad9715d2ab2 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -78,7 +78,7 @@ static void joined_armature_fix_links_constraints( bConstraint *con; for (con = lb->first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -435,7 +435,7 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm) if (ob->type == OB_ARMATURE) { for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { for (con = pchan->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -473,7 +473,7 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm) /* fix object-level constraints */ if (ob != origArm) { for (con = ob->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c index 5376fc8c79b..2235f9f92cc 100644 --- a/source/blender/editors/armature/editarmature_retarget.c +++ b/source/blender/editors/armature/editarmature_retarget.c @@ -707,7 +707,7 @@ static void RIG_reconnectControlBones(RigGraph *rg) /* DO SOME MAGIC HERE */ for (pchan = rg->ob->pose->chanbase.first; pchan; pchan = pchan->next) { for (con = pchan->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -832,7 +832,7 @@ static void RIG_reconnectControlBones(RigGraph *rg) /* DO SOME MAGIC HERE */ for (pchan = rg->ob->pose->chanbase.first; pchan; pchan = pchan->next) { for (con = pchan->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index a4a21a0a225..ce8d026f73b 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -458,7 +458,7 @@ static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op { if (pchan->bone->flag & BONE_SELECTED) { for (con = pchan->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 7db734ee919..73df06bcc37 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -823,7 +823,7 @@ static int modifier_is_simulation(ModifierData *md) static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, ModifierData *md, int index, int cageIndex, int lastCageIndex) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); PointerRNA ptr; uiBut *but; uiBlock *block; @@ -1095,7 +1095,7 @@ static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v) static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) { bPoseChannel *pchan = BKE_pose_channel_active(ob); - bConstraintTypeInfo *cti; + const bConstraintTypeInfo *cti; uiBlock *block; uiLayout *result = NULL, *col, *box, *row; PointerRNA ptr; diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index f1b349d5a44..d459dd417c7 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -226,7 +226,7 @@ static void update_pyconstraint_cb(void *arg1, void *arg2) /* helper function for add_constriant - sets the last target for the active constraint */ static void set_constraint_nth_target(bConstraint *con, Object *target, const char subtarget[], int index) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; int num_targets, i; @@ -262,7 +262,7 @@ static void set_constraint_nth_target(bConstraint *con, Object *target, const ch static void test_constraint(Object *owner, bPoseChannel *pchan, bConstraint *con, int type) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; bool check_targets = true; diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 710cf2dbdd2..f9315214557 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -96,7 +96,7 @@ static void modifier_skin_customdata_delete(struct Object *ob); ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type) { ModifierData *md = NULL, *new_md = NULL; - ModifierTypeInfo *mti = modifierType_getInfo(type); + const ModifierTypeInfo *mti = modifierType_getInfo(type); /* only geometry objects should be able to get modifiers [#25291] */ if (!ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { @@ -368,10 +368,10 @@ void ED_object_modifier_clear(Main *bmain, Object *ob) int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md) { if (md->prev) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); if (mti->type != eModifierTypeType_OnlyDeform) { - ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type); + const ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type); if (nmti->flags & eModifierTypeFlag_RequiresOriginalData) { BKE_report(reports, RPT_WARNING, "Cannot move above a modifier requiring original data"); @@ -389,10 +389,10 @@ int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *md) { if (md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); if (mti->flags & eModifierTypeFlag_RequiresOriginalData) { - ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type); + const ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type); if (nmti->type != eModifierTypeType_OnlyDeform) { BKE_report(reports, RPT_WARNING, "Cannot move beyond a non-deforming modifier"); @@ -518,7 +518,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene * static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, ModifierData *md) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); md->scene = scene; @@ -578,7 +578,7 @@ static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, M static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, ModifierData *md) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); md->scene = scene; @@ -742,7 +742,7 @@ static EnumPropertyItem *modifier_add_itemf(bContext *C, PointerRNA *UNUSED(ptr) { Object *ob = ED_object_active_context(C); EnumPropertyItem *item = NULL, *md_item, *group_item = NULL; - ModifierTypeInfo *mti; + const ModifierTypeInfo *mti; int totitem = 0, a; if (!ob) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index ea046b7d4d5..5c55ad1c63d 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -4746,7 +4746,7 @@ static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, co /* exception for shape keys because we can edit those */ for (; md; md = md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue; if (mti->type == eModifierTypeType_Constructive) { diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index c8bea114373..db8881a865e 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -2042,7 +2042,7 @@ static void object_solver_inverted_matrix(Scene *scene, Object *ob, float invmat bool found = false; for (con = ob->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (!cti) continue; @@ -2073,7 +2073,7 @@ static Object *object_solver_camera(Scene *scene, Object *ob) bConstraint *con; for (con = ob->constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (!cti) continue; diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 559eec8fe48..a26bfddf65a 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -2248,7 +2248,7 @@ static EnumPropertyItem *graph_fmodifier_itemf(bContext *C, PointerRNA *UNUSED(p /* start from 1 to skip the 'Invalid' modifier type */ for (i = 1; i < FMODIFIER_NUM_TYPES; i++) { - FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i); + const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i); int index; /* check if modifier is valid for this context */ diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index a883f350f1c..56825ff1aa4 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -2189,7 +2189,7 @@ static int nla_fmodifier_add_invoke(bContext *C, wmOperator *UNUSED(op), const w /* start from 1 to skip the 'Invalid' modifier type */ for (i = 1; i < FMODIFIER_NUM_TYPES; i++) { - FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i); + const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i); /* check if modifier is valid for this context */ if (fmi == NULL) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 628fd23e0d5..f14c19dc07e 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -7922,7 +7922,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } } else { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon); if ((cti && cti->get_constraint_targets) && (curcon->flag & CONSTRAINT_EXPAND)) { ListBase targets = {NULL, NULL}; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 8b2bc3bee4d..9cf90cbd45c 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2516,8 +2516,8 @@ static void protectedQuaternionBits(short protectflag, float quat[4], const floa static void constraintTransLim(TransInfo *t, TransData *td) { if (td->con) { - bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_LOCLIMIT); - bConstraintTypeInfo *ctiDist = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_DISTLIMIT); + const bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_LOCLIMIT); + const bConstraintTypeInfo *ctiDist = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_DISTLIMIT); bConstraintOb cob = {NULL}; bConstraint *con; @@ -2532,7 +2532,7 @@ static void constraintTransLim(TransInfo *t, TransData *td) /* Evaluate valid constraints */ for (con = td->con; con; con = con->next) { - bConstraintTypeInfo *cti = NULL; + const bConstraintTypeInfo *cti = NULL; ListBase targets = {NULL, NULL}; /* only consider constraint if enabled */ @@ -2619,7 +2619,7 @@ static void constraintob_from_transdata(bConstraintOb *cob, TransData *td) static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) { if (td->con) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT); bConstraintOb cob; bConstraint *con; bool do_limit = false; @@ -2686,7 +2686,7 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) static void constraintSizeLim(TransInfo *t, TransData *td) { if (td->con && td->ext) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT); bConstraintOb cob = {NULL}; bConstraint *con; float size_sign[3], size_abs[3]; diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 0f4830a8a7e..e4aa21867e7 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -323,7 +323,7 @@ static EnumPropertyItem *rna_Constraint_target_space_itemf(bContext *UNUSED(C), PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) { bConstraint *con = (bConstraint *)ptr->data; - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 6c893255601..576af7b3a1c 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -574,7 +574,7 @@ static void rna_FModifier_blending_range(PointerRNA *ptr, float *min, float *max static void rna_FModifier_verify_data_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { FModifier *fcm = (FModifier *)ptr->data; - FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); + const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); /* call the verify callback on the modifier if applicable */ if (fmi && fmi->verify_data) -- cgit v1.2.3 From 01e0062b4c537498d69b30f733e03680da6435c6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 30 Mar 2015 21:25:28 +1100 Subject: missed last commit --- source/blender/collada/SceneExporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index b50b8b0a302..b2d9aed579b 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -210,7 +210,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) //not ideal: add the target object name as another parameter. //No real mapping in the .dae //Need support for multiple target objects also. - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; if (cti && cti->get_constraint_targets) { -- cgit v1.2.3 From bfe63bbfc470bd2deba0c3fdd793b3f59b682979 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 30 Mar 2015 12:47:37 +0200 Subject: Grey out high quality depth of field when it's not supported by GPU --- intern/cycles/blender/addon/ui.py | 8 ++++++-- release/scripts/startup/bl_ui/properties_data_camera.py | 8 +++++--- source/blender/makesrna/intern/rna_scene.c | 13 +++++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index f0f256f979e..956d8b962e9 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -456,11 +456,15 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel): sub = col.row() sub.active = cam.dof_object is None sub.prop(cam, "dof_distance", text="Distance") + + hq_support = dof_options.is_hq_supported sub = col.column(align=True) sub.label("Viewport:") - sub.prop(dof_options, "use_high_quality") + subhq = sub.column() + subhq.active = hq_support; + subhq.prop(dof_options, "use_high_quality") sub.prop(dof_options, "fstop") - if dof_options.use_high_quality: + if dof_options.use_high_quality and hq_support: sub.prop(dof_options, "blades") col = split.column() diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py index bc66e39b48f..e4255966a5f 100644 --- a/release/scripts/startup/bl_ui/properties_data_camera.py +++ b/release/scripts/startup/bl_ui/properties_data_camera.py @@ -188,12 +188,14 @@ class DATA_PT_camera_dof(CameraButtonsPanel, Panel): sub.active = (cam.dof_object is None) sub.prop(cam, "dof_distance", text="Distance") + hq_support = dof_options.is_hq_supported col = split.column(align=True) col.label("Viewport:") - col.prop(dof_options, "use_high_quality") + sub = col.column() + sub.active = hq_support + sub.prop(dof_options, "use_high_quality") col.prop(dof_options, "fstop") - - if dof_options.use_high_quality: + if dof_options.use_high_quality and hq_support: col.prop(dof_options, "blades") diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 8cf36367e01..700d1aa91ea 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -45,6 +45,8 @@ #include "BKE_paint.h" #include "BKE_scene.h" +#include "GPU_extensions.h" + #include "RNA_define.h" #include "RNA_enum_types.h" @@ -1758,6 +1760,11 @@ static void rna_GPUDOFSettings_blades_set(PointerRNA *ptr, const int value) } +static int rna_gpu_is_hq_supported_get(PointerRNA *UNUSED(ptr)) +{ + return GPU_instanced_drawing_support() && GPU_geometry_shader_support(); +} + #else static void rna_def_transform_orientation(BlenderRNA *brna) @@ -3947,6 +3954,12 @@ static void rna_def_gpu_dof_fx(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "high_quality", 1); RNA_def_property_ui_text(prop, "High Quality", "Use high quality depth of field"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "is_hq_supported", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_gpu_is_hq_supported_get", NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "High Quality", "Use high quality depth of field"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); } static void rna_def_gpu_ssao_fx(BlenderRNA *brna) -- cgit v1.2.3 From 98cbde91d2b6dba76875a078f705c77733cbb1e2 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 30 Mar 2015 13:06:54 +0200 Subject: Fix compilation of game engine in ubuntu --- source/gameengine/Converter/BL_ArmatureObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index bc2fc0179fd..795a7a9ae87 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -268,7 +268,7 @@ void BL_ArmatureObject::LoadConstraints(KX_BlenderSceneConverter* converter) // get the persistent pose structure bPoseChannel* pchan; bConstraint* pcon; - bConstraintTypeInfo* cti; + const bConstraintTypeInfo* cti; Object* blendtarget; KX_GameObject* gametarget; KX_GameObject* gamesubtarget; -- cgit v1.2.3 From 4aeb34dc82e904660a1df06617406028b5331ff1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 30 Mar 2015 21:29:20 +1100 Subject: Cleanup: use const for typeinfo --- .../editors/animation/anim_channels_defines.c | 32 +++++++++++----------- .../blender/editors/animation/anim_channels_edit.c | 8 +++--- source/blender/editors/animation/anim_filter.c | 2 +- source/blender/editors/include/ED_anim_api.h | 2 +- source/blender/editors/space_action/action_draw.c | 2 +- source/blender/editors/space_action/action_edit.c | 2 +- source/blender/editors/space_graph/graph_buttons.c | 2 +- source/blender/editors/space_nla/nla_edit.c | 2 +- 8 files changed, 26 insertions(+), 26 deletions(-) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 7eb32d4dc45..d71cba86f8d 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -110,7 +110,7 @@ static void acf_generic_root_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUS /* backdrop for top-level widgets (Scene and Object only) */ static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); View2D *v2d = &ac->ar->v2d; short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0; short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; @@ -136,7 +136,7 @@ static void acf_generic_dataexpand_color(bAnimContext *UNUSED(ac), bAnimListElem /* backdrop for data expanders under top-level Scene/Object */ static void acf_generic_dataexpand_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); View2D *v2d = &ac->ar->v2d; short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; float color[3]; @@ -177,7 +177,7 @@ static bool acf_show_channel_colors(bAnimContext *ac) /* get backdrop color for generic channels */ static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, float r_color[3]) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); bActionGroup *grp = NULL; short indent = (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0; bool showGroupColors = acf_show_channel_colors(ac); @@ -217,7 +217,7 @@ static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, floa /* backdrop for generic channels */ static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); View2D *v2d = &ac->ar->v2d; short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; float color[3]; @@ -269,7 +269,7 @@ static short acf_generic_indention_flexible(bAnimContext *UNUSED(ac), bAnimListE /* basic offset for channels derived from indention */ static short acf_generic_basic_offset(bAnimContext *ac, bAnimListElem *ale) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); if (acf && acf->get_indent_level) return acf->get_indent_level(ac, ale) * INDENT_STEP_SIZE; @@ -409,7 +409,7 @@ static void acf_summary_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(al /* backdrop for summary widget */ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); View2D *v2d = &ac->ar->v2d; float color[3]; @@ -790,7 +790,7 @@ static void acf_group_color(bAnimContext *ac, bAnimListElem *ale, float r_color[ /* backdrop for group widget */ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); View2D *v2d = &ac->ar->v2d; short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0; short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; @@ -1029,7 +1029,7 @@ static void acf_nla_controls_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUS /* backdrop for nla controls expander widget */ static void acf_nla_controls_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); View2D *v2d = &ac->ar->v2d; short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0; short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; @@ -3206,7 +3206,7 @@ static void acf_nlaaction_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, fl /* backdrop for nla action channel */ static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); View2D *v2d = &ac->ar->v2d; AnimData *adt = ale->adt; short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; @@ -3402,7 +3402,7 @@ static void ANIM_init_channel_typeinfo_data(void) } /* Get type info from given channel type */ -bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale) +const bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale) { /* santiy checks */ if (ale == NULL) @@ -3423,7 +3423,7 @@ bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale) /* Print debug info string for the given channel */ void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); /* print indents */ for (; indent_level > 0; indent_level--) @@ -3455,7 +3455,7 @@ void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level) */ short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); /* 1) check that the setting exists for the current context */ if ((acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting))) { @@ -3528,7 +3528,7 @@ short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChanne */ void ANIM_channel_setting_set(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting, eAnimChannels_SetFlag mode) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); /* 1) check that the setting exists for the current context */ if ((acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting))) { @@ -3579,7 +3579,7 @@ void ANIM_channel_setting_set(bAnimContext *ac, bAnimListElem *ale, eAnimChannel /* Draw the given channel */ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); View2D *v2d = &ac->ar->v2d; short selected, offset; float y, ymid, ytext; @@ -3956,7 +3956,7 @@ static void achannel_setting_slider_nla_curve_cb(bContext *C, void *UNUSED(id_po } /* Draw a widget for some setting */ -static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChannelType *acf, +static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, const bAnimChannelType *acf, uiBlock *block, int xpos, int ypos, int setting) { short ptrsize, butType; @@ -4096,7 +4096,7 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann /* Draw UI widgets the given channel */ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListElem *ale, uiBlock *block, float yminc, float ymaxc, size_t channel_index) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); View2D *v2d = &ac->ar->v2d; float y, ymid /*, ytext*/; short offset; diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index cf2fa9fffe1..1782152560a 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -448,7 +448,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn return; } else { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale_setting); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale_setting); if (acf == NULL) { printf("ERROR: no channel info for the changed channel\n"); @@ -477,7 +477,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn { /* go backwards in the list, until the highest-ranking element (by indention has been covered) */ for (ale = match->prev; ale; ale = ale->prev) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); int level; /* if no channel info was found, skip, since this type might not have any useful info */ @@ -521,7 +521,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn { /* go forwards in the list, until the lowest-ranking element (by indention has been covered) */ for (ale = match->next; ale; ale = ale->next) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); int level; /* if no channel info was found, skip, since this type might not have any useful info */ @@ -2499,7 +2499,7 @@ static void ANIM_OT_channels_select_border(wmOperatorType *ot) static void rename_anim_channels(bAnimContext *ac, int channel_index) { ListBase anim_data = {NULL, NULL}; - bAnimChannelType *acf; + const bAnimChannelType *acf; bAnimListElem *ale; int filter; diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 76bede8edaa..ee662c46fd0 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -992,7 +992,7 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id static bool skip_fcurve_with_name(bDopeSheet *ads, FCurve *fcu, ID *owner_id) { bAnimListElem ale_dummy = {NULL}; - bAnimChannelType *acf; + const bAnimChannelType *acf; /* create a dummy wrapper for the F-Curve */ ale_dummy.type = ANIMTYPE_FCURVE; diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 1ce285f8190..8cf42dfce6c 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -455,7 +455,7 @@ typedef struct bAnimChannelType { /* ------------------------ Drawing API -------------------------- */ /* Get typeinfo for the given channel */ -bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale); +const bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale); /* Print debugging info about a given channel */ void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level); diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index a17cfa4d87c..cc30639332a 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -210,7 +210,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); int sel = 0; /* determine if any need to draw channel */ diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 740992a3ad4..ce8723c572d 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -752,7 +752,7 @@ static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *min, y = (float)ACHANNEL_FIRST; for (ale = anim_data.first; ale; ale = ale->next) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); /* must be selected... */ if (acf && acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT) && diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index f1e094c31ed..e0b62722d57 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -172,7 +172,7 @@ static void graph_panel_properties(const bContext *C, Panel *pa) } else { /* NLA Control Curve, etc. */ - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); /* get name */ if (acf && acf->name) { diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 56825ff1aa4..9ae96292f52 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -382,7 +382,7 @@ static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, floa y = (float)NLACHANNEL_FIRST; for (ale = anim_data.first; ale; ale = ale->next) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); /* must be selected... */ if (acf && acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT) && -- cgit v1.2.3 From 590efaacb862aa4352b11e77d37805df5445a90f Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 30 Mar 2015 14:14:32 +0200 Subject: Potential fix for T43987, ambient occlusion different between offscreen and on screen rendering. Aaaaah, the beauty of driver implementations of OpenGL! Turns out the problem here is that drivers calculate df/dy differently in some cases (probably because OpenGL counts y reverse to how the window system does, so drivers can get confused). Fixed this for the ATI case based on info we have so far, there's also the Intel case which will be handled separately (missing info on Intel's renderer string etc). Unfortunately we can't really fix this for the general case so we'll have to haldle cases as they come in our tracker and by adding silly string comparisons in our GPU initialization module . --- source/blender/gpu/GPU_extensions.h | 1 + source/blender/gpu/intern/gpu_compositing.c | 4 +++ source/blender/gpu/intern/gpu_extensions.c | 29 +++++++++++++++++++++- source/blender/gpu/shaders/gpu_shader_fx_lib.glsl | 8 ------ .../gpu/shaders/gpu_shader_fx_ssao_frag.glsl | 8 ++++++ 5 files changed, 41 insertions(+), 9 deletions(-) diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index c006540ddf4..de0af815bf4 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -66,6 +66,7 @@ bool GPU_instanced_drawing_support(void); int GPU_max_texture_size(void); int GPU_color_depth(void); +void GPU_get_dfdy_factors(float fac[2]); void GPU_code_generate_glsl_lib(void); diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index f850b6fcc55..ab4726508e8 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -645,6 +645,7 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str int numslots = 0; float invproj[4][4]; int i; + float dfdyfac[2]; /* number of passes left. when there are no more passes, the result is passed to the frambuffer */ int passes_left = fx->num_passes; /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */ @@ -657,6 +658,7 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str if (fx->effects == 0) return false; + GPU_get_dfdy_factors(dfdyfac); /* first, unbind the render-to-texture framebuffer */ GPU_framebuffer_texture_detach(fx->color_buffer); GPU_framebuffer_texture_detach(fx->depth_buffer); @@ -722,6 +724,8 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str sample_params[2] = fx->gbuffer_dim[0] / 64.0; sample_params[3] = fx->gbuffer_dim[1] / 64.0; + ssao_params[3] = (passes_left == 1) ? dfdyfac[0] : dfdyfac[1]; + ssao_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_params"); ssao_color_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_color"); color_uniform = GPU_shader_get_uniform(ssao_shader, "colorbuffer"); diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index bc6e24f5072..c602fdad18e 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -40,6 +40,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_math_base.h" +#include "BLI_math_vector.h" #include "BKE_global.h" @@ -113,6 +114,9 @@ static struct GPUGlobal { GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */ GPUTexture *invalid_tex_2D; GPUTexture *invalid_tex_3D; + float dfdyfactors[2]; /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers + calculate dfdy in shader differently when drawing to an offscreen buffer. First + number is factor on screen and second is off-screen */ } GG = {1, 0}; /* Number of maximum output slots. We support 4 outputs for now (usually we wouldn't need more to preserve fill rate) */ @@ -144,10 +148,15 @@ int GPU_max_texture_size(void) return GG.maxtexsize; } +void GPU_get_dfdy_factors(float fac[2]) +{ + copy_v2_v2(fac, GG.dfdyfactors); +} + void gpu_extensions_init(void) { GLint r, g, b; - const char *vendor, *renderer; + const char *vendor, *renderer, *version; /* glewIsSupported("GL_VERSION_2_0") */ @@ -168,6 +177,7 @@ void gpu_extensions_init(void) vendor = (const char *)glGetString(GL_VENDOR); renderer = (const char *)glGetString(GL_RENDERER); + version = (const char *)glGetString(GL_VERSION); if (strstr(vendor, "ATI")) { GG.device = GPU_DEVICE_ATI; @@ -244,6 +254,23 @@ void gpu_extensions_init(void) #endif + /* df/dy calculation factors, those are dependent on driver */ + if ((strstr(vendor, "ATI") && strstr(version, "3.3.10750"))) { + GG.dfdyfactors[0] = 1.0; + GG.dfdyfactors[1] = -1.0; + } + /* + if ((strstr(vendor, "Intel"))) { + GG.dfdyfactors[0] = -1.0; + GG.dfdyfactors[1] = 1.0; + } + */ + else { + GG.dfdyfactors[0] = 1.0; + GG.dfdyfactors[1] = 1.0; + } + + GPU_invalid_tex_init(); GPU_simple_shaders_init(); } diff --git a/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl index 6c4bf3bb7a0..1dc49b52be1 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl @@ -1,11 +1,3 @@ -vec3 calculate_view_space_normal(in vec3 viewposition) -{ - vec3 normal = cross(normalize(dFdx(viewposition)), - normalize(dFdy(viewposition))); - normalize(normal); - return normal; -} - /* simple depth reconstruction, see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer * we change the factors from the article to fit the OpennGL model. */ #ifdef PERSP_MATRIX diff --git a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl index 5e2512b6a46..783bce75fbd 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl @@ -23,6 +23,14 @@ uniform vec4 ssao_color; * see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ uniform vec4 viewvecs[3]; +vec3 calculate_view_space_normal(in vec3 viewposition) +{ + vec3 normal = cross(normalize(dFdx(viewposition)), + ssao_params.w * normalize(dFdy(viewposition))); + normalize(normal); + return normal; +} + float calculate_ssao_factor(float depth) { /* take the normalized ray direction here */ -- cgit v1.2.3 From 79a68617b3fbf2d714cde0a8964572a9a7f2a759 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 30 Mar 2015 23:31:07 +1100 Subject: Pass bool arg to RNA_property_boolean_set --- source/blender/editors/transform/transform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 9cf90cbd45c..586c9d62589 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1989,7 +1989,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } if ((prop = RNA_struct_find_property(op->ptr, "mirror"))) { - RNA_property_boolean_set(op->ptr, prop, t->flag & T_MIRROR); + RNA_property_boolean_set(op->ptr, prop, (t->flag & T_MIRROR) != 0); } if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) { -- cgit v1.2.3 From c6ce8200dd3f3b67029cfd5578f21d206cff219e Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 30 Mar 2015 14:44:31 +0200 Subject: Attempt to fix T44056, dof high quality shader error in ATI cards. ATI driver does not like declaration of gl_FragColor and glFragData in the same source file (even though only one of the two is ever referenced), just use one of the two. --- source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl index 8c2aff45679..e315d2fb97a 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl @@ -107,7 +107,7 @@ void accumulate_pass(void) { if (dot(particlecoord, particlecoord) > r * r) discard; - gl_FragColor = color; + gl_FragData[0] = color; } #define MERGE_THRESHOLD 4.0 @@ -151,7 +151,7 @@ void final_pass(void) { finalcolor = mix(finalcolor, nearcolor, nearweight / totalweight); } - gl_FragColor = finalcolor; + gl_FragData[0] = finalcolor; } void main() -- cgit v1.2.3 From bacdfc70e2109711eeecef122cf408e6803990ca Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 30 Mar 2015 15:04:42 +0200 Subject: Fix T41191: Custom Loop Normals Viewport shading not updating when set from py script Missing update tagging... Safe for 2.74. --- source/blender/makesrna/intern/rna_mesh_api.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 48a5f09fda0..632b07c19ce 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -170,6 +170,8 @@ static void rna_Mesh_normals_split_custom_set(Mesh *mesh, ReportList *reports, i } rna_Mesh_normals_split_custom_do(mesh, loopnors, false); + + DAG_id_tag_update(&mesh->id, 0); } static void rna_Mesh_normals_split_custom_set_from_vertices( @@ -186,6 +188,8 @@ static void rna_Mesh_normals_split_custom_set_from_vertices( } rna_Mesh_normals_split_custom_do(mesh, vertnors, true); + + DAG_id_tag_update(&mesh->id, 0); } static void rna_Mesh_transform(Mesh *mesh, float *mat, int shape_keys) -- cgit v1.2.3 From 050f28f03f968cbee7bd2640aa67d43d80713c62 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 30 Mar 2015 18:27:08 +0200 Subject: Remove wrong back jump detection on looping --- source/blender/editors/screen/screen_ops.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index a192a501177..25571c00928 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -3529,8 +3529,12 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv sad->flag |= ANIMPLAY_FLAG_JUMPED; } - if (sad->flag & ANIMPLAY_FLAG_JUMPED) + if (sad->flag & ANIMPLAY_FLAG_JUMPED) { BKE_sound_seek_scene(bmain, scene); + #ifdef PROFILE_AUDIO_SYNCH + old_frame = CFRA; + #endif + } /* since we follow drawflags, we can't send notifier but tag regions ourselves */ ED_update_for_newframe(bmain, scene, 1); -- cgit v1.2.3 From 9b4172cc6c0ab8f3c5476a37273197474ff33de0 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 30 Mar 2015 19:21:38 +0200 Subject: Fix T43266, when we have a blendfile name use only that without the pid for autosave. Will save Windows users from polluting their tmp folders too much. --- source/blender/windowmanager/intern/wm_files.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 697a798ed3c..3fd1fe427c9 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -1086,7 +1086,7 @@ void wm_autosave_location(char *filepath) if (G.main && G.relbase_valid) { const char *basename = BLI_path_basename(G.main->name); int len = strlen(basename) - 6; - BLI_snprintf(path, sizeof(path), "%.*s-%d.blend", len, basename, pid); + BLI_snprintf(path, sizeof(path), "%.*s.blend", len, basename); } else { BLI_snprintf(path, sizeof(path), "%d.blend", pid); -- cgit v1.2.3 From dd0604c6066a46a72fccc185bbbc592ff76c7052 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 31 Mar 2015 00:21:04 +0500 Subject: Fix T44193: Hair intersection with duplis causes flickering It was an issue with what bounds to use for BVH node during construction. Also corrected case when there are all 4 primitive types in the range and also there're objects in the same range. --- intern/cycles/bvh/bvh_build.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index cb389b78049..5baf94918b4 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -577,17 +577,22 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range) return new InnerNode(range.bounds(), leaves[0], leaves[1]); } else if(num_leaves == 3) { - BoundBox inner_bounds = merge(bounds[1], bounds[2]); + BoundBox inner_bounds = merge(leaves[1]->m_bounds, leaves[2]->m_bounds); BVHNode *inner = new InnerNode(inner_bounds, leaves[1], leaves[2]); return new InnerNode(range.bounds(), leaves[0], inner); - } else /*if(num_leaves == 4)*/ { + } else { /* Shpuld be doing more branches if more primitive types added. */ - assert(num_leaves == 4); - BoundBox inner_bounds_a = merge(bounds[0], bounds[1]); - BoundBox inner_bounds_b = merge(bounds[2], bounds[3]); + assert(num_leaves <= 5); + BoundBox inner_bounds_a = merge(leaves[0]->m_bounds, leaves[1]->m_bounds); + BoundBox inner_bounds_b = merge(leaves[2]->m_bounds, leaves[3]->m_bounds); BVHNode *inner_a = new InnerNode(inner_bounds_a, leaves[0], leaves[1]); BVHNode *inner_b = new InnerNode(inner_bounds_b, leaves[2], leaves[3]); - return new InnerNode(range.bounds(), inner_a, inner_b); + BoundBox inner_bounds_c = merge(inner_a->m_bounds, inner_b->m_bounds); + BVHNode *inner_c = new InnerNode(inner_bounds_c, inner_a, inner_b); + if(num_leaves == 5) { + return new InnerNode(range.bounds(), inner_c, leaves[4]); + } + return inner_c; } } -- cgit v1.2.3 From 660173ed72d9c69f6891d5ad05a8c4a35ece9c7c Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Mon, 30 Mar 2015 22:47:09 +0200 Subject: BGE: Fix: VehicleWrapper compiler warning. The return type of raise_exc_wheel() is bool, but the method return -1. The compiler will change the return type type to an int. This can cause some problems on 64bit systems. Reviewers: lordloki, sybren Reviewed By: lordloki, sybren Differential Revision: https://developer.blender.org/D1204 --- source/gameengine/Ketsji/KX_VehicleWrapper.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index d10e51a491a..237f485134a 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -54,19 +54,20 @@ KX_VehicleWrapper::~KX_VehicleWrapper() #ifdef WITH_PYTHON -static bool raise_exc_wheel(PHY_IVehicle* vehicle, int i, const char *method) +static bool raise_exc_wheel(PHY_IVehicle *vehicle, int i, const char *method) { - if ( i < 0 || i >= vehicle->GetNumWheels() ) { + if (i < 0 || i >= vehicle->GetNumWheels()) { PyErr_Format(PyExc_ValueError, - "%s(...): wheel index %d out of range (0 to %d).", method, i, vehicle->GetNumWheels()-1); - return -1; - } else { - return 0; + "%s(...): wheel index %d out of range (0 to %d).", method, i, vehicle->GetNumWheels() - 1); + return true; + } + else { + return false; } } #define WHEEL_INDEX_CHECK_OR_RETURN(i, method) \ - if (raise_exc_wheel(m_vehicle, i, method) == -1) { return NULL; } (void)0 + if (raise_exc_wheel(m_vehicle, i, method)) {return NULL;} (void)0 PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args) -- cgit v1.2.3 From c16a8983efba9ecacd8da408d03c37a55483e528 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 29 Mar 2015 04:44:05 +1100 Subject: Corrective Smooth Modifier (aka delta-mush) This modifier can be used to correct bad deformations, Original patch D1183 by @sazerac, with own modifications --- .../startup/bl_ui/properties_data_modifier.py | 25 + source/blender/blenkernel/BKE_editmesh.h | 1 + source/blender/blenkernel/BKE_mesh.h | 2 +- source/blender/blenkernel/intern/editmesh.c | 18 + source/blender/blenkernel/intern/mesh.c | 2 +- source/blender/blenloader/intern/readfile.c | 14 + source/blender/blenloader/intern/writefile.c | 7 + source/blender/editors/object/object_intern.h | 1 + source/blender/editors/object/object_modifier.c | 67 ++ source/blender/editors/object/object_ops.c | 1 + .../blender/editors/space_outliner/outliner_draw.c | 1 + source/blender/makesdna/DNA_modifier_types.h | 43 ++ source/blender/makesrna/RNA_access.h | 1 + source/blender/makesrna/intern/rna_modifier.c | 116 ++++ source/blender/modifiers/CMakeLists.txt | 1 + source/blender/modifiers/MOD_modifiertypes.h | 1 + .../modifiers/intern/MOD_correctivesmooth.c | 768 +++++++++++++++++++++ source/blender/modifiers/intern/MOD_util.c | 1 + 18 files changed, 1068 insertions(+), 2 deletions(-) create mode 100644 source/blender/modifiers/intern/MOD_correctivesmooth.c diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index f22976f5b6d..a3cf079f915 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -1386,6 +1386,31 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): sub.active = has_vgroup sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT') + def CORRECTIVE_SMOOTH(self, layout, ob, md): + is_bind = md.is_bind + + layout.prop(md, "iterations") + layout.prop(md, "lambda_factor", text="Factor") + + row = layout.row() + row.prop(md, "smooth_type") + + split = layout.split() + + col = split.column() + col.label(text="Vertex Group:") + row = col.row(align=True) + row.prop_search(md, "vertex_group", ob, "vertex_groups", text="") + row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT') + + col = split.column() + col.prop(md, "use_only_smooth") + col.prop(md, "use_pin_boundary") + + layout.prop(md, "rest_source") + if md.rest_source == 'BIND': + layout.operator("object.correctivesmooth_bind", text="Unbind" if is_bind else "Bind") + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index d0b94117b23..d350eea7ac7 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -92,6 +92,7 @@ void BKE_editmesh_update_linked_customdata(BMEditMesh *em); void BKE_editmesh_color_free(BMEditMesh *em); void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype); +float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3]; /* editderivedmesh.c */ /* should really be defined in editmesh.c, but they use 'EditDerivedBMesh' */ diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 5cf557a07e5..05c20410458 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -119,7 +119,7 @@ bool BKE_mesh_uv_cdlayer_rename_index(struct Mesh *me, const int poly_index, con const char *new_name, const bool do_tessface); bool BKE_mesh_uv_cdlayer_rename(struct Mesh *me, const char *old_name, const char *new_name, bool do_tessface); -float (*BKE_mesh_vertexCos_get(struct Mesh *me, int *r_numVerts))[3]; +float (*BKE_mesh_vertexCos_get(const struct Mesh *me, int *r_numVerts))[3]; void BKE_mesh_calc_normals_split(struct Mesh *mesh); void BKE_mesh_split_faces(struct Mesh *mesh); diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c index 2247b91df1d..87a5c6f149f 100644 --- a/source/blender/blenkernel/intern/editmesh.c +++ b/source/blender/blenkernel/intern/editmesh.c @@ -246,3 +246,21 @@ void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype) break; } } + +float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3] +{ + BMIter iter; + BMVert *eve; + float (*orco)[3]; + int i; + + orco = MEM_mallocN(em->bm->totvert * sizeof(*orco), __func__); + + BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { + copy_v3_v3(orco[i], eve->co); + } + + *r_numVerts = em->bm->totvert; + + return orco; +} diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 8ebc318ff9e..adce6e15732 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1805,7 +1805,7 @@ void BKE_mesh_smooth_flag_set(Object *meshOb, int enableSmooth) * Return a newly MEM_malloc'd array of all the mesh vertex locations * \note \a r_numVerts may be NULL */ -float (*BKE_mesh_vertexCos_get(Mesh *me, int *r_numVerts))[3] +float (*BKE_mesh_vertexCos_get(const Mesh *me, int *r_numVerts))[3] { int i, numVerts = me->totvert; float (*cos)[3] = MEM_mallocN(sizeof(*cos) * numVerts, "vertexcos1"); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index b8c3bffae0f..b0aa47787b6 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4949,6 +4949,20 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) } lmd->cache_system = NULL; } + else if (md->type == eModifierType_CorrectiveSmooth) { + CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData*)md; + + if (csmd->bind_coords) { + csmd->bind_coords = newdataadr(fd, csmd->bind_coords); + if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) { + BLI_endian_switch_float_array((float *)csmd->bind_coords, csmd->bind_coords_num * 3); + } + } + + /* runtime only */ + csmd->delta_cache = NULL; + csmd->delta_cache_num = 0; + } } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index bc1bc9c7759..afc53f343f1 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1620,6 +1620,13 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) writedata(wd, DATA, sizeof(float)*lmd->total_verts * 3, lmd->vertexco); } + else if (md->type == eModifierType_CorrectiveSmooth) { + CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md; + + if (csmd->bind_coords) { + writedata(wd, DATA, sizeof(float[3]) * csmd->bind_coords_num, csmd->bind_coords); + } + } } } diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index db040bc2017..d535457fc5b 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -174,6 +174,7 @@ void OBJECT_OT_multires_higher_levels_delete(struct wmOperatorType *ot); void OBJECT_OT_multires_base_apply(struct wmOperatorType *ot); void OBJECT_OT_multires_external_save(struct wmOperatorType *ot); void OBJECT_OT_multires_external_pack(struct wmOperatorType *ot); +void OBJECT_OT_correctivesmooth_bind(struct wmOperatorType *ot); void OBJECT_OT_meshdeform_bind(struct wmOperatorType *ot); void OBJECT_OT_explode_refresh(struct wmOperatorType *ot); void OBJECT_OT_ocean_bake(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index f9315214557..ad02f78e7b6 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -1815,6 +1815,73 @@ void OBJECT_OT_skin_armature_create(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; edit_modifier_properties(ot); } +/************************ delta mush bind operator *********************/ + +static int correctivesmooth_poll(bContext *C) +{ + return edit_modifier_poll_generic(C, &RNA_CorrectiveSmoothModifier, 0); +} + +static int correctivesmooth_bind_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = ED_object_active_context(C); + CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)edit_modifier_property_get(op, ob, eModifierType_CorrectiveSmooth); + bool is_bind; + + if (!csmd) { + return OPERATOR_CANCELLED; + } + + if (!modifier_isEnabled(scene, &csmd->modifier, eModifierMode_Realtime)) { + BKE_report(op->reports, RPT_ERROR, "Modifier is disabled"); + return OPERATOR_CANCELLED; + } + + is_bind = (csmd->bind_coords != NULL); + + MEM_SAFE_FREE(csmd->bind_coords); + MEM_SAFE_FREE(csmd->delta_cache); + + if (is_bind) { + /* toggle off */ + csmd->bind_coords_num = 0; + } + else { + /* signal to modifier to recalculate */ + csmd->bind_coords_num = (unsigned int)-1; + } + + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + + return OPERATOR_FINISHED; +} + +static int correctivesmooth_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + if (edit_modifier_invoke_properties(C, op)) + return correctivesmooth_bind_exec(C, op); + else + return OPERATOR_CANCELLED; +} + +void OBJECT_OT_correctivesmooth_bind(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Corrective Smooth Bind"; + ot->description = "Bind base pose in delta mush modifier"; + ot->idname = "OBJECT_OT_correctivesmooth_bind"; + + /* api callbacks */ + ot->poll = correctivesmooth_poll; + ot->invoke = correctivesmooth_bind_invoke; + ot->exec = correctivesmooth_bind_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + edit_modifier_properties(ot); +} /************************ mdef bind operator *********************/ diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 15eb9090ce5..422f0c12e51 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -144,6 +144,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_skin_radii_equalize); WM_operatortype_append(OBJECT_OT_skin_armature_create); + WM_operatortype_append(OBJECT_OT_correctivesmooth_bind); WM_operatortype_append(OBJECT_OT_meshdeform_bind); WM_operatortype_append(OBJECT_OT_explode_refresh); WM_operatortype_append(OBJECT_OT_ocean_bake); diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 873b5f5319f..420b73cee86 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1121,6 +1121,7 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto UI_icon_draw(x, y, ICON_MOD_BEVEL); break; case eModifierType_Smooth: case eModifierType_LaplacianSmooth: + case eModifierType_CorrectiveSmooth: UI_icon_draw(x, y, ICON_MOD_SMOOTH); break; case eModifierType_SimpleDeform: UI_icon_draw(x, y, ICON_MOD_SIMPLEDEFORM); break; diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index b32b228fda4..f3c61f0ab6c 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -84,6 +84,7 @@ typedef enum ModifierType { eModifierType_Wireframe = 48, eModifierType_DataTransfer = 49, eModifierType_NormalEdit = 50, + eModifierType_CorrectiveSmooth = 51, NUM_MODIFIER_TYPES } ModifierType; @@ -1288,6 +1289,48 @@ enum { MOD_LAPLACIANSMOOTH_NORMALIZED = (1 << 5), }; + +typedef struct CorrectiveSmoothModifierData { + ModifierData modifier; + + /* positions set during 'bind' operator + * use for MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND */ + float (*bind_coords)[3]; + + /* note: -1 is used to bind */ + unsigned int bind_coords_num; + + float lambda; + short repeat, flag; + char smooth_type, rest_source; + char pad[2]; + + char defgrp_name[64]; /* MAX_VGROUP_NAME */ + + /* runtime-only cache (delta's between), + * delta's between the original positions and the smoothed positions */ + float (*delta_cache)[3]; + unsigned int delta_cache_num; + char pad2[4]; +} CorrectiveSmoothModifierData; + +enum { + MOD_CORRECTIVESMOOTH_SMOOTH_SIMPLE = 0, + MOD_CORRECTIVESMOOTH_SMOOTH_LENGTH_WEIGHT = 1, +}; + +enum { + MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO = 0, + MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND = 1, +}; + +/* Corrective Smooth modifier flags */ +enum { + MOD_CORRECTIVESMOOTH_INVERT_VGROUP = (1 << 0), + MOD_CORRECTIVESMOOTH_ONLY_SMOOTH = (1 << 1), + MOD_CORRECTIVESMOOTH_PIN_BOUNDARY = (1 << 2), +}; + typedef struct UVWarpModifierData { ModifierData modifier; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 577f27f564e..8aa1bc59b43 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -202,6 +202,7 @@ extern StructRNA RNA_DampedTrackConstraint; extern StructRNA RNA_DataTransferModifier; extern StructRNA RNA_DecimateModifier; extern StructRNA RNA_DelaySensor; +extern StructRNA RNA_CorrectiveSmoothModifier; extern StructRNA RNA_DisplaceModifier; extern StructRNA RNA_DisplaySafeAreas; extern StructRNA RNA_DistortedNoiseTexture; diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index bde8fd73d85..635336004f9 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -92,6 +92,7 @@ EnumPropertyItem modifier_type_items[] = { {0, "", 0, N_("Deform"), ""}, {eModifierType_Armature, "ARMATURE", ICON_MOD_ARMATURE, "Armature", ""}, {eModifierType_Cast, "CAST", ICON_MOD_CAST, "Cast", ""}, + {eModifierType_CorrectiveSmooth, "CORRECTIVE_SMOOTH", ICON_MOD_SMOOTH, "Corrective Smooth", ""}, {eModifierType_Curve, "CURVE", ICON_MOD_CURVE, "Curve", ""}, {eModifierType_Displace, "DISPLACE", ICON_MOD_DISPLACE, "Displace", ""}, {eModifierType_Hook, "HOOK", ICON_HOOK, "Hook", ""}, @@ -377,6 +378,8 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr) return &RNA_DataTransferModifier; case eModifierType_NormalEdit: return &RNA_NormalEditModifier; + case eModifierType_CorrectiveSmooth: + return &RNA_CorrectiveSmoothModifier; /* Default */ case eModifierType_None: case eModifierType_ShapeKey: @@ -444,6 +447,7 @@ RNA_MOD_VGROUP_NAME_SET(Cast, defgrp_name); RNA_MOD_VGROUP_NAME_SET(Curve, name); RNA_MOD_VGROUP_NAME_SET(DataTransfer, defgrp_name); RNA_MOD_VGROUP_NAME_SET(Decimate, defgrp_name); +RNA_MOD_VGROUP_NAME_SET(CorrectiveSmooth, defgrp_name); RNA_MOD_VGROUP_NAME_SET(Displace, defgrp_name); RNA_MOD_VGROUP_NAME_SET(Hook, name); RNA_MOD_VGROUP_NAME_SET(LaplacianDeform, anchor_grp_name); @@ -1034,6 +1038,33 @@ static EnumPropertyItem *rna_DataTransferModifier_mix_mode_itemf(bContext *C, Po return item; } +static void rna_CorrectiveSmoothModifier_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)ptr->data; + + MEM_SAFE_FREE(csmd->delta_cache); + + rna_Modifier_update(bmain, scene, ptr); +} + +static void rna_CorrectiveSmoothModifier_rest_source_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)ptr->data; + + if (csmd->rest_source != MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) { + MEM_SAFE_FREE(csmd->bind_coords); + csmd->bind_coords_num = 0; + } + + rna_CorrectiveSmoothModifier_update(bmain, scene, ptr); +} + +static int rna_CorrectiveSmoothModifier_is_bind_get(PointerRNA *ptr) +{ + CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)ptr->data; + return (csmd->bind_coords != NULL); +} + #else static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const char type[]) @@ -2111,6 +2142,90 @@ static void rna_def_modifier_smooth(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update"); } + +static void rna_def_modifier_correctivesmooth(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem modifier_smooth_type_items[] = { + {MOD_CORRECTIVESMOOTH_SMOOTH_SIMPLE, "SIMPLE", 0, "Simple", + "Use the average of adjacent edge-vertices"}, + {MOD_CORRECTIVESMOOTH_SMOOTH_LENGTH_WEIGHT, "LENGTH_WEIGHTED", 0, "Length Weight", + "Use the average of adjacent edge-vertices weighted by their length"}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem modifier_rest_source_items[] = { + {MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO, "ORCO", 0, "Original Coords", + "Use base mesh vert coords as the rest position"}, + {MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND, "BIND", 0, "Bind Coords", + "Use bind vert coords for rest position"}, + {0, NULL, 0, NULL, NULL} + }; + + srna = RNA_def_struct(brna, "CorrectiveSmoothModifier", "Modifier"); + RNA_def_struct_ui_text(srna, "Corrective Smooth Modifier", "Correct distortion caused by deformation"); + RNA_def_struct_sdna(srna, "CorrectiveSmoothModifierData"); + RNA_def_struct_ui_icon(srna, ICON_MOD_SMOOTH); + + prop = RNA_def_property(srna, "lambda_factor", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "lambda"); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0, 1.0, 5, 3); + RNA_def_property_ui_text(prop, "Lambda Factor", "Smooth factor effect"); + RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_update"); + + prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "repeat"); + RNA_def_property_ui_range(prop, 0, 200, 1, -1); + RNA_def_property_ui_text(prop, "Repeat", ""); + RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_update"); + + prop = RNA_def_property(srna, "rest_source", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "rest_source"); + RNA_def_property_enum_items(prop, modifier_rest_source_items); + RNA_def_property_ui_text(prop, "Rest Source", "Select the source of rest positions"); + RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_rest_source_update"); + + prop = RNA_def_property(srna, "smooth_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "smooth_type"); + RNA_def_property_enum_items(prop, modifier_smooth_type_items); + RNA_def_property_ui_text(prop, "Smooth Type", "Method used for smoothing"); + RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_update"); + + prop = RNA_def_property(srna, "invert_vertex_group", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_CORRECTIVESMOOTH_INVERT_VGROUP); + RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); + RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_update"); + + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "defgrp_name"); + RNA_def_property_ui_text(prop, "Vertex Group", + "Name of Vertex Group which determines influence of modifier per point"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_CorrectiveSmoothModifier_defgrp_name_set"); + RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_update"); + + prop = RNA_def_property(srna, "is_bind", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_ui_text(prop, "Bind current shape", ""); + RNA_def_property_boolean_funcs(prop, "rna_CorrectiveSmoothModifier_is_bind_get", NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "use_only_smooth", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_CORRECTIVESMOOTH_ONLY_SMOOTH); + RNA_def_property_ui_text(prop, "Only Smooth", + "Apply smoothing without reconstructing the surface"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "use_pin_boundary", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_CORRECTIVESMOOTH_PIN_BOUNDARY); + RNA_def_property_ui_text(prop, "Pin Boundaries", + "Excludes boundary vertices from being smoothed"); + RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_update"); +} + + static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna) { StructRNA *srna; @@ -4520,6 +4635,7 @@ void RNA_def_modifier(BlenderRNA *brna) rna_def_modifier_displace(brna); rna_def_modifier_uvproject(brna); rna_def_modifier_smooth(brna); + rna_def_modifier_correctivesmooth(brna); rna_def_modifier_cast(brna); rna_def_modifier_meshdeform(brna); rna_def_modifier_particlesystem(brna); diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 57e927fffed..1de3fc9eac0 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -51,6 +51,7 @@ set(SRC intern/MOD_cast.c intern/MOD_cloth.c intern/MOD_collision.c + intern/MOD_correctivesmooth.c intern/MOD_curve.c intern/MOD_datatransfer.c intern/MOD_decimate.c diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h index 66e613be68a..a5d96759952 100644 --- a/source/blender/modifiers/MOD_modifiertypes.h +++ b/source/blender/modifiers/MOD_modifiertypes.h @@ -83,6 +83,7 @@ extern ModifierTypeInfo modifierType_LaplacianDeform; extern ModifierTypeInfo modifierType_Wireframe; extern ModifierTypeInfo modifierType_DataTransfer; extern ModifierTypeInfo modifierType_NormalEdit; +extern ModifierTypeInfo modifierType_CorrectiveSmooth; /* MOD_util.c */ void modifier_type_init(ModifierTypeInfo *types[]); diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c new file mode 100644 index 00000000000..82c1d6f2ec8 --- /dev/null +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -0,0 +1,768 @@ +/* +* ***** BEGIN GPL LICENSE BLOCK ***** +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* The Original Code is Copyright (C) 2015 by the Blender Foundation. +* All rights reserved. +* +* Contributor(s): Jack Simpson, +* Campbell Barton +* +* ***** END GPL LICENSE BLOCK ***** +* +*/ + +/** \file blender/modifiers/intern/MOD_correctivesmooth.c + * \ingroup modifiers + * + * Method of smoothing deformation, also known as 'delta-mush'. + */ + +#include "DNA_scene_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" + +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "MEM_guardedalloc.h" + +#include "BKE_cdderivedmesh.h" +#include "BKE_deform.h" +#include "BKE_mesh.h" +#include "BKE_editmesh.h" + +#include "MOD_modifiertypes.h" +#include "MOD_util.h" + +#include "BLI_strict_flags.h" + + +// #define DEBUG_TIME + +#include "PIL_time.h" +#ifdef DEBUG_TIME +# include "PIL_time_utildefines.h" +#endif + +/* minor optimization, calculate this inline */ +#define USE_TANGENT_CALC_INLINE + +static void initData(ModifierData *md) +{ + CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md; + + csmd->bind_coords = NULL; + csmd->bind_coords_num = 0; + + csmd->lambda = 0.5f; + csmd->repeat = 5; + csmd->flag = 0; + csmd->smooth_type = MOD_CORRECTIVESMOOTH_SMOOTH_SIMPLE; + + csmd->defgrp_name[0] = '\0'; + + csmd->delta_cache = NULL; +} + + +static void copyData(ModifierData *md, ModifierData *target) +{ + CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md; + CorrectiveSmoothModifierData *tcsmd = (CorrectiveSmoothModifierData *)target; + + modifier_copyData_generic(md, target); + + if (csmd->bind_coords) { + tcsmd->bind_coords = MEM_dupallocN(csmd->bind_coords); + } + + tcsmd->delta_cache = NULL; + tcsmd->delta_cache_num = 0; +} + + +static void freeBind(CorrectiveSmoothModifierData *csmd) +{ + MEM_SAFE_FREE(csmd->bind_coords); + MEM_SAFE_FREE(csmd->delta_cache); + + csmd->bind_coords_num = 0; +} + + +static void freeData(ModifierData *md) +{ + CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md; + freeBind(csmd); +} + + +static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) +{ + CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md; + CustomDataMask dataMask = 0; + /* ask for vertex groups if we need them */ + if (csmd->defgrp_name[0]) { + dataMask |= CD_MASK_MDEFORMVERT; + } + return dataMask; +} + + +/* check individual weights for changes and cache values */ +static void dm_get_weights( + MDeformVert *dvert, const int defgrp_index, + const unsigned int numVerts, const bool use_invert_vgroup, + float *smooth_weights) +{ + unsigned int i; + + for (i = 0; i < numVerts; i++, dvert++) { + const float w = defvert_find_weight(dvert, defgrp_index); + + if (use_invert_vgroup == false) { + smooth_weights[i] = w; + } + else { + smooth_weights[i] = 1.0f - w; + } + } +} + + +static void dm_get_boundaries(DerivedMesh *dm, float *smooth_weights) +{ + const MPoly *mpoly = dm->getPolyArray(dm); + const MLoop *mloop = dm->getLoopArray(dm); + const MEdge *medge = dm->getEdgeArray(dm); + unsigned int mpoly_num, medge_num, i; + unsigned short *boundaries; + + mpoly_num = (unsigned int)dm->getNumPolys(dm); + medge_num = (unsigned int)dm->getNumEdges(dm); + + boundaries = MEM_callocN(medge_num * sizeof(*boundaries), __func__); + + /* count the number of adjacent faces */ + for (i = 0; i < mpoly_num; i++) { + const MPoly *p = &mpoly[i]; + const int totloop = p->totloop; + int j; + for (j = 0; j < totloop; j++) { + boundaries[mloop[p->loopstart + j].e]++; + } + } + + for (i = 0; i < medge_num; i++) { + if (boundaries[i] == 1) { + smooth_weights[medge[i].v1] = 0.0f; + smooth_weights[medge[i].v2] = 0.0f; + } + } + + MEM_freeN(boundaries); +} + + +/* -------------------------------------------------------------------- */ +/* Simple Weighted Smoothing + * + * (average of surrounding verts) + */ +static void smooth_iter__simple( + CorrectiveSmoothModifierData *csmd, DerivedMesh *dm, + float (*vertexCos)[3], unsigned int numVerts, + const float *smooth_weights, + unsigned int iterations) +{ + const float lambda = csmd->lambda; + unsigned int i; + + const unsigned int numEdges = (unsigned int)dm->getNumEdges(dm); + const MEdge *edges = dm->getEdgeArray(dm); + float *vertex_edge_count_div; + + struct SmoothingData_Simple { + float delta[3]; + } *smooth_data = MEM_callocN((size_t)numVerts * sizeof(*smooth_data), __func__); + + vertex_edge_count_div = MEM_callocN((size_t)numVerts * sizeof(float), __func__); + + /* calculate as floats to avoid int->float conversion in #smooth_iter */ + for (i = 0; i < numEdges; i++) { + vertex_edge_count_div[edges[i].v1] += 1.0f; + vertex_edge_count_div[edges[i].v2] += 1.0f; + } + + /* a little confusing, but we can include 'lambda' and smoothing weight + * here to avoid multiplying for every iteration */ + if (smooth_weights == NULL) { + for (i = 0; i < numVerts; i++) { + vertex_edge_count_div[i] = + lambda * (vertex_edge_count_div[i] ? (1.0f / vertex_edge_count_div[i]) : 1.0f); + } + } + else { + for (i = 0; i < numVerts; i++) { + vertex_edge_count_div[i] = + smooth_weights[i] * lambda * (vertex_edge_count_div[i] ? (1.0f / vertex_edge_count_div[i]) : 1.0f); + } + } + + /* -------------------------------------------------------------------- */ + /* Main Smoothing Loop */ + + while (iterations--) { + for (i = 0; i < numEdges; i++) { + struct SmoothingData_Simple *sd_v1; + struct SmoothingData_Simple *sd_v2; + float edge_dir[3]; + + sub_v3_v3v3(edge_dir, vertexCos[edges[i].v2], vertexCos[edges[i].v1]); + + sd_v1 = &smooth_data[edges[i].v1]; + sd_v2 = &smooth_data[edges[i].v2]; + + add_v3_v3(sd_v1->delta, edge_dir); + sub_v3_v3(sd_v2->delta, edge_dir); + } + + + for (i = 0; i < numVerts; i++) { + struct SmoothingData_Simple *sd = &smooth_data[i]; + madd_v3_v3fl(vertexCos[i], sd->delta, vertex_edge_count_div[i]); + /* zero for the next iteration (saves memset on entire array) */ + memset(sd, 0, sizeof(*sd)); + } + } + + MEM_freeN(vertex_edge_count_div); + MEM_freeN(smooth_data); +} + + +/* -------------------------------------------------------------------- */ +/* Edge-Length Weighted Smoothing + */ +static void smooth_iter__length_weight( + CorrectiveSmoothModifierData *csmd, DerivedMesh *dm, + float (*vertexCos)[3], unsigned int numVerts, + const float *smooth_weights, + unsigned int iterations) +{ + const float eps = FLT_EPSILON * 10.0f; + const unsigned int numEdges = (unsigned int)dm->getNumEdges(dm); + /* note: the way this smoothing method works, its approx half as strong as the simple-smooth, + * and 2.0 rarely spikes, double the value for consistent behavior. */ + const float lambda = csmd->lambda * 2.0f; + const MEdge *edges = dm->getEdgeArray(dm); + float *vertex_edge_count; + unsigned int i; + + struct SmoothingData_Weighted { + float delta[3]; + float edge_length_sum; + } *smooth_data = MEM_callocN((size_t)numVerts * sizeof(*smooth_data), __func__); + + + /* calculate as floats to avoid int->float conversion in #smooth_iter */ + vertex_edge_count = MEM_callocN((size_t)numVerts * sizeof(float), __func__); + for (i = 0; i < numEdges; i++) { + vertex_edge_count[edges[i].v1] += 1.0f; + vertex_edge_count[edges[i].v2] += 1.0f; + } + + + /* -------------------------------------------------------------------- */ + /* Main Smoothing Loop */ + + while (iterations--) { + for (i = 0; i < numEdges; i++) { + struct SmoothingData_Weighted *sd_v1; + struct SmoothingData_Weighted *sd_v2; + float edge_dir[3]; + float edge_dist; + + sub_v3_v3v3(edge_dir, vertexCos[edges[i].v2], vertexCos[edges[i].v1]); + edge_dist = len_v3(edge_dir); + + /* weight by distance */ + mul_v3_fl(edge_dir, edge_dist); + + + sd_v1 = &smooth_data[edges[i].v1]; + sd_v2 = &smooth_data[edges[i].v2]; + + add_v3_v3(sd_v1->delta, edge_dir); + sub_v3_v3(sd_v2->delta, edge_dir); + + sd_v1->edge_length_sum += edge_dist; + sd_v2->edge_length_sum += edge_dist; + } + + if (smooth_weights == NULL) { + /* fast-path */ + for (i = 0; i < numVerts; i++) { + struct SmoothingData_Weighted *sd = &smooth_data[i]; + /* divide by sum of all neighbour distances (weighted) and amount of neighbours, (mean average) */ + const float div = sd->edge_length_sum * vertex_edge_count[i]; + if (div > eps) { +#if 0 + /* first calculate the new location */ + mul_v3_fl(sd->delta, 1.0f / div); + /* then interpolate */ + madd_v3_v3fl(vertexCos[i], sd->delta, lambda); +#else + /* do this in one step */ + madd_v3_v3fl(vertexCos[i], sd->delta, lambda / div); +#endif + } + /* zero for the next iteration (saves memset on entire array) */ + memset(sd, 0, sizeof(*sd)); + } + } + else { + for (i = 0; i < numVerts; i++) { + struct SmoothingData_Weighted *sd = &smooth_data[i]; + const float div = sd->edge_length_sum * vertex_edge_count[i]; + if (div > eps) { + const float lambda_w = lambda * smooth_weights[i]; + madd_v3_v3fl(vertexCos[i], sd->delta, lambda_w / div); + } + + memset(sd, 0, sizeof(*sd)); + } + } + } + + MEM_freeN(vertex_edge_count); + MEM_freeN(smooth_data); +} + + +static void smooth_iter( + CorrectiveSmoothModifierData *csmd, DerivedMesh *dm, + float (*vertexCos)[3], unsigned int numVerts, + const float *smooth_weights, + unsigned int iterations) +{ + switch (csmd->smooth_type) { + case MOD_CORRECTIVESMOOTH_SMOOTH_LENGTH_WEIGHT: + smooth_iter__length_weight(csmd, dm, vertexCos, numVerts, smooth_weights, iterations); + break; + + /* case MOD_CORRECTIVESMOOTH_SMOOTH_SIMPLE: */ + default: + smooth_iter__simple(csmd, dm, vertexCos, numVerts, smooth_weights, iterations); + break; + } +} + +static void smooth_verts( + CorrectiveSmoothModifierData *csmd, DerivedMesh *dm, + MDeformVert *dvert, const int defgrp_index, + float (*vertexCos)[3], unsigned int numVerts) +{ + float *smooth_weights = NULL; + + if (dvert || (csmd->flag & MOD_CORRECTIVESMOOTH_PIN_BOUNDARY)) { + + smooth_weights = MEM_mallocN(numVerts * sizeof(float), __func__); + + if (dvert) { + dm_get_weights( + dvert, defgrp_index, + numVerts, (csmd->flag & MOD_CORRECTIVESMOOTH_INVERT_VGROUP) != 0, + smooth_weights); + } + else { + fill_vn_fl(smooth_weights, (int)numVerts, 1.0f); + } + + if (csmd->flag & MOD_CORRECTIVESMOOTH_PIN_BOUNDARY) { + dm_get_boundaries(dm, smooth_weights); + } + } + + smooth_iter(csmd, dm, vertexCos, numVerts, smooth_weights, (unsigned int)csmd->repeat); + + if (smooth_weights) { + MEM_freeN(smooth_weights); + } +} + +/** + * finalize after accumulation. + */ +static void calc_tangent_ortho(float ts[3][3]) +{ + float v_tan_a[3], v_tan_b[3]; + float t_vec_a[3], t_vec_b[3]; + + normalize_v3(ts[2]); + + copy_v3_v3(v_tan_a, ts[0]); + copy_v3_v3(v_tan_b, ts[1]); + + cross_v3_v3v3(ts[1], ts[2], v_tan_a); + mul_v3_fl(ts[1], dot_v3v3(ts[1], v_tan_b) < 0.0f ? -1.0f : 1.0f); + + /* orthognalise tangent */ + mul_v3_v3fl(t_vec_a, ts[2], dot_v3v3(ts[2], v_tan_a)); + sub_v3_v3v3(ts[0], v_tan_a, t_vec_a); + + /* orthognalise bitangent */ + mul_v3_v3fl(t_vec_a, ts[2], dot_v3v3(ts[2], ts[1])); + mul_v3_v3fl(t_vec_b, ts[0], dot_v3v3(ts[0], ts[1]) / dot_v3v3(v_tan_a, v_tan_a)); + sub_v3_v3(ts[1], t_vec_a); + sub_v3_v3(ts[1], t_vec_b); + + normalize_v3(ts[0]); + normalize_v3(ts[1]); +} + +/** + * accumulate edge-vectors from all polys. + */ +static void calc_tangent_loop_accum( + const float v_dir_prev[3], + const float v_dir_next[3], + float r_tspace[3][3]) +{ + add_v3_v3v3(r_tspace[1], v_dir_prev, v_dir_next); + + if (compare_v3v3(v_dir_prev, v_dir_next, FLT_EPSILON * 10.0f) == false) { + const float weight = fabsf(acosf(dot_v3v3(v_dir_next, v_dir_prev))); + float nor[3]; + + cross_v3_v3v3(nor, v_dir_prev, v_dir_next); + normalize_v3(nor); + + cross_v3_v3v3(r_tspace[0], r_tspace[1], nor); + + mul_v3_fl(nor, weight); + /* accumulate weighted normals */ + add_v3_v3(r_tspace[2], nor); + } +} + + +static void calc_tangent_spaces( + DerivedMesh *dm, float (*vertexCos)[3], + float (*r_tangent_spaces)[3][3]) +{ + const unsigned int mpoly_num = (unsigned int)dm->getNumPolys(dm); +#ifndef USE_TANGENT_CALC_INLINE + const unsigned int mvert_num = (unsigned int)dm->getNumVerts(dm); +#endif + const MPoly *mpoly = dm->getPolyArray(dm); + const MLoop *mloop = dm->getLoopArray(dm); + unsigned int i; + + for (i = 0; i < mpoly_num; i++) { + const MPoly *mp = &mpoly[i]; + const MLoop *l_next = &mloop[mp->loopstart]; + const MLoop *l_term = l_next + mp->totloop; + const MLoop *l_prev = l_term - 2; + const MLoop *l_curr = l_term - 1; + + /* loop directions */ + float v_dir_prev[3], v_dir_next[3]; + + /* needed entering the loop */ + sub_v3_v3v3(v_dir_prev, vertexCos[l_prev->v], vertexCos[l_curr->v]); + normalize_v3(v_dir_prev); + + for (; + l_next != l_term; + l_prev = l_curr, l_curr = l_next, l_next++) + { + float (*ts)[3] = r_tangent_spaces[l_curr->v]; + + /* re-use the previous value */ +#if 0 + sub_v3_v3v3(v_dir_prev, vertexCos[l_prev->v], vertexCos[l_curr->v]); + normalize_v3(v_dir_prev); +#endif + sub_v3_v3v3(v_dir_next, vertexCos[l_curr->v], vertexCos[l_next->v]); + normalize_v3(v_dir_next); + + calc_tangent_loop_accum(v_dir_prev, v_dir_next, ts); + + copy_v3_v3(v_dir_prev, v_dir_next); + } + } + + /* do inline */ +#ifndef USE_TANGENT_CALC_INLINE + for (i = 0; i < mvert_num; i++) { + float (*ts)[3] = r_tangent_spaces[i]; + calc_tangent_ortho(ts); + } +#endif +} + +/** + * This calculates #CorrectiveSmoothModifierData.delta_cache + * It's not run on every update (during animation for example). + */ +static void calc_deltas( + CorrectiveSmoothModifierData *csmd, DerivedMesh *dm, + MDeformVert *dvert, const int defgrp_index, + const float (*rest_coords)[3], unsigned int numVerts) +{ + float (*smooth_vertex_coords)[3] = MEM_dupallocN(rest_coords); + float (*tangent_spaces)[3][3]; + unsigned int i; + + tangent_spaces = MEM_callocN((size_t)(numVerts) * sizeof(float[3][3]), __func__); + + if (csmd->delta_cache_num != numVerts) { + MEM_SAFE_FREE(csmd->delta_cache); + } + + /* allocate deltas if they have not yet been allocated, otheriwse we will just write over them */ + if (!csmd->delta_cache) { + csmd->delta_cache_num = numVerts; + csmd->delta_cache = MEM_mallocN((size_t)numVerts * sizeof(float[3]), __func__); + } + + smooth_verts(csmd, dm, dvert, defgrp_index, smooth_vertex_coords, numVerts); + + calc_tangent_spaces(dm, smooth_vertex_coords, tangent_spaces); + + for (i = 0; i < numVerts; i++) { + float imat[3][3], delta[3]; + +#ifdef USE_TANGENT_CALC_INLINE + calc_tangent_ortho(tangent_spaces[i]); +#endif + + sub_v3_v3v3(delta, rest_coords[i], smooth_vertex_coords[i]); + if (UNLIKELY(!invert_m3_m3(imat, tangent_spaces[i]))) { + transpose_m3_m3(imat, tangent_spaces[i]); + } + mul_v3_m3v3(csmd->delta_cache[i], imat, delta); + } + + MEM_freeN(tangent_spaces); + MEM_freeN(smooth_vertex_coords); +} + + +static void correctivesmooth_modifier_do( + ModifierData *md, Object *ob, DerivedMesh *dm, + float (*vertexCos)[3], unsigned int numVerts, + struct BMEditMesh *em) +{ + CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md; + + const bool force_delta_cache_update = + /* XXX, take care! if mesh data its self changes we need to forcefully recalculate deltas */ + ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO) && + (((ID *)ob->data)->flag & LIB_ID_RECALC)); + + bool use_only_smooth = (csmd->flag & MOD_CORRECTIVESMOOTH_ONLY_SMOOTH) != 0; + MDeformVert *dvert = NULL; + int defgrp_index; + + modifier_get_vgroup(ob, dm, csmd->defgrp_name, &dvert, &defgrp_index); + + /* if rest bind_coords not are defined, set them (only run during bind) */ + if ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) && + /* signal to recalculate, whoever sets MUST also free bind coords */ + (csmd->bind_coords_num == (unsigned int)-1)) + { + BLI_assert(csmd->bind_coords == NULL); + csmd->bind_coords = MEM_dupallocN(vertexCos); + csmd->bind_coords_num = numVerts; + BLI_assert(csmd->bind_coords != NULL); + } + + if (UNLIKELY(use_only_smooth)) { + smooth_verts(csmd, dm, dvert, defgrp_index, vertexCos, numVerts); + return; + } + + if ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) && (csmd->bind_coords == NULL)) { + modifier_setError(md, "Bind data required"); + goto error; + } + + /* If the number of verts has changed, the bind is invalid, so we do nothing */ + if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) { + if (csmd->bind_coords_num != numVerts) { + modifier_setError(md, "Bind vertex count mismatch: %d to %d", csmd->bind_coords_num, numVerts); + goto error; + } + } + else { + /* MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO */ + if (ob->type != OB_MESH) { + modifier_setError(md, "Object is not a mesh"); + goto error; + } + else { + int me_numVerts = (em) ? em->bm->totvert : ((Mesh *)ob->data)->totvert; + + if ((unsigned int)me_numVerts != numVerts) { + modifier_setError(md, "Original vertex count mismatch: %d to %d", me_numVerts, numVerts); + goto error; + } + } + } + + /* check to see if our deltas are still valid */ + if (!csmd->delta_cache || (csmd->delta_cache_num != numVerts) || force_delta_cache_update) { + const float (*rest_coords)[3]; + bool is_rest_coords_alloc = false; + + if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) { + /* caller needs to do sanity check here */ + csmd->bind_coords_num = numVerts; + rest_coords = (const float (*)[3])csmd->bind_coords; + } + else { + int me_numVerts; + rest_coords = (const float (*)[3]) ((em) ? + BKE_editmesh_vertexCos_get_orco(em, &me_numVerts) : + BKE_mesh_vertexCos_get(ob->data, &me_numVerts)); + + BLI_assert((unsigned int)me_numVerts == numVerts); + is_rest_coords_alloc = true; + } + +#ifdef DEBUG_TIME + TIMEIT_START(corrective_smooth_deltas); +#endif + + calc_deltas(csmd, dm, dvert, defgrp_index, rest_coords, numVerts); + +#ifdef DEBUG_TIME + TIMEIT_END(corrective_smooth_deltas); +#endif + if (is_rest_coords_alloc) { + MEM_freeN((void *)rest_coords); + } + } + + if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) { + /* this could be a check, but at this point it _must_ be valid */ + BLI_assert(csmd->bind_coords_num == numVerts && csmd->delta_cache); + } + + +#ifdef DEBUG_TIME + TIMEIT_START(corrective_smooth); +#endif + + /* do the actual delta mush */ + smooth_verts(csmd, dm, dvert, defgrp_index, vertexCos, numVerts); + + { + unsigned int i; + + float (*tangent_spaces)[3][3]; + + /* calloc, since values are accumulated */ + tangent_spaces = MEM_callocN((size_t)numVerts * sizeof(float[3][3]), __func__); + + calc_tangent_spaces(dm, vertexCos, tangent_spaces); + + for (i = 0; i < numVerts; i++) { + float delta[3]; + +#ifdef USE_TANGENT_CALC_INLINE + calc_tangent_ortho(tangent_spaces[i]); +#endif + + mul_v3_m3v3(delta, tangent_spaces[i], csmd->delta_cache[i]); + add_v3_v3(vertexCos[i], delta); + } + + MEM_freeN(tangent_spaces); + } + +#ifdef DEBUG_TIME + TIMEIT_END(corrective_smooth); +#endif + + return; + + /* when the modifier fails to execute */ +error: + MEM_SAFE_FREE(csmd->delta_cache); + csmd->delta_cache_num = 0; + +} + + +static void deformVerts( + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts, ModifierApplyFlag UNUSED(flag)) +{ + DerivedMesh *dm = get_dm(ob, NULL, derivedData, NULL, false, false); + + correctivesmooth_modifier_do(md, ob, dm, vertexCos, (unsigned int)numVerts, NULL); + + if (dm != derivedData) { + dm->release(dm); + } +} + + +static void deformVertsEM( + ModifierData *md, Object *ob, struct BMEditMesh *editData, + DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) +{ + DerivedMesh *dm = get_dm(ob, editData, derivedData, NULL, false, false); + + correctivesmooth_modifier_do(md, ob, dm, vertexCos, (unsigned int)numVerts, editData); + + if (dm != derivedData) { + dm->release(dm); + } +} + + +ModifierTypeInfo modifierType_CorrectiveSmooth = { + /* name */ "CorrectiveSmooth", + /* structName */ "CorrectiveSmoothModifierData", + /* structSize */ sizeof(CorrectiveSmoothModifierData), + /* type */ eModifierTypeType_OnlyDeform, + /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_SupportsEditmode, + + /* copyData */ copyData, + /* deformVerts */ deformVerts, + /* deformMatrices */ NULL, + /* deformVertsEM */ deformVertsEM, + /* deformMatricesEM */ NULL, + /* applyModifier */ NULL, + /* applyModifierEM */ NULL, + /* initData */ initData, + /* requiredDataMask */ requiredDataMask, + /* freeData */ freeData, + /* isDisabled */ NULL, + /* updateDepgraph */ NULL, + /* dependsOnTime */ NULL, + /* dependsOnNormals */ NULL, + /* foreachObjectLink */ NULL, + /* foreachIDLink */ NULL, + /* foreachTexLink */ NULL, +}; diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index eac2f24d064..be6f7af7791 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -306,5 +306,6 @@ void modifier_type_init(ModifierTypeInfo *types[]) INIT_TYPE(Wireframe); INIT_TYPE(DataTransfer); INIT_TYPE(NormalEdit); + INIT_TYPE(CorrectiveSmooth); #undef INIT_TYPE } -- cgit v1.2.3 From 4153ff3610241cc4e4a73326eca49ee2797ee125 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 31 Mar 2015 08:36:48 +0200 Subject: Fix T44201: Crash Deleting Hierarchy in Outliner Typical error using '->next' member of a freed linked list item. A bit trickier even here, since we have some recursion... Trivial fix for nasty crasher, safe for 2.74 imho? --- source/blender/editors/space_outliner/outliner_tools.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 64e00589712..fc6717f47be 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -694,23 +694,26 @@ static void outliner_do_data_operation(SpaceOops *soops, int type, int event, Li } } -static void outline_delete_hierarchy(bContext *C, Scene *scene, Base *base) +static Base *outline_delete_hierarchy(bContext *C, Scene *scene, Base *base) { - Base *child_base; + Base *child_base, *base_next; Object *parent; if (!base) { - return; + return NULL; } - for (child_base = scene->base.first; child_base; child_base = child_base->next) { + for (child_base = scene->base.first; child_base; child_base = base_next) { + base_next = child_base->next; for (parent = child_base->object->parent; parent && (parent != base->object); parent = parent->parent); if (parent) { - outline_delete_hierarchy(C, scene, child_base); + base_next = outline_delete_hierarchy(C, scene, child_base); } } + base_next = base->next; ED_base_object_free_and_unlink(CTX_data_main(C), scene, base); + return base_next; } static void object_delete_hierarchy_cb( -- cgit v1.2.3 From b98c7bcf3a6473491f116aefa1a82f45d28d3451 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 31 Mar 2015 11:42:39 +0200 Subject: Fix T44077 material update fails in textured mode when VBOs are off. The issue has been here since we changed drawing code for meshes to use vertex arrays instead of immediate mode when VBO was off. Basically we should now always invalidate the GPU objects regardless of the VBO setting in the preferences. The bug has been there since 2.73 at least, but what made it apparent now is that new version resets preferences and as an extension the VBO flag. Should be included in final 2.74 release --- source/blender/editors/render/render_update.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 4980e0bba80..d3d5cb12ac8 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -300,7 +300,7 @@ static void material_changed(Main *bmain, Material *ma) } /* find textured objects */ - if (texture_draw && !(U.gameflags & USER_DISABLE_VBO)) { + if (texture_draw) { for (ob = bmain->object.first; ob; ob = ob->id.next) { DerivedMesh *dm = ob->derivedFinal; Material ***material = give_matarar(ob); @@ -423,7 +423,7 @@ static void texture_changed(Main *bmain, Tex *tex) } /* find textured objects */ - if (texture_draw && !(U.gameflags & USER_DISABLE_VBO)) { + if (texture_draw) { for (ob = bmain->object.first; ob; ob = ob->id.next) { DerivedMesh *dm = ob->derivedFinal; Material ***material = give_matarar(ob); -- cgit v1.2.3 From 41f9cdc955d82bcf25abc86942f7bb9c98084db4 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 31 Mar 2015 18:57:17 +0500 Subject: Point master's submodules to v2.74 tag as well --- release/scripts/addons | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/scripts/addons b/release/scripts/addons index 3fc5b82c6bd..6cf8e325dba 160000 --- a/release/scripts/addons +++ b/release/scripts/addons @@ -1 +1 @@ -Subproject commit 3fc5b82c6bdba2f9c954fbf497621b9bb794a1bc +Subproject commit 6cf8e325dba9c5afa1cb2a7cbf62159dd049e9b6 -- cgit v1.2.3 From 66a028a5761c44fa37963443c78bd7baf04ff551 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 27 Mar 2015 15:23:39 +0100 Subject: Proportional editing for IPO editor - version ready for feedback by artists. This works by using the distance in the x axis only (usually artists want to influence nearby keyframes based on timing, not value). Tweaking handles is the same as tweaking the central handle. It's a bit ambiguous if proportional editing is really meaningful for handles but will leave that for artists to decide. --- release/scripts/startup/bl_ui/space_graph.py | 6 + source/blender/editors/include/ED_anim_api.h | 5 +- source/blender/editors/space_graph/graph_ops.c | 6 +- source/blender/editors/transform/transform.c | 6 + .../editors/transform/transform_constraints.c | 15 +- .../editors/transform/transform_conversions.c | 228 +++++++++++++++------ 6 files changed, 201 insertions(+), 65 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index d3e1a866e43..4c3f4bb695e 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -29,6 +29,7 @@ class GRAPH_HT_header(Header): from bl_ui.space_dopesheet import dopesheet_filter layout = self.layout + toolsettings = context.tool_settings st = context.space_data @@ -46,6 +47,11 @@ class GRAPH_HT_header(Header): row.active = st.use_normalization row.prop(st, "use_auto_normalization", text="Auto") + row = layout.row(align=True) + row.prop(toolsettings, "proportional_edit", icon_only=True) + if toolsettings.proportional_edit != 'DISABLED': + row.prop(toolsettings, "proportional_edit_falloff", icon_only=True) + layout.prop(st, "auto_snap", text="") layout.prop(st, "pivot_point", icon_only=True) diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 8cf42dfce6c..7fd0d35d514 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -114,8 +114,9 @@ typedef struct bAnimListElem { int flag; /* copy of elem's flags for quick access */ int index; /* for un-named data, the index of the data in its collection */ - short update; /* (eAnim_Update_Flags) tag the element for updating */ - + char update; /* (eAnim_Update_Flags) tag the element for updating */ + char tag; /* tag the included data. Temporary always */ + short datatype; /* (eAnim_KeyType) type of motion data to expect */ void *key_data; /* motion data - mostly F-Curves, but can be other types too */ diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index b52945297b9..33e8b522335 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -562,7 +562,6 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) WM_keymap_add_item(keymap, "GRAPH_OT_easing_type", EKEY, KM_PRESS, KM_CTRL, 0); /* destructive */ - WM_keymap_add_item(keymap, "GRAPH_OT_clean", OKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "GRAPH_OT_smooth", OKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "GRAPH_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0); @@ -608,6 +607,11 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* transform system */ transform_keymap_for_space(keyconf, keymap, SPACE_IPO); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", OKEY, KM_PRESS, 0, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.proportional_edit"); + RNA_string_set(kmi->ptr, "value_1", "DISABLED"); + RNA_string_set(kmi->ptr, "value_2", "ENABLED"); + /* pivot point settings */ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, 0, 0); RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point"); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 586c9d62589..c8d81383d79 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2089,6 +2089,12 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t); } + else if (t->spacetype == SPACE_IPO) { + unit_m3(t->spacemtx); + t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); + //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); + t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t); + } else unit_m3(t->spacemtx); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index ccb81c7342b..bcd66f56c53 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -46,6 +46,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_string.h" +#include "BLI_rect.h" #include "BKE_context.h" @@ -757,12 +758,22 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) ED_space_image_get_aspect(t->sa->spacedata.first, &aspx, &aspy); } else if (t->options & CTX_PAINT_CURVE) { - aspx = aspy = 1.0; + aspx = aspy = 1.0f; } else { ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy); } - glScalef(1.0f / aspx, 1.0f / aspy, 1.0); + glScalef(1.0f / aspx, 1.0f / aspy, 1.0f); + } + else if (t->spacetype == SPACE_IPO) { + /* only scale y */ + rcti *mask = &t->ar->v2d.mask; + rctf *datamask = &t->ar->v2d.cur; + float xsize = BLI_rctf_size_x(datamask); + float ysize = BLI_rctf_size_y(datamask); + float xmask = BLI_rcti_size_x(mask); + float ymask = BLI_rcti_size_y(mask); + glScalef(1.0f, (ysize / xsize) * (xmask / ymask), 1.0f); } depth_test_enabled = glIsEnabled(GL_DEPTH_TEST); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index a74de31491a..e34439945ca 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3786,6 +3786,27 @@ static bool graph_edit_use_local_center(TransInfo *t) return (t->around == V3D_LOCAL) && !graph_edit_is_translation_mode(t); } + +static void graph_key_shortest_dist(FCurve *fcu, TransData *td_start, TransData *td, bool use_handle) +{ + int j = 0; + TransData *td_iter = td_start; + + td->dist = FLT_MAX; + for (; j < fcu->totvert; j++) { + BezTriple *bezt = fcu->bezt + j; + const bool sel2 = (bezt->f2 & SELECT) != 0; + const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2; + const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; + + if (sel1 || sel2 || sel3) { + td->dist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0])); + } + + td_iter += 3; + } +} + static void createTransGraphEditData(bContext *C, TransInfo *t) { SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first; @@ -3808,6 +3829,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) const bool is_translation_mode = graph_edit_is_translation_mode(t); const bool use_handle = !(sipo->flag & SIPO_NOHANDLES); const bool use_local_center = graph_edit_use_local_center(t); + const bool propedit = (t->flag & T_PROP_EDIT) != 0; short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS; /* determine what type of data we are operating on */ @@ -3839,6 +3861,8 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) AnimData *adt = ANIM_nla_mapping_get(&ac, ale); FCurve *fcu = (FCurve *)ale->key_data; float cfra; + int curvecount = 0; + bool selected = false; /* F-Curve may not have any keyframes */ if (fcu->bezt == NULL) @@ -3859,20 +3883,34 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2; const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; - if (!is_translation_mode || !(sel2)) { - if (sel1) { - count++; + if (propedit) { + curvecount += 3; + if (sel2 || sel1 || sel3) + selected = true; + } + else { + if (!is_translation_mode || !(sel2)) { + if (sel1) { + count++; + } + + if (sel3) { + count++; + } } - if (sel3) { + /* only include main vert if selected */ + if (sel2 && !use_local_center) { count++; } } + } + } - /* only include main vert if selected */ - if (sel2 && !use_local_center) { - count++; - } + if (propedit) { + if (selected) { + count += curvecount; + ale->tag = true; } } } @@ -3925,7 +3963,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) float cfra; /* F-Curve may not have any keyframes */ - if (fcu->bezt == NULL) + if (fcu->bezt == NULL || (propedit && ale->tag == 0)) continue; /* convert current-frame to action-time (slightly less accurate, especially under @@ -3948,66 +3986,135 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) TransDataCurveHandleFlags *hdata = NULL; /* short h1=1, h2=1; */ /* UNUSED */ - /* only include handles if selected, irrespective of the interpolation modes. - * also, only treat handles specially if the center point isn't selected. - */ - if (!is_translation_mode || !(sel2)) { - if (sel1) { - hdata = initTransDataCurveHandles(td, bezt); - bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, sel1, true, intvals, mtx, smtx, unit_scale); + if (propedit) { + bool is_sel = (sel2 || sel1 || sel3); + /* we always select all handles for proportional editing if central handle is selected */ + initTransDataCurveHandles(td, bezt); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, is_sel, true, intvals, mtx, smtx, unit_scale); + initTransDataCurveHandles(td, bezt); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, is_sel, false, intvals, mtx, smtx, unit_scale); + initTransDataCurveHandles(td, bezt); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, is_sel, true, intvals, mtx, smtx, unit_scale); + } + else { + /* only include handles if selected, irrespective of the interpolation modes. + * also, only treat handles specially if the center point isn't selected. + */ + if (!is_translation_mode || !(sel2)) { + if (sel1) { + hdata = initTransDataCurveHandles(td, bezt); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, sel1, true, intvals, mtx, smtx, unit_scale); + } + else { + /* h1 = 0; */ /* UNUSED */ + } + + if (sel3) { + if (hdata == NULL) + hdata = initTransDataCurveHandles(td, bezt); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, sel3, true, intvals, mtx, smtx, unit_scale); + } + else { + /* h2 = 0; */ /* UNUSED */ + } } - else { - /* h1 = 0; */ /* UNUSED */ + + /* only include main vert if selected */ + if (sel2 && !use_local_center) { + /* move handles relative to center */ + if (is_translation_mode) { + if (sel1) td->flag |= TD_MOVEHANDLE1; + if (sel3) td->flag |= TD_MOVEHANDLE2; + } + + /* if handles were not selected, store their selection status */ + if (!(sel1) || !(sel3)) { + if (hdata == NULL) + hdata = initTransDataCurveHandles(td, bezt); + } + + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, sel2, false, intvals, mtx, smtx, unit_scale); + } - - if (sel3) { - if (hdata == NULL) - hdata = initTransDataCurveHandles(td, bezt); - bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, sel3, true, intvals, mtx, smtx, unit_scale); + /* special hack (must be done after initTransDataCurveHandles(), as that stores handle settings to restore...): + * - Check if we've got entire BezTriple selected and we're scaling/rotating that point, + * then check if we're using auto-handles. + * - If so, change them auto-handles to aligned handles so that handles get affected too + */ + if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && + ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) && + ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) + { + if (hdata && (sel1) && (sel3)) { + bezt->h1 = HD_ALIGN; + bezt->h2 = HD_ALIGN; + } + } + } + } + } + + /* Sets handles based on the selection */ + testhandles_fcurve(fcu, use_handle); + } + + if (propedit) { + /* loop 2: build transdata arrays */ + td = t->data; + + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ANIM_nla_mapping_get(&ac, ale); + FCurve *fcu = (FCurve *)ale->key_data; + TransData *td_start = td; + float cfra; + + /* F-Curve may not have any keyframes */ + if (fcu->bezt == NULL || (ale->tag == 0)) + continue; + + /* convert current-frame to action-time (slightly less accurate, especially under + * higher scaling ratios, but is faster than converting all points) + */ + if (adt) + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); + else + cfra = (float)CFRA; + + /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */ + for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { + if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { + const bool sel2 = (bezt->f2 & SELECT) != 0; + const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2; + const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; + + if (sel1 || sel2) { + td->dist = 0.0f; } else { - /* h2 = 0; */ /* UNUSED */ + graph_key_shortest_dist(fcu, td_start, td, use_handle); } - } - - /* only include main vert if selected */ - if (sel2 && !use_local_center) { - /* move handles relative to center */ - if (is_translation_mode) { - if (sel1) td->flag |= TD_MOVEHANDLE1; - if (sel3) td->flag |= TD_MOVEHANDLE2; + td++; + + if (sel2) { + td->dist = 0.0f; } - - /* if handles were not selected, store their selection status */ - if (!(sel1) || !(sel3)) { - if (hdata == NULL) - hdata = initTransDataCurveHandles(td, bezt); + else { + graph_key_shortest_dist(fcu, td_start, td, use_handle); } - - bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, sel2, false, intvals, mtx, smtx, unit_scale); - - } - /* special hack (must be done after initTransDataCurveHandles(), as that stores handle settings to restore...): - * - Check if we've got entire BezTriple selected and we're scaling/rotating that point, - * then check if we're using auto-handles. - * - If so, change them auto-handles to aligned handles so that handles get affected too - */ - if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && - ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) && - ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) - { - if (hdata && (sel1) && (sel3)) { - bezt->h1 = HD_ALIGN; - bezt->h2 = HD_ALIGN; + td++; + + if (sel3 || sel2) { + td->dist = 0.0f; } + else { + graph_key_shortest_dist(fcu, td_start, td, use_handle); + } + td++; } } } - - /* Sets handles based on the selection */ - testhandles_fcurve(fcu, use_handle); } - + /* cleanup temp list */ ANIM_animdata_freelist(&anim_data); } @@ -7631,13 +7738,14 @@ void createTransData(bContext *C, TransInfo *t) else if (t->spacetype == SPACE_IPO) { t->flag |= T_POINTS | T_2D_EDIT; createTransGraphEditData(C, t); -#if 0 + if (t->data && (t->flag & T_PROP_EDIT)) { + t->flag |= T_PROP_CONNECTED; + t->flag &= ~T_PROP_PROJECTED; sort_trans_data(t); // makes selected become first in array - set_prop_dist(t, 1); + set_prop_dist(t, false); sort_trans_data_dist(t); } -#endif } else if (t->spacetype == SPACE_NODE) { t->flag |= T_POINTS | T_2D_EDIT; -- cgit v1.2.3 From 7da4c2637d35c8f0f05de43a2bfbea7958dc6e44 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 31 Mar 2015 19:50:15 +0500 Subject: Cycles: Fix typo in distance heuristic for shadow rays It's not that bad because this typo could only caused not really efficient BVH traversal, causing higher render times. Not as if it was causing render artifacts. --- intern/cycles/kernel/geom/geom_qbvh_shadow.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_qbvh_shadow.h b/intern/cycles/kernel/geom/geom_qbvh_shadow.h index 4233ff15c86..dde5331970a 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_shadow.h +++ b/intern/cycles/kernel/geom/geom_qbvh_shadow.h @@ -155,11 +155,11 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, ++stackPtr; kernel_assert(stackPtr < BVH_QSTACK_SIZE); traversalStack[stackPtr].addr = c1; - traversalStack[stackPtr].dist = c1; + traversalStack[stackPtr].dist = d1; ++stackPtr; kernel_assert(stackPtr < BVH_QSTACK_SIZE); traversalStack[stackPtr].addr = c0; - traversalStack[stackPtr].dist = c0; + traversalStack[stackPtr].dist = d0; /* Three children are hit, push all onto stack and sort 3 * stack items, continue with closest child. -- cgit v1.2.3 From 79918e05773132ce1f96c90b555348229ddfcf73 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 31 Mar 2015 19:51:55 +0500 Subject: Cycles: Avoid float/int conversion in few places --- intern/cycles/kernel/geom/geom_object.h | 2 +- intern/cycles/kernel/svm/svm.h | 2 +- intern/cycles/kernel/svm/svm_light_path.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h index 79a56683454..7df71010232 100644 --- a/intern/cycles/kernel/geom/geom_object.h +++ b/intern/cycles/kernel/geom/geom_object.h @@ -243,7 +243,7 @@ ccl_device_inline float object_random_number(KernelGlobals *kg, int object) ccl_device_inline int object_particle_id(KernelGlobals *kg, int object) { if(object == OBJECT_NONE) - return 0.0f; + return 0; int offset = object*OBJECT_SIZE + OBJECT_PROPERTIES; float4 f = kernel_tex_fetch(__objects, offset); diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index d59c9b9e61c..dd9173d92b3 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -87,7 +87,7 @@ ccl_device_inline int stack_load_int(float *stack, uint a) return __float_as_int(stack[a]); } -ccl_device_inline float stack_load_int_default(float *stack, uint a, uint value) +ccl_device_inline int stack_load_int_default(float *stack, uint a, uint value) { return (a == (uint)SVM_STACK_INVALID)? (int)value: stack_load_int(stack, a); } diff --git a/intern/cycles/kernel/svm/svm_light_path.h b/intern/cycles/kernel/svm/svm_light_path.h index 677d139c5d4..ffadafb1d0c 100644 --- a/intern/cycles/kernel/svm/svm_light_path.h +++ b/intern/cycles/kernel/svm/svm_light_path.h @@ -34,7 +34,7 @@ ccl_device void svm_node_light_path(ShaderData *sd, float *stack, uint type, uin case NODE_LP_backfacing: info = (sd->flag & SD_BACKFACING)? 1.0f: 0.0f; break; case NODE_LP_ray_length: info = sd->ray_length; break; case NODE_LP_ray_depth: info = (float)sd->ray_depth; break; - case NODE_LP_ray_transparent: info = sd->transparent_depth; break; + case NODE_LP_ray_transparent: info = (float)sd->transparent_depth; break; } stack_store_float(stack, out_offset, info); -- cgit v1.2.3 From 7ee340c0b43c89c157264bb723b01dff5c6005b4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 1 Apr 2015 01:58:15 +1100 Subject: Fix writing freed memory, exiting full view --- source/blender/editors/screen/screen_edit.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index aadfa9e6608..e1c414b0031 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1765,6 +1765,7 @@ void ED_screen_full_prevspace(bContext *C, ScrArea *sa) if (sa->flag & AREA_FLAG_STACKED_FULLSCREEN) { /* stacked fullscreen -> only go back to previous screen and don't toggle out of fullscreen */ ED_area_prevspace(C, sa); + sa->flag &= ~AREA_FLAG_TEMP_TYPE; } else { ED_screen_restore_temp_type(C, sa); @@ -1804,8 +1805,7 @@ void ED_screen_full_restore(bContext *C, ScrArea *sa) else { ED_screen_state_toggle(C, win, sa, state); } - - sa->flag &= ~AREA_FLAG_TEMP_TYPE; + /* warning: 'sa' may be freed */ } /* otherwise just tile the area again */ else { @@ -1813,7 +1813,11 @@ void ED_screen_full_restore(bContext *C, ScrArea *sa) } } -/* this function toggles: if area is maximized/full then the parent will be restored */ +/** + * this function toggles: if area is maximized/full then the parent will be restored + * + * \warning \a sa may be freed. + */ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const short state) { bScreen *sc, *oldscreen; -- cgit v1.2.3 From f3b45eb76fe39a908d485bc8fdd67bbd5369a483 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 31 Mar 2015 17:37:09 +0200 Subject: Fix T43987 ambient occlusion wrong for Intel cards on windows (tested on HD3000 and HD4000 cards so far). Similar issue to Radeon 3xxx series but Intels need the opposite factors for dfdy. --- source/blender/gpu/intern/gpu_extensions.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index c602fdad18e..363e19908e5 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -259,12 +259,10 @@ void gpu_extensions_init(void) GG.dfdyfactors[0] = 1.0; GG.dfdyfactors[1] = -1.0; } - /* - if ((strstr(vendor, "Intel"))) { + else if (GG.device == GPU_DEVICE_INTEL && GG.os == GPU_OS_WIN) { GG.dfdyfactors[0] = -1.0; GG.dfdyfactors[1] = 1.0; } - */ else { GG.dfdyfactors[0] = 1.0; GG.dfdyfactors[1] = 1.0; -- cgit v1.2.3 From d9c566a2d8ad935f5f7dc08d20f11fbf8cfe5fc0 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 31 Mar 2015 22:10:26 +0500 Subject: Corrections to submodules: we need to use latest tag available from master branch --- release/scripts/addons | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/scripts/addons b/release/scripts/addons index 6cf8e325dba..3fc5b82c6bd 160000 --- a/release/scripts/addons +++ b/release/scripts/addons @@ -1 +1 @@ -Subproject commit 6cf8e325dba9c5afa1cb2a7cbf62159dd049e9b6 +Subproject commit 3fc5b82c6bdba2f9c954fbf497621b9bb794a1bc -- cgit v1.2.3 From c59ca9e477d23884997046d61d9ea20c78ee06bb Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 31 Mar 2015 14:57:19 -0400 Subject: silence MSVC warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ‘*/‘ found outside of comment --- source/blender/compositor/operations/COM_CalculateMeanOperation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp index 32395f44ef1..d26dcd17750 100644 --- a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp +++ b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp @@ -46,7 +46,7 @@ void CalculateMeanOperation::initExecution() void CalculateMeanOperation::executePixel(float output[4], int /*x*/, int /*y*/, - void */*data*/) + void * /*data*/) { output[0] = this->m_result; } -- cgit v1.2.3 From 879f5c832bfeaf1e29479319dbdf4898cbd43a6d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 1 Apr 2015 09:29:56 +1100 Subject: Match corrective-smooth UI to smooth modifier --- release/scripts/startup/bl_ui/properties_data_modifier.py | 2 +- source/blender/makesrna/intern/rna_modifier.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index a3cf079f915..1186992b13e 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -1389,8 +1389,8 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): def CORRECTIVE_SMOOTH(self, layout, ob, md): is_bind = md.is_bind + layout.prop(md, "factor", text="Factor") layout.prop(md, "iterations") - layout.prop(md, "lambda_factor", text="Factor") row = layout.row() row.prop(md, "smooth_type") diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 635336004f9..93f29dbee66 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -2169,7 +2169,7 @@ static void rna_def_modifier_correctivesmooth(BlenderRNA *brna) RNA_def_struct_sdna(srna, "CorrectiveSmoothModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_SMOOTH); - prop = RNA_def_property(srna, "lambda_factor", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "lambda"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); RNA_def_property_ui_range(prop, 0.0, 1.0, 5, 3); -- cgit v1.2.3 From 6461fbd9ce1f6cbaded1a53b689ea190b6f22f5e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 1 Apr 2015 17:07:04 +1100 Subject: Fix glitch scaling bone radius connected parents radius could get out of sync with child. --- source/blender/editors/transform/transform_generics.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 5f02fa1b05f..eb68e54b4b8 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -808,6 +808,10 @@ static void recalcData_objects(TransInfo *t) ebo->rad_head *= ebo->length / ebo->oldlength; ebo->rad_tail *= ebo->length / ebo->oldlength; ebo->oldlength = ebo->length; + + if (ebo_parent) { + ebo_parent->rad_tail = ebo->rad_head; + } } } -- cgit v1.2.3 From f7dbce9914a86952b1a9ca2657a3c735cb693ef1 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 1 Apr 2015 09:34:01 +0200 Subject: Real fix for T44127: Python does not guarantee to free all objects on exit... All kudos to Campbell for the head-up and patch! --- source/blender/python/intern/bpy_app_translations.c | 9 +++++++++ source/blender/python/intern/bpy_app_translations.h | 1 + source/blender/python/intern/bpy_interface.c | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c index 123b111f3cb..ae5ea88abdf 100644 --- a/source/blender/python/intern/bpy_app_translations.c +++ b/source/blender/python/intern/bpy_app_translations.c @@ -821,3 +821,12 @@ PyObject *BPY_app_translations_struct(void) return ret; } + +void BPY_app_translations_end(void) +{ + /* Incase the object remains in a module's namespace, see T44127. */ +#ifdef WITH_INTERNATIONAL + _clear_translations_cache(); +#endif +} + diff --git a/source/blender/python/intern/bpy_app_translations.h b/source/blender/python/intern/bpy_app_translations.h index 704307574d0..e04c2484ecc 100644 --- a/source/blender/python/intern/bpy_app_translations.h +++ b/source/blender/python/intern/bpy_app_translations.h @@ -28,5 +28,6 @@ #define __BPY_APP_TRANSLATIONS_H__ PyObject *BPY_app_translations_struct(void); +void BPY_app_translations_end(void); #endif /* __BPY_APP_TRANSLATIONS_H__ */ diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 5b4db89a41a..690ea115fcd 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -61,6 +61,8 @@ #include "bpy_traceback.h" #include "bpy_intern_string.h" +#include "bpy_app_translations.h" + #include "DNA_text_types.h" #include "BKE_appdir.h" @@ -358,6 +360,9 @@ void BPY_python_end(void) bpy_intern_string_exit(); + /* bpy.app modules that need cleanup */ + BPY_app_translations_end(); + #ifndef WITH_PYTHON_MODULE BPY_atexit_unregister(); /* without this we get recursive calls to WM_exit */ -- cgit v1.2.3 From 71af08e1c972024244e48096a3f44da25de2eb95 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 1 Apr 2015 09:48:48 +0200 Subject: Fix T44212: Crash on Group Rename. Nice offset-by-one index error. ;) --- source/blender/editors/space_outliner/outliner_tools.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index fc6717f47be..af21478150b 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -946,16 +946,15 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op) default: BLI_assert(0); } - if (event == 3) { /* instance */ /* works without this except if you try render right after, see: 22027 */ DAG_relations_tag_update(CTX_data_main(C)); } - - ED_undo_push(C, prop_group_op_types[event].name); + + ED_undo_push(C, prop_group_op_types[event - 1].name); WM_event_add_notifier(C, NC_GROUP, NULL); - + return OPERATOR_FINISHED; } -- cgit v1.2.3 From af399884e16e263062e19ed921608d1003e62f6d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 1 Apr 2015 14:21:21 +0500 Subject: Fix T44113: Ashikhmin-Shirley distribution of glossy shader at 0 roughness causes artifacts when background uses MIS Was a division by zero error, solved in the same way as beckmann/ggx deals with small roughness values. --- intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h index acc477246d2..dec09e00395 100644 --- a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h @@ -69,6 +69,9 @@ ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, c float out = 0.0f; + if(fmaxf(sc->data0, sc->data1) <= 1e-4f) + return make_float3(0, 0, 0); + if(NdotI > 0.0f && NdotO > 0.0f) { NdotI = fmaxf(NdotI, 1e-6f); NdotO = fmaxf(NdotO, 1e-6f); @@ -190,8 +193,15 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng, /* reflect I on H to get omega_in */ *omega_in = -I + (2.0f * HdotI) * H; - /* leave the rest to eval_reflect */ - *eval = bsdf_ashikhmin_shirley_eval_reflect(sc, I, *omega_in, pdf); + if(fmaxf(sc->data0, sc->data1) <= 1e-4f) { + /* Some high number for MIS. */ + *pdf = 1e6f; + *eval = make_float3(1e6f, 1e6f, 1e6f); + } + else { + /* leave the rest to eval_reflect */ + *eval = bsdf_ashikhmin_shirley_eval_reflect(sc, I, *omega_in, pdf); + } #ifdef __RAY_DIFFERENTIALS__ /* just do the reflection thing for now */ -- cgit v1.2.3 From 8e6e7010bc8ee8a2133939cd106fd0a22ea5e244 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 1 Apr 2015 11:24:26 +0200 Subject: Proportional editing for graph editor did not work outside edit mode --- source/blender/editors/transform/transform_generics.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index eb68e54b4b8..14ae93d1144 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1320,7 +1320,10 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve /* use settings from scene only if modal */ if (t->flag & T_MODAL) { if ((t->options & CTX_NO_PET) == 0) { - if (t->obedit) { + if (t->spacetype == SPACE_IPO) { + t->flag |= T_PROP_EDIT; + } + else if (t->obedit) { t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional); } else if (t->options & CTX_GPENCIL_STROKES) { -- cgit v1.2.3 From 394b947a500db59b753e39841057e3f0c5422bbc Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 1 Apr 2015 21:08:12 +0500 Subject: Cycles: Remove unused direction from triangle intersection functions This argument was unused and got nicely optimized out. But once it starts to be using registers are getting stressed really crazy, causing slow down of render. --- intern/cycles/kernel/geom/geom_bvh_shadow.h | 2 +- intern/cycles/kernel/geom/geom_bvh_subsurface.h | 2 +- intern/cycles/kernel/geom/geom_bvh_traversal.h | 2 +- intern/cycles/kernel/geom/geom_bvh_volume.h | 2 +- intern/cycles/kernel/geom/geom_qbvh_shadow.h | 2 +- intern/cycles/kernel/geom/geom_qbvh_subsurface.h | 2 +- intern/cycles/kernel/geom/geom_qbvh_traversal.h | 2 +- intern/cycles/kernel/geom/geom_qbvh_volume.h | 2 +- intern/cycles/kernel/geom/geom_triangle_intersect.h | 4 +--- 9 files changed, 9 insertions(+), 11 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_bvh_shadow.h b/intern/cycles/kernel/geom/geom_bvh_shadow.h index 193f49074a3..030283e903e 100644 --- a/intern/cycles/kernel/geom/geom_bvh_shadow.h +++ b/intern/cycles/kernel/geom/geom_bvh_shadow.h @@ -226,7 +226,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, switch(p_type) { case PRIMITIVE_TRIANGLE: { - hit = triangle_intersect(kg, &isect_precalc, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr); + hit = triangle_intersect(kg, &isect_precalc, isect_array, P, PATH_RAY_SHADOW, object, primAddr); break; } #if BVH_FEATURE(BVH_MOTION) diff --git a/intern/cycles/kernel/geom/geom_bvh_subsurface.h b/intern/cycles/kernel/geom/geom_bvh_subsurface.h index 290297ef5c5..73d392b2ea6 100644 --- a/intern/cycles/kernel/geom/geom_bvh_subsurface.h +++ b/intern/cycles/kernel/geom/geom_bvh_subsurface.h @@ -210,7 +210,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; if(tri_object != subsurface_object) continue; - triangle_intersect_subsurface(kg, &isect_precalc, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits); + triangle_intersect_subsurface(kg, &isect_precalc, isect_array, P, object, primAddr, isect_t, &num_hits, lcg_state, max_hits); } break; } diff --git a/intern/cycles/kernel/geom/geom_bvh_traversal.h b/intern/cycles/kernel/geom/geom_bvh_traversal.h index 0298e687de2..c4d2a1bdc6a 100644 --- a/intern/cycles/kernel/geom/geom_bvh_traversal.h +++ b/intern/cycles/kernel/geom/geom_bvh_traversal.h @@ -269,7 +269,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, isect->num_traversal_steps++; #endif kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); - if(triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr)) { + if(triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, primAddr)) { /* shadow ray early termination */ #if defined(__KERNEL_SSE2__) if(visibility == PATH_RAY_SHADOW_OPAQUE) diff --git a/intern/cycles/kernel/geom/geom_bvh_volume.h b/intern/cycles/kernel/geom/geom_bvh_volume.h index 0862812a170..111f840cb95 100644 --- a/intern/cycles/kernel/geom/geom_bvh_volume.h +++ b/intern/cycles/kernel/geom/geom_bvh_volume.h @@ -213,7 +213,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { continue; } - triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr); + triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, primAddr); } break; } diff --git a/intern/cycles/kernel/geom/geom_qbvh_shadow.h b/intern/cycles/kernel/geom/geom_qbvh_shadow.h index dde5331970a..f9fda39c3fc 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_shadow.h +++ b/intern/cycles/kernel/geom/geom_qbvh_shadow.h @@ -241,7 +241,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, switch(p_type) { case PRIMITIVE_TRIANGLE: { - hit = triangle_intersect(kg, &isect_precalc, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr); + hit = triangle_intersect(kg, &isect_precalc, isect_array, P, PATH_RAY_SHADOW, object, primAddr); break; } #if BVH_FEATURE(BVH_MOTION) diff --git a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h index 62598115fa3..654c5cf1493 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h +++ b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h @@ -226,7 +226,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, if(tri_object != subsurface_object) { continue; } - triangle_intersect_subsurface(kg, &isect_precalc, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits); + triangle_intersect_subsurface(kg, &isect_precalc, isect_array, P, object, primAddr, isect_t, &num_hits, lcg_state, max_hits); } break; } diff --git a/intern/cycles/kernel/geom/geom_qbvh_traversal.h b/intern/cycles/kernel/geom/geom_qbvh_traversal.h index 99d2fb20837..6c61296ad1f 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_traversal.h +++ b/intern/cycles/kernel/geom/geom_qbvh_traversal.h @@ -296,7 +296,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, isect->num_traversal_steps++; #endif kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); - if(triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr)) { + if(triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, primAddr)) { tfar = ssef(isect->t); /* Shadow ray early termination. */ if(visibility == PATH_RAY_SHADOW_OPAQUE) diff --git a/intern/cycles/kernel/geom/geom_qbvh_volume.h b/intern/cycles/kernel/geom/geom_qbvh_volume.h index 2c396e99fc4..1c9ace68d53 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_volume.h +++ b/intern/cycles/kernel/geom/geom_qbvh_volume.h @@ -234,7 +234,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, continue; } /* Intersect ray against primitive. */ - triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr); + triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, primAddr); } break; } diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index 983e4ad90b9..d3919a05396 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -14,7 +14,7 @@ * limitations under the License. */ -/* Triangle/Ray intersections . +/* Triangle/Ray intersections. * * For BVH ray intersection we use a precomputed triangle storage to accelerate * intersection at the cost of more memory usage. @@ -98,7 +98,6 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg, const IsectPrecalc *isect_precalc, Intersection *isect, float3 P, - float3 dir, uint visibility, int object, int triAddr) @@ -191,7 +190,6 @@ ccl_device_inline void triangle_intersect_subsurface( const IsectPrecalc *isect_precalc, Intersection *isect_array, float3 P, - float3 dir, int object, int triAddr, float tmax, -- cgit v1.2.3 From f1494edf787099d9261f7ab82a66c68ffbe8e727 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 1 Apr 2015 21:19:29 +0500 Subject: Cycles: Make SSS intersection closer to regular triangle intersection --- intern/cycles/kernel/geom/geom_triangle_intersect.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index d3919a05396..b29fc2b4e9d 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -247,13 +247,10 @@ ccl_device_inline void triangle_intersect_subsurface( /* Calculate scaled z−coordinates of vertices and use them to calculate * the hit distance. */ - const float Az = Sz * A_kz; - const float Bz = Sz * B_kz; - const float Cz = Sz * C_kz; - const float T = U * Az + V * Bz + W * Cz; - - if((xor_signmast(T, sign_mask) < 0.0f) || - (xor_signmast(T, sign_mask) > tmax * xor_signmast(det, sign_mask))) + const float T = (U * A_kz + V * B_kz + W * C_kz) * Sz; + const float sign_T = xor_signmast(T, sign_mask); + if((sign_T < 0.0f) || + (sign_T > tmax * xor_signmast(det, sign_mask))) { return; } -- cgit v1.2.3 From 4b847595eebc42828ecb87d198bf7c2c7bce7372 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Thu, 2 Apr 2015 00:24:58 +0200 Subject: Fix T44217: Crash when starting .blend without "Load UI" enabled Caused by changes in 31e26bb83b. This makes it fall back to the old method if we can't find a screen. Patch is actually by @LazyDodo with minor edits by me. --- source/blender/blenkernel/intern/blender.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index c7b306521c4..8106f27253b 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -283,7 +283,10 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath /* clear_global will free G.main, here we can still restore pointers */ blo_lib_link_screen_restore(bfd->main, curscreen, curscene); - curscene = curscreen->scene; + /* curscreen might not be set when loading without ui (see T44217) so only re-assign if available */ + if (curscreen) { + curscene = curscreen->scene; + } if (track_undo_scene) { wmWindowManager *wm = bfd->main->wm.first; -- cgit v1.2.3 From b6d878fa960c25e2c07f5950c02371e5d0e50425 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 29 Mar 2015 20:58:10 +1300 Subject: Fix for incorrect description --- source/blender/editors/interface/interface_eyedropper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index aabb8e29fa9..f5847a9d701 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -632,7 +632,7 @@ void UI_OT_eyedropper_id(wmOperatorType *ot) /* identifiers */ ot->name = "Eyedropper Datablock"; ot->idname = "UI_OT_eyedropper_id"; - ot->description = "Sample a color from the Blender Window to store in a property"; + ot->description = "Sample a datablock from the Blender Window to store in a property"; /* api callbacks */ ot->invoke = datadropper_invoke; -- cgit v1.2.3 From 26fa13e6f8d9a6bf64aa50070c5f146461520f96 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Apr 2015 16:29:33 +1300 Subject: Code Cleanup: Reshuffling some of the GPencil code * Moved the context handling stuff into gpencil_utils.c * Moved the datablock and layer operators out into their own file too. Again, these weren't related to the other stuff that much * Split the GPencil to Curves operator out into its own file (gpencil_convert.c). This was quite a massive blob of code (48kb) that was not that related to the other operators still in that file (gpencil_edit.c) --- source/blender/editors/gpencil/CMakeLists.txt | 2 + source/blender/editors/gpencil/gpencil_convert.c | 1484 +++++++++++++++++ source/blender/editors/gpencil/gpencil_data.c | 366 +++++ source/blender/editors/gpencil/gpencil_edit.c | 1840 +--------------------- source/blender/editors/gpencil/gpencil_intern.h | 6 + source/blender/editors/gpencil/gpencil_utils.c | 180 +++ 6 files changed, 2040 insertions(+), 1838 deletions(-) create mode 100644 source/blender/editors/gpencil/gpencil_convert.c create mode 100644 source/blender/editors/gpencil/gpencil_data.c diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt index 58192f59219..56b8d284386 100644 --- a/source/blender/editors/gpencil/CMakeLists.txt +++ b/source/blender/editors/gpencil/CMakeLists.txt @@ -39,6 +39,8 @@ set(INC_SYS set(SRC drawgpencil.c editaction_gpencil.c + gpencil_convert.c + gpencil_data.c gpencil_edit.c gpencil_ops.c gpencil_paint.c diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c new file mode 100644 index 00000000000..2c8f86423a5 --- /dev/null +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -0,0 +1,1484 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008, Blender Foundation + * This is a new part of Blender + * + * Contributor(s): Joshua Leung + * Bastien Montagne + * + * ***** END GPL LICENSE BLOCK ***** + * + * Operator for converting Grease Pencil data to geometry + */ + +/** \file blender/editors/gpencil/gpencil_convert.c + * \ingroup edgpencil + */ + + +#include +#include +#include +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" +#include "BLI_blenlib.h" +#include "BLI_rand.h" +#include "BLI_utildefines.h" + +#include "BLF_translation.h" + +#include "DNA_anim_types.h" +#include "DNA_curve_types.h" +#include "DNA_object_types.h" +#include "DNA_node_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_view3d_types.h" +#include "DNA_gpencil_types.h" + +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_fcurve.h" +#include "BKE_global.h" +#include "BKE_gpencil.h" +#include "BKE_library.h" +#include "BKE_object.h" +#include "BKE_report.h" +#include "BKE_scene.h" +#include "BKE_screen.h" +#include "BKE_tracking.h" + +#include "UI_interface.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "UI_view2d.h" + +#include "ED_gpencil.h" +#include "ED_view3d.h" +#include "ED_clip.h" +#include "ED_keyframing.h" + +#include "gpencil_intern.h" + +/* ************************************************ */ +/* Grease Pencil to Data Operator */ + +/* defines for possible modes */ +enum { + GP_STROKECONVERT_PATH = 1, + GP_STROKECONVERT_CURVE, + GP_STROKECONVERT_POLY, +}; + +/* Defines for possible timing modes */ +enum { + GP_STROKECONVERT_TIMING_NONE = 1, + GP_STROKECONVERT_TIMING_LINEAR = 2, + GP_STROKECONVERT_TIMING_FULL = 3, + GP_STROKECONVERT_TIMING_CUSTOMGAP = 4, +}; + +/* RNA enum define */ +static EnumPropertyItem prop_gpencil_convertmodes[] = { + {GP_STROKECONVERT_PATH, "PATH", 0, "Path", ""}, + {GP_STROKECONVERT_CURVE, "CURVE", 0, "Bezier Curve", ""}, + {GP_STROKECONVERT_POLY, "POLY", 0, "Polygon Curve", ""}, + {0, NULL, 0, NULL, NULL} +}; + +static EnumPropertyItem prop_gpencil_convert_timingmodes_restricted[] = { + {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"}, + {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"}, + {0, NULL, 0, NULL, NULL}, +}; + +static EnumPropertyItem prop_gpencil_convert_timingmodes[] = { + {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"}, + {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"}, + {GP_STROKECONVERT_TIMING_FULL, "FULL", 0, "Original", "Use the original timing, gaps included"}, + {GP_STROKECONVERT_TIMING_CUSTOMGAP, "CUSTOMGAP", 0, "Custom Gaps", + "Use the original timing, but with custom gap lengths (in frames)"}, + {0, NULL, 0, NULL, NULL}, +}; + +static EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), + bool *UNUSED(r_free)) +{ + if (RNA_boolean_get(ptr, "use_timing_data")) { + return prop_gpencil_convert_timingmodes; + } + return prop_gpencil_convert_timingmodes_restricted; +} + +/* --- */ + +/* convert the coordinates from the given stroke point into 3d-coordinates + * - assumes that the active space is the 3D-View + */ +static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoint *pt, float p3d[3], rctf *subrect) +{ + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + + if (gps->flag & GP_STROKE_3DSPACE) { + /* directly use 3d-coordinates */ + copy_v3_v3(p3d, &pt->x); + } + else { + const float *fp = ED_view3d_cursor3d_get(scene, v3d); + float mvalf[2]; + + /* get screen coordinate */ + if (gps->flag & GP_STROKE_2DSPACE) { + View2D *v2d = &ar->v2d; + UI_view2d_view_to_region_fl(v2d, pt->x, pt->y, &mvalf[0], &mvalf[1]); + } + else { + if (subrect) { + mvalf[0] = (((float)pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin; + mvalf[1] = (((float)pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin; + } + else { + mvalf[0] = (float)pt->x / 100.0f * ar->winx; + mvalf[1] = (float)pt->y / 100.0f * ar->winy; + } + } + + ED_view3d_win_to_3d(ar, fp, mvalf, p3d); + } +} + +/* --- */ + +/* temp struct for gp_stroke_path_animation() */ +typedef struct tGpTimingData { + /* Data set from operator settings */ + int mode; + int frame_range; /* Number of frames evaluated for path animation */ + int start_frame, end_frame; + bool realtime; /* Will overwrite end_frame in case of Original or CustomGap timing... */ + float gap_duration, gap_randomness; /* To be used with CustomGap mode*/ + int seed; + + /* Data set from points, used to compute final timing FCurve */ + int num_points, cur_point; + + /* Distances */ + float *dists; + float tot_dist; + + /* Times */ + float *times; /* Note: Gap times will be negative! */ + float tot_time, gap_tot_time; + double inittime; + + /* Only used during creation of dists & times lists. */ + float offset_time; +} tGpTimingData; + +/* Init point buffers for timing data. + * Note this assumes we only grow those arrays! + */ +static void gp_timing_data_set_nbr(tGpTimingData *gtd, const int nbr) +{ + float *tmp; + + BLI_assert(nbr > gtd->num_points); + + /* distances */ + tmp = gtd->dists; + gtd->dists = MEM_callocN(sizeof(float) * nbr, __func__); + if (tmp) { + memcpy(gtd->dists, tmp, sizeof(float) * gtd->num_points); + MEM_freeN(tmp); + } + + /* times */ + tmp = gtd->times; + gtd->times = MEM_callocN(sizeof(float) * nbr, __func__); + if (tmp) { + memcpy(gtd->times, tmp, sizeof(float) * gtd->num_points); + MEM_freeN(tmp); + } + + gtd->num_points = nbr; +} + +/* add stroke point to timing buffers */ +static void gp_timing_data_add_point(tGpTimingData *gtd, const double stroke_inittime, const float time, + const float delta_dist) +{ + float delta_time = 0.0f; + const int cur_point = gtd->cur_point; + + if (!cur_point) { + /* Special case, first point, if time is not 0.0f we have to compensate! */ + gtd->offset_time = -time; + gtd->times[cur_point] = 0.0f; + } + else if (time < 0.0f) { + /* This is a gap, negative value! */ + gtd->times[cur_point] = -(((float)(stroke_inittime - gtd->inittime)) + time + gtd->offset_time); + delta_time = -gtd->times[cur_point] - gtd->times[cur_point - 1]; + + gtd->gap_tot_time += delta_time; + } + else { + gtd->times[cur_point] = (((float)(stroke_inittime - gtd->inittime)) + time + gtd->offset_time); + delta_time = gtd->times[cur_point] - fabsf(gtd->times[cur_point - 1]); + } + + gtd->tot_time += delta_time; + gtd->tot_dist += delta_dist; + gtd->dists[cur_point] = gtd->tot_dist; + + gtd->cur_point++; +} + +/* In frames! Binary search for FCurve keys have a threshold of 0.01, so we can't set + * arbitrarily close points - this is esp. important with NoGaps mode! + */ +#define MIN_TIME_DELTA 0.02f + +/* Loop over next points to find the end of the stroke, and compute */ +static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, RNG *rng, const int idx, const int nbr_gaps, + int *nbr_done_gaps, const float tot_gaps_time, const float delta_time, + float *next_delta_time) +{ + int j; + + for (j = idx + 1; j < gtd->num_points; j++) { + if (gtd->times[j] < 0) { + gtd->times[j] = -gtd->times[j]; + if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { + /* In this mode, gap time between this stroke and the next should be 0 currently... + * So we have to compute its final duration! + */ + if (gtd->gap_randomness > 0.0f) { + /* We want gaps that are in gtd->gap_duration +/- gtd->gap_randomness range, + * and which sum to exactly tot_gaps_time... + */ + int rem_gaps = nbr_gaps - (*nbr_done_gaps); + if (rem_gaps < 2) { + /* Last gap, just give remaining time! */ + *next_delta_time = tot_gaps_time; + } + else { + float delta, min, max; + + /* This code ensures that if the first gaps have been shorter than average gap_duration, + * next gaps will tend to be longer (i.e. try to recover the lateness), and vice-versa! + */ + delta = delta_time - (gtd->gap_duration * (*nbr_done_gaps)); + + /* Clamp min between [-gap_randomness, 0.0], with lower delta giving higher min */ + min = -gtd->gap_randomness - delta; + CLAMP(min, -gtd->gap_randomness, 0.0f); + + /* Clamp max between [0.0, gap_randomness], with lower delta giving higher max */ + max = gtd->gap_randomness - delta; + CLAMP(max, 0.0f, gtd->gap_randomness); + *next_delta_time += gtd->gap_duration + (BLI_rng_get_float(rng) * (max - min)) + min; + } + } + else { + *next_delta_time += gtd->gap_duration; + } + } + (*nbr_done_gaps)++; + break; + } + } + + return j - 1; +} + +static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, RNG *rng, int *nbr_gaps, float *tot_gaps_time) +{ + int i; + float delta_time = 0.0f; + + for (i = 0; i < gtd->num_points; i++) { + if (gtd->times[i] < 0 && i) { + (*nbr_gaps)++; + gtd->times[i] = -gtd->times[i] - delta_time; + delta_time += gtd->times[i] - gtd->times[i - 1]; + gtd->times[i] = -gtd->times[i - 1]; /* Temp marker, values *have* to be different! */ + } + else { + gtd->times[i] -= delta_time; + } + } + gtd->tot_time -= delta_time; + + *tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration; + gtd->tot_time += *tot_gaps_time; + if (G.debug & G_DEBUG) { + printf("%f, %f, %f, %d\n", gtd->tot_time, delta_time, *tot_gaps_time, *nbr_gaps); + } + if (gtd->gap_randomness > 0.0f) { + BLI_rng_srandom(rng, gtd->seed); + } +} + +static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, + Curve *cu, tGpTimingData *gtd, RNG *rng, const float time_range, + const int nbr_gaps, const float tot_gaps_time) +{ + /* Use actual recorded timing! */ + const float time_start = (float)gtd->start_frame; + + float last_valid_time = 0.0f; + int end_stroke_idx = -1, start_stroke_idx = 0; + float end_stroke_time = 0.0f; + + /* CustomGaps specific */ + float delta_time = 0.0f, next_delta_time = 0.0f; + int nbr_done_gaps = 0; + + int i; + float cfra; + + /* This is a bit tricky, as: + * - We can't add arbitrarily close points on FCurve (in time). + * - We *must* have all "caps" points of all strokes in FCurve, as much as possible! + */ + for (i = 0; i < gtd->num_points; i++) { + /* If new stroke... */ + if (i > end_stroke_idx) { + start_stroke_idx = i; + delta_time = next_delta_time; + /* find end of that new stroke */ + end_stroke_idx = gp_find_end_of_stroke_idx(gtd, rng, i, nbr_gaps, &nbr_done_gaps, + tot_gaps_time, delta_time, &next_delta_time); + /* This one should *never* be negative! */ + end_stroke_time = time_start + ((gtd->times[end_stroke_idx] + delta_time) / gtd->tot_time * time_range); + } + + /* Simple proportional stuff... */ + cu->ctime = gtd->dists[i] / gtd->tot_dist * cu->pathlen; + cfra = time_start + ((gtd->times[i] + delta_time) / gtd->tot_time * time_range); + + /* And now, the checks about timing... */ + if (i == start_stroke_idx) { + /* If first point of a stroke, be sure it's enough ahead of last valid keyframe, and + * that the end point of the stroke is far enough! + * In case it is not, we keep the end point... + * Note that with CustomGaps mode, this is here we set the actual gap timing! + */ + if ((end_stroke_time - last_valid_time) > MIN_TIME_DELTA * 2) { + if ((cfra - last_valid_time) < MIN_TIME_DELTA) { + cfra = last_valid_time + MIN_TIME_DELTA; + } + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + last_valid_time = cfra; + } + else if (G.debug & G_DEBUG) { + printf("\t Skipping start point %d, too close from end point %d\n", i, end_stroke_idx); + } + } + else if (i == end_stroke_idx) { + /* Always try to insert end point of a curve (should be safe enough, anyway...) */ + if ((cfra - last_valid_time) < MIN_TIME_DELTA) { + cfra = last_valid_time + MIN_TIME_DELTA; + } + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + last_valid_time = cfra; + } + else { + /* Else ("middle" point), we only insert it if it's far enough from last keyframe, + * and also far enough from (not yet added!) end_stroke keyframe! + */ + if ((cfra - last_valid_time) > MIN_TIME_DELTA && (end_stroke_time - cfra) > MIN_TIME_DELTA) { + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + last_valid_time = cfra; + } + else if (G.debug & G_DEBUG) { + printf("\t Skipping \"middle\" point %d, too close from last added point or end point %d\n", + i, end_stroke_idx); + } + } + } +} + +static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu, tGpTimingData *gtd) +{ + Scene *scene = CTX_data_scene(C); + bAction *act; + FCurve *fcu; + PointerRNA ptr; + PropertyRNA *prop = NULL; + int nbr_gaps = 0, i; + + if (gtd->mode == GP_STROKECONVERT_TIMING_NONE) + return; + + /* gap_duration and gap_randomness are in frames, but we need seconds!!! */ + gtd->gap_duration = FRA2TIME(gtd->gap_duration); + gtd->gap_randomness = FRA2TIME(gtd->gap_randomness); + + /* Enable path! */ + cu->flag |= CU_PATH; + cu->pathlen = gtd->frame_range; + + /* Get RNA pointer to read/write path time values */ + RNA_id_pointer_create((ID *)cu, &ptr); + prop = RNA_struct_find_property(&ptr, "eval_time"); + + /* Ensure we have an F-Curve to add keyframes to */ + act = verify_adt_action((ID *)cu, true); + fcu = verify_fcurve(act, NULL, &ptr, "eval_time", 0, true); + + if (G.debug & G_DEBUG) { + printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time); + for (i = 0; i < gtd->num_points; i++) { + printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]); + } + } + + if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) { + float cfra; + + /* Linear extrapolation! */ + fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; + + cu->ctime = 0.0f; + cfra = (float)gtd->start_frame; + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + + cu->ctime = cu->pathlen; + if (gtd->realtime) { + cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */ + } + else { + cfra = (float)gtd->end_frame; + } + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + } + else { + /* Use actual recorded timing! */ + RNG *rng = BLI_rng_new(0); + float time_range; + + /* CustomGaps specific */ + float tot_gaps_time = 0.0f; + + /* Pre-process gaps, in case we don't want to keep their original timing */ + if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { + gp_stroke_path_animation_preprocess_gaps(gtd, rng, &nbr_gaps, &tot_gaps_time); + } + + if (gtd->realtime) { + time_range = (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */ + } + else { + time_range = (float)(gtd->end_frame - gtd->start_frame); + } + + if (G.debug & G_DEBUG) { + printf("GP Stroke Path Conversion: Starting keying!\n"); + } + + gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, rng, time_range, + nbr_gaps, tot_gaps_time); + + BLI_rng_free(rng); + } + + /* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */ + calchandles_fcurve(fcu); + + if (G.debug & G_DEBUG) { + printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time); + for (i = 0; i < gtd->num_points; i++) { + printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]); + } + printf("\n\n"); + } + + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + + /* send updates */ + DAG_id_tag_update(&cu->id, 0); +} + +#undef MIN_TIME_DELTA + +#define GAP_DFAC 0.01f +#define WIDTH_CORR_FAC 0.1f +#define BEZT_HANDLE_FAC 0.3f + +/* convert stroke to 3d path */ + +/* helper */ +static void gp_stroke_to_path_add_point(tGpTimingData *gtd, BPoint *bp, const float p[3], const float prev_p[3], + const bool do_gtd, const double inittime, const float time, + const float width, const float rad_fac, float minmax_weights[2]) +{ + copy_v3_v3(bp->vec, p); + bp->vec[3] = 1.0f; + + /* set settings */ + bp->f1 = SELECT; + bp->radius = width * rad_fac; + bp->weight = width; + CLAMP(bp->weight, 0.0f, 1.0f); + if (bp->weight < minmax_weights[0]) { + minmax_weights[0] = bp->weight; + } + else if (bp->weight > minmax_weights[1]) { + minmax_weights[1] = bp->weight; + } + + /* Update timing data */ + if (do_gtd) { + gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p)); + } +} + +static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu, + float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point, + const bool add_end_point, tGpTimingData *gtd) +{ + bGPDspoint *pt; + Nurb *nu = (curnu) ? *curnu : NULL; + BPoint *bp, *prev_bp = NULL; + const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE); + const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0); + int i, old_nbp = 0; + + /* create new 'nurb' or extend current one within the curve */ + if (nu) { + old_nbp = nu->pntsu; + + /* If stitch, the first point of this stroke is already present in current nu. + * Else, we have to add two additional points to make the zero-radius link between strokes. + */ + BKE_nurb_points_add(nu, gps->totpoints + (stitch ? -1 : 2) + add_start_end_points); + } + else { + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)"); + + nu->pntsu = gps->totpoints + add_start_end_points; + nu->pntsv = 1; + nu->orderu = 2; /* point-to-point! */ + nu->type = CU_NURBS; + nu->flagu = CU_NURB_ENDPOINT; + nu->resolu = cu->resolu; + nu->resolv = cu->resolv; + nu->knotsu = NULL; + + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "bpoints"); + + stitch = false; /* Security! */ + } + + if (do_gtd) { + gp_timing_data_set_nbr(gtd, nu->pntsu); + } + + /* If needed, make the link between both strokes with two zero-radius additional points */ + /* About "zero-radius" point interpolations: + * - If we have at least two points in current curve (most common case), we linearly extrapolate + * the last segment to get the first point (p1) position and timing. + * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point + * with the first point of the current stroke. + * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated + * if it exists, else (if the stroke is a single point), linear interpolation with last curve point... + */ + if (curnu && !stitch && old_nbp) { + float p1[3], p2[3], p[3], next_p[3]; + float dt1 = 0.0f, dt2 = 0.0f; + + BLI_assert(gps->prev != NULL); + + prev_bp = NULL; + if ((old_nbp > 1) && (gps->prev->totpoints > 1)) { + /* Only use last curve segment if previous stroke was not a single-point one! */ + prev_bp = &nu->bp[old_nbp - 2]; + } + bp = &nu->bp[old_nbp - 1]; + + /* First point */ + gp_strokepoint_convertcoords(C, gps, gps->points, p, subrect); + if (prev_bp) { + interp_v3_v3v3(p1, bp->vec, prev_bp->vec, -GAP_DFAC); + if (do_gtd) { + const int idx = gps->prev->totpoints - 1; + dt1 = interpf(gps->prev->points[idx - 1].time, gps->prev->points[idx].time, -GAP_DFAC); + } + } + else { + interp_v3_v3v3(p1, bp->vec, p, GAP_DFAC); + if (do_gtd) { + dt1 = interpf(gps->inittime - gps->prev->inittime, 0.0f, GAP_DFAC); + } + } + bp++; + gp_stroke_to_path_add_point(gtd, bp, p1, (bp - 1)->vec, do_gtd, gps->prev->inittime, dt1, + 0.0f, rad_fac, minmax_weights); + + /* Second point */ + /* Note dt2 is always negative, which marks the gap. */ + if (gps->totpoints > 1) { + gp_strokepoint_convertcoords(C, gps, gps->points + 1, next_p, subrect); + interp_v3_v3v3(p2, p, next_p, -GAP_DFAC); + if (do_gtd) { + dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC); + } + } + else { + interp_v3_v3v3(p2, p, bp->vec, GAP_DFAC); + if (do_gtd) { + dt2 = interpf(gps->prev->inittime - gps->inittime, 0.0f, GAP_DFAC); + } + } + bp++; + gp_stroke_to_path_add_point(gtd, bp, p2, p1, do_gtd, gps->inittime, dt2, 0.0f, rad_fac, minmax_weights); + + old_nbp += 2; + } + else if (add_start_point) { + float p[3], next_p[3]; + float dt = 0.0f; + + gp_strokepoint_convertcoords(C, gps, gps->points, p, subrect); + if (gps->totpoints > 1) { + gp_strokepoint_convertcoords(C, gps, gps->points + 1, next_p, subrect); + interp_v3_v3v3(p, p, next_p, -GAP_DFAC); + if (do_gtd) { + dt = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC); + } + } + else { + p[0] -= GAP_DFAC; /* Rather arbitrary... */ + dt = -GAP_DFAC; /* Rather arbitrary too! */ + } + bp = &nu->bp[old_nbp]; + /* Note we can't give anything else than 0.0 as time here, since a negative one (which would be expected value) + * would not work (it would be *before* gtd->inittime, which is not supported currently). + */ + gp_stroke_to_path_add_point(gtd, bp, p, p, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights); + + old_nbp++; + } + + if (old_nbp) { + prev_bp = &nu->bp[old_nbp - 1]; + } + + /* add points */ + for (i = (stitch) ? 1 : 0, pt = &gps->points[(stitch) ? 1 : 0], bp = &nu->bp[old_nbp]; + i < gps->totpoints; + i++, pt++, bp++) + { + float p[3]; + float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC; + + /* get coordinates to add at */ + gp_strokepoint_convertcoords(C, gps, pt, p, subrect); + + gp_stroke_to_path_add_point(gtd, bp, p, (prev_bp) ? prev_bp->vec : p, do_gtd, gps->inittime, pt->time, + width, rad_fac, minmax_weights); + + prev_bp = bp; + } + + if (add_end_point) { + float p[3]; + float dt = 0.0f; + + if (gps->totpoints > 1) { + interp_v3_v3v3(p, prev_bp->vec, (prev_bp - 1)->vec, -GAP_DFAC); + if (do_gtd) { + const int idx = gps->totpoints - 1; + dt = interpf(gps->points[idx - 1].time, gps->points[idx].time, -GAP_DFAC); + } + } + else { + copy_v3_v3(p, prev_bp->vec); + p[0] += GAP_DFAC; /* Rather arbitrary... */ + dt = GAP_DFAC; /* Rather arbitrary too! */ + } + /* Note bp has already been incremented in main loop above, so it points to the right place. */ + gp_stroke_to_path_add_point(gtd, bp, p, prev_bp->vec, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights); + } + + /* add nurb to curve */ + if (!curnu || !*curnu) { + BLI_addtail(&cu->nurb, nu); + } + if (curnu) { + *curnu = nu; + } + + BKE_nurb_knot_calc_u(nu); +} + +/* convert stroke to 3d bezier */ + +/* helper */ +static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, BezTriple *bezt, + const float p[3], const float h1[3], const float h2[3], const float prev_p[3], + const bool do_gtd, const double inittime, const float time, + const float width, const float rad_fac, float minmax_weights[2]) +{ + copy_v3_v3(bezt->vec[0], h1); + copy_v3_v3(bezt->vec[1], p); + copy_v3_v3(bezt->vec[2], h2); + + /* set settings */ + bezt->h1 = bezt->h2 = HD_FREE; + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + bezt->radius = width * rad_fac; + bezt->weight = width; + CLAMP(bezt->weight, 0.0f, 1.0f); + if (bezt->weight < minmax_weights[0]) { + minmax_weights[0] = bezt->weight; + } + else if (bezt->weight > minmax_weights[1]) { + minmax_weights[1] = bezt->weight; + } + + /* Update timing data */ + if (do_gtd) { + gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p)); + } +} + +static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu, + float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point, + const bool add_end_point, tGpTimingData *gtd) +{ + bGPDspoint *pt; + Nurb *nu = (curnu) ? *curnu : NULL; + BezTriple *bezt, *prev_bezt = NULL; + int i, tot, old_nbezt = 0; + const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0); + float p3d_cur[3], p3d_prev[3], p3d_next[3], h1[3], h2[3]; + const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE); + + /* create new 'nurb' or extend current one within the curve */ + if (nu) { + old_nbezt = nu->pntsu; + /* If we do stitch, first point of current stroke is assumed the same as last point of previous stroke, + * so no need to add it. + * If no stitch, we want to add two additional points to make a "zero-radius" link between both strokes. + */ + BKE_nurb_bezierPoints_add(nu, gps->totpoints + ((stitch) ? -1 : 2) + add_start_end_points); + } + else { + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)"); + + nu->pntsu = gps->totpoints + add_start_end_points; + nu->resolu = 12; + nu->resolv = 12; + nu->type = CU_BEZIER; + nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * nu->pntsu, "bezts"); + + stitch = false; /* Security! */ + } + + if (do_gtd) { + gp_timing_data_set_nbr(gtd, nu->pntsu); + } + + tot = gps->totpoints; + + /* get initial coordinates */ + pt = gps->points; + if (tot) { + gp_strokepoint_convertcoords(C, gps, pt, (stitch) ? p3d_prev : p3d_cur, subrect); + if (tot > 1) { + gp_strokepoint_convertcoords(C, gps, pt + 1, (stitch) ? p3d_cur : p3d_next, subrect); + } + if (stitch && tot > 2) { + gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect); + } + } + + /* If needed, make the link between both strokes with two zero-radius additional points */ + if (curnu && old_nbezt) { + BLI_assert(gps->prev != NULL); + + /* Update last point's second handle */ + if (stitch) { + bezt = &nu->bezt[old_nbezt - 1]; + interp_v3_v3v3(h2, bezt->vec[1], p3d_cur, BEZT_HANDLE_FAC); + copy_v3_v3(bezt->vec[2], h2); + pt++; + } + + /* Create "link points" */ + /* About "zero-radius" point interpolations: + * - If we have at least two points in current curve (most common case), we linearly extrapolate + * the last segment to get the first point (p1) position and timing. + * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point + * with the first point of the current stroke. + * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated + * if it exists, else (if the stroke is a single point), linear interpolation with last curve point... + */ + else { + float p1[3], p2[3]; + float dt1 = 0.0f, dt2 = 0.0f; + + prev_bezt = NULL; + if ((old_nbezt > 1) && (gps->prev->totpoints > 1)) { + /* Only use last curve segment if previous stroke was not a single-point one! */ + prev_bezt = &nu->bezt[old_nbezt - 2]; + } + bezt = &nu->bezt[old_nbezt - 1]; + + /* First point */ + if (prev_bezt) { + interp_v3_v3v3(p1, prev_bezt->vec[1], bezt->vec[1], 1.0f + GAP_DFAC); + if (do_gtd) { + const int idx = gps->prev->totpoints - 1; + dt1 = interpf(gps->prev->points[idx - 1].time, gps->prev->points[idx].time, -GAP_DFAC); + } + } + else { + interp_v3_v3v3(p1, bezt->vec[1], p3d_cur, GAP_DFAC); + if (do_gtd) { + dt1 = interpf(gps->inittime - gps->prev->inittime, 0.0f, GAP_DFAC); + } + } + + /* Second point */ + /* Note dt2 is always negative, which marks the gap. */ + if (tot > 1) { + interp_v3_v3v3(p2, p3d_cur, p3d_next, -GAP_DFAC); + if (do_gtd) { + dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC); + } + } + else { + interp_v3_v3v3(p2, p3d_cur, bezt->vec[1], GAP_DFAC); + if (do_gtd) { + dt2 = interpf(gps->prev->inittime - gps->inittime, 0.0f, GAP_DFAC); + } + } + + /* Second handle of last point of previous stroke. */ + interp_v3_v3v3(h2, bezt->vec[1], p1, BEZT_HANDLE_FAC); + copy_v3_v3(bezt->vec[2], h2); + + /* First point */ + interp_v3_v3v3(h1, p1, bezt->vec[1], BEZT_HANDLE_FAC); + interp_v3_v3v3(h2, p1, p2, BEZT_HANDLE_FAC); + bezt++; + gp_stroke_to_bezier_add_point(gtd, bezt, p1, h1, h2, (bezt - 1)->vec[1], do_gtd, gps->prev->inittime, dt1, + 0.0f, rad_fac, minmax_weights); + + /* Second point */ + interp_v3_v3v3(h1, p2, p1, BEZT_HANDLE_FAC); + interp_v3_v3v3(h2, p2, p3d_cur, BEZT_HANDLE_FAC); + bezt++; + gp_stroke_to_bezier_add_point(gtd, bezt, p2, h1, h2, p1, do_gtd, gps->inittime, dt2, + 0.0f, rad_fac, minmax_weights); + + old_nbezt += 2; + copy_v3_v3(p3d_prev, p2); + } + } + else if (add_start_point) { + float p[3]; + float dt = 0.0f; + + if (gps->totpoints > 1) { + interp_v3_v3v3(p, p3d_cur, p3d_next, -GAP_DFAC); + if (do_gtd) { + dt = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC); + } + } + else { + copy_v3_v3(p, p3d_cur); + p[0] -= GAP_DFAC; /* Rather arbitrary... */ + dt = -GAP_DFAC; /* Rather arbitrary too! */ + } + interp_v3_v3v3(h1, p, p3d_cur, -BEZT_HANDLE_FAC); + interp_v3_v3v3(h2, p, p3d_cur, BEZT_HANDLE_FAC); + bezt = &nu->bezt[old_nbezt]; + gp_stroke_to_bezier_add_point(gtd, bezt, p, h1, h2, p, do_gtd, gps->inittime, dt, + 0.0f, rad_fac, minmax_weights); + + old_nbezt++; + copy_v3_v3(p3d_prev, p); + } + + if (old_nbezt) { + prev_bezt = &nu->bezt[old_nbezt - 1]; + } + + /* add points */ + for (i = stitch ? 1 : 0, bezt = &nu->bezt[old_nbezt]; i < tot; i++, pt++, bezt++) { + float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC; + + if (i || old_nbezt) { + interp_v3_v3v3(h1, p3d_cur, p3d_prev, BEZT_HANDLE_FAC); + } + else { + interp_v3_v3v3(h1, p3d_cur, p3d_next, -BEZT_HANDLE_FAC); + } + + if (i < tot - 1) { + interp_v3_v3v3(h2, p3d_cur, p3d_next, BEZT_HANDLE_FAC); + } + else { + interp_v3_v3v3(h2, p3d_cur, p3d_prev, -BEZT_HANDLE_FAC); + } + + gp_stroke_to_bezier_add_point(gtd, bezt, p3d_cur, h1, h2, prev_bezt ? prev_bezt->vec[1] : p3d_cur, + do_gtd, gps->inittime, pt->time, width, rad_fac, minmax_weights); + + /* shift coord vects */ + copy_v3_v3(p3d_prev, p3d_cur); + copy_v3_v3(p3d_cur, p3d_next); + + if (i + 2 < tot) { + gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect); + } + + prev_bezt = bezt; + } + + if (add_end_point) { + float p[3]; + float dt = 0.0f; + + if (gps->totpoints > 1) { + interp_v3_v3v3(p, prev_bezt->vec[1], (prev_bezt - 1)->vec[1], -GAP_DFAC); + if (do_gtd) { + const int idx = gps->totpoints - 1; + dt = interpf(gps->points[idx - 1].time, gps->points[idx].time, -GAP_DFAC); + } + } + else { + copy_v3_v3(p, prev_bezt->vec[1]); + p[0] += GAP_DFAC; /* Rather arbitrary... */ + dt = GAP_DFAC; /* Rather arbitrary too! */ + } + + /* Second handle of last point of this stroke. */ + interp_v3_v3v3(h2, prev_bezt->vec[1], p, BEZT_HANDLE_FAC); + copy_v3_v3(prev_bezt->vec[2], h2); + + /* The end point */ + interp_v3_v3v3(h1, p, prev_bezt->vec[1], BEZT_HANDLE_FAC); + interp_v3_v3v3(h2, p, prev_bezt->vec[1], -BEZT_HANDLE_FAC); + /* Note bezt has already been incremented in main loop above, so it points to the right place. */ + gp_stroke_to_bezier_add_point(gtd, bezt, p, h1, h2, prev_bezt->vec[1], do_gtd, gps->inittime, dt, + 0.0f, rad_fac, minmax_weights); + } + + /* must calculate handles or else we crash */ + BKE_nurb_handles_calc(nu); + + if (!curnu || !*curnu) { + BLI_addtail(&cu->nurb, nu); + } + if (curnu) { + *curnu = nu; + } +} + +#undef GAP_DFAC +#undef WIDTH_CORR_FAC +#undef BEZT_HANDLE_FAC + +static void gp_stroke_finalize_curve_endpoints(Curve *cu) +{ + /* start */ + Nurb *nu = cu->nurb.first; + int i = 0; + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + if (bezt) { + bezt[i].weight = bezt[i].radius = 0.0f; + } + } + else if (nu->bp) { + BPoint *bp = nu->bp; + if (bp) { + bp[i].weight = bp[i].radius = 0.0f; + } + } + + /* end */ + nu = cu->nurb.last; + i = nu->pntsu - 1; + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + if (bezt) { + bezt[i].weight = bezt[i].radius = 0.0f; + } + } + else if (nu->bp) { + BPoint *bp = nu->bp; + if (bp) { + bp[i].weight = bp[i].radius = 0.0f; + } + } +} + +static void gp_stroke_norm_curve_weights(Curve *cu, const float minmax_weights[2]) +{ + Nurb *nu; + const float delta = minmax_weights[0]; + float fac; + int i; + + /* when delta == minmax_weights[0] == minmax_weights[1], we get div by zero [#35686] */ + if (IS_EQF(delta, minmax_weights[1])) + fac = 1.0f; + else + fac = 1.0f / (minmax_weights[1] - delta); + + for (nu = cu->nurb.first; nu; nu = nu->next) { + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + for (i = 0; i < nu->pntsu; i++, bezt++) { + bezt->weight = (bezt->weight - delta) * fac; + } + } + else if (nu->bp) { + BPoint *bp = nu->bp; + for (i = 0; i < nu->pntsu; i++, bp++) { + bp->weight = (bp->weight - delta) * fac; + } + } + } +} + +static int gp_camera_view_subrect(bContext *C, rctf *subrect) +{ + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + + if (v3d) { + RegionView3D *rv3d = ar->regiondata; + + /* for camera view set the subrect */ + if (rv3d->persp == RV3D_CAMOB) { + Scene *scene = CTX_data_scene(C); + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, subrect, true); /* no shift */ + return 1; + } + } + + return 0; +} + +/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */ +static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bGPDlayer *gpl, const int mode, + const bool norm_weights, const float rad_fac, const bool link_strokes, tGpTimingData *gtd) +{ + struct Main *bmain = CTX_data_main(C); + View3D *v3d = CTX_wm_view3d(C); /* may be NULL */ + Scene *scene = CTX_data_scene(C); + bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); + bGPDstroke *gps, *prev_gps = NULL; + Object *ob; + Curve *cu; + Nurb *nu = NULL; + Base *base_orig = BASACT, *base_new = NULL; + float minmax_weights[2] = {1.0f, 0.0f}; + + /* camera framing */ + rctf subrect, *subrect_ptr = NULL; + + /* error checking */ + if (ELEM(NULL, gpd, gpl, gpf)) + return; + + /* only convert if there are any strokes on this layer's frame to convert */ + if (BLI_listbase_is_empty(&gpf->strokes)) + return; + + /* initialize camera framing */ + if (gp_camera_view_subrect(C, &subrect)) { + subrect_ptr = &subrect; + } + + /* init the curve object (remove rotation and get curve data from it) + * - must clear transforms set on object, as those skew our results + */ + ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info); + cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE); + base_new = BKE_scene_base_add(scene, ob); + + cu->flag |= CU_3D; + + gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime; + + /* add points to curve */ + for (gps = gpf->strokes.first; gps; gps = gps->next) { + const bool add_start_point = (link_strokes && !(prev_gps)); + const bool add_end_point = (link_strokes && !(gps->next)); + + /* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached, and stitch them to previous one. */ + bool stitch = false; + if (prev_gps) { + bGPDspoint *pt1 = &prev_gps->points[prev_gps->totpoints - 1]; + bGPDspoint *pt2 = &gps->points[0]; + + if ((pt1->x == pt2->x) && (pt1->y == pt2->y)) { + stitch = true; + } + } + + /* Decide whether we connect this stroke to previous one */ + if (!(stitch || link_strokes)) { + nu = NULL; + } + + switch (mode) { + case GP_STROKECONVERT_PATH: + gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, + add_start_point, add_end_point, gtd); + break; + case GP_STROKECONVERT_CURVE: + case GP_STROKECONVERT_POLY: /* convert after */ + gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, + add_start_point, add_end_point, gtd); + break; + default: + BLI_assert(!"invalid mode"); + break; + } + prev_gps = gps; + } + + /* If link_strokes, be sure first and last points have a zero weight/size! */ + if (link_strokes) { + gp_stroke_finalize_curve_endpoints(cu); + } + + /* Update curve's weights, if needed */ + if (norm_weights && ((minmax_weights[0] > 0.0f) || (minmax_weights[1] < 1.0f))) { + gp_stroke_norm_curve_weights(cu, minmax_weights); + } + + /* Create the path animation, if needed */ + gp_stroke_path_animation(C, reports, cu, gtd); + + if (mode == GP_STROKECONVERT_POLY) { + for (nu = cu->nurb.first; nu; nu = nu->next) { + BKE_nurb_type_convert(nu, CU_POLY, false); + } + } + + /* set the layer and select */ + base_new->lay = ob->lay = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene); + base_new->flag = ob->flag = base_new->flag | SELECT; +} + +/* --- */ + +/* Check a GP layer has valid timing data! Else, most timing options are hidden in the operator. + * op may be NULL. + */ +static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + bGPDframe *gpf = NULL; + bGPDstroke *gps = NULL; + bGPDspoint *pt; + double base_time, cur_time, prev_time = -1.0; + int i; + bool valid = true; + + if (!gpl || !(gpf = gpencil_layer_getframe(gpl, CFRA, 0)) || !(gps = gpf->strokes.first)) + return false; + + do { + base_time = cur_time = gps->inittime; + if (cur_time <= prev_time) { + valid = false; + break; + } + + prev_time = cur_time; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + cur_time = base_time + (double)pt->time; + /* First point of a stroke should have the same time as stroke's inittime, + * so it's the only case where equality is allowed! + */ + if ((i && cur_time <= prev_time) || (cur_time < prev_time)) { + valid = false; + break; + } + prev_time = cur_time; + } + + if (!valid) { + break; + } + } while ((gps = gps->next)); + + if (op) { + RNA_boolean_set(op->ptr, "use_timing_data", valid); + } + return valid; +} + +/* Check end_frame is always > start frame! */ +static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UNUSED(scene), struct PointerRNA *ptr) +{ + int start_frame = RNA_int_get(ptr, "start_frame"); + int end_frame = RNA_int_get(ptr, "end_frame"); + + if (end_frame <= start_frame) { + RNA_int_set(ptr, "end_frame", start_frame + 1); + } +} + +static int gp_convert_poll(bContext *C) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + bGPDlayer *gpl = NULL; + bGPDframe *gpf = NULL; + ScrArea *sa = CTX_wm_area(C); + Scene *scene = CTX_data_scene(C); + + /* only if the current view is 3D View, if there's valid data (i.e. at least one stroke!), + * and if we are not in edit mode! + */ + return ((sa && sa->spacetype == SPACE_VIEW3D) && + (gpl = gpencil_layer_getactive(gpd)) && + (gpf = gpencil_layer_getframe(gpl, CFRA, 0)) && + (gpf->strokes.first) && + (scene->obedit == NULL)); +} + +static int gp_convert_layer_exec(bContext *C, wmOperator *op) +{ + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_timing_data"); + bGPdata *gpd = ED_gpencil_data_get_active(C); + bGPDlayer *gpl = gpencil_layer_getactive(gpd); + Scene *scene = CTX_data_scene(C); + const int mode = RNA_enum_get(op->ptr, "type"); + const bool norm_weights = RNA_boolean_get(op->ptr, "use_normalize_weights"); + const float rad_fac = RNA_float_get(op->ptr, "radius_multiplier"); + const bool link_strokes = RNA_boolean_get(op->ptr, "use_link_strokes"); + bool valid_timing; + tGpTimingData gtd; + + /* check if there's data to work with */ + if (gpd == NULL) { + BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data to work on"); + return OPERATOR_CANCELLED; + } + + if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) { + BKE_report(op->reports, RPT_WARNING, + "Current Grease Pencil strokes have no valid timing data, most timing options will be hidden!"); + } + valid_timing = RNA_property_boolean_get(op->ptr, prop); + + gtd.mode = RNA_enum_get(op->ptr, "timing_mode"); + /* Check for illegal timing mode! */ + if (!valid_timing && !ELEM(gtd.mode, GP_STROKECONVERT_TIMING_NONE, GP_STROKECONVERT_TIMING_LINEAR)) { + gtd.mode = GP_STROKECONVERT_TIMING_LINEAR; + RNA_enum_set(op->ptr, "timing_mode", gtd.mode); + } + if (!link_strokes) { + gtd.mode = GP_STROKECONVERT_TIMING_NONE; + } + + /* grab all relevant settings */ + gtd.frame_range = RNA_int_get(op->ptr, "frame_range"); + gtd.start_frame = RNA_int_get(op->ptr, "start_frame"); + gtd.realtime = valid_timing ? RNA_boolean_get(op->ptr, "use_realtime") : false; + gtd.end_frame = RNA_int_get(op->ptr, "end_frame"); + gtd.gap_duration = RNA_float_get(op->ptr, "gap_duration"); + gtd.gap_randomness = RNA_float_get(op->ptr, "gap_randomness"); + gtd.gap_randomness = min_ff(gtd.gap_randomness, gtd.gap_duration); + gtd.seed = RNA_int_get(op->ptr, "seed"); + gtd.num_points = gtd.cur_point = 0; + gtd.dists = gtd.times = NULL; + gtd.tot_dist = gtd.tot_time = gtd.gap_tot_time = 0.0f; + gtd.inittime = 0.0; + gtd.offset_time = 0.0f; + + /* perform conversion */ + gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, >d); + + /* free temp memory */ + if (gtd.dists) { + MEM_freeN(gtd.dists); + gtd.dists = NULL; + } + if (gtd.times) { + MEM_freeN(gtd.times); + gtd.times = NULL; + } + + /* notifiers */ + WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); + + /* done */ + return OPERATOR_FINISHED; +} + +static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) +{ + const char *prop_id = RNA_property_identifier(prop); + const bool link_strokes = RNA_boolean_get(ptr, "use_link_strokes"); + int timing_mode = RNA_enum_get(ptr, "timing_mode"); + bool realtime = RNA_boolean_get(ptr, "use_realtime"); + float gap_duration = RNA_float_get(ptr, "gap_duration"); + float gap_randomness = RNA_float_get(ptr, "gap_randomness"); + const bool valid_timing = RNA_boolean_get(ptr, "use_timing_data"); + + /* Always show those props */ + if (STREQ(prop_id, "type") || + STREQ(prop_id, "use_normalize_weights") || + STREQ(prop_id, "radius_multiplier") || + STREQ(prop_id, "use_link_strokes")) + { + return true; + } + + /* Never show this prop */ + if (STREQ(prop_id, "use_timing_data")) + return false; + + if (link_strokes) { + /* Only show when link_stroke is true */ + if (STREQ(prop_id, "timing_mode")) + return true; + + if (timing_mode != GP_STROKECONVERT_TIMING_NONE) { + /* Only show when link_stroke is true and stroke timing is enabled */ + if (STREQ(prop_id, "frame_range") || + STREQ(prop_id, "start_frame")) + { + return true; + } + + /* Only show if we have valid timing data! */ + if (valid_timing && STREQ(prop_id, "use_realtime")) + return true; + + /* Only show if realtime or valid_timing is false! */ + if ((!realtime || !valid_timing) && STREQ(prop_id, "end_frame")) + return true; + + if (valid_timing && timing_mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { + /* Only show for custom gaps! */ + if (STREQ(prop_id, "gap_duration")) + return true; + + /* Only show randomness for non-null custom gaps! */ + if (STREQ(prop_id, "gap_randomness") && (gap_duration > 0.0f)) + return true; + + /* Only show seed for randomize action! */ + if (STREQ(prop_id, "seed") && (gap_duration > 0.0f) && (gap_randomness > 0.0f)) + return true; + } + } + } + + /* Else, hidden! */ + return false; +} + +static void gp_convert_ui(bContext *C, wmOperator *op) +{ + uiLayout *layout = op->layout; + wmWindowManager *wm = CTX_wm_manager(C); + PointerRNA ptr; + + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); + + /* Main auto-draw call */ + uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, '\0'); +} + +void GPENCIL_OT_convert(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Convert Grease Pencil"; + ot->idname = "GPENCIL_OT_convert"; + ot->description = "Convert the active Grease Pencil layer to a new Curve Object"; + + /* callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = gp_convert_layer_exec; + ot->poll = gp_convert_poll; + ot->ui = gp_convert_ui; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", "Which type of curve to convert to"); + + RNA_def_boolean(ot->srna, "use_normalize_weights", true, "Normalize Weight", + "Normalize weight (set from stroke width)"); + RNA_def_float(ot->srna, "radius_multiplier", 1.0f, 0.0f, 1000.0f, "Radius Fac", + "Multiplier for the points' radii (set from stroke width)", 0.0f, 10.0f); + RNA_def_boolean(ot->srna, "use_link_strokes", true, "Link Strokes", + "Whether to link strokes with zero-radius sections of curves"); + + prop = RNA_def_enum(ot->srna, "timing_mode", prop_gpencil_convert_timingmodes, GP_STROKECONVERT_TIMING_FULL, + "Timing Mode", "How to use timing data stored in strokes"); + RNA_def_enum_funcs(prop, rna_GPConvert_mode_items); + + RNA_def_int(ot->srna, "frame_range", 100, 1, 10000, "Frame Range", + "The duration of evaluation of the path control curve", 1, 1000); + RNA_def_int(ot->srna, "start_frame", 1, 1, 100000, "Start Frame", + "The start frame of the path control curve", 1, 100000); + RNA_def_boolean(ot->srna, "use_realtime", false, "Realtime", + "Whether the path control curve reproduces the drawing in realtime, starting from Start Frame"); + prop = RNA_def_int(ot->srna, "end_frame", 250, 1, 100000, "End Frame", + "The end frame of the path control curve (if Realtime is not set)", 1, 100000); + RNA_def_property_update_runtime(prop, gp_convert_set_end_frame); + + RNA_def_float(ot->srna, "gap_duration", 0.0f, 0.0f, 10000.0f, "Gap Duration", + "Custom Gap mode: (Average) length of gaps, in frames " + "(Note: Realtime value, will be scaled if Realtime is not set)", 0.0f, 1000.0f); + RNA_def_float(ot->srna, "gap_randomness", 0.0f, 0.0f, 10000.0f, "Gap Randomness", + "Custom Gap mode: Number of frames that gap lengths can vary", 0.0f, 1000.0f); + RNA_def_int(ot->srna, "seed", 0, 0, 1000, "Random Seed", + "Custom Gap mode: Random generator seed", 0, 100); + + /* Note: Internal use, this one will always be hidden by UI code... */ + prop = RNA_def_boolean(ot->srna, "use_timing_data", false, "Has Valid Timing", + "Whether the converted Grease Pencil layer has valid timing data (internal use)"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); +} + +/* ************************************************ */ diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c new file mode 100644 index 00000000000..2046dc1ba7a --- /dev/null +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -0,0 +1,366 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008, Blender Foundation, Joshua Leung + * This is a new part of Blender + * + * Contributor(s): Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + * + * Operators for dealing with GP datablocks and layers + */ + +/** \file blender/editors/gpencil/gpencil_data.c + * \ingroup edgpencil + */ + + +#include +#include +#include +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" +#include "BLI_blenlib.h" +#include "BLI_rand.h" +#include "BLI_utildefines.h" + +#include "BLF_translation.h" + +#include "DNA_anim_types.h" +#include "DNA_curve_types.h" +#include "DNA_object_types.h" +#include "DNA_node_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_view3d_types.h" +#include "DNA_gpencil_types.h" + +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_fcurve.h" +#include "BKE_global.h" +#include "BKE_gpencil.h" +#include "BKE_library.h" +#include "BKE_object.h" +#include "BKE_report.h" +#include "BKE_scene.h" +#include "BKE_screen.h" + +#include "UI_interface.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "UI_view2d.h" + +#include "ED_gpencil.h" +#include "ED_view3d.h" +#include "ED_keyframing.h" + +#include "gpencil_intern.h" + + +/* ************************************************ */ +/* Datablock Operators */ + +/* ******************* Add New Data ************************ */ + +/* add new datablock - wrapper around API */ +static int gp_data_add_exec(bContext *C, wmOperator *op) +{ + bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); + + if (gpd_ptr == NULL) { + BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go"); + return OPERATOR_CANCELLED; + } + else { + /* decrement user count and add new datablock */ + bGPdata *gpd = (*gpd_ptr); + + id_us_min(&gpd->id); + *gpd_ptr = gpencil_data_addnew(DATA_("GPencil")); + } + + /* notifiers */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_data_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Grease Pencil Add New"; + ot->idname = "GPENCIL_OT_data_add"; + ot->description = "Add new Grease Pencil datablock"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* callbacks */ + ot->exec = gp_data_add_exec; + ot->poll = gp_add_poll; +} + +/* ******************* Unlink Data ************************ */ + +/* poll callback for adding data/layers - special */ +static int gp_data_unlink_poll(bContext *C) +{ + bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); + + /* if we have access to some active data, make sure there's a datablock before enabling this */ + return (gpd_ptr && *gpd_ptr); +} + + +/* unlink datablock - wrapper around API */ +static int gp_data_unlink_exec(bContext *C, wmOperator *op) +{ + bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); + + if (gpd_ptr == NULL) { + BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go"); + return OPERATOR_CANCELLED; + } + else { + /* just unlink datablock now, decreasing its user count */ + bGPdata *gpd = (*gpd_ptr); + + id_us_min(&gpd->id); + *gpd_ptr = NULL; + } + + /* notifiers */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_data_unlink(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Grease Pencil Unlink"; + ot->idname = "GPENCIL_OT_data_unlink"; + ot->description = "Unlink active Grease Pencil datablock"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* callbacks */ + ot->exec = gp_data_unlink_exec; + ot->poll = gp_data_unlink_poll; +} + + +/* ************************************************ */ +/* Layer Operators */ + +/* ******************* Add New Layer ************************ */ + +/* add new layer - wrapper around API */ +static int gp_layer_add_exec(bContext *C, wmOperator *op) +{ + bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); + + /* if there's no existing Grease-Pencil data there, add some */ + if (gpd_ptr == NULL) { + BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go"); + return OPERATOR_CANCELLED; + } + if (*gpd_ptr == NULL) + *gpd_ptr = gpencil_data_addnew(DATA_("GPencil")); + + /* add new layer now */ + gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), 1); + + /* notifiers */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_layer_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add New Layer"; + ot->idname = "GPENCIL_OT_layer_add"; + ot->description = "Add new Grease Pencil layer for the active Grease Pencil datablock"; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* callbacks */ + ot->exec = gp_layer_add_exec; + ot->poll = gp_add_poll; +} + +/* ******************* Remove Active Layer ************************* */ + +static int gp_layer_remove_exec(bContext *C, wmOperator *op) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + bGPDlayer *gpl = gpencil_layer_getactive(gpd); + + /* sanity checks */ + if (ELEM(NULL, gpd, gpl)) + return OPERATOR_CANCELLED; + + if (gpl->flag & GP_LAYER_LOCKED) { + BKE_report(op->reports, RPT_ERROR, "Cannot delete locked layers"); + return OPERATOR_CANCELLED; + } + + /* make the layer before this the new active layer + * - use the one after if this is the first + * - if this is the only layer, this naturally becomes NULL + */ + if (gpl->prev) + gpencil_layer_setactive(gpd, gpl->prev); + else + gpencil_layer_setactive(gpd, gpl->next); + + /* delete the layer now... */ + gpencil_layer_delete(gpd, gpl); + + /* notifiers */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_layer_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Layer"; + ot->idname = "GPENCIL_OT_layer_remove"; + ot->description = "Remove active Grease Pencil layer"; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* callbacks */ + ot->exec = gp_layer_remove_exec; + ot->poll = gp_active_layer_poll; +} + +/* ******************* Move Layer Up/Down ************************** */ + +enum { + GP_LAYER_MOVE_UP = -1, + GP_LAYER_MOVE_DOWN = 1 +}; + +static int gp_layer_move_exec(bContext *C, wmOperator *op) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + bGPDlayer *gpl = gpencil_layer_getactive(gpd); + + int direction = RNA_enum_get(op->ptr, "type"); + + /* sanity checks */ + if (ELEM(NULL, gpd, gpl)) + return OPERATOR_CANCELLED; + + /* up or down? */ + if (direction == GP_LAYER_MOVE_UP) { + /* up */ + BLI_remlink(&gpd->layers, gpl); + BLI_insertlinkbefore(&gpd->layers, gpl->prev, gpl); + } + else { + /* down */ + BLI_remlink(&gpd->layers, gpl); + BLI_insertlinkafter(&gpd->layers, gpl->next, gpl); + } + + /* notifiers */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_layer_move(wmOperatorType *ot) +{ + static EnumPropertyItem slot_move[] = { + {GP_LAYER_MOVE_UP, "UP", 0, "Up", ""}, + {GP_LAYER_MOVE_DOWN, "DOWN", 0, "Down", ""}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "Move Grease Pencil Layer"; + ot->idname = "GPENCIL_OT_layer_move"; + ot->description = "Move the active Grease Pencil layer up/down in the list"; + + /* api callbacks */ + ot->exec = gp_layer_move_exec; + ot->poll = gp_active_layer_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", ""); +} + +/* ********************* Duplicate Layer ************************** */ + +static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op)) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + bGPDlayer *gpl = gpencil_layer_getactive(gpd); + bGPDlayer *new_layer; + + /* sanity checks */ + if (ELEM(NULL, gpd, gpl)) + return OPERATOR_CANCELLED; + + /* make copy of layer, and add it immediately after the existing layer */ + new_layer = gpencil_layer_duplicate(gpl); + BLI_insertlinkafter(&gpd->layers, gpl, new_layer); + + /* ensure new layer has a unique name, and is now the active layer */ + BLI_uniquename(&gpd->layers, new_layer, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(new_layer->info)); + gpencil_layer_setactive(gpd, new_layer); + + /* notifiers */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_layer_duplicate(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Duplicate Layer"; + ot->idname = "GPENCIL_OT_layer_duplicate"; + ot->description = "Make a copy of the active Grease Pencil layer"; + + /* callbacks */ + ot->exec = gp_layer_copy_exec; + ot->poll = gp_active_layer_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ************************************************ */ diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 212d384e5ca..66ba8814f4b 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -21,6 +21,8 @@ * Contributor(s): Joshua Leung * * ***** END GPL LICENSE BLOCK ***** + * + * Operators for editing Grease Pencil strokes */ /** \file blender/editors/gpencil/gpencil_edit.c @@ -83,449 +85,6 @@ #include "gpencil_intern.h" - -/* ************************************************ */ -/* Context Wrangling... */ - -/* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it, - * when context info is not available. - */ -bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrArea *sa, Object *ob, PointerRNA *ptr) -{ - /* if there's an active area, check if the particular editor may - * have defined any special Grease Pencil context for editing... - */ - if (sa) { - SpaceLink *sl = sa->spacedata.first; - - switch (sa->spacetype) { - case SPACE_VIEW3D: /* 3D-View */ - case SPACE_TIME: /* Timeline - XXX: this is a hack to get it to show GP keyframes for 3D view */ - case SPACE_ACTION: /* DepeSheet - XXX: this is a hack to get the keyframe jump operator to take GP Keyframes into account */ - { - BLI_assert(scene && ELEM(scene->toolsettings->gpencil_src, - GP_TOOL_SOURCE_SCENE, GP_TOOL_SOURCE_OBJECT)); - - if (scene->toolsettings->gpencil_src == GP_TOOL_SOURCE_OBJECT) { - /* legacy behaviour for usage with old addons requiring object-linked to objects */ - - /* just in case no active/selected object... */ - if (ob && (ob->flag & SELECT)) { - /* for now, as long as there's an object, default to using that in 3D-View */ - if (ptr) RNA_id_pointer_create(&ob->id, ptr); - return &ob->gpd; - } - /* else: defaults to scene... */ - } - else { - if (ptr) RNA_id_pointer_create(&scene->id, ptr); - return &scene->gpd; - } - break; - } - case SPACE_NODE: /* Nodes Editor */ - { - SpaceNode *snode = (SpaceNode *)sl; - - /* return the GP data for the active node block/node */ - if (snode && snode->nodetree) { - /* for now, as long as there's an active node tree, default to using that in the Nodes Editor */ - if (ptr) RNA_id_pointer_create(&snode->nodetree->id, ptr); - return &snode->nodetree->gpd; - } - - /* even when there is no node-tree, don't allow this to flow to scene */ - return NULL; - } - case SPACE_SEQ: /* Sequencer */ - { - SpaceSeq *sseq = (SpaceSeq *)sl; - - /* for now, Grease Pencil data is associated with the space (actually preview region only) */ - /* XXX our convention for everything else is to link to data though... */ - if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceSequenceEditor, sseq, ptr); - return &sseq->gpd; - } - case SPACE_IMAGE: /* Image/UV Editor */ - { - SpaceImage *sima = (SpaceImage *)sl; - - /* for now, Grease Pencil data is associated with the space... */ - /* XXX our convention for everything else is to link to data though... */ - if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, ptr); - return &sima->gpd; - } - case SPACE_CLIP: /* Nodes Editor */ - { - SpaceClip *sc = (SpaceClip *)sl; - MovieClip *clip = ED_space_clip_get_clip(sc); - - if (clip) { - if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { - MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking); - - if (!track) - return NULL; - - if (ptr) - RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, ptr); - - return &track->gpd; - } - else { - if (ptr) - RNA_id_pointer_create(&clip->id, ptr); - - return &clip->gpd; - } - } - break; - } - default: /* unsupported space */ - return NULL; - } - } - - /* just fall back on the scene's GP data */ - if (ptr) RNA_id_pointer_create((ID *)scene, ptr); - return (scene) ? &scene->gpd : NULL; -} - -/* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it */ -bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr) -{ - ID *screen_id = (ID *)CTX_wm_screen(C); - Scene *scene = CTX_data_scene(C); - ScrArea *sa = CTX_wm_area(C); - Object *ob = CTX_data_active_object(C); - - return ED_gpencil_data_get_pointers_direct(screen_id, scene, sa, ob, ptr); -} - -/* -------------------------------------------------------- */ - -/* Get the active Grease Pencil datablock, when context is not available */ -bGPdata *ED_gpencil_data_get_active_direct(ID *screen_id, Scene *scene, ScrArea *sa, Object *ob) -{ - bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(screen_id, scene, sa, ob, NULL); - return (gpd_ptr) ? *(gpd_ptr) : NULL; -} - -/* Get the active Grease Pencil datablock */ -bGPdata *ED_gpencil_data_get_active(const bContext *C) -{ - bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); - return (gpd_ptr) ? *(gpd_ptr) : NULL; -} - -/* -------------------------------------------------------- */ - -// XXX: this should be removed... We really shouldn't duplicate logic like this! -bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, View3D *v3d) -{ - Base *base = scene->basact; - bGPdata *gpd = NULL; - /* We have to make sure active object is actually visible and selected, else we must use default scene gpd, - * to be consistent with ED_gpencil_data_get_active's behavior. - */ - - if (base && TESTBASE(v3d, base)) { - gpd = base->object->gpd; - } - return gpd ? gpd : scene->gpd; -} - -/* ************************************************ */ -/* Panel Operators */ - -/* poll callback for adding data/layers - special */ -static int gp_add_poll(bContext *C) -{ - /* the base line we have is that we have somewhere to add Grease Pencil data */ - return ED_gpencil_data_get_pointers(C, NULL) != NULL; -} - -/* poll callback for checking if there is an active layer */ -static int gp_active_layer_poll(bContext *C) -{ - bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = gpencil_layer_getactive(gpd); - - return (gpl != NULL); -} - -/* ******************* Add New Data ************************ */ - -/* add new datablock - wrapper around API */ -static int gp_data_add_exec(bContext *C, wmOperator *op) -{ - bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); - - if (gpd_ptr == NULL) { - BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go"); - return OPERATOR_CANCELLED; - } - else { - /* decrement user count and add new datablock */ - bGPdata *gpd = (*gpd_ptr); - - id_us_min(&gpd->id); - *gpd_ptr = gpencil_data_addnew(DATA_("GPencil")); - } - - /* notifiers */ - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - - return OPERATOR_FINISHED; -} - -void GPENCIL_OT_data_add(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Grease Pencil Add New"; - ot->idname = "GPENCIL_OT_data_add"; - ot->description = "Add new Grease Pencil datablock"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* callbacks */ - ot->exec = gp_data_add_exec; - ot->poll = gp_add_poll; -} - -/* ******************* Unlink Data ************************ */ - -/* poll callback for adding data/layers - special */ -static int gp_data_unlink_poll(bContext *C) -{ - bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); - - /* if we have access to some active data, make sure there's a datablock before enabling this */ - return (gpd_ptr && *gpd_ptr); -} - - -/* unlink datablock - wrapper around API */ -static int gp_data_unlink_exec(bContext *C, wmOperator *op) -{ - bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); - - if (gpd_ptr == NULL) { - BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go"); - return OPERATOR_CANCELLED; - } - else { - /* just unlink datablock now, decreasing its user count */ - bGPdata *gpd = (*gpd_ptr); - - id_us_min(&gpd->id); - *gpd_ptr = NULL; - } - - /* notifiers */ - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - - return OPERATOR_FINISHED; -} - -void GPENCIL_OT_data_unlink(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Grease Pencil Unlink"; - ot->idname = "GPENCIL_OT_data_unlink"; - ot->description = "Unlink active Grease Pencil datablock"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* callbacks */ - ot->exec = gp_data_unlink_exec; - ot->poll = gp_data_unlink_poll; -} - -/* ******************* Add New Layer ************************ */ - -/* add new layer - wrapper around API */ -static int gp_layer_add_exec(bContext *C, wmOperator *op) -{ - bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); - - /* if there's no existing Grease-Pencil data there, add some */ - if (gpd_ptr == NULL) { - BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go"); - return OPERATOR_CANCELLED; - } - if (*gpd_ptr == NULL) - *gpd_ptr = gpencil_data_addnew(DATA_("GPencil")); - - /* add new layer now */ - gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), 1); - - /* notifiers */ - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - - return OPERATOR_FINISHED; -} - -void GPENCIL_OT_layer_add(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Add New Layer"; - ot->idname = "GPENCIL_OT_layer_add"; - ot->description = "Add new Grease Pencil layer for the active Grease Pencil datablock"; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* callbacks */ - ot->exec = gp_layer_add_exec; - ot->poll = gp_add_poll; -} - -/* ******************* Remove Active Layer ************************* */ - -static int gp_layer_remove_exec(bContext *C, wmOperator *op) -{ - bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = gpencil_layer_getactive(gpd); - - /* sanity checks */ - if (ELEM(NULL, gpd, gpl)) - return OPERATOR_CANCELLED; - - if (gpl->flag & GP_LAYER_LOCKED) { - BKE_report(op->reports, RPT_ERROR, "Cannot delete locked layers"); - return OPERATOR_CANCELLED; - } - - /* make the layer before this the new active layer - * - use the one after if this is the first - * - if this is the only layer, this naturally becomes NULL - */ - if (gpl->prev) - gpencil_layer_setactive(gpd, gpl->prev); - else - gpencil_layer_setactive(gpd, gpl->next); - - /* delete the layer now... */ - gpencil_layer_delete(gpd, gpl); - - /* notifiers */ - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - - return OPERATOR_FINISHED; -} - -void GPENCIL_OT_layer_remove(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Remove Layer"; - ot->idname = "GPENCIL_OT_layer_remove"; - ot->description = "Remove active Grease Pencil layer"; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* callbacks */ - ot->exec = gp_layer_remove_exec; - ot->poll = gp_active_layer_poll; -} - -/* ******************* Move Layer Up/Down ************************** */ - -enum { - GP_LAYER_MOVE_UP = -1, - GP_LAYER_MOVE_DOWN = 1 -}; - -static int gp_layer_move_exec(bContext *C, wmOperator *op) -{ - bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = gpencil_layer_getactive(gpd); - - int direction = RNA_enum_get(op->ptr, "type"); - - /* sanity checks */ - if (ELEM(NULL, gpd, gpl)) - return OPERATOR_CANCELLED; - - /* up or down? */ - if (direction == GP_LAYER_MOVE_UP) { - /* up */ - BLI_remlink(&gpd->layers, gpl); - BLI_insertlinkbefore(&gpd->layers, gpl->prev, gpl); - } - else { - /* down */ - BLI_remlink(&gpd->layers, gpl); - BLI_insertlinkafter(&gpd->layers, gpl->next, gpl); - } - - /* notifiers */ - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - - return OPERATOR_FINISHED; -} - -void GPENCIL_OT_layer_move(wmOperatorType *ot) -{ - static EnumPropertyItem slot_move[] = { - {GP_LAYER_MOVE_UP, "UP", 0, "Up", ""}, - {GP_LAYER_MOVE_DOWN, "DOWN", 0, "Down", ""}, - {0, NULL, 0, NULL, NULL} - }; - - /* identifiers */ - ot->name = "Move Grease Pencil Layer"; - ot->idname = "GPENCIL_OT_layer_move"; - ot->description = "Move the active Grease Pencil layer up/down in the list"; - - /* api callbacks */ - ot->exec = gp_layer_move_exec; - ot->poll = gp_active_layer_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", ""); -} - -/* ********************* Duplicate Layer ************************** */ - -static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op)) -{ - bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = gpencil_layer_getactive(gpd); - bGPDlayer *new_layer; - - /* sanity checks */ - if (ELEM(NULL, gpd, gpl)) - return OPERATOR_CANCELLED; - - /* make copy of layer, and add it immediately after the existing layer */ - new_layer = gpencil_layer_duplicate(gpl); - BLI_insertlinkafter(&gpd->layers, gpl, new_layer); - - /* ensure new layer has a unique name, and is now the active layer */ - BLI_uniquename(&gpd->layers, new_layer, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(new_layer->info)); - gpencil_layer_setactive(gpd, new_layer); - - /* notifiers */ - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - - return OPERATOR_FINISHED; -} - -void GPENCIL_OT_layer_duplicate(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Duplicate Layer"; - ot->idname = "GPENCIL_OT_layer_duplicate"; - ot->description = "Make a copy of the active Grease Pencil layer"; - - /* callbacks */ - ot->exec = gp_layer_copy_exec; - ot->poll = gp_active_layer_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - /* ************************************************ */ /* Stroke Editing Operators */ @@ -1256,1398 +815,3 @@ void GPENCIL_OT_delete(wmOperatorType *ot) } /* ************************************************ */ -/* Grease Pencil to Data Operator */ - -/* defines for possible modes */ -enum { - GP_STROKECONVERT_PATH = 1, - GP_STROKECONVERT_CURVE, - GP_STROKECONVERT_POLY, -}; - -/* Defines for possible timing modes */ -enum { - GP_STROKECONVERT_TIMING_NONE = 1, - GP_STROKECONVERT_TIMING_LINEAR = 2, - GP_STROKECONVERT_TIMING_FULL = 3, - GP_STROKECONVERT_TIMING_CUSTOMGAP = 4, -}; - -/* RNA enum define */ -static EnumPropertyItem prop_gpencil_convertmodes[] = { - {GP_STROKECONVERT_PATH, "PATH", 0, "Path", ""}, - {GP_STROKECONVERT_CURVE, "CURVE", 0, "Bezier Curve", ""}, - {GP_STROKECONVERT_POLY, "POLY", 0, "Polygon Curve", ""}, - {0, NULL, 0, NULL, NULL} -}; - -static EnumPropertyItem prop_gpencil_convert_timingmodes_restricted[] = { - {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"}, - {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"}, - {0, NULL, 0, NULL, NULL}, -}; - -static EnumPropertyItem prop_gpencil_convert_timingmodes[] = { - {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"}, - {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"}, - {GP_STROKECONVERT_TIMING_FULL, "FULL", 0, "Original", "Use the original timing, gaps included"}, - {GP_STROKECONVERT_TIMING_CUSTOMGAP, "CUSTOMGAP", 0, "Custom Gaps", - "Use the original timing, but with custom gap lengths (in frames)"}, - {0, NULL, 0, NULL, NULL}, -}; - -static EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), - bool *UNUSED(r_free)) -{ - if (RNA_boolean_get(ptr, "use_timing_data")) { - return prop_gpencil_convert_timingmodes; - } - return prop_gpencil_convert_timingmodes_restricted; -} - -/* --- */ - -/* convert the coordinates from the given stroke point into 3d-coordinates - * - assumes that the active space is the 3D-View - */ -static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoint *pt, float p3d[3], rctf *subrect) -{ - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - ARegion *ar = CTX_wm_region(C); - - if (gps->flag & GP_STROKE_3DSPACE) { - /* directly use 3d-coordinates */ - copy_v3_v3(p3d, &pt->x); - } - else { - const float *fp = ED_view3d_cursor3d_get(scene, v3d); - float mvalf[2]; - - /* get screen coordinate */ - if (gps->flag & GP_STROKE_2DSPACE) { - View2D *v2d = &ar->v2d; - UI_view2d_view_to_region_fl(v2d, pt->x, pt->y, &mvalf[0], &mvalf[1]); - } - else { - if (subrect) { - mvalf[0] = (((float)pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin; - mvalf[1] = (((float)pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin; - } - else { - mvalf[0] = (float)pt->x / 100.0f * ar->winx; - mvalf[1] = (float)pt->y / 100.0f * ar->winy; - } - } - - ED_view3d_win_to_3d(ar, fp, mvalf, p3d); - } -} - -/* --- */ - -/* temp struct for gp_stroke_path_animation() */ -typedef struct tGpTimingData { - /* Data set from operator settings */ - int mode; - int frame_range; /* Number of frames evaluated for path animation */ - int start_frame, end_frame; - bool realtime; /* Will overwrite end_frame in case of Original or CustomGap timing... */ - float gap_duration, gap_randomness; /* To be used with CustomGap mode*/ - int seed; - - /* Data set from points, used to compute final timing FCurve */ - int num_points, cur_point; - - /* Distances */ - float *dists; - float tot_dist; - - /* Times */ - float *times; /* Note: Gap times will be negative! */ - float tot_time, gap_tot_time; - double inittime; - - /* Only used during creation of dists & times lists. */ - float offset_time; -} tGpTimingData; - -/* Init point buffers for timing data. - * Note this assumes we only grow those arrays! - */ -static void gp_timing_data_set_nbr(tGpTimingData *gtd, const int nbr) -{ - float *tmp; - - BLI_assert(nbr > gtd->num_points); - - /* distances */ - tmp = gtd->dists; - gtd->dists = MEM_callocN(sizeof(float) * nbr, __func__); - if (tmp) { - memcpy(gtd->dists, tmp, sizeof(float) * gtd->num_points); - MEM_freeN(tmp); - } - - /* times */ - tmp = gtd->times; - gtd->times = MEM_callocN(sizeof(float) * nbr, __func__); - if (tmp) { - memcpy(gtd->times, tmp, sizeof(float) * gtd->num_points); - MEM_freeN(tmp); - } - - gtd->num_points = nbr; -} - -/* add stroke point to timing buffers */ -static void gp_timing_data_add_point(tGpTimingData *gtd, const double stroke_inittime, const float time, - const float delta_dist) -{ - float delta_time = 0.0f; - const int cur_point = gtd->cur_point; - - if (!cur_point) { - /* Special case, first point, if time is not 0.0f we have to compensate! */ - gtd->offset_time = -time; - gtd->times[cur_point] = 0.0f; - } - else if (time < 0.0f) { - /* This is a gap, negative value! */ - gtd->times[cur_point] = -(((float)(stroke_inittime - gtd->inittime)) + time + gtd->offset_time); - delta_time = -gtd->times[cur_point] - gtd->times[cur_point - 1]; - - gtd->gap_tot_time += delta_time; - } - else { - gtd->times[cur_point] = (((float)(stroke_inittime - gtd->inittime)) + time + gtd->offset_time); - delta_time = gtd->times[cur_point] - fabsf(gtd->times[cur_point - 1]); - } - - gtd->tot_time += delta_time; - gtd->tot_dist += delta_dist; - gtd->dists[cur_point] = gtd->tot_dist; - - gtd->cur_point++; -} - -/* In frames! Binary search for FCurve keys have a threshold of 0.01, so we can't set - * arbitrarily close points - this is esp. important with NoGaps mode! - */ -#define MIN_TIME_DELTA 0.02f - -/* Loop over next points to find the end of the stroke, and compute */ -static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, RNG *rng, const int idx, const int nbr_gaps, - int *nbr_done_gaps, const float tot_gaps_time, const float delta_time, - float *next_delta_time) -{ - int j; - - for (j = idx + 1; j < gtd->num_points; j++) { - if (gtd->times[j] < 0) { - gtd->times[j] = -gtd->times[j]; - if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { - /* In this mode, gap time between this stroke and the next should be 0 currently... - * So we have to compute its final duration! - */ - if (gtd->gap_randomness > 0.0f) { - /* We want gaps that are in gtd->gap_duration +/- gtd->gap_randomness range, - * and which sum to exactly tot_gaps_time... - */ - int rem_gaps = nbr_gaps - (*nbr_done_gaps); - if (rem_gaps < 2) { - /* Last gap, just give remaining time! */ - *next_delta_time = tot_gaps_time; - } - else { - float delta, min, max; - - /* This code ensures that if the first gaps have been shorter than average gap_duration, - * next gaps will tend to be longer (i.e. try to recover the lateness), and vice-versa! - */ - delta = delta_time - (gtd->gap_duration * (*nbr_done_gaps)); - - /* Clamp min between [-gap_randomness, 0.0], with lower delta giving higher min */ - min = -gtd->gap_randomness - delta; - CLAMP(min, -gtd->gap_randomness, 0.0f); - - /* Clamp max between [0.0, gap_randomness], with lower delta giving higher max */ - max = gtd->gap_randomness - delta; - CLAMP(max, 0.0f, gtd->gap_randomness); - *next_delta_time += gtd->gap_duration + (BLI_rng_get_float(rng) * (max - min)) + min; - } - } - else { - *next_delta_time += gtd->gap_duration; - } - } - (*nbr_done_gaps)++; - break; - } - } - - return j - 1; -} - -static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, RNG *rng, int *nbr_gaps, float *tot_gaps_time) -{ - int i; - float delta_time = 0.0f; - - for (i = 0; i < gtd->num_points; i++) { - if (gtd->times[i] < 0 && i) { - (*nbr_gaps)++; - gtd->times[i] = -gtd->times[i] - delta_time; - delta_time += gtd->times[i] - gtd->times[i - 1]; - gtd->times[i] = -gtd->times[i - 1]; /* Temp marker, values *have* to be different! */ - } - else { - gtd->times[i] -= delta_time; - } - } - gtd->tot_time -= delta_time; - - *tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration; - gtd->tot_time += *tot_gaps_time; - if (G.debug & G_DEBUG) { - printf("%f, %f, %f, %d\n", gtd->tot_time, delta_time, *tot_gaps_time, *nbr_gaps); - } - if (gtd->gap_randomness > 0.0f) { - BLI_rng_srandom(rng, gtd->seed); - } -} - -static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, - Curve *cu, tGpTimingData *gtd, RNG *rng, const float time_range, - const int nbr_gaps, const float tot_gaps_time) -{ - /* Use actual recorded timing! */ - const float time_start = (float)gtd->start_frame; - - float last_valid_time = 0.0f; - int end_stroke_idx = -1, start_stroke_idx = 0; - float end_stroke_time = 0.0f; - - /* CustomGaps specific */ - float delta_time = 0.0f, next_delta_time = 0.0f; - int nbr_done_gaps = 0; - - int i; - float cfra; - - /* This is a bit tricky, as: - * - We can't add arbitrarily close points on FCurve (in time). - * - We *must* have all "caps" points of all strokes in FCurve, as much as possible! - */ - for (i = 0; i < gtd->num_points; i++) { - /* If new stroke... */ - if (i > end_stroke_idx) { - start_stroke_idx = i; - delta_time = next_delta_time; - /* find end of that new stroke */ - end_stroke_idx = gp_find_end_of_stroke_idx(gtd, rng, i, nbr_gaps, &nbr_done_gaps, - tot_gaps_time, delta_time, &next_delta_time); - /* This one should *never* be negative! */ - end_stroke_time = time_start + ((gtd->times[end_stroke_idx] + delta_time) / gtd->tot_time * time_range); - } - - /* Simple proportional stuff... */ - cu->ctime = gtd->dists[i] / gtd->tot_dist * cu->pathlen; - cfra = time_start + ((gtd->times[i] + delta_time) / gtd->tot_time * time_range); - - /* And now, the checks about timing... */ - if (i == start_stroke_idx) { - /* If first point of a stroke, be sure it's enough ahead of last valid keyframe, and - * that the end point of the stroke is far enough! - * In case it is not, we keep the end point... - * Note that with CustomGaps mode, this is here we set the actual gap timing! - */ - if ((end_stroke_time - last_valid_time) > MIN_TIME_DELTA * 2) { - if ((cfra - last_valid_time) < MIN_TIME_DELTA) { - cfra = last_valid_time + MIN_TIME_DELTA; - } - insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); - last_valid_time = cfra; - } - else if (G.debug & G_DEBUG) { - printf("\t Skipping start point %d, too close from end point %d\n", i, end_stroke_idx); - } - } - else if (i == end_stroke_idx) { - /* Always try to insert end point of a curve (should be safe enough, anyway...) */ - if ((cfra - last_valid_time) < MIN_TIME_DELTA) { - cfra = last_valid_time + MIN_TIME_DELTA; - } - insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); - last_valid_time = cfra; - } - else { - /* Else ("middle" point), we only insert it if it's far enough from last keyframe, - * and also far enough from (not yet added!) end_stroke keyframe! - */ - if ((cfra - last_valid_time) > MIN_TIME_DELTA && (end_stroke_time - cfra) > MIN_TIME_DELTA) { - insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); - last_valid_time = cfra; - } - else if (G.debug & G_DEBUG) { - printf("\t Skipping \"middle\" point %d, too close from last added point or end point %d\n", - i, end_stroke_idx); - } - } - } -} - -static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu, tGpTimingData *gtd) -{ - Scene *scene = CTX_data_scene(C); - bAction *act; - FCurve *fcu; - PointerRNA ptr; - PropertyRNA *prop = NULL; - int nbr_gaps = 0, i; - - if (gtd->mode == GP_STROKECONVERT_TIMING_NONE) - return; - - /* gap_duration and gap_randomness are in frames, but we need seconds!!! */ - gtd->gap_duration = FRA2TIME(gtd->gap_duration); - gtd->gap_randomness = FRA2TIME(gtd->gap_randomness); - - /* Enable path! */ - cu->flag |= CU_PATH; - cu->pathlen = gtd->frame_range; - - /* Get RNA pointer to read/write path time values */ - RNA_id_pointer_create((ID *)cu, &ptr); - prop = RNA_struct_find_property(&ptr, "eval_time"); - - /* Ensure we have an F-Curve to add keyframes to */ - act = verify_adt_action((ID *)cu, true); - fcu = verify_fcurve(act, NULL, &ptr, "eval_time", 0, true); - - if (G.debug & G_DEBUG) { - printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time); - for (i = 0; i < gtd->num_points; i++) { - printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]); - } - } - - if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) { - float cfra; - - /* Linear extrapolation! */ - fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; - - cu->ctime = 0.0f; - cfra = (float)gtd->start_frame; - insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); - - cu->ctime = cu->pathlen; - if (gtd->realtime) { - cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */ - } - else { - cfra = (float)gtd->end_frame; - } - insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); - } - else { - /* Use actual recorded timing! */ - RNG *rng = BLI_rng_new(0); - float time_range; - - /* CustomGaps specific */ - float tot_gaps_time = 0.0f; - - /* Pre-process gaps, in case we don't want to keep their original timing */ - if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { - gp_stroke_path_animation_preprocess_gaps(gtd, rng, &nbr_gaps, &tot_gaps_time); - } - - if (gtd->realtime) { - time_range = (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */ - } - else { - time_range = (float)(gtd->end_frame - gtd->start_frame); - } - - if (G.debug & G_DEBUG) { - printf("GP Stroke Path Conversion: Starting keying!\n"); - } - - gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, rng, time_range, - nbr_gaps, tot_gaps_time); - - BLI_rng_free(rng); - } - - /* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */ - calchandles_fcurve(fcu); - - if (G.debug & G_DEBUG) { - printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time); - for (i = 0; i < gtd->num_points; i++) { - printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]); - } - printf("\n\n"); - } - - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - - /* send updates */ - DAG_id_tag_update(&cu->id, 0); -} - -#undef MIN_TIME_DELTA - -#define GAP_DFAC 0.01f -#define WIDTH_CORR_FAC 0.1f -#define BEZT_HANDLE_FAC 0.3f - -/* convert stroke to 3d path */ - -/* helper */ -static void gp_stroke_to_path_add_point(tGpTimingData *gtd, BPoint *bp, const float p[3], const float prev_p[3], - const bool do_gtd, const double inittime, const float time, - const float width, const float rad_fac, float minmax_weights[2]) -{ - copy_v3_v3(bp->vec, p); - bp->vec[3] = 1.0f; - - /* set settings */ - bp->f1 = SELECT; - bp->radius = width * rad_fac; - bp->weight = width; - CLAMP(bp->weight, 0.0f, 1.0f); - if (bp->weight < minmax_weights[0]) { - minmax_weights[0] = bp->weight; - } - else if (bp->weight > minmax_weights[1]) { - minmax_weights[1] = bp->weight; - } - - /* Update timing data */ - if (do_gtd) { - gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p)); - } -} - -static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu, - float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point, - const bool add_end_point, tGpTimingData *gtd) -{ - bGPDspoint *pt; - Nurb *nu = (curnu) ? *curnu : NULL; - BPoint *bp, *prev_bp = NULL; - const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE); - const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0); - int i, old_nbp = 0; - - /* create new 'nurb' or extend current one within the curve */ - if (nu) { - old_nbp = nu->pntsu; - - /* If stitch, the first point of this stroke is already present in current nu. - * Else, we have to add two additional points to make the zero-radius link between strokes. - */ - BKE_nurb_points_add(nu, gps->totpoints + (stitch ? -1 : 2) + add_start_end_points); - } - else { - nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)"); - - nu->pntsu = gps->totpoints + add_start_end_points; - nu->pntsv = 1; - nu->orderu = 2; /* point-to-point! */ - nu->type = CU_NURBS; - nu->flagu = CU_NURB_ENDPOINT; - nu->resolu = cu->resolu; - nu->resolv = cu->resolv; - nu->knotsu = NULL; - - nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "bpoints"); - - stitch = false; /* Security! */ - } - - if (do_gtd) { - gp_timing_data_set_nbr(gtd, nu->pntsu); - } - - /* If needed, make the link between both strokes with two zero-radius additional points */ - /* About "zero-radius" point interpolations: - * - If we have at least two points in current curve (most common case), we linearly extrapolate - * the last segment to get the first point (p1) position and timing. - * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point - * with the first point of the current stroke. - * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated - * if it exists, else (if the stroke is a single point), linear interpolation with last curve point... - */ - if (curnu && !stitch && old_nbp) { - float p1[3], p2[3], p[3], next_p[3]; - float dt1 = 0.0f, dt2 = 0.0f; - - BLI_assert(gps->prev != NULL); - - prev_bp = NULL; - if ((old_nbp > 1) && (gps->prev->totpoints > 1)) { - /* Only use last curve segment if previous stroke was not a single-point one! */ - prev_bp = &nu->bp[old_nbp - 2]; - } - bp = &nu->bp[old_nbp - 1]; - - /* First point */ - gp_strokepoint_convertcoords(C, gps, gps->points, p, subrect); - if (prev_bp) { - interp_v3_v3v3(p1, bp->vec, prev_bp->vec, -GAP_DFAC); - if (do_gtd) { - const int idx = gps->prev->totpoints - 1; - dt1 = interpf(gps->prev->points[idx - 1].time, gps->prev->points[idx].time, -GAP_DFAC); - } - } - else { - interp_v3_v3v3(p1, bp->vec, p, GAP_DFAC); - if (do_gtd) { - dt1 = interpf(gps->inittime - gps->prev->inittime, 0.0f, GAP_DFAC); - } - } - bp++; - gp_stroke_to_path_add_point(gtd, bp, p1, (bp - 1)->vec, do_gtd, gps->prev->inittime, dt1, - 0.0f, rad_fac, minmax_weights); - - /* Second point */ - /* Note dt2 is always negative, which marks the gap. */ - if (gps->totpoints > 1) { - gp_strokepoint_convertcoords(C, gps, gps->points + 1, next_p, subrect); - interp_v3_v3v3(p2, p, next_p, -GAP_DFAC); - if (do_gtd) { - dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC); - } - } - else { - interp_v3_v3v3(p2, p, bp->vec, GAP_DFAC); - if (do_gtd) { - dt2 = interpf(gps->prev->inittime - gps->inittime, 0.0f, GAP_DFAC); - } - } - bp++; - gp_stroke_to_path_add_point(gtd, bp, p2, p1, do_gtd, gps->inittime, dt2, 0.0f, rad_fac, minmax_weights); - - old_nbp += 2; - } - else if (add_start_point) { - float p[3], next_p[3]; - float dt = 0.0f; - - gp_strokepoint_convertcoords(C, gps, gps->points, p, subrect); - if (gps->totpoints > 1) { - gp_strokepoint_convertcoords(C, gps, gps->points + 1, next_p, subrect); - interp_v3_v3v3(p, p, next_p, -GAP_DFAC); - if (do_gtd) { - dt = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC); - } - } - else { - p[0] -= GAP_DFAC; /* Rather arbitrary... */ - dt = -GAP_DFAC; /* Rather arbitrary too! */ - } - bp = &nu->bp[old_nbp]; - /* Note we can't give anything else than 0.0 as time here, since a negative one (which would be expected value) - * would not work (it would be *before* gtd->inittime, which is not supported currently). - */ - gp_stroke_to_path_add_point(gtd, bp, p, p, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights); - - old_nbp++; - } - - if (old_nbp) { - prev_bp = &nu->bp[old_nbp - 1]; - } - - /* add points */ - for (i = (stitch) ? 1 : 0, pt = &gps->points[(stitch) ? 1 : 0], bp = &nu->bp[old_nbp]; - i < gps->totpoints; - i++, pt++, bp++) - { - float p[3]; - float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC; - - /* get coordinates to add at */ - gp_strokepoint_convertcoords(C, gps, pt, p, subrect); - - gp_stroke_to_path_add_point(gtd, bp, p, (prev_bp) ? prev_bp->vec : p, do_gtd, gps->inittime, pt->time, - width, rad_fac, minmax_weights); - - prev_bp = bp; - } - - if (add_end_point) { - float p[3]; - float dt = 0.0f; - - if (gps->totpoints > 1) { - interp_v3_v3v3(p, prev_bp->vec, (prev_bp - 1)->vec, -GAP_DFAC); - if (do_gtd) { - const int idx = gps->totpoints - 1; - dt = interpf(gps->points[idx - 1].time, gps->points[idx].time, -GAP_DFAC); - } - } - else { - copy_v3_v3(p, prev_bp->vec); - p[0] += GAP_DFAC; /* Rather arbitrary... */ - dt = GAP_DFAC; /* Rather arbitrary too! */ - } - /* Note bp has already been incremented in main loop above, so it points to the right place. */ - gp_stroke_to_path_add_point(gtd, bp, p, prev_bp->vec, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights); - } - - /* add nurb to curve */ - if (!curnu || !*curnu) { - BLI_addtail(&cu->nurb, nu); - } - if (curnu) { - *curnu = nu; - } - - BKE_nurb_knot_calc_u(nu); -} - -/* convert stroke to 3d bezier */ - -/* helper */ -static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, BezTriple *bezt, - const float p[3], const float h1[3], const float h2[3], const float prev_p[3], - const bool do_gtd, const double inittime, const float time, - const float width, const float rad_fac, float minmax_weights[2]) -{ - copy_v3_v3(bezt->vec[0], h1); - copy_v3_v3(bezt->vec[1], p); - copy_v3_v3(bezt->vec[2], h2); - - /* set settings */ - bezt->h1 = bezt->h2 = HD_FREE; - bezt->f1 = bezt->f2 = bezt->f3 = SELECT; - bezt->radius = width * rad_fac; - bezt->weight = width; - CLAMP(bezt->weight, 0.0f, 1.0f); - if (bezt->weight < minmax_weights[0]) { - minmax_weights[0] = bezt->weight; - } - else if (bezt->weight > minmax_weights[1]) { - minmax_weights[1] = bezt->weight; - } - - /* Update timing data */ - if (do_gtd) { - gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p)); - } -} - -static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu, - float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point, - const bool add_end_point, tGpTimingData *gtd) -{ - bGPDspoint *pt; - Nurb *nu = (curnu) ? *curnu : NULL; - BezTriple *bezt, *prev_bezt = NULL; - int i, tot, old_nbezt = 0; - const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0); - float p3d_cur[3], p3d_prev[3], p3d_next[3], h1[3], h2[3]; - const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE); - - /* create new 'nurb' or extend current one within the curve */ - if (nu) { - old_nbezt = nu->pntsu; - /* If we do stitch, first point of current stroke is assumed the same as last point of previous stroke, - * so no need to add it. - * If no stitch, we want to add two additional points to make a "zero-radius" link between both strokes. - */ - BKE_nurb_bezierPoints_add(nu, gps->totpoints + ((stitch) ? -1 : 2) + add_start_end_points); - } - else { - nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)"); - - nu->pntsu = gps->totpoints + add_start_end_points; - nu->resolu = 12; - nu->resolv = 12; - nu->type = CU_BEZIER; - nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * nu->pntsu, "bezts"); - - stitch = false; /* Security! */ - } - - if (do_gtd) { - gp_timing_data_set_nbr(gtd, nu->pntsu); - } - - tot = gps->totpoints; - - /* get initial coordinates */ - pt = gps->points; - if (tot) { - gp_strokepoint_convertcoords(C, gps, pt, (stitch) ? p3d_prev : p3d_cur, subrect); - if (tot > 1) { - gp_strokepoint_convertcoords(C, gps, pt + 1, (stitch) ? p3d_cur : p3d_next, subrect); - } - if (stitch && tot > 2) { - gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect); - } - } - - /* If needed, make the link between both strokes with two zero-radius additional points */ - if (curnu && old_nbezt) { - BLI_assert(gps->prev != NULL); - - /* Update last point's second handle */ - if (stitch) { - bezt = &nu->bezt[old_nbezt - 1]; - interp_v3_v3v3(h2, bezt->vec[1], p3d_cur, BEZT_HANDLE_FAC); - copy_v3_v3(bezt->vec[2], h2); - pt++; - } - - /* Create "link points" */ - /* About "zero-radius" point interpolations: - * - If we have at least two points in current curve (most common case), we linearly extrapolate - * the last segment to get the first point (p1) position and timing. - * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point - * with the first point of the current stroke. - * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated - * if it exists, else (if the stroke is a single point), linear interpolation with last curve point... - */ - else { - float p1[3], p2[3]; - float dt1 = 0.0f, dt2 = 0.0f; - - prev_bezt = NULL; - if ((old_nbezt > 1) && (gps->prev->totpoints > 1)) { - /* Only use last curve segment if previous stroke was not a single-point one! */ - prev_bezt = &nu->bezt[old_nbezt - 2]; - } - bezt = &nu->bezt[old_nbezt - 1]; - - /* First point */ - if (prev_bezt) { - interp_v3_v3v3(p1, prev_bezt->vec[1], bezt->vec[1], 1.0f + GAP_DFAC); - if (do_gtd) { - const int idx = gps->prev->totpoints - 1; - dt1 = interpf(gps->prev->points[idx - 1].time, gps->prev->points[idx].time, -GAP_DFAC); - } - } - else { - interp_v3_v3v3(p1, bezt->vec[1], p3d_cur, GAP_DFAC); - if (do_gtd) { - dt1 = interpf(gps->inittime - gps->prev->inittime, 0.0f, GAP_DFAC); - } - } - - /* Second point */ - /* Note dt2 is always negative, which marks the gap. */ - if (tot > 1) { - interp_v3_v3v3(p2, p3d_cur, p3d_next, -GAP_DFAC); - if (do_gtd) { - dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC); - } - } - else { - interp_v3_v3v3(p2, p3d_cur, bezt->vec[1], GAP_DFAC); - if (do_gtd) { - dt2 = interpf(gps->prev->inittime - gps->inittime, 0.0f, GAP_DFAC); - } - } - - /* Second handle of last point of previous stroke. */ - interp_v3_v3v3(h2, bezt->vec[1], p1, BEZT_HANDLE_FAC); - copy_v3_v3(bezt->vec[2], h2); - - /* First point */ - interp_v3_v3v3(h1, p1, bezt->vec[1], BEZT_HANDLE_FAC); - interp_v3_v3v3(h2, p1, p2, BEZT_HANDLE_FAC); - bezt++; - gp_stroke_to_bezier_add_point(gtd, bezt, p1, h1, h2, (bezt - 1)->vec[1], do_gtd, gps->prev->inittime, dt1, - 0.0f, rad_fac, minmax_weights); - - /* Second point */ - interp_v3_v3v3(h1, p2, p1, BEZT_HANDLE_FAC); - interp_v3_v3v3(h2, p2, p3d_cur, BEZT_HANDLE_FAC); - bezt++; - gp_stroke_to_bezier_add_point(gtd, bezt, p2, h1, h2, p1, do_gtd, gps->inittime, dt2, - 0.0f, rad_fac, minmax_weights); - - old_nbezt += 2; - copy_v3_v3(p3d_prev, p2); - } - } - else if (add_start_point) { - float p[3]; - float dt = 0.0f; - - if (gps->totpoints > 1) { - interp_v3_v3v3(p, p3d_cur, p3d_next, -GAP_DFAC); - if (do_gtd) { - dt = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC); - } - } - else { - copy_v3_v3(p, p3d_cur); - p[0] -= GAP_DFAC; /* Rather arbitrary... */ - dt = -GAP_DFAC; /* Rather arbitrary too! */ - } - interp_v3_v3v3(h1, p, p3d_cur, -BEZT_HANDLE_FAC); - interp_v3_v3v3(h2, p, p3d_cur, BEZT_HANDLE_FAC); - bezt = &nu->bezt[old_nbezt]; - gp_stroke_to_bezier_add_point(gtd, bezt, p, h1, h2, p, do_gtd, gps->inittime, dt, - 0.0f, rad_fac, minmax_weights); - - old_nbezt++; - copy_v3_v3(p3d_prev, p); - } - - if (old_nbezt) { - prev_bezt = &nu->bezt[old_nbezt - 1]; - } - - /* add points */ - for (i = stitch ? 1 : 0, bezt = &nu->bezt[old_nbezt]; i < tot; i++, pt++, bezt++) { - float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC; - - if (i || old_nbezt) { - interp_v3_v3v3(h1, p3d_cur, p3d_prev, BEZT_HANDLE_FAC); - } - else { - interp_v3_v3v3(h1, p3d_cur, p3d_next, -BEZT_HANDLE_FAC); - } - - if (i < tot - 1) { - interp_v3_v3v3(h2, p3d_cur, p3d_next, BEZT_HANDLE_FAC); - } - else { - interp_v3_v3v3(h2, p3d_cur, p3d_prev, -BEZT_HANDLE_FAC); - } - - gp_stroke_to_bezier_add_point(gtd, bezt, p3d_cur, h1, h2, prev_bezt ? prev_bezt->vec[1] : p3d_cur, - do_gtd, gps->inittime, pt->time, width, rad_fac, minmax_weights); - - /* shift coord vects */ - copy_v3_v3(p3d_prev, p3d_cur); - copy_v3_v3(p3d_cur, p3d_next); - - if (i + 2 < tot) { - gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect); - } - - prev_bezt = bezt; - } - - if (add_end_point) { - float p[3]; - float dt = 0.0f; - - if (gps->totpoints > 1) { - interp_v3_v3v3(p, prev_bezt->vec[1], (prev_bezt - 1)->vec[1], -GAP_DFAC); - if (do_gtd) { - const int idx = gps->totpoints - 1; - dt = interpf(gps->points[idx - 1].time, gps->points[idx].time, -GAP_DFAC); - } - } - else { - copy_v3_v3(p, prev_bezt->vec[1]); - p[0] += GAP_DFAC; /* Rather arbitrary... */ - dt = GAP_DFAC; /* Rather arbitrary too! */ - } - - /* Second handle of last point of this stroke. */ - interp_v3_v3v3(h2, prev_bezt->vec[1], p, BEZT_HANDLE_FAC); - copy_v3_v3(prev_bezt->vec[2], h2); - - /* The end point */ - interp_v3_v3v3(h1, p, prev_bezt->vec[1], BEZT_HANDLE_FAC); - interp_v3_v3v3(h2, p, prev_bezt->vec[1], -BEZT_HANDLE_FAC); - /* Note bezt has already been incremented in main loop above, so it points to the right place. */ - gp_stroke_to_bezier_add_point(gtd, bezt, p, h1, h2, prev_bezt->vec[1], do_gtd, gps->inittime, dt, - 0.0f, rad_fac, minmax_weights); - } - - /* must calculate handles or else we crash */ - BKE_nurb_handles_calc(nu); - - if (!curnu || !*curnu) { - BLI_addtail(&cu->nurb, nu); - } - if (curnu) { - *curnu = nu; - } -} - -#undef GAP_DFAC -#undef WIDTH_CORR_FAC -#undef BEZT_HANDLE_FAC - -static void gp_stroke_finalize_curve_endpoints(Curve *cu) -{ - /* start */ - Nurb *nu = cu->nurb.first; - int i = 0; - if (nu->bezt) { - BezTriple *bezt = nu->bezt; - if (bezt) { - bezt[i].weight = bezt[i].radius = 0.0f; - } - } - else if (nu->bp) { - BPoint *bp = nu->bp; - if (bp) { - bp[i].weight = bp[i].radius = 0.0f; - } - } - - /* end */ - nu = cu->nurb.last; - i = nu->pntsu - 1; - if (nu->bezt) { - BezTriple *bezt = nu->bezt; - if (bezt) { - bezt[i].weight = bezt[i].radius = 0.0f; - } - } - else if (nu->bp) { - BPoint *bp = nu->bp; - if (bp) { - bp[i].weight = bp[i].radius = 0.0f; - } - } -} - -static void gp_stroke_norm_curve_weights(Curve *cu, const float minmax_weights[2]) -{ - Nurb *nu; - const float delta = minmax_weights[0]; - float fac; - int i; - - /* when delta == minmax_weights[0] == minmax_weights[1], we get div by zero [#35686] */ - if (IS_EQF(delta, minmax_weights[1])) - fac = 1.0f; - else - fac = 1.0f / (minmax_weights[1] - delta); - - for (nu = cu->nurb.first; nu; nu = nu->next) { - if (nu->bezt) { - BezTriple *bezt = nu->bezt; - for (i = 0; i < nu->pntsu; i++, bezt++) { - bezt->weight = (bezt->weight - delta) * fac; - } - } - else if (nu->bp) { - BPoint *bp = nu->bp; - for (i = 0; i < nu->pntsu; i++, bp++) { - bp->weight = (bp->weight - delta) * fac; - } - } - } -} - -static int gp_camera_view_subrect(bContext *C, rctf *subrect) -{ - View3D *v3d = CTX_wm_view3d(C); - ARegion *ar = CTX_wm_region(C); - - if (v3d) { - RegionView3D *rv3d = ar->regiondata; - - /* for camera view set the subrect */ - if (rv3d->persp == RV3D_CAMOB) { - Scene *scene = CTX_data_scene(C); - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, subrect, true); /* no shift */ - return 1; - } - } - - return 0; -} - -/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */ -static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bGPDlayer *gpl, const int mode, - const bool norm_weights, const float rad_fac, const bool link_strokes, tGpTimingData *gtd) -{ - struct Main *bmain = CTX_data_main(C); - View3D *v3d = CTX_wm_view3d(C); /* may be NULL */ - Scene *scene = CTX_data_scene(C); - bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); - bGPDstroke *gps, *prev_gps = NULL; - Object *ob; - Curve *cu; - Nurb *nu = NULL; - Base *base_orig = BASACT, *base_new = NULL; - float minmax_weights[2] = {1.0f, 0.0f}; - - /* camera framing */ - rctf subrect, *subrect_ptr = NULL; - - /* error checking */ - if (ELEM(NULL, gpd, gpl, gpf)) - return; - - /* only convert if there are any strokes on this layer's frame to convert */ - if (BLI_listbase_is_empty(&gpf->strokes)) - return; - - /* initialize camera framing */ - if (gp_camera_view_subrect(C, &subrect)) { - subrect_ptr = &subrect; - } - - /* init the curve object (remove rotation and get curve data from it) - * - must clear transforms set on object, as those skew our results - */ - ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info); - cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE); - base_new = BKE_scene_base_add(scene, ob); - - cu->flag |= CU_3D; - - gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime; - - /* add points to curve */ - for (gps = gpf->strokes.first; gps; gps = gps->next) { - const bool add_start_point = (link_strokes && !(prev_gps)); - const bool add_end_point = (link_strokes && !(gps->next)); - - /* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached, and stitch them to previous one. */ - bool stitch = false; - if (prev_gps) { - bGPDspoint *pt1 = &prev_gps->points[prev_gps->totpoints - 1]; - bGPDspoint *pt2 = &gps->points[0]; - - if ((pt1->x == pt2->x) && (pt1->y == pt2->y)) { - stitch = true; - } - } - - /* Decide whether we connect this stroke to previous one */ - if (!(stitch || link_strokes)) { - nu = NULL; - } - - switch (mode) { - case GP_STROKECONVERT_PATH: - gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, - add_start_point, add_end_point, gtd); - break; - case GP_STROKECONVERT_CURVE: - case GP_STROKECONVERT_POLY: /* convert after */ - gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, - add_start_point, add_end_point, gtd); - break; - default: - BLI_assert(!"invalid mode"); - break; - } - prev_gps = gps; - } - - /* If link_strokes, be sure first and last points have a zero weight/size! */ - if (link_strokes) { - gp_stroke_finalize_curve_endpoints(cu); - } - - /* Update curve's weights, if needed */ - if (norm_weights && ((minmax_weights[0] > 0.0f) || (minmax_weights[1] < 1.0f))) { - gp_stroke_norm_curve_weights(cu, minmax_weights); - } - - /* Create the path animation, if needed */ - gp_stroke_path_animation(C, reports, cu, gtd); - - if (mode == GP_STROKECONVERT_POLY) { - for (nu = cu->nurb.first; nu; nu = nu->next) { - BKE_nurb_type_convert(nu, CU_POLY, false); - } - } - - /* set the layer and select */ - base_new->lay = ob->lay = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene); - base_new->flag = ob->flag = base_new->flag | SELECT; -} - -/* --- */ - -/* Check a GP layer has valid timing data! Else, most timing options are hidden in the operator. - * op may be NULL. - */ -static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op) -{ - Scene *scene = CTX_data_scene(C); - bGPDframe *gpf = NULL; - bGPDstroke *gps = NULL; - bGPDspoint *pt; - double base_time, cur_time, prev_time = -1.0; - int i; - bool valid = true; - - if (!gpl || !(gpf = gpencil_layer_getframe(gpl, CFRA, 0)) || !(gps = gpf->strokes.first)) - return false; - - do { - base_time = cur_time = gps->inittime; - if (cur_time <= prev_time) { - valid = false; - break; - } - - prev_time = cur_time; - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - cur_time = base_time + (double)pt->time; - /* First point of a stroke should have the same time as stroke's inittime, - * so it's the only case where equality is allowed! - */ - if ((i && cur_time <= prev_time) || (cur_time < prev_time)) { - valid = false; - break; - } - prev_time = cur_time; - } - - if (!valid) { - break; - } - } while ((gps = gps->next)); - - if (op) { - RNA_boolean_set(op->ptr, "use_timing_data", valid); - } - return valid; -} - -/* Check end_frame is always > start frame! */ -static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UNUSED(scene), struct PointerRNA *ptr) -{ - int start_frame = RNA_int_get(ptr, "start_frame"); - int end_frame = RNA_int_get(ptr, "end_frame"); - - if (end_frame <= start_frame) { - RNA_int_set(ptr, "end_frame", start_frame + 1); - } -} - -static int gp_convert_poll(bContext *C) -{ - bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = NULL; - bGPDframe *gpf = NULL; - ScrArea *sa = CTX_wm_area(C); - Scene *scene = CTX_data_scene(C); - - /* only if the current view is 3D View, if there's valid data (i.e. at least one stroke!), - * and if we are not in edit mode! - */ - return ((sa && sa->spacetype == SPACE_VIEW3D) && - (gpl = gpencil_layer_getactive(gpd)) && - (gpf = gpencil_layer_getframe(gpl, CFRA, 0)) && - (gpf->strokes.first) && - (scene->obedit == NULL)); -} - -static int gp_convert_layer_exec(bContext *C, wmOperator *op) -{ - PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_timing_data"); - bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = gpencil_layer_getactive(gpd); - Scene *scene = CTX_data_scene(C); - const int mode = RNA_enum_get(op->ptr, "type"); - const bool norm_weights = RNA_boolean_get(op->ptr, "use_normalize_weights"); - const float rad_fac = RNA_float_get(op->ptr, "radius_multiplier"); - const bool link_strokes = RNA_boolean_get(op->ptr, "use_link_strokes"); - bool valid_timing; - tGpTimingData gtd; - - /* check if there's data to work with */ - if (gpd == NULL) { - BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data to work on"); - return OPERATOR_CANCELLED; - } - - if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) { - BKE_report(op->reports, RPT_WARNING, - "Current Grease Pencil strokes have no valid timing data, most timing options will be hidden!"); - } - valid_timing = RNA_property_boolean_get(op->ptr, prop); - - gtd.mode = RNA_enum_get(op->ptr, "timing_mode"); - /* Check for illegal timing mode! */ - if (!valid_timing && !ELEM(gtd.mode, GP_STROKECONVERT_TIMING_NONE, GP_STROKECONVERT_TIMING_LINEAR)) { - gtd.mode = GP_STROKECONVERT_TIMING_LINEAR; - RNA_enum_set(op->ptr, "timing_mode", gtd.mode); - } - if (!link_strokes) { - gtd.mode = GP_STROKECONVERT_TIMING_NONE; - } - - /* grab all relevant settings */ - gtd.frame_range = RNA_int_get(op->ptr, "frame_range"); - gtd.start_frame = RNA_int_get(op->ptr, "start_frame"); - gtd.realtime = valid_timing ? RNA_boolean_get(op->ptr, "use_realtime") : false; - gtd.end_frame = RNA_int_get(op->ptr, "end_frame"); - gtd.gap_duration = RNA_float_get(op->ptr, "gap_duration"); - gtd.gap_randomness = RNA_float_get(op->ptr, "gap_randomness"); - gtd.gap_randomness = min_ff(gtd.gap_randomness, gtd.gap_duration); - gtd.seed = RNA_int_get(op->ptr, "seed"); - gtd.num_points = gtd.cur_point = 0; - gtd.dists = gtd.times = NULL; - gtd.tot_dist = gtd.tot_time = gtd.gap_tot_time = 0.0f; - gtd.inittime = 0.0; - gtd.offset_time = 0.0f; - - /* perform conversion */ - gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, >d); - - /* free temp memory */ - if (gtd.dists) { - MEM_freeN(gtd.dists); - gtd.dists = NULL; - } - if (gtd.times) { - MEM_freeN(gtd.times); - gtd.times = NULL; - } - - /* notifiers */ - WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); - WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); - - /* done */ - return OPERATOR_FINISHED; -} - -static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) -{ - const char *prop_id = RNA_property_identifier(prop); - const bool link_strokes = RNA_boolean_get(ptr, "use_link_strokes"); - int timing_mode = RNA_enum_get(ptr, "timing_mode"); - bool realtime = RNA_boolean_get(ptr, "use_realtime"); - float gap_duration = RNA_float_get(ptr, "gap_duration"); - float gap_randomness = RNA_float_get(ptr, "gap_randomness"); - const bool valid_timing = RNA_boolean_get(ptr, "use_timing_data"); - - /* Always show those props */ - if (STREQ(prop_id, "type") || - STREQ(prop_id, "use_normalize_weights") || - STREQ(prop_id, "radius_multiplier") || - STREQ(prop_id, "use_link_strokes")) - { - return true; - } - - /* Never show this prop */ - if (STREQ(prop_id, "use_timing_data")) - return false; - - if (link_strokes) { - /* Only show when link_stroke is true */ - if (STREQ(prop_id, "timing_mode")) - return true; - - if (timing_mode != GP_STROKECONVERT_TIMING_NONE) { - /* Only show when link_stroke is true and stroke timing is enabled */ - if (STREQ(prop_id, "frame_range") || - STREQ(prop_id, "start_frame")) - { - return true; - } - - /* Only show if we have valid timing data! */ - if (valid_timing && STREQ(prop_id, "use_realtime")) - return true; - - /* Only show if realtime or valid_timing is false! */ - if ((!realtime || !valid_timing) && STREQ(prop_id, "end_frame")) - return true; - - if (valid_timing && timing_mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { - /* Only show for custom gaps! */ - if (STREQ(prop_id, "gap_duration")) - return true; - - /* Only show randomness for non-null custom gaps! */ - if (STREQ(prop_id, "gap_randomness") && (gap_duration > 0.0f)) - return true; - - /* Only show seed for randomize action! */ - if (STREQ(prop_id, "seed") && (gap_duration > 0.0f) && (gap_randomness > 0.0f)) - return true; - } - } - } - - /* Else, hidden! */ - return false; -} - -static void gp_convert_ui(bContext *C, wmOperator *op) -{ - uiLayout *layout = op->layout; - wmWindowManager *wm = CTX_wm_manager(C); - PointerRNA ptr; - - RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); - - /* Main auto-draw call */ - uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, '\0'); -} - -void GPENCIL_OT_convert(wmOperatorType *ot) -{ - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Convert Grease Pencil"; - ot->idname = "GPENCIL_OT_convert"; - ot->description = "Convert the active Grease Pencil layer to a new Curve Object"; - - /* callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = gp_convert_layer_exec; - ot->poll = gp_convert_poll; - ot->ui = gp_convert_ui; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", "Which type of curve to convert to"); - - RNA_def_boolean(ot->srna, "use_normalize_weights", true, "Normalize Weight", - "Normalize weight (set from stroke width)"); - RNA_def_float(ot->srna, "radius_multiplier", 1.0f, 0.0f, 1000.0f, "Radius Fac", - "Multiplier for the points' radii (set from stroke width)", 0.0f, 10.0f); - RNA_def_boolean(ot->srna, "use_link_strokes", true, "Link Strokes", - "Whether to link strokes with zero-radius sections of curves"); - - prop = RNA_def_enum(ot->srna, "timing_mode", prop_gpencil_convert_timingmodes, GP_STROKECONVERT_TIMING_FULL, - "Timing Mode", "How to use timing data stored in strokes"); - RNA_def_enum_funcs(prop, rna_GPConvert_mode_items); - - RNA_def_int(ot->srna, "frame_range", 100, 1, 10000, "Frame Range", - "The duration of evaluation of the path control curve", 1, 1000); - RNA_def_int(ot->srna, "start_frame", 1, 1, 100000, "Start Frame", - "The start frame of the path control curve", 1, 100000); - RNA_def_boolean(ot->srna, "use_realtime", false, "Realtime", - "Whether the path control curve reproduces the drawing in realtime, starting from Start Frame"); - prop = RNA_def_int(ot->srna, "end_frame", 250, 1, 100000, "End Frame", - "The end frame of the path control curve (if Realtime is not set)", 1, 100000); - RNA_def_property_update_runtime(prop, gp_convert_set_end_frame); - - RNA_def_float(ot->srna, "gap_duration", 0.0f, 0.0f, 10000.0f, "Gap Duration", - "Custom Gap mode: (Average) length of gaps, in frames " - "(Note: Realtime value, will be scaled if Realtime is not set)", 0.0f, 1000.0f); - RNA_def_float(ot->srna, "gap_randomness", 0.0f, 0.0f, 10000.0f, "Gap Randomness", - "Custom Gap mode: Number of frames that gap lengths can vary", 0.0f, 1000.0f); - RNA_def_int(ot->srna, "seed", 0, 0, 1000, "Random Seed", - "Custom Gap mode: Random generator seed", 0, 100); - - /* Note: Internal use, this one will always be hidden by UI code... */ - prop = RNA_def_boolean(ot->srna, "use_timing_data", false, "Has Valid Timing", - "Whether the converted Grease Pencil layer has valid timing data (internal use)"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); -} - -/* ************************************************ */ diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 56420434494..cd0c32a35bf 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -96,6 +96,12 @@ void gp_point_conversion_init(struct bContext *C, GP_SpaceConversion *r_gsc); void gp_point_to_xy(GP_SpaceConversion *settings, struct bGPDstroke *gps, struct bGPDspoint *pt, int *r_x, int *r_y); +/* Poll Callbacks ------------------------------------ */ +/* gpencil_utils.c */ + +int gp_add_poll(struct bContext *C); +int gp_active_layer_poll(struct bContext *C); + /* ***************************************************** */ /* Operator Defines */ diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 425983397e0..0d7aac7f48f 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -37,23 +37,201 @@ #include "BLI_utildefines.h" #include "DNA_gpencil_types.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_view3d_types.h" #include "BKE_context.h" +#include "BKE_gpencil.h" +#include "BKE_tracking.h" #include "WM_api.h" +#include "RNA_access.h" +#include "RNA_define.h" + #include "UI_view2d.h" #include "ED_gpencil.h" +#include "ED_clip.h" #include "ED_view3d.h" #include "gpencil_intern.h" /* ******************************************************** */ +/* Context Wrangling... */ + +/* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it, + * when context info is not available. + */ +bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrArea *sa, Object *ob, PointerRNA *ptr) +{ + /* if there's an active area, check if the particular editor may + * have defined any special Grease Pencil context for editing... + */ + if (sa) { + SpaceLink *sl = sa->spacedata.first; + + switch (sa->spacetype) { + case SPACE_VIEW3D: /* 3D-View */ + case SPACE_TIME: /* Timeline - XXX: this is a hack to get it to show GP keyframes for 3D view */ + case SPACE_ACTION: /* DepeSheet - XXX: this is a hack to get the keyframe jump operator to take GP Keyframes into account */ + { + BLI_assert(scene && ELEM(scene->toolsettings->gpencil_src, + GP_TOOL_SOURCE_SCENE, GP_TOOL_SOURCE_OBJECT)); + + if (scene->toolsettings->gpencil_src == GP_TOOL_SOURCE_OBJECT) { + /* legacy behaviour for usage with old addons requiring object-linked to objects */ + + /* just in case no active/selected object... */ + if (ob && (ob->flag & SELECT)) { + /* for now, as long as there's an object, default to using that in 3D-View */ + if (ptr) RNA_id_pointer_create(&ob->id, ptr); + return &ob->gpd; + } + /* else: defaults to scene... */ + } + else { + if (ptr) RNA_id_pointer_create(&scene->id, ptr); + return &scene->gpd; + } + break; + } + case SPACE_NODE: /* Nodes Editor */ + { + SpaceNode *snode = (SpaceNode *)sl; + + /* return the GP data for the active node block/node */ + if (snode && snode->nodetree) { + /* for now, as long as there's an active node tree, default to using that in the Nodes Editor */ + if (ptr) RNA_id_pointer_create(&snode->nodetree->id, ptr); + return &snode->nodetree->gpd; + } + + /* even when there is no node-tree, don't allow this to flow to scene */ + return NULL; + } + case SPACE_SEQ: /* Sequencer */ + { + SpaceSeq *sseq = (SpaceSeq *)sl; + + /* for now, Grease Pencil data is associated with the space (actually preview region only) */ + /* XXX our convention for everything else is to link to data though... */ + if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceSequenceEditor, sseq, ptr); + return &sseq->gpd; + } + case SPACE_IMAGE: /* Image/UV Editor */ + { + SpaceImage *sima = (SpaceImage *)sl; + + /* for now, Grease Pencil data is associated with the space... */ + /* XXX our convention for everything else is to link to data though... */ + if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, ptr); + return &sima->gpd; + } + case SPACE_CLIP: /* Nodes Editor */ + { + SpaceClip *sc = (SpaceClip *)sl; + MovieClip *clip = ED_space_clip_get_clip(sc); + + if (clip) { + if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { + MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking); + + if (!track) + return NULL; + + if (ptr) + RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, ptr); + + return &track->gpd; + } + else { + if (ptr) + RNA_id_pointer_create(&clip->id, ptr); + + return &clip->gpd; + } + } + break; + } + default: /* unsupported space */ + return NULL; + } + } + + /* just fall back on the scene's GP data */ + if (ptr) RNA_id_pointer_create((ID *)scene, ptr); + return (scene) ? &scene->gpd : NULL; +} + +/* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it */ +bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr) +{ + ID *screen_id = (ID *)CTX_wm_screen(C); + Scene *scene = CTX_data_scene(C); + ScrArea *sa = CTX_wm_area(C); + Object *ob = CTX_data_active_object(C); + + return ED_gpencil_data_get_pointers_direct(screen_id, scene, sa, ob, ptr); +} + +/* -------------------------------------------------------- */ + +/* Get the active Grease Pencil datablock, when context is not available */ +bGPdata *ED_gpencil_data_get_active_direct(ID *screen_id, Scene *scene, ScrArea *sa, Object *ob) +{ + bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(screen_id, scene, sa, ob, NULL); + return (gpd_ptr) ? *(gpd_ptr) : NULL; +} + +/* Get the active Grease Pencil datablock */ +bGPdata *ED_gpencil_data_get_active(const bContext *C) +{ + bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); + return (gpd_ptr) ? *(gpd_ptr) : NULL; +} + +/* -------------------------------------------------------- */ + +// XXX: this should be removed... We really shouldn't duplicate logic like this! +bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, View3D *v3d) +{ + Base *base = scene->basact; + bGPdata *gpd = NULL; + /* We have to make sure active object is actually visible and selected, else we must use default scene gpd, + * to be consistent with ED_gpencil_data_get_active's behavior. + */ + + if (base && TESTBASE(v3d, base)) { + gpd = base->object->gpd; + } + return gpd ? gpd : scene->gpd; +} + +/* ******************************************************** */ +/* Poll Callbacks */ + +/* poll callback for adding data/layers - special */ +int gp_add_poll(bContext *C) +{ + /* the base line we have is that we have somewhere to add Grease Pencil data */ + return ED_gpencil_data_get_pointers(C, NULL) != NULL; +} + +/* poll callback for checking if there is an active layer */ +int gp_active_layer_poll(bContext *C) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + bGPDlayer *gpl = gpencil_layer_getactive(gpd); + + return (gpl != NULL); +} + +/* ******************************************************** */ +/* Brush Tool Core */ /* Check if part of stroke occurs within last segment drawn by eraser */ bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]), @@ -73,6 +251,7 @@ bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]), } /* ******************************************************** */ +/* Stroke Validity Testing */ /* Check whether given stroke can be edited given the supplied context */ // XXX: do we need additional flags for screenspace vs dataspace? @@ -109,6 +288,7 @@ bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps) } /* ******************************************************** */ +/* Space Conversion */ /* Init handling for space-conversion function (from passed-in parameters) */ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc) -- cgit v1.2.3 From efc7c355b2e4fcbf4261675d174f04e02fef3fed Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Apr 2015 16:33:09 +1300 Subject: Code Cleanup: Pruning back the unusued includes now --- source/blender/editors/gpencil/gpencil_data.c | 13 ------------- source/blender/editors/gpencil/gpencil_edit.c | 13 ------------- 2 files changed, 26 deletions(-) diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 2046dc1ba7a..fc4dd3f410a 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -38,17 +38,11 @@ #include "MEM_guardedalloc.h" -#include "BLI_math.h" #include "BLI_blenlib.h" -#include "BLI_rand.h" #include "BLI_utildefines.h" #include "BLF_translation.h" -#include "DNA_anim_types.h" -#include "DNA_curve_types.h" -#include "DNA_object_types.h" -#include "DNA_node_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" @@ -56,9 +50,6 @@ #include "DNA_gpencil_types.h" #include "BKE_context.h" -#include "BKE_curve.h" -#include "BKE_depsgraph.h" -#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_gpencil.h" #include "BKE_library.h" @@ -75,11 +66,7 @@ #include "RNA_access.h" #include "RNA_define.h" -#include "UI_view2d.h" - #include "ED_gpencil.h" -#include "ED_view3d.h" -#include "ED_keyframing.h" #include "gpencil_intern.h" diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 66ba8814f4b..26237890539 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -40,15 +40,10 @@ #include "BLI_math.h" #include "BLI_blenlib.h" -#include "BLI_rand.h" #include "BLI_utildefines.h" #include "BLF_translation.h" -#include "DNA_anim_types.h" -#include "DNA_curve_types.h" -#include "DNA_object_types.h" -#include "DNA_node_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" @@ -56,17 +51,11 @@ #include "DNA_gpencil_types.h" #include "BKE_context.h" -#include "BKE_curve.h" -#include "BKE_depsgraph.h" -#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_gpencil.h" #include "BKE_library.h" -#include "BKE_object.h" #include "BKE_report.h" -#include "BKE_scene.h" #include "BKE_screen.h" -#include "BKE_tracking.h" #include "UI_interface.h" @@ -80,8 +69,6 @@ #include "ED_gpencil.h" #include "ED_view3d.h" -#include "ED_clip.h" -#include "ED_keyframing.h" #include "gpencil_intern.h" -- cgit v1.2.3 From 77667ad80f39e608d625ddae07914a9f42a4ed86 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 2 Apr 2015 15:55:43 +1100 Subject: Cleanup --- source/blender/compositor/intern/COM_ExecutionSystem.cpp | 4 ++-- source/blender/compositor/intern/COM_compositor.cpp | 2 +- source/blender/editors/animation/keyframing.c | 3 ++- source/blender/editors/screen/screen_ops.c | 4 ++-- source/blender/freestyle/intern/view_map/BoxGrid.cpp | 4 ++-- source/blender/freestyle/intern/view_map/BoxGrid.h | 4 ++-- source/blender/freestyle/intern/view_map/SphericalGrid.cpp | 4 ++-- source/gameengine/Ketsji/KX_GameObject.cpp | 4 ++-- source/gameengine/Ketsji/KX_PythonInit.cpp | 4 ++-- 9 files changed, 17 insertions(+), 16 deletions(-) diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index 0466fbedb0a..2ed9e6187ba 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -127,7 +127,7 @@ void ExecutionSystem::set_operations(const Operations &operations, const Groups void ExecutionSystem::execute() { const bNodeTree *editingtree = this->m_context.getbNodeTree(); - editingtree->stats_draw(editingtree->sdh, (char*)"Compositing | Initializing execution"); + editingtree->stats_draw(editingtree->sdh, (char *)"Compositing | Initializing execution"); DebugInfo::execute_started(this); @@ -183,7 +183,7 @@ void ExecutionSystem::execute() WorkScheduler::finish(); WorkScheduler::stop(); - editingtree->stats_draw(editingtree->sdh, (char*)"Compositing | Deinitializing execution"); + editingtree->stats_draw(editingtree->sdh, (char *)"Compositing | Deinitializing execution"); for (index = 0; index < this->m_operations.size(); index++) { NodeOperation *operation = this->m_operations[index]; operation->deinitExecution(); diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp index 3348e7c73d8..ff601e6f58e 100644 --- a/source/blender/compositor/intern/COM_compositor.cpp +++ b/source/blender/compositor/intern/COM_compositor.cpp @@ -77,7 +77,7 @@ void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rende /* set progress bar to 0% and status to init compositing */ editingtree->progress(editingtree->prh, 0.0); - editingtree->stats_draw(editingtree->sdh, (char*)"Compositing"); + editingtree->stats_draw(editingtree->sdh, (char *)"Compositing"); bool twopass = (editingtree->flag & NTREE_TWO_PASS) > 0 && !rendering; /* initialize execution system */ diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 68ef704272d..78509dd6079 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1738,7 +1738,8 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) } else { BKE_report(op->reports, RPT_WARNING, - "Failed to resolve path to property, try manually specifying this using a Keying Set instead"); + "Failed to resolve path to property, " + "try manually specifying this using a Keying Set instead"); } } } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 25571c00928..2064555f27e 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -3531,9 +3531,9 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv if (sad->flag & ANIMPLAY_FLAG_JUMPED) { BKE_sound_seek_scene(bmain, scene); - #ifdef PROFILE_AUDIO_SYNCH +#ifdef PROFILE_AUDIO_SYNCH old_frame = CFRA; - #endif +#endif } /* since we follow drawflags, we can't send notifier but tag regions ourselves */ diff --git a/source/blender/freestyle/intern/view_map/BoxGrid.cpp b/source/blender/freestyle/intern/view_map/BoxGrid.cpp index de60cc3812f..ae22a26ec9b 100644 --- a/source/blender/freestyle/intern/view_map/BoxGrid.cpp +++ b/source/blender/freestyle/intern/view_map/BoxGrid.cpp @@ -76,13 +76,13 @@ BoxGrid::Iterator::Iterator (BoxGrid& grid, Vec3r& center, real /*epsilon*/) { // Find target cell _cell = grid.findCell(_target); - #if BOX_GRID_LOGGING +#if BOX_GRID_LOGGING if (G.debug & G_DEBUG_FREESTYLE) { cout << "Searching for occluders of edge centered at " << _target << " in cell [" << 1_cell->boundary[0] << ", " << _cell->boundary[1] << ", " << _cell->boundary[2] << ", " << _cell->boundary[3] << "] (" << _cell->faces.size() << " occluders)" << endl; } - #endif +#endif // Set iterator _current = _cell->faces.begin(); diff --git a/source/blender/freestyle/intern/view_map/BoxGrid.h b/source/blender/freestyle/intern/view_map/BoxGrid.h index 0ef4ce37b11..b8e751d041d 100644 --- a/source/blender/freestyle/intern/view_map/BoxGrid.h +++ b/source/blender/freestyle/intern/view_map/BoxGrid.h @@ -303,11 +303,11 @@ inline void BoxGrid::Iterator::reportDepth(Vec3r origin, Vec3r u, real t) // The reported depth is the length of a ray in camera space // We need to convert it into a Z-value in grid space real depth = -(origin + (u * t))[2]; - #if BOX_GRID_LOGGING +#if BOX_GRID_LOGGING if (G.debug & G_DEBUG_FREESTYLE) { std::cout << "\t\tReporting depth of occluder/ee: " << depth; } - #endif +#endif if (depth > _target[2]) { #if BOX_GRID_LOGGING if (G.debug & G_DEBUG_FREESTYLE) { diff --git a/source/blender/freestyle/intern/view_map/SphericalGrid.cpp b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp index fedd5767e32..10c88190cb3 100644 --- a/source/blender/freestyle/intern/view_map/SphericalGrid.cpp +++ b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp @@ -77,13 +77,13 @@ SphericalGrid::Iterator::Iterator(SphericalGrid& grid, Vec3r& center, real /*eps { // Find target cell _cell = grid.findCell(_target); - #if SPHERICAL_GRID_LOGGING +#if SPHERICAL_GRID_LOGGING if (G.debug & G_DEBUG_FREESTYLE) { cout << "Searching for occluders of edge centered at " << _target << " in cell [" << _cell->boundary[0] << ", " << _cell->boundary[1] << ", " << _cell->boundary[2] << ", " << _cell->boundary[3] << "] (" << _cell->faces.size() << " occluders)" << endl; } - #endif +#endif // Set iterator _current = _cell->faces.begin(); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 84916b45ebf..412a0b823c7 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1550,7 +1550,7 @@ void KX_GameObject::RegisterCollisionCallbacks() } void KX_GameObject::RunCollisionCallbacks(KX_GameObject *collider, const MT_Vector3 &point, const MT_Vector3 &normal) { - #ifdef WITH_PYTHON +#ifdef WITH_PYTHON Py_ssize_t len; PyObject* collision_callbacks = m_collisionCallbacks; @@ -1613,7 +1613,7 @@ void KX_GameObject::RunCollisionCallbacks(KX_GameObject *collider, const MT_Vect if (args_3) Py_DECREF(args_3); if (args_1) Py_DECREF(args_1); } - #endif +#endif } /* Suspend/ resume: for the dynamic behavior, there is a simple diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 074cbd9937e..18b25d340dd 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -2057,14 +2057,14 @@ PyObject *initGamePlayerPythonScripting(Main *maggie, int argc, char** argv) Py_SetProgramName(program_path_wchar); /* Update, Py3.3 resolves attempting to parse non-existing header */ - #if 0 +#if 0 /* Python 3.2 now looks for '2.xx/python/include/python3.2d/pyconfig.h' to * parse from the 'sysconfig' module which is used by 'site', * so for now disable site. alternatively we could copy the file. */ if (py_path_bundle != NULL) { Py_NoSiteFlag = 1; /* inhibits the automatic importing of 'site' */ } - #endif +#endif Py_FrozenFlag = 1; -- cgit v1.2.3 From ac2530be8c7b5742e89e517ae97386d89d935982 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 2 Apr 2015 14:39:58 +0500 Subject: Cleanup own todo: RE_pipeline is not a bad include from BKE, it's already used in few places --- source/blender/blenkernel/intern/seqeffects.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 6157d63047e..a8787d44914 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -52,9 +52,6 @@ #include "RNA_access.h" -/* TODO(sergey): Could be considered a bad level call, but - * need this for gaussian table. - */ #include "RE_pipeline.h" static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, -- cgit v1.2.3 From 2fc69d11c8a2df89c32a8bb320da2350fff7c8ba Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 2 Apr 2015 21:05:12 +1100 Subject: Add custom properties to sequence strips --- release/scripts/startup/bl_ui/space_sequencer.py | 7 +++++++ source/blender/blenkernel/intern/sequencer.c | 10 ++++++++++ source/blender/blenloader/intern/readfile.c | 5 ++++- source/blender/blenloader/intern/writefile.c | 4 ++++ source/blender/makesdna/DNA_sequence_types.h | 2 ++ source/blender/makesrna/intern/rna_sequencer.c | 14 ++++++++++++++ 6 files changed, 41 insertions(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index ce1add12f54..da477e4e6be 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -19,6 +19,7 @@ # import bpy from bpy.types import Header, Menu, Panel +from rna_prop_ui import PropertyPanel from bl_ui.properties_grease_pencil_common import GreasePencilDataPanel, GreasePencilToolsPanel from bpy.app.translations import pgettext_iface as iface_ @@ -1107,5 +1108,11 @@ class SEQUENCER_PT_grease_pencil_tools(GreasePencilToolsPanel, SequencerButtonsP # toolbar, which doesn't exist here... +class SEQUENCER_PT_custom_props(SequencerButtonsPanel, PropertyPanel, Panel): + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} + _context_path = "scene.sequence_editor.active_strip" + _property_type = (bpy.types.Sequence,) + + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 1e32c586176..721555097d7 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -66,6 +66,7 @@ #include "BKE_scene.h" #include "BKE_mask.h" #include "BKE_library.h" +#include "BKE_idprop.h" #include "RNA_access.h" @@ -210,6 +211,11 @@ static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const bool do_cach seq_free_animdata(scene, seq); } + if (seq->prop) { + IDP_FreeProperty(seq->prop); + MEM_freeN(seq->prop); + } + /* free modifiers */ BKE_sequence_modifier_clear(seq); @@ -4630,6 +4636,10 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup seqn->strip->proxy->anim = NULL; } + if (seq->prop) { + seqn->prop = IDP_CopyProperty(seq->prop); + } + if (seqn->modifiers.first) { BLI_listbase_clear(&seqn->modifiers); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index b0aa47787b6..8c5959f20bf 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5618,7 +5618,10 @@ static void direct_link_scene(FileData *fd, Scene *sce) SpeedControlVars *s = seq->effectdata; s->frameMap = NULL; } - + + seq->prop = newdataadr(fd, seq->prop); + IDP_DirectLinkGroup_OrFree(&seq->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + seq->strip = newdataadr(fd, seq->strip); if (seq->strip && seq->strip->done==0) { seq->strip->done = true; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index afc53f343f1..c616436d584 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2441,6 +2441,10 @@ static void write_scenes(WriteData *wd, ListBase *scebase) strip->done = true; } + if (seq->prop) { + IDP_WriteProperty(seq->prop, wd); + } + write_sequence_modifiers(wd, &seq->modifiers); } SEQ_END diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 9a6d8a533b0..46a91cf6ceb 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -189,6 +189,8 @@ typedef struct Sequence { char alpha_mode; char pad[3]; + struct IDProperty *prop; + /* modifiers */ ListBase modifiers; } Sequence; diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 231341ef554..0d46924c129 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -72,6 +72,7 @@ EnumPropertyItem sequence_modifier_type_items[] = { #ifdef RNA_RUNTIME #include "BKE_report.h" +#include "BKE_idprop.h" #include "WM_api.h" #include "WM_types.h" @@ -564,6 +565,18 @@ static char *rna_Sequence_path(PointerRNA *ptr) } } +static IDProperty *rna_Sequence_idprops(PointerRNA *ptr, bool create) +{ + Sequence *seq = ptr->data; + + if (create && !seq->prop) { + IDPropertyTemplate val = {0}; + seq->prop = IDP_New(IDP_GROUP, &val, "Sequence ID properties"); + } + + return seq->prop; +} + static PointerRNA rna_SequenceEditor_meta_stack_get(CollectionPropertyIterator *iter) { ListBaseIterator *internal = &iter->internal.listbase; @@ -1397,6 +1410,7 @@ static void rna_def_sequence(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Sequence", "Sequence strip in the sequence editor"); RNA_def_struct_refine_func(srna, "rna_Sequence_refine"); RNA_def_struct_path_func(srna, "rna_Sequence_path"); + RNA_def_struct_idprops_func(srna, "rna_Sequence_idprops"); prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_Sequence_name_get", "rna_Sequence_name_length", "rna_Sequence_name_set"); -- cgit v1.2.3 From 146be8e25816c5bcd12a1e0a8b12bed4220befa6 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 2 Apr 2015 12:34:35 +0200 Subject: Fix proportional editing always turned on in graph editor. --- source/blender/editors/transform/transform_conversions.c | 12 +++++------- source/blender/editors/transform/transform_generics.c | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index e34439945ca..6124dab343f 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3800,7 +3800,7 @@ static void graph_key_shortest_dist(FCurve *fcu, TransData *td_start, TransData const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; if (sel1 || sel2 || sel3) { - td->dist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0])); + td->dist = td->rdist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0])); } td_iter += 3; @@ -4088,7 +4088,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; if (sel1 || sel2) { - td->dist = 0.0f; + td->dist = td->rdist = 0.0f; } else { graph_key_shortest_dist(fcu, td_start, td, use_handle); @@ -4096,7 +4096,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) td++; if (sel2) { - td->dist = 0.0f; + td->dist = td->rdist = 0.0f; } else { graph_key_shortest_dist(fcu, td_start, td, use_handle); @@ -4104,7 +4104,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) td++; if (sel3 || sel2) { - td->dist = 0.0f; + td->dist = td->rdist = 0.0f; } else { graph_key_shortest_dist(fcu, td_start, td, use_handle); @@ -7740,10 +7740,8 @@ void createTransData(bContext *C, TransInfo *t) createTransGraphEditData(C, t); if (t->data && (t->flag & T_PROP_EDIT)) { - t->flag |= T_PROP_CONNECTED; - t->flag &= ~T_PROP_PROJECTED; sort_trans_data(t); // makes selected become first in array - set_prop_dist(t, false); + //set_prop_dist(t, false); /* don't do that, distance has been set in createTransGraphEditData already */ sort_trans_data_dist(t); } } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 14ae93d1144..0571fc399a6 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1321,7 +1321,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve if (t->flag & T_MODAL) { if ((t->options & CTX_NO_PET) == 0) { if (t->spacetype == SPACE_IPO) { - t->flag |= T_PROP_EDIT; + t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional); } else if (t->obedit) { t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional); -- cgit v1.2.3 From 2cac2e721387ed6a04f18445f4ef6bac7f405c63 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Apr 2015 17:26:43 +1300 Subject: GPencil: H/Shift-H/Alt-H now work to Hide and Reveal Layers in Strokes Edit Mode * H = Hide active layer * Shift-H = Hide non-active layers * Alt-H = Show all layers --- source/blender/editors/gpencil/gpencil_data.c | 94 +++++++++++++++++++++++++ source/blender/editors/gpencil/gpencil_intern.h | 3 + source/blender/editors/gpencil/gpencil_ops.c | 16 ++++- 3 files changed, 112 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index fc4dd3f410a..fa76029bb2e 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -350,4 +350,98 @@ void GPENCIL_OT_layer_duplicate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/* *********************** Hide Layers ******************************** */ + +static int gp_hide_exec(bContext *C, wmOperator *op) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + bGPDlayer *layer = gpencil_layer_getactive(gpd); + bool unselected = RNA_boolean_get(op->ptr, "unselected"); + + /* sanity checks */ + if (ELEM(NULL, gpd, layer)) + return OPERATOR_CANCELLED; + + if (unselected) { + bGPDlayer *gpl; + + /* hide unselected */ + for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { + if (gpl != layer) { + gpl->flag |= GP_LAYER_HIDE; + } + } + } + else { + /* hide selected/active */ + layer->flag |= GP_LAYER_HIDE; + } + + /* notifiers */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_hide(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Hide Layer(s)"; + ot->idname = "GPENCIL_OT_hide"; + ot->description = "Hide selected/unselected Grease Pencil layers"; + + /* callbacks */ + ot->exec = gp_hide_exec; + ot->poll = gp_active_layer_poll; /* NOTE: we need an active layer to play with */ + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* props */ + RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers"); +} + +/* ********************** Show All Layers ***************************** */ + +/* poll callback for showing layers */ +static int gp_reveal_poll(bContext *C) +{ + return ED_gpencil_data_get_active(C) != NULL; +} + +static int gp_reveal_exec(bContext *C, wmOperator *UNUSED(op)) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + bGPDlayer *gpl; + + /* sanity checks */ + if (gpd == NULL) + return OPERATOR_CANCELLED; + + /* make all layers visible */ + for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { + gpl->flag &= ~GP_LAYER_HIDE; + } + + /* notifiers */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_reveal(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Show All Layers"; + ot->idname = "GPENCIL_OT_reveal"; + ot->description = "Show all Grease Pencil layers"; + + /* callbacks */ + ot->exec = gp_reveal_exec; + ot->poll = gp_reveal_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + /* ************************************************ */ diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index cd0c32a35bf..72cd9022d69 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -144,6 +144,9 @@ void GPENCIL_OT_layer_remove(struct wmOperatorType *ot); void GPENCIL_OT_layer_move(struct wmOperatorType *ot); void GPENCIL_OT_layer_duplicate(struct wmOperatorType *ot); +void GPENCIL_OT_hide(struct wmOperatorType *ot); +void GPENCIL_OT_reveal(struct wmOperatorType *ot); + void GPENCIL_OT_active_frame_delete(struct wmOperatorType *ot); void GPENCIL_OT_convert(struct wmOperatorType *ot); diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index 5970a9497a0..4752f3dbb36 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -181,7 +181,18 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf) #ifdef __APPLE__ WM_keymap_add_item(keymap, "GPENCIL_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0); WM_keymap_add_item(keymap, "GPENCIL_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0); -#endif +#endif + + /* Show/Hide */ + /* NOTE: These are available only in EditMode now, since they clash with general-purpose hotkeys */ + WM_keymap_add_item(keymap, "GPENCIL_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0); + + kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_hide", HKEY, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "unselected", false); + + kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "unselected", true); + /* Transform Tools */ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", GKEY, KM_PRESS, 0, 0); @@ -260,6 +271,9 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_layer_move); WM_operatortype_append(GPENCIL_OT_layer_duplicate); + WM_operatortype_append(GPENCIL_OT_hide); + WM_operatortype_append(GPENCIL_OT_reveal); + WM_operatortype_append(GPENCIL_OT_active_frame_delete); WM_operatortype_append(GPENCIL_OT_convert); -- cgit v1.2.3 From f5adbcc3a276c331847945a182adfa6855a60992 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Apr 2015 20:49:29 +1300 Subject: GPencil: Draw status indicator in top-right corner when in Stroke Edit Mode When in Stroke Edit Mode, an indicator/warning message is now shown in the top-right corner to make it easier to notice that operations will apply to Grease Pencil strokes instead. --- source/blender/editors/gpencil/drawgpencil.c | 66 +++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index c2072d30310..e4d13e2ed23 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -40,6 +40,9 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLF_api.h" +#include "BLF_translation.h" + #include "DNA_gpencil_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -59,6 +62,7 @@ #include "ED_gpencil.h" #include "ED_view3d.h" +#include "UI_interface_icons.h" #include "UI_resources.h" /* ************************************************** */ @@ -1042,6 +1046,42 @@ static void gp_draw_data_layers(bGPdata *gpd, int offsx, int offsy, int winx, in } } +/* draw a short status message in the top-right corner */ +static void gp_draw_status_text(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag) +{ + /* for now, this should only be used to indicate when we are in stroke editmode */ + if (gpd->flag & GP_DATA_STROKE_EDITMODE) { + const char *printable = IFACE_("GPencil Stroke Editing"); + float printable_size[2]; + int xco, yco; + + BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); + + xco = offsx + (winx - U.widget_unit) - (int)printable_size[0]; + yco = offsy + (winy - U.widget_unit); + + /* text label */ + UI_ThemeColor(TH_TEXT_HI); +#ifdef WITH_INTERNATIONAL + BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); +#else + BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); +#endif + + /* grease pencil icon... */ + // XXX: is this too intrusive? + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + xco -= U.widget_unit; + yco -= (int)printable_size[1] / 2; + + UI_icon_draw(xco, yco, ICON_GREASEPENCIL); + + glDisable(GL_BLEND); + } +} + /* draw grease-pencil datablock */ static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag) { @@ -1067,6 +1107,16 @@ static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy, glDisable(GL_BLEND); // alpha blending glDisable(GL_LINE_SMOOTH); // smooth lines + /* Draw status text: + * - This cannot be drawn when doing OpenGL "renders" and also when "only render" is enabled + * - NOSTATUS should also catch all the other cases where the we are drawing into the "wrong" + * coordinate space (e.g. 3D, View 2D, etc.) + */ + /* XXX: Reinstate the "draw info" flag into the UI? */ + if ((dflag & GP_DRAWDATA_NOSTATUS) == 0 && (G.f & G_RENDER_OGL) == 0) { + gp_draw_status_text(gpd, offsx, offsy, winx, winy, cfra, dflag); + } + /* restore initial gl conditions */ glLineWidth(1.0); glPointSize(1.0); @@ -1227,9 +1277,21 @@ void ED_gpencil_draw_view3d(Scene *scene, View3D *v3d, ARegion *ar, bool only3d) winy = ar->winy; } - /* draw it! */ - if (only3d) dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS); + /* set flags */ + if (only3d) { + /* 3D strokes/3D space: + * - only 3D space points + * - don't status text either (as it's the wrong space) + */ + dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS); + } + if (v3d->flag2 & V3D_RENDER_OVERRIDE) { + /* don't draw status text when "only render" flag is set */ + dflag |= GP_DRAWDATA_NOSTATUS; + } + + /* draw it! */ gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype); } -- cgit v1.2.3 From 97f6bff45aa9259b9123272eacc03ba9bc4444d4 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Apr 2015 23:30:30 +1300 Subject: Propagate Pose: Added 'Selected Keyframes' mode This commit adds a new mode for the Propagate Pose tool. With this new option, the Propagate Pose will copy the current pose over to all selected keyframes after the current frame. For reference, some of the other/existing options are: to copy it to each subsequent keyframe with the same value (WHILE_HELD - the default), to the next keyframe, or to the last keyframe. --- release/scripts/startup/bl_ui/space_view3d.py | 4 ++++ source/blender/editors/armature/pose_slide.c | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 9de40171e51..6b9e4b85875 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1933,6 +1933,10 @@ class VIEW3D_MT_pose_propagate(Menu): layout.separator() + layout.operator("pose.propagate", text="On Selected Keyframes").mode = 'SELECTED_KEYS' + + layout.separator() + layout.operator("pose.propagate", text="On Selected Markers").mode = 'SELECTED_MARKERS' diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index 5f9f24d23a4..17ef62b49af 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -898,6 +898,8 @@ typedef enum ePosePropagate_Termination { /* stop when we run out of keyframes */ POSE_PROPAGATE_BEFORE_END, + /* only do on keyframes that are selected */ + POSE_PROPAGATE_SELECTED_KEYS, /* only do on the frames where markers are selected */ POSE_PROPAGATE_SELECTED_MARKERS } ePosePropagate_Termination; @@ -1137,6 +1139,11 @@ static void pose_propagate_fcurve(wmOperator *op, Object *ob, FCurve *fcu, if (ce == NULL) continue; } + else if (mode == POSE_PROPAGATE_SELECTED_KEYS) { + /* only allow if this keyframe is already selected - skip otherwise */ + if (BEZSELECTED(bezt) == 0) + continue; + } /* just flatten handles, since values will now be the same either side... */ /* TODO: perhaps a fade-out modulation of the value is required here (optional once again)? */ @@ -1224,6 +1231,7 @@ void POSE_OT_propagate(wmOperatorType *ot) {POSE_PROPAGATE_LAST_KEY, "LAST_KEY", 0, "To Last Keyframe", "Propagate pose to the last keyframe only (i.e. making action cyclic)"}, {POSE_PROPAGATE_BEFORE_FRAME, "BEFORE_FRAME", 0, "Before Frame", "Propagate pose to all keyframes between current frame and 'Frame' property"}, {POSE_PROPAGATE_BEFORE_END, "BEFORE_END", 0, "Before Last Keyframe", "Propagate pose to all keyframes from current frame until no more are found"}, + {POSE_PROPAGATE_SELECTED_KEYS, "SELECTED_KEYS", 0, "On Selected Keyframes", "Propagate pose to all keyframes that are selected"}, {POSE_PROPAGATE_SELECTED_MARKERS, "SELECTED_MARKERS", 0, "On Selected Markers", "Propagate pose to all keyframes occurring on frames with Scene Markers after the current frame"}, {0, NULL, 0, NULL, NULL}}; -- cgit v1.2.3 From 838c3503a78b1cc7a352e9722b39610319cc0bb3 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Apr 2015 23:40:09 +1300 Subject: Expose the Pose Propagate tool a bit more in the UI From the various forum threads and the fact that a new addon has cropped up, it appears that it is not that well known that this tool exists, and that it can be used solve a very common problem that animators face. Namely: When you've gone through blocking out your key poses and then realise that you need to adjust parts of the rig which don't change much, this tool solves the problem of needing to go through doing grunt-work to fix all the other keyframes which now need to change as well. So, this tool is now available in the following two places (in addition to the existing Pose -> Propagate menu): * Toolbar - The "Propagate" button will use the default mode (or the last used mode for each subsequent invocation). The arrow-button beside this will allow choosing between the different modes. (NOTE: The UI team may have different thoughts on this, but, let's give this a try for a while first, to see if this sort of thing works) * Alt-P - In Pose Mode, this will now bring up a menu allowing you to choose which mode is used. Since this sort of thing is something that does get run several times in a row when you need it, having this hotkey will make it a bit more convenient. --- release/scripts/startup/bl_ui/space_view3d_toolbar.py | 4 ++++ source/blender/editors/armature/armature_ops.c | 1 + 2 files changed, 5 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 70874460d4d..f01ea793e4f 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -758,6 +758,10 @@ class VIEW3D_PT_tools_posemode(View3DPanel, Panel): row.operator("pose.copy", text="Copy") row.operator("pose.paste", text="Paste") + row = layout.row(align=True) + row.operator("pose.propagate", text="Propagate") + row.menu("VIEW3D_MT_pose_propagate", icon='TRIA_RIGHT', text="") + col = layout.column(align=True) col.operator("poselib.pose_add", text="Add To Library") diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index 552faa4ecfb..61c9dfb24fa 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -412,5 +412,6 @@ void ED_keymap_armature(wmKeyConfig *keyconf) /* menus */ WM_keymap_add_menu(keymap, "VIEW3D_MT_pose_specials", WKEY, KM_PRESS, 0, 0); + WM_keymap_add_menu(keymap, "VIEW3D_MT_pose_propagate", PKEY, KM_PRESS, KM_ALT, 0); } -- cgit v1.2.3 From f30b60d1397d8109d6fb25188eace7b8d3a7e1d5 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Apr 2015 23:47:55 +1300 Subject: Fix: Crash when using "On Selected Markers" mode for Propogate Pose with no markers present The function to get a list of markers was not clearing the list before it exited early, and with no way to tell that the method failed, callers could make the mistake of trusting that the list was now valid (i.e. either full of marker frames or empty, vs being invalid) --- source/blender/editors/animation/anim_markers.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 140b7e0b117..68660740ac7 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -266,8 +266,20 @@ void ED_markers_make_cfra_list(ListBase *markers, ListBase *lb, short only_sel) { TimeMarker *marker; - if (markers == NULL) + if (lb) { + /* Clear the list first, since callers have no way of knowing + * whether this terminated early otherwise. This may lead + * to crashes if the user didn't clear the memory first. + */ + lb->first = lb->last = NULL; + } + else { + return; + } + + if (markers == NULL) { return; + } for (marker = markers->first; marker; marker = marker->next) add_marker_to_cfra_elem(lb, marker, only_sel); -- cgit v1.2.3 From fd2ea3a90941f319beb9346869efcef05979e7a8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 2 Apr 2015 15:06:40 +0500 Subject: Cycles: Make guarded allocator happy about strict C++ flags --- intern/cycles/util/util_guarded_allocator.h | 1 + 1 file changed, 1 insertion(+) diff --git a/intern/cycles/util/util_guarded_allocator.h b/intern/cycles/util/util_guarded_allocator.h index 263199417c4..c4edb172eb8 100644 --- a/intern/cycles/util/util_guarded_allocator.h +++ b/intern/cycles/util/util_guarded_allocator.h @@ -53,6 +53,7 @@ public: { util_guarded_mem_alloc(n * sizeof(T)); #ifdef WITH_BLENDER_GUARDEDALLOC + (void)hint; return (T*)MEM_mallocN(n * sizeof(T), "Cycles Alloc"); #else return std::allocator::allocate(n, hint); -- cgit v1.2.3 From ff45930cc5ada1e32af569d0f90d18af2a1cc771 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 2 Apr 2015 16:01:23 +0500 Subject: Cleanup: Make strict flags happy We might also just remove those arguments perhaps? --- source/blender/editors/gpencil/drawgpencil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index e4d13e2ed23..93a485423c0 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -1047,7 +1047,7 @@ static void gp_draw_data_layers(bGPdata *gpd, int offsx, int offsy, int winx, in } /* draw a short status message in the top-right corner */ -static void gp_draw_status_text(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag) +static void gp_draw_status_text(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int UNUSED(cfra), int UNUSED(dflag)) { /* for now, this should only be used to indicate when we are in stroke editmode */ if (gpd->flag & GP_DATA_STROKE_EDITMODE) { -- cgit v1.2.3 From 77ff544d93258017d1af61699156f05f2e453979 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 2 Apr 2015 13:47:39 +0200 Subject: Fix issue reported by copias on irc, shift duplicate and snap crashes in sequencer. Missing snap callback case. Quick patch is to use the sequencer specific operator instead of generic translate. We really need to support proper snap/snap options at some point though. --- source/blender/editors/space_sequencer/sequencer_ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c index 33a8a1c5b41..5bc7fea9a55 100644 --- a/source/blender/editors/space_sequencer/sequencer_ops.c +++ b/source/blender/editors/space_sequencer/sequencer_ops.c @@ -365,5 +365,5 @@ void ED_operatormacros_sequencer(void) "Duplicate selected strips and move them", OPTYPE_UNDO | OPTYPE_REGISTER); WM_operatortype_macro_define(ot, "SEQUENCER_OT_duplicate"); - WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + WM_operatortype_macro_define(ot, "TRANSFORM_OT_seq_slide"); } -- cgit v1.2.3 From f87d7c605dcfb1a439635f6856cbbd50904ae0b6 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 2 Apr 2015 09:08:25 -0300 Subject: Fix error messages for RE_layer_load_from_file() and RE_layer_load_from_file() --- source/blender/render/intern/source/pipeline.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index b18edd4c61e..49119505cab 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -3261,25 +3261,25 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char IMB_freeImBuf(ibuf_clip); } else { - BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to allocate clip buffer '%s'", filename); + BKE_reportf(reports, RPT_ERROR, "RE_layer_load_from_file: failed to allocate clip buffer '%s'", filename); } } else { - BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: incorrect dimensions for partial copy '%s'", filename); + BKE_reportf(reports, RPT_ERROR, "RE_layer_load_from_file: incorrect dimensions for partial copy '%s'", filename); } } IMB_freeImBuf(ibuf); } else { - BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'", filename); + BKE_reportf(reports, RPT_ERROR, "RE_layer_load_from_file: failed to load '%s'", filename); } } void RE_result_load_from_file(RenderResult *result, ReportList *reports, const char *filename) { if (!render_result_exr_file_read_path(result, NULL, filename)) { - BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'", filename); + BKE_reportf(reports, RPT_ERROR, "RE_result_load_from_file: failed to load '%s'", filename); return; } } -- cgit v1.2.3 From 64fed6841a48d6d8f1dfdee65bb3bbfb38654026 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 2 Apr 2015 14:51:37 +0200 Subject: Cleanup: followup to rBf87d7c605dcfb - use __func__ instead of literal func name in string. Since we are already using BKE_reportf... This way, no more issue if/when we copy/paste or rename that! --- source/blender/render/intern/source/pipeline.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 49119505cab..4bde3dddaff 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -3261,25 +3261,25 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char IMB_freeImBuf(ibuf_clip); } else { - BKE_reportf(reports, RPT_ERROR, "RE_layer_load_from_file: failed to allocate clip buffer '%s'", filename); + BKE_reportf(reports, RPT_ERROR, "%s: failed to allocate clip buffer '%s'", __func__, filename); } } else { - BKE_reportf(reports, RPT_ERROR, "RE_layer_load_from_file: incorrect dimensions for partial copy '%s'", filename); + BKE_reportf(reports, RPT_ERROR, "%s: incorrect dimensions for partial copy '%s'", __func__, filename); } } IMB_freeImBuf(ibuf); } else { - BKE_reportf(reports, RPT_ERROR, "RE_layer_load_from_file: failed to load '%s'", filename); + BKE_reportf(reports, RPT_ERROR, "%s: failed to load '%s'", __func__, filename); } } void RE_result_load_from_file(RenderResult *result, ReportList *reports, const char *filename) { if (!render_result_exr_file_read_path(result, NULL, filename)) { - BKE_reportf(reports, RPT_ERROR, "RE_result_load_from_file: failed to load '%s'", filename); + BKE_reportf(reports, RPT_ERROR, "%s: failed to load '%s'", __func__, filename); return; } } -- cgit v1.2.3 From 5d4beee8c651b193c64657665a97796eaf147ee7 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 3 Apr 2015 01:31:34 +1300 Subject: Code Cleanup: Split Action management operator stuff into action_data.c --- source/blender/editors/space_action/CMakeLists.txt | 1 + source/blender/editors/space_action/action_data.c | 509 +++++++++++++++++++++ source/blender/editors/space_action/action_edit.c | 426 ----------------- 3 files changed, 510 insertions(+), 426 deletions(-) create mode 100644 source/blender/editors/space_action/action_data.c diff --git a/source/blender/editors/space_action/CMakeLists.txt b/source/blender/editors/space_action/CMakeLists.txt index 50cf84079d2..68e56490217 100644 --- a/source/blender/editors/space_action/CMakeLists.txt +++ b/source/blender/editors/space_action/CMakeLists.txt @@ -36,6 +36,7 @@ set(INC_SYS ) set(SRC + action_data.c action_draw.c action_edit.c action_ops.c diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c new file mode 100644 index 00000000000..d3693608a1f --- /dev/null +++ b/source/blender/editors/space_action/action_data.c @@ -0,0 +1,509 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015 Blender Foundation + * This is a new part of Blender + * + * Contributor(s): Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_action/action_edit.c + * \ingroup spaction + */ + + +#include +#include +#include +#include + + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BLF_translation.h" + +#include "DNA_anim_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_key_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_mask_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "BKE_action.h" +#include "BKE_fcurve.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_key.h" +#include "BKE_main.h" +#include "BKE_nla.h" +#include "BKE_context.h" +#include "BKE_report.h" + +#include "UI_view2d.h" + +#include "ED_anim_api.h" +#include "ED_gpencil.h" +#include "ED_keyframing.h" +#include "ED_keyframes_edit.h" +#include "ED_screen.h" +#include "ED_markers.h" +#include "ED_mask.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_interface.h" + +#include "action_intern.h" + +/* ************************************************************************** */ +/* ACTION MANAGEMENT */ + +/* Helper function to find the active AnimData block from the Action Editor context */ +static AnimData *actedit_animdata_from_context(bContext *C) +{ + SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); + Object *ob = CTX_data_active_object(C); + AnimData *adt = NULL; + + /* Get AnimData block to use */ + if (saction->mode == SACTCONT_ACTION) { + /* Currently, "Action Editor" means object-level only... */ + if (ob) { + adt = ob->adt; + } + } + else if (saction->mode == SACTCONT_SHAPEKEY) { + Key *key = BKE_key_from_object(ob); + if (key) { + adt = key->adt; + } + } + + return adt; +} + +/* -------------------------------------------------------------------- */ + +/* Create new action */ +static bAction *action_create_new(bContext *C, bAction *oldact) +{ + ScrArea *sa = CTX_wm_area(C); + bAction *action; + + /* create action - the way to do this depends on whether we've got an + * existing one there already, in which case we make a copy of it + * (which is useful for "versioning" actions within the same file) + */ + if (oldact && GS(oldact->id.name) == ID_AC) { + /* make a copy of the existing action */ + action = BKE_action_copy(oldact); + } + else { + /* just make a new (empty) action */ + action = add_empty_action(CTX_data_main(C), "Action"); + } + + /* when creating new ID blocks, there is already 1 user (as for all new datablocks), + * but the RNA pointer code will assign all the proper users instead, so we compensate + * for that here + */ + BLI_assert(action->id.us == 1); + action->id.us--; + + /* set ID-Root type */ + if (sa->spacetype == SPACE_ACTION) { + SpaceAction *saction = (SpaceAction *)sa->spacedata.first; + + if (saction->mode == SACTCONT_SHAPEKEY) + action->idroot = ID_KE; + else + action->idroot = ID_OB; + } + + return action; +} + +/* Change the active action used by the action editor */ +static void actedit_change_action(bContext *C, bAction *act) +{ + bScreen *screen = CTX_wm_screen(C); + SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); + + PointerRNA ptr, idptr; + PropertyRNA *prop; + + /* create RNA pointers and get the property */ + RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, saction, &ptr); + prop = RNA_struct_find_property(&ptr, "action"); + + /* NOTE: act may be NULL here, so better to just use a cast here */ + RNA_id_pointer_create((ID *)act, &idptr); + + /* set the new pointer, and force a refresh */ + RNA_property_pointer_set(&ptr, prop, idptr); + RNA_property_update(C, &ptr, prop); +} + +/* ******************** New Action Operator *********************** */ + +/* Criteria: + * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions... + * OR + * The NLA Editor is active (i.e. Animation Data panel -> new action) + * 2) The associated AnimData block must not be in tweakmode + */ +static int action_new_poll(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + + /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */ + /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */ + if (!(scene->flag & SCE_NLA_EDIT_ON)) { + if (ED_operator_action_active(C)) { + SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); + Object *ob = CTX_data_active_object(C); + + /* For now, actions are only for the active object, and on object and shapekey levels... */ + if (saction->mode == SACTCONT_ACTION) { + /* XXX: This assumes that actions are assigned to the active object */ + if (ob) + return true; + } + else if (saction->mode == SACTCONT_SHAPEKEY) { + Key *key = BKE_key_from_object(ob); + if (key) + return true; + } + } + else if (ED_operator_nla_active(C)) { + return true; + } + } + + /* something failed... */ + return false; +} + +static int action_new_exec(bContext *C, wmOperator *UNUSED(op)) +{ + PointerRNA ptr, idptr; + PropertyRNA *prop; + + /* hook into UI */ + UI_context_active_but_prop_get_templateID(C, &ptr, &prop); + + if (prop) { + bAction *action = NULL, *oldact = NULL; + AnimData *adt = NULL; + PointerRNA oldptr; + + oldptr = RNA_property_pointer_get(&ptr, prop); + oldact = (bAction *)oldptr.id.data; + + /* stash the old action to prevent it from being lost */ + if (ptr.type == &RNA_AnimData) { + adt = ptr.data; + } + else if (ptr.type == &RNA_SpaceDopeSheetEditor) { + adt = actedit_animdata_from_context(C); + } + + /* Perform stashing operation - But only if there is an action */ + if (adt && oldact) { + /* stash the action */ + if (BKE_nla_action_stash(adt)) { + /* The stash operation will remove the user already + * (and unlink the action from the AnimData action slot). + * Hence, we must unset the ref to the action in the + * action editor too (if this is where we're being called from) + * first before setting the new action once it is created, + * or else the user gets decremented twice! + */ + if (ptr.type == &RNA_SpaceDopeSheetEditor) { + SpaceAction *saction = (SpaceAction *)ptr.data; + saction->action = NULL; + } + } + else { + //printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n", oldact->id.name); + } + } + + /* create action */ + action = action_create_new(C, oldact); + + /* set this new action + * NOTE: we can't use actedit_change_action, as this function is also called from the NLA + */ + RNA_id_pointer_create(&action->id, &idptr); + RNA_property_pointer_set(&ptr, prop, idptr); + RNA_property_update(C, &ptr, prop); + } + + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL); + + return OPERATOR_FINISHED; +} + +void ACTION_OT_new(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "New Action"; + ot->idname = "ACTION_OT_new"; + ot->description = "Create new action"; + + /* api callbacks */ + ot->exec = action_new_exec; + ot->poll = action_new_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ******************* Action Push-Down Operator ******************** */ + +/* Criteria: + * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions + * 2) There must be an action active + * 3) The associated AnimData block must not be in tweakmode + */ +static int action_pushdown_poll(bContext *C) +{ + if (ED_operator_action_active(C)) { + SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_active_object(C); + + /* Check for actions and that tweakmode is off */ + if ((saction->action) && !(scene->flag & SCE_NLA_EDIT_ON)) { + /* For now, actions are only for the active object, and on object and shapekey levels... */ + if (saction->mode == SACTCONT_ACTION) { + return (ob->adt != NULL); + } + else if (saction->mode == SACTCONT_SHAPEKEY) { + Key *key = BKE_key_from_object(ob); + + return (key && key->adt); + } + } + } + + /* something failed... */ + return false; +} + +static int action_pushdown_exec(bContext *C, wmOperator *op) +{ + SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); + AnimData *adt = actedit_animdata_from_context(C); + + /* Do the deed... */ + if (adt) { + /* Perform the pushdown operation + * - This will deal with all the AnimData-side usercounts + */ + if (action_has_motion(adt->action) == 0) { + /* action may not be suitable... */ + BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier"); + return OPERATOR_CANCELLED; + } + else { + /* action can be safely added */ + BKE_nla_action_pushdown(adt); + } + + /* Stop displaying this action in this editor + * NOTE: The editor itself doesn't set a user... + */ + saction->action = NULL; + } + + /* Send notifiers that stuff has changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); + return OPERATOR_FINISHED; +} + +void ACTION_OT_push_down(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Push Down Action"; + ot->idname = "ACTION_OT_push_down"; + ot->description = "Push action down on to the NLA stack as a new strip"; + + /* callbacks */ + ot->exec = action_pushdown_exec; + ot->poll = action_pushdown_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ******************* Action Stash Operator ******************** */ + +static int action_stash_exec(bContext *C, wmOperator *op) +{ + SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); + AnimData *adt = actedit_animdata_from_context(C); + + /* Perform stashing operation */ + if (adt) { + /* don't do anything if this action is empty... */ + if (action_has_motion(adt->action) == 0) { + /* action may not be suitable... */ + BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier"); + return OPERATOR_CANCELLED; + } + else { + /* stash the action */ + if (BKE_nla_action_stash(adt)) { + /* The stash operation will remove the user already, + * so the flushing step later shouldn't double up + * the usercount fixes. Hence, we must unset this ref + * first before setting the new action. + */ + saction->action = NULL; + } + else { + /* action has already been added - simply warn about this, and clear */ + BKE_report(op->reports, RPT_ERROR, "Action has already been stashed"); + } + + /* clear action refs from editor, and then also the backing data (not necessary) */ + actedit_change_action(C, NULL); + } + } + + /* Send notifiers that stuff has changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); + return OPERATOR_FINISHED; +} + +void ACTION_OT_stash(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Stash Action"; + ot->idname = "ACTION_OT_stash"; + ot->description = "Store this action in the NLA stack as a non-contributing strip for later use"; + + /* callbacks */ + ot->exec = action_stash_exec; + ot->poll = action_pushdown_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_boolean(ot->srna, "create_new", true, "Create New Action", + "Create a new action once the existing one has been safely stored"); +} + +/* ----------------- */ + +/* Criteria: + * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions + * 2) The associated AnimData block must not be in tweakmode + */ +static int action_stash_create_poll(bContext *C) +{ + if (ED_operator_action_active(C)) { + SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); + Scene *scene = CTX_data_scene(C); + + /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */ + /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */ + if (!(scene->flag & SCE_NLA_EDIT_ON)) { + /* For now, actions are only for the active object, and on object and shapekey levels... */ + return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY); + } + } + + /* something failed... */ + return false; +} + +static int action_stash_create_exec(bContext *C, wmOperator *op) +{ + SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); + AnimData *adt = actedit_animdata_from_context(C); + + /* Check for no action... */ + if (saction->action == NULL) { + /* just create a new action */ + bAction *action = action_create_new(C, NULL); + actedit_change_action(C, action); + } + else if (adt) { + /* Perform stashing operation */ + if (action_has_motion(adt->action) == 0) { + /* don't do anything if this action is empty... */ + BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier"); + return OPERATOR_CANCELLED; + } + else { + /* stash the action */ + if (BKE_nla_action_stash(adt)) { + bAction *new_action = NULL; + + /* create new action not based on the old one (since the "new" operator already does that) */ + new_action = action_create_new(C, NULL); + + /* The stash operation will remove the user already, + * so the flushing step later shouldn't double up + * the usercount fixes. Hence, we must unset this ref + * first before setting the new action. + */ + saction->action = NULL; + actedit_change_action(C, new_action); + } + else { + /* action has already been added - simply warn about this, and clear */ + BKE_report(op->reports, RPT_ERROR, "Action has already been stashed"); + actedit_change_action(C, NULL); + } + } + } + + /* Send notifiers that stuff has changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); + return OPERATOR_FINISHED; +} + +void ACTION_OT_stash_and_create(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Stash Action"; + ot->idname = "ACTION_OT_stash_and_create"; + ot->description = "Store this action in the NLA stack as a non-contributing strip for later use, and create a new action"; + + /* callbacks */ + ot->exec = action_stash_create_exec; + ot->poll = action_stash_create_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index ce8723c572d..4b8ddacb418 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -80,432 +80,6 @@ #include "action_intern.h" -/* ************************************************************************** */ -/* ACTION MANAGEMENT */ - -/* Helper function to find the active AnimData block from the Action Editor context */ -static AnimData *actedit_animdata_from_context(bContext *C) -{ - SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - Object *ob = CTX_data_active_object(C); - AnimData *adt = NULL; - - /* Get AnimData block to use */ - if (saction->mode == SACTCONT_ACTION) { - /* Currently, "Action Editor" means object-level only... */ - if (ob) { - adt = ob->adt; - } - } - else if (saction->mode == SACTCONT_SHAPEKEY) { - Key *key = BKE_key_from_object(ob); - if (key) { - adt = key->adt; - } - } - - return adt; -} - -/* Create new action */ -static bAction *action_create_new(bContext *C, bAction *oldact) -{ - ScrArea *sa = CTX_wm_area(C); - bAction *action; - - /* create action - the way to do this depends on whether we've got an - * existing one there already, in which case we make a copy of it - * (which is useful for "versioning" actions within the same file) - */ - if (oldact && GS(oldact->id.name) == ID_AC) { - /* make a copy of the existing action */ - action = BKE_action_copy(oldact); - } - else { - /* just make a new (empty) action */ - action = add_empty_action(CTX_data_main(C), "Action"); - } - - /* when creating new ID blocks, there is already 1 user (as for all new datablocks), - * but the RNA pointer code will assign all the proper users instead, so we compensate - * for that here - */ - BLI_assert(action->id.us == 1); - action->id.us--; - - /* set ID-Root type */ - if (sa->spacetype == SPACE_ACTION) { - SpaceAction *saction = (SpaceAction *)sa->spacedata.first; - - if (saction->mode == SACTCONT_SHAPEKEY) - action->idroot = ID_KE; - else - action->idroot = ID_OB; - } - - return action; -} - -/* Change the active action used by the action editor */ -static void actedit_change_action(bContext *C, bAction *act) -{ - bScreen *screen = CTX_wm_screen(C); - SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - - PointerRNA ptr, idptr; - PropertyRNA *prop; - - /* create RNA pointers and get the property */ - RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, saction, &ptr); - prop = RNA_struct_find_property(&ptr, "action"); - - /* NOTE: act may be NULL here, so better to just use a cast here */ - RNA_id_pointer_create((ID *)act, &idptr); - - /* set the new pointer, and force a refresh */ - RNA_property_pointer_set(&ptr, prop, idptr); - RNA_property_update(C, &ptr, prop); -} - -/* ******************** New Action Operator *********************** */ - -/* Criteria: - * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions... - * OR - * The NLA Editor is active (i.e. Animation Data panel -> new action) - * 2) The associated AnimData block must not be in tweakmode - */ -static int action_new_poll(bContext *C) -{ - Scene *scene = CTX_data_scene(C); - - /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */ - /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */ - if (!(scene->flag & SCE_NLA_EDIT_ON)) { - if (ED_operator_action_active(C)) { - SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - Object *ob = CTX_data_active_object(C); - - /* For now, actions are only for the active object, and on object and shapekey levels... */ - if (saction->mode == SACTCONT_ACTION) { - /* XXX: This assumes that actions are assigned to the active object */ - if (ob) - return true; - } - else if (saction->mode == SACTCONT_SHAPEKEY) { - Key *key = BKE_key_from_object(ob); - if (key) - return true; - } - } - else if (ED_operator_nla_active(C)) { - return true; - } - } - - /* something failed... */ - return false; -} - -static int action_new_exec(bContext *C, wmOperator *UNUSED(op)) -{ - PointerRNA ptr, idptr; - PropertyRNA *prop; - - /* hook into UI */ - UI_context_active_but_prop_get_templateID(C, &ptr, &prop); - - if (prop) { - bAction *action = NULL, *oldact = NULL; - AnimData *adt = NULL; - PointerRNA oldptr; - - oldptr = RNA_property_pointer_get(&ptr, prop); - oldact = (bAction *)oldptr.id.data; - - /* stash the old action to prevent it from being lost */ - if (ptr.type == &RNA_AnimData) { - adt = ptr.data; - } - else if (ptr.type == &RNA_SpaceDopeSheetEditor) { - adt = actedit_animdata_from_context(C); - } - - /* Perform stashing operation - But only if there is an action */ - if (adt && oldact) { - /* stash the action */ - if (BKE_nla_action_stash(adt)) { - /* The stash operation will remove the user already - * (and unlink the action from the AnimData action slot). - * Hence, we must unset the ref to the action in the - * action editor too (if this is where we're being called from) - * first before setting the new action once it is created, - * or else the user gets decremented twice! - */ - if (ptr.type == &RNA_SpaceDopeSheetEditor) { - SpaceAction *saction = (SpaceAction *)ptr.data; - saction->action = NULL; - } - } - else { - //printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n", oldact->id.name); - } - } - - /* create action */ - action = action_create_new(C, oldact); - - /* set this new action - * NOTE: we can't use actedit_change_action, as this function is also called from the NLA - */ - RNA_id_pointer_create(&action->id, &idptr); - RNA_property_pointer_set(&ptr, prop, idptr); - RNA_property_update(C, &ptr, prop); - } - - /* set notifier that keyframes have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL); - - return OPERATOR_FINISHED; -} - -void ACTION_OT_new(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "New Action"; - ot->idname = "ACTION_OT_new"; - ot->description = "Create new action"; - - /* api callbacks */ - ot->exec = action_new_exec; - ot->poll = action_new_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* ******************* Action Push-Down Operator ******************** */ - -/* Criteria: - * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions - * 2) There must be an action active - * 3) The associated AnimData block must not be in tweakmode - */ -static int action_pushdown_poll(bContext *C) -{ - if (ED_operator_action_active(C)) { - SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - Scene *scene = CTX_data_scene(C); - Object *ob = CTX_data_active_object(C); - - /* Check for actions and that tweakmode is off */ - if ((saction->action) && !(scene->flag & SCE_NLA_EDIT_ON)) { - /* For now, actions are only for the active object, and on object and shapekey levels... */ - if (saction->mode == SACTCONT_ACTION) { - return (ob->adt != NULL); - } - else if (saction->mode == SACTCONT_SHAPEKEY) { - Key *key = BKE_key_from_object(ob); - - return (key && key->adt); - } - } - } - - /* something failed... */ - return false; -} - -static int action_pushdown_exec(bContext *C, wmOperator *op) -{ - SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - AnimData *adt = actedit_animdata_from_context(C); - - /* Do the deed... */ - if (adt) { - /* Perform the pushdown operation - * - This will deal with all the AnimData-side usercounts - */ - if (action_has_motion(adt->action) == 0) { - /* action may not be suitable... */ - BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier"); - return OPERATOR_CANCELLED; - } - else { - /* action can be safely added */ - BKE_nla_action_pushdown(adt); - } - - /* Stop displaying this action in this editor - * NOTE: The editor itself doesn't set a user... - */ - saction->action = NULL; - } - - /* Send notifiers that stuff has changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); - return OPERATOR_FINISHED; -} - -void ACTION_OT_push_down(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Push Down Action"; - ot->idname = "ACTION_OT_push_down"; - ot->description = "Push action down on to the NLA stack as a new strip"; - - /* callbacks */ - ot->exec = action_pushdown_exec; - ot->poll = action_pushdown_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* ******************* Action Stash Operator ******************** */ - -static int action_stash_exec(bContext *C, wmOperator *op) -{ - SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - AnimData *adt = actedit_animdata_from_context(C); - - /* Perform stashing operation */ - if (adt) { - /* don't do anything if this action is empty... */ - if (action_has_motion(adt->action) == 0) { - /* action may not be suitable... */ - BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier"); - return OPERATOR_CANCELLED; - } - else { - /* stash the action */ - if (BKE_nla_action_stash(adt)) { - /* The stash operation will remove the user already, - * so the flushing step later shouldn't double up - * the usercount fixes. Hence, we must unset this ref - * first before setting the new action. - */ - saction->action = NULL; - } - else { - /* action has already been added - simply warn about this, and clear */ - BKE_report(op->reports, RPT_ERROR, "Action has already been stashed"); - } - - /* clear action refs from editor, and then also the backing data (not necessary) */ - actedit_change_action(C, NULL); - } - } - - /* Send notifiers that stuff has changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); - return OPERATOR_FINISHED; -} - -void ACTION_OT_stash(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Stash Action"; - ot->idname = "ACTION_OT_stash"; - ot->description = "Store this action in the NLA stack as a non-contributing strip for later use"; - - /* callbacks */ - ot->exec = action_stash_exec; - ot->poll = action_pushdown_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - ot->prop = RNA_def_boolean(ot->srna, "create_new", true, "Create New Action", - "Create a new action once the existing one has been safely stored"); -} - -/* ----------------- */ - -/* Criteria: - * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions - * 2) The associated AnimData block must not be in tweakmode - */ -static int action_stash_create_poll(bContext *C) -{ - if (ED_operator_action_active(C)) { - SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - Scene *scene = CTX_data_scene(C); - - /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */ - /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */ - if (!(scene->flag & SCE_NLA_EDIT_ON)) { - /* For now, actions are only for the active object, and on object and shapekey levels... */ - return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY); - } - } - - /* something failed... */ - return false; -} - -static int action_stash_create_exec(bContext *C, wmOperator *op) -{ - SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - AnimData *adt = actedit_animdata_from_context(C); - - /* Check for no action... */ - if (saction->action == NULL) { - /* just create a new action */ - bAction *action = action_create_new(C, NULL); - actedit_change_action(C, action); - } - else if (adt) { - /* Perform stashing operation */ - if (action_has_motion(adt->action) == 0) { - /* don't do anything if this action is empty... */ - BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier"); - return OPERATOR_CANCELLED; - } - else { - /* stash the action */ - if (BKE_nla_action_stash(adt)) { - bAction *new_action = NULL; - - /* create new action not based on the old one (since the "new" operator already does that) */ - new_action = action_create_new(C, NULL); - - /* The stash operation will remove the user already, - * so the flushing step later shouldn't double up - * the usercount fixes. Hence, we must unset this ref - * first before setting the new action. - */ - saction->action = NULL; - actedit_change_action(C, new_action); - } - else { - /* action has already been added - simply warn about this, and clear */ - BKE_report(op->reports, RPT_ERROR, "Action has already been stashed"); - actedit_change_action(C, NULL); - } - } - } - - /* Send notifiers that stuff has changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); - return OPERATOR_FINISHED; -} - -void ACTION_OT_stash_and_create(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Stash Action"; - ot->idname = "ACTION_OT_stash_and_create"; - ot->description = "Store this action in the NLA stack as a non-contributing strip for later use, and create a new action"; - - /* callbacks */ - ot->exec = action_stash_create_exec; - ot->poll = action_stash_create_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} /* ************************************************************************** */ /* POSE MARKERS STUFF */ -- cgit v1.2.3 From 018dc3aeda4ae637a134b043ced15d2c037ddc41 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 3 Apr 2015 02:10:20 +1300 Subject: Action Editor: Experimental tweak to ordering of buttons This commit is an experiment exploring the relationship between the action management buttons (i.e. action selector + pushdown/stash, and soon a few others) and the filtering stuff (i.e. summary, only selected, etc.) The old ordering meant that the filtering stuff was consistently in the same place beside the mode selector, meaning that the order was "common stuff, then editor specific stuff", this was not that great on smaller windows, where there important stuff was often out of view. This new order places greater emphasis on the parts which are likely to be more important. It also allows us to have a better hierarchy/flow; this is especially because we'll soon introduce a way to specify which datablock "level" the action comes from, so going from "level -> action -> filters within action" will make more sense. --- release/scripts/startup/bl_ui/space_dopesheet.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 5358670c2f2..2d362149d8b 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -112,6 +112,14 @@ class DOPESHEET_HT_header(Header): DOPESHEET_MT_editor_menus.draw_collapsible(context, layout) layout.prop(st, "mode", text="") + + if st.mode in {'ACTION', 'SHAPEKEY'}: + layout.template_ID(st, "action", new="action.new") + + row = layout.row(align=True) + row.operator("action.push_down", text="Push Down", icon='NLA_PUSHDOWN') + row.operator("action.stash", text="Stash", icon='FREEZE') + layout.prop(st.dopesheet, "show_summary", text="Summary") if st.mode == 'DOPESHEET': @@ -121,13 +129,6 @@ class DOPESHEET_HT_header(Header): # filters which will work here and are useful (especially for character animation) dopesheet_filter(layout, context, genericFiltersOnly=True) - if st.mode in {'ACTION', 'SHAPEKEY'}: - layout.template_ID(st, "action", new="action.new") - - row = layout.row(align=True) - row.operator("action.push_down", text="Push Down", icon='NLA_PUSHDOWN') - row.operator("action.stash", text="Stash", icon='FREEZE') - # Grease Pencil mode doesn't need snapping, as it's frame-aligned only if st.mode != 'GPENCIL': layout.prop(st, "auto_snap", text="") -- cgit v1.2.3 From 43101289a6696c176ee9d1c5e19b9919d5495455 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 2 Apr 2015 17:13:24 +0200 Subject: Fix T44183 particles in linked group offset from object A nice bug combining all the broken features of blender: Particles, duplis and multiple scene dependencies. Fortunately this was solvable: Basically, we need to make sure derivedmesh for dupli instance is generated before obmat is overriden. This also makes sense, since no instance has "true" obmat apart from original. Lazy initialization of derivedmesh just does not work here (or it -does- work but first use should be before instance drawing). Fingers crossed nothing else breaks after this... --- source/blender/blenkernel/BKE_anim.h | 2 +- source/blender/blenkernel/intern/object_dupli.c | 10 +++++++++- source/blender/editors/space_view3d/view3d_draw.c | 3 ++- source/blender/makesdna/DNA_object_types.h | 2 +- source/blender/render/intern/source/convertblender.c | 2 +- 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index e2b9c66780b..584f0da323a 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -80,7 +80,7 @@ typedef struct DupliApplyData { DupliExtraData *extra; } DupliApplyData; -DupliApplyData *duplilist_apply(struct Object *ob, struct ListBase *duplilist); +DupliApplyData *duplilist_apply(struct Object *ob, struct Scene *scene, struct ListBase *duplilist); void duplilist_restore(struct ListBase *duplilist, DupliApplyData *apply_data); void duplilist_free_apply_data(DupliApplyData *apply_data); diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index c77f65f69e1..8abe4bdbb97 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -1237,7 +1237,7 @@ int count_duplilist(Object *ob) return 1; } -DupliApplyData *duplilist_apply(Object *ob, ListBase *duplilist) +DupliApplyData *duplilist_apply(Object *ob, Scene *scene, ListBase *duplilist) { DupliApplyData *apply_data = NULL; int num_objects = BLI_listbase_count(duplilist); @@ -1253,6 +1253,13 @@ DupliApplyData *duplilist_apply(Object *ob, ListBase *duplilist) for (dob = duplilist->first, i = 0; dob; dob = dob->next, ++i) { /* copy obmat from duplis */ copy_m4_m4(apply_data->extra[i].obmat, dob->ob->obmat); + + /* make sure derivedmesh is calculated once, before drawing */ + if (scene && !(dob->ob->transflag & OB_DUPLICALCDERIVED) && dob->ob->type == OB_MESH) { + mesh_get_derived_final(scene, dob->ob, scene->customdata_mask); + dob->ob->transflag |= OB_DUPLICALCDERIVED; + } + copy_m4_m4(dob->ob->obmat, dob->mat); /* copy layers from the main duplicator object */ @@ -1273,6 +1280,7 @@ void duplilist_restore(ListBase *duplilist, DupliApplyData *apply_data) */ for (dob = duplilist->last, i = apply_data->num_objects - 1; dob; dob = dob->prev, --i) { copy_m4_m4(dob->ob->obmat, apply_data->extra[i].obmat); + dob->ob->transflag &= ~OB_DUPLICALCDERIVED; dob->ob->lay = apply_data->extra[i].lay; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index e51993ce91f..8600c1190d4 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -55,6 +55,7 @@ #include "BKE_camera.h" #include "BKE_context.h" #include "BKE_customdata.h" +#include "BKE_DerivedMesh.h" #include "BKE_image.h" #include "BKE_key.h" #include "BKE_main.h" @@ -2051,7 +2052,7 @@ static void draw_dupli_objects_color( lb = object_duplilist(G.main->eval_ctx, scene, base->object); // BLI_listbase_sort(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */ - apply_data = duplilist_apply(base->object, lb); + apply_data = duplilist_apply(base->object, scene, lb); dob = dupli_step(lb->first); if (dob) dob_next = dupli_step(dob->next); diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 702d9acfb58..286461f1b69 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -397,7 +397,7 @@ enum { OB_DUPLIVERTS = 1 << 4, OB_DUPLIROT = 1 << 5, OB_DUPLINOSPEED = 1 << 6, -/* OB_POWERTRACK = 1 << 7,*/ /*UNUSED*/ + OB_DUPLICALCDERIVED = 1 << 7, /* runtime, calculate derivedmesh for dupli before it's used */ OB_DUPLIGROUP = 1 << 8, OB_DUPLIFACES = 1 << 9, OB_DUPLIFACES_SCALE = 1 << 10, diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index e900d29aa19..8c9bebe7ff9 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -5002,7 +5002,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp * system need to have render settings set for dupli particles */ dupli_render_particle_set(re, ob, timeoffset, 0, 1); duplilist = object_duplilist(re->eval_ctx, re->scene, ob); - duplilist_apply_data = duplilist_apply(ob, duplilist); + duplilist_apply_data = duplilist_apply(ob, NULL, duplilist); dupli_render_particle_set(re, ob, timeoffset, 0, 0); for (dob= duplilist->first, i = 0; dob; dob= dob->next, ++i) { -- cgit v1.2.3 From 89530f1486cecb3b1036d1b06964aee1ba68d3ac Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 3 Apr 2015 11:17:58 +0200 Subject: Fix T44240: Lamp Halo invisible in rendering. Halo is not possible when using 'deep' buffer shadow - reflect that in UI. When not using buffered shadows, switch lamp bufftype to 'regular' on render, as already done with 'halfway' method. --- release/scripts/startup/bl_ui/properties_data_lamp.py | 1 + source/blender/render/intern/source/convertblender.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_lamp.py b/release/scripts/startup/bl_ui/properties_data_lamp.py index 6fef30fa3e6..0121ad46c86 100644 --- a/release/scripts/startup/bl_ui/properties_data_lamp.py +++ b/release/scripts/startup/bl_ui/properties_data_lamp.py @@ -355,6 +355,7 @@ class DATA_PT_spot(DataButtonsPanel, Panel): col = split.column() + col.active = (lamp.shadow_method != 'BUFFER_SHADOW' or lamp.shadow_buffer_type != 'DEEP') col.prop(lamp, "use_halo") sub = col.column(align=True) sub.active = lamp.use_halo diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 8c9bebe7ff9..c0ba2f43c36 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -3813,7 +3813,9 @@ static GroupObject *add_render_lamp(Render *re, Object *ob) } /* set flag for spothalo en initvars */ - if (la->type==LA_SPOT && (la->mode & LA_HALO) && (la->buftype != LA_SHADBUF_DEEP)) { + if ((la->type == LA_SPOT) && (la->mode & LA_HALO) && + (!(la->mode & LA_SHAD_BUF) || la->buftype != LA_SHADBUF_DEEP)) + { if (la->haint>0.0f) { re->flag |= R_LAMPHALO; @@ -3832,7 +3834,7 @@ static GroupObject *add_render_lamp(Render *re, Object *ob) lar->sh_invcampos[2]*= lar->sh_zfac; /* halfway shadow buffer doesn't work for volumetric effects */ - if (lar->buftype == LA_SHADBUF_HALFWAY) + if (ELEM(lar->buftype, LA_SHADBUF_HALFWAY, LA_SHADBUF_DEEP)) lar->buftype = LA_SHADBUF_REGULAR; } -- cgit v1.2.3 From 99d8e08ed9df1d8b163908eceb81fc8c7990f853 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 3 Apr 2015 12:26:29 +0200 Subject: Fix T44237: translation does not work in spacebar search. Added translation there, also fixed a stupid bug which was leading most internal operators to have 'dual' i18n_context (default NULL one and default 'Operator' one). --- source/blender/editors/interface/interface_templates.c | 7 ++++--- source/blender/windowmanager/intern/wm_operators.c | 9 +++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 73df06bcc37..c4158fe2a17 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -3274,17 +3274,18 @@ static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { wmOperatorType *ot = BLI_ghashIterator_getValue(&iter); + const char *ot_ui_name = CTX_IFACE_(ot->translation_context, ot->name); if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) continue; - if (BLI_strcasestr(ot->name, str)) { + if (BLI_strcasestr(ot_ui_name, str)) { if (WM_operator_poll((bContext *)C, ot)) { char name[256]; - int len = strlen(ot->name); + int len = strlen(ot_ui_name); /* display name for menu, can hold hotkey */ - BLI_strncpy(name, ot->name, sizeof(name)); + BLI_strncpy(name, ot_ui_name, sizeof(name)); /* check for hotkey */ if (len < sizeof(name) - 6) { diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 6f9646f35a1..c62e82b8e43 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -172,6 +172,7 @@ void WM_operatortype_append(void (*opfunc)(wmOperatorType *)) ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties); /* Set the default i18n context now, so that opfunc can redefine it if needed! */ RNA_def_struct_translation_context(ot->srna, BLF_I18NCONTEXT_OPERATOR_DEFAULT); + ot->translation_context = BLF_I18NCONTEXT_OPERATOR_DEFAULT; opfunc(ot); if (ot->name == NULL) { @@ -194,6 +195,7 @@ void WM_operatortype_append_ptr(void (*opfunc)(wmOperatorType *, void *), void * ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties); /* Set the default i18n context now, so that opfunc can redefine it if needed! */ RNA_def_struct_translation_context(ot->srna, BLF_I18NCONTEXT_OPERATOR_DEFAULT); + ot->translation_context = BLF_I18NCONTEXT_OPERATOR_DEFAULT; opfunc(ot, userdata); RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP); RNA_def_struct_identifier(ot->srna, ot->idname); @@ -374,6 +376,7 @@ static void wm_macro_cancel(bContext *C, wmOperator *op) wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *name, const char *description, int flag) { wmOperatorType *ot; + const char *i18n_context; if (WM_operatortype_find(idname, true)) { printf("%s: macro error: operator %s exists\n", __func__, idname); @@ -400,8 +403,9 @@ wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *nam RNA_def_struct_ui_text(ot->srna, ot->name, ot->description); RNA_def_struct_identifier(ot->srna, ot->idname); /* Use i18n context from ext.srna if possible (py operators). */ - RNA_def_struct_translation_context(ot->srna, ot->ext.srna ? RNA_struct_translation_context(ot->ext.srna) : - BLF_I18NCONTEXT_OPERATOR_DEFAULT); + i18n_context = ot->ext.srna ? RNA_struct_translation_context(ot->ext.srna) : BLF_I18NCONTEXT_OPERATOR_DEFAULT; + RNA_def_struct_translation_context(ot->srna, i18n_context); + ot->translation_context = i18n_context; BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot); @@ -427,6 +431,7 @@ void WM_operatortype_append_macro_ptr(void (*opfunc)(wmOperatorType *, void *), /* Set the default i18n context now, so that opfunc can redefine it if needed! */ RNA_def_struct_translation_context(ot->srna, BLF_I18NCONTEXT_OPERATOR_DEFAULT); + ot->translation_context = BLF_I18NCONTEXT_OPERATOR_DEFAULT; opfunc(ot, userdata); RNA_def_struct_ui_text(ot->srna, ot->name, ot->description); -- cgit v1.2.3 From 13a63234d6a63c334b550215b3345b46956fcef7 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 3 Apr 2015 12:38:59 +0200 Subject: Fix T44237: translation does not work for input sockets in 'Active node properties' panel. --- release/scripts/startup/bl_ui/space_node.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index a5ab6898b13..31bfed21c4a 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -19,6 +19,7 @@ # import bpy from bpy.types import Header, Menu, Panel +from bpy.app.translations import pgettext_iface as iface_ from bl_ui.properties_grease_pencil_common import ( GreasePencilDrawingToolsPanel, GreasePencilStrokeEditPanel, @@ -358,7 +359,7 @@ class NODE_PT_active_node_properties(Panel): layout.label("Inputs:") for socket in value_inputs: row = layout.row() - socket.draw(context, row, node, socket.name) + socket.draw(context, row, node, iface_(socket.name, socket.bl_rna.translation_context)) # Node Backdrop options -- cgit v1.2.3 From bcf1abbc83a6673b4111f52c83cfce88597f20d5 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 3 Apr 2015 23:15:56 +1300 Subject: Action Editor: Go to Next/Previous Animation Layer With this feature, it is now possible to quickly switch between different actions stacked/stashed on top of each other in the NLA Stack without having to go to the NLA Editor and doing a tab-select-tab dance, thus saving quite a few clicks. It was specifically designed with Game Animation / Action Library workflows in mind, but also helps layered animation workflows. Usage: Simply click on the up/down arrow buttons (between the action datablock selector and the pushdown/stash buttons) to go to the action in the NLA Track above/below the NLA Strip being whose action is being tweaked in the Action Editor. Notes: - These still work when you're not editing the action used by a NLA Strip. If you're just animating a new action normally, it is possible to use the "down arrow" to temporarily jump down to the previous action without losing the new action you're working on, and then use the "up arrow" to get back to it once you're done checking the other action(s). - If there are multiple actions/strips on the same layer/track, then only the one closest to the current frame will be used. --- release/scripts/startup/bl_ui/space_dopesheet.py | 4 + source/blender/editors/space_action/action_data.c | 322 +++++++++++++++++++++ .../blender/editors/space_action/action_intern.h | 3 + source/blender/editors/space_action/action_ops.c | 3 + 4 files changed, 332 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 2d362149d8b..27fc73f88b6 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -116,6 +116,10 @@ class DOPESHEET_HT_header(Header): if st.mode in {'ACTION', 'SHAPEKEY'}: layout.template_ID(st, "action", new="action.new") + row = layout.row(align=True) + row.operator("action.layer_prev", text="", icon='TRIA_DOWN') + row.operator("action.layer_next", text="", icon='TRIA_UP') + row = layout.row(align=True) row.operator("action.push_down", text="Push Down", icon='NLA_PUSHDOWN') row.operator("action.stash", text="Stash", icon='FREEZE') diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index d3693608a1f..111cb5257da 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -51,6 +51,7 @@ #include "RNA_define.h" #include "RNA_enum_types.h" +#include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_fcurve.h" #include "BKE_global.h" @@ -58,6 +59,7 @@ #include "BKE_key.h" #include "BKE_main.h" #include "BKE_nla.h" +#include "BKE_scene.h" #include "BKE_context.h" #include "BKE_report.h" @@ -507,3 +509,323 @@ void ACTION_OT_stash_and_create(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/* ************************************************************************** */ +/* ACTION BROWSING */ + +/* Get the NLA Track that the active action comes from, since this is not stored in AnimData */ +/* TODO: Move this to blenkernel/nla.c */ +static NlaTrack *nla_tweak_track_get(AnimData *adt) +{ + NlaTrack *nlt; + + /* sanity check */ + if (adt == NULL) + return NULL; + + /* Since the track itself gets disabled, we want the first disabled... */ + for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { + if (nlt->flag & (NLATRACK_ACTIVE | NLATRACK_DISABLED)) { + /* For good measure, make sure that strip actually exists there */ + if (BLI_findindex(&nlt->strips, adt->actstrip) != -1) { + return nlt; + } + else if (G.debug & G_DEBUG) { + printf("%s: Active strip (%p, %s) not in NLA track found (%p, %s)\n", + __func__, + adt->actstrip, (adt->actstrip) ? adt->actstrip->name : "", + nlt, (nlt) ? nlt->name : ""); + } + } + } + + /* Not found! */ + return NULL; +} + +/* ********************** One Layer Up Operator ************************** */ + +static int action_layer_next_poll(bContext *C) +{ + /* Action Editor's action editing modes only */ + if (ED_operator_action_active(C)) { + AnimData *adt = actedit_animdata_from_context(C); + if (adt) { + /* only allow if we're in tweakmode, and there's something above us... */ + if (adt->flag & ADT_NLA_EDIT_ON) { + /* We need to check if there are any tracks above the active one + * since the track the action comes from is not stored in AnimData + */ + if (adt->nla_tracks.last) { + NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.last; + + if (nlt->flag & NLATRACK_DISABLED) { + /* A disabled track will either be the track itself, + * or one of the ones above it. + * + * If this is the top-most one, there is the possibility + * that there is no active action. For now, we let this + * case return true too, so that there is a natural way + * to "move to an empty layer", even though this means + * that we won't actually have an action. + */ + // return (adt->tmpact != NULL); + return true; + } + } + } + } + } + + /* something failed... */ + return false; +} + +static int action_layer_next_exec(bContext *C, wmOperator *op) +{ + AnimData *adt = actedit_animdata_from_context(C); + NlaTrack *act_track; + + Scene *scene = CTX_data_scene(C); + float ctime = BKE_scene_frame_get(scene); + + /* Get active track */ + act_track = nla_tweak_track_get(adt); + + if (act_track == NULL) { + BKE_report(op->reports, RPT_ERROR, "Could not find current NLA Track"); + return OPERATOR_CANCELLED; + } + + /* Find next action, and hook it up */ + if (act_track->next) { + NlaTrack *nlt; + NlaStrip *strip; + bool found = false; + + /* Find next action to use */ + for (nlt = act_track->next; nlt && !found; nlt = nlt->next) { + for (strip = nlt->strips.first; strip; strip = strip->next) { + /* Can we use this? */ + if (IN_RANGE_INCL(ctime, strip->start, strip->end)) { + /* in range - use this one */ + found = true; + } + else if ((ctime < strip->start) && (strip->prev == NULL)) { + /* before first - use this one */ + found = true; + } + else if ((ctime > strip->end) && (strip->next == NULL)) { + /* after last - use this one */ + found = true; + } + + /* Apply... */ + if (found) { + NlaStrip *old_strip = adt->actstrip; + + /* Exit tweakmode on old strip + * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it + */ + BKE_nla_tweakmode_exit(adt); + + old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); + act_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED); + + /* Make this one the active one instead */ + strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); + nlt->flag |= NLATRACK_ACTIVE; + + /* Copy over "solo" flag - This is useful for stashed actions... */ + if (act_track->flag & NLATRACK_SOLO) { + act_track->flag &= ~NLATRACK_SOLO; + nlt->flag |= NLATRACK_SOLO; + } + + /* Enter tweakmode again - hopefully we're now "it" */ + BKE_nla_tweakmode_enter(adt); + BLI_assert(adt->actstrip == strip); + + break; + } + } + } + } + else { + /* No more actions - Go back to editing the original active action + * NOTE: This will mean exiting tweakmode... + */ + BKE_nla_tweakmode_exit(adt); + + /* Deal with solo flags... */ + // XXX: if solo, turn off NLA while we edit this action? + act_track->flag &= ~NLATRACK_SOLO; + adt->flag &= ~ADT_NLA_SOLO_TRACK; + } + + /* Update the action that this editor now uses + * NOTE: The calls above have already handled the usercount/animdata side of things + */ + actedit_change_action(C, adt->action); + return OPERATOR_FINISHED; +} + +void ACTION_OT_layer_next(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Next Layer"; + ot->idname = "ACTION_OT_layer_next"; + ot->description = "Edit action in animation layer above the current action in the NLA Stack"; + + /* callbacks */ + ot->exec = action_layer_next_exec; + ot->poll = action_layer_next_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ********************* One Layer Down Operator ************************* */ + +static int action_layer_prev_poll(bContext *C) +{ + /* Action Editor's action editing modes only */ + if (ED_operator_action_active(C)) { + AnimData *adt = actedit_animdata_from_context(C); + if (adt) { + if (adt->flag & ADT_NLA_EDIT_ON) { + /* Tweak Mode: We need to check if there are any tracks below the active one that we can move to */ + if (adt->nla_tracks.first) { + NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.first; + + /* Since the first disabled track is the track being tweaked/edited, + * we can simplify things by only checking the first track: + * - If it is disabled, this is the track being tweaked, + * so there can't be anything below it + * - Otherwise, there is at least 1 track below the tweaking + * track that we can descend to + */ + if ((nlt->flag & NLATRACK_DISABLED) == 0) { + /* not disabled = there are actions below the one being tweaked */ + return true; + } + } + } + else { + /* Normal Mode: If there are any tracks, we can try moving to those */ + return (adt->nla_tracks.first != NULL); + } + } + } + + /* something failed... */ + return false; +} + +static int action_layer_prev_exec(bContext *C, wmOperator *op) +{ + AnimData *adt = actedit_animdata_from_context(C); + NlaTrack *act_track; + + NlaTrack *nlt; + NlaStrip *strip; + bool found = false; + + Scene *scene = CTX_data_scene(C); + float ctime = BKE_scene_frame_get(scene); + + /* Sanity Check */ + if (adt == NULL) { + BKE_report(op->reports, RPT_ERROR, "Internal Error: Could not find Animation Data/NLA Stack to use"); + return OPERATOR_CANCELLED; + } + + /* Get active track */ + act_track = nla_tweak_track_get(adt); + + /* If there is no active track, that means we are using the active action... */ + if (act_track) { + /* Active Track - Start from the one below it */ + nlt = act_track->prev; + } + else { + /* Active Action - Use the top-most track */ + nlt = adt->nla_tracks.last; + } + + /* Find previous action and hook it up */ + for (; nlt && !found; nlt = nlt->prev) { + for (strip = nlt->strips.first; strip; strip = strip->next) { + /* Can we use this? */ + if (IN_RANGE_INCL(ctime, strip->start, strip->end)) { + /* in range - use this one */ + found = true; + } + else if ((ctime < strip->start) && (strip->prev == NULL)) { + /* before first - use this one */ + found = true; + } + else if ((ctime > strip->end) && (strip->next == NULL)) { + /* after last - use this one */ + found = true; + } + + /* Apply... */ + if (found) { + NlaStrip *old_strip = adt->actstrip; + + /* Exit tweakmode on old strip + * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it + */ + BKE_nla_tweakmode_exit(adt); + + if (old_strip) { + old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); + } + if (act_track) { + act_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED); + } + + /* Make this one the active one instead */ + strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); + nlt->flag |= NLATRACK_ACTIVE; + + /* Copy over "solo" flag - This is useful for stashed actions... */ + if (act_track) { + if (act_track->flag & NLATRACK_SOLO) { + act_track->flag &= ~NLATRACK_SOLO; + nlt->flag |= NLATRACK_SOLO; + } + } + + /* Enter tweakmode again - hopefully we're now "it" */ + BKE_nla_tweakmode_enter(adt); + BLI_assert(adt->actstrip == strip); + + break; + } + } + } + + /* Update the action that this editor now uses + * NOTE: The calls above have already handled the usercount/animdata side of things + */ + actedit_change_action(C, adt->action); + return OPERATOR_FINISHED; +} + +void ACTION_OT_layer_prev(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Previous Layer"; + ot->idname = "ACTION_OT_layer_prev"; + ot->description = "Edit action in animation layer below the current action in the NLA Stack"; + + /* callbacks */ + ot->exec = action_layer_prev_exec; + ot->poll = action_layer_prev_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ************************************************************************** */ diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index 9a19e4a926b..3b0da089b9b 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -102,6 +102,9 @@ void ACTION_OT_push_down(struct wmOperatorType *ot); void ACTION_OT_stash(struct wmOperatorType *ot); void ACTION_OT_stash_and_create(struct wmOperatorType *ot); +void ACTION_OT_layer_next(struct wmOperatorType *ot); +void ACTION_OT_layer_prev(struct wmOperatorType *ot); + void ACTION_OT_markers_make_local(struct wmOperatorType *ot); /* defines for snap keyframes diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 8c706d8da57..431dd27d064 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -83,6 +83,9 @@ void action_operatortypes(void) WM_operatortype_append(ACTION_OT_stash); WM_operatortype_append(ACTION_OT_stash_and_create); + WM_operatortype_append(ACTION_OT_layer_next); + WM_operatortype_append(ACTION_OT_layer_prev); + WM_operatortype_append(ACTION_OT_previewrange_set); WM_operatortype_append(ACTION_OT_view_all); WM_operatortype_append(ACTION_OT_view_selected); -- cgit v1.2.3 From f350e9f3fcfd5818e345a8c5b9f543a052940556 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 3 Apr 2015 23:33:32 +1300 Subject: Code Cleanup: Split out duplicate code for finding an available NLA strip above/below --- source/blender/editors/space_action/action_data.c | 174 ++++++++++------------ 1 file changed, 82 insertions(+), 92 deletions(-) diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index 111cb5257da..a3e189124fb 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -542,6 +542,31 @@ static NlaTrack *nla_tweak_track_get(AnimData *adt) return NULL; } +/* Try to find NLA Strip to use for action layer up/down tool */ +static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime) +{ + NlaStrip *strip; + + for (strip = strips->first; strip; strip = strip->next) { + /* Can we use this? */ + if (IN_RANGE_INCL(ctime, strip->start, strip->end)) { + /* in range - use this one */ + return strip; + } + else if ((ctime < strip->start) && (strip->prev == NULL)) { + /* before first - use this one */ + return strip; + } + else if ((ctime > strip->end) && (strip->next == NULL)) { + /* after last - use this one */ + return strip; + } + } + + /* nothing suitable found... */ + return NULL; +} + /* ********************** One Layer Up Operator ************************** */ static int action_layer_next_poll(bContext *C) @@ -599,54 +624,37 @@ static int action_layer_next_exec(bContext *C, wmOperator *op) /* Find next action, and hook it up */ if (act_track->next) { NlaTrack *nlt; - NlaStrip *strip; - bool found = false; /* Find next action to use */ - for (nlt = act_track->next; nlt && !found; nlt = nlt->next) { - for (strip = nlt->strips.first; strip; strip = strip->next) { - /* Can we use this? */ - if (IN_RANGE_INCL(ctime, strip->start, strip->end)) { - /* in range - use this one */ - found = true; - } - else if ((ctime < strip->start) && (strip->prev == NULL)) { - /* before first - use this one */ - found = true; - } - else if ((ctime > strip->end) && (strip->next == NULL)) { - /* after last - use this one */ - found = true; - } + for (nlt = act_track->next; nlt; nlt = nlt->next) { + NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime); + + if (strip) { + NlaStrip *old_strip = adt->actstrip; - /* Apply... */ - if (found) { - NlaStrip *old_strip = adt->actstrip; - - /* Exit tweakmode on old strip - * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it - */ - BKE_nla_tweakmode_exit(adt); - - old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); - act_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED); - - /* Make this one the active one instead */ - strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); - nlt->flag |= NLATRACK_ACTIVE; - - /* Copy over "solo" flag - This is useful for stashed actions... */ - if (act_track->flag & NLATRACK_SOLO) { - act_track->flag &= ~NLATRACK_SOLO; - nlt->flag |= NLATRACK_SOLO; - } - - /* Enter tweakmode again - hopefully we're now "it" */ - BKE_nla_tweakmode_enter(adt); - BLI_assert(adt->actstrip == strip); - - break; + /* Exit tweakmode on old strip + * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it + */ + BKE_nla_tweakmode_exit(adt); + + old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); + act_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED); + + /* Make this one the active one instead */ + strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); + nlt->flag |= NLATRACK_ACTIVE; + + /* Copy over "solo" flag - This is useful for stashed actions... */ + if (act_track->flag & NLATRACK_SOLO) { + act_track->flag &= ~NLATRACK_SOLO; + nlt->flag |= NLATRACK_SOLO; } + + /* Enter tweakmode again - hopefully we're now "it" */ + BKE_nla_tweakmode_enter(adt); + BLI_assert(adt->actstrip == strip); + + break; } } } @@ -725,10 +733,7 @@ static int action_layer_prev_exec(bContext *C, wmOperator *op) { AnimData *adt = actedit_animdata_from_context(C); NlaTrack *act_track; - NlaTrack *nlt; - NlaStrip *strip; - bool found = false; Scene *scene = CTX_data_scene(C); float ctime = BKE_scene_frame_get(scene); @@ -753,56 +758,41 @@ static int action_layer_prev_exec(bContext *C, wmOperator *op) } /* Find previous action and hook it up */ - for (; nlt && !found; nlt = nlt->prev) { - for (strip = nlt->strips.first; strip; strip = strip->next) { - /* Can we use this? */ - if (IN_RANGE_INCL(ctime, strip->start, strip->end)) { - /* in range - use this one */ - found = true; - } - else if ((ctime < strip->start) && (strip->prev == NULL)) { - /* before first - use this one */ - found = true; + for (; nlt; nlt = nlt->prev) { + NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime); + + if (strip) { + NlaStrip *old_strip = adt->actstrip; + + /* Exit tweakmode on old strip + * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it + */ + BKE_nla_tweakmode_exit(adt); + + if (old_strip) { + old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); } - else if ((ctime > strip->end) && (strip->next == NULL)) { - /* after last - use this one */ - found = true; + if (act_track) { + act_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED); } - /* Apply... */ - if (found) { - NlaStrip *old_strip = adt->actstrip; - - /* Exit tweakmode on old strip - * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it - */ - BKE_nla_tweakmode_exit(adt); - - if (old_strip) { - old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); - } - if (act_track) { - act_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED); - } - - /* Make this one the active one instead */ - strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); - nlt->flag |= NLATRACK_ACTIVE; - - /* Copy over "solo" flag - This is useful for stashed actions... */ - if (act_track) { - if (act_track->flag & NLATRACK_SOLO) { - act_track->flag &= ~NLATRACK_SOLO; - nlt->flag |= NLATRACK_SOLO; - } + /* Make this one the active one instead */ + strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); + nlt->flag |= NLATRACK_ACTIVE; + + /* Copy over "solo" flag - This is useful for stashed actions... */ + if (act_track) { + if (act_track->flag & NLATRACK_SOLO) { + act_track->flag &= ~NLATRACK_SOLO; + nlt->flag |= NLATRACK_SOLO; } - - /* Enter tweakmode again - hopefully we're now "it" */ - BKE_nla_tweakmode_enter(adt); - BLI_assert(adt->actstrip == strip); - - break; } + + /* Enter tweakmode again - hopefully we're now "it" */ + BKE_nla_tweakmode_enter(adt); + BLI_assert(adt->actstrip == strip); + + break; } } -- cgit v1.2.3 From 961dac55cfc74f778ac0868e39707daea3098ef6 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 3 Apr 2015 23:50:07 +1300 Subject: Code Cleanup: Deduplicate logic to switch between NLA Strips/Actions --- source/blender/editors/space_action/action_data.c | 90 +++++++++-------------- 1 file changed, 36 insertions(+), 54 deletions(-) diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index a3e189124fb..52c8729fc8a 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -567,6 +567,40 @@ static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime) return NULL; } +/* Switch NLA Strips/Actions */ +static void action_layer_switch_strip(AnimData *adt, + NlaTrack *old_track, NlaStrip *old_strip, + NlaTrack *nlt, NlaStrip *strip) +{ + /* Exit tweakmode on old strip + * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it + */ + BKE_nla_tweakmode_exit(adt); + + if (old_strip) { + old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); + } + if (old_track) { + old_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED); + } + + /* Make this one the active one instead */ + strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); + nlt->flag |= NLATRACK_ACTIVE; + + /* Copy over "solo" flag - This is useful for stashed actions... */ + if (old_track) { + if (old_track->flag & NLATRACK_SOLO) { + old_track->flag &= ~NLATRACK_SOLO; + nlt->flag |= NLATRACK_SOLO; + } + } + + /* Enter tweakmode again - hopefully we're now "it" */ + BKE_nla_tweakmode_enter(adt); + BLI_assert(adt->actstrip == strip); +} + /* ********************** One Layer Up Operator ************************** */ static int action_layer_next_poll(bContext *C) @@ -630,30 +664,7 @@ static int action_layer_next_exec(bContext *C, wmOperator *op) NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime); if (strip) { - NlaStrip *old_strip = adt->actstrip; - - /* Exit tweakmode on old strip - * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it - */ - BKE_nla_tweakmode_exit(adt); - - old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); - act_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED); - - /* Make this one the active one instead */ - strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); - nlt->flag |= NLATRACK_ACTIVE; - - /* Copy over "solo" flag - This is useful for stashed actions... */ - if (act_track->flag & NLATRACK_SOLO) { - act_track->flag &= ~NLATRACK_SOLO; - nlt->flag |= NLATRACK_SOLO; - } - - /* Enter tweakmode again - hopefully we're now "it" */ - BKE_nla_tweakmode_enter(adt); - BLI_assert(adt->actstrip == strip); - + action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip); break; } } @@ -762,36 +773,7 @@ static int action_layer_prev_exec(bContext *C, wmOperator *op) NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime); if (strip) { - NlaStrip *old_strip = adt->actstrip; - - /* Exit tweakmode on old strip - * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it - */ - BKE_nla_tweakmode_exit(adt); - - if (old_strip) { - old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); - } - if (act_track) { - act_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED); - } - - /* Make this one the active one instead */ - strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT); - nlt->flag |= NLATRACK_ACTIVE; - - /* Copy over "solo" flag - This is useful for stashed actions... */ - if (act_track) { - if (act_track->flag & NLATRACK_SOLO) { - act_track->flag &= ~NLATRACK_SOLO; - nlt->flag |= NLATRACK_SOLO; - } - } - - /* Enter tweakmode again - hopefully we're now "it" */ - BKE_nla_tweakmode_enter(adt); - BLI_assert(adt->actstrip == strip); - + action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip); break; } } -- cgit v1.2.3 From 943b830bf6b0b992323e9d439bdf7ed758212846 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 4 Apr 2015 00:13:42 +1300 Subject: Action Layer Up/Down: Fixes for NLA Solo / NLA Muting Now marking NLA Tracks as Solo'd and muting the NLA stack are linked together when using the Action Layer Up/Down tools. That is, when switching from a NLA strip to the active action, if the track was solo'd, then the NLA stack will get muted; and when switching from the active action to a NLA track, if the stack was muted, the track will get solo'd. This linkage means that we ensure that when moving up and down the stack, we can continue to check the actions in isolation without things messing up when you switch to and from the active action. Also fixed a bug where this wasn't getting applied when going in the other direction. TODO: - When we get the rest/reference track support, we're going to need to insert some calls to flush the restpose values so that values from the previously used action do not pollute the pose for the new action (if not all the same controls get keyed across both). For now, it's best to only do this switching from the first frame. --- source/blender/editors/space_action/action_data.c | 32 +++++++++++++++++++---- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index 52c8729fc8a..e141789d7a9 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -595,6 +595,19 @@ static void action_layer_switch_strip(AnimData *adt, nlt->flag |= NLATRACK_SOLO; } } + else { + /* NLA muting <==> Solo Tracks */ + if (adt->flag & ADT_NLA_EVAL_OFF) { + /* disable NLA muting */ + adt->flag &= ~ADT_NLA_EVAL_OFF; + + /* mark this track as being solo */ + adt->flag |= ADT_NLA_SOLO_TRACK; + nlt->flag |= NLATRACK_SOLO; + + // TODO: Needs restpose flushing (when we get reference track) + } + } /* Enter tweakmode again - hopefully we're now "it" */ BKE_nla_tweakmode_enter(adt); @@ -670,15 +683,24 @@ static int action_layer_next_exec(bContext *C, wmOperator *op) } } else { - /* No more actions - Go back to editing the original active action + /* No more actions (strips) - Go back to editing the original active action * NOTE: This will mean exiting tweakmode... */ BKE_nla_tweakmode_exit(adt); - /* Deal with solo flags... */ - // XXX: if solo, turn off NLA while we edit this action? - act_track->flag &= ~NLATRACK_SOLO; - adt->flag &= ~ADT_NLA_SOLO_TRACK; + /* Deal with solo flags... + * Assume: Solo Track == NLA Muting + */ + if (adt->flag & ADT_NLA_SOLO_TRACK) { + /* turn off solo flags on tracks */ + act_track->flag &= ~NLATRACK_SOLO; + adt->flag &= ~ADT_NLA_SOLO_TRACK; + + /* turn on NLA muting (to keep same effect) */ + adt->flag |= ADT_NLA_EVAL_OFF; + + // TODO: Needs restpose flushing (when we get reference track) + } } /* Update the action that this editor now uses -- cgit v1.2.3 From 5681b4fc83c4ce96ae15a0ab63bea94a9b53b142 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 4 Apr 2015 00:16:40 +1300 Subject: Action Editor: Move up/down buttons to be before the datablock selector It turned out that the constantly changing width of the datablock selector made it a pain to use these to quickly toggle between different actions, as the buttons would keep jumping around, thus leading to errors when quickly toggling between actions. This way doesn't look quite as great, but should be more usable. --- release/scripts/startup/bl_ui/space_dopesheet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 27fc73f88b6..c4452ee61f4 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -114,12 +114,12 @@ class DOPESHEET_HT_header(Header): layout.prop(st, "mode", text="") if st.mode in {'ACTION', 'SHAPEKEY'}: - layout.template_ID(st, "action", new="action.new") - row = layout.row(align=True) row.operator("action.layer_prev", text="", icon='TRIA_DOWN') row.operator("action.layer_next", text="", icon='TRIA_UP') + layout.template_ID(st, "action", new="action.new") + row = layout.row(align=True) row.operator("action.push_down", text="Push Down", icon='NLA_PUSHDOWN') row.operator("action.stash", text="Stash", icon='FREEZE') -- cgit v1.2.3 From b30836dad742f4f6c72e0b5b58cf1abe2fcef09d Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 4 Apr 2015 01:05:52 +1300 Subject: Fix: Action/NLA Tweakmode Checks Made all action management operators use the AnimData-local flag instead of the scene global one. Technically, this is more accurate and results in less blocking situations (i.e. another object may be in tweakmode, but because of that, the active object's action couldn't be stashed). The main impetus for this though was that the Action Up/Down feature doesn't clear the global flag, since it is not in a position to do so (since it can't load up everything to clear it). TODO: I'll need to review how this global flag works and/or potentially ditch it (or perhaps add some better ways to ensure that it stays valid), since while thinking this over, I've noticed a few problems here. But, for the meantime, this commit at least makes things more usable here in the short term. --- source/blender/editors/space_action/action_data.c | 77 +++++++++++++---------- 1 file changed, 44 insertions(+), 33 deletions(-) diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index e141789d7a9..f7e110e3b90 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -182,25 +182,29 @@ static int action_new_poll(bContext *C) Scene *scene = CTX_data_scene(C); /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */ - /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */ - if (!(scene->flag & SCE_NLA_EDIT_ON)) { - if (ED_operator_action_active(C)) { - SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - Object *ob = CTX_data_active_object(C); - - /* For now, actions are only for the active object, and on object and shapekey levels... */ - if (saction->mode == SACTCONT_ACTION) { - /* XXX: This assumes that actions are assigned to the active object */ - if (ob) + /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */ + if (ED_operator_action_active(C)) { + SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); + Object *ob = CTX_data_active_object(C); + + /* For now, actions are only for the active object, and on object and shapekey levels... */ + if (saction->mode == SACTCONT_ACTION) { + /* XXX: This assumes that actions are assigned to the active object in this mode */ + if (ob) { + if ((ob->adt == NULL) || (ob->adt->flag & ADT_NLA_EDIT_ON) == 0) return true; } - else if (saction->mode == SACTCONT_SHAPEKEY) { - Key *key = BKE_key_from_object(ob); - if (key) + } + else if (saction->mode == SACTCONT_SHAPEKEY) { + Key *key = BKE_key_from_object(ob); + if (key) { + if ((key->adt == NULL) || (key->adt->flag & ADT_NLA_EDIT_ON) == 0) return true; } } - else if (ED_operator_nla_active(C)) { + } + else if (ED_operator_nla_active(C)) { + if (!(scene->flag & SCE_NLA_EDIT_ON)) { return true; } } @@ -297,21 +301,16 @@ static int action_pushdown_poll(bContext *C) { if (ED_operator_action_active(C)) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - Scene *scene = CTX_data_scene(C); - Object *ob = CTX_data_active_object(C); + AnimData *adt = actedit_animdata_from_context(C); - /* Check for actions and that tweakmode is off */ - if ((saction->action) && !(scene->flag & SCE_NLA_EDIT_ON)) { - /* For now, actions are only for the active object, and on object and shapekey levels... */ - if (saction->mode == SACTCONT_ACTION) { - return (ob->adt != NULL); - } - else if (saction->mode == SACTCONT_SHAPEKEY) { - Key *key = BKE_key_from_object(ob); - - return (key && key->adt); - } - } + /* Check for AnimData, Actions, and that tweakmode is off */ + if (adt && saction->action) { + /* NOTE: We check this for the AnimData block in question and not the global flag, + * as the global flag may be left dirty by some of the browsing ops here. + */ + if (!(adt->flag & ADT_NLA_EDIT_ON)) + return true; + } } /* something failed... */ @@ -432,14 +431,26 @@ void ACTION_OT_stash(wmOperatorType *ot) static int action_stash_create_poll(bContext *C) { if (ED_operator_action_active(C)) { - SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - Scene *scene = CTX_data_scene(C); + AnimData *adt = actedit_animdata_from_context(C); /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */ /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */ - if (!(scene->flag & SCE_NLA_EDIT_ON)) { - /* For now, actions are only for the active object, and on object and shapekey levels... */ - return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY); + if (adt) { + if (!(adt->flag & ADT_NLA_EDIT_ON)) + return true; + } + else { + /* There may not be any action/animdata yet, so, just fallback to the global setting + * (which may not be totally valid yet if the action editor was used and things are + * now in an inconsistent state) + */ + SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); + Scene *scene = CTX_data_scene(C); + + if (!(scene->flag & SCE_NLA_EDIT_ON)) { + /* For now, actions are only for the active object, and on object and shapekey levels... */ + return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY); + } } } -- cgit v1.2.3 From 6ef7e0a194b4eac66d110b601a807dd5bf4921ab Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 4 Apr 2015 01:12:32 +1300 Subject: Bugfix: Stashed actions now get added to the bottom of the NLA Stack if there weren't any stashed actions already --- source/blender/blenkernel/intern/nla.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 9a04312aaab..c87f378d5ae 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1584,6 +1584,12 @@ bool BKE_nla_action_stash(AnimData *adt) nlt = add_nlatrack(adt, prev_track); BLI_assert(nlt != NULL); + /* we need to ensure that if there wasn't any previous instance, it must go to tbe bottom of the stack */ + if (prev_track == NULL) { + BLI_remlink(&adt->nla_tracks, nlt); + BLI_addhead(&adt->nla_tracks, nlt); + } + BLI_strncpy(nlt->name, STASH_TRACK_NAME, sizeof(nlt->name)); BLI_uniquename(&adt->nla_tracks, nlt, STASH_TRACK_NAME, '.', offsetof(NlaTrack, name), sizeof(nlt->name)); -- cgit v1.2.3 From 03f2e5d4a6fce84e81b52b1d46ab1d5e305057d0 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 4 Apr 2015 01:38:56 +1300 Subject: Fix: Drawing glitch when renaming animation channels When renaming animation channels, the old names are no longer drawn behind the text boxes anymore. This used to cause problems if the names were long, or if text boxes were set to have transparent backgrounds. Thanks to kopias for reporting on IRC. --- .../editors/animation/anim_channels_defines.c | 70 +++++++++++++--------- source/blender/editors/include/ED_anim_api.h | 2 +- source/blender/editors/space_action/action_draw.c | 5 +- source/blender/editors/space_graph/graph_draw.c | 5 +- source/blender/editors/space_nla/nla_draw.c | 5 +- 5 files changed, 54 insertions(+), 33 deletions(-) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index d71cba86f8d..18ac5b0d0c4 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -3576,8 +3576,24 @@ void ANIM_channel_setting_set(bAnimContext *ac, bAnimListElem *ale, eAnimChannel // width of rename textboxes #define RENAME_TEXT_WIDTH (5 * U.widget_unit) + +/* Helper - Check if a channel needs renaming */ +static bool achannel_is_being_renamed(const bAnimContext *ac, const bAnimChannelType *acf, size_t channel_index) +{ + if (acf->name_prop && ac->ads) { + /* if rename index matches, this channel is being renamed */ + if (ac->ads->renameIndex == channel_index + 1) { + return true; + } + } + + /* not being renamed */ + return false; +} + + /* Draw the given channel */ -void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) +void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc, size_t channel_index) { const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); View2D *v2d = &ac->ar->v2d; @@ -3664,8 +3680,8 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float } /* step 5) draw name ............................................... */ - /* TODO: when renaming, we might not want to draw this, especially if name happens to be longer than channel */ - if (acf->name) { + /* Don't draw this if renaming... */ + if (acf->name && !achannel_is_being_renamed(ac, acf, channel_index)) { const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */ @@ -4175,36 +4191,32 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle } /* step 4) draw text - check if renaming widget is in use... */ - if (acf->name_prop && ac->ads) { - float channel_height = ymaxc - yminc; + if (achannel_is_being_renamed(ac, acf, channel_index)) { + PointerRNA ptr = {{NULL}}; + PropertyRNA *prop = NULL; - /* if rename index matches, add widget for this */ - if (ac->ads->renameIndex == channel_index + 1) { - PointerRNA ptr = {{NULL}}; - PropertyRNA *prop = NULL; + /* draw renaming widget if we can get RNA pointer for it + * NOTE: property may only be available in some cases, even if we have + * a callback available (e.g. broken F-Curve rename) + */ + if (acf->name_prop(ale, &ptr, &prop)) { + const float channel_height = ymaxc - yminc; + uiBut *but; - /* draw renaming widget if we can get RNA pointer for it - * NOTE: property may only be available in some cases, even if we have - * a callback available (e.g. broken F-Curve rename) - */ - if (acf->name_prop(ale, &ptr, &prop)) { - uiBut *but; - - UI_block_emboss_set(block, UI_EMBOSS); - - but = uiDefButR(block, UI_BTYPE_TEXT, 1, "", offset + 3, yminc, RENAME_TEXT_WIDTH, channel_height, - &ptr, RNA_property_identifier(prop), -1, 0, 0, -1, -1, NULL); - - /* copy what outliner does here, see outliner_buttons */ - if (UI_but_active_only(C, ac->ar, block, but) == false) { - ac->ads->renameIndex = 0; - - /* send notifiers */ - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, NULL); - } + UI_block_emboss_set(block, UI_EMBOSS); + + but = uiDefButR(block, UI_BTYPE_TEXT, 1, "", offset + 3, yminc, RENAME_TEXT_WIDTH, channel_height, + &ptr, RNA_property_identifier(prop), -1, 0, 0, -1, -1, NULL); + + /* copy what outliner does here, see outliner_buttons */ + if (UI_but_active_only(C, ac->ar, block, but) == false) { + ac->ads->renameIndex = 0; - UI_block_emboss_set(block, UI_EMBOSS_NONE); + /* send notifiers */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, NULL); } + + UI_block_emboss_set(block, UI_EMBOSS_NONE); } } diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 7fd0d35d514..4c7c78df349 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -462,7 +462,7 @@ const bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale); void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level); /* Draw the given channel */ -void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc); +void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc, size_t channel_index); /* Draw the widgets for the given channel */ void ANIM_channel_draw_widgets(const struct bContext *C, bAnimContext *ac, bAnimListElem *ale, struct uiBlock *block, float yminc, float ymaxc, size_t channel_index); diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index cc30639332a..10748c2fe15 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -93,6 +93,8 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar) /* loop through channels, and set up drawing depending on their type */ { /* first pass: just the standard GL-drawing for backdrop + text */ + size_t channel_index = 0; + y = (float)ACHANNEL_FIRST; for (ale = anim_data.first; ale; ale = ale->next) { @@ -104,11 +106,12 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar) IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) { /* draw all channels using standard channel-drawing API */ - ANIM_channel_draw(ac, ale, yminc, ymaxc); + ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index); } /* adjust y-position for next one */ y -= ACHANNEL_STEP; + channel_index++; } } { /* second pass: widgets */ diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index a5c04ce2cb4..0313ce4b1d4 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -1137,6 +1137,8 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar) /* loop through channels, and set up drawing depending on their type */ { /* first pass: just the standard GL-drawing for backdrop + text */ + size_t channel_index = 0; + y = (float)ACHANNEL_FIRST; for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) { @@ -1148,11 +1150,12 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar) IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) { /* draw all channels using standard channel-drawing API */ - ANIM_channel_draw(ac, ale, yminc, ymaxc); + ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index); } /* adjust y-position for next one */ y -= ACHANNEL_STEP; + channel_index++; } } { /* second pass: widgets */ diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index aae0e38696c..5d9a77c8576 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -650,6 +650,8 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar) /* draw channels */ { /* first pass: just the standard GL-drawing for backdrop + text */ + size_t channel_index = 0; + y = (float)(-NLACHANNEL_HEIGHT(snla)); for (ale = anim_data.first; ale; ale = ale->next) { @@ -661,11 +663,12 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar) IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) { /* draw all channels using standard channel-drawing API */ - ANIM_channel_draw(ac, ale, yminc, ymaxc); + ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index); } /* adjust y-position for next one */ y -= NLACHANNEL_STEP(snla); + channel_index++; } } { /* second pass: UI widgets */ -- cgit v1.2.3 From 3f30ebf64aee964362874aaf985b092b8bc3de8e Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 3 Apr 2015 15:49:52 +0200 Subject: Fix related to T44243: do not systematically do live-update when tab-completing textedit buttons. We now have a specific flag for that, use it! Note that for all 'search menu' buttons, there is already a similar behavior, so there is no need to force apply butt in this case anyway, which means in practice this change only has effect in the single place it is needed currently - file browser dir/file fields. In this case (dir field), applying button even on partial matches leads code to ask to create a new dir, which breaks completely the expected behavior of completion. And we do not need immediate apply at all here. Note this is the only 'autocomplete' button not using search menu, so this change does not affect anything else in UI. --- source/blender/editors/interface/interface_handlers.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index b4f26998c77..bc35fde633c 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -2864,8 +2864,6 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle if (autocomplete == AUTOCOMPLETE_FULL_MATCH) button_activate_state(C, but, BUTTON_STATE_EXIT); - - update = true; /* do live update for tab key */ } /* the hotkey here is not well defined, was G.qual so we check all */ else if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) { @@ -2944,7 +2942,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle #endif if (changed) { - /* only update when typing for TAB key */ + /* only do live update when but flag request it (UI_BUT_TEXTEDIT_UPDATE). */ if (update && data->interactive) { ui_apply_but(C, block, but, data, true); } -- cgit v1.2.3 From b444887054297d83c560e860219a5c598d390935 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 3 Apr 2015 16:17:17 +0200 Subject: Fix T44243: File browser behavior is inconsistent between append and open. Only basic fix, the whole 'dir' field handling needs rework to correctly support lib stuff (will be done as part of asset-experiment rewriting work)... All this code is doing way too much filesystem inspection by itself, instead of reusing flielist.c work - this is stupid, and will completely break with future asset engines! --- source/blender/editors/space_file/filesel.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 14b72eb8f6d..6858f536e92 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -642,8 +642,8 @@ int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matche */ for (i = 0; i < n; i++) { file = filelist_file(sfile->files, i); - /* use same rule as 'FileCheckType.CHECK_FILES' */ - if (S_ISREG(file->type) && (fnmatch(pattern, file->relname, 0) == 0)) { + /* Do not check wether file is a file or dir here! Causes T44243 (we do accept dirs at this stage). */ + if (fnmatch(pattern, file->relname, 0) == 0) { file->selflag |= FILE_SEL_SELECTED; if (!match) { BLI_strncpy(matched_file, file->relname, FILE_MAX); @@ -694,13 +694,8 @@ int autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v)) closedir(dir); match = UI_autocomplete_end(autocpl, str); - if (match) { - if (match == AUTOCOMPLETE_FULL_MATCH) { - BLI_add_slash(str); - } - else { - BLI_strncpy(sfile->params->dir, str, sizeof(sfile->params->dir)); - } + if (match == AUTOCOMPLETE_FULL_MATCH) { + BLI_add_slash(str); } } } -- cgit v1.2.3 From 53a3850a8a05249942a0c4a16060e9491456af02 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 3 Apr 2015 16:21:22 +0200 Subject: Sticky Keys backend Design task: T42339 Differential Revision: D840 Initial implementation proposal: T41867 Short description: With this we can distinguish between holding and tabbing a key. Useful is this if we want to assign to operators to a single shortcut. If two operators are assigned to one shortcut, we call this a sticky key. More info is accessible through the design task and the diff. A few people that were involved with this: * Sean Olson for stressing me with this burden ;) - It is his enthusiasm that pushed me forward to get this done * Campbell and Antony for the code and design review * Ton for the design review * All the other people that gave feedback on the patch and helped to make this possible A big "Thank You" for you all! --- release/scripts/startup/bl_ui/space_userpref.py | 13 +- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/editors/armature/armature_ops.c | 2 +- source/blender/editors/curve/curve_ops.c | 2 +- source/blender/editors/gpencil/gpencil_paint.c | 2 +- .../editors/interface/interface_eyedropper.c | 4 + .../blender/editors/interface/interface_handlers.c | 67 ++++++----- source/blender/editors/interface/interface_panel.c | 2 +- .../blender/editors/interface/interface_regions.c | 4 +- source/blender/editors/interface/resources.c | 7 +- source/blender/editors/mesh/mesh_ops.c | 2 +- source/blender/editors/object/object_ops.c | 2 +- source/blender/editors/space_console/console_ops.c | 6 +- source/blender/editors/space_file/space_file.c | 16 +-- source/blender/editors/space_graph/graph_ops.c | 2 +- .../editors/space_node/node_relationships.c | 13 +- .../blender/editors/space_outliner/outliner_ops.c | 8 +- source/blender/editors/space_text/text_ops.c | 11 +- source/blender/editors/space_view3d/view3d_ops.c | 2 +- source/blender/makesdna/DNA_userdef_types.h | 7 +- source/blender/makesdna/DNA_windowmanager_types.h | 3 +- source/blender/makesrna/intern/rna_userdef.c | 8 +- source/blender/makesrna/intern/rna_wm.c | 2 + source/blender/windowmanager/WM_types.h | 17 +-- .../blender/windowmanager/intern/wm_event_system.c | 134 +++++++++------------ source/blender/windowmanager/intern/wm_keymap.c | 4 + source/blender/windowmanager/intern/wm_operators.c | 2 +- source/blender/windowmanager/intern/wm_window.c | 76 +++++++++++- 28 files changed, 267 insertions(+), 153 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 3b17e40c294..04020d0a1bb 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -1055,6 +1055,15 @@ class USERPREF_PT_input(Panel): subrow.menu("USERPREF_MT_interaction_presets", text=bpy.types.USERPREF_MT_interaction_presets.bl_label) subrow.operator("wm.interaction_preset_add", text="", icon='ZOOMIN') subrow.operator("wm.interaction_preset_add", text="", icon='ZOOMOUT').remove_active = True + + sub.separator() + + sub = col.column() + sub.label(text="Double Click:") + sub.prop(inputs, "double_click_time", text="Speed") + sub.label(text="Sticky Keys:") + sub.prop(inputs, "click_timeout") + sub.separator() sub.label(text="Mouse:") @@ -1068,10 +1077,6 @@ class USERPREF_PT_input(Panel): sub.label(text="Select With:") sub.row().prop(inputs, "select_mouse", expand=True) - sub = col.column() - sub.label(text="Double Click:") - sub.prop(inputs, "mouse_double_click_time", text="Speed") - sub.separator() sub.prop(inputs, "use_emulate_numpad") diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index e4d3fe4868b..a790715ac98 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 274 -#define BLENDER_SUBVERSION 2 +#define BLENDER_SUBVERSION 3 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 5 diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index 61c9dfb24fa..3f00068c3d2 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -271,7 +271,7 @@ void ED_keymap_armature(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "ARMATURE_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_extrude_move", EKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_extrude_forked", EKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "ARMATURE_OT_click_extrude", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); + WM_keymap_add_item(keymap, "ARMATURE_OT_click_extrude", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_fill", FKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_merge", MKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_split", YKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c index 4bcb16d31ef..561c349edec 100644 --- a/source/blender/editors/curve/curve_ops.c +++ b/source/blender/editors/curve/curve_ops.c @@ -230,7 +230,7 @@ void ED_keymap_curve(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "CURVE_OT_handle_type_set", VKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "CURVE_OT_vertex_add", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); + WM_keymap_add_item(keymap, "CURVE_OT_vertex_add", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0); kmi = WM_keymap_add_item(keymap, "CURVE_OT_select_all", AKEY, KM_PRESS, 0, 0); RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE); diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index c8774cb73a1..a299e23830d 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1930,7 +1930,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* stroke could be smoothed, send notifier to refresh screen */ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); } - else { + else if (event->val == KM_RELEASE) { /* printf("\t\tGP - end of stroke + op\n"); */ p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index f5847a9d701..96f9b87611f 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -277,6 +277,10 @@ static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event) eyedropper_cancel(C, op); return OPERATOR_CANCELLED; case LEFTMOUSE: + /* two release events are sent on KM_CLICK, so ignore second one */ + if (event->click_type == KM_CLICK) { + break; + } if (event->val == KM_RELEASE) { if (eye->accum_tot == 0) { eyedropper_color_sample(C, eye, event->x, event->y); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index bc35fde633c..163502b4230 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1180,7 +1180,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void switch (event->type) { case LEFTMOUSE: { - if (event->val != KM_PRESS) { + if (event->val == KM_RELEASE) { done = true; } break; @@ -2721,8 +2721,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle if (data->searchbox) inbox = ui_searchbox_inside(data->searchbox, event->x, event->y); - /* for double click: we do a press again for when you first click on button (selects all text, no cursor pos) */ - if (event->val == KM_PRESS || event->val == KM_DBL_CLICK) { + if (event->val == KM_PRESS) { float mx, my; mx = event->x; @@ -2747,7 +2746,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle } /* only select a word in button if there was no selection before */ - if (event->val == KM_DBL_CLICK && had_selection == false) { + if ((event->click_type == KM_DBL_CLICK) && (had_selection == false)) { ui_textedit_move(but, data, STRCUR_DIR_PREV, false, STRCUR_JUMP_DELIM); ui_textedit_move(but, data, STRCUR_DIR_NEXT, true, STRCUR_JUMP_DELIM); retval = WM_UI_HANDLER_BREAK; @@ -3171,7 +3170,7 @@ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, cons } } else if (data->state == BUTTON_STATE_WAIT_RELEASE) { - if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { if (!(but->flag & UI_SELECT)) data->cancel = true; button_activate_state(C, but, BUTTON_STATE_EXIT); @@ -3739,7 +3738,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton button_activate_state(C, but, BUTTON_STATE_EXIT); } } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { if (data->dragchange) { #ifdef USE_DRAG_MULTINUM /* if we started multibutton but didnt drag, then edit */ @@ -4036,7 +4035,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton button_activate_state(C, but, BUTTON_STATE_EXIT); } } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { if (data->dragchange) { #ifdef USE_DRAG_MULTINUM /* if we started multibutton but didnt drag, then edit */ @@ -4181,7 +4180,7 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut button_activate_state(C, but, BUTTON_STATE_EXIT); } } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->type == MOUSEMOVE) { @@ -4229,7 +4228,7 @@ static int ui_do_but_GRIP(bContext *C, uiBlock *block, uiBut *but, uiHandleButto button_activate_state(C, but, BUTTON_STATE_EXIT); } } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->type == MOUSEMOVE) { @@ -4253,7 +4252,7 @@ static int ui_do_but_LISTROW(bContext *C, uiBut *but, uiHandleButtonData *data, * editing field for editing list item names */ if ((ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS && event->ctrl) || - (event->type == LEFTMOUSE && event->val == KM_DBL_CLICK)) + (event->type == LEFTMOUSE && event->click_type == KM_DBL_CLICK)) { uiBut *labelbut = ui_but_list_row_text_activate(C, but, data, event, BUTTON_ACTIVATE_TEXT_EDITING); if (labelbut) { @@ -4605,7 +4604,7 @@ static int ui_do_but_UNITVEC(bContext *C, uiBlock *block, uiBut *but, uiHandleBu ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { button_activate_state(C, but, BUTTON_STATE_EXIT); } @@ -4926,7 +4925,7 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { button_activate_state(C, but, BUTTON_STATE_EXIT); } @@ -5199,7 +5198,7 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle } } } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { button_activate_state(C, but, BUTTON_STATE_EXIT); } return WM_UI_HANDLER_BREAK; @@ -5284,7 +5283,7 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { button_activate_state(C, but, BUTTON_STATE_EXIT); } @@ -5523,7 +5522,7 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { if (data->dragsel != -1) { CurveMapping *cumap = (CurveMapping *)but->poin; CurveMap *cuma = cumap->cm + cumap->cur; @@ -5619,7 +5618,7 @@ static int ui_do_but_HISTOGRAM(bContext *C, uiBlock *block, uiBut *but, uiHandle ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { button_activate_state(C, but, BUTTON_STATE_EXIT); } return WM_UI_HANDLER_BREAK; @@ -5692,7 +5691,7 @@ static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleB ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { button_activate_state(C, but, BUTTON_STATE_EXIT); } return WM_UI_HANDLER_BREAK; @@ -5717,7 +5716,7 @@ static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, con } else if (data->state == BUTTON_STATE_WAIT_RELEASE) { - if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { if (!(but->flag & UI_SELECT)) data->cancel = true; button_activate_state(C, but, BUTTON_STATE_EXIT); @@ -5800,7 +5799,7 @@ static int ui_do_but_TRACKPREVIEW(bContext *C, uiBlock *block, uiBut *but, uiHan ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { button_activate_state(C, but, BUTTON_STATE_EXIT); } return WM_UI_HANDLER_BREAK; @@ -8316,7 +8315,7 @@ static int ui_handle_menu_event( #ifdef USE_DRAG_POPUP if (menu->is_grab) { - if (event->type == LEFTMOUSE) { + if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { menu->is_grab = false; retval = WM_UI_HANDLER_BREAK; } @@ -8601,7 +8600,7 @@ static int ui_handle_menu_event( uiSafetyRct *saferct = block->saferct.first; if (ELEM(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) && - ELEM(event->val, KM_PRESS, KM_DBL_CLICK)) + (event->val == KM_PRESS || event->click_type == KM_DBL_CLICK)) { if ((is_parent_menu == false) && (U.uiflag & USER_MENUOPENAUTO) == 0) { /* for root menus, allow clicking to close */ @@ -8978,6 +8977,11 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle switch (event->type) { case MOUSEMOVE: + /* verify we have a real mousemove */ + if (event->x == event->prevx && event->y == event->prevy) { + break; + } + if (!is_click_style) { float len_sq = len_squared_v2v2(event_xy, block->pie_data.pie_center_init); @@ -9004,7 +9008,9 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle case LEFTMOUSE: if (is_click_style) { - if (block->pie_data.flags & UI_PIE_INVALID_DIR) { + /* the click_type test sends a second event on KM_CLICK that + * may destroy nested pies even before they are drawn */ + if ((block->pie_data.flags & UI_PIE_INVALID_DIR) && (event->click_type != KM_CLICK)) { menu->menuretval = UI_RETURN_CANCEL; } else { @@ -9045,9 +9051,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle case YKEY: case ZKEY: { - if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) && - !IS_EVENT_MOD(event, shift, ctrl, oskey)) - { + if ((event->val == KM_PRESS) && !IS_EVENT_MOD(event, shift, ctrl, oskey)) { for (but = block->buttons.first; but; but = but->next) { if (but->menu_key == event->type) { ui_but_pie_button_activate(C, but, menu); @@ -9154,8 +9158,9 @@ static int ui_handle_menus_recursive( if (block->flag & UI_BLOCK_RADIAL) retval = ui_pie_handler(C, event, menu); - else if (event->type == LEFTMOUSE || event->val != KM_DBL_CLICK) + else if ((event->type == LEFTMOUSE) || (event->click_type != KM_DBL_CLICK)) { retval = ui_handle_menu_event(C, event, menu, level, is_parent_inside, is_parent_menu, is_floating); + } } } @@ -9191,10 +9196,16 @@ static int ui_region_handler(bContext *C, const wmEvent *event, void *UNUSED(use retval = ui_handle_list_event(C, event, ar); if (retval == WM_UI_HANDLER_CONTINUE) { - if (but) + if (but) { retval = ui_handle_button_event(C, event, but); - else + } + else { retval = ui_handle_button_over(C, event, ar); + + /* let's make sure we are really not hovering a button by adding a mousemove! + * XXX some WM_event_add_mousemove calls may become unnecessary with this and can be removed */ + WM_event_add_mousemove(C); + } } /* re-enable tooltips */ diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index d165e2719c5..7d6d5c3a6d7 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -1865,7 +1865,7 @@ static int ui_handler_panel(bContext *C, const wmEvent *event, void *userdata) uiHandlePanelData *data = panel->activedata; /* verify if we can stop */ - if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); int align = panel_aligned(sa, ar); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 7cb9dca78bf..0fbd0c40510 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -2749,8 +2749,8 @@ uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, co pie->block_radial->puphash = ui_popup_menu_hash(title); pie->block_radial->flag |= UI_BLOCK_RADIAL; - /* if pie is spawned by a left click, it is always assumed to be click style */ - if (event->type == LEFTMOUSE) { + /* if pie is spawned by a left click or on release, it is always assumed to be click style */ + if ((event->type == LEFTMOUSE) || (event->val == KM_RELEASE)) { pie->block_radial->pie_data.flags |= UI_PIE_CLICK_STYLE; pie->block_radial->pie_data.event = EVENT_NONE; win->lock_pie_event = EVENT_NONE; diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 15e742c930a..b7545199f56 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -2602,7 +2602,12 @@ void init_userdef_do_versions(void) cp[3] = 255; } } - + + if (U.versionfile < 274 || (U.versionfile == 274 && U.subversionfile < 3)) { + if (U.click_timeout == 0) + U.click_timeout = 250; + } + if (U.pixelsize == 0.0f) U.pixelsize = 1.0f; diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 2855af063c0..126d1cb0ad9 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -409,7 +409,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) /* use KM_CLICK because same key is used for tweaks */ kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "rotate_source", true); - kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_SHIFT | KM_CTRL, 0); + kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_PRESS, KM_SHIFT | KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "rotate_source", false); WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_delete", XKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 422f0c12e51..cf717cc48ca 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -295,7 +295,7 @@ void ED_keymap_object(wmKeyConfig *keyconf) keymap = WM_keymap_find(keyconf, "Object Non-modal", 0, 0); /* Note: this keymap works disregarding mode */ - kmi = WM_keymap_add_item(keymap, "OBJECT_OT_mode_set", TABKEY, KM_PRESS, 0, 0); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_mode_set", TABKEY, KM_CLICK, 0, 0); RNA_enum_set(kmi->ptr, "mode", OB_MODE_EDIT); RNA_boolean_set(kmi->ptr, "toggle", true); diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index 92731c2f135..b3f5e81f154 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -1140,8 +1140,10 @@ static int console_modal_select(bContext *C, wmOperator *op, const wmEvent *even case LEFTMOUSE: case MIDDLEMOUSE: case RIGHTMOUSE: - console_cursor_set_exit(C, op); - return OPERATOR_FINISHED; + if (event->val == KM_RELEASE) { + console_cursor_set_exit(C, op); + return OPERATOR_FINISHED; + } case MOUSEMOVE: console_modal_select_apply(C, op, event); break; diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 782b318b8a2..557a495cb8f 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -444,27 +444,27 @@ static void file_keymap(struct wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "need_active", true); /* left mouse selects and opens */ - WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, 0, 0); - kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_PRESS, 0, 0); + kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", true); - kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_CTRL | KM_SHIFT, 0); + kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", true); RNA_boolean_set(kmi->ptr, "fill", true); /* right mouse selects without opening */ - kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_CLICK, 0, 0); + kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "open", false); - kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_CLICK, KM_SHIFT, 0); + kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", true); RNA_boolean_set(kmi->ptr, "open", false); - kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_CLICK, KM_ALT, 0); + kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "extend", true); RNA_boolean_set(kmi->ptr, "fill", true); RNA_boolean_set(kmi->ptr, "open", false); /* front and back mouse folder navigation */ - WM_keymap_add_item(keymap, "FILE_OT_previous", BUTTON4MOUSE, KM_CLICK, 0, 0); - WM_keymap_add_item(keymap, "FILE_OT_next", BUTTON5MOUSE, KM_CLICK, 0, 0); + WM_keymap_add_item(keymap, "FILE_OT_previous", BUTTON4MOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "FILE_OT_next", BUTTON5MOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "FILE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "FILE_OT_refresh", PADPERIOD, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 33e8b522335..e266a5089c8 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -574,7 +574,7 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* insertkey */ WM_keymap_add_item(keymap, "GRAPH_OT_keyframe_insert", IKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "GRAPH_OT_click_insert", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_click_insert", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0); /* copy/paste */ WM_keymap_add_item(keymap, "GRAPH_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index c8951a1172e..f72def8377f 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -633,11 +633,14 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) case RIGHTMOUSE: case MIDDLEMOUSE: { - node_link_exit(C, op, true); - - ED_area_headerprint(CTX_wm_area(C), NULL); - ED_region_tag_redraw(ar); - return OPERATOR_FINISHED; + if (event->val != KM_NOTHING) { + node_link_exit(C, op, true); + + ED_area_headerprint(CTX_wm_area(C), NULL); + ED_region_tag_redraw(ar); + return OPERATOR_FINISHED; + } + break; } } diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index f5869575cc6..93116dbe22c 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -91,19 +91,19 @@ void outliner_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "OUTLINER_OT_item_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0); - kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, 0, 0); + kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "recursive", false); RNA_boolean_set(kmi->ptr, "extend", false); - kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, KM_SHIFT, 0); + kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "recursive", false); RNA_boolean_set(kmi->ptr, "extend", true); - kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, KM_CTRL, 0); + kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "recursive", true); RNA_boolean_set(kmi->ptr, "extend", false); - kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, KM_CTRL | KM_SHIFT, 0); + kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "recursive", true); RNA_boolean_set(kmi->ptr, "extend", true); diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index ad8050a50e8..6fb5706bfdf 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -2163,6 +2163,11 @@ static int text_scroll_modal(bContext *C, wmOperator *op, const wmEvent *event) case LEFTMOUSE: case RIGHTMOUSE: case MIDDLEMOUSE: + /* don't exit on dummy events */ + if (event->val == KM_NOTHING) { + return OPERATOR_RUNNING_MODAL; + } + if (ELEM(tsc->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) { txt_screen_skip(st, ar, st->viewlines * (tsc->zone == SCROLLHANDLE_MIN_OUTSIDE ? 1 : -1)); @@ -2667,8 +2672,10 @@ static int text_set_selection_modal(bContext *C, wmOperator *op, const wmEvent * case LEFTMOUSE: case MIDDLEMOUSE: case RIGHTMOUSE: - text_cursor_set_exit(C, op); - return OPERATOR_FINISHED; + if (event->val != KM_NOTHING) { + text_cursor_set_exit(C, op); + return OPERATOR_FINISHED; + } case TIMER: case MOUSEMOVE: text_cursor_set_apply(C, op, event); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 8c668b2b8e0..c5425f238cc 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -386,7 +386,7 @@ void view3d_keymap(wmKeyConfig *keyconf) /* drawtype */ - kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", ZKEY, KM_PRESS, 0, 0); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", ZKEY, KM_CLICK, 0, 0); RNA_string_set(kmi->ptr, "data_path", "space_data.viewport_shade"); RNA_string_set(kmi->ptr, "value_1", "SOLID"); RNA_string_set(kmi->ptr, "value_2", "WIREFRAME"); diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index afa1f03a8ca..348e895e0a9 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -447,7 +447,9 @@ typedef struct UserDef { short versions; short dbl_click_time; - + short click_timeout; + short pad3; + short gameflags; short wheellinescroll; int uiflag, uiflag2; @@ -465,7 +467,8 @@ typedef struct UserDef { char pad2[2]; short transopts; short menuthreshold1, menuthreshold2; - + int pad4; + struct ListBase themes; struct ListBase uifonts; struct ListBase uistyles; diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 919cdb7ea2f..ebbafb19aa5 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -249,7 +249,8 @@ typedef struct wmKeyMapItem { /* event */ short type; /* event code itself */ - short val; /* KM_ANY, KM_PRESS, KM_NOTHING etc */ + short val; /* NOTE: other than event->val this can be the value itself + * (KM_ANY, KM_PRESS, etc) AND the clicktype (KM_DBL_CLICK, KM_HOLD, etc) */ short shift, ctrl, alt, oskey; /* oskey is apple or windowskey, value denotes order of pressed */ short keymodifier; /* rawkey modifier */ diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 15a4ef5eaf6..fc6d28e67c2 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -4324,12 +4324,16 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_FLY_HELICOPTER); RNA_def_property_ui_text(prop, "Helicopter Mode", "Device up/down directly controls your Z position"); - - prop = RNA_def_property(srna, "mouse_double_click_time", PROP_INT, PROP_NONE); + prop = RNA_def_property(srna, "double_click_time", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "dbl_click_time"); RNA_def_property_range(prop, 1, 1000); RNA_def_property_ui_text(prop, "Double Click Timeout", "Time/delay (in ms) for a double click"); + prop = RNA_def_property(srna, "click_timeout", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "click_timeout"); + RNA_def_property_range(prop, 0, 10000); + RNA_def_property_ui_text(prop, "Click Timeout", "Time (in ms) to determine if a key is clicked or held"); + prop = RNA_def_property(srna, "use_mouse_emulate_3_button", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_TWOBUTTONMOUSE); RNA_def_property_ui_text(prop, "Emulate 3 Button Mouse", diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 6119bc968e6..64ecf61f774 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -49,6 +49,7 @@ static EnumPropertyItem event_keymouse_value_items[] = { {KM_PRESS, "PRESS", 0, "Press", ""}, {KM_RELEASE, "RELEASE", 0, "Release", ""}, {KM_CLICK, "CLICK", 0, "Click", ""}, + {KM_HOLD, "HOLD", 0, "Hold", ""}, {KM_DBL_CLICK, "DOUBLE_CLICK", 0, "Double Click", ""}, {0, NULL, 0, NULL, NULL} }; @@ -380,6 +381,7 @@ EnumPropertyItem event_value_items[] = { {KM_PRESS, "PRESS", 0, "Press", ""}, {KM_RELEASE, "RELEASE", 0, "Release", ""}, {KM_CLICK, "CLICK", 0, "Click", ""}, + {KM_HOLD, "HOLD", 0, "Hold", ""}, {KM_DBL_CLICK, "DOUBLE_CLICK", 0, "Double Click", ""}, {EVT_GESTURE_N, "NORTH", 0, "North", ""}, {EVT_GESTURE_NE, "NORTH_EAST", 0, "North-East", ""}, diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index e716cd6b779..366d3218176 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -180,9 +180,11 @@ enum { #define KM_NOTHING 0 #define KM_PRESS 1 #define KM_RELEASE 2 -#define KM_CLICK 3 -#define KM_DBL_CLICK 4 +/* clicktype */ +#define KM_CLICK 3 /* clicked key (click_time <= U.click_timeout) */ +#define KM_DBL_CLICK 4 /* double click - keep at 4 to avoid breakage with older key configs */ +#define KM_HOLD 5 /* held key (click_time > U.click_timeout) */ /* ************** UI Handler ***************** */ @@ -427,7 +429,9 @@ typedef struct wmEvent { short type; /* event code itself (short, is also in keymap) */ short val; /* press, release, scrollvalue */ + short click_type; /* click, hold or double click */ int x, y; /* mouse pointer position, screen coord */ + double click_time; /* the time since keypress started */ int mval[2]; /* region mouse position, name convention pre 2.5 :) */ char utf8_buf[6]; /* from, ghost if utf8 is enabled for the platform, * BLI_str_utf8_size() must _always_ be valid, check @@ -435,20 +439,19 @@ typedef struct wmEvent { char ascii; /* from ghost, fallback if utf8 isn't set */ char pad; - /* previous state, used for double click and the 'click' */ + bool is_key_pressed; /* is a (non-modifier) key is pressed? (keyboard, mouse, NDOF, ...) */ + + /* previous state, used for clicktype */ short prevtype; short prevval; int prevx, prevy; - double prevclicktime; + double prevclick_time; int prevclickx, prevclicky; /* modifier states */ short shift, ctrl, alt, oskey; /* oskey is apple or windowskey, value denotes order of pressed */ short keymodifier; /* rawkey modifier */ - /* set in case a KM_PRESS went by unhandled */ - short check_click; - /* keymap item, set by handler (weak?) */ const char *keymap_idname; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index e8004297011..ce9a729a7a9 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -404,7 +404,7 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve * to make the DBL_CLICK conversion work, we just don't send this to UI, except mouse clicks */ if (((handler->flag & WM_HANDLER_ACCEPT_DBL_CLICK) == 0) && (event->type != LEFTMOUSE) && - (event->val == KM_DBL_CLICK)) + (event->click_type == KM_DBL_CLICK)) { return WM_HANDLER_CONTINUE; } @@ -1442,6 +1442,7 @@ int WM_userdef_event_map(int kmitype) } +/* XXX rename to something more descriptive like wm_event_is_keymapitem_matching and use bool */ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) { int kmitype = WM_userdef_event_map(kmi->type); @@ -1458,10 +1459,13 @@ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) if (kmitype != KM_ANY) if (winevent->type != kmitype) return 0; - + + /* KM_ANY excludes click_type events - filter them out */ + if (kmi->val == KM_ANY && winevent->click_type) return 0; + if (kmi->val != KM_ANY) - if (winevent->val != kmi->val) return 0; - + if (!ELEM(kmi->val, winevent->val, winevent->click_type)) return 0; + /* modifiers also check bits, so it allows modifier order */ if (kmi->shift != KM_ANY) if (winevent->shift != kmi->shift && !(winevent->shift & kmi->shift)) return 0; @@ -1508,8 +1512,9 @@ static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *eve /* modal keymap checking returns handled events fine, but all hardcoded modal * handling typically swallows all events (OPERATOR_RUNNING_MODAL). * This bypass just disables support for double clicks in hardcoded modal handlers */ - if (event->val == KM_DBL_CLICK) { + if (event->click_type == KM_DBL_CLICK) { event->val = KM_PRESS; + event->click_type = 0; *dbl_click_disabled = true; } } @@ -1541,9 +1546,9 @@ static void wm_event_modalmap_end(wmEvent *event, bool dbl_click_disabled) event->val = event->prevval; event->prevval = 0; } - else if (dbl_click_disabled) - event->val = KM_DBL_CLICK; - + else if (dbl_click_disabled) { + event->click_type = KM_DBL_CLICK; + } } /* Warning: this function removes a modal handler, when finished */ @@ -2021,47 +2026,21 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) /* test for CLICK events */ if (wm_action_not_handled(action)) { wmWindow *win = CTX_wm_window(C); - - /* eventstate stores if previous event was a KM_PRESS, in case that - * wasn't handled, the KM_RELEASE will become a KM_CLICK */ - - if (win && event->val == KM_PRESS) { - win->eventstate->check_click = true; - } - - if (win && win->eventstate->prevtype == event->type) { - - if ((event->val == KM_RELEASE) && - (win->eventstate->prevval == KM_PRESS) && - (win->eventstate->check_click == true)) - { - event->val = KM_CLICK; - - if (G.debug & (G_DEBUG_HANDLERS)) { - printf("%s: handling CLICK\n", __func__); - } - - action |= wm_handlers_do_intern(C, event, handlers); - event->val = KM_RELEASE; - } - else if (event->val == KM_DBL_CLICK) { + /* XXX check if those double click hacks can be removed/improved since click_type was introduced */ + if (win && win->eventstate->prevtype == event->type) { + if (event->click_type == KM_DBL_CLICK) { event->val = KM_PRESS; + event->click_type = 0; action |= wm_handlers_do_intern(C, event, handlers); /* revert value if not handled */ if (wm_action_not_handled(action)) { - event->val = KM_DBL_CLICK; + event->click_type = KM_DBL_CLICK; } } } } - else { - wmWindow *win = CTX_wm_window(C); - - if (win) - win->eventstate->check_click = 0; - } } return action; @@ -3005,22 +2984,50 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi return NULL; } -static bool wm_event_is_double_click(wmEvent *event, wmEvent *event_state) +/** + * Clicktype test + * + * We have 3 different click_types: #KM_CLICK, #KM_HOLD# and #KM_DBL_CLICK. + * + * Time is used to determine, what to send. It works as follows: + * - #KM_RELEASE && time since first #KM_PRESS < U.click_timeout --> send #KM_CLICK + * - #KM_PRESS && time since first #KM_PRESS > U.click_timeout --> send #KM_HOLD + * - #KM_PRESS after a #KM_RELEASE && time since previous #KM_PRESS < U.dbl_click_time --> send #KM_DBL_CLICK + * + * \note: only #KM_DBL_CLICK is handled here, rest in #wm_window_event_clicktype_init (wm_window.c) + */ +static void wm_event_clicktype_init(wmWindow *win, wmEvent *event, wmEvent *event_state) { - if ((event->type == event_state->prevtype) && - (event_state->prevval == KM_RELEASE) && - (event->val == KM_PRESS)) + short click_type = 0; + + if ((event->val == KM_PRESS) && + (event_state->prevval != KM_PRESS || event->prevtype != win->eventstate->prevtype)) + { + event_state->prevclick_time = event->click_time; + event_state->prevclickx = event->x; + event_state->prevclicky = event->y; + } + + /* double click */ + if (event->type == event_state->prevtype && + event_state->prevval == KM_RELEASE && + event->val == KM_PRESS) { if ((ISMOUSE(event->type) == false) || ((ABS(event->x - event_state->prevclickx)) <= 2 && (ABS(event->y - event_state->prevclicky)) <= 2)) { - if ((PIL_check_seconds_timer() - event_state->prevclicktime) * 1000 < U.dbl_click_time) { - return true; + if ((PIL_check_seconds_timer() - event_state->prevclick_time) * 1000 < U.dbl_click_time) { + click_type = KM_DBL_CLICK; + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) { + printf("%s Send double click event\n", __func__); + } } } } - return false; + if (click_type != event->click_type) { + event_state->click_type = event->click_type = click_type; + } } static void wm_event_add_mousemove(wmWindow *win, const wmEvent *event) @@ -3152,6 +3159,9 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U evt->val = event.val; evt->type = event.type; + /* click_type */ + wm_event_clicktype_init(win, &event, evt); + if (win->active == 0) { int cx, cy; @@ -3162,18 +3172,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event.y = evt->y = cy; } - /* double click test */ - if (wm_event_is_double_click(&event, evt)) { - if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) - printf("%s Send double click\n", __func__); - event.val = KM_DBL_CLICK; - } - if (event.val == KM_PRESS) { - evt->prevclicktime = PIL_check_seconds_timer(); - evt->prevclickx = event.x; - evt->prevclicky = event.y; - } - /* add to other window if event is there (not to both!) */ owin = wm_event_cursor_other_windows(wm, win, &event); if (owin) { @@ -3212,7 +3210,10 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U /* copy to event state */ evt->val = event.val; evt->type = event.type; - + + /* clicktype */ + wm_event_clicktype_init(win, &event, evt); + /* exclude arrow keys, esc, etc from text input */ if (type == GHOST_kEventKeyUp) { event.ascii = '\0'; @@ -3278,14 +3279,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event.keymodifier = evt->keymodifier = 0; break; } - - /* double click test */ - /* if previous event was same type, and previous was release, and now it presses... */ - if (wm_event_is_double_click(&event, evt)) { - if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) - printf("%s Send double click\n", __func__); - evt->val = event.val = KM_DBL_CLICK; - } /* this case happens on holding a key pressed, it should not generate * press events events with the same key as modifier */ @@ -3306,13 +3299,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U G.is_break = true; } - /* double click test - only for press */ - if (event.val == KM_PRESS) { - evt->prevclicktime = PIL_check_seconds_timer(); - evt->prevclickx = event.x; - evt->prevclicky = event.y; - } - wm_event_add(win, &event); break; diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 82e46c1b333..0a89ca113c4 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -1192,11 +1192,15 @@ int WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2) return 0; if (k1->val != KM_ANY && k2->val != KM_ANY) { + +#if 0 /* thanks to clicktype those shouldn't be needed anymore */ /* take click, press, release conflict into account */ if (k1->val == KM_CLICK && ELEM(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0) return 0; if (k2->val == KM_CLICK && ELEM(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0) return 0; +#endif + if (k1->val != k2->val) return 0; } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index c62e82b8e43..c2cd96165f3 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -5108,7 +5108,7 @@ void wm_window_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "WM_OT_debug_menu", DKEY, KM_PRESS, KM_ALT | KM_CTRL, 0); /* menus that can be accessed anywhere in blender */ - WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_PRESS, 0, 0); + WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_CLICK, 0, 0); WM_keymap_add_menu(keymap, "USERPREF_MT_ndof_settings", NDOF_BUTTON_MENU, KM_PRESS, 0, 0); /* Space switching */ diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 4f7e5ab75b3..98766f35006 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1097,6 +1097,76 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr return 1; } +/** + * #KM_DBL_CLICK is set in wm_event_clicktype_init (wm_event_system.c) + * Normally, this should be there too, but for #KM_CLICK/#KM_HOLD, we need a + * time precision of a few milliseconds, which we can't get from there + */ +static void wm_window_event_clicktype_init(const bContext *C) +{ + wmWindowManager *wm = CTX_wm_manager(C); + + if (wm->winactive) { + wmWindow *win = wm->winactive; + wmEvent *event = win->eventstate; + short click_type = event->click_type; + + BLI_assert(event != NULL); + + if ((event->type == EVENT_NONE) || + ((event->val == KM_NOTHING) && (event->is_key_pressed == false))) + { + /* nothing needs to be done here */ + return; + } + + /* we always want click_type of last clicked button (to enable + * use with modifier keys) - unnecessary for mouse though */ + if (!ISMOUSE(event->type) && + event->val == KM_PRESS && + event->type != event->keymodifier) + { + event->is_key_pressed = false; + } + else if (event->val == KM_PRESS && !event->is_key_pressed) { + event->is_key_pressed = true; + event->click_time = PIL_check_seconds_timer(); + } + else if (event->val == KM_RELEASE && event->is_key_pressed) { + event->is_key_pressed = false; + } + else if (event->is_key_pressed == false) { + return; + } + + /* the actual test */ + if ((PIL_check_seconds_timer() - event->click_time) * 1000 <= U.click_timeout) { + /* for any reason some X11 systems send two release events triggering two KM_CLICK + * events - making the rules more strict by checking for prevval resolves this */ + if (event->val == KM_RELEASE && event->prevval != KM_RELEASE) { + click_type = KM_CLICK; + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) { + printf("%s Send click event\n", __func__); + } + } + } + else if (event->is_key_pressed) { + click_type = KM_HOLD; + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) { + printf("%s Send hold event\n", __func__); + } + + /* the event we send in this case is a "dummy" event - don't send value */ + event->val = KM_NOTHING; + } + + /* send event with new click_type */ + if (event->click_type != click_type) { + event->click_type = click_type; + wm_event_add(win, event); + } + } +} /* This timer system only gives maximum 1 timer event per redraw cycle, * to prevent queues to get overloaded. @@ -1156,7 +1226,11 @@ void wm_window_process_events(const bContext *C) if (hasevent) GHOST_DispatchEvents(g_system); - + + /* not nice to have this here, but it's the only place + * that can call it with the needed time precision */ + wm_window_event_clicktype_init(C); + hasevent |= wm_window_timer(C); /* no event, we sleep 5 milliseconds */ -- cgit v1.2.3 From a3fdc6b75525b3cdd02d6d29a7965aa9f6ae334c Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 3 Apr 2015 16:43:33 +0200 Subject: Update keyconfigs for stickies Change are needed to avoid conflicts due to rB53a3850a8a05249942a0c4 --- release/scripts/presets/keyconfig/3dsmax.py | 56 +++++++++++++-------------- release/scripts/presets/keyconfig/maya.py | 60 ++++++++++++++--------------- 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/release/scripts/presets/keyconfig/3dsmax.py b/release/scripts/presets/keyconfig/3dsmax.py index 7694e338d68..319728df4cc 100644 --- a/release/scripts/presets/keyconfig/3dsmax.py +++ b/release/scripts/presets/keyconfig/3dsmax.py @@ -139,16 +139,16 @@ kmi = km.keymap_items.new('marker.camera_bind', 'B', 'PRESS', ctrl=True) km = kc.keymaps.new('Outliner', space_type='OUTLINER', region_type='WINDOW', modal=False) kmi = km.keymap_items.new('outliner.item_rename', 'LEFTMOUSE', 'DOUBLE_CLICK') -kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'CLICK') +kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'PRESS') kmi.properties.extend = False kmi.properties.recursive = False -kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'CLICK', shift=True) +kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'PRESS', shift=True) kmi.properties.extend = True kmi.properties.recursive = False -kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'CLICK', ctrl=True) +kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'PRESS', ctrl=True) kmi.properties.extend = False kmi.properties.recursive = True -kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'CLICK', shift=True, ctrl=True) +kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'PRESS', shift=True, ctrl=True) kmi.properties.extend = True kmi.properties.recursive = True kmi = km.keymap_items.new('outliner.select_border', 'B', 'PRESS') @@ -236,7 +236,7 @@ kmi = km.keymap_items.new('pose.paste', 'V', 'PRESS', ctrl=True) kmi.properties.flipped = False kmi = km.keymap_items.new('pose.paste', 'V', 'PRESS', shift=True, ctrl=True) kmi.properties.flipped = True -kmi = km.keymap_items.new('pose.select_all', 'LEFTMOUSE', 'CLICK') +kmi = km.keymap_items.new('pose.select_all', 'LEFTMOUSE', 'PRESS') kmi.properties.action = 'TOGGLE' kmi = km.keymap_items.new('pose.select_all', 'I', 'PRESS', ctrl=True) kmi.properties.action = 'INVERT' @@ -586,56 +586,56 @@ kmi = km.keymap_items.new('wm.context_toggle_enum', 'Z', 'PRESS', alt=True) kmi.properties.data_path = 'space_data.viewport_shade' kmi.properties.value_1 = 'SOLID' kmi.properties.value_2 = 'TEXTURED' -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK') +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS') kmi.properties.extend = False kmi.properties.deselect = False kmi.properties.toggle = False kmi.properties.center = False kmi.properties.enumerate = False kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', ctrl=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', ctrl=True) kmi.properties.extend = False kmi.properties.deselect = False kmi.properties.toggle = True kmi.properties.center = False kmi.properties.enumerate = False kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True) kmi.properties.extend = False kmi.properties.deselect = False kmi.properties.toggle = False kmi.properties.center = True kmi.properties.enumerate = False kmi.properties.object = True -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', alt=True) kmi.properties.extend = False kmi.properties.deselect = False kmi.properties.toggle = False kmi.properties.center = False kmi.properties.enumerate = True kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True, ctrl=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True) kmi.properties.extend = True kmi.properties.deselect = False kmi.properties.toggle = True kmi.properties.center = True kmi.properties.enumerate = False kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', ctrl=True, alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True) kmi.properties.extend = False kmi.properties.deselect = False kmi.properties.toggle = False kmi.properties.center = True kmi.properties.enumerate = True kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True, alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True, alt=True) kmi.properties.extend = False kmi.properties.deselect = False kmi.properties.toggle = True kmi.properties.center = False kmi.properties.enumerate = True kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True, ctrl=True, alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True) kmi.properties.extend = False kmi.properties.deselect = False kmi.properties.toggle = True @@ -971,7 +971,7 @@ kmi = km.keymap_items.new('graph.delete', 'X', 'PRESS') kmi = km.keymap_items.new('graph.delete', 'DEL', 'PRESS') kmi = km.keymap_items.new('graph.duplicate_move', 'D', 'PRESS', shift=True) kmi = km.keymap_items.new('graph.keyframe_insert', 'I', 'PRESS') -kmi = km.keymap_items.new('graph.click_insert', 'ACTIONMOUSE', 'CLICK', ctrl=True) +kmi = km.keymap_items.new('graph.click_insert', 'ACTIONMOUSE', 'PRESS', ctrl=True) kmi = km.keymap_items.new('graph.copy', 'C', 'PRESS', ctrl=True) kmi = km.keymap_items.new('graph.paste', 'V', 'PRESS', ctrl=True) kmi = km.keymap_items.new('graph.previewrange_set', 'P', 'PRESS', ctrl=True, alt=True) @@ -1130,18 +1130,18 @@ km = kc.keymaps.new('File Browser Main', space_type='FILE_BROWSER', region_type= kmi = km.keymap_items.new('file.execute', 'LEFTMOUSE', 'DOUBLE_CLICK') kmi.properties.need_active = True -kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'CLICK') -kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'CLICK', shift=True) +kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'PRESS') +kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'PRESS', shift=True) kmi.properties.extend = True -kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'CLICK', alt=True) +kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'PRESS', alt=True) kmi.properties.extend = True kmi.properties.fill = True -kmi = km.keymap_items.new('file.select', 'RIGHTMOUSE', 'CLICK') +kmi = km.keymap_items.new('file.select', 'RIGHTMOUSE', 'PRESS') kmi.properties.open = False -kmi = km.keymap_items.new('file.select', 'RIGHTMOUSE', 'CLICK', shift=True) +kmi = km.keymap_items.new('file.select', 'RIGHTMOUSE', 'PRESS', shift=True) kmi.properties.extend = True kmi.properties.open = False -kmi = km.keymap_items.new('file.select', 'RIGHTMOUSE', 'CLICK', alt=True) +kmi = km.keymap_items.new('file.select', 'RIGHTMOUSE', 'PRESS', alt=True) kmi.properties.extend = True kmi.properties.fill = True kmi.properties.open = False @@ -2156,9 +2156,9 @@ kmi = km.keymap_items.new('mesh.separate', 'P', 'PRESS') kmi = km.keymap_items.new('mesh.split', 'Y', 'PRESS') kmi = km.keymap_items.new('mesh.vert_connect', 'J', 'PRESS') kmi = km.keymap_items.new('transform.vert_slide', 'V', 'PRESS', shift=True) -kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'CLICK', ctrl=True) +kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'PRESS', ctrl=True) kmi.properties.rotate_source = True -kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'CLICK', shift=True, ctrl=True) +kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'PRESS', shift=True, ctrl=True) kmi.properties.rotate_source = False kmi = km.keymap_items.new('wm.call_menu', 'X', 'PRESS') kmi.properties.name = 'VIEW3D_MT_edit_mesh_delete' @@ -2223,8 +2223,8 @@ km = kc.keymaps.new('Curve', space_type='EMPTY', region_type='WINDOW', modal=Fal kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True) kmi.properties.name = 'INFO_MT_edit_curve_add' kmi = km.keymap_items.new('curve.handle_type_set', 'V', 'PRESS') -kmi = km.keymap_items.new('curve.vertex_add', 'LEFTMOUSE', 'CLICK', ctrl=True) -kmi = km.keymap_items.new('curve.select_all', 'LEFTMOUSE', 'CLICK') +kmi = km.keymap_items.new('curve.vertex_add', 'LEFTMOUSE', 'PRESS', ctrl=True) +kmi = km.keymap_items.new('curve.select_all', 'LEFTMOUSE', 'PRESS') kmi.properties.action = 'TOGGLE' kmi = km.keymap_items.new('curve.select_all', 'I', 'PRESS', ctrl=True) kmi.properties.action = 'INVERT' @@ -2293,7 +2293,7 @@ kmi = km.keymap_items.new('armature.switch_direction', 'F', 'PRESS', alt=True) kmi = km.keymap_items.new('armature.bone_primitive_add', 'A', 'PRESS', shift=True) kmi = km.keymap_items.new('armature.parent_set', 'P', 'PRESS', ctrl=True) kmi = km.keymap_items.new('armature.parent_clear', 'P', 'PRESS', alt=True) -kmi = km.keymap_items.new('armature.select_all', 'LEFTMOUSE', 'CLICK') +kmi = km.keymap_items.new('armature.select_all', 'LEFTMOUSE', 'PRESS') kmi.properties.action = 'TOGGLE' kmi = km.keymap_items.new('armature.select_all', 'I', 'PRESS', ctrl=True) kmi.properties.action = 'INVERT' @@ -2316,7 +2316,7 @@ kmi = km.keymap_items.new('armature.delete', 'DEL', 'PRESS') kmi = km.keymap_items.new('armature.duplicate_move', 'D', 'PRESS', shift=True) kmi = km.keymap_items.new('armature.extrude_move', 'E', 'PRESS') kmi = km.keymap_items.new('armature.extrude_forked', 'E', 'PRESS', shift=True) -kmi = km.keymap_items.new('armature.click_extrude', 'LEFTMOUSE', 'CLICK', ctrl=True) +kmi = km.keymap_items.new('armature.click_extrude', 'LEFTMOUSE', 'PRESS', ctrl=True) kmi = km.keymap_items.new('armature.fill', 'F', 'PRESS', ctrl=True) kmi = km.keymap_items.new('armature.merge', 'M', 'PRESS', alt=True) kmi = km.keymap_items.new('armature.separate', 'P', 'PRESS', ctrl=True, alt=True) @@ -2348,7 +2348,7 @@ kmi.properties.unselected = True kmi = km.keymap_items.new('mball.delete_metaelems', 'X', 'PRESS') kmi = km.keymap_items.new('mball.delete_metaelems', 'DEL', 'PRESS') kmi = km.keymap_items.new('mball.duplicate_metaelems', 'D', 'PRESS', shift=True) -kmi = km.keymap_items.new('mball.select_all', 'LEFTMOUSE', 'CLICK') +kmi = km.keymap_items.new('mball.select_all', 'LEFTMOUSE', 'PRESS') kmi.properties.action = 'TOGGLE' kmi = km.keymap_items.new('mball.select_all', 'I', 'PRESS', ctrl=True) kmi.properties.action = 'INVERT' @@ -2366,7 +2366,7 @@ kmi.properties.value_2 = 'CONNECTED' # Map Lattice km = kc.keymaps.new('Lattice', space_type='EMPTY', region_type='WINDOW', modal=False) -kmi = km.keymap_items.new('lattice.select_all', 'LEFTMOUSE', 'CLICK') +kmi = km.keymap_items.new('lattice.select_all', 'LEFTMOUSE', 'PRESS') kmi.properties.action = 'TOGGLE' kmi = km.keymap_items.new('lattice.select_all', 'I', 'PRESS', ctrl=True) kmi.properties.action = 'INVERT' diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py index 28799d1cf67..f9bb020d856 100644 --- a/release/scripts/presets/keyconfig/maya.py +++ b/release/scripts/presets/keyconfig/maya.py @@ -227,9 +227,9 @@ kmi = km.keymap_items.new('time.view_all', 'A', 'PRESS') km = kc.keymaps.new('Outliner', space_type='OUTLINER', region_type='WINDOW', modal=False) kmi = km.keymap_items.new('outliner.item_rename', 'LEFTMOUSE', 'DOUBLE_CLICK') -kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'CLICK') +kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'PRESS') kmi.properties.extend = False -kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'CLICK', shift=True) +kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'PRESS', shift=True) kmi.properties.extend = True kmi = km.keymap_items.new('outliner.select_border', 'EVT_TWEAK_S', 'ANY', any=True) kmi = km.keymap_items.new('outliner.item_openclose', 'RET', 'PRESS') @@ -656,7 +656,7 @@ kmi = km.keymap_items.new('mesh.edge_face_add', 'F', 'PRESS', alt=True) kmi = km.keymap_items.new('mesh.duplicate_move', 'D', 'PRESS', ctrl=True) kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True) kmi.properties.name = 'INFO_MT_mesh_add' -kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'MIDDLEMOUSE', 'CLICK', ctrl=True) +kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'MIDDLEMOUSE', 'PRESS', ctrl=True) kmi = km.keymap_items.new('wm.call_menu', 'BACK_SPACE', 'PRESS') kmi.properties.name = 'VIEW3D_MT_edit_mesh_delete' kmi = km.keymap_items.new('wm.call_menu', 'DEL', 'PRESS') @@ -727,7 +727,7 @@ km = kc.keymaps.new('Curve', space_type='EMPTY', region_type='WINDOW', modal=Fal kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True) kmi.properties.name = 'INFO_MT_edit_curve_add' kmi = km.keymap_items.new('curve.handle_type_set', 'RIGHTMOUSE', 'PRESS') -kmi = km.keymap_items.new('curve.vertex_add', 'MIDDLEMOUSE', 'CLICK', ctrl=True) +kmi = km.keymap_items.new('curve.vertex_add', 'MIDDLEMOUSE', 'PRESS', ctrl=True) kmi = km.keymap_items.new('curve.select_all', 'A', 'PRESS', ctrl=True) kmi.properties.action = 'TOGGLE' kmi = km.keymap_items.new('curve.select_all', 'I', 'PRESS', ctrl=True) @@ -817,7 +817,7 @@ kmi = km.keymap_items.new('armature.delete', 'DEL', 'PRESS') kmi = km.keymap_items.new('armature.duplicate_move', 'D', 'PRESS', ctrl=True) kmi = km.keymap_items.new('armature.extrude_move', 'X', 'PRESS', alt=True) kmi = km.keymap_items.new('armature.extrude_forked', 'X', 'PRESS', shift=True, alt=True) -kmi = km.keymap_items.new('armature.click_extrude', 'MIDDLEMOUSE', 'CLICK', ctrl=True) +kmi = km.keymap_items.new('armature.click_extrude', 'MIDDLEMOUSE', 'PRESS', ctrl=True) kmi = km.keymap_items.new('armature.fill', 'F', 'PRESS', alt=True) kmi = km.keymap_items.new('armature.merge', 'M', 'PRESS', alt=True) kmi = km.keymap_items.new('armature.separate', 'P', 'PRESS', ctrl=True, alt=True) @@ -1003,56 +1003,56 @@ kmi = km.keymap_items.new('wm.context_toggle_enum', 'FIVE', 'PRESS') kmi.properties.data_path = 'space_data.viewport_shade' kmi.properties.value_1 = 'TEXTURED' kmi.properties.value_2 = 'SOLID' -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK') +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS') kmi.properties.extend = False kmi.properties.toggle = False kmi.properties.deselect = False kmi.properties.center = False kmi.properties.object = False kmi.properties.enumerate = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True) kmi.properties.extend = False kmi.properties.toggle = True kmi.properties.deselect = False kmi.properties.center = False kmi.properties.object = False kmi.properties.enumerate = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', ctrl=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', ctrl=True) kmi.properties.center = False kmi.properties.extend = False kmi.properties.toggle = False kmi.properties.deselect = True kmi.properties.object = False kmi.properties.enumerate = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', alt=True) kmi.properties.enumerate = True kmi.properties.extend = False kmi.properties.toggle = False kmi.properties.deselect = False kmi.properties.center = False kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True, ctrl=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True) kmi.properties.extend = True kmi.properties.center = True kmi.properties.toggle = False kmi.properties.deselect = False kmi.properties.object = False kmi.properties.enumerate = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', ctrl=True, alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True) kmi.properties.center = True kmi.properties.enumerate = True kmi.properties.extend = False kmi.properties.toggle = False kmi.properties.deselect = False kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True, alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True, alt=True) kmi.properties.extend = True kmi.properties.enumerate = True kmi.properties.toggle = False kmi.properties.deselect = False kmi.properties.center = False kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True, ctrl=True, alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True) kmi.properties.extend = True kmi.properties.center = True kmi.properties.enumerate = True @@ -1106,7 +1106,7 @@ km = kc.keymaps.new('Animation Channels', space_type='EMPTY', region_type='WINDO kmi = km.keymap_items.new('anim.channels_click', 'LEFTMOUSE', 'PRESS') kmi.properties.extend = False -kmi = km.keymap_items.new('anim.channels_click', 'LEFTMOUSE', 'CLICK', shift=True) +kmi = km.keymap_items.new('anim.channels_click', 'LEFTMOUSE', 'PRESS', shift=True) kmi.properties.extend = True kmi = km.keymap_items.new('anim.channels_click', 'LEFTMOUSE', 'PRESS', shift=True, ctrl=True) kmi.properties.children_only = True @@ -1144,9 +1144,9 @@ km = kc.keymaps.new('UV Editor', space_type='EMPTY', region_type='WINDOW', modal kmi = km.keymap_items.new('wm.context_toggle', 'Q', 'PRESS') kmi.properties.data_path = 'tool_settings.use_uv_sculpt' kmi = km.keymap_items.new('uv.mark_seam', 'E', 'PRESS', ctrl=True) -kmi = km.keymap_items.new('uv.select', 'SELECTMOUSE', 'CLICK') +kmi = km.keymap_items.new('uv.select', 'SELECTMOUSE', 'PRESS') kmi.properties.extend = False -kmi = km.keymap_items.new('uv.select', 'SELECTMOUSE', 'CLICK', shift=True) +kmi = km.keymap_items.new('uv.select', 'SELECTMOUSE', 'PRESS', shift=True) kmi.properties.extend = True kmi = km.keymap_items.new('uv.select_loop', 'LEFTMOUSE', 'PRESS', ctrl=True, alt=True) kmi.properties.extend = False @@ -1314,7 +1314,7 @@ kmi = km.keymap_items.new('wm.context_toggle', 'H', 'PRESS', ctrl=True) kmi.properties.data_path = 'space_data.show_handles' kmi = km.keymap_items.new('graph.cursor_set', 'LEFTMOUSE', 'PRESS', key_modifier='K') kmi.properties.value = 1.1754943508222875e-38 -kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'CLICK') +kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'PRESS') kmi.properties.extend = False kmi.properties.column = False kmi.properties.curves = False @@ -1322,11 +1322,11 @@ kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'PRESS', alt=True) kmi.properties.extend = False kmi.properties.column = True kmi.properties.curves = False -kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'CLICK', shift=True) +kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'PRESS', shift=True) kmi.properties.extend = True kmi.properties.column = False kmi.properties.curves = False -kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'CLICK', shift=True, alt=True) +kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'PRESS', shift=True, alt=True) kmi.properties.extend = True kmi.properties.column = True kmi.properties.curves = False @@ -1334,7 +1334,7 @@ kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'PRESS', ctrl=True kmi.properties.extend = False kmi.properties.column = False kmi.properties.curves = True -kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'CLICK', shift=True, ctrl=True, alt=True) +kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True) kmi.properties.extend = True kmi.properties.column = False kmi.properties.curves = True @@ -1366,7 +1366,7 @@ kmi = km.keymap_items.new('graph.delete', 'BACK_SPACE', 'PRESS') kmi = km.keymap_items.new('graph.delete', 'DEL', 'PRESS') kmi = km.keymap_items.new('graph.duplicate_move', 'D', 'PRESS', ctrl=True) kmi = km.keymap_items.new('graph.keyframe_insert', 'I', 'PRESS') -kmi = km.keymap_items.new('graph.click_insert', 'LEFTMOUSE', 'CLICK', ctrl=True) +kmi = km.keymap_items.new('graph.click_insert', 'LEFTMOUSE', 'PRESS', ctrl=True) kmi = km.keymap_items.new('graph.copy', 'C', 'PRESS', ctrl=True) kmi = km.keymap_items.new('graph.paste', 'V', 'PRESS', ctrl=True) kmi = km.keymap_items.new('graph.previewrange_set', 'P', 'PRESS', ctrl=True, alt=True) @@ -1511,11 +1511,11 @@ km = kc.keymaps.new('File Browser Main', space_type='FILE_BROWSER', region_type= kmi = km.keymap_items.new('file.execute', 'LEFTMOUSE', 'DOUBLE_CLICK') kmi.properties.need_active = True -kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'CLICK') +kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'PRESS') kmi.properties.extend = False -kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'CLICK', shift=True) +kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'PRESS', shift=True) kmi.properties.extend = True -kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'CLICK', alt=True) +kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'PRESS', alt=True) kmi.properties.extend = True kmi.properties.fill = True kmi = km.keymap_items.new('file.select_all_toggle', 'A', 'PRESS', ctrl=True) @@ -1541,13 +1541,13 @@ kmi.properties.increment = -100 # Map Dopesheet km = kc.keymaps.new('Dopesheet', space_type='DOPESHEET_EDITOR', region_type='WINDOW', modal=False) -kmi = km.keymap_items.new('action.clickselect', 'LEFTMOUSE', 'CLICK') +kmi = km.keymap_items.new('action.clickselect', 'LEFTMOUSE', 'PRESS') kmi.properties.extend = False kmi.properties.column = False kmi = km.keymap_items.new('action.clickselect', 'LEFTMOUSE', 'PRESS', alt=True) kmi.properties.extend = False kmi.properties.column = True -kmi = km.keymap_items.new('action.clickselect', 'LEFTMOUSE', 'CLICK', shift=True) +kmi = km.keymap_items.new('action.clickselect', 'LEFTMOUSE', 'PRESS', shift=True) kmi.properties.extend = True kmi.properties.column = False kmi = km.keymap_items.new('action.clickselect', 'LEFTMOUSE', 'PRESS', shift=True, alt=True) @@ -1618,7 +1618,7 @@ kmi = km.keymap_items.new('nla.tracks_delete', 'DEL', 'PRESS') # Map NLA Editor km = kc.keymaps.new('NLA Editor', space_type='NLA_EDITOR', region_type='WINDOW', modal=False) -kmi = km.keymap_items.new('nla.click_select', 'SELECTMOUSE', 'CLICK') +kmi = km.keymap_items.new('nla.click_select', 'SELECTMOUSE', 'PRESS') kmi.properties.extend = False kmi = km.keymap_items.new('nla.click_select', 'SELECTMOUSE', 'PRESS', shift=True) kmi.properties.extend = True @@ -1740,12 +1740,12 @@ kmi = km.keymap_items.new('sequencer.cut_multicam', 'NINE', 'PRESS') kmi.properties.camera = 9 kmi = km.keymap_items.new('sequencer.cut_multicam', 'ZERO', 'PRESS') kmi.properties.camera = 10 -kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'CLICK') +kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'PRESS') kmi.properties.extend = False kmi.properties.linked_handle = False kmi.properties.left_right = 'NONE' kmi.properties.linked_time = False -kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'CLICK', shift=True) +kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'PRESS', shift=True) kmi.properties.extend = True kmi.properties.linked_handle = False kmi.properties.left_right = 'NONE' @@ -1755,7 +1755,7 @@ kmi.properties.extend = False kmi.properties.linked_handle = True kmi.properties.left_right = 'NONE' kmi.properties.linked_time = False -kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'CLICK', shift=True, alt=True) +kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'PRESS', shift=True, alt=True) kmi.properties.extend = True kmi.properties.linked_handle = True kmi.properties.left_right = 'NONE' -- cgit v1.2.3 From 34c4133daf01cd7b2b94bc54b3b78de21b3091b9 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 4 Apr 2015 01:44:08 +1300 Subject: Tweaks to descriptions for Action Layer Up/Down --- source/blender/editors/space_action/action_data.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index f7e110e3b90..a4eadd8a63b 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -726,7 +726,7 @@ void ACTION_OT_layer_next(wmOperatorType *ot) /* identifiers */ ot->name = "Next Layer"; ot->idname = "ACTION_OT_layer_next"; - ot->description = "Edit action in animation layer above the current action in the NLA Stack"; + ot->description = "Switch to editing action in animation layer above the current action in the NLA Stack"; /* callbacks */ ot->exec = action_layer_next_exec; @@ -823,7 +823,7 @@ void ACTION_OT_layer_prev(wmOperatorType *ot) /* identifiers */ ot->name = "Previous Layer"; ot->idname = "ACTION_OT_layer_prev"; - ot->description = "Edit action in animation layer below the current action in the NLA Stack"; + ot->description = "Switch to editing action in animation layer below the current action in the NLA Stack"; /* callbacks */ ot->exec = action_layer_prev_exec; -- cgit v1.2.3 From 53f4aa78175307e75e6a9c6deb6fb7f1caf766f9 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 4 Apr 2015 11:36:46 +1300 Subject: WIP: Added dedicated operator for unlinking actions from the Action Editor (NLA buttons support to come) After looking into this more carefully, I've found that we do in fact need a dedicate operator to add some custom logic when trying to unlink an action from the editor/datablocks. Specifically, this new operator does the following: 1) When in Tweak Mode, it shouldn't be possible to unlink the active action, or else, everything turns to custard. 2) If the Action doesn't have any other users, the user should at least get a warning that it is going to get lost. 3) We need a convenient way to exit Tweak Mode from the Action Editor 4) If none of the above apply, we can just unlink normally This commit implements this for the Action Editor, with stubs for the NLA Editor too. Those will be fixed next. --- release/scripts/startup/bl_ui/space_dopesheet.py | 2 +- source/blender/editors/include/ED_anim_api.h | 8 ++ source/blender/editors/space_action/action_data.c | 126 +++++++++++++++++++-- .../blender/editors/space_action/action_intern.h | 2 + source/blender/editors/space_action/action_ops.c | 2 + source/blender/editors/space_nla/nla_buttons.c | 6 +- source/blender/editors/space_nla/nla_channels.c | 46 ++++++++ source/blender/editors/space_nla/nla_intern.h | 1 + source/blender/editors/space_nla/nla_ops.c | 1 + 9 files changed, 179 insertions(+), 15 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index c4452ee61f4..bb08a7c392e 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -118,7 +118,7 @@ class DOPESHEET_HT_header(Header): row.operator("action.layer_prev", text="", icon='TRIA_DOWN') row.operator("action.layer_next", text="", icon='TRIA_UP') - layout.template_ID(st, "action", new="action.new") + layout.template_ID(st, "action", new="action.new", unlink="action.unlink") row = layout.row(align=True) row.operator("action.push_down", text="Push Down", icon='NLA_PUSHDOWN') diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 4c7c78df349..9dea66adc7c 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -675,6 +675,14 @@ void ED_operatormacros_graph(void); /* space_action */ void ED_operatormacros_action(void); +/* ************************************************ */ +/* Animation Editor Exports */ +/* XXX: Should we be doing these here, or at all? */ + +/* Action Editor - Action Management */ +struct AnimData *ED_actedit_animdata_from_context(struct bContext *C); +void ED_animedit_unlink_action(struct bContext *C, struct ID *id, struct AnimData *adt, struct bAction *act, struct ReportList *reports); + /* ************************************************ */ #endif /* __ED_ANIM_API_H__ */ diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index a4eadd8a63b..e55da7dd4b3 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -81,10 +81,10 @@ #include "action_intern.h" /* ************************************************************************** */ -/* ACTION MANAGEMENT */ +/* ACTION CREATION */ /* Helper function to find the active AnimData block from the Action Editor context */ -static AnimData *actedit_animdata_from_context(bContext *C) +AnimData *ED_actedit_animdata_from_context(bContext *C) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); Object *ob = CTX_data_active_object(C); @@ -234,7 +234,7 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op)) adt = ptr.data; } else if (ptr.type == &RNA_SpaceDopeSheetEditor) { - adt = actedit_animdata_from_context(C); + adt = ED_actedit_animdata_from_context(C); } /* Perform stashing operation - But only if there is an action */ @@ -301,7 +301,7 @@ static int action_pushdown_poll(bContext *C) { if (ED_operator_action_active(C)) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); /* Check for AnimData, Actions, and that tweakmode is off */ if (adt && saction->action) { @@ -320,7 +320,7 @@ static int action_pushdown_poll(bContext *C) static int action_pushdown_exec(bContext *C, wmOperator *op) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); /* Do the deed... */ if (adt) { @@ -368,7 +368,7 @@ void ACTION_OT_push_down(wmOperatorType *ot) static int action_stash_exec(bContext *C, wmOperator *op) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); /* Perform stashing operation */ if (adt) { @@ -431,7 +431,7 @@ void ACTION_OT_stash(wmOperatorType *ot) static int action_stash_create_poll(bContext *C) { if (ED_operator_action_active(C)) { - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */ /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */ @@ -461,7 +461,7 @@ static int action_stash_create_poll(bContext *C) static int action_stash_create_exec(bContext *C, wmOperator *op) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); /* Check for no action... */ if (saction->action == NULL) { @@ -520,6 +520,108 @@ void ACTION_OT_stash_and_create(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/* ************************************************************************** */ +/* ACTION UNLINK */ + +/* ******************* Action Unlink Operator ******************** */ +/* We use a custom unlink operator here, as there are some technicalities which need special care: + * 1) When in Tweak Mode, it shouldn't be possible to unlink the active action, + * or else, everything turns to custard. + * 2) If the Action doesn't have any other users, the user should at least get + * a warning that it is going to get lost. + * 3) We need a convenient way to exit Tweak Mode from the Action Editor + */ + +void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports) +{ + ScrArea *sa = CTX_wm_area(C); + + /* If the old action only has a single user (that it's about to lose), + * warn user about it + * + * TODO: Maybe we should just save it for them? But then, there's the problem of + * trying to get rid of stuff that's actually unwanted! + */ + if (act->id.us == 1) { + BKE_reportf(reports, RPT_ERROR, + "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain", + act->id.name + 2); + } + + /* If in Tweak Mode, don't unlink. Instead, this + * becomes a shortcut to exit Tweak Mode instead + */ + if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) { + /* Exit Tweak Mode */ + BKE_nla_tweakmode_exit(adt); + + /* Flush this to the Action Editor (if that's where this change was initiated) */ + if (sa->spacetype == SPACE_ACTION) { + actedit_change_action(C, NULL); + } + } + else { + /* Unlink normally - Setting it to NULL should be enough to get the old one unlinked */ + if (sa->spacetype == SPACE_ACTION) { + /* clear action editor -> action */ + actedit_change_action(C, NULL); + } + else { + /* clear AnimData -> action */ + PointerRNA ptr; + PropertyRNA *prop; + + /* create AnimData RNA pointers */ + RNA_pointer_create(id, &RNA_AnimData, adt, &ptr); + prop = RNA_struct_find_property(&ptr, "action"); + + /* clear... */ + RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL); + RNA_property_update(C, &ptr, prop); + } + } +} + +/* -------------------------- */ + +static int action_unlink_poll(bContext *C) +{ + if (ED_operator_action_active(C)) { + SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); + AnimData *adt = ED_actedit_animdata_from_context(C); + + /* Only when there's an active action, in the right modes... */ + if (saction->action && adt) + return true; + } + + /* something failed... */ + return false; +} + +static int action_unlink_exec(bContext *C, wmOperator *op) +{ + AnimData *adt = ED_actedit_animdata_from_context(C); + + if (adt && adt->action) { + ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports); + } + + return OPERATOR_FINISHED; +} + +void ACTION_OT_unlink(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Unlink Action"; + ot->idname = "ACTION_OT_unlink"; + ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)"; + + /* callbacks */ + ot->exec = action_unlink_exec; + ot->poll = action_unlink_poll; +} + /* ************************************************************************** */ /* ACTION BROWSING */ @@ -631,7 +733,7 @@ static int action_layer_next_poll(bContext *C) { /* Action Editor's action editing modes only */ if (ED_operator_action_active(C)) { - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); if (adt) { /* only allow if we're in tweakmode, and there's something above us... */ if (adt->flag & ADT_NLA_EDIT_ON) { @@ -665,7 +767,7 @@ static int action_layer_next_poll(bContext *C) static int action_layer_next_exec(bContext *C, wmOperator *op) { - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); NlaTrack *act_track; Scene *scene = CTX_data_scene(C); @@ -742,7 +844,7 @@ static int action_layer_prev_poll(bContext *C) { /* Action Editor's action editing modes only */ if (ED_operator_action_active(C)) { - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); if (adt) { if (adt->flag & ADT_NLA_EDIT_ON) { /* Tweak Mode: We need to check if there are any tracks below the active one that we can move to */ @@ -775,7 +877,7 @@ static int action_layer_prev_poll(bContext *C) static int action_layer_prev_exec(bContext *C, wmOperator *op) { - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); NlaTrack *act_track; NlaTrack *nlt; diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index 3b0da089b9b..9f9b15c3c26 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -98,6 +98,8 @@ void ACTION_OT_snap(struct wmOperatorType *ot); void ACTION_OT_mirror(struct wmOperatorType *ot); void ACTION_OT_new(struct wmOperatorType *ot); +void ACTION_OT_unlink(struct wmOperatorType *ot); + void ACTION_OT_push_down(struct wmOperatorType *ot); void ACTION_OT_stash(struct wmOperatorType *ot); void ACTION_OT_stash_and_create(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 431dd27d064..9ad0931a957 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -79,6 +79,8 @@ void action_operatortypes(void) WM_operatortype_append(ACTION_OT_paste); WM_operatortype_append(ACTION_OT_new); + WM_operatortype_append(ACTION_OT_unlink); + WM_operatortype_append(ACTION_OT_push_down); WM_operatortype_append(ACTION_OT_stash); WM_operatortype_append(ACTION_OT_stash_and_create); diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 66023ce1243..1fb7228dd98 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -159,7 +159,9 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p } /* AnimData pointer */ - RNA_pointer_create(id, &RNA_AnimData, ale->adt, adt_ptr); + if (adt_ptr) { + RNA_pointer_create(id, &RNA_AnimData, ale->adt, adt_ptr); + } /* set found status to -1, since setting to 1 would break the loop * and potentially skip an active NLA-Track in some cases... @@ -282,7 +284,7 @@ static void nla_panel_animdata(const bContext *C, Panel *pa) /* Active Action Properties ------------------------------------- */ /* action */ row = uiLayoutRow(layout, true); - uiTemplateID(row, (bContext *)C, &adt_ptr, "action", "ACTION_OT_new", NULL, NULL /*"ACTION_OT_unlink"*/); // XXX: need to make these operators + uiTemplateID(row, (bContext *)C, &adt_ptr, "action", "ACTION_OT_new", NULL, "NLA_OT_action_unlink"); /* extrapolation */ row = uiLayoutRow(layout, true); diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 5476d1c2683..70d9bfe99fe 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -504,6 +504,52 @@ void NLA_OT_action_pushdown(wmOperatorType *ot) RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); } +/* ******************** Action Unlink ******************************** */ + +static int nla_action_unlink_poll(bContext *C) +{ + if (ED_operator_nla_active(C)) { + return nla_panel_context(C, NULL, NULL, NULL); + } + + /* something failed... */ + return false; +} + +static int nla_action_unlink_exec(bContext *C, wmOperator *op) +{ + PointerRNA adt_ptr; + AnimData *adt; + + /* check context and also validity of pointer */ + if (!nla_panel_context(C, &adt_ptr, NULL, NULL)) + return OPERATOR_CANCELLED; + + /* get animdata */ + adt = adt_ptr.data; + if (adt == NULL) + return OPERATOR_CANCELLED; + + /* do unlinking */ + if (adt && adt->action) { + ED_animedit_unlink_action(C, adt_ptr.id.data, adt, adt->action, op->reports); + } + + return OPERATOR_FINISHED; +} + +void NLA_OT_action_unlink(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Unlink Action"; + ot->idname = "NLA_OT_action_unlink"; + ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)"; + + /* callbacks */ + ot->exec = nla_action_unlink_exec; + ot->poll = nla_action_unlink_poll; +} + /* ******************** Add Tracks Operator ***************************** */ /* Add NLA Tracks to the same AnimData block as a selected track, or above the selected tracks */ diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index bd96b5a4de5..70fdb2d478d 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -137,6 +137,7 @@ bool nlaedit_add_tracks_empty(bAnimContext *ac); void NLA_OT_channels_click(wmOperatorType *ot); void NLA_OT_action_pushdown(wmOperatorType *ot); +void NLA_OT_action_unlink(wmOperatorType *ot); void NLA_OT_tracks_add(wmOperatorType *ot); void NLA_OT_tracks_delete(wmOperatorType *ot); diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index b3a875047db..43bc4b9df0f 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -114,6 +114,7 @@ void nla_operatortypes(void) WM_operatortype_append(NLA_OT_channels_click); WM_operatortype_append(NLA_OT_action_pushdown); + WM_operatortype_append(NLA_OT_action_unlink); WM_operatortype_append(NLA_OT_tracks_add); WM_operatortype_append(NLA_OT_tracks_delete); -- cgit v1.2.3 From f9b6709a17f3189a3036250b630216d9b70bd9d2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 4 Apr 2015 10:23:22 +1100 Subject: Add missing declarations --- source/blender/blenlib/BLI_math_color.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 5652c8056c0..d70dfcd9e58 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -129,6 +129,9 @@ void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4]); void xyz_to_lab(float x, float y, float z, float *l, float *a, float *b); +MINLINE float rgb_to_grayscale(const float rgb[3]); +MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3]); + MINLINE int compare_rgb_uchar(const unsigned char a[3], const unsigned char b[3], const int limit); MINLINE float dither_random_value(float s, float t); -- cgit v1.2.3 From 4a4aaabfa90273b4db36c131cdff320e44c8bec6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 4 Apr 2015 10:37:00 +1100 Subject: CMake: treat inline C files as headers --- source/blender/blenlib/CMakeLists.txt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index e614a2a0663..eceec2ab850 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -205,10 +205,14 @@ if(WIN32) ) endif() -blender_add_lib(bf_blenlib "${SRC}" "${INC}" "${INC_SYS}") +# no need to compile object files for inline headers. +set_source_files_properties( + intern/math_base_inline.c + intern/math_color_blend_inline.c + intern/math_color_inline.c + intern/math_geom_inline.c + intern/math_vector_inline.c + PROPERTIES HEADER_FILE_ONLY TRUE +) -if(MSVC) - # Quiet warning about inline math library files that do not export symbols. - # (normally you'd exclude from project, but we still want to see the files in MSVC) - set_target_properties(bf_blenlib PROPERTIES STATIC_LIBRARY_FLAGS /ignore:4221) -endif() +blender_add_lib(bf_blenlib "${SRC}" "${INC}" "${INC_SYS}") -- cgit v1.2.3 From 92c763283568415800319f8139aeb1002dee56a0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 4 Apr 2015 10:48:05 +1100 Subject: Add missing break statements --- source/blender/editors/space_console/console_ops.c | 1 + source/blender/editors/space_text/text_ops.c | 1 + 2 files changed, 2 insertions(+) diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index b3f5e81f154..b3149c1bbf4 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -1144,6 +1144,7 @@ static int console_modal_select(bContext *C, wmOperator *op, const wmEvent *even console_cursor_set_exit(C, op); return OPERATOR_FINISHED; } + break; case MOUSEMOVE: console_modal_select_apply(C, op, event); break; diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 6fb5706bfdf..9d517b20f01 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -2676,6 +2676,7 @@ static int text_set_selection_modal(bContext *C, wmOperator *op, const wmEvent * text_cursor_set_exit(C, op); return OPERATOR_FINISHED; } + break; case TIMER: case MOUSEMOVE: text_cursor_set_apply(C, op, event); -- cgit v1.2.3 From 519e20f9849e13d697aaee6dcab747896f110312 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 4 Apr 2015 10:48:17 +1100 Subject: Cleanup --- source/blender/editors/animation/anim_channels_defines.c | 2 +- source/blender/editors/space_action/action_data.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 18ac5b0d0c4..ebd05d8b16b 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -4206,7 +4206,7 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle UI_block_emboss_set(block, UI_EMBOSS); but = uiDefButR(block, UI_BTYPE_TEXT, 1, "", offset + 3, yminc, RENAME_TEXT_WIDTH, channel_height, - &ptr, RNA_property_identifier(prop), -1, 0, 0, -1, -1, NULL); + &ptr, RNA_property_identifier(prop), -1, 0, 0, -1, -1, NULL); /* copy what outliner does here, see outliner_buttons */ if (UI_but_active_only(C, ac->ar, block, but) == false) { diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index e55da7dd4b3..a7358172ef5 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -23,7 +23,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/editors/space_action/action_edit.c +/** \file blender/editors/space_action/action_data.c * \ingroup spaction */ @@ -544,8 +544,8 @@ void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act, */ if (act->id.us == 1) { BKE_reportf(reports, RPT_ERROR, - "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain", - act->id.name + 2); + "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain", + act->id.name + 2); } /* If in Tweak Mode, don't unlink. Instead, this -- cgit v1.2.3 From 89a3e4deffde3f3a20fad22cf95f368153d3da32 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 4 Apr 2015 14:45:54 +1100 Subject: Cleanup: redundant normalize in expmap_to_quat --- source/blender/blenlib/intern/math_rotation.c | 11 ++++++----- source/blender/editors/space_view3d/view3d_fly.c | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 3d5d47bc2e0..7706e8e8e49 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -1043,11 +1043,12 @@ void expmap_to_quat(float r[4], const float expmap[3]) float angle; /* Obtain axis/angle representation. */ - angle = normalize_v3_v3(axis, expmap); - angle = angle_wrap_rad(angle); - - /* Convert to quaternion. */ - axis_angle_to_quat(r, axis, angle); + if (LIKELY((angle = normalize_v3_v3(axis, expmap)) != 0.0f)) { + axis_angle_normalized_to_quat(r, axis, angle_wrap_rad(angle)); + } + else { + unit_qt(r); + } } /******************************** XYZ Eulers *********************************/ diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index da77c4f75f7..a3dfd62ba6b 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -806,7 +806,7 @@ static int flyApply(bContext *C, FlyInfo *fly) copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); mul_m3_v3(mat, upvec); /* Rotate about the relative up vec */ - axis_angle_to_quat(tmp_quat, upvec, (float)moffset[1] * time_redraw * -FLY_ROTATE_FAC); + axis_angle_to_quat(tmp_quat, upvec, moffset[1] * time_redraw * -FLY_ROTATE_FAC); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); if (fly->xlock != FLY_AXISLOCK_STATE_OFF) @@ -836,7 +836,7 @@ static int flyApply(bContext *C, FlyInfo *fly) } /* Rotate about the relative up vec */ - axis_angle_to_quat(tmp_quat, upvec, (float)moffset[0] * time_redraw * FLY_ROTATE_FAC); + axis_angle_to_quat(tmp_quat, upvec, moffset[0] * time_redraw * FLY_ROTATE_FAC); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); if (fly->xlock != FLY_AXISLOCK_STATE_OFF) -- cgit v1.2.3 From 1c96a84320dad3455a94510baa3ecec1bb45b2e7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 4 Apr 2015 15:13:56 +1100 Subject: Cleanup: use BKE_animdata_* prefix --- source/blender/blenkernel/BKE_animsys.h | 14 ++++++------ source/blender/blenkernel/intern/anim_sys.c | 20 ++++++++--------- source/blender/blenkernel/intern/armature.c | 2 +- source/blender/blenkernel/intern/camera.c | 2 +- source/blender/blenkernel/intern/curve.c | 2 +- source/blender/blenkernel/intern/gpencil.c | 2 +- source/blender/blenkernel/intern/ipo.c | 26 +++++++++++----------- source/blender/blenkernel/intern/key.c | 2 +- source/blender/blenkernel/intern/lamp.c | 2 +- source/blender/blenkernel/intern/lattice.c | 2 +- source/blender/blenkernel/intern/library.c | 4 ++-- source/blender/blenkernel/intern/linestyle.c | 2 +- source/blender/blenkernel/intern/material.c | 2 +- source/blender/blenkernel/intern/mball.c | 2 +- source/blender/blenkernel/intern/mesh.c | 2 +- source/blender/blenkernel/intern/movieclip.c | 2 +- source/blender/blenkernel/intern/node.c | 2 +- source/blender/blenkernel/intern/object.c | 6 ++--- source/blender/blenkernel/intern/particle.c | 2 +- source/blender/blenkernel/intern/scene.c | 6 ++--- source/blender/blenkernel/intern/speaker.c | 2 +- source/blender/blenkernel/intern/texture.c | 2 +- source/blender/blenkernel/intern/world.c | 2 +- .../blender/editors/animation/anim_channels_edit.c | 2 +- source/blender/editors/animation/drivers.c | 2 +- source/blender/editors/animation/keyframing.c | 2 +- source/blender/editors/armature/armature_naming.c | 2 +- .../blender/editors/armature/armature_relations.c | 4 ++-- source/blender/editors/object/object_add.c | 14 ++++++------ source/blender/editors/object/object_relations.c | 20 ++++++++--------- source/blender/editors/space_nla/nla_channels.c | 2 +- .../editors/space_outliner/outliner_tools.c | 2 +- source/blender/makesrna/intern/rna_ID.c | 4 ++-- source/blender/makesrna/intern/rna_constraint.c | 2 +- source/blender/makesrna/intern/rna_key.c | 2 +- source/blender/makesrna/intern/rna_modifier.c | 2 +- source/blender/makesrna/intern/rna_nodetree.c | 2 +- source/blender/makesrna/intern/rna_scene.c | 2 +- source/blender/makesrna/intern/rna_sequencer.c | 2 +- source/blender/makesrna/intern/rna_space.c | 4 ++-- 40 files changed, 90 insertions(+), 90 deletions(-) diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index 0acfd40a110..a8e430c78df 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -56,22 +56,22 @@ bool id_type_can_have_animdata(struct ID *id); struct AnimData *BKE_animdata_from_id(struct ID *id); /* Add AnimData to the given ID-block */ -struct AnimData *BKE_id_add_animdata(struct ID *id); +struct AnimData *BKE_animdata_add_id(struct ID *id); /* Set active action used by AnimData from the given ID-block */ bool BKE_animdata_set_action(struct ReportList *reports, struct ID *id, struct bAction *act); /* Free AnimData */ -void BKE_free_animdata(struct ID *id); +void BKE_animdata_free(struct ID *id); /* Copy AnimData */ -struct AnimData *BKE_copy_animdata(struct AnimData *adt, const bool do_action); +struct AnimData *BKE_animdata_copy(struct AnimData *adt, const bool do_action); /* Copy AnimData */ -bool BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from, const bool do_action); +bool BKE_animdata_copy_id(struct ID *id_to, struct ID *id_from, const bool do_action); /* Copy AnimData Actions */ -void BKE_copy_animdata_id_action(struct ID *id); +void BKE_animdata_copy_id_action(struct ID *id); /* Merge copies of data from source AnimData block */ typedef enum eAnimData_MergeCopy_Modes { @@ -91,7 +91,7 @@ void BKE_animdata_merge_copy(struct ID *dst_id, struct ID *src_id, eAnimData_Mer void BKE_animdata_make_local(struct AnimData *adt); /* Re-Assign ID's */ -void BKE_relink_animdata(struct AnimData *adt); +void BKE_animdata_relink(struct AnimData *adt); /* ************************************* */ /* KeyingSets API */ @@ -134,7 +134,7 @@ void BKE_animdata_fix_paths_rename(struct ID *owner_id, struct AnimData *adt, st bool verify_paths); /* Fix all the paths for the entire database... */ -void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const char *oldName, const char *newName); +void BKE_animdata_fix_paths_rename_all(ID *ref_id, const char *prefix, const char *oldName, const char *newName); /* Fix the path after removing elements that are not ID (e.g., node) */ void BKE_animdata_fix_paths_remove(struct ID *id, const char *path); diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index b4c396d38d2..3c98d11dbdb 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -134,7 +134,7 @@ AnimData *BKE_animdata_from_id(ID *id) * the AnimData pointer is stored immediately after the given ID-block in the struct, * as per IdAdtTemplate. Also note that */ -AnimData *BKE_id_add_animdata(ID *id) +AnimData *BKE_animdata_add_id(ID *id) { /* Only some ID-blocks have this info for now, so we cast the * types that do to be of type IdAdtTemplate, and add the AnimData @@ -216,7 +216,7 @@ bool BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act) /* Freeing -------------------------------------------- */ /* Free AnimData used by the nominated ID-block, and clear ID-block's AnimData pointer */ -void BKE_free_animdata(ID *id) +void BKE_animdata_free(ID *id) { /* Only some ID-blocks have this info for now, so we cast the * types that do to be of type IdAdtTemplate @@ -253,7 +253,7 @@ void BKE_free_animdata(ID *id) /* Copying -------------------------------------------- */ /* Make a copy of the given AnimData - to be used when copying datablocks */ -AnimData *BKE_copy_animdata(AnimData *adt, const bool do_action) +AnimData *BKE_animdata_copy(AnimData *adt, const bool do_action) { AnimData *dadt; @@ -285,25 +285,25 @@ AnimData *BKE_copy_animdata(AnimData *adt, const bool do_action) return dadt; } -bool BKE_copy_animdata_id(ID *id_to, ID *id_from, const bool do_action) +bool BKE_animdata_copy_id(ID *id_to, ID *id_from, const bool do_action) { AnimData *adt; if ((id_to && id_from) && (GS(id_to->name) != GS(id_from->name))) return false; - BKE_free_animdata(id_to); + BKE_animdata_free(id_to); adt = BKE_animdata_from_id(id_from); if (adt) { IdAdtTemplate *iat = (IdAdtTemplate *)id_to; - iat->adt = BKE_copy_animdata(adt, do_action); + iat->adt = BKE_animdata_copy(adt, do_action); } return true; } -void BKE_copy_animdata_id_action(ID *id) +void BKE_animdata_copy_id_action(ID *id) { AnimData *adt = BKE_animdata_from_id(id); if (adt) { @@ -426,7 +426,7 @@ void BKE_animdata_make_local(AnimData *adt) /* When duplicating data (i.e. objects), drivers referring to the original data will * get updated to point to the duplicated data (if drivers belong to the new data) */ -void BKE_relink_animdata(AnimData *adt) +void BKE_animdata_relink(AnimData *adt) { /* sanity check */ if (adt == NULL) @@ -571,7 +571,7 @@ void BKE_animdata_separate_by_basepath(ID *srcID, ID *dstID, ListBase *basepaths /* get animdata from src, and create for destination (if needed) */ srcAdt = BKE_animdata_from_id(srcID); - dstAdt = BKE_id_add_animdata(dstID); + dstAdt = BKE_animdata_add_id(dstID); if (ELEM(NULL, srcAdt, dstAdt)) { if (G.debug & G_DEBUG) @@ -1167,7 +1167,7 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u * i.e. pose.bones["Bone"] */ /* TODO: use BKE_animdata_main_cb for looping over all data */ -void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const char *oldName, const char *newName) +void BKE_animdata_fix_paths_rename_all(ID *ref_id, const char *prefix, const char *oldName, const char *newName) { Main *mainptr = G.main; ID *id; diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index f775b67eedb..9e209cb16b6 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -127,7 +127,7 @@ void BKE_armature_free(bArmature *arm) /* free animation data */ if (arm->adt) { - BKE_free_animdata(&arm->id); + BKE_animdata_free(&arm->id); arm->adt = NULL; } } diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 886df16d0ee..5b4d7ba8214 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -138,7 +138,7 @@ void BKE_camera_make_local(Camera *cam) void BKE_camera_free(Camera *ca) { - BKE_free_animdata((ID *)ca); + BKE_animdata_free((ID *)ca); } /******************************** Camera Usage *******************************/ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index b6a167da53d..5fcdc9c2e78 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -147,7 +147,7 @@ void BKE_curve_free(Curve *cu) BKE_curve_editNurb_free(cu); BKE_curve_unlink(cu); - BKE_free_animdata((ID *)cu); + BKE_animdata_free((ID *)cu); if (cu->mat) MEM_freeN(cu->mat); diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index dd2155505fb..17d87394118 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -119,7 +119,7 @@ void BKE_gpencil_free(bGPdata *gpd) /* free animation data */ if (gpd->adt) { - BKE_free_animdata(&gpd->id); + BKE_animdata_free(&gpd->id); gpd->adt = NULL; } } diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 09ce9484a69..6d37f3ae006 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1712,7 +1712,7 @@ void do_versions_ipos_to_animato(Main *main) /* check if object has any animation data */ if (ob->nlastrips.first) { /* Add AnimData block */ - BKE_id_add_animdata(id); + BKE_animdata_add_id(id); /* IPO first to take into any non-NLA'd Object Animation */ if (ob->ipo) { @@ -1735,7 +1735,7 @@ void do_versions_ipos_to_animato(Main *main) } else if ((ob->ipo) || (ob->action)) { /* Add AnimData block */ - AnimData *adt = BKE_id_add_animdata(id); + AnimData *adt = BKE_animdata_add_id(id); /* Action first - so that Action name get conserved */ if (ob->action) { @@ -1776,7 +1776,7 @@ void do_versions_ipos_to_animato(Main *main) /* check PoseChannels for constraints with local data */ if (ob->pose) { /* Verify if there's AnimData block */ - BKE_id_add_animdata(id); + BKE_animdata_add_id(id); for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { for (con = pchan->constraints.first; con; con = con->next) { @@ -1802,7 +1802,7 @@ void do_versions_ipos_to_animato(Main *main) */ if (con->ipo) { /* Verify if there's AnimData block, just in case */ - BKE_id_add_animdata(id); + BKE_animdata_add_id(id); /* although this was the constraint's local IPO, we still need to provide con * so that drivers can be added properly... @@ -1819,7 +1819,7 @@ void do_versions_ipos_to_animato(Main *main) /* check constraint channels - we need to remove them anyway... */ if (ob->constraintChannels.first) { /* Verify if there's AnimData block */ - BKE_id_add_animdata(id); + BKE_animdata_add_id(id); for (conchan = ob->constraintChannels.first; conchan; conchan = conchann) { /* get pointer to next Constraint Channel */ @@ -1857,7 +1857,7 @@ void do_versions_ipos_to_animato(Main *main) */ if (key->ipo) { /* Add AnimData block */ - AnimData *adt = BKE_id_add_animdata(id); + AnimData *adt = BKE_animdata_add_id(id); /* Convert Shapekey data... */ ipo_to_animdata(id, key->ipo, NULL, NULL, NULL); @@ -1879,7 +1879,7 @@ void do_versions_ipos_to_animato(Main *main) /* we're only interested in the IPO */ if (ma->ipo) { /* Add AnimData block */ - AnimData *adt = BKE_id_add_animdata(id); + AnimData *adt = BKE_animdata_add_id(id); /* Convert Material data... */ ipo_to_animdata(id, ma->ipo, NULL, NULL, NULL); @@ -1901,7 +1901,7 @@ void do_versions_ipos_to_animato(Main *main) /* we're only interested in the IPO */ if (wo->ipo) { /* Add AnimData block */ - AnimData *adt = BKE_id_add_animdata(id); + AnimData *adt = BKE_animdata_add_id(id); /* Convert World data... */ ipo_to_animdata(id, wo->ipo, NULL, NULL, NULL); @@ -1921,7 +1921,7 @@ void do_versions_ipos_to_animato(Main *main) if (ed && ed->seqbasep) { Sequence *seq; - AnimData *adt = BKE_id_add_animdata(id); + AnimData *adt = BKE_animdata_add_id(id); SEQ_BEGIN(ed, seq) { @@ -1977,7 +1977,7 @@ void do_versions_ipos_to_animato(Main *main) /* we're only interested in the IPO */ if (te->ipo) { /* Add AnimData block */ - AnimData *adt = BKE_id_add_animdata(id); + AnimData *adt = BKE_animdata_add_id(id); /* Convert Texture data... */ ipo_to_animdata(id, te->ipo, NULL, NULL, NULL); @@ -1999,7 +1999,7 @@ void do_versions_ipos_to_animato(Main *main) /* we're only interested in the IPO */ if (ca->ipo) { /* Add AnimData block */ - AnimData *adt = BKE_id_add_animdata(id); + AnimData *adt = BKE_animdata_add_id(id); /* Convert Camera data... */ ipo_to_animdata(id, ca->ipo, NULL, NULL, NULL); @@ -2021,7 +2021,7 @@ void do_versions_ipos_to_animato(Main *main) /* we're only interested in the IPO */ if (la->ipo) { /* Add AnimData block */ - AnimData *adt = BKE_id_add_animdata(id); + AnimData *adt = BKE_animdata_add_id(id); /* Convert Lamp data... */ ipo_to_animdata(id, la->ipo, NULL, NULL, NULL); @@ -2043,7 +2043,7 @@ void do_versions_ipos_to_animato(Main *main) /* we're only interested in the IPO */ if (cu->ipo) { /* Add AnimData block */ - AnimData *adt = BKE_id_add_animdata(id); + AnimData *adt = BKE_animdata_add_id(id); /* Convert Curve data... */ ipo_to_animdata(id, cu->ipo, NULL, NULL, NULL); diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 560a3c0726b..3aea343ec5a 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -77,7 +77,7 @@ void BKE_key_free(Key *key) { KeyBlock *kb; - BKE_free_animdata((ID *)key); + BKE_animdata_free((ID *)key); while ((kb = BLI_pophead(&key->block))) { if (kb->data) diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 93b9c22566d..96b0b95adf3 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -221,7 +221,7 @@ void BKE_lamp_free(Lamp *la) if (mtex) MEM_freeN(mtex); } - BKE_free_animdata((ID *)la); + BKE_animdata_free((ID *)la); curvemapping_free(la->curfalloff); diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 4cf99dc173c..73dca9436ef 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -307,7 +307,7 @@ void BKE_lattice_free(Lattice *lt) /* free animation data */ if (lt->adt) { - BKE_free_animdata(<->id); + BKE_animdata_free(<->id); lt->adt = NULL; } } diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 9cda4d91933..2cee08a821b 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -432,7 +432,7 @@ bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop) if (RNA_property_editable(ptr, prop)) { if (id_copy(id, &newid, false) && newid) { /* copy animation actions too */ - BKE_copy_animdata_id_action(id); + BKE_animdata_copy_id_action(id); /* us is 1 by convention, but RNA_property_pointer_set * will also increment it, so set it to zero */ newid->us = 0; @@ -785,7 +785,7 @@ static void id_copy_animdata(ID *id, const bool do_action) if (adt) { IdAdtTemplate *iat = (IdAdtTemplate *)id; - iat->adt = BKE_copy_animdata(iat->adt, do_action); /* could be set to false, need to investigate */ + iat->adt = BKE_animdata_copy(iat->adt, do_action); /* could be set to false, need to investigate */ } } diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index 28b7ceded67..40db411ef4c 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -135,7 +135,7 @@ void BKE_linestyle_free(FreestyleLineStyle *linestyle) MEM_freeN(linestyle->nodetree); } - BKE_free_animdata(&linestyle->id); + BKE_animdata_free(&linestyle->id); while ((m = (LineStyleModifier *)linestyle->color_modifiers.first)) BKE_linestyle_color_modifier_remove(linestyle, m); while ((m = (LineStyleModifier *)linestyle->alpha_modifiers.first)) diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 9b682f101ad..b5b7f3d06aa 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -99,7 +99,7 @@ void BKE_material_free_ex(Material *ma, bool do_id_user) if (ma->ramp_col) MEM_freeN(ma->ramp_col); if (ma->ramp_spec) MEM_freeN(ma->ramp_spec); - BKE_free_animdata((ID *)ma); + BKE_animdata_free((ID *)ma); if (ma->preview) BKE_previewimg_free(&ma->preview); diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 25031183545..8728e6f98d5 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -83,7 +83,7 @@ void BKE_mball_free(MetaBall *mb) BKE_mball_unlink(mb); if (mb->adt) { - BKE_free_animdata((ID *)mb); + BKE_animdata_free((ID *)mb); mb->adt = NULL; } if (mb->mat) MEM_freeN(mb->mat); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index adce6e15732..840ef473691 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -463,7 +463,7 @@ void BKE_mesh_free(Mesh *me, int unlink) CustomData_free(&me->pdata, me->totpoly); if (me->adt) { - BKE_free_animdata(&me->id); + BKE_animdata_free(&me->id); me->adt = NULL; } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 73f75f4f96d..1aeb7bed86c 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1168,7 +1168,7 @@ static void free_buffers(MovieClip *clip) clip->anim = NULL; } - BKE_free_animdata((ID *) clip); + BKE_animdata_free((ID *) clip); } void BKE_movieclip_clear_cache(MovieClip *clip) diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index ac79e13ac83..7f3db700534 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1733,7 +1733,7 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const bool do_id_user) /* unregister associated RNA types */ ntreeInterfaceTypeFree(ntree); - BKE_free_animdata((ID *)ntree); + BKE_animdata_free((ID *)ntree); id_us_min((ID *)ntree->gpd); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index b3607d38014..9e771b3d39e 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -408,7 +408,7 @@ void BKE_object_free_ex(Object *ob, bool do_id_user) ob->iuser = NULL; if (ob->bb) MEM_freeN(ob->bb); ob->bb = NULL; - if (ob->adt) BKE_free_animdata((ID *)ob); + if (ob->adt) BKE_animdata_free((ID *)ob); if (ob->poselib) ob->poselib->id.us--; if (ob->gpd) ((ID *)ob->gpd)->us--; if (ob->defbase.first) @@ -1707,7 +1707,7 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target) /* add new animdata block */ if (!ob->adt) - ob->adt = BKE_id_add_animdata(&ob->id); + ob->adt = BKE_animdata_add_id(&ob->id); /* make a copy of all the drivers (for now), then correct any links that need fixing */ free_fcurves(&ob->adt->drivers); @@ -3731,7 +3731,7 @@ void BKE_object_relink(Object *ob) modifiers_foreachIDLink(ob, copy_object__forwardModifierLinks, NULL); if (ob->adt) - BKE_relink_animdata(ob->adt); + BKE_animdata_relink(ob->adt); if (ob->rigidbody_constraint) BKE_rigidbody_relink_constraint(ob->rigidbody_constraint); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 5d553f5deee..8d3f92182d4 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -375,7 +375,7 @@ void BKE_particlesettings_free(ParticleSettings *part) { MTex *mtex; int a; - BKE_free_animdata(&part->id); + BKE_animdata_free(&part->id); if (part->clumpcurve) curvemapping_free(part->clumpcurve); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index f51dadf1da6..3b48de13553 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -224,7 +224,7 @@ Scene *BKE_scene_copy(Scene *sce, int type) sizeof(scen->sequencer_colorspace_settings.name)); /* copy action and remove animation used by sequencer */ - BKE_copy_animdata_id_action(&scen->id); + BKE_animdata_copy_id_action(&scen->id); if (type != SCE_COPY_FULL) remove_sequencer_fcurves(scen); @@ -300,7 +300,7 @@ Scene *BKE_scene_copy(Scene *sce, int type) if (scen->world) { id_us_plus((ID *)scen->world); scen->world = BKE_world_copy(scen->world); - BKE_copy_animdata_id_action((ID *)scen->world); + BKE_animdata_copy_id_action((ID *)scen->world); } if (sce->ed) { @@ -361,7 +361,7 @@ void BKE_scene_free(Scene *sce) BLI_freelistN(&sce->base); BKE_sequencer_editing_free(sce); - BKE_free_animdata((ID *)sce); + BKE_animdata_free((ID *)sce); BKE_keyingsets_free(&sce->keyingsets); if (sce->rigidbody_world) diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c index b11d0ae03b0..7a800555144 100644 --- a/source/blender/blenkernel/intern/speaker.c +++ b/source/blender/blenkernel/intern/speaker.c @@ -130,5 +130,5 @@ void BKE_speaker_free(Speaker *spk) if (spk->sound) spk->sound->id.us--; - BKE_free_animdata((ID *)spk); + BKE_animdata_free((ID *)spk); } diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 7e7bcace30d..8e4fcc5d1cc 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -564,7 +564,7 @@ void BKE_texture_free(Tex *tex) if (tex->pd) BKE_texture_pointdensity_free(tex->pd); if (tex->vd) BKE_texture_voxeldata_free(tex->vd); if (tex->ot) BKE_texture_ocean_free(tex->ot); - BKE_free_animdata((struct ID *)tex); + BKE_animdata_free((struct ID *)tex); BKE_previewimg_free(&tex->preview); BKE_icon_delete((struct ID *)tex); diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 699e0d34161..f26cbf7880a 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -63,7 +63,7 @@ void BKE_world_free_ex(World *wrld, bool do_id_user) } BKE_previewimg_free(&wrld->preview); - BKE_free_animdata((ID *)wrld); + BKE_animdata_free((ID *)wrld); /* is no lib link block, but world extension */ if (wrld->nodetree) { diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 1782152560a..4828343fa0e 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -2117,7 +2117,7 @@ static int animchannels_clean_empty_exec(bContext *C, wmOperator *UNUSED(op)) /* remove AnimData? */ if (action_empty && nla_empty && drivers_empty) { - BKE_free_animdata(id); + BKE_animdata_free(id); } } diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 67ba82f1858..08e0daf8eb9 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -84,7 +84,7 @@ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_inde /* init animdata if none available yet */ adt = BKE_animdata_from_id(id); if ((adt == NULL) && (add)) - adt = BKE_id_add_animdata(id); + adt = BKE_animdata_add_id(id); if (adt == NULL) { /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ return NULL; diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 78509dd6079..64ced437142 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -130,7 +130,7 @@ bAction *verify_adt_action(ID *id, short add) /* init animdata if none available yet */ adt = BKE_animdata_from_id(id); if ((adt == NULL) && (add)) - adt = BKE_id_add_animdata(id); + adt = BKE_animdata_add_id(id); if (adt == NULL) { /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ printf("ERROR: Couldn't add AnimData (ID = %s)\n", (id) ? (id->name) : ""); diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index 177fb6c9118..eedff896315 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -270,7 +270,7 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n // XXX: the ID here is for armatures, but most bone drivers are actually on the object instead... { - BKE_all_animdata_fix_paths_rename(&arm->id, "pose.bones", oldname, newname); + BKE_animdata_fix_paths_rename_all(&arm->id, "pose.bones", oldname, newname); } /* correct view locking */ diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index ad9715d2ab2..cee34257b2c 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -380,7 +380,7 @@ int join_armature_exec(bContext *C, wmOperator *op) if (base->object->adt) { if (ob->adt == NULL) { /* no animdata, so just use a copy of the whole thing */ - ob->adt = BKE_copy_animdata(base->object->adt, false); + ob->adt = BKE_animdata_copy(base->object->adt, false); } else { /* merge in data - we'll fix the drivers manually */ @@ -391,7 +391,7 @@ int join_armature_exec(bContext *C, wmOperator *op) if (curarm->adt) { if (arm->adt == NULL) { /* no animdata, so just use a copy of the whole thing */ - arm->adt = BKE_copy_animdata(curarm->adt, false); + arm->adt = BKE_animdata_copy(curarm->adt, false); } else { /* merge in data - we'll fix the drivers manually */ diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 99b351561c7..37faa7ba664 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1051,7 +1051,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) */ { /* create new data for NLA hierarchy */ - AnimData *adt = BKE_id_add_animdata(&ob->id); + AnimData *adt = BKE_animdata_add_id(&ob->id); NlaTrack *nlt = add_nlatrack(adt, NULL); NlaStrip *strip = add_nla_soundstrip(scene, ob->data); strip->start = CFRA; @@ -1358,7 +1358,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, basen->object = ob; /* make sure apply works */ - BKE_free_animdata(&ob->id); + BKE_animdata_free(&ob->id); ob->adt = NULL; /* Proxies are not to be copied. */ @@ -1976,7 +1976,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base /* duplicates using userflags */ if (dupflag & USER_DUP_ACT) { - BKE_copy_animdata_id_action(&obn->id); + BKE_animdata_copy_id_action(&obn->id); } if (dupflag & USER_DUP_MAT) { @@ -1989,7 +1989,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base id->us--; if (dupflag & USER_DUP_ACT) { - BKE_copy_animdata_id_action(&obn->mat[a]->id); + BKE_animdata_copy_id_action(&obn->mat[a]->id); } } } @@ -2004,7 +2004,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base psys->part = BKE_particlesettings_copy(psys->part); if (dupflag & USER_DUP_ACT) { - BKE_copy_animdata_id_action(&psys->part->id); + BKE_animdata_copy_id_action(&psys->part->id); } id->us--; @@ -2132,9 +2132,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag & USER_DUP_ACT) { bActuator *act; - BKE_copy_animdata_id_action((ID *)obn->data); + BKE_animdata_copy_id_action((ID *)obn->data); if (key) { - BKE_copy_animdata_id_action((ID *)key); + BKE_animdata_copy_id_action((ID *)key); } /* Update the duplicated action in the action actuators */ diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index bfa501c3732..2d981594524 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1574,13 +1574,13 @@ static int make_links_data_exec(bContext *C, wmOperator *op) DAG_id_tag_update(&ob_dst->id, 0); break; case MAKE_LINKS_ANIMDATA: - BKE_copy_animdata_id((ID *)ob_dst, (ID *)ob_src, false); + BKE_animdata_copy_id((ID *)ob_dst, (ID *)ob_src, false); if (ob_dst->data && ob_src->data) { if (obdata_id->lib) { is_lib = true; break; } - BKE_copy_animdata_id((ID *)ob_dst->data, (ID *)ob_src->data, false); + BKE_animdata_copy_id((ID *)ob_dst->data, (ID *)ob_src->data, false); } DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); break; @@ -1871,7 +1871,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) case OB_MESH: ob->data = me = BKE_mesh_copy(ob->data); if (me->key) - BKE_copy_animdata_id_action((ID *)me->key); + BKE_animdata_copy_id_action((ID *)me->key); break; case OB_MBALL: ob->data = BKE_mball_copy(ob->data); @@ -1883,12 +1883,12 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) ID_NEW(cu->bevobj); ID_NEW(cu->taperobj); if (cu->key) - BKE_copy_animdata_id_action((ID *)cu->key); + BKE_animdata_copy_id_action((ID *)cu->key); break; case OB_LATTICE: ob->data = lat = BKE_lattice_copy(ob->data); if (lat->key) - BKE_copy_animdata_id_action((ID *)lat->key); + BKE_animdata_copy_id_action((ID *)lat->key); break; case OB_ARMATURE: DAG_id_tag_update(&ob->id, OB_RECALC_DATA); @@ -1909,7 +1909,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) * AnimData structure, which is not what we want. * (sergey) */ - BKE_copy_animdata_id_action((ID *)ob->data); + BKE_animdata_copy_id_action((ID *)ob->data); id->us--; id->newid = ob->data; @@ -1933,7 +1933,7 @@ static void single_object_action_users(Scene *scene, const int flag) ob = base->object; if (ob->id.lib == NULL && (flag == 0 || (base->flag & SELECT)) ) { DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - BKE_copy_animdata_id_action(&ob->id); + BKE_animdata_copy_id_action(&ob->id); } } } @@ -1956,7 +1956,7 @@ static void single_mat_users(Scene *scene, const int flag, const bool do_texture if (ma->id.us > 1) { man = BKE_material_copy(ma); - BKE_copy_animdata_id_action(&man->id); + BKE_animdata_copy_id_action(&man->id); man->id.us = 0; assign_material(ob, man, a, BKE_MAT_ASSIGN_USERPREF); @@ -1967,7 +1967,7 @@ static void single_mat_users(Scene *scene, const int flag, const bool do_texture if (tex->id.us > 1) { tex->id.us--; tex = BKE_texture_copy(tex); - BKE_copy_animdata_id_action(&tex->id); + BKE_animdata_copy_id_action(&tex->id); man->mtex[b]->tex = tex; } } @@ -1994,7 +1994,7 @@ static void do_single_tex_user(Tex **from) } else if (tex->id.us > 1) { texn = BKE_texture_copy(tex); - BKE_copy_animdata_id_action(&texn->id); + BKE_animdata_copy_id_action(&texn->id); tex->id.newid = (ID *)texn; tex->id.us--; *from = texn; diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 70d9bfe99fe..4ed4a3f9514 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -771,7 +771,7 @@ static int nlaedit_objects_add_exec(bContext *C, wmOperator *UNUSED(op)) CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { /* ensure that object has AnimData... that's all */ - BKE_id_add_animdata(&ob->id); + BKE_animdata_add_id(&ob->id); } CTX_DATA_END; diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index af21478150b..e5833103658 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -467,7 +467,7 @@ void outliner_do_object_operation(bContext *C, Scene *scene_act, SpaceOops *soop static void clear_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te), TreeStoreElem *tselem, void *UNUSED(arg)) { - BKE_free_animdata(tselem->id); + BKE_animdata_free(tselem->id); } diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 009e3799c49..8632467281a 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -598,12 +598,12 @@ static void rna_def_ID(BlenderRNA *brna) RNA_def_function_ui_description(func, "Clear the user count of a datablock so its not saved, " "on reload the data will be removed"); - func = RNA_def_function(srna, "animation_data_create", "BKE_id_add_animdata"); + func = RNA_def_function(srna, "animation_data_create", "BKE_animdata_add_id"); RNA_def_function_ui_description(func, "Create animation data to this ID, note that not all ID types support this"); parm = RNA_def_pointer(func, "anim_data", "AnimData", "", "New animation data or NULL"); RNA_def_function_return(func, parm); - func = RNA_def_function(srna, "animation_data_clear", "BKE_free_animdata"); + func = RNA_def_function(srna, "animation_data_clear", "BKE_animdata_free"); RNA_def_function_ui_description(func, "Clear animation on this this ID"); func = RNA_def_function(srna, "update_tag", "rna_ID_update_tag"); diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index e4aa21867e7..2cff8cfb376 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -241,7 +241,7 @@ static void rna_Constraint_name_set(PointerRNA *ptr, const char *value) } /* fix all the animation data which may link to this */ - BKE_all_animdata_fix_paths_rename(NULL, "constraints", oldname, con->name); + BKE_animdata_fix_paths_rename_all(NULL, "constraints", oldname, con->name); } static char *rna_Constraint_path(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c index 8a3626de81d..249d132068c 100644 --- a/source/blender/makesrna/intern/rna_key.c +++ b/source/blender/makesrna/intern/rna_key.c @@ -89,7 +89,7 @@ static void rna_ShapeKey_name_set(PointerRNA *ptr, const char *value) } /* fix all the animation data which may link to this */ - BKE_all_animdata_fix_paths_rename(NULL, "key_blocks", oldname, kb->name); + BKE_animdata_fix_paths_rename_all(NULL, "key_blocks", oldname, kb->name); } static float rna_ShapeKey_frame_get(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 93f29dbee66..8d0e95504a8 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -408,7 +408,7 @@ static void rna_Modifier_name_set(PointerRNA *ptr, const char *value) } /* fix all the animation data which may link to this */ - BKE_all_animdata_fix_paths_rename(NULL, "modifiers", oldname, md->name); + BKE_animdata_fix_paths_rename_all(NULL, "modifiers", oldname, md->name); } static char *rna_Modifier_path(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 90ee9e1d7d9..e577f7635f1 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1549,7 +1549,7 @@ static void rna_Node_name_set(PointerRNA *ptr, const char *value) nodeUniqueName(ntree, node); /* fix all the animation data which may link to this */ - BKE_all_animdata_fix_paths_rename(NULL, "nodes", oldname, node->name); + BKE_animdata_fix_paths_rename_all(NULL, "nodes", oldname, node->name); } static bNodeSocket *rna_Node_inputs_new(ID *id, bNode *node, ReportList *reports, const char *type, const char *name, const char *identifier) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 700d1aa91ea..c9d1a4b6429 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1251,7 +1251,7 @@ static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value) } /* fix all the animation data which may link to this */ - BKE_all_animdata_fix_paths_rename(NULL, "render.layers", oldname, rl->name); + BKE_animdata_fix_paths_rename_all(NULL, "render.layers", oldname, rl->name); } static char *rna_SceneRenderLayer_path(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 0d46924c129..fc9a501dae8 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -485,7 +485,7 @@ static void rna_Sequence_name_set(PointerRNA *ptr, const char *value) /* fix all the animation data which may link to this */ /* don't rename everywhere because these are per scene */ - /* BKE_all_animdata_fix_paths_rename(NULL, "sequence_editor.sequences_all", oldname, seq->name + 2); */ + /* BKE_animdata_fix_paths_rename_all(NULL, "sequence_editor.sequences_all", oldname, seq->name + 2); */ adt = BKE_animdata_from_id(&scene->id); if (adt) BKE_animdata_fix_paths_rename(&scene->id, adt, NULL, "sequence_editor.sequences_all", oldname, seq->name + 2, 0, 0, 1); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 8e262df7e67..6aaa947e9e4 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -1117,12 +1117,12 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *UNUSED(bmain), Scene *s if (saction->mode == SACTCONT_ACTION) { /* TODO: context selector could help decide this with more control? */ - adt = BKE_id_add_animdata(&obact->id); /* this only adds if non-existent */ + adt = BKE_animdata_add_id(&obact->id); /* this only adds if non-existent */ } else if (saction->mode == SACTCONT_SHAPEKEY) { Key *key = BKE_key_from_object(obact); if (key) - adt = BKE_id_add_animdata(&key->id); /* this only adds if non-existent */ + adt = BKE_animdata_add_id(&key->id); /* this only adds if non-existent */ } /* set action */ -- cgit v1.2.3 From 7acd69958b336663e62f85deb50b3eb1da92cf95 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 4 Apr 2015 15:15:50 +1100 Subject: Cleanup: use BKE_sculptsession_* prefix --- source/blender/blenkernel/BKE_paint.h | 4 ++-- source/blender/blenkernel/intern/object.c | 4 ++-- source/blender/blenkernel/intern/paint.c | 8 ++++---- source/blender/editors/sculpt_paint/sculpt.c | 4 ++-- source/blender/editors/sculpt_paint/sculpt_undo.c | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index d5cd1fd5d3e..4d713449b17 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -194,8 +194,8 @@ typedef struct SculptSession { struct StrokeCache *cache; } SculptSession; -void BKE_free_sculptsession(struct Object *ob); -void BKE_free_sculptsession_deformMats(struct SculptSession *ss); +void BKE_sculptsession_free(struct Object *ob); +void BKE_sculptsession_free_deformMats(struct SculptSession *ss); void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder); void BKE_sculptsession_bm_to_me_for_render(struct Object *object); void BKE_sculpt_update_mesh_elements(struct Scene *scene, struct Sculpt *sd, struct Object *ob, diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 9e771b3d39e..c485e00ed69 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -434,7 +434,7 @@ void BKE_object_free_ex(Object *ob, bool do_id_user) if (ob->bsoft) bsbFree(ob->bsoft); if (ob->gpulamp.first) GPU_lamp_free(ob); - BKE_free_sculptsession(ob); + BKE_sculptsession_free(ob); if (ob->pc_ids.first) BLI_freelistN(&ob->pc_ids); @@ -3244,7 +3244,7 @@ void BKE_object_sculpt_modifiers_changed(Object *ob) ss->pbvh = NULL; } - BKE_free_sculptsession_deformMats(ob->sculpt); + BKE_sculptsession_free_deformMats(ob->sculpt); } else { PBVHNode **nodes; diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 07b3893c545..a5b608703d1 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -559,7 +559,7 @@ void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, cons } } -void BKE_free_sculptsession_deformMats(SculptSession *ss) +void BKE_sculptsession_free_deformMats(SculptSession *ss) { if (ss->orig_cos) MEM_freeN(ss->orig_cos); if (ss->deform_cos) MEM_freeN(ss->deform_cos); @@ -626,7 +626,7 @@ void BKE_sculptsession_bm_to_me_for_render(Object *object) } } -void BKE_free_sculptsession(Object *ob) +void BKE_sculptsession_free(Object *ob) { if (ob && ob->sculpt) { SculptSession *ss = ob->sculpt; @@ -804,7 +804,7 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, if (!ss->orig_cos) { int a; - BKE_free_sculptsession_deformMats(ss); + BKE_sculptsession_free_deformMats(ss); ss->orig_cos = (ss->kb) ? BKE_keyblock_convert_to_vertcos(ob, ss->kb) : BKE_mesh_vertexCos_get(me, NULL); @@ -817,7 +817,7 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, } } else { - BKE_free_sculptsession_deformMats(ss); + BKE_sculptsession_free_deformMats(ss); } if (ss->kb != NULL && ss->deform_cos == NULL) { diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 5c55ad1c63d..6ca368ea4f7 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -4912,7 +4912,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) /* Leave sculptmode */ ob->mode &= ~mode_flag; - BKE_free_sculptsession(ob); + BKE_sculptsession_free(ob); paint_cursor_delete_textures(); } @@ -4950,7 +4950,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) /* Create sculpt mode session data */ if (ob->sculpt) - BKE_free_sculptsession(ob); + BKE_sculptsession_free(ob); sculpt_init_session(scene, ob); diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index a4adbc6bca8..7b4e6109f1a 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -484,7 +484,7 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb) BKE_mesh_calc_normals_tessface(mesh->mvert, mesh->totvert, mesh->mface, mesh->totface, NULL); - BKE_free_sculptsession_deformMats(ss); + BKE_sculptsession_free_deformMats(ss); tag_update |= true; } -- cgit v1.2.3 From 12cede5ca3a1d4c13de9eda8cc2bac28bbbaca08 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 4 Apr 2015 15:18:52 +1100 Subject: Cleanup: use BKE_ocean_* prefix --- source/blender/blenkernel/BKE_ocean.h | 26 ++++++++------- source/blender/blenkernel/intern/ocean.c | 42 ++++++++++++------------- source/blender/editors/object/object_modifier.c | 12 +++---- source/blender/modifiers/intern/MOD_ocean.c | 22 ++++++------- 4 files changed, 52 insertions(+), 50 deletions(-) diff --git a/source/blender/blenkernel/BKE_ocean.h b/source/blender/blenkernel/BKE_ocean.h index b750d8b283a..9b1b937febf 100644 --- a/source/blender/blenkernel/BKE_ocean.h +++ b/source/blender/blenkernel/BKE_ocean.h @@ -74,13 +74,14 @@ typedef struct OceanCache { #define OCEAN_CACHING 1 #define OCEAN_CACHED 2 -struct Ocean *BKE_add_ocean(void); -void BKE_free_ocean_data(struct Ocean *oc); -void BKE_free_ocean(struct Ocean *oc); +struct Ocean *BKE_ocean_add(void); +void BKE_ocean_free_data(struct Ocean *oc); +void BKE_ocean_free(struct Ocean *oc); -void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V, float l, float A, float w, float damp, - float alignment, float depth, float time, short do_height_field, short do_chop, short do_normals, short do_jacobian, int seed); -void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount); +void BKE_ocean_init( + struct Ocean *o, int M, int N, float Lx, float Lz, float V, float l, float A, float w, float damp, + float alignment, float depth, float time, short do_height_field, short do_chop, short do_normals, short do_jacobian, int seed); +void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount); /* sampling the ocean surface */ float BKE_ocean_jminus_to_foam(float jminus, float coverage); @@ -92,16 +93,17 @@ void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j) /* ocean cache handling */ -struct OceanCache *BKE_init_ocean_cache(const char *bakepath, const char *relbase, - int start, int end, float wave_scale, - float chop_amount, float foam_coverage, float foam_fade, int resolution); -void BKE_simulate_ocean_cache(struct OceanCache *och, int frame); +struct OceanCache *BKE_ocean_init_cache( + const char *bakepath, const char *relbase, + int start, int end, float wave_scale, + float chop_amount, float foam_coverage, float foam_fade, int resolution); +void BKE_ocean_simulate_cache(struct OceanCache *och, int frame); -void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(void *, float progress, int *cancel), void *update_cb_data); +void BKE_ocean_bake(struct Ocean *o, struct OceanCache *och, void (*update_cb)(void *, float progress, int *cancel), void *update_cb_data); void BKE_ocean_cache_eval_uv(struct OceanCache *och, struct OceanResult *ocr, int f, float u, float v); void BKE_ocean_cache_eval_ij(struct OceanCache *och, struct OceanResult *ocr, int f, int i, int j); -void BKE_free_ocean_cache(struct OceanCache *och); +void BKE_ocean_free_cache(struct OceanCache *och); #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 12e82d3a34f..81460ecdcc9 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -494,7 +494,7 @@ void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j) BLI_rw_mutex_unlock(&oc->oceanmutex); } -void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount) +void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount) { int i, j; @@ -732,7 +732,7 @@ static void set_height_normalize_factor(struct Ocean *oc) oc->normalize_factor = 1.0; - BKE_simulate_ocean(oc, 0.0, 1.0, 0); + BKE_ocean_simulate(oc, 0.0, 1.0, 0); BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ); @@ -754,7 +754,7 @@ static void set_height_normalize_factor(struct Ocean *oc) oc->normalize_factor = res; } -struct Ocean *BKE_add_ocean(void) +struct Ocean *BKE_ocean_add(void) { Ocean *oc = MEM_callocN(sizeof(Ocean), "ocean sim data"); @@ -763,7 +763,7 @@ struct Ocean *BKE_add_ocean(void) return oc; } -void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V, float l, float A, float w, float damp, +void BKE_ocean_init(struct Ocean *o, int M, int N, float Lx, float Lz, float V, float l, float A, float w, float damp, float alignment, float depth, float time, short do_height_field, short do_chop, short do_normals, short do_jacobian, int seed) { @@ -900,7 +900,7 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V, BLI_rng_free(rng); } -void BKE_free_ocean_data(struct Ocean *oc) +void BKE_ocean_free_data(struct Ocean *oc) { if (!oc) return; @@ -962,11 +962,11 @@ void BKE_free_ocean_data(struct Ocean *oc) BLI_rw_mutex_unlock(&oc->oceanmutex); } -void BKE_free_ocean(struct Ocean *oc) +void BKE_ocean_free(struct Ocean *oc) { if (!oc) return; - BKE_free_ocean_data(oc); + BKE_ocean_free_data(oc); BLI_rw_mutex_end(&oc->oceanmutex); MEM_freeN(oc); @@ -1021,7 +1021,7 @@ MINLINE void value_to_rgba_unit_alpha(float r_rgba[4], const float value) r_rgba[3] = 1.0f; } -void BKE_free_ocean_cache(struct OceanCache *och) +void BKE_ocean_free_cache(struct OceanCache *och) { int i, f = 0; @@ -1111,7 +1111,7 @@ void BKE_ocean_cache_eval_ij(struct OceanCache *och, struct OceanResult *ocr, in } } -struct OceanCache *BKE_init_ocean_cache(const char *bakepath, const char *relbase, int start, int end, float wave_scale, +struct OceanCache *BKE_ocean_init_cache(const char *bakepath, const char *relbase, int start, int end, float wave_scale, float chop_amount, float foam_coverage, float foam_fade, int resolution) { OceanCache *och = MEM_callocN(sizeof(OceanCache), "ocean cache data"); @@ -1138,7 +1138,7 @@ struct OceanCache *BKE_init_ocean_cache(const char *bakepath, const char *relbas return och; } -void BKE_simulate_ocean_cache(struct OceanCache *och, int frame) +void BKE_ocean_simulate_cache(struct OceanCache *och, int frame) { char string[FILE_MAX]; int f = frame; @@ -1182,7 +1182,7 @@ void BKE_simulate_ocean_cache(struct OceanCache *och, int frame) } -void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(void *, float progress, int *cancel), +void BKE_ocean_bake(struct Ocean *o, struct OceanCache *och, void (*update_cb)(void *, float progress, int *cancel), void *update_cb_data) { /* note: some of these values remain uninitialized unless certain options @@ -1221,7 +1221,7 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v ibuf_disp = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat); ibuf_normal = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat); - BKE_simulate_ocean(o, och->time[i], och->wave_scale, och->chop_amount); + BKE_ocean_simulate(o, och->time[i], och->wave_scale, och->chop_amount); /* add new foam */ for (y = 0; y < res_y; y++) { @@ -1371,29 +1371,29 @@ void BKE_ocean_eval_ij(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr) { } -void BKE_simulate_ocean(struct Ocean *UNUSED(o), float UNUSED(t), float UNUSED(scale), float UNUSED(chop_amount)) +void BKE_ocean_simulate(struct Ocean *UNUSED(o), float UNUSED(t), float UNUSED(scale), float UNUSED(chop_amount)) { } -struct Ocean *BKE_add_ocean(void) +struct Ocean *BKE_ocean_add(void) { Ocean *oc = MEM_callocN(sizeof(Ocean), "ocean sim data"); return oc; } -void BKE_init_ocean(struct Ocean *UNUSED(o), int UNUSED(M), int UNUSED(N), float UNUSED(Lx), float UNUSED(Lz), +void BKE_ocean_init(struct Ocean *UNUSED(o), int UNUSED(M), int UNUSED(N), float UNUSED(Lx), float UNUSED(Lz), float UNUSED(V), float UNUSED(l), float UNUSED(A), float UNUSED(w), float UNUSED(damp), float UNUSED(alignment), float UNUSED(depth), float UNUSED(time), short UNUSED(do_height_field), short UNUSED(do_chop), short UNUSED(do_normals), short UNUSED(do_jacobian), int UNUSED(seed)) { } -void BKE_free_ocean_data(struct Ocean *UNUSED(oc)) +void BKE_ocean_free_data(struct Ocean *UNUSED(oc)) { } -void BKE_free_ocean(struct Ocean *oc) +void BKE_ocean_free(struct Ocean *oc) { if (!oc) return; MEM_freeN(oc); @@ -1403,7 +1403,7 @@ void BKE_free_ocean(struct Ocean *oc) /* ********* Baking/Caching ********* */ -void BKE_free_ocean_cache(struct OceanCache *och) +void BKE_ocean_free_cache(struct OceanCache *och) { if (!och) return; @@ -1420,7 +1420,7 @@ void BKE_ocean_cache_eval_ij(struct OceanCache *UNUSED(och), struct OceanResult { } -OceanCache *BKE_init_ocean_cache(const char *UNUSED(bakepath), const char *UNUSED(relbase), int UNUSED(start), +OceanCache *BKE_ocean_init_cache(const char *UNUSED(bakepath), const char *UNUSED(relbase), int UNUSED(start), int UNUSED(end), float UNUSED(wave_scale), float UNUSED(chop_amount), float UNUSED(foam_coverage), float UNUSED(foam_fade), int UNUSED(resolution)) { @@ -1429,11 +1429,11 @@ OceanCache *BKE_init_ocean_cache(const char *UNUSED(bakepath), const char *UNUSE return och; } -void BKE_simulate_ocean_cache(struct OceanCache *UNUSED(och), int UNUSED(frame)) +void BKE_ocean_simulate_cache(struct OceanCache *UNUSED(och), int UNUSED(frame)) { } -void BKE_bake_ocean(struct Ocean *UNUSED(o), struct OceanCache *UNUSED(och), +void BKE_ocean_bake(struct Ocean *UNUSED(o), struct OceanCache *UNUSED(och), void (*update_cb)(void *, float progress, int *cancel), void *UNUSED(update_cb_data)) { /* unused */ diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index ad02f78e7b6..9a0377d28ad 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -2045,7 +2045,7 @@ static void init_ocean_modifier_bake(struct Ocean *oc, struct OceanModifierData do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS); do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM); - BKE_init_ocean(oc, omd->resolution * omd->resolution, omd->resolution * omd->resolution, omd->spatial_size, omd->spatial_size, + BKE_ocean_init(oc, omd->resolution * omd->resolution, omd->resolution * omd->resolution, omd->spatial_size, omd->spatial_size, omd->wind_velocity, omd->smallest_wave, 1.0, omd->wave_direction, omd->damp, omd->wave_alignment, omd->depth, omd->time, do_heightfield, do_chop, do_normals, do_jacobian, @@ -2103,7 +2103,7 @@ static void oceanbake_startjob(void *customdata, short *stop, short *do_update, G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */ - BKE_bake_ocean(oj->ocean, oj->och, oceanbake_update, (void *)oj); + BKE_ocean_bake(oj->ocean, oj->och, oceanbake_update, (void *)oj); *do_update = true; *stop = 0; @@ -2114,7 +2114,7 @@ static void oceanbake_endjob(void *customdata) OceanBakeJob *oj = customdata; if (oj->ocean) { - BKE_free_ocean(oj->ocean); + BKE_ocean_free(oj->ocean); oj->ocean = NULL; } @@ -2145,7 +2145,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } - och = BKE_init_ocean_cache(omd->cachepath, modifier_path_relbase(ob), + och = BKE_ocean_init_cache(omd->cachepath, modifier_path_relbase(ob), omd->bakestart, omd->bakeend, omd->wave_scale, omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution); @@ -2179,11 +2179,11 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) } /* make a copy of ocean to use for baking - threadsafety */ - ocean = BKE_add_ocean(); + ocean = BKE_ocean_add(); init_ocean_modifier_bake(ocean, omd); #if 0 - BKE_bake_ocean(ocean, och); + BKE_ocean_bake(ocean, och); omd->oceancache = och; omd->cached = true; diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index 1c8dcdff46d..4cbe0967b01 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -48,14 +48,14 @@ static void init_cache_data(Object *ob, struct OceanModifierData *omd) { const char *relbase = modifier_path_relbase(ob); - omd->oceancache = BKE_init_ocean_cache(omd->cachepath, relbase, + omd->oceancache = BKE_ocean_init_cache(omd->cachepath, relbase, omd->bakestart, omd->bakeend, omd->wave_scale, omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution); } static void clear_cache_data(struct OceanModifierData *omd) { - BKE_free_ocean_cache(omd->oceancache); + BKE_ocean_free_cache(omd->oceancache); omd->oceancache = NULL; omd->cached = false; } @@ -72,8 +72,8 @@ static void init_ocean_modifier(struct OceanModifierData *omd) do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS); do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM); - BKE_free_ocean_data(omd->ocean); - BKE_init_ocean(omd->ocean, omd->resolution * omd->resolution, omd->resolution * omd->resolution, + BKE_ocean_free_data(omd->ocean); + BKE_ocean_init(omd->ocean, omd->resolution * omd->resolution, omd->resolution * omd->resolution, omd->spatial_size, omd->spatial_size, omd->wind_velocity, omd->smallest_wave, 1.0, omd->wave_direction, omd->damp, omd->wave_alignment, omd->depth, omd->time, @@ -85,7 +85,7 @@ static void simulate_ocean_modifier(struct OceanModifierData *omd) { if (!omd || !omd->ocean) return; - BKE_simulate_ocean(omd->ocean, omd->time, omd->wave_scale, omd->chop_amount); + BKE_ocean_simulate(omd->ocean, omd->time, omd->wave_scale, omd->chop_amount); } #endif /* WITH_OCEANSIM */ @@ -133,7 +133,7 @@ static void initData(ModifierData *md) omd->foam_fade = 0.98; omd->foamlayername[0] = '\0'; /* layer name empty by default */ - omd->ocean = BKE_add_ocean(); + omd->ocean = BKE_ocean_add(); init_ocean_modifier(omd); simulate_ocean_modifier(omd); #else /* WITH_OCEANSIM */ @@ -147,9 +147,9 @@ static void freeData(ModifierData *md) #ifdef WITH_OCEANSIM OceanModifierData *omd = (OceanModifierData *) md; - BKE_free_ocean(omd->ocean); + BKE_ocean_free(omd->ocean); if (omd->oceancache) - BKE_free_ocean_cache(omd->oceancache); + BKE_ocean_free_cache(omd->oceancache); #else /* WITH_OCEANSIM */ /* unused */ (void)md; @@ -195,7 +195,7 @@ static void copyData(ModifierData *md, ModifierData *target) tomd->bakeend = omd->bakeend; tomd->oceancache = NULL; - tomd->ocean = BKE_add_ocean(); + tomd->ocean = BKE_ocean_add(); init_ocean_modifier(tomd); simulate_ocean_modifier(tomd); #else /* WITH_OCEANSIM */ @@ -426,7 +426,7 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob, /* update modifier */ if (omd->refresh & MOD_OCEAN_REFRESH_ADD) - omd->ocean = BKE_add_ocean(); + omd->ocean = BKE_ocean_add(); if (omd->refresh & MOD_OCEAN_REFRESH_RESET) init_ocean_modifier(omd); if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE) @@ -437,7 +437,7 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob, /* do ocean simulation */ if (omd->cached == true) { if (!omd->oceancache) init_cache_data(ob, omd); - BKE_simulate_ocean_cache(omd->oceancache, md->scene->r.cfra); + BKE_ocean_simulate_cache(omd->oceancache, md->scene->r.cfra); } else { simulate_ocean_modifier(omd); -- cgit v1.2.3 From e5392069ccc444df56f0fbcdde82aba42d20daa7 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sat, 4 Apr 2015 07:46:28 +0200 Subject: Cleanup: Typo fix in HSV code. --- intern/cycles/kernel/svm/svm_hsv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/kernel/svm/svm_hsv.h b/intern/cycles/kernel/svm/svm_hsv.h index 4f3f5d5f091..1f2cad60df7 100644 --- a/intern/cycles/kernel/svm/svm_hsv.h +++ b/intern/cycles/kernel/svm/svm_hsv.h @@ -46,7 +46,7 @@ ccl_device void svm_node_hsv(KernelGlobals *kg, ShaderData *sd, float *stack, ui color.y = fac*color.y + (1.0f - fac)*in_color.y; color.z = fac*color.z + (1.0f - fac)*in_color.z; - /* Clamp color to prevent negative values cauzed by oversaturation. */ + /* Clamp color to prevent negative values caused by oversaturation. */ color.x = max(color.x, 0.0f); color.y = max(color.y, 0.0f); color.z = max(color.z, 0.0f); -- cgit v1.2.3 From eca22d076cb8a90d02f0ce0424d4333e2b6c2773 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 4 Apr 2015 17:15:33 +1100 Subject: Cleanup: move filelist out of storage Depends on imbuf, problematic for tests --- source/blender/blenlib/CMakeLists.txt | 1 + source/blender/blenlib/intern/BLI_filelist.c | 358 +++++++++++++++++++++++++++ source/blender/blenlib/intern/storage.c | 309 +---------------------- 3 files changed, 360 insertions(+), 308 deletions(-) create mode 100644 source/blender/blenlib/intern/BLI_filelist.c diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index eceec2ab850..73bd4869566 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -44,6 +44,7 @@ set(SRC intern/BLI_array.c intern/BLI_dial.c intern/BLI_dynstr.c + intern/BLI_filelist.c intern/BLI_ghash.c intern/BLI_heap.c intern/BLI_kdopbvh.c diff --git a/source/blender/blenlib/intern/BLI_filelist.c b/source/blender/blenlib/intern/BLI_filelist.c new file mode 100644 index 00000000000..f032b753a77 --- /dev/null +++ b/source/blender/blenlib/intern/BLI_filelist.c @@ -0,0 +1,358 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenlib/intern/filelist.c + * \ingroup bli + */ + +#include +#include +#include + +#ifndef WIN32 +# include +#endif + +#include +#include +#include /* strcpy etc.. */ + +#ifdef WIN32 +# include +# include +# include "BLI_winstuff.h" +# include "utfconv.h" +#else +# include +# include +# include +#endif + +/* lib includes */ +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" + +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_fileops.h" +#include "BLI_fileops_types.h" +#include "BLI_path_util.h" + +#include "../imbuf/IMB_imbuf.h" + + +/* + * Ordering function for sorting lists of files/directories. Returns -1 if + * entry1 belongs before entry2, 0 if they are equal, 1 if they should be swapped. + */ +static int bli_compare(struct direntry *entry1, struct direntry *entry2) +{ + /* type is equal to stat.st_mode */ + + /* directories come before non-directories */ + if (S_ISDIR(entry1->type)) { + if (S_ISDIR(entry2->type) == 0) return (-1); + } + else { + if (S_ISDIR(entry2->type)) return (1); + } + /* non-regular files come after regular files */ + if (S_ISREG(entry1->type)) { + if (S_ISREG(entry2->type) == 0) return (-1); + } + else { + if (S_ISREG(entry2->type)) return (1); + } + /* arbitrary, but consistent, ordering of different types of non-regular files */ + if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1); + if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1); + + /* OK, now we know their S_IFMT fields are the same, go on to a name comparison */ + /* make sure "." and ".." are always first */ + if (FILENAME_IS_CURRENT(entry1->relname)) return (-1); + if (FILENAME_IS_CURRENT(entry2->relname)) return (1); + if (FILENAME_IS_PARENT(entry1->relname)) return (-1); + if (FILENAME_IS_PARENT(entry2->relname)) return (1); + + return (BLI_natstrcmp(entry1->relname, entry2->relname)); +} + + +struct BuildDirCtx { + struct direntry *files; /* array[nrfiles] */ + int nrfiles; +}; + +/** + * Scans the directory named *dirname and appends entries for its contents to files. + */ +static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) +{ + struct ListBase dirbase = {NULL, NULL}; + int newnum = 0; + DIR *dir; + + if ((dir = opendir(dirname)) != NULL) { + const struct dirent *fname; + while ((fname = readdir(dir)) != NULL) { + struct dirlink * const dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); + if (dlink != NULL) { + dlink->name = BLI_strdup(fname->d_name); + BLI_addhead(&dirbase, dlink); + newnum++; + } + } + + if (newnum) { + if (dir_ctx->files) { + void * const tmp = MEM_reallocN(dir_ctx->files, (dir_ctx->nrfiles + newnum) * sizeof(struct direntry)); + if (tmp) { + dir_ctx->files = (struct direntry *)tmp; + } + else { /* realloc fail */ + MEM_freeN(dir_ctx->files); + dir_ctx->files = NULL; + } + } + + if (dir_ctx->files == NULL) + dir_ctx->files = (struct direntry *)MEM_mallocN(newnum * sizeof(struct direntry), __func__); + + if (dir_ctx->files) { + struct dirlink * dlink = (struct dirlink *) dirbase.first; + struct direntry *file = &dir_ctx->files[dir_ctx->nrfiles]; + while (dlink) { + char fullname[PATH_MAX]; + memset(file, 0, sizeof(struct direntry)); + file->relname = dlink->name; + file->path = BLI_strdupcat(dirname, dlink->name); + BLI_join_dirfile(fullname, sizeof(fullname), dirname, dlink->name); + if (BLI_stat(fullname, &file->s) != -1) { + file->type = file->s.st_mode; + } + file->flags = 0; + dir_ctx->nrfiles++; + file++; + dlink = dlink->next; + } + } + else { + printf("Couldn't get memory for dir\n"); + exit(1); + } + + BLI_freelist(&dirbase); + if (dir_ctx->files) { + qsort(dir_ctx->files, dir_ctx->nrfiles, sizeof(struct direntry), (int (*)(const void *, const void *))bli_compare); + } + } + else { + printf("%s empty directory\n", dirname); + } + + closedir(dir); + } + else { + printf("%s non-existent directory\n", dirname); + } +} + +/** + * Fills in the "mode[123]", "size" and "string" fields in the elements of the files + * array with descriptive details about each item. "string" will have a format similar to "ls -l". + */ +static void bli_adddirstrings(struct BuildDirCtx *dir_ctx) +{ + const char *types[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"}; + /* symbolic display, indexed by mode field value */ + int num; +#ifdef WIN32 + __int64 st_size; +#else + off_t st_size; + int mode; +#endif + + struct direntry *file; + struct tm *tm; + time_t zero = 0; + + for (num = 0, file = dir_ctx->files; num < dir_ctx->nrfiles; num++, file++) { + + + /* Mode */ +#ifdef WIN32 + BLI_strncpy(file->mode1, types[0], sizeof(file->mode1)); + BLI_strncpy(file->mode2, types[0], sizeof(file->mode2)); + BLI_strncpy(file->mode3, types[0], sizeof(file->mode3)); +#else + mode = file->s.st_mode; + + BLI_strncpy(file->mode1, types[(mode & 0700) >> 6], sizeof(file->mode1)); + BLI_strncpy(file->mode2, types[(mode & 0070) >> 3], sizeof(file->mode2)); + BLI_strncpy(file->mode3, types[(mode & 0007)], sizeof(file->mode3)); + + if (((mode & S_ISGID) == S_ISGID) && (file->mode2[2] == '-')) file->mode2[2] = 'l'; + + if (mode & (S_ISUID | S_ISGID)) { + if (file->mode1[2] == 'x') file->mode1[2] = 's'; + else file->mode1[2] = 'S'; + + if (file->mode2[2] == 'x') file->mode2[2] = 's'; + } + + if (mode & S_ISVTX) { + if (file->mode3[2] == 'x') file->mode3[2] = 't'; + else file->mode3[2] = 'T'; + } +#endif + + + /* User */ +#ifdef WIN32 + strcpy(file->owner, "user"); +#else + { + struct passwd *pwuser; + pwuser = getpwuid(file->s.st_uid); + if (pwuser) { + BLI_strncpy(file->owner, pwuser->pw_name, sizeof(file->owner)); + } + else { + BLI_snprintf(file->owner, sizeof(file->owner), "%u", file->s.st_uid); + } + } +#endif + + + /* Time */ + tm = localtime(&file->s.st_mtime); + // prevent impossible dates in windows + if (tm == NULL) tm = localtime(&zero); + strftime(file->time, sizeof(file->time), "%H:%M", tm); + strftime(file->date, sizeof(file->date), "%d-%b-%y", tm); + + + /* Size */ + /* + * Seems st_size is signed 32-bit value in *nix and Windows. This + * will buy us some time until files get bigger than 4GB or until + * everyone starts using __USE_FILE_OFFSET64 or equivalent. + */ + st_size = file->s.st_size; + + if (st_size > 1024 * 1024 * 1024) { + BLI_snprintf(file->size, sizeof(file->size), "%.2f GiB", ((double)st_size) / (1024 * 1024 * 1024)); + } + else if (st_size > 1024 * 1024) { + BLI_snprintf(file->size, sizeof(file->size), "%.1f MiB", ((double)st_size) / (1024 * 1024)); + } + else if (st_size > 1024) { + BLI_snprintf(file->size, sizeof(file->size), "%d KiB", (int)(st_size / 1024)); + } + else { + BLI_snprintf(file->size, sizeof(file->size), "%d B", (int)st_size); + } + } +} + +/** + * Scans the contents of the directory named *dirname, and allocates and fills in an + * array of entries describing them in *filelist. + * + * \return The length of filelist array. + */ +unsigned int BLI_filelist_dir_contents(const char *dirname, struct direntry **filelist) +{ + struct BuildDirCtx dir_ctx; + + dir_ctx.nrfiles = 0; + dir_ctx.files = NULL; + + bli_builddir(&dir_ctx, dirname); + bli_adddirstrings(&dir_ctx); + + if (dir_ctx.files) { + *filelist = dir_ctx.files; + } + else { + // keep blender happy. Blender stores this in a variable + // where 0 has special meaning..... + *filelist = MEM_mallocN(sizeof(**filelist), __func__); + } + + return dir_ctx.nrfiles; +} + +/** + * Deep-duplicate of an array of direntries, including the array itself. + * + * \param dup_poin If given, called for each non-NULL direntry->poin. Otherwise, pointer is always simply copied over. + */ +void BLI_filelist_duplicate( + struct direntry **dest_filelist, struct direntry *src_filelist, unsigned int nrentries, + void *(*dup_poin)(void *)) +{ + unsigned int i; + + *dest_filelist = MEM_mallocN(sizeof(**dest_filelist) * (size_t)(nrentries), __func__); + for (i = 0; i < nrentries; ++i) { + struct direntry * const src = &src_filelist[i]; + struct direntry *dest = &(*dest_filelist)[i]; + *dest = *src; + if (dest->image) { + dest->image = IMB_dupImBuf(src->image); + } + if (dest->relname) { + dest->relname = MEM_dupallocN(src->relname); + } + if (dest->path) { + dest->path = MEM_dupallocN(src->path); + } + if (dest->poin && dup_poin) { + dest->poin = dup_poin(src->poin); + } + } +} + +/** + * frees storage for an array of direntries, including the array itself. + */ +void BLI_filelist_free(struct direntry *filelist, unsigned int nrentries, void (*free_poin)(void *)) +{ + unsigned int i; + for (i = 0; i < nrentries; ++i) { + struct direntry *entry = filelist + i; + if (entry->image) { + IMB_freeImBuf(entry->image); + } + if (entry->relname) + MEM_freeN(entry->relname); + if (entry->path) + MEM_freeN(entry->path); + if (entry->poin && free_poin) + free_poin(entry->poin); + } + + if (filelist != NULL) { + MEM_freeN(filelist); + } +} diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 46c5a11949c..046dba26c69 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -35,11 +35,6 @@ #include #include -#ifndef WIN32 -# include -#endif - -#include #include #if defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun__) || defined(__sun) @@ -79,17 +74,13 @@ /* lib includes */ #include "MEM_guardedalloc.h" -#include "DNA_listBase.h" - -#include "BLI_listbase.h" +#include "BLI_utildefines.h" #include "BLI_linklist.h" #include "BLI_string.h" #include "BLI_fileops.h" #include "BLI_fileops_types.h" #include "BLI_path_util.h" -#include "../imbuf/IMB_imbuf.h" - /** * Copies the current working directory into *dir (max size maxncpy), and * returns a pointer to same. @@ -107,42 +98,6 @@ char *BLI_current_working_dir(char *dir, const size_t maxncpy) return getcwd(dir, maxncpy); } -/* - * Ordering function for sorting lists of files/directories. Returns -1 if - * entry1 belongs before entry2, 0 if they are equal, 1 if they should be swapped. - */ -static int bli_compare(struct direntry *entry1, struct direntry *entry2) -{ - /* type is equal to stat.st_mode */ - - /* directories come before non-directories */ - if (S_ISDIR(entry1->type)) { - if (S_ISDIR(entry2->type) == 0) return (-1); - } - else { - if (S_ISDIR(entry2->type)) return (1); - } - /* non-regular files come after regular files */ - if (S_ISREG(entry1->type)) { - if (S_ISREG(entry2->type) == 0) return (-1); - } - else { - if (S_ISREG(entry2->type)) return (1); - } - /* arbitrary, but consistent, ordering of different types of non-regular files */ - if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1); - if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1); - - /* OK, now we know their S_IFMT fields are the same, go on to a name comparison */ - /* make sure "." and ".." are always first */ - if (FILENAME_IS_CURRENT(entry1->relname)) return (-1); - if (FILENAME_IS_CURRENT(entry2->relname)) return (1); - if (FILENAME_IS_PARENT(entry1->relname)) return (-1); - if (FILENAME_IS_PARENT(entry2->relname)) return (1); - - return (BLI_natstrcmp(entry1->relname, entry2->relname)); -} - /** * Returns the number of free bytes on the volume containing the specified pathname. */ /* Not actually used anywhere. @@ -204,267 +159,6 @@ double BLI_dir_free_space(const char *dir) #endif } -struct BuildDirCtx { - struct direntry *files; /* array[nrfiles] */ - int nrfiles; -}; - -/** - * Scans the directory named *dirname and appends entries for its contents to files. - */ -static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) -{ - struct ListBase dirbase = {NULL, NULL}; - int newnum = 0; - DIR *dir; - - if ((dir = opendir(dirname)) != NULL) { - const struct dirent *fname; - while ((fname = readdir(dir)) != NULL) { - struct dirlink * const dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); - if (dlink != NULL) { - dlink->name = BLI_strdup(fname->d_name); - BLI_addhead(&dirbase, dlink); - newnum++; - } - } - - if (newnum) { - if (dir_ctx->files) { - void * const tmp = MEM_reallocN(dir_ctx->files, (dir_ctx->nrfiles + newnum) * sizeof(struct direntry)); - if (tmp) { - dir_ctx->files = (struct direntry *)tmp; - } - else { /* realloc fail */ - MEM_freeN(dir_ctx->files); - dir_ctx->files = NULL; - } - } - - if (dir_ctx->files == NULL) - dir_ctx->files = (struct direntry *)MEM_mallocN(newnum * sizeof(struct direntry), __func__); - - if (dir_ctx->files) { - struct dirlink * dlink = (struct dirlink *) dirbase.first; - struct direntry *file = &dir_ctx->files[dir_ctx->nrfiles]; - while (dlink) { - char fullname[PATH_MAX]; - memset(file, 0, sizeof(struct direntry)); - file->relname = dlink->name; - file->path = BLI_strdupcat(dirname, dlink->name); - BLI_join_dirfile(fullname, sizeof(fullname), dirname, dlink->name); - if (BLI_stat(fullname, &file->s) != -1) { - file->type = file->s.st_mode; - } - file->flags = 0; - dir_ctx->nrfiles++; - file++; - dlink = dlink->next; - } - } - else { - printf("Couldn't get memory for dir\n"); - exit(1); - } - - BLI_freelist(&dirbase); - if (dir_ctx->files) { - qsort(dir_ctx->files, dir_ctx->nrfiles, sizeof(struct direntry), (int (*)(const void *, const void *))bli_compare); - } - } - else { - printf("%s empty directory\n", dirname); - } - - closedir(dir); - } - else { - printf("%s non-existent directory\n", dirname); - } -} - -/** - * Fills in the "mode[123]", "size" and "string" fields in the elements of the files - * array with descriptive details about each item. "string" will have a format similar to "ls -l". - */ -static void bli_adddirstrings(struct BuildDirCtx *dir_ctx) -{ - const char *types[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"}; - /* symbolic display, indexed by mode field value */ - int num; -#ifdef WIN32 - __int64 st_size; -#else - off_t st_size; - int mode; -#endif - - struct direntry *file; - struct tm *tm; - time_t zero = 0; - - for (num = 0, file = dir_ctx->files; num < dir_ctx->nrfiles; num++, file++) { - - - /* Mode */ -#ifdef WIN32 - BLI_strncpy(file->mode1, types[0], sizeof(file->mode1)); - BLI_strncpy(file->mode2, types[0], sizeof(file->mode2)); - BLI_strncpy(file->mode3, types[0], sizeof(file->mode3)); -#else - mode = file->s.st_mode; - - BLI_strncpy(file->mode1, types[(mode & 0700) >> 6], sizeof(file->mode1)); - BLI_strncpy(file->mode2, types[(mode & 0070) >> 3], sizeof(file->mode2)); - BLI_strncpy(file->mode3, types[(mode & 0007)], sizeof(file->mode3)); - - if (((mode & S_ISGID) == S_ISGID) && (file->mode2[2] == '-')) file->mode2[2] = 'l'; - - if (mode & (S_ISUID | S_ISGID)) { - if (file->mode1[2] == 'x') file->mode1[2] = 's'; - else file->mode1[2] = 'S'; - - if (file->mode2[2] == 'x') file->mode2[2] = 's'; - } - - if (mode & S_ISVTX) { - if (file->mode3[2] == 'x') file->mode3[2] = 't'; - else file->mode3[2] = 'T'; - } -#endif - - - /* User */ -#ifdef WIN32 - strcpy(file->owner, "user"); -#else - { - struct passwd *pwuser; - pwuser = getpwuid(file->s.st_uid); - if (pwuser) { - BLI_strncpy(file->owner, pwuser->pw_name, sizeof(file->owner)); - } - else { - BLI_snprintf(file->owner, sizeof(file->owner), "%u", file->s.st_uid); - } - } -#endif - - - /* Time */ - tm = localtime(&file->s.st_mtime); - // prevent impossible dates in windows - if (tm == NULL) tm = localtime(&zero); - strftime(file->time, sizeof(file->time), "%H:%M", tm); - strftime(file->date, sizeof(file->date), "%d-%b-%y", tm); - - - /* Size */ - /* - * Seems st_size is signed 32-bit value in *nix and Windows. This - * will buy us some time until files get bigger than 4GB or until - * everyone starts using __USE_FILE_OFFSET64 or equivalent. - */ - st_size = file->s.st_size; - - if (st_size > 1024 * 1024 * 1024) { - BLI_snprintf(file->size, sizeof(file->size), "%.2f GiB", ((double)st_size) / (1024 * 1024 * 1024)); - } - else if (st_size > 1024 * 1024) { - BLI_snprintf(file->size, sizeof(file->size), "%.1f MiB", ((double)st_size) / (1024 * 1024)); - } - else if (st_size > 1024) { - BLI_snprintf(file->size, sizeof(file->size), "%d KiB", (int)(st_size / 1024)); - } - else { - BLI_snprintf(file->size, sizeof(file->size), "%d B", (int)st_size); - } - } -} - -/** - * Scans the contents of the directory named *dirname, and allocates and fills in an - * array of entries describing them in *filelist. - * - * \return The length of filelist array. - */ -unsigned int BLI_filelist_dir_contents(const char *dirname, struct direntry **filelist) -{ - struct BuildDirCtx dir_ctx; - - dir_ctx.nrfiles = 0; - dir_ctx.files = NULL; - - bli_builddir(&dir_ctx, dirname); - bli_adddirstrings(&dir_ctx); - - if (dir_ctx.files) { - *filelist = dir_ctx.files; - } - else { - // keep blender happy. Blender stores this in a variable - // where 0 has special meaning..... - *filelist = MEM_mallocN(sizeof(**filelist), __func__); - } - - return dir_ctx.nrfiles; -} - -/** - * Deep-duplicate of an array of direntries, including the array itself. - * - * \param dup_poin If given, called for each non-NULL direntry->poin. Otherwise, pointer is always simply copied over. - */ -void BLI_filelist_duplicate( - struct direntry **dest_filelist, struct direntry *src_filelist, unsigned int nrentries, - void *(*dup_poin)(void *)) -{ - unsigned int i; - - *dest_filelist = MEM_mallocN(sizeof(**dest_filelist) * (size_t)(nrentries), __func__); - for (i = 0; i < nrentries; ++i) { - struct direntry * const src = &src_filelist[i]; - struct direntry *dest = &(*dest_filelist)[i]; - *dest = *src; - if (dest->image) { - dest->image = IMB_dupImBuf(src->image); - } - if (dest->relname) { - dest->relname = MEM_dupallocN(src->relname); - } - if (dest->path) { - dest->path = MEM_dupallocN(src->path); - } - if (dest->poin && dup_poin) { - dest->poin = dup_poin(src->poin); - } - } -} - -/** - * frees storage for an array of direntries, including the array itself. - */ -void BLI_filelist_free(struct direntry *filelist, unsigned int nrentries, void (*free_poin)(void *)) -{ - unsigned int i; - for (i = 0; i < nrentries; ++i) { - struct direntry *entry = filelist + i; - if (entry->image) { - IMB_freeImBuf(entry->image); - } - if (entry->relname) - MEM_freeN(entry->relname); - if (entry->path) - MEM_freeN(entry->path); - if (entry->poin && free_poin) - free_poin(entry->poin); - } - - if (filelist != NULL) { - MEM_freeN(filelist); - } -} - /** * Returns the file size of an opened file descriptor. @@ -674,4 +368,3 @@ bool BLI_file_older(const char *file1, const char *file2) #endif return (st1.st_mtime < st2.st_mtime); } - -- cgit v1.2.3 From e84b0e4c3518b7ea5914993d9c0ef0f28a0d76a4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 4 Apr 2015 17:20:17 +1100 Subject: Ghost: update tests for recent changes --- intern/ghost/test/CMakeLists.txt | 11 ++++++++++ intern/ghost/test/gears/GHOST_C-Test.c | 34 ++++++++++++---------------- intern/ghost/test/gears/GHOST_Test.cpp | 17 ++++++++++---- intern/ghost/test/multitest/MultiTest.c | 39 +++++++++++++++++++++++---------- 4 files changed, 65 insertions(+), 36 deletions(-) diff --git a/intern/ghost/test/CMakeLists.txt b/intern/ghost/test/CMakeLists.txt index 165f5b414b6..e1475966d47 100644 --- a/intern/ghost/test/CMakeLists.txt +++ b/intern/ghost/test/CMakeLists.txt @@ -115,6 +115,13 @@ suffix_relpaths(SRC_NEW "${SRC}" "../../../extern/wcwidth/") include_directories(${INC_NEW}) add_library(wcwidth_lib ${SRC_NEW}) +# glew-mx +include(${CMAKE_SOURCE_DIR}/../../../intern/glew-mx/CMakeLists.txt) +suffix_relpaths(INC_NEW "${INC}" "../../../intern/glew-mx/") +suffix_relpaths(SRC_NEW "${SRC}" "../../../intern/glew-mx/") +include_directories(${INC_NEW}) +add_library(glewmx_lib ${SRC_NEW}) + # grr, blenfont needs BLI include_directories( "../../../source/blender/blenlib" @@ -136,6 +143,7 @@ add_library(bli_lib "../../../source/blender/blenlib/intern/BLI_linklist.c" "../../../source/blender/blenlib/intern/BLI_memarena.c" "../../../source/blender/blenlib/intern/BLI_mempool.c" + "../../../source/blender/blenlib/intern/system.c" ) set(PLATFORM_CGLAGS) @@ -190,6 +198,7 @@ add_executable(gears_c target_link_libraries(gears_c ghost_lib + glewmx_lib string_lib ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} @@ -203,6 +212,7 @@ add_executable(gears_cpp target_link_libraries(gears_cpp ghost_lib + glewmx_lib string_lib ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} @@ -231,6 +241,7 @@ target_link_libraries(multitest_c blenfont_lib bli_lib ghost_lib + glewmx_lib string_lib guardedalloc_lib wcwidth_lib diff --git a/intern/ghost/test/gears/GHOST_C-Test.c b/intern/ghost/test/gears/GHOST_C-Test.c index 00ae4bb25b4..c635ab9be5b 100644 --- a/intern/ghost/test/gears/GHOST_C-Test.c +++ b/intern/ghost/test/gears/GHOST_C-Test.c @@ -448,6 +448,7 @@ int processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData) int main(int argc, char **argv) { + GHOST_GLSettings glSettings = {0}; char *title1 = "gears - main window"; char *title2 = "gears - secondary window"; GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(processEvent, NULL); @@ -459,16 +460,12 @@ int main(int argc, char **argv) if (shSystem) { /* Create the main window */ - sMainWindow = GHOST_CreateWindow(shSystem, - title1, - 10, - 64, - 320, - 200, - GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, - FALSE, - FALSE); + sMainWindow = GHOST_CreateWindow( + shSystem, title1, + 10, 64, 320, 200, + GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL, + glSettings); if (!sMainWindow) { printf("could not create main window\n"); @@ -476,16 +473,13 @@ int main(int argc, char **argv) } /* Create a secondary window */ - sSecondaryWindow = GHOST_CreateWindow(shSystem, - title2, - 340, - 64, - 320, - 200, - GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, - FALSE, - FALSE); + sSecondaryWindow = GHOST_CreateWindow( + shSystem, + title2, + 340, 64, 320, 200, + GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL, + glSettings); if (!sSecondaryWindow) { printf("could not create secondary window\n"); diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp index a81aaa85ecf..d6c8f25707c 100644 --- a/intern/ghost/test/gears/GHOST_Test.cpp +++ b/intern/ghost/test/gears/GHOST_Test.cpp @@ -418,12 +418,17 @@ Application::Application(GHOST_ISystem *system) m_gearsTimer(0), m_testTimer(0), m_cursor(GHOST_kStandardCursorFirstCursor), m_exitRequested(false), stereo(false) { + GHOST_GLSettings glSettings = {0}; fApp = this; // Create the main window STR_String title1("gears - main window"); - m_mainWindow = system->createWindow(title1, 10, 64, 320, 200, GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, false, false); + m_mainWindow = system->createWindow( + title1, + 10, 64, 320, 200, + GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL, + glSettings); if (!m_mainWindow) { std::cout << "could not create main window\n"; @@ -432,8 +437,12 @@ Application::Application(GHOST_ISystem *system) // Create a secondary window STR_String title2("gears - secondary window"); - m_secondaryWindow = system->createWindow(title2, 340, 64, 320, 200, GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, false, false); + m_secondaryWindow = system->createWindow( + title2, + 340, 64, 320, 200, + GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL, + glSettings); if (!m_secondaryWindow) { std::cout << "could not create secondary window\n"; exit(-1); diff --git a/intern/ghost/test/multitest/MultiTest.c b/intern/ghost/test/multitest/MultiTest.c index 9a192c17180..a5b5a511cb2 100644 --- a/intern/ghost/test/multitest/MultiTest.c +++ b/intern/ghost/test/multitest/MultiTest.c @@ -309,13 +309,18 @@ static void mainwindow_timer_proc(GHOST_TimerTaskHandle task, GHOST_TUns64 time) mainwindow_log(mw, buf); } -MainWindow *mainwindow_new(MultiTestApp *app) { +MainWindow *mainwindow_new(MultiTestApp *app) +{ GHOST_SystemHandle sys = multitestapp_get_system(app); GHOST_WindowHandle win; + GHOST_GLSettings glSettings = {0}; - win = GHOST_CreateWindow(sys, "MultiTest:Main", 40, 40, 400, 400, - GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL, - FALSE, FALSE); + win = GHOST_CreateWindow( + sys, "MultiTest:Main", + 40, 40, 400, 400, + GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL, + glSettings); if (win) { MainWindow *mw = MEM_callocN(sizeof(*mw), "mainwindow_new"); @@ -577,15 +582,20 @@ static void loggerwindow_handle(void *priv, GHOST_EventHandle evt) /**/ -LoggerWindow *loggerwindow_new(MultiTestApp *app) { +LoggerWindow *loggerwindow_new(MultiTestApp *app) +{ + GHOST_GLSettings glSettings = {0}; GHOST_SystemHandle sys = multitestapp_get_system(app); GHOST_TUns32 screensize[2]; GHOST_WindowHandle win; GHOST_GetMainDisplayDimensions(sys, &screensize[0], &screensize[1]); - win = GHOST_CreateWindow(sys, "MultiTest:Logger", 40, screensize[1] - 432, - 800, 300, GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, FALSE, FALSE); + win = GHOST_CreateWindow( + sys, "MultiTest:Logger", + 40, screensize[1] - 432, 800, 300, + GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL, + glSettings); if (win) { LoggerWindow *lw = MEM_callocN(sizeof(*lw), "loggerwindow_new"); @@ -775,13 +785,18 @@ static void extrawindow_handle(void *priv, GHOST_EventHandle evt) /**/ -ExtraWindow *extrawindow_new(MultiTestApp *app) { +ExtraWindow *extrawindow_new(MultiTestApp *app) +{ + GHOST_GLSettings glSettings = {0}; GHOST_SystemHandle sys = multitestapp_get_system(app); GHOST_WindowHandle win; - win = GHOST_CreateWindow(sys, "MultiTest:Extra", 500, 40, 400, 400, - GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL, - FALSE, FALSE); + win = GHOST_CreateWindow( + sys, "MultiTest:Extra", + 500, 40, 400, 400, + GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL, + glSettings); if (win) { ExtraWindow *ew = MEM_callocN(sizeof(*ew), "mainwindow_new"); -- cgit v1.2.3 From f5949efb53f39f4132f9a2604ec5e83aa3e98b27 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 4 Apr 2015 18:58:49 +1100 Subject: Missed in recent cleanup --- source/gameengine/Converter/KX_BlenderSceneConverter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 21c8f39f782..4f251a66ccf 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -675,7 +675,7 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) if (blenderObject && blenderObject->parent==NULL && gameObj->IsRecordAnimation()) { if (blenderObject->adt==NULL) - BKE_id_add_animdata(&blenderObject->id); + BKE_animdata_add_id(&blenderObject->id); if (blenderObject->adt) { -- cgit v1.2.3 From 59df941ea57770250c59feeed4f7ce72bafd5b60 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Sat, 4 Apr 2015 14:27:05 +0200 Subject: Fix T44259: Secondary strokes get terminated early when drawing in Continuous Drawing mode --- source/blender/editors/gpencil/gpencil_paint.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index a299e23830d..0c5d381ed27 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1885,8 +1885,9 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) * - LEFTMOUSE = standard drawing (all) / straight line drawing (all) / polyline (toolbox only) * - RIGHTMOUSE = polyline (hotkey) / eraser (all) * (Disabling RIGHTMOUSE case here results in bugs like [#32647]) + * also making sure we have a valid event value, to not exit too early */ - if (ELEM(event->type, LEFTMOUSE, RIGHTMOUSE)) { + if (ELEM(event->type, LEFTMOUSE, RIGHTMOUSE) && event->val != 0) { /* if painting, end stroke */ if (p->status == GP_STATUS_PAINTING) { int sketch = 0; -- cgit v1.2.3 From 1604a26fe648ba712cf2cbead2a96dbd0dab817c Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Sat, 4 Apr 2015 19:17:39 +0200 Subject: Fix T44251: Changing views using numpad broken For KM_ANY I've filtered out every event that has a click type, although that was only needed for the additional event sent on KM_HOLD. A bit weird that this only happened on a few machines though. --- source/blender/windowmanager/intern/wm_event_system.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index ce9a729a7a9..5fd6342b95e 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1460,8 +1460,8 @@ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) if (kmitype != KM_ANY) if (winevent->type != kmitype) return 0; - /* KM_ANY excludes click_type events - filter them out */ - if (kmi->val == KM_ANY && winevent->click_type) return 0; + /* KM_ANY excludes KM_HOLD since it's time based and not a real input - filter it out */ + if (kmi->val == KM_ANY && winevent->click_type == KM_HOLD) return 0; if (kmi->val != KM_ANY) if (!ELEM(kmi->val, winevent->val, winevent->click_type)) return 0; -- cgit v1.2.3 From 8eac4085be42f01d09843e918936a01d3615d518 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Sat, 4 Apr 2015 22:38:31 +0200 Subject: Fix T44264 copy paste error, checking same condition twice. --- source/blender/editors/sculpt_paint/paint_image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 5cfbd164153..097ffe3523b 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -1393,7 +1393,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op) if (ma && ma->texpaintslot) ima = ma->texpaintslot[ma->paint_active_slot].ima; } - else if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) { + else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) { ima = imapaint->canvas; } -- cgit v1.2.3 From cedd7cde442edc57b3aa1a562b3c0855a2db8d8b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 5 Apr 2015 06:22:49 +1000 Subject: WM: prefer define over zero wmEvent.val --- source/blender/editors/gpencil/gpencil_paint.c | 2 +- source/blender/editors/screen/screen_ops.c | 2 +- source/blender/windowmanager/intern/wm_event_system.c | 6 +++--- source/blender/windowmanager/intern/wm_window.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 0c5d381ed27..3a564cc6ddb 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1887,7 +1887,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) * (Disabling RIGHTMOUSE case here results in bugs like [#32647]) * also making sure we have a valid event value, to not exit too early */ - if (ELEM(event->type, LEFTMOUSE, RIGHTMOUSE) && event->val != 0) { + if (ELEM(event->type, LEFTMOUSE, RIGHTMOUSE) && (event->val != KM_NOTHING)) { /* if painting, end stroke */ if (p->status == GP_STATUS_PAINTING) { int sketch = 0; diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 2064555f27e..894a801b677 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -717,7 +717,7 @@ static void actionzone_apply(bContext *C, wmOperator *op, int type) else event.type = EVT_ACTIONZONE_REGION; - event.val = 0; + event.val = KM_NOTHING; event.customdata = op->customdata; event.customdatafree = true; op->customdata = NULL; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 5fd6342b95e..8c013eb7cd4 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -3116,7 +3116,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event.x = evt->x = pd->x; event.y = evt->y = pd->y; - event.val = 0; + event.val = KM_NOTHING; /* Use prevx/prevy so we can calculate the delta later */ event.prevx = event.x - pd->deltaX; @@ -3323,7 +3323,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event.type = TIMER; event.custom = EVT_DATA_TIMER; event.customdata = customdata; - event.val = 0; + event.val = KM_NOTHING; event.keymodifier = 0; wm_event_add(win, &event); @@ -3333,7 +3333,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U case GHOST_kEventNDOFMotion: { event.type = NDOF_MOTION; - event.val = 0; + event.val = KM_NOTHING; attach_ndof_data(&event, customdata); wm_event_add(win, &event); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 98766f35006..5c05d86da57 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1202,7 +1202,7 @@ static int wm_window_timer(const bContext *C) wm_event_init_from_window(win, &event); event.type = wt->event_type; - event.val = 0; + event.val = KM_NOTHING; event.keymodifier = 0; event.custom = EVT_DATA_TIMER; event.customdata = wt; -- cgit v1.2.3 From 26979d45b196d2102f80b9048d90db885acaf675 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 5 Apr 2015 06:32:25 +1000 Subject: Cleanup: use float math funcs --- source/blender/blenkernel/intern/armature.c | 2 +- source/blender/editors/sculpt_paint/paint_image_proj.c | 2 +- source/blender/editors/sculpt_paint/paint_stroke.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 9e209cb16b6..dc11bcb00aa 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2238,7 +2238,7 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o } /* compute scale factor for xz axes from this value */ - final_scale = sqrt(bulge); + final_scale = sqrtf(bulge); } else { /* no scaling, so scale factor is simple */ diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index f853fd91491..9ee15f3a532 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -1964,7 +1964,7 @@ static float angle_2d_clockwise(const float p1[2], const float p2[2], const floa v1[0] = p1[0] - p2[0]; v1[1] = p1[1] - p2[1]; v2[0] = p3[0] - p2[0]; v2[1] = p3[1] - p2[1]; - return -atan2(v1[0] * v2[1] - v1[1] * v2[0], v1[0] * v2[0] + v1[1] * v2[1]); + return -atan2f(v1[0] * v2[1] - v1[1] * v2[0], v1[0] * v2[0] + v1[1] * v2[1]); } #endif diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index bfd429d0924..0db2259b307 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -1022,7 +1022,7 @@ static void paint_stroke_line_constrain (PaintStroke *stroke, float mouse[2]) float angle, len, res; sub_v2_v2v2(line, mouse, stroke->last_mouse_position); - angle = atan2(line[1], line[0]); + angle = atan2f(line[1], line[0]); len = len_v2(line); /* divide angle by PI/4 */ -- cgit v1.2.3 From 2f42be6995503ff1df7dd14941ecc43ab0cb49c5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 5 Apr 2015 06:47:31 +1000 Subject: Cleanup: remove MSVC2008 workaround --- source/blender/blenlib/intern/math_base.c | 36 ------------------------------- 1 file changed, 36 deletions(-) diff --git a/source/blender/blenlib/intern/math_base.c b/source/blender/blenlib/intern/math_base.c index 3ff1af3513e..cddfde371f5 100644 --- a/source/blender/blenlib/intern/math_base.c +++ b/source/blender/blenlib/intern/math_base.c @@ -31,42 +31,6 @@ #include "BLI_strict_flags.h" -/* WARNING: MSVC compiling hack for double_round() */ -#if (defined(WIN32) || defined(WIN64)) && !(defined(FREE_WINDOWS)) - -/* from python 3.1 pymath.c */ -double copysign(double x, double y) -{ - /* use atan2 to distinguish -0.0 from 0.0 */ - if (y > 0.0 || (y == 0.0 && atan2(y, -1.0) > 0.0)) { - return fabs(x); - } - else { - return -fabs(x); - } -} - -/* from python 3.1 pymath.c */ -double round(double x) -{ - double absx, y; - absx = fabs(x); - y = floor(absx); - if (absx - y >= 0.5) - y += 1.0; - return copysign(y, x); -} -#else /* OpenSuse 11.1 seems to need this. */ -# ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wredundant-decls" -# endif -double round(double x); -# ifdef __GNUC__ -# pragma GCC diagnostic pop -# endif -#endif - /* from python 3.1 floatobject.c * ndigits must be between 0 and 21 */ double double_round(double x, int ndigits) -- cgit v1.2.3 From 00f732f268d32f661a0b75e7f98d9924ca0fd4b7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 5 Apr 2015 06:53:34 +1000 Subject: Fix T44266: win32 delete's malloc'd memory --- intern/ghost/intern/GHOST_ContextWGL.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/intern/ghost/intern/GHOST_ContextWGL.cpp b/intern/ghost/intern/GHOST_ContextWGL.cpp index 055737481ae..d155e689b04 100644 --- a/intern/ghost/intern/GHOST_ContextWGL.cpp +++ b/intern/ghost/intern/GHOST_ContextWGL.cpp @@ -120,9 +120,9 @@ GHOST_ContextWGL::~GHOST_ContextWGL() #endif #ifndef NDEBUG - delete m_dummyRenderer; - delete m_dummyVendor; - delete m_dummyVersion; + free(m_dummyRenderer); + free(m_dummyVendor); + free(m_dummyVersion); #endif } @@ -393,9 +393,9 @@ void GHOST_ContextWGL::initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD) // the following are not technially WGLEW, but they also require a context to work #ifndef NDEBUG - delete m_dummyRenderer; - delete m_dummyVendor; - delete m_dummyVersion; + free(m_dummyRenderer); + free(m_dummyVendor); + free(m_dummyVersion); m_dummyRenderer = _strdup(reinterpret_cast(glGetString(GL_RENDERER))); m_dummyVendor = _strdup(reinterpret_cast(glGetString(GL_VENDOR))); -- cgit v1.2.3 From 59bfc5c76ee98ca53be8ec3d422529d62676fdac Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 5 Apr 2015 09:44:30 +1000 Subject: Fix T44270: Similar face region crash /w wire edge --- source/blender/bmesh/tools/bmesh_region_match.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c index bb7000e5534..c695d4c1774 100644 --- a/source/blender/bmesh/tools/bmesh_region_match.c +++ b/source/blender/bmesh/tools/bmesh_region_match.c @@ -1451,7 +1451,7 @@ int BM_mesh_region_match( BMFace **faces_result; unsigned int faces_result_len_out; - if (BM_elem_flag_test(e_dst, BM_ELEM_TAG)) { + if (BM_elem_flag_test(e_dst, BM_ELEM_TAG) || BM_edge_is_wire(e_dst)) { continue; } -- cgit v1.2.3 From a1c2b1a8a88e2046ff48279dcb0a2b5a71ac14b4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 5 Apr 2015 09:57:10 +1000 Subject: Fix T44265: Win32 error checking GL version --- intern/ghost/intern/GHOST_ContextWGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_ContextWGL.cpp b/intern/ghost/intern/GHOST_ContextWGL.cpp index d155e689b04..979dc549498 100644 --- a/intern/ghost/intern/GHOST_ContextWGL.cpp +++ b/intern/ghost/intern/GHOST_ContextWGL.cpp @@ -888,7 +888,7 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext() if (!s_warn_old) { if ((strcmp(vendor, "Microsoft Corporation") == 0 || - strcmp(renderer, "GDI Generic") == 0) && version[0] == '1' && version[0] == '1') + strcmp(renderer, "GDI Generic") == 0) && version[0] == '1' && version[2] == '1') { MessageBox(m_hWnd, "Your system does not use 3D hardware acceleration.\n" "Such systems can cause stability problems in Blender and they are unsupported.\n\n" -- cgit v1.2.3 From 1a117ad40c62cfab3cec6c4513627e781cd2b331 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 5 Apr 2015 09:50:16 +0200 Subject: Fix T44263: Invalid parameters to fill_vn_fl in deform.c. Own fault, thanks a bunch to LazyDodo for finding that - and odd GCC did not warn about it... --- source/blender/blenkernel/intern/deform.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 350b19b0250..72133cf6460 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -982,7 +982,7 @@ void BKE_defvert_extract_vgroup_to_vertweights( } } else { - fill_vn_fl(r_weights, invert_vgroup ? 1.0f : 0.0f, num_verts); + fill_vn_fl(r_weights, num_verts, invert_vgroup ? 1.0f : 0.0f); } } @@ -1008,7 +1008,7 @@ void BKE_defvert_extract_vgroup_to_edgeweights( MEM_freeN(tmp_weights); } else { - fill_vn_fl(r_weights, 0.0f, num_edges); + fill_vn_fl(r_weights, num_edges, 0.0f); } } @@ -1031,7 +1031,7 @@ void BKE_defvert_extract_vgroup_to_loopweights( MEM_freeN(tmp_weights); } else { - fill_vn_fl(r_weights, 0.0f, num_loops); + fill_vn_fl(r_weights, num_loops, 0.0f); } } @@ -1060,7 +1060,7 @@ void BKE_defvert_extract_vgroup_to_polyweights( MEM_freeN(tmp_weights); } else { - fill_vn_fl(r_weights, 0.0f, num_polys); + fill_vn_fl(r_weights, num_polys, 0.0f); } } -- cgit v1.2.3 From 29e968a3158b2e51a7d03b993b5e64a47ebea276 Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Sun, 5 Apr 2015 10:13:04 +0200 Subject: BGE: Fix T36703: Character motion actuator local movement not working correct. The character motion actuator local movement does not taking account of the object rotation. It is necessary to rotate the motion vector before adding the local movement. Reviewers: sybren, lordloki, moguri Reviewed By: lordloki, moguri Maniphest Tasks: T42709 Differential Revision: https://developer.blender.org/D1206 --- source/gameengine/Ketsji/KX_ObjectActuator.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index 0eec86987be..f65b0ac0f4f 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -223,6 +223,11 @@ bool KX_ObjectActuator::Update() else if (m_bitLocalFlag.CharacterMotion) { MT_Vector3 dir = m_dloc; + if (m_bitLocalFlag.DLoc) { + MT_Matrix3x3 basis = parent->GetPhysicsController()->GetOrientation(); + dir = basis * dir; + } + if (m_bitLocalFlag.AddOrSetCharLoc) { MT_Vector3 old_dir = character->GetWalkDirection(); @@ -236,11 +241,6 @@ bool KX_ObjectActuator::Update() } // We always want to set the walk direction since a walk direction of (0, 0, 0) should stop the character - if (m_bitLocalFlag.DLoc) - { - MT_Matrix3x3 basis = parent->GetPhysicsController()->GetOrientation(); - dir = basis*dir; - } character->SetWalkDirection(dir/parent->GetScene()->GetPhysicsEnvironment()->GetNumTimeSubSteps()); if (!m_bitLocalFlag.ZeroDRot) -- cgit v1.2.3 From 92755da4712a68ed62857a1c00eb8b43916d07b6 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Sun, 5 Apr 2015 15:41:20 +0200 Subject: Fix T44251 (2nd try): Changing views using numpad broken --- source/blender/editors/space_view3d/view3d_ops.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index c5425f238cc..6ba3a2850cc 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -236,7 +236,8 @@ void view3d_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "VIEW3D_OT_navigate", FKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_verify_item(keymap, "VIEW3D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0); + /* value is set to KM_NOTHING to avoid conflicts with click type (see T44251) */ + WM_keymap_verify_item(keymap, "VIEW3D_OT_smoothview", TIMER1, KM_NOTHING, KM_ANY, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEPAN, 0, 0, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEROTATE, 0, 0, 0); -- cgit v1.2.3 From 252b36ce77fdb75b97b28503d1d5510980d3d51f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 5 Apr 2015 17:42:27 +0500 Subject: Cycles: Remove unused Beckmann slope sampling code It did not preserve stratification too well and lookup-table approach was working much better. There are now also some more interesting forumlation from Wenzel and OpenShadingLanguage which should work better than old code. --- intern/cycles/kernel/closure/bsdf_microfacet.h | 40 -------------------------- 1 file changed, 40 deletions(-) diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index 71086f2e764..4116c86df2c 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -137,44 +137,6 @@ ccl_device_inline void microfacet_beckmann_sample_slopes( *G1i = G1; -#if 0 - const float C = 1.0f - G1 * erf_a; - - /* sample slope X */ - if(randu < C) { - /* rescale randu */ - randu = randu / C; - const float w_1 = 0.5f * SQRT_PI_INV * sin_theta_i * exp_a2; - const float w_2 = cos_theta_i * (0.5f - 0.5f*erf_a); - const float p = w_1 / (w_1 + w_2); - - if(randu < p) { - randu = randu / p; - *slope_x = -sqrtf(-logf(randu*exp_a2)); - } - else { - randu = (randu - p) / (1.0f - p); - *slope_x = approx_erfinvf(randu - 1.0f - randu*erf_a); - } - } - else { - /* rescale randu */ - randu = (randu - C) / (1.0f - C); - *slope_x = approx_erfinvf((-1.0f + 2.0f*randu)*erf_a); - - const float p = (-(*slope_x)*sin_theta_i + cos_theta_i) / (2.0f*cos_theta_i); - - if(randv > p) { - *slope_x = -(*slope_x); - randv = (randv - p) / (1.0f - p); - } - else - randv = randv / p; - } - - /* sample slope Y */ - *slope_y = approx_erfinvf(2.0f*randv - 1.0f); -#else /* use precomputed table, because it better preserves stratification * of the random number pattern */ int beckmann_table_offset = kernel_data.tables.beckmann_offset; @@ -182,8 +144,6 @@ ccl_device_inline void microfacet_beckmann_sample_slopes( *slope_x = lookup_table_read_2D(kg, randu, cos_theta_i, beckmann_table_offset, BECKMANN_TABLE_SIZE, BECKMANN_TABLE_SIZE); *slope_y = approx_erfinvf(2.0f*randv - 1.0f); -#endif - } ccl_device_inline void microfacet_ggx_sample_slopes( -- cgit v1.2.3 From b06962fcfe8124ba15761703aaf24086c4b6fa5b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 5 Apr 2015 18:40:46 +0500 Subject: Cycles: Avoid using lookup table for Beckmann slopes on GPU This patch is based on some work done in D788 and re-formulation from Beckmann implementation in OpenShadingLanguage. Skipping texture lookup helps a lot on GPUs where it's more expensive to access texture memory than to do some extra calculation in threads. CPU code still uses lookup-table based approach since this seems to be still faster (at least on computers i've got access to). This change gives about 2% speedup on BMW scene with GTX560TI. --- intern/cycles/kernel/closure/bsdf_microfacet.h | 62 ++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index 4116c86df2c..b225e674702 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -104,10 +104,7 @@ ccl_device_inline float approx_erfinvf(float x) } } -/* Beckmann and GGX microfacet importance sampling from: - * - * Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals. - * E. Heitz and E. d'Eon, EGSR 2014 */ +/* Beckmann and GGX microfacet importance sampling. */ ccl_device_inline void microfacet_beckmann_sample_slopes( KernelGlobals *kg, @@ -128,24 +125,71 @@ ccl_device_inline void microfacet_beckmann_sample_slopes( /* precomputations */ const float tan_theta_i = sin_theta_i/cos_theta_i; const float inv_a = tan_theta_i; - const float a = 1.0f/inv_a; - const float erf_a = approx_erff(a); - const float exp_a2 = expf(-a*a); + const float cot_theta_i = 1.0f/tan_theta_i; + const float erf_a = approx_erff(cot_theta_i); + const float exp_a2 = expf(-cot_theta_i*cot_theta_i); const float SQRT_PI_INV = 0.56418958354f; const float Lambda = 0.5f*(erf_a - 1.0f) + (0.5f*SQRT_PI_INV)*(exp_a2*inv_a); const float G1 = 1.0f/(1.0f + Lambda); /* masking */ *G1i = G1; - /* use precomputed table, because it better preserves stratification - * of the random number pattern */ +#if defined(__KERNEL_GPU__) + /* Based on paper from Wenzel Jakob + * An Improved Visible Normal Sampling Routine for the Beckmann Distribution + * + * http://www.mitsuba-renderer.org/~wenzel/files/visnormal.pdf + * + * Reformulation from OpenShadingLanguage which avoids using inverse + * trigonometric functions. + */ + + /* Sample slope X. + * + * Compute a coarse approximation using the approximation: + * exp(-ierf(x)^2) ~= 1 - x * x + * solve y = 1 + b + K * (1 - b * b) + */ + float K = tan_theta_i * SQRT_PI_INV; + float y_approx = randu * (1.0f + erf_a + K * (1 - erf_a * erf_a)); + float y_exact = randu * (1.0f + erf_a + K * exp_a2); + float b = K > 0 ? (0.5f - sqrtf(K * (K - y_approx + 1.0f) + 0.25f)) / K : y_approx - 1.0f; + + /* Perform newton step to refine toward the true root. */ + float inv_erf = approx_erfinvf(b); + float value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact; + /* Check if we are close enough already, + * this also avoids NaNs as we get close to the root. + */ + if(fabsf(value) > 1e-6f) { + b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 1. */ + inv_erf = approx_erfinvf(b); + value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact; + b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 2. */ + /* Compute the slope from the refined value. */ + *slope_x = approx_erfinvf(b); + } + else { + /* We are close enough already. */ + *slope_x = inv_erf; + } + *slope_y = approx_erfinvf(2.0f*randv - 1.0f); +#else + /* Use precomputed table on CPU, it gives better perfomance. */ int beckmann_table_offset = kernel_data.tables.beckmann_offset; *slope_x = lookup_table_read_2D(kg, randu, cos_theta_i, beckmann_table_offset, BECKMANN_TABLE_SIZE, BECKMANN_TABLE_SIZE); *slope_y = approx_erfinvf(2.0f*randv - 1.0f); +#endif } +/* GGX microfacet importance sampling from: + * + * Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals. + * E. Heitz and E. d'Eon, EGSR 2014 + */ + ccl_device_inline void microfacet_ggx_sample_slopes( const float cos_theta_i, const float sin_theta_i, float randu, float randv, float *slope_x, float *slope_y, -- cgit v1.2.3 From ab2d05d9588fa1d40333f3ab86d54513c6e50dc9 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 5 Apr 2015 18:51:54 +0500 Subject: Fix T44269: Typo in volume_attribute_float:geom_volume.h Was rather harmless typo since we either pass both dx,dy or pass both NULL. --- intern/cycles/kernel/geom/geom_volume.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/kernel/geom/geom_volume.h b/intern/cycles/kernel/geom/geom_volume.h index c33509fbf4f..c72afa2a3a4 100644 --- a/intern/cycles/kernel/geom/geom_volume.h +++ b/intern/cycles/kernel/geom/geom_volume.h @@ -60,7 +60,7 @@ ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd, #endif if(dx) *dx = 0.0f; - if(dx) *dy = 0.0f; + if(dy) *dy = 0.0f; /* todo: support float textures to lower memory usage for single floats */ return average(float4_to_float3(r)); -- cgit v1.2.3 From af23e8d44a6c70ce98a15d0aa2721c152c578dae Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Sun, 5 Apr 2015 18:48:49 +0200 Subject: Fix T44275: CTRL+LMB to extrude to mouse position conflicts with snapped extruding More practical description of the bug: extruding with ctrl to use snapping and confirming the action added another extrusion to the mouse position. This was caused from the second event that is now sent if a key release happens within the click timeout. It triggers the "Extrude to Cursor" operator since it is called by CTRL+LMB wich is exactly the event that is sent in this case. I'm not totally happy with this workaround since it changes the Confirm/ Abort event for all transformation actions to key release which *might* result in more conflicts (fingers crossed this isn't the case). If this happens we might need to write some special transformation handling for extrusion. This is an example of the difficulties we get from loading too much functions on the same keys - we need to be careful with that! --- source/blender/editors/mesh/editmesh_extrude.c | 5 ++++- source/blender/editors/mesh/mesh_ops.c | 2 +- source/blender/editors/transform/transform.c | 8 ++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 9b1b0b915c1..3c9c8a45d4d 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -510,7 +510,10 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w float min[3], max[3]; bool done = false; bool use_proj; - + + if (ELEM(event->click_type, KM_CLICK, KM_HOLD)) + return OPERATOR_CANCELLED; + em_setup_viewcontext(C, &vc); ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 126d1cb0ad9..79eec57712f 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -407,7 +407,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) /* Vertex Slide */ WM_keymap_add_item(keymap, "TRANSFORM_OT_vert_slide", VKEY, KM_PRESS, KM_SHIFT, 0); /* use KM_CLICK because same key is used for tweaks */ - kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); + kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_RELEASE, KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "rotate_source", true); kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_PRESS, KM_SHIFT | KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "rotate_source", false); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index c8d81383d79..401accba40b 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -866,10 +866,10 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) keymap = WM_modalkeymap_add(keyconf, "Transform Modal Map", modal_items); /* items for modal map */ - WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_CANCEL); - WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM); - WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM); - WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, ESCKEY, KM_RELEASE, KM_ANY, 0, TFM_MODAL_CANCEL); + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, TFM_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, RETKEY, KM_RELEASE, KM_ANY, 0, TFM_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, PADENTER, KM_RELEASE, KM_ANY, 0, TFM_MODAL_CONFIRM); WM_modalkeymap_add_item(keymap, GKEY, KM_PRESS, 0, 0, TFM_MODAL_TRANSLATE); WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, TFM_MODAL_ROTATE); -- cgit v1.2.3 From 776bfa64a53191b6f6aba107449be9353b7a2bee Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Sun, 5 Apr 2015 19:32:57 +0200 Subject: Stickies: Don't send extra event on KM_CLICK Just add KM_CLICK to the already sent KM_RELEASE, don't send a new one for this. This might help us to get rid of quite some glitches and workarounds \o/ (why didn't this come earlier to my mind? :S) --- source/blender/windowmanager/intern/wm_event_system.c | 15 ++++++++++++++- source/blender/windowmanager/intern/wm_window.c | 15 ++++----------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 8c013eb7cd4..0a8da1df233 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2994,7 +2994,7 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi * - #KM_PRESS && time since first #KM_PRESS > U.click_timeout --> send #KM_HOLD * - #KM_PRESS after a #KM_RELEASE && time since previous #KM_PRESS < U.dbl_click_time --> send #KM_DBL_CLICK * - * \note: only #KM_DBL_CLICK is handled here, rest in #wm_window_event_clicktype_init (wm_window.c) + * \note: only #KM_DBL_CLICK and #KM_CLICK are handled here, #KM_HOLD in #wm_window_event_clicktype_init (wm_window.c) */ static void wm_event_clicktype_init(wmWindow *win, wmEvent *event, wmEvent *event_state) { @@ -3025,6 +3025,19 @@ static void wm_event_clicktype_init(wmWindow *win, wmEvent *event, wmEvent *even } } + if ((PIL_check_seconds_timer() - event->click_time) * 1000 <= U.click_timeout) { + /* for any reason some X11 systems send two release events triggering two KM_CLICK events + * - making the rules more strict by checking for prevval resolves this (not needed for mouse) */ + if (event->val == KM_RELEASE && + (ISMOUSE(event->type) || event->prevval != KM_RELEASE)) + { + click_type = KM_CLICK; + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) { + printf("%s Send click event\n", __func__); + } + } + } + if (click_type != event->click_type) { event_state->click_type = event->click_type = click_type; } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 5c05d86da57..1af20e6036d 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1098,9 +1098,9 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr } /** - * #KM_DBL_CLICK is set in wm_event_clicktype_init (wm_event_system.c) - * Normally, this should be there too, but for #KM_CLICK/#KM_HOLD, we need a - * time precision of a few milliseconds, which we can't get from there + * #KM_DBL_CLICK and #KM_CLICK are set in wm_event_clicktype_init (wm_event_system.c) + * Normally, #KM_HOLD should be there too, but we need a time precision of a few + * milliseconds for it, which we can't get from there */ static void wm_window_event_clicktype_init(const bContext *C) { @@ -1141,14 +1141,7 @@ static void wm_window_event_clicktype_init(const bContext *C) /* the actual test */ if ((PIL_check_seconds_timer() - event->click_time) * 1000 <= U.click_timeout) { - /* for any reason some X11 systems send two release events triggering two KM_CLICK - * events - making the rules more strict by checking for prevval resolves this */ - if (event->val == KM_RELEASE && event->prevval != KM_RELEASE) { - click_type = KM_CLICK; - if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) { - printf("%s Send click event\n", __func__); - } - } + /* sending of KM_CLICK is handled in wm_event_clicktype_init (wm_event_system.c) */ } else if (event->is_key_pressed) { click_type = KM_HOLD; -- cgit v1.2.3 From c3dad7953afccd440c63c60b5ce34f147178d826 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Sun, 5 Apr 2015 20:04:37 +0200 Subject: Stickies: Remove redundant fixes Those fixes aren't needed anymore due to 776bfa64a53191b6f6aba107449be9353b7a2bee --- source/blender/editors/interface/interface_eyedropper.c | 4 ---- source/blender/editors/mesh/editmesh_extrude.c | 3 --- 2 files changed, 7 deletions(-) diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index 96f9b87611f..f5847a9d701 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -277,10 +277,6 @@ static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event) eyedropper_cancel(C, op); return OPERATOR_CANCELLED; case LEFTMOUSE: - /* two release events are sent on KM_CLICK, so ignore second one */ - if (event->click_type == KM_CLICK) { - break; - } if (event->val == KM_RELEASE) { if (eye->accum_tot == 0) { eyedropper_color_sample(C, eye, event->x, event->y); diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 3c9c8a45d4d..5c7efcc40da 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -511,9 +511,6 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w bool done = false; bool use_proj; - if (ELEM(event->click_type, KM_CLICK, KM_HOLD)) - return OPERATOR_CANCELLED; - em_setup_viewcontext(C, &vc); ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); -- cgit v1.2.3 From 7157f3dbce257d9f9a0df7b243e306949fb9678e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 6 Apr 2015 09:03:32 +1000 Subject: GHash: no reason to use GSetEntry in ghash API --- source/blender/blenlib/intern/BLI_ghash.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index f2705c79574..11848804194 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -162,7 +162,7 @@ BLI_INLINE unsigned int ghash_bucket_index(GHash *gh, const unsigned int hash) #ifdef GHASH_USE_MODULO_BUCKETS return hash % gh->nbuckets; #else - return full_hash & gh->bucket_mask; + return hash & gh->bucket_mask; #endif } @@ -450,14 +450,14 @@ BLI_INLINE void ghash_insert_ex( BLI_INLINE void ghash_insert_ex_keyonly( GHash *gh, void *key, const unsigned int bucket_index) { - GSetEntry *e = BLI_mempool_alloc(gh->entrypool); + Entry *e = BLI_mempool_alloc(gh->entrypool); BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)); BLI_assert((gh->flag & GHASH_FLAG_IS_GSET) != 0); e->next = gh->buckets[bucket_index]; e->key = key; - gh->buckets[bucket_index] = (Entry *)e; + gh->buckets[bucket_index] = e; ghash_buckets_expand(gh, ++gh->nentries, false); } @@ -498,7 +498,7 @@ BLI_INLINE bool ghash_insert_safe_keyonly(GHash *gh, void *key, const bool overr { const unsigned int hash = ghash_keyhash(gh, key); const unsigned int bucket_index = ghash_bucket_index(gh, hash); - GSetEntry *e = ghash_lookup_entry_ex(gh, key, bucket_index); + Entry *e = ghash_lookup_entry_ex(gh, key, bucket_index); BLI_assert((gh->flag & GHASH_FLAG_IS_GSET) != 0); -- cgit v1.2.3 From 5574f4c59d324e82796abc9435c222c227fc0a4e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 5 Apr 2015 12:17:14 +1200 Subject: Fix: It was difficult to select control points for NLA Control FCurves in the Graph Editor --- source/blender/editors/space_graph/graph_select.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 78dbae7618b..28107337084 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -1089,6 +1089,8 @@ typedef struct tNearestVertInfo { short hpoint; /* the handle index that we hit (eHandleIndex) */ short sel; /* whether the handle is selected or not */ int dist; /* distance from mouse to vert */ + + eAnim_ChannelType ctype; /* type of animation channel this FCurve comes from */ } tNearestVertInfo; /* Tags for the type of graph vert that we have */ @@ -1116,7 +1118,7 @@ static bool fcurve_handle_sel_check(SpaceIpo *sipo, BezTriple *bezt) /* check if the given vertex is within bounds or not */ // TODO: should we return if we hit something? static void nearest_fcurve_vert_store( - ListBase *matches, View2D *v2d, FCurve *fcu, + ListBase *matches, View2D *v2d, FCurve *fcu, eAnim_ChannelType ctype, BezTriple *bezt, FPoint *fpt, short hpoint, const int mval[2], float unit_scale) { /* Keyframes or Samples? */ @@ -1149,6 +1151,8 @@ static void nearest_fcurve_vert_store( /* store values */ nvi->fcu = fcu; + nvi->ctype = ctype; + nvi->bezt = bezt; nvi->hpoint = hpoint; nvi->dist = dist; @@ -1190,29 +1194,29 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L FCurve *fcu = (FCurve *)ale->key_data; AnimData *adt = ANIM_nla_mapping_get(ac, ale); float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag); - + /* apply NLA mapping to all the keyframes */ if (adt) ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0); - + if (fcu->bezt) { BezTriple *bezt1 = fcu->bezt, *prevbezt = NULL; int i; for (i = 0; i < fcu->totvert; i++, prevbezt = bezt1, bezt1++) { /* keyframe */ - nearest_fcurve_vert_store(matches, v2d, fcu, bezt1, NULL, NEAREST_HANDLE_KEY, mval, unit_scale); + nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_KEY, mval, unit_scale); /* handles - only do them if they're visible */ if (fcurve_handle_sel_check(sipo, bezt1) && (fcu->totvert > 1)) { /* first handle only visible if previous segment had handles */ if ((!prevbezt && (bezt1->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) { - nearest_fcurve_vert_store(matches, v2d, fcu, bezt1, NULL, NEAREST_HANDLE_LEFT, mval, unit_scale); + nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_LEFT, mval, unit_scale); } /* second handle only visible if this segment is bezier */ if (bezt1->ipo == BEZT_IPO_BEZ) { - nearest_fcurve_vert_store(matches, v2d, fcu, bezt1, NULL, NEAREST_HANDLE_RIGHT, mval, unit_scale); + nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_RIGHT, mval, unit_scale); } } } @@ -1405,7 +1409,7 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m /* needs to be called with (sipo->flag & SIPO_SELCUVERTSONLY) otherwise the active flag won't be set [#26452] */ if (nvi->fcu->flag & FCURVE_SELECTED) { int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, ANIMTYPE_FCURVE); + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, nvi->ctype); } /* free temp sample data for filtering */ -- cgit v1.2.3 From 46b42dba141621fad9fdfe536c7bf0652998e992 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 6 Apr 2015 13:21:18 +1200 Subject: Fix: Stroke Edit Mode warning for GPencil draws correctly with Region Overlap enabled --- source/blender/editors/gpencil/drawgpencil.c | 36 ++++++++++++++++++---------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 93a485423c0..d4d601b1e8d 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -60,6 +60,7 @@ #include "BIF_glutil.h" #include "ED_gpencil.h" +#include "ED_screen.h" #include "ED_view3d.h" #include "UI_interface_icons.h" @@ -1047,8 +1048,17 @@ static void gp_draw_data_layers(bGPdata *gpd, int offsx, int offsy, int winx, in } /* draw a short status message in the top-right corner */ -static void gp_draw_status_text(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int UNUSED(cfra), int UNUSED(dflag)) +static void gp_draw_status_text(bGPdata *gpd, ARegion *ar) { + rcti rect; + + /* Cannot draw any status text when drawing OpenGL Renders */ + if (G.f & G_RENDER_OGL) + return; + + /* Get bounds of region - Necessary to avoid problems with region overlap */ + ED_region_visible_rect(ar, &rect); + /* for now, this should only be used to indicate when we are in stroke editmode */ if (gpd->flag & GP_DATA_STROKE_EDITMODE) { const char *printable = IFACE_("GPencil Stroke Editing"); @@ -1057,8 +1067,8 @@ static void gp_draw_status_text(bGPdata *gpd, int offsx, int offsy, int winx, in BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); - xco = offsx + (winx - U.widget_unit) - (int)printable_size[0]; - yco = offsy + (winy - U.widget_unit); + xco = (rect.xmax - U.widget_unit) - (int)printable_size[0]; + yco = (rect.ymax - U.widget_unit); /* text label */ UI_ThemeColor(TH_TEXT_HI); @@ -1107,16 +1117,6 @@ static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy, glDisable(GL_BLEND); // alpha blending glDisable(GL_LINE_SMOOTH); // smooth lines - /* Draw status text: - * - This cannot be drawn when doing OpenGL "renders" and also when "only render" is enabled - * - NOSTATUS should also catch all the other cases where the we are drawing into the "wrong" - * coordinate space (e.g. 3D, View 2D, etc.) - */ - /* XXX: Reinstate the "draw info" flag into the UI? */ - if ((dflag & GP_DRAWDATA_NOSTATUS) == 0 && (G.f & G_RENDER_OGL) == 0) { - gp_draw_status_text(gpd, offsx, offsy, winx, winy, cfra, dflag); - } - /* restore initial gl conditions */ glLineWidth(1.0); glPointSize(1.0); @@ -1243,6 +1243,11 @@ void ED_gpencil_draw_view2d(const bContext *C, bool onlyv2d) /* draw it! */ if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_NOSTATUS); gp_draw_data_all(scene, gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag, sa->spacetype); + + /* draw status text (if in screen/pixel-space) */ + if (onlyv2d == false) { + gp_draw_status_text(gpd, ar); + } } /* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly @@ -1293,6 +1298,11 @@ void ED_gpencil_draw_view3d(Scene *scene, View3D *v3d, ARegion *ar, bool only3d) /* draw it! */ gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype); + + /* draw status text (if in screen/pixel-space) */ + if (only3d == false) { + gp_draw_status_text(gpd, ar); + } } void ED_gpencil_draw_ex(Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype) -- cgit v1.2.3 From 434087981aa26212b3b3b30f838f4ef87994b8df Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 6 Apr 2015 14:54:28 +1000 Subject: Fix minor glitch getting depth from mouse cursor --- source/blender/editors/space_view3d/view3d_edit.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 671fc682409..706cb517683 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -4709,8 +4709,8 @@ bool ED_view3d_autodist(Scene *scene, ARegion *ar, View3D *v3d, depth_close = view_autodist_depth_margin(ar, mval, 4); if (depth_close != FLT_MAX) { - cent[0] = (double)mval[0]; - cent[1] = (double)mval[1]; + cent[0] = (double)mval[0] + 0.5; + cent[1] = (double)mval[1] + 0.5; if (gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) @@ -4761,8 +4761,8 @@ bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_world if (depth == FLT_MAX) return false; - cent[0] = (double)mval[0]; - cent[1] = (double)mval[1]; + cent[0] = (double)mval[0] + 0.5; + cent[1] = (double)mval[1] + 0.5; bgl_get_mats(&mats); -- cgit v1.2.3 From 986972701ea01667c97fe0831ac90a27ef15d881 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 6 Apr 2015 14:57:43 +1000 Subject: Fix T44249: Cursor depth offset --- source/blender/editors/space_view3d/view3d_edit.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 706cb517683..236fefc7088 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -4701,14 +4701,22 @@ bool ED_view3d_autodist(Scene *scene, ARegion *ar, View3D *v3d, bglMats mats; /* ZBuffer depth vars */ float depth_close; double cent[2], p[3]; + int margin_arr[] = {0, 2, 4}; + int i; + bool depth_ok = false; /* Get Z Depths, needed for perspective, nice for ortho */ bgl_get_mats(&mats); ED_view3d_draw_depth(scene, ar, v3d, alphaoverride); - depth_close = view_autodist_depth_margin(ar, mval, 4); + /* Attempt with low margin's first */ + i = 0; + do { + depth_close = view_autodist_depth_margin(ar, mval, margin_arr[i++] * U.pixelsize); + depth_ok = (depth_close != FLT_MAX); + } while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr))); - if (depth_close != FLT_MAX) { + if (depth_ok) { cent[0] = (double)mval[0] + 0.5; cent[1] = (double)mval[1] + 0.5; -- cgit v1.2.3 From 8cc475c40b8e0b316430b536dac7ca0251994124 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 6 Apr 2015 15:53:06 +1000 Subject: Fix T43696: Baking tearing normals Patch D1207 by @chrisr --- source/blender/render/intern/source/zbuf.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 7e8f0e3e9fc..be2927db9b0 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -1513,7 +1513,7 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float * float x0, y0, x1, y1, x2, y2, z0, z1, z2; float u, v, uxd, uyd, vxd, vyd, uy0, vy0, xx1; const float *span1, *span2; - int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2; + int i, j, x, y, sn1, sn2, rectx = zspan->rectx, my0, my2; /* init */ zbuf_init_span(zspan); @@ -1574,7 +1574,7 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float * span2= zspan->span1+my2; } - for (y=my2; y>=my0; y--, span1--, span2--) { + for (i = 0, y = my2; y >= my0; i++, y--, span1--, span2--) { sn1= floor(*span1); sn2= floor(*span2); @@ -1583,14 +1583,12 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float * if (sn2>=rectx) sn2= rectx-1; if (sn1<0) sn1= 0; - u= (double)sn1*uxd + uy0; - v= (double)sn1*vxd + vy0; - - for (x= sn1; x<=sn2; x++, u+=uxd, v+=vxd) - func(handle, x, y, u, v); + u = (((double)sn1 * uxd) + uy0) - (i * uyd); + v = (((double)sn1 * vxd) + vy0) - (i * vyd); - uy0 -= uyd; - vy0 -= vyd; + for (j = 0, x = sn1; x <= sn2; j++, x++) { + func(handle, x, y, u + (j * uxd), v + (j * vxd)); + } } } -- cgit v1.2.3 From dd3aa1b3725c9cd739a0cc0d22f4a3bcfed4fe0b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 6 Apr 2015 16:40:26 +1000 Subject: Cleanup: replace confusing 'if' statements --- source/blender/editors/screen/area.c | 6 ++-- source/blender/editors/space_view3d/view3d_draw.c | 15 +++++----- .../blender/render/intern/source/render_texture.c | 13 ++++----- source/blender/render/intern/source/shadeinput.c | 2 +- source/blender/render/intern/source/zbuf.c | 32 +++++++++++----------- 5 files changed, 33 insertions(+), 35 deletions(-) diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index c423d81bfe2..be9336cc984 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -773,7 +773,7 @@ static void region_azone_tab_plus(ScrArea *sa, AZone *az, ARegion *ar) switch (az->edge) { case AE_TOP_TO_BOTTOMRIGHT: - if (ar->winrct.ymax == sa->totrct.ymin) add = 1; else add = 0; + add = (ar->winrct.ymax == sa->totrct.ymin) ? 1 : 0; az->x1 = ar->winrct.xmax - 2.5f * AZONEPAD_TAB_PLUSW; az->y1 = ar->winrct.ymax - add; az->x2 = ar->winrct.xmax - 1.5f * AZONEPAD_TAB_PLUSW; @@ -818,7 +818,7 @@ static void region_azone_tab(ScrArea *sa, AZone *az, ARegion *ar) switch (az->edge) { case AE_TOP_TO_BOTTOMRIGHT: - if (ar->winrct.ymax == sa->totrct.ymin) add = 1; else add = 0; + add = (ar->winrct.ymax == sa->totrct.ymin) ? 1 : 0; az->x1 = ar->winrct.xmax - 2 * AZONEPAD_TABW; az->y1 = ar->winrct.ymax - add; az->x2 = ar->winrct.xmax - AZONEPAD_TABW; @@ -863,7 +863,7 @@ static void region_azone_tria(ScrArea *sa, AZone *az, ARegion *ar) switch (az->edge) { case AE_TOP_TO_BOTTOMRIGHT: - if (ar->winrct.ymax == sa->totrct.ymin) add = 1; else add = 0; + add = (ar->winrct.ymax == sa->totrct.ymin) ? 1 : 0; az->x1 = ar->winrct.xmax - 2 * AZONEPAD_TRIAW; az->y1 = ar->winrct.ymax - add; az->x2 = ar->winrct.xmax - AZONEPAD_TRIAW; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 8600c1190d4..e480593b1e5 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1482,14 +1482,15 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, short xminc, yminc, xmaxc, ymaxc, xs, ys; /* clip */ - if (xmin < 0) xminc = 0; else xminc = xmin; - if (xmax >= vc->ar->winx) xmaxc = vc->ar->winx - 1; else xmaxc = xmax; - if (xminc > xmaxc) return NULL; + xminc = max_ii(xmin, 0); + yminc = max_ii(ymin, 0); + xmaxc = min_ii(xmax, vc->ar->winx - 1); + ymaxc = min_ii(ymax, vc->ar->winy - 1); + + if (UNLIKELY((xminc > xmaxc) || (yminc > ymaxc))) { + return NULL; + } - if (ymin < 0) yminc = 0; else yminc = ymin; - if (ymax >= vc->ar->winy) ymaxc = vc->ar->winy - 1; else ymaxc = ymax; - if (yminc > ymaxc) return NULL; - ibuf = IMB_allocImBuf((xmaxc - xminc + 1), (ymaxc - yminc + 1), 32, IB_rect); view3d_validate_backbuf(vc); diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index dc8c714bea5..c6a80c822a3 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -1348,7 +1348,7 @@ int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct Image /* fact = texture strength, facg = button strength value */ void texture_rgb_blend(float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype) { - float facm, col; + float facm; switch (blendtype) { case MTEX_BLEND: @@ -1435,13 +1435,10 @@ void texture_rgb_blend(float in[3], const float tex[3], const float out[3], floa case MTEX_LIGHT: fact*= facg; - - col= fact*tex[0]; - if (col > out[0]) in[0]= col; else in[0]= out[0]; - col= fact*tex[1]; - if (col > out[1]) in[1]= col; else in[1]= out[1]; - col= fact*tex[2]; - if (col > out[2]) in[2]= col; else in[2]= out[2]; + + in[0] = max_ff(fact * tex[0], out[0]); + in[1] = max_ff(fact * tex[1], out[1]); + in[2] = max_ff(fact * tex[2], out[2]); break; case MTEX_BLEND_HUE: diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 01055d87a38..9ea7cb62c58 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -633,7 +633,7 @@ void shade_input_calc_viewco(ShadeInput *shi, float x, float y, float z, float v dyco[2] = 0.0f; if (dxyview) { - if (co[2] != 0.0f) fac = 1.0f / co[2]; else fac = 0.0f; + fac = (co[2] != 0.0f) ? (1.0f / co[2]) : 0.0f; dxyview[0] = -R.viewdx * fac; dxyview[1] = -R.viewdy * fac; } diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index be2927db9b0..d5d8595bf3f 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -330,8 +330,8 @@ static void zbuffillAc4(ZSpan *zspan, int obi, int zvlnr, /* clipped */ if (zspan->minp2==NULL || zspan->maxp2==NULL) return; - if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; - if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; + my0 = max_ii(zspan->miny1, zspan->miny2); + my2 = min_ii(zspan->maxy1, zspan->maxy2); if (my2minp2==NULL || zspan->maxp2==NULL) return; - if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; - if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; + my0 = max_ii(zspan->miny1, zspan->miny2); + my2 = min_ii(zspan->maxy1, zspan->maxy2); // printf("my %d %d\n", my0, my2); if (my2minp2==NULL || zspan->maxp2==NULL) return; - if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; - if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; + my0 = max_ii(zspan->miny1, zspan->miny2); + my2 = min_ii(zspan->maxy1, zspan->maxy2); // printf("my %d %d\n", my0, my2); if (my2minp2==NULL || zspan->maxp2==NULL) return; - if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; - if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; + my0 = max_ii(zspan->miny1, zspan->miny2); + my2 = min_ii(zspan->maxy1, zspan->maxy2); // printf("my %d %d\n", my0, my2); if (my2minp2==NULL || zspan->maxp2==NULL) return; - if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; - if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; + my0 = max_ii(zspan->miny1, zspan->miny2); + my2 = min_ii(zspan->maxy1, zspan->maxy2); // printf("my %d %d\n", my0, my2); if (my2minp2==NULL || zspan->maxp2==NULL) return; - if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; - if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; + my0 = max_ii(zspan->miny1, zspan->miny2); + my2 = min_ii(zspan->maxy1, zspan->maxy2); // printf("my %d %d\n", my0, my2); if (my2minp2==NULL || zspan->maxp2==NULL) return; - if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; - if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; + my0 = max_ii(zspan->miny1, zspan->miny2); + my2 = min_ii(zspan->maxy1, zspan->maxy2); if (my2minp2==NULL || zspan->maxp2==NULL) return; - if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; - if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; + my0 = max_ii(zspan->miny1, zspan->miny2); + my2 = min_ii(zspan->maxy1, zspan->maxy2); // printf("my %d %d\n", my0, my2); if (my2 Date: Mon, 6 Apr 2015 17:06:37 +1000 Subject: Only show image slot-name in render view --- release/scripts/startup/bl_ui/space_image.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index a75e0916c09..e2c2783fae1 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -625,6 +625,8 @@ class IMAGE_PT_view_properties(Panel): sima = context.space_data ima = sima.image + + show_render = sima.show_render show_uvedit = sima.show_uvedit show_maskedit = sima.show_maskedit uvedit = sima.uv_editor @@ -669,7 +671,7 @@ class IMAGE_PT_view_properties(Panel): sub.active = uvedit.show_stretch sub.row().prop(uvedit, "draw_stretch_type", expand=True) - if ima: + if show_render and ima: layout.separator() render_slot = ima.render_slots.active layout.prop(render_slot, "name", text="Slot Name") -- cgit v1.2.3 From a9bb8d8a73cad2edd96297c868ae3a3ab4b04e27 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 5 Apr 2015 22:13:10 +0500 Subject: Cycles: de-duplicate fast/approximate erf function calculation Our own implementation is in fact the same performance as in fast_math from OpenShadingLanguage, but implementation from fast_math is using explicit madd function, which increases chance of compiler deciding to use intrinsics. --- intern/cycles/kernel/closure/bsdf_microfacet.h | 81 ++------------------------ intern/cycles/util/util_math_fast.h | 4 +- 2 files changed, 8 insertions(+), 77 deletions(-) diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index b225e674702..32cf36abd27 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -35,75 +35,6 @@ CCL_NAMESPACE_BEGIN -/* Approximate erf and erfinv implementations. - * Implementation comes straight from Wikipedia: - * - * http://en.wikipedia.org/wiki/Error_function - * - * Some constants are baked into the code. - */ - -ccl_device_inline float approx_erff_do(float x) -{ - /* Such a clamp doesn't give much distortion to the output value - * and gives quite a few of the speedup. - */ - if(x > 3.0f) { - return 1.0f; - } - float t = 1.0f / (1.0f + 0.47047f*x); - return (1.0f - - t*(0.3480242f + t*(-0.0958798f + t*0.7478556f)) * expf(-x*x)); -} - -ccl_device_inline float approx_erff(float x) -{ - if(x >= 0.0f) { - return approx_erff_do(x); - } - else { - return -approx_erff_do(-x); - } -} - -ccl_device_inline float approx_erfinvf_do(float x) -{ - if(x <= 0.7f) { - const float x2 = x * x; - const float a1 = 0.886226899f; - const float a2 = -1.645349621f; - const float a3 = 0.914624893f; - const float a4 = -0.140543331f; - const float b1 = -2.118377725f; - const float b2 = 1.442710462f; - const float b3 = -0.329097515f; - const float b4 = 0.012229801f; - return x * (((a4 * x2 + a3) * x2 + a2) * x2 + a1) / - ((((b4 * x2 + b3) * x2 + b2) * x2 + b1) * x2 + 1.0f); - } - else { - const float c1 = -1.970840454f; - const float c2 = -1.624906493f; - const float c3 = 3.429567803f; - const float c4 = 1.641345311f; - const float d1 = 3.543889200f; - const float d2 = 1.637067800f; - const float z = sqrtf(-logf((1.0f - x) * 0.5f)); - return (((c4 * z + c3) * z + c2) * z + c1) / - ((d2 * z + d1) * z + 1.0f); - } -} - -ccl_device_inline float approx_erfinvf(float x) -{ - if(x >= 0.0f) { - return approx_erfinvf_do(x); - } - else { - return -approx_erfinvf_do(-x); - } -} - /* Beckmann and GGX microfacet importance sampling. */ ccl_device_inline void microfacet_beckmann_sample_slopes( @@ -126,7 +57,7 @@ ccl_device_inline void microfacet_beckmann_sample_slopes( const float tan_theta_i = sin_theta_i/cos_theta_i; const float inv_a = tan_theta_i; const float cot_theta_i = 1.0f/tan_theta_i; - const float erf_a = approx_erff(cot_theta_i); + const float erf_a = fast_erff(cot_theta_i); const float exp_a2 = expf(-cot_theta_i*cot_theta_i); const float SQRT_PI_INV = 0.56418958354f; const float Lambda = 0.5f*(erf_a - 1.0f) + (0.5f*SQRT_PI_INV)*(exp_a2*inv_a); @@ -156,31 +87,31 @@ ccl_device_inline void microfacet_beckmann_sample_slopes( float b = K > 0 ? (0.5f - sqrtf(K * (K - y_approx + 1.0f) + 0.25f)) / K : y_approx - 1.0f; /* Perform newton step to refine toward the true root. */ - float inv_erf = approx_erfinvf(b); + float inv_erf = fast_ierff(b); float value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact; /* Check if we are close enough already, * this also avoids NaNs as we get close to the root. */ if(fabsf(value) > 1e-6f) { b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 1. */ - inv_erf = approx_erfinvf(b); + inv_erf = fast_ierff(b); value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact; b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 2. */ /* Compute the slope from the refined value. */ - *slope_x = approx_erfinvf(b); + *slope_x = fast_ierff(b); } else { /* We are close enough already. */ *slope_x = inv_erf; } - *slope_y = approx_erfinvf(2.0f*randv - 1.0f); + *slope_y = fast_ierff(2.0f*randv - 1.0f); #else /* Use precomputed table on CPU, it gives better perfomance. */ int beckmann_table_offset = kernel_data.tables.beckmann_offset; *slope_x = lookup_table_read_2D(kg, randu, cos_theta_i, beckmann_table_offset, BECKMANN_TABLE_SIZE, BECKMANN_TABLE_SIZE); - *slope_y = approx_erfinvf(2.0f*randv - 1.0f); + *slope_y = fast_ierff(2.0f*randv - 1.0f); #endif } diff --git a/intern/cycles/util/util_math_fast.h b/intern/cycles/util/util_math_fast.h index 4ad81e9c015..1acceee22a5 100644 --- a/intern/cycles/util/util_math_fast.h +++ b/intern/cycles/util/util_math_fast.h @@ -539,7 +539,7 @@ ccl_device float fast_safe_powf(float x, float y) * bsdf_microfaset.h. */ -ccl_device float fast_erff(float x) +ccl_device_inline float fast_erff(float x) { /* Examined 1082130433 values of erff on [0,4]: 1.93715e-06 max error. */ /* Abramowitz and Stegun, 7.1.28. */ @@ -570,7 +570,7 @@ ccl_device_inline float fast_erfcf(float x) return 1.0f - fast_erff(x); } -ccl_device float fast_ierff(float x) +ccl_device_inline float fast_ierff(float x) { /* From: Approximating the erfinv function by Mike Giles. */ /* To avoid trouble at the limit, clamp input to 1-eps. */ -- cgit v1.2.3 From 3639a70eaec1d49e5634f2cd5f6d4ecb7d79ef14 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 6 Apr 2015 14:11:28 +0500 Subject: Fix T44222: Crash using pointiness attribute for volume shaders This attribute is not really supported for volumes, so it get's converted to constant 0 at shader compile time. TODO: We should consider doing the same for tangent attribute in order to save some annoying checks at tracing time. --- intern/cycles/render/nodes.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index a62634efa42..40bb82c6330 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -2248,10 +2248,15 @@ void GeometryNode::compile(SVMCompiler& compiler) out = output("Pointiness"); if(!out->links.empty()) { compiler.stack_assign(out); - compiler.add_node(attr_node, - ATTR_STD_POINTINESS, - out->stack_offset, - NODE_ATTR_FLOAT); + if(compiler.output_type() != SHADER_TYPE_VOLUME) { + compiler.add_node(attr_node, + ATTR_STD_POINTINESS, + out->stack_offset, + NODE_ATTR_FLOAT); + } + else { + compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), out->stack_offset); + } } } -- cgit v1.2.3 From dd129125b6f6c9fff5ef4423b221cf68fedbd188 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 6 Apr 2015 19:55:08 +1000 Subject: GHash: ensure function, avoids multiple lookups --- source/blender/blenlib/BLI_ghash.h | 1 + source/blender/blenlib/intern/BLI_ghash.c | 46 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index 16d18ef1315..a00ddeefb2b 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -79,6 +79,7 @@ bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfre void *BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT; void *BLI_ghash_lookup_default(GHash *gh, const void *key, void *val_default) ATTR_WARN_UNUSED_RESULT; void **BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT; +bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT; bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 11848804194..dae7af6a927 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -444,6 +444,22 @@ BLI_INLINE void ghash_insert_ex( ghash_buckets_expand(gh, ++gh->nentries, false); } +/** + * Insert function that takes a pre-allocated entry. + */ +BLI_INLINE void ghash_insert_ex_keyonly_entry( + GHash *gh, void *key, const unsigned int bucket_index, + Entry *e) +{ + BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)); + + e->next = gh->buckets[bucket_index]; + e->key = key; + gh->buckets[bucket_index] = e; + + ghash_buckets_expand(gh, ++gh->nentries, false); +} + /** * Insert function that doesn't set the value (use for GSet) */ @@ -720,6 +736,36 @@ void **BLI_ghash_lookup_p(GHash *gh, const void *key) return e ? &e->val : NULL; } +/** + * Ensure \a key is exists in \a gh. + * + * This handles the common situation where the caller needs ensure a key is added to \a gh, + * constructing a new value in the case the key isn't found. + * Otherwise use the existing value. + * + * Such situations typically incur multiple lookups, however this function + * avoids them by ensuring the key is added, + * returning a pointer to the value so it can be used or initialized by the caller. + * + * \returns true when the value didn't need to be added. + * (when false, the caller _must_ initialize the value). + */ +bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) +{ + const unsigned int hash = ghash_keyhash(gh, key); + const unsigned int bucket_index = ghash_bucket_index(gh, hash); + GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index); + const bool haskey = (e != NULL); + + if (!haskey) { + e = BLI_mempool_alloc(gh->entrypool); + ghash_insert_ex_keyonly_entry(gh, key, bucket_index, (Entry *)e); + } + + *r_val = &e->val; + return haskey; +} + /** * Remove \a key from \a gh, or return false if the key wasn't found. * -- cgit v1.2.3 From 26e50295ceb81bd09f65d30116f897ba53e50daf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 6 Apr 2015 20:03:49 +1000 Subject: Use BKE_ghash_ensure_p where possible --- source/blender/blenkernel/intern/icons.c | 8 ++--- source/blender/blenkernel/intern/treehash.c | 10 +++--- source/blender/blenlib/intern/scanfill_utils.c | 10 +++--- source/blender/bmesh/intern/bmesh_log.c | 5 +-- source/blender/bmesh/tools/bmesh_region_match.c | 25 +++++++++------ source/blender/editors/transform/transform.c | 5 +-- source/blender/modifiers/intern/MOD_build.c | 42 +++++++++++++++---------- 7 files changed, 62 insertions(+), 43 deletions(-) diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index 8bda957f187..d3225f3fa35 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -311,16 +311,14 @@ Icon *BKE_icon_get(int icon_id) void BKE_icon_set(int icon_id, struct Icon *icon) { - Icon *old_icon = NULL; + void **val_p; - old_icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(icon_id)); - - if (old_icon) { + if (BLI_ghash_ensure_p(gIcons, SET_INT_IN_POINTER(icon_id), &val_p)) { printf("BKE_icon_set: Internal error, icon already set: %d\n", icon_id); return; } - BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(icon_id), icon); + *val_p = icon; } void BKE_icon_delete(struct ID *id) diff --git a/source/blender/blenkernel/intern/treehash.c b/source/blender/blenkernel/intern/treehash.c index 866502c4ae1..43eeae7329e 100644 --- a/source/blender/blenkernel/intern/treehash.c +++ b/source/blender/blenkernel/intern/treehash.c @@ -129,11 +129,13 @@ void *BKE_treehash_rebuild_from_treestore(void *treehash, BLI_mempool *treestore void BKE_treehash_add_element(void *treehash, TreeStoreElem *elem) { - TseGroup *group = BLI_ghash_lookup(treehash, elem); - if (!group) { - group = tse_group_create(); - BLI_ghash_insert(treehash, elem, group); + TseGroup *group; + void **val_p; + + if (!BLI_ghash_ensure_p(treehash, elem, &val_p)) { + *val_p = tse_group_create(); } + group = *val_p; tse_group_add(group, elem); } diff --git a/source/blender/blenlib/intern/scanfill_utils.c b/source/blender/blenlib/intern/scanfill_utils.c index a606ac41aa1..d0420a30448 100644 --- a/source/blender/blenlib/intern/scanfill_utils.c +++ b/source/blender/blenlib/intern/scanfill_utils.c @@ -112,11 +112,13 @@ void BLI_scanfill_view3d_dump(ScanFillContext *sf_ctx) static ListBase *edge_isect_ls_ensure(GHash *isect_hash, ScanFillEdge *eed) { ListBase *e_ls; - e_ls = BLI_ghash_lookup(isect_hash, eed); - if (e_ls == NULL) { - e_ls = MEM_callocN(sizeof(ListBase), __func__); - BLI_ghash_insert(isect_hash, eed, e_ls); + void **val_p; + + if (!BLI_ghash_ensure_p(isect_hash, eed, &val_p)) { + *val_p = MEM_callocN(sizeof(ListBase), __func__); } + e_ls = *val_p; + return e_ls; } diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index 158c2aa4263..c53b7f939c9 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -836,14 +836,15 @@ void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_o BMLogVert *lv; unsigned int v_id = bm_log_vert_id_get(log, v); void *key = SET_UINT_IN_POINTER(v_id); + void **val_p; /* Find or create the BMLogVert entry */ if ((lv = BLI_ghash_lookup(entry->added_verts, key))) { bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset); } - else if (!BLI_ghash_haskey(entry->modified_verts, key)) { + else if (!BLI_ghash_ensure_p(entry->modified_verts, key, &val_p)) { lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset); - BLI_ghash_insert(entry->modified_verts, key, lv); + *val_p = lv; } } diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c index c695d4c1774..0c0bb892f7b 100644 --- a/source/blender/bmesh/tools/bmesh_region_match.c +++ b/source/blender/bmesh/tools/bmesh_region_match.c @@ -534,12 +534,13 @@ static void bm_uuidwalk_pass_add( l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { /* fill verts_new */ + void **val_p; if (!BLI_ghash_haskey(uuidwalk->verts_uuid, l_iter->v) && - !BLI_ghash_haskey(verts_uuid_pass, l_iter->v) && + !BLI_ghash_ensure_p(verts_uuid_pass, l_iter->v, &val_p) && (bm_vert_is_uuid_connect(uuidwalk, l_iter->v) == true)) { const UUID_Int uuid = bm_uuidwalk_calc_vert_uuid(uuidwalk, l_iter->v); - BLI_ghash_insert(verts_uuid_pass, l_iter->v, (void *)uuid); + *val_p = (void *)uuid; } /* fill faces_step_next */ @@ -667,13 +668,15 @@ static bool bm_uuidwalk_facestep_begin( if (!BLI_ghash_haskey(uuidwalk->faces_uuid, f)) { const UUID_Int uuid = bm_uuidwalk_calc_face_uuid(uuidwalk, f); UUIDFaceStepItem *fstep_item; + void **val_p; ok = true; - fstep_item = BLI_ghash_lookup(uuidwalk->cache.faces_from_uuid, (void *)uuid); - if (UNLIKELY(fstep_item == NULL)) { - fstep_item = BLI_mempool_alloc(uuidwalk->step_pool_items); - BLI_ghash_insert(uuidwalk->cache.faces_from_uuid, (void *)uuid, fstep_item); + if (BLI_ghash_ensure_p(uuidwalk->cache.faces_from_uuid, (void *)uuid, &val_p)) { + fstep_item = *val_p; + } + else { + fstep_item = *val_p = BLI_mempool_alloc(uuidwalk->step_pool_items); /* add to start, so its handled on the next round of passes */ BLI_addhead(&fstep->items, fstep_item); @@ -1111,9 +1114,10 @@ static BMEdge *bm_face_region_pivot_edge_find( if (bm_edge_is_region_boundary(e)) { unsigned int j; for (j = 0; j < 2; j++) { - if (!BLI_ghash_haskey(gh, (&e->v1)[j])) { + void **val_p; + if (!BLI_ghash_ensure_p(gh, (&e->v1)[j], &val_p)) { SUID_Int v_id = bm_face_region_vert_boundary_id((&e->v1)[j]); - BLI_ghash_insert(gh, (&e->v1)[j], (void *)v_id); + *val_p = (void *)v_id; BLI_LINKSTACK_PUSH(vert_queue_prev, (&e->v1)[j]); vert_queue_used += 1; } @@ -1137,10 +1141,11 @@ static BMEdge *bm_face_region_pivot_edge_find( if (BM_elem_flag_test(e, BM_ELEM_TAG)) { BMVert *v_other = BM_edge_other_vert(e, v); if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) { - if (!BLI_ghash_haskey(gh, v_other)) { + void **val_p; + if (!BLI_ghash_ensure_p(gh, v_other, &val_p)) { /* add as negative, so we know not to read from them this pass */ const SUID_Int v_id_other = -bm_face_region_vert_pass_id(gh, v_other); - BLI_ghash_insert(gh, v_other, (void *)v_id_other); + *val_p = (void *)v_id_other; BLI_LINKSTACK_PUSH(vert_queue_next, v_other); vert_queue_used += 1; } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 401accba40b..161b8ca232d 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -5266,9 +5266,10 @@ static void slide_origdata_create_data_vert( loop_weights = BLI_array_alloca(loop_weights, l_num); for (j = 0; j < l_num; j++) { BMLoop *l = BM_iter_step(&liter); - if (!BLI_ghash_haskey(sod->origfaces, l->f)) { + void **val_p; + if (!BLI_ghash_ensure_p(sod->origfaces, l->f, &val_p)) { BMFace *f_copy = BM_face_copy(sod->bm_origfaces, bm, l->f, true, true); - BLI_ghash_insert(sod->origfaces, l->f, f_copy); + *val_p = f_copy; } loop_weights[j] = BM_loop_calc_face_angle(l); } diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index 1dc1a1f8d64..96337c33373 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -131,6 +131,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), MPoly *mpoly, *mp; MLoop *ml, *mloop; MEdge *medge; + uintptr_t hash_num, hash_num_alt; if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) { BLI_array_randomize(faceMap, sizeof(*faceMap), @@ -142,40 +143,44 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), */ mpoly = mpoly_src; mloop = mloop_src; + hash_num = 0; for (i = 0; i < numFaces_dst; i++) { mp = mpoly + faceMap[i]; ml = mloop + mp->loopstart; for (j = 0; j < mp->totloop; j++, ml++) { - if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(ml->v))) - BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(ml->v), - SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); + void **val_p; + if (!BLI_ghash_ensure_p(vertHash, SET_INT_IN_POINTER(ml->v), &val_p)) { + *val_p = (void *)hash_num; + hash_num++; + } } - + numLoops_dst += mp->totloop; } + BLI_assert(hash_num == BLI_ghash_size(vertHash)); /* get the set of edges that will be in the new mesh (i.e. all edges * that have both verts in the new mesh) */ medge = medge_src; - for (i = 0; i < numEdge_src; i++) { + hash_num = 0; + hash_num_alt = 0; + for (i = 0; i < numEdge_src; i++, hash_num_alt++) { MEdge *me = medge + i; if (BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1)) && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2))) { - j = BLI_ghash_size(edgeHash); - - BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(j), - SET_INT_IN_POINTER(i)); - BLI_ghash_insert(edgeHash2, SET_INT_IN_POINTER(i), - SET_INT_IN_POINTER(j)); + BLI_ghash_insert(edgeHash, (void *)hash_num, (void *)hash_num_alt); + BLI_ghash_insert(edgeHash2, (void *)hash_num_alt, (void *)hash_num); + hash_num++; } } } else if (numEdges_dst) { MEdge *medge, *me; + uintptr_t hash_num; if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) BLI_array_randomize(edgeMap, sizeof(*edgeMap), @@ -185,17 +190,22 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), * mapped to the new indices */ medge = medge_src; + hash_num = 0; + BLI_assert(hash_num == BLI_ghash_size(vertHash)); for (i = 0; i < numEdges_dst; i++) { + void **val_p; me = medge + edgeMap[i]; - if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1))) { - BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me->v1), - SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); + if (!BLI_ghash_ensure_p(vertHash, SET_INT_IN_POINTER(me->v1), &val_p)) { + *val_p = (void *)hash_num; + hash_num++; } - if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2))) { - BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me->v2), SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); + if (!BLI_ghash_ensure_p(vertHash, SET_INT_IN_POINTER(me->v2), &val_p)) { + *val_p = (void *)hash_num; + hash_num++; } } + BLI_assert(hash_num == BLI_ghash_size(vertHash)); /* get the set of edges that will be in the new mesh */ for (i = 0; i < numEdges_dst; i++) { -- cgit v1.2.3 From 883663a0ad7fd1cbb7bdc9cf4429217ef1f3b9de Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 6 Apr 2015 13:13:35 +0200 Subject: Fix T44278: Tab, Z-Key and Spacebar not working Seems like a fix that is needed for some X11 systems causes this bug on others :| Not sure if the systems that needed this fix are now still fine (since I did a slight change to the click type check procedure), but I need to check that on my system in the institute in a bit. --- source/blender/windowmanager/intern/wm_event_system.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 0a8da1df233..225e3138859 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -3025,12 +3025,9 @@ static void wm_event_clicktype_init(wmWindow *win, wmEvent *event, wmEvent *even } } + /* click */ if ((PIL_check_seconds_timer() - event->click_time) * 1000 <= U.click_timeout) { - /* for any reason some X11 systems send two release events triggering two KM_CLICK events - * - making the rules more strict by checking for prevval resolves this (not needed for mouse) */ - if (event->val == KM_RELEASE && - (ISMOUSE(event->type) || event->prevval != KM_RELEASE)) - { + if (event->val == KM_RELEASE) { click_type = KM_CLICK; if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) { printf("%s Send click event\n", __func__); -- cgit v1.2.3 From bb2300de945f625abf602a2dcce077f32797a226 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 6 Apr 2015 14:12:05 +0200 Subject: Fix T44282: Image sampling line disappears after a while Now even to master --- source/blender/editors/space_image/image_ops.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 976c7675371..5890ed61118 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -2609,8 +2609,11 @@ static int image_sample_modal(bContext *C, wmOperator *op, const wmEvent *event) switch (event->type) { case LEFTMOUSE: case RIGHTMOUSE: // XXX hardcoded + if (event->val == KM_RELEASE) { image_sample_exit(C, op); return OPERATOR_CANCELLED; + } + break; case MOUSEMOVE: image_sample_apply(C, op, event); break; -- cgit v1.2.3 From 74df307ca43df14b759fd9eb6a049a6c5d90dcda Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 2 Apr 2015 19:24:14 +0500 Subject: Cycles: Free unused image buffers when rendering with locked interface It is still possible to free a bit more memory by detecting buildin images which are not used by shaders, but that's not going to improve memory usage that much to bother about this now. Such change brings peak memory usage from 4.1GB to 3.4GB when rendering 01_01_01_D layout scene from the Gooseberry project. Mainly because of freeing memory used by rather huge environment map in the viewport. Reviewers: campbellbarton, juicyfruit Subscribers: eyecandy Differential Revision: https://developer.blender.org/D1215 --- intern/cycles/blender/blender_sync.cpp | 33 ++++++++++++++++++++++++++ intern/cycles/blender/blender_sync.h | 3 +++ source/blender/makesrna/intern/rna_image_api.c | 8 +++++++ 3 files changed, 44 insertions(+) diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 2ed61860066..aaf7d7d58ef 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -150,6 +150,7 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, void * sync_integrator(); sync_film(); sync_shaders(); + sync_images(); sync_curve_settings(); mesh_synced.clear(); /* use for objects and motion sync */ @@ -360,6 +361,38 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) } } +/* Images */ +void BlenderSync::sync_images() +{ + /* Sync is a convention for this API, but currently it frees unused buffers. */ + + const bool is_interface_locked = b_engine.render() && + b_engine.render().use_lock_interface(); + if(is_interface_locked == false && BlenderSession::headless == false) { + /* If interface is not locked, it's possible image is needed for + * the display. + */ + return; + } + /* Free buffers used by images which are not needed for render. */ + BL::BlendData::images_iterator b_image; + for(b_data.images.begin(b_image); + b_image != b_data.images.end(); + ++b_image) + { + /* TODO(sergey): Consider making it an utility function to check + * whether image is considered builtin. + */ + const bool is_builtin = b_image->packed_file() || + b_image->source() == BL::Image::source_GENERATED || + b_image->source() == BL::Image::source_MOVIE; + if(is_builtin == false) { + b_image->buffers_free(); + } + /* TODO(sergey): Free builtin images not used by any shader. */ + } +} + /* Scene Parameters */ SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background, bool is_cpu) diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 2c2e41fbca2..5fbf2c3011f 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -95,6 +95,9 @@ private: /* particles */ bool sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object); + /* Images. */ + void sync_images(); + /* util */ void find_shader(BL::ID id, vector& used_shaders, int default_shader); bool BKE_object_is_modified(BL::Object b_ob); diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index b9a1237c1f2..7fb5885f709 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -288,6 +288,11 @@ static void rna_Image_filepath_from_user(Image *image, ImageUser *image_user, ch BKE_image_user_file_path(image_user, image, filepath); } +static void rna_Image_buffers_free(Image *image) +{ + BKE_image_free_buffers(image); +} + #else void RNA_api_image(StructRNA *srna) @@ -374,6 +379,9 @@ void RNA_api_image(StructRNA *srna) RNA_def_property_flag(parm, PROP_THICK_WRAP); /* needed for string return value */ RNA_def_function_output(func, parm); + func = RNA_def_function(srna, "buffers_free", "rna_Image_buffers_free"); + RNA_def_function_ui_description(func, "Free the image buffers from memory"); + /* TODO, pack/unpack, maybe should be generic functions? */ } -- cgit v1.2.3 From d5f1b9c2223333e03f2e4994171ad9df8c1c4f21 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Mon, 6 Apr 2015 10:40:12 -0300 Subject: Multi-View and Stereo 3D Official Documentation: http://www.blender.org/manual/render/workflows/multiview.html Implemented Features ==================== Builtin Stereo Camera * Convergence Mode * Interocular Distance * Convergence Distance * Pivot Mode Viewport * Cameras * Plane * Volume Compositor * View Switch Node * Image Node Multi-View OpenEXR support Sequencer * Image/Movie Strips 'Use Multiview' UV/Image Editor * Option to see Multi-View images in Stereo-3D or its individual images * Save/Open Multi-View (OpenEXR, Stereo3D, individual views) images I/O * Save/Open Multi-View (OpenEXR, Stereo3D, individual views) images Scene Render Views * Ability to have an arbitrary number of views in the scene Missing Bits ============ First rule of Multi-View bug report: If something is not working as it should *when Views is off* this is a severe bug, do mention this in the report. Second rule is, if something works *when Views is off* but doesn't (or crashes) when *Views is on*, this is a important bug. Do mention this in the report. Everything else is likely small todos, and may wait until we are sure none of the above is happening. Apart from that there are those known issues: * Compositor Image Node poorly working for Multi-View OpenEXR (this was working prefectly before the 'Use Multi-View' functionality) * Selecting camera from Multi-View when looking from camera is problematic * Animation Playback (ctrl+F11) doesn't support stereo formats * Wrong filepath when trying to play back animated scene * Viewport Rendering doesn't support Multi-View * Overscan Rendering * Fullscreen display modes need to warn the user * Object copy should be aware of views suffix Acknowledgments =============== * Francesco Siddi for the help with the original feature specs and design * Brecht Van Lommel for the original review of the code and design early on * Blender Foundation for the Development Fund to support the project wrap up Final patch reviewers: * Antony Riakiotakis (psy-fi) * Campbell Barton (ideasman42) * Julian Eisel (Severin) * Sergey Sharybin (nazgul) * Thomas Dinged (dingto) Code contributors of the original branch in github: * Alexey Akishin * Gabriel Caraballo --- intern/cycles/blender/addon/ui.py | 46 +- intern/cycles/blender/blender_camera.cpp | 54 +- intern/cycles/blender/blender_session.cpp | 74 +- intern/cycles/blender/blender_session.h | 1 + .../startup/bl_ui/properties_data_camera.py | 29 + release/scripts/startup/bl_ui/properties_render.py | 2 + .../startup/bl_ui/properties_render_layer.py | 58 + release/scripts/startup/bl_ui/space_image.py | 4 + release/scripts/startup/bl_ui/space_info.py | 4 + release/scripts/startup/bl_ui/space_sequencer.py | 16 +- release/scripts/startup/bl_ui/space_view3d.py | 40 +- release/scripts/startup/nodeitems_builtins.py | 1 + source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/BKE_camera.h | 8 + source/blender/blenkernel/BKE_image.h | 40 +- source/blender/blenkernel/BKE_node.h | 4 +- source/blender/blenkernel/BKE_scene.h | 21 + source/blender/blenkernel/BKE_sequencer.h | 11 +- source/blender/blenkernel/BKE_writeavi.h | 18 +- source/blender/blenkernel/BKE_writeffmpeg.h | 13 +- source/blender/blenkernel/BKE_writeframeserver.h | 13 +- source/blender/blenkernel/intern/bpath.c | 4 +- source/blender/blenkernel/intern/camera.c | 254 +++- source/blender/blenkernel/intern/image.c | 1157 +++++++++++++++--- source/blender/blenkernel/intern/node.c | 1 + source/blender/blenkernel/intern/ocean.c | 2 +- source/blender/blenkernel/intern/packedFile.c | 64 +- source/blender/blenkernel/intern/scene.c | 350 +++++- source/blender/blenkernel/intern/seqcache.c | 7 +- source/blender/blenkernel/intern/sequencer.c | 902 +++++++++++--- source/blender/blenkernel/intern/writeavi.c | 88 +- source/blender/blenkernel/intern/writeffmpeg.c | 408 ++++--- .../blender/blenkernel/intern/writeframeserver.c | 132 +- source/blender/blenlib/BLI_threads.h | 1 + source/blender/blenlib/intern/threads.c | 5 + source/blender/blenloader/intern/readfile.c | 41 +- source/blender/blenloader/intern/versioning_270.c | 88 +- source/blender/blenloader/intern/writefile.c | 31 +- source/blender/collada/ImageExporter.cpp | 2 +- source/blender/compositor/CMakeLists.txt | 4 + source/blender/compositor/COM_compositor.h | 3 +- .../compositor/intern/COM_CompositorContext.h | 17 +- source/blender/compositor/intern/COM_Converter.cpp | 4 + .../compositor/intern/COM_ExecutionSystem.cpp | 4 +- .../compositor/intern/COM_ExecutionSystem.h | 3 +- .../blender/compositor/intern/COM_compositor.cpp | 7 +- .../compositor/nodes/COM_CompositorNode.cpp | 1 + source/blender/compositor/nodes/COM_ImageNode.cpp | 50 +- source/blender/compositor/nodes/COM_ImageNode.h | 2 +- .../compositor/nodes/COM_OutputFileNode.cpp | 46 +- .../compositor/nodes/COM_RenderLayersNode.cpp | 3 +- .../compositor/nodes/COM_SplitViewerNode.cpp | 4 + .../compositor/nodes/COM_SwitchViewNode.cpp | 42 + .../blender/compositor/nodes/COM_SwitchViewNode.h | 37 + source/blender/compositor/nodes/COM_ViewerNode.cpp | 5 + .../operations/COM_CompositorOperation.cpp | 15 +- .../operations/COM_CompositorOperation.h | 6 + .../compositor/operations/COM_ImageOperation.cpp | 11 +- .../compositor/operations/COM_ImageOperation.h | 7 +- .../operations/COM_MultilayerImageOperation.cpp | 23 +- .../operations/COM_MultilayerImageOperation.h | 11 +- .../COM_OutputFileMultiViewOperation.cpp | 317 +++++ .../operations/COM_OutputFileMultiViewOperation.h | 74 ++ .../operations/COM_OutputFileOperation.cpp | 116 +- .../operations/COM_OutputFileOperation.h | 15 +- .../compositor/operations/COM_RenderLayersProg.cpp | 10 +- .../compositor/operations/COM_RenderLayersProg.h | 9 +- .../compositor/operations/COM_ViewerOperation.cpp | 15 +- .../compositor/operations/COM_ViewerOperation.h | 6 +- source/blender/editors/include/ED_screen.h | 1 + source/blender/editors/include/ED_view3d.h | 7 +- source/blender/editors/include/UI_interface.h | 3 + source/blender/editors/interface/interface_ops.c | 1 + source/blender/editors/object/object_bake_api.c | 2 +- source/blender/editors/render/render_intern.h | 3 + source/blender/editors/render/render_internal.c | 21 +- source/blender/editors/render/render_opengl.c | 347 ++++-- source/blender/editors/render/render_ops.c | 3 + source/blender/editors/render/render_preview.c | 10 +- source/blender/editors/render/render_shading.c | 64 + source/blender/editors/screen/area.c | 1 - source/blender/editors/screen/screen_edit.c | 82 ++ source/blender/editors/screen/screen_ops.c | 1 + source/blender/editors/screen/screendump.c | 29 +- source/blender/editors/sculpt_paint/paint_image.c | 2 +- .../blender/editors/sculpt_paint/paint_image_2d.c | 2 +- .../editors/sculpt_paint/paint_image_proj.c | 4 +- source/blender/editors/space_image/image_buttons.c | 266 +++- source/blender/editors/space_image/image_draw.c | 12 +- source/blender/editors/space_image/image_ops.c | 491 ++++++-- source/blender/editors/space_image/space_image.c | 3 +- source/blender/editors/space_node/drawnode.c | 56 +- source/blender/editors/space_node/node_edit.c | 56 +- source/blender/editors/space_node/node_intern.h | 2 + source/blender/editors/space_node/node_ops.c | 2 + .../editors/space_sequencer/sequencer_add.c | 92 +- .../editors/space_sequencer/sequencer_draw.c | 10 +- .../editors/space_sequencer/sequencer_edit.c | 20 +- .../editors/space_sequencer/sequencer_intern.h | 2 +- .../editors/space_sequencer/sequencer_view.c | 2 +- source/blender/editors/space_view3d/drawobject.c | 263 +++- source/blender/editors/space_view3d/space_view3d.c | 8 +- source/blender/editors/space_view3d/view3d_draw.c | 162 ++- .../intern/blender_interface/FRS_freestyle.cpp | 9 +- source/blender/gpu/GPU_draw.h | 2 +- source/blender/gpu/intern/gpu_draw.c | 4 +- source/blender/imbuf/CMakeLists.txt | 1 + source/blender/imbuf/IMB_imbuf.h | 40 +- source/blender/imbuf/IMB_imbuf_types.h | 4 +- source/blender/imbuf/intern/IMB_anim.h | 1 + source/blender/imbuf/intern/anim_movie.c | 5 + source/blender/imbuf/intern/indexer.c | 12 +- .../blender/imbuf/intern/openexr/openexr_api.cpp | 1030 +++++++++++++--- .../blender/imbuf/intern/openexr/openexr_multi.h | 39 +- .../blender/imbuf/intern/openexr/openexr_stub.cpp | 46 +- source/blender/imbuf/intern/stereoimbuf.c | 1292 ++++++++++++++++++++ source/blender/imbuf/intern/thumbs.c | 2 +- source/blender/imbuf/intern/util.c | 12 + source/blender/imbuf/intern/writeimage.c | 30 +- source/blender/makesdna/DNA_camera_types.h | 27 + source/blender/makesdna/DNA_image_types.h | 52 +- source/blender/makesdna/DNA_node_types.h | 1 + source/blender/makesdna/DNA_scene_types.h | 94 +- source/blender/makesdna/DNA_sequence_types.h | 15 +- source/blender/makesdna/DNA_space_types.h | 3 + source/blender/makesdna/DNA_view3d_types.h | 16 +- source/blender/makesdna/DNA_windowmanager_types.h | 6 +- source/blender/makesrna/RNA_access.h | 2 + source/blender/makesrna/RNA_enum_types.h | 7 + source/blender/makesrna/intern/rna_camera.c | 67 + source/blender/makesrna/intern/rna_color.c | 11 +- source/blender/makesrna/intern/rna_image.c | 109 +- source/blender/makesrna/intern/rna_image_api.c | 2 +- source/blender/makesrna/intern/rna_main_api.c | 5 +- source/blender/makesrna/intern/rna_nodetree.c | 97 ++ source/blender/makesrna/intern/rna_render.c | 128 +- source/blender/makesrna/intern/rna_scene.c | 393 +++++- source/blender/makesrna/intern/rna_scene_api.c | 8 +- source/blender/makesrna/intern/rna_sequencer.c | 41 + source/blender/makesrna/intern/rna_sequencer_api.c | 7 +- source/blender/makesrna/intern/rna_space.c | 133 +- source/blender/makesrna/intern/rna_ui_api.c | 10 + source/blender/makesrna/intern/rna_userdef.c | 4 +- source/blender/makesrna/intern/rna_wm.c | 39 + source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_composite.h | 1 + source/blender/nodes/NOD_static_types.h | 1 + .../blender/nodes/composite/node_composite_tree.c | 7 +- .../nodes/composite/nodes/node_composite_image.c | 11 +- .../composite/nodes/node_composite_outputFile.c | 4 +- .../composite/nodes/node_composite_switchview.c | 153 +++ source/blender/quicktime/apple/qtkit_export.m | 43 +- source/blender/quicktime/quicktime_export.h | 10 +- source/blender/render/extern/include/RE_engine.h | 6 +- source/blender/render/extern/include/RE_pipeline.h | 65 +- .../blender/render/intern/include/render_result.h | 21 +- .../blender/render/intern/include/render_types.h | 3 + .../blender/render/intern/source/convertblender.c | 6 +- source/blender/render/intern/source/envmap.c | 6 +- .../blender/render/intern/source/external_engine.c | 27 +- source/blender/render/intern/source/initrender.c | 20 +- source/blender/render/intern/source/pipeline.c | 1099 ++++++++++++----- .../blender/render/intern/source/render_result.c | 815 ++++++++---- source/blender/render/intern/source/rendercore.c | 111 +- source/blender/render/intern/source/zbuf.c | 14 +- source/blender/windowmanager/CMakeLists.txt | 1 + source/blender/windowmanager/WM_api.h | 1 + source/blender/windowmanager/intern/wm_draw.c | 284 ++++- source/blender/windowmanager/intern/wm_files.c | 4 +- source/blender/windowmanager/intern/wm_operators.c | 43 +- source/blender/windowmanager/intern/wm_stereo.c | 534 ++++++++ source/blender/windowmanager/intern/wm_window.c | 27 +- source/blender/windowmanager/wm.h | 7 + source/blender/windowmanager/wm_draw.h | 21 + source/blenderplayer/bad_level_call_stubs/stubs.c | 23 +- 175 files changed, 11910 insertions(+), 2158 deletions(-) create mode 100644 source/blender/compositor/nodes/COM_SwitchViewNode.cpp create mode 100644 source/blender/compositor/nodes/COM_SwitchViewNode.h create mode 100644 source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp create mode 100644 source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h create mode 100644 source/blender/imbuf/intern/stereoimbuf.c create mode 100644 source/blender/nodes/composite/nodes/node_composite_switchview.c create mode 100644 source/blender/windowmanager/intern/wm_stereo.c diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 956d8b962e9..74de31850ee 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -18,7 +18,7 @@ import bpy -from bpy.types import Panel, Menu, Operator +from bpy.types import Panel, Menu, Operator, UIList class CYCLES_MT_sampling_presets(Menu): @@ -413,6 +413,49 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel): col.prop(rl, "use_pass_environment") +class CyclesRender_PT_views(CyclesButtonsPanel, Panel): + bl_label = "Views" + bl_context = "render_layer" + + def draw_header(self, context): + rd = context.scene.render + self.layout.prop(rd, "use_multiview", text="") + + def draw(self, context): + layout = self.layout + + scene = context.scene + rd = scene.render + rv = rd.views.active + + + layout.active = rd.use_multiview + basic_stereo = (rd.views_format == 'STEREO_3D') + + row = layout.row() + row.prop(rd, "views_format", expand=True) + + if basic_stereo: + row = layout.row() + row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2) + + row = layout.row() + row.label(text="File Suffix:") + row.prop(rv, "file_suffix", text="") + + else: + row = layout.row() + row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2) + + col = row.column(align=True) + col.operator("scene.render_view_add", icon='ZOOMIN', text="") + col.operator("scene.render_view_remove", icon='ZOOMOUT', text="") + + row = layout.row() + row.label(text="Camera Suffix:") + row.prop(rv, "camera_suffix", text="") + + class Cycles_PT_post_processing(CyclesButtonsPanel, Panel): bl_label = "Post Processing" bl_options = {'DEFAULT_CLOSED'} @@ -1428,6 +1471,7 @@ def get_panels(): "DATA_PT_vertex_colors", "DATA_PT_camera", "DATA_PT_camera_display", + "DATA_PT_camera_stereoscopy", "DATA_PT_camera_safe_areas", "DATA_PT_lens", "DATA_PT_speaker", diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index 5b3e666e7c7..fffc46ec9a6 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -95,7 +95,7 @@ static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings b_render bcam->full_height = render_resolution_y(b_render); } -static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera) +static float blender_camera_focal_distance(BL::RenderEngine b_engine, BL::Object b_ob, BL::Camera b_camera) { BL::Object b_dof_object = b_camera.dof_object(); @@ -103,14 +103,16 @@ static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera) return b_camera.dof_distance(); /* for dof object, return distance along camera Z direction */ - Transform obmat = transform_clear_scale(get_transform(b_ob.matrix_world())); + BL::Array b_ob_matrix; + b_engine.camera_model_matrix(b_ob, b_ob_matrix); + Transform obmat = get_transform(b_ob_matrix); Transform dofmat = get_transform(b_dof_object.matrix_world()); Transform mat = transform_inverse(obmat) * dofmat; return fabsf(transform_get_column(&mat, 3).z); } -static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, bool skip_panorama = false) +static void blender_camera_from_object(BlenderCamera *bcam, BL::RenderEngine b_engine, BL::Object b_ob, bool skip_panorama = false) { BL::ID b_ob_data = b_ob.data(); @@ -181,10 +183,10 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, boo bcam->apertureblades = RNA_int_get(&ccamera, "aperture_blades"); bcam->aperturerotation = RNA_float_get(&ccamera, "aperture_rotation"); - bcam->focaldistance = blender_camera_focal_distance(b_ob, b_camera); + bcam->focaldistance = blender_camera_focal_distance(b_engine, b_ob, b_camera); bcam->aperture_ratio = RNA_float_get(&ccamera, "aperture_ratio"); - bcam->shift.x = b_camera.shift_x(); + bcam->shift.x = b_engine.camera_shift_x(b_ob); bcam->shift.y = b_camera.shift_y(); bcam->sensor_width = b_camera.sensor_width(); @@ -402,8 +404,10 @@ void BlenderSync::sync_camera(BL::RenderSettings b_render, BL::Object b_override b_ob = b_override; if(b_ob) { - blender_camera_from_object(&bcam, b_ob); - bcam.matrix = get_transform(b_ob.matrix_world()); + BL::Array b_ob_matrix; + blender_camera_from_object(&bcam, b_engine, b_ob); + b_engine.camera_model_matrix(b_ob, b_ob_matrix); + bcam.matrix = get_transform(b_ob_matrix); } /* sync */ @@ -414,8 +418,9 @@ void BlenderSync::sync_camera(BL::RenderSettings b_render, BL::Object b_override void BlenderSync::sync_camera_motion(BL::Object b_ob, float motion_time) { Camera *cam = scene->camera; - - Transform tfm = get_transform(b_ob.matrix_world()); + BL::Array b_ob_matrix; + b_engine.camera_model_matrix(b_ob, b_ob_matrix); + Transform tfm = get_transform(b_ob_matrix); tfm = blender_camera_matrix(tfm, cam->type); if(tfm != cam->matrix) { @@ -433,10 +438,10 @@ void BlenderSync::sync_camera_motion(BL::Object b_ob, float motion_time) /* Sync 3D View Camera */ -static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d, +static void blender_camera_view_subset(BL::RenderEngine b_engine, BL::RenderSettings b_render, BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box); -static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, bool skip_panorama = false) +static void blender_camera_from_view(BlenderCamera *bcam, BL::RenderEngine b_engine, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, bool skip_panorama = false) { /* 3d view parameters */ bcam->nearclip = b_v3d.clip_start(); @@ -449,13 +454,13 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL: BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera(); if(b_ob) { - blender_camera_from_object(bcam, b_ob, skip_panorama); + blender_camera_from_object(bcam, b_engine, b_ob, skip_panorama); if(!skip_panorama && bcam->type == CAMERA_PANORAMA) { /* in panorama camera view, we map viewplane to camera border */ BoundBox2D view_box, cam_box; - blender_camera_view_subset(b_scene.render(), b_scene, b_ob, b_v3d, b_rv3d, width, height, + blender_camera_view_subset(b_engine, b_scene.render(), b_scene, b_ob, b_v3d, b_rv3d, width, height, &view_box, &cam_box); bcam->pano_viewplane = view_box.make_relative_to(cam_box); @@ -493,7 +498,7 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL: bcam->matrix = transform_inverse(get_transform(b_rv3d.view_matrix())); } -static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d, +static void blender_camera_view_subset(BL::RenderEngine b_engine, BL::RenderSettings b_render, BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box) { BoundBox2D cam, view; @@ -502,7 +507,7 @@ static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_ /* get viewport viewplane */ BlenderCamera view_bcam; blender_camera_init(&view_bcam, b_render); - blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true); + blender_camera_from_view(&view_bcam, b_engine, b_scene, b_v3d, b_rv3d, width, height, true); blender_camera_viewplane(&view_bcam, width, height, &view, &view_aspect, &sensor_size); @@ -510,7 +515,7 @@ static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_ /* get camera viewplane */ BlenderCamera cam_bcam; blender_camera_init(&cam_bcam, b_render); - blender_camera_from_object(&cam_bcam, b_ob, true); + blender_camera_from_object(&cam_bcam, b_engine, b_ob, true); blender_camera_viewplane(&cam_bcam, cam_bcam.full_width, cam_bcam.full_height, &cam, &cam_aspect, &sensor_size); @@ -520,7 +525,8 @@ static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_ *cam_box = cam * (1.0f/cam_aspect); } -static void blender_camera_border_subset(BL::RenderSettings b_render, +static void blender_camera_border_subset(BL::RenderEngine b_engine, + BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, @@ -531,7 +537,7 @@ static void blender_camera_border_subset(BL::RenderSettings b_render, { /* Determine camera viewport subset. */ BoundBox2D view_box, cam_box; - blender_camera_view_subset(b_render, b_scene, b_ob, b_v3d, b_rv3d, width, height, + blender_camera_view_subset(b_engine, b_render, b_scene, b_ob, b_v3d, b_rv3d, width, height, &view_box, &cam_box); /* Determine viewport subset matching given border. */ @@ -539,7 +545,7 @@ static void blender_camera_border_subset(BL::RenderSettings b_render, *result = cam_box.subset(border); } -static void blender_camera_border(BlenderCamera *bcam, BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d, +static void blender_camera_border(BlenderCamera *bcam, BL::RenderEngine b_engine, BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) { bool is_camera_view; @@ -568,7 +574,8 @@ static void blender_camera_border(BlenderCamera *bcam, BL::RenderSettings b_rend /* Determine camera border inside the viewport. */ BoundBox2D full_border; - blender_camera_border_subset(b_render, + blender_camera_border_subset(b_engine, + b_render, b_scene, b_v3d, b_rv3d, @@ -587,7 +594,8 @@ static void blender_camera_border(BlenderCamera *bcam, BL::RenderSettings b_rend bcam->border.top = b_render.border_max_y(); /* Determine viewport subset matching camera border. */ - blender_camera_border_subset(b_render, + blender_camera_border_subset(b_engine, + b_render, b_scene, b_v3d, b_rv3d, @@ -602,8 +610,8 @@ void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int { BlenderCamera bcam; blender_camera_init(&bcam, b_scene.render()); - blender_camera_from_view(&bcam, b_scene, b_v3d, b_rv3d, width, height); - blender_camera_border(&bcam, b_scene.render(), b_scene, b_v3d, b_rv3d, width, height); + blender_camera_from_view(&bcam, b_engine, b_scene, b_v3d, b_rv3d, width, height); + blender_camera_border(&bcam, b_engine, b_scene.render(), b_scene, b_v3d, b_rv3d, width, height); blender_camera_sync(scene->camera, &bcam, width, height); } diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 4f428bbea57..17bab0ab525 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -331,9 +331,9 @@ static ShaderEvalType get_shader_type(const string& pass_type) return SHADER_EVAL_BAKE; } -static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, int y, int w, int h, const char *layername) +static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, int y, int w, int h, const char *layername, const char *viewname) { - return b_engine.begin_result(x, y, w, h, layername); + return b_engine.begin_result(x, y, w, h, layername, viewname); } static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, bool cancel, bool do_merge_results) @@ -350,7 +350,7 @@ void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_upda int h = params.height; /* get render result */ - BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str()); + BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str(), b_rview_name.c_str()); /* can happen if the intersected rectangle gives 0 width or height */ if(b_rr.ptr.data == NULL) { @@ -415,13 +415,14 @@ void BlenderSession::render() /* render each layer */ BL::RenderSettings r = b_scene.render(); - BL::RenderSettings::layers_iterator b_iter; + BL::RenderSettings::layers_iterator b_layer_iter; + BL::RenderResult::views_iterator b_view_iter; - for(r.layers.begin(b_iter); b_iter != r.layers.end(); ++b_iter) { - b_rlay_name = b_iter->name(); + for(r.layers.begin(b_layer_iter); b_layer_iter != r.layers.end(); ++b_layer_iter) { + b_rlay_name = b_layer_iter->name(); - /* temporary render result to find needed passes */ - BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str()); + /* temporary render result to find needed passes and views */ + BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str(), NULL); BL::RenderResult::layers_iterator b_single_rlay; b_rr.layers.begin(b_single_rlay); @@ -456,31 +457,41 @@ void BlenderSession::render() } } - /* free result without merging */ - end_render_result(b_engine, b_rr, true, false); - buffer_params.passes = passes; - scene->film->pass_alpha_threshold = b_iter->pass_alpha_threshold(); + scene->film->pass_alpha_threshold = b_layer_iter->pass_alpha_threshold(); scene->film->tag_passes_update(scene, passes); scene->film->tag_update(scene); scene->integrator->tag_update(scene); - /* update scene */ - sync->sync_camera(b_render, b_engine.camera_override(), width, height); - sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state, b_rlay_name.c_str()); + for(b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter) { + b_rview_name = b_view_iter->name(); - /* update number of samples per layer */ - int samples = sync->get_layer_samples(); - bool bound_samples = sync->get_layer_bound_samples(); + /* set the current view */ + b_engine.active_view_set(b_rview_name.c_str()); - if(samples != 0 && (!bound_samples || (samples < session_params.samples))) - session->reset(buffer_params, samples); - else - session->reset(buffer_params, session_params.samples); + /* update scene */ + sync->sync_camera(b_render, b_engine.camera_override(), width, height); + sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state, b_rlay_name.c_str()); - /* render */ - session->start(); - session->wait(); + /* update number of samples per layer */ + int samples = sync->get_layer_samples(); + bool bound_samples = sync->get_layer_bound_samples(); + + if(samples != 0 && (!bound_samples || (samples < session_params.samples))) + session->reset(buffer_params, samples); + else + session->reset(buffer_params, session_params.samples); + + /* render */ + session->start(); + session->wait(); + + if(session->progress.get_cancel()) + break; + } + + /* free result without merging */ + end_render_result(b_engine, b_rr, true, false); if(session->progress.get_cancel()) break; @@ -619,10 +630,12 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::Re b_pass.rect(&pixels[0]); } } - - /* copy combined pass */ - if(buffers->get_pass_rect(PASS_COMBINED, exposure, rtile.sample, 4, &pixels[0])) - b_rlay.rect(&pixels[0]); + else { + /* copy combined pass */ + BL::RenderPass b_combined_pass(b_rlay.passes.find_by_type(BL::RenderPass::type_COMBINED, b_rview_name.c_str())); + if(buffers->get_pass_rect(PASS_COMBINED, exposure, rtile.sample, 4, &pixels[0])) + b_combined_pass.rect(&pixels[0]); + } /* tag result as updated */ b_engine.update_result(b_rr); @@ -841,6 +854,9 @@ void BlenderSession::update_status_progress() scene += " | " + b_scene.name(); if(b_rlay_name != "") scene += ", " + b_rlay_name; + + if(b_rview_name != "") + scene += ", " + b_rview_name; } else { BLI_timestr(total_time, time_str, sizeof(time_str)); diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index c8070286006..b6fc709b92e 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -90,6 +90,7 @@ public: BL::SpaceView3D b_v3d; BL::RegionView3D b_rv3d; string b_rlay_name; + string b_rview_name; string last_status; string last_error; diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py index e4255966a5f..6c87af8ad68 100644 --- a/release/scripts/startup/bl_ui/properties_data_camera.py +++ b/release/scripts/startup/bl_ui/properties_data_camera.py @@ -135,6 +135,35 @@ class DATA_PT_lens(CameraButtonsPanel, Panel): col.prop(cam, "clip_end", text="End") +class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel): + bl_label = "Stereoscopy" + COMPAT_ENGINES = {'BLENDER_RENDER'} + + @classmethod + def poll(cls, context): + render = context.scene.render + return (super().poll(context) and render.use_multiview \ + and render.views_format == 'STEREO_3D') + + def draw(self, context): + layout = self.layout + render = context.scene.render + st = context.camera.stereo + + col = layout.column() + col.row().prop(st, "convergence_mode", expand=True) + + if st.convergence_mode == 'PARALLEL': + col.prop(st, "viewport_convergence") + else: + col.prop(st, "convergence_distance") + + col.prop(st, "interocular_distance") + + col.label(text="Pivot:") + col.row().prop(st, "pivot", expand=True) + + class DATA_PT_camera(CameraButtonsPanel, Panel): bl_label = "Camera" COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index b596fe48b49..35f77e02834 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -404,6 +404,8 @@ class RENDER_PT_output(RenderButtonsPanel, Panel): col.prop(rd, "use_render_cache") layout.template_image_settings(image_settings, color_management=False) + if rd.use_multiview: + layout.template_image_views(image_settings) if file_format == 'QUICKTIME': quicktime = rd.quicktime diff --git a/release/scripts/startup/bl_ui/properties_render_layer.py b/release/scripts/startup/bl_ui/properties_render_layer.py index 35032d38933..18c75ccb20c 100644 --- a/release/scripts/startup/bl_ui/properties_render_layer.py +++ b/release/scripts/startup/bl_ui/properties_render_layer.py @@ -167,5 +167,63 @@ class RENDERLAYER_PT_layer_passes(RenderLayerButtonsPanel, Panel): self.draw_pass_type_buttons(col, rl, "refraction") +class RENDERLAYER_UL_renderviews(UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): + # assert(isinstance(item, bpy.types.SceneRenderView) + view = item + if self.layout_type in {'DEFAULT', 'COMPACT'}: + if view.name in {'left', 'right'}: + layout.label(view.name, icon_value=icon + (not view.use)) + else: + layout.prop(view, "name", text="", index=index, icon_value=icon, emboss=False) + layout.prop(view, "use", text="", index=index) + + elif self.layout_type == 'GRID': + layout.alignment = 'CENTER' + layout.label("", icon_value=icon + (not view.use)) + + +class RENDERLAYER_PT_views(RenderLayerButtonsPanel, Panel): + bl_label = "Views" + COMPAT_ENGINES = {'BLENDER_RENDER'} + + def draw_header(self, context): + rd = context.scene.render + self.layout.prop(rd, "use_multiview", text="") + + def draw(self, context): + layout = self.layout + + scene = context.scene + rd = scene.render + rv = rd.views.active + + layout.active = rd.use_multiview + basic_stereo = rd.views_format == 'STEREO_3D' + + row = layout.row() + row.prop(rd, "views_format", expand=True) + + if basic_stereo: + row = layout.row() + row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2) + + row = layout.row() + row.label(text="File Suffix:") + row.prop(rv, "file_suffix", text="") + + else: + row = layout.row() + row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2) + + col = row.column(align=True) + col.operator("scene.render_view_add", icon='ZOOMIN', text="") + col.operator("scene.render_view_remove", icon='ZOOMOUT', text="") + + row = layout.row() + row.label(text="Camera Suffix:") + row.prop(rv, "camera_suffix", text="") + + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index e2c2783fae1..a1101bb3efb 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -458,6 +458,10 @@ class IMAGE_HT_header(Header): layout.prop_search(mesh.uv_textures, "active", mesh, "uv_textures", text="") if ima: + if ima.is_stereo_3d: + row = layout.row() + row.prop(sima, "show_stereo_3d", text="") + # layers layout.template_image_layers(ima, iuser) diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py index 927967c8bc6..48a1b28289e 100644 --- a/release/scripts/startup/bl_ui/space_info.py +++ b/release/scripts/startup/bl_ui/space_info.py @@ -282,6 +282,10 @@ class INFO_MT_window(Menu): layout.separator() layout.operator("wm.console_toggle", icon='CONSOLE') + if context.scene.render.use_multiview: + layout.separator() + layout.operator("wm.set_stereo_3d", icon='CAMERA_STEREO') + class INFO_MT_help(Menu): bl_label = "Help" diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index da477e4e6be..e19cf8239d7 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -659,6 +659,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel): def draw(self, context): layout = self.layout + scene = context.scene strip = act_strip(context) @@ -672,7 +673,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel): # Current element for the filename - elem = strip.strip_elem_from_frame(context.scene.frame_current) + elem = strip.strip_elem_from_frame(scene.frame_current) if elem: split = layout.split(percentage=0.2) split.label(text="File:") @@ -718,6 +719,19 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel): col.prop(strip, "frame_offset_start", text="Start") col.prop(strip, "frame_offset_end", text="End") + if scene.render.use_multiview and seq_type in {'IMAGE', 'MOVIE'}: + layout.prop(strip, "use_multiview") + + col = layout.column() + col.active = strip.use_multiview + + col.label(text="Views Format:") + col.row().prop(strip, "views_format", expand=True) + + box = col.box() + box.active = strip.views_format == 'STEREO_3D' + box.template_image_stereo_3d(strip.stereo_3d_format) + class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel): bl_label = "Sound" diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 6b9e4b85875..a23ad4209d5 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -2936,16 +2936,50 @@ class VIEW3D_PT_view3d_display(Panel): row.prop(region, "use_box_clip") -class VIEW3D_PT_view3d_shading(Panel): +class VIEW3D_PT_view3d_stereo(Panel): bl_space_type = 'VIEW_3D' bl_region_type = 'UI' - bl_label = "Shading" + bl_label = "Stereoscopy" bl_options = {'DEFAULT_CLOSED'} @classmethod def poll(cls, context): + scene = context.scene + + multiview = scene.render.use_multiview + return context.space_data and multiview + + def draw(self, context): + layout = self.layout view = context.space_data - return (view) + + basic_stereo = context.scene.render.views_format == 'STEREO_3D' + + col = layout.column() + col.row().prop(view, "stereo_3d_camera", expand=True) + + col.label(text="Display:") + row = col.row() + row.active = basic_stereo + row.prop(view, "show_stereo_3d_cameras") + row = col.row() + row.active = basic_stereo + split = row.split() + split.prop(view, "show_stereo_3d_convergence_plane") + split = row.split() + split.prop(view, "stereo_3d_convergence_plane_alpha", text="Alpha") + split.active = view.show_stereo_3d_convergence_plane + row = col.row() + split = row.split() + split.prop(view, "show_stereo_3d_volume") + split = row.split() + split.prop(view, "stereo_3d_volume_alpha", text="Alpha") + + +class VIEW3D_PT_view3d_shading(Panel): + bl_space_type = 'VIEW_3D' + bl_region_type = 'UI' + bl_label = "Shading" def draw(self, context): layout = self.layout diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 1590bd49763..98c524b0b37 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -328,6 +328,7 @@ compositor_node_categories = [ NodeItem("CompositorNodeCombYUVA"), NodeItem("CompositorNodeSepYCCA"), NodeItem("CompositorNodeCombYCCA"), + NodeItem("CompositorNodeSwitchView"), ]), CompositorNodeCategory("CMP_OP_FILTER", "Filter", items=[ NodeItem("CompositorNodeBlur"), diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index a790715ac98..86576f9a11b 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 274 -#define BLENDER_SUBVERSION 3 +#define BLENDER_SUBVERSION 4 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 5 diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h index 4849c66df1b..aacb7a4066b 100644 --- a/source/blender/blenkernel/BKE_camera.h +++ b/source/blender/blenkernel/BKE_camera.h @@ -136,6 +136,14 @@ bool BKE_camera_view_frame_fit_to_coords( void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings); +/* Camera multi-view API */ + +struct Object *BKE_camera_multiview_render(struct Scene *scene, struct Object *camera, const char *viewname); +void BKE_camera_multiview_view_matrix(struct RenderData *rd, struct Object *camera, const bool is_left, float r_viewmat[4][4]); +void BKE_camera_multiview_model_matrix(struct RenderData *rd, struct Object *camera, const char *viewname, float r_modelmat[4][4]); +float BKE_camera_multiview_shift_x(struct RenderData *rd, struct Object *camera, const char *viewname); +void BKE_camera_multiview_params(struct RenderData *rd, struct CameraParams *params, struct Object *camera, const char *viewname); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 3b7ba24d20b..ad191968a40 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -45,34 +45,34 @@ struct Object; struct ImageFormatData; struct ImagePool; struct Main; +struct ReportList; #define IMA_MAX_SPACE 64 void BKE_images_init(void); void BKE_images_exit(void); +void BKE_image_free_packedfiles(struct Image *image); +void BKE_image_free_views(struct Image *image); void BKE_image_free_buffers(struct Image *image); /* call from library */ void BKE_image_free(struct Image *image); void BKE_imbuf_stamp_info(struct Scene *scene, struct Object *camera, struct ImBuf *ibuf); -void BKE_image_stamp_buf( - struct Scene *scene, struct Object *camera, - unsigned char *rect, float *rectf, int width, int height, int channels); +void BKE_image_stamp_buf(struct Scene *scene, struct Object *camera, unsigned char *rect, float *rectf, int width, int height, int channels); bool BKE_imbuf_alpha_test(struct ImBuf *ibuf); int BKE_imbuf_write_stamp(struct Scene *scene, struct Object *camera, struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf); +void BKE_imbuf_write_prepare(struct ImBuf *ibuf, struct ImageFormatData *imf); int BKE_imbuf_write(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf); int BKE_imbuf_write_as(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf, const bool is_copy); - void BKE_image_path_from_imformat( char *string, const char *base, const char *relbase, int frame, - const struct ImageFormatData *im_format, const bool use_ext, const bool use_frames); + const struct ImageFormatData *im_format, const bool use_ext, const bool use_frames, const char *suffix); void BKE_image_path_from_imtype( char *string, const char *base, const char *relbase, int frame, - const char imtype, const bool use_ext, const bool use_frames); - -bool BKE_image_path_ensure_ext_from_imformat(char *string, const struct ImageFormatData *im_format); -bool BKE_image_path_ensure_ext_from_imtype(char *string, const char imtype); + const char imtype, const bool use_ext, const bool use_frames, const char *suffix); +int BKE_image_path_ensure_ext_from_imformat(char *string, const struct ImageFormatData *im_format); +int BKE_image_path_ensure_ext_from_imtype(char *string, const char imtype); char BKE_image_ftype_to_imtype(const int ftype); int BKE_image_imtype_to_ftype(const char imtype); @@ -103,6 +103,7 @@ void BKE_image_tag_time(struct Image *ima); /* ImageUser is in Texture, in Nodes, Background Image, Image Window, .... */ /* should be used in conjunction with an ID * to Image. */ struct ImageUser; +struct RenderData; struct RenderPass; struct RenderResult; @@ -172,11 +173,12 @@ struct Image *BKE_image_load_exists(const char *filepath); /* adds image, adds ibuf, generates color or pattern */ struct Image *BKE_image_add_generated( - struct Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4]); + struct Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4], const bool stereo3d); /* adds image from imbuf, owns imbuf */ struct Image *BKE_image_add_from_imbuf(struct ImBuf *ibuf); /* for reload, refresh, pack */ +void BKE_image_init_imageuser(struct Image *ima, struct ImageUser *iuser); void BKE_image_signal(struct Image *ima, struct ImageUser *iuser, int signal); void BKE_image_walk_all_users(const struct Main *mainp, void *customdata, @@ -184,6 +186,8 @@ void BKE_image_walk_all_users(const struct Main *mainp, void *customdata, /* ensures an Image exists for viewing nodes or render */ struct Image *BKE_image_verify_viewer(int type, const char *name); +/* ensures the view node cache is compatible with the scene views */ +void BKE_image_verify_viewer_views(const struct RenderData *rd, struct Image *ima, struct ImageUser *iuser); /* called on frame change or before render */ void BKE_image_user_frame_calc(struct ImageUser *iuser, int cfra, int fieldnr); @@ -195,13 +199,23 @@ void BKE_image_update_frame(const struct Main *bmain, int cfra); /* sets index offset for multilayer files */ struct RenderPass *BKE_image_multilayer_index(struct RenderResult *rr, struct ImageUser *iuser); +/* sets index offset for multiview files */ +void BKE_image_multiview_index(struct Image *ima, struct ImageUser *iuser); + /* for multilayer images as well as for render-viewer */ +bool BKE_image_is_multilayer(struct Image *ima); struct RenderResult *BKE_image_acquire_renderresult(struct Scene *scene, struct Image *ima); void BKE_image_release_renderresult(struct Scene *scene, struct Image *ima); +/* for multilayer images as well as for singlelayer */ +bool BKE_image_is_openexr(struct Image *ima); + /* for multiple slot render, call this before render */ void BKE_image_backup_render(struct Scene *scene, struct Image *ima); - + +/* for singlelayer openexr saving */ +bool BKE_image_save_openexr_multiview(struct Image *ima, struct ImBuf *ibuf, const char *filepath, const int flags); + /* goes over all textures that use images */ void BKE_image_free_all_textures(void); @@ -212,6 +226,7 @@ void BKE_image_free_anim_ibufs(struct Image *ima, int except_frame); void BKE_image_all_free_anim_ibufs(int except_frame); void BKE_image_memorypack(struct Image *ima); +void BKE_image_packfiles(struct ReportList *reports, struct Image *ima, const char *basepath); /* prints memory statistics for images */ void BKE_image_print_memlist(void); @@ -243,7 +258,8 @@ float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame); /* Guess offset for the first frame in the sequence */ int BKE_image_sequence_guess_offset(struct Image *image); - +bool BKE_image_has_anim(struct Image *image); +bool BKE_image_has_packedfile(struct Image *image); bool BKE_image_is_animated(struct Image *image); bool BKE_image_is_dirty(struct Image *image); void BKE_image_file_format_set(struct Image *image, int ftype); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index ee63771406e..eca15a62c70 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -941,6 +941,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria #define CMP_NODE_MAP_RANGE 319 #define CMP_NODE_PLANETRACKDEFORM 320 #define CMP_NODE_CORNERPIN 321 +#define CMP_NODE_SWITCH_VIEW 322 /* channel toggles */ #define CMP_CHAN_RGB 1 @@ -975,7 +976,8 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria /* API */ void ntreeCompositExecTree(struct Scene *scene, struct bNodeTree *ntree, struct RenderData *rd, int rendering, int do_previews, - const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings); + const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, + const char *view_name); void ntreeCompositTagRender(struct Scene *sce); int ntreeCompositTagAnimated(struct bNodeTree *ntree); void ntreeCompositTagGenerators(struct bNodeTree *ntree); diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 27c89dd3a09..79778d504a5 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -70,6 +70,7 @@ void BKE_scene_free(struct Scene *sce); struct Scene *BKE_scene_add(struct Main *bmain, const char *name); /* base functions */ +struct Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name); struct Base *BKE_scene_base_find(struct Scene *scene, struct Object *ob); struct Base *BKE_scene_base_add(struct Scene *sce, struct Object *ob); void BKE_scene_base_unlink(struct Scene *sce, struct Base *base); @@ -122,6 +123,9 @@ void BKE_scene_update_for_newframe_ex(struct EvaluationContext *eval_ctx, struct struct SceneRenderLayer *BKE_scene_add_render_layer(struct Scene *sce, const char *name); bool BKE_scene_remove_render_layer(struct Main *main, struct Scene *scene, struct SceneRenderLayer *srl); +struct SceneRenderView *BKE_scene_add_render_view(struct Scene *sce, const char *name); +bool BKE_scene_remove_render_view(struct Scene *scene, struct SceneRenderView *srv); + /* render profile */ int get_render_subsurf_level(const struct RenderData *r, int level); int get_render_child_particle_number(const struct RenderData *r, int num); @@ -142,6 +146,23 @@ int BKE_render_num_threads(const struct RenderData *r); double BKE_scene_unit_scale(const struct UnitSettings *unit, const int unit_type, double value); +/* multiview */ +bool BKE_scene_multiview_is_stereo3d(const struct RenderData *rd); +bool BKE_scene_multiview_is_render_view_active(const struct RenderData *rd, const struct SceneRenderView *srv); +bool BKE_scene_multiview_is_render_view_first(const struct RenderData *rd, const char *viewname); +bool BKE_scene_multiview_is_render_view_last(const struct RenderData *rd, const char *viewname); +size_t BKE_scene_multiview_num_views_get(const struct RenderData *rd); +struct SceneRenderView *BKE_scene_multiview_render_view_findindex(const struct RenderData *rd, const int view_id); +const char *BKE_scene_multiview_render_view_name_get(const struct RenderData *rd, const int view_id); +size_t BKE_scene_multiview_view_id_get(const struct RenderData *rd, const char *viewname); +void BKE_scene_multiview_filepath_get(struct SceneRenderView *srv, const char *filepath, char *r_filepath); +void BKE_scene_multiview_view_filepath_get(const struct RenderData *rd, const char *filepath, const char *view, char *r_filepath); +const char *BKE_scene_multiview_view_suffix_get(const struct RenderData *rd, const char *viewname); +const char *BKE_scene_multiview_view_id_suffix_get(const struct RenderData *rd, const size_t view_id); +void BKE_scene_multiview_view_prefix_get(struct Scene *scene, const char *name, char *rprefix, char **rext); +void BKE_scene_multiview_videos_dimensions_get(const struct RenderData *rd, const size_t width, const size_t height, size_t *r_width, size_t *r_height); +size_t BKE_scene_multiview_num_videos_get(const struct RenderData *rd); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 84818276e7b..4a45489933c 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -41,6 +41,7 @@ struct Mask; struct Scene; struct Sequence; struct SequenceModifierData; +struct Stereo3dFormat; struct StripElem; struct bSound; @@ -99,6 +100,7 @@ typedef struct SeqRenderData { float motion_blur_shutter; bool skip_cache; bool is_proxy_render; + size_t view_id; } SeqRenderData; void BKE_sequencer_new_render_data( @@ -223,6 +225,7 @@ void BKE_sequencer_base_clipboard_pointers_store(struct ListBase *seqbase); void BKE_sequencer_base_clipboard_pointers_restore(struct ListBase *seqbase, struct Main *bmain); void BKE_sequence_free(struct Scene *scene, struct Sequence *seq); +void BKE_sequence_free_anim(struct Sequence *seq); const char *BKE_sequence_give_name(struct Sequence *seq); void BKE_sequence_calc(struct Scene *scene, struct Sequence *seq); void BKE_sequence_calc_disp(struct Scene *scene, struct Sequence *seq); @@ -235,7 +238,7 @@ struct StripElem *BKE_sequencer_give_stripelem(struct Sequence *seq, int cfra); void BKE_sequencer_update_changed_seq_and_deps(struct Scene *scene, struct Sequence *changed_seq, int len_change, int ibuf_change); bool BKE_sequencer_input_have_to_preprocess(const SeqRenderData *context, struct Sequence *seq, float cfra); -struct SeqIndexBuildContext *BKE_sequencer_proxy_rebuild_context(struct Main *bmain, struct Scene *scene, struct Sequence *seq, struct GSet *file_list); +void BKE_sequencer_proxy_rebuild_context(struct Main *bmain, struct Scene *scene, struct Sequence *seq, struct GSet *file_list, ListBase *queue); void BKE_sequencer_proxy_rebuild(struct SeqIndexBuildContext *context, short *stop, short *do_update, float *progress); void BKE_sequencer_proxy_rebuild_finish(struct SeqIndexBuildContext *context, bool stop); @@ -355,6 +358,10 @@ typedef struct SeqLoadInfo { int len; /* only for image strips */ char path[1024]; /* 1024 = FILE_MAX */ + /* multiview */ + char views_format; + struct Stereo3dFormat *stereo3d_format; + /* return values */ char name[64]; struct Sequence *seq_sound; /* for movie's */ @@ -399,7 +406,7 @@ struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, ListBase *seq struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); /* view3d draw callback, run when not in background view */ -typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, bool, bool, bool, int, char[256]); +typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, bool, bool, bool, int, const char *, char[256]); extern SequencerDrawView sequencer_view3d_cb; /* copy/paste */ diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h index bc06be0295a..ca295c51f5d 100644 --- a/source/blender/blenkernel/BKE_writeavi.h +++ b/source/blender/blenkernel/BKE_writeavi.h @@ -43,16 +43,20 @@ struct ReportList; struct Scene; typedef struct bMovieHandle { - int (*start_movie)(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview); - int (*append_movie)(struct RenderData *rd, int start_frame, int frame, int *pixels, - int rectx, int recty, struct ReportList *reports); - void (*end_movie)(void); - int (*get_next_frame)(struct RenderData *rd, struct ReportList *reports); /* optional */ - void (*get_movie_path)(char *string, struct RenderData *rd, bool preview); /* optional */ + int (*start_movie)(void *context_v, struct Scene *scene, struct RenderData *rd, int rectx, int recty, + struct ReportList *reports, bool preview, const char *suffix); + int (*append_movie)(void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels, + int rectx, int recty, const char *suffix, struct ReportList *reports); + void (*end_movie)(void *context_v); + int (*get_next_frame)(void *context_v, struct RenderData *rd, struct ReportList *reports); /* optional */ + void (*get_movie_path)(char *string, struct RenderData *rd, bool preview, const char *suffix); /* optional */ + void *(*context_create)(void); + void (*context_free)(void *context_v); } bMovieHandle; bMovieHandle *BKE_movie_handle_get(const char imtype); -void BKE_movie_filepath_get(char *string, struct RenderData *rd, bool preview); +void BKE_movie_filepath_get(char *string, struct RenderData *rd, bool preview, const char *suffix); +void BKE_context_create(bMovieHandle *mh); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h index 951fa501f9c..a40c31022e3 100644 --- a/source/blender/blenkernel/BKE_writeffmpeg.h +++ b/source/blender/blenkernel/BKE_writeffmpeg.h @@ -68,11 +68,11 @@ struct RenderData; struct ReportList; struct Scene; -int BKE_ffmpeg_start(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview); -void BKE_ffmpeg_end(void); -int BKE_ffmpeg_append(struct RenderData *rd, int start_frame, int frame, int *pixels, - int rectx, int recty, struct ReportList *reports); -void BKE_ffmpeg_filepath_get(char *string, struct RenderData *rd, bool preview); +int BKE_ffmpeg_start(void *context_v, struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview, const char *suffix); +void BKE_ffmpeg_end(void *context_v); +int BKE_ffmpeg_append(void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels, + int rectx, int recty, const char *suffix, struct ReportList *reports); +void BKE_ffmpeg_filepath_get(char *string, struct RenderData *rd, bool preview, const char *suffix); void BKE_ffmpeg_preset_set(struct RenderData *rd, int preset); void BKE_ffmpeg_image_type_verify(struct RenderData *rd, struct ImageFormatData *imf); @@ -82,6 +82,9 @@ bool BKE_ffmpeg_alpha_channel_is_supported(struct RenderData *rd); int BKE_ffmpeg_property_add_string(struct RenderData *rd, const char *type, const char *str); void BKE_ffmpeg_property_del(struct RenderData *rd, void *type, void *prop_); +void *BKE_ffmpeg_context_create(void); +void BKE_ffmpeg_context_free(void *context_v); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_writeframeserver.h b/source/blender/blenkernel/BKE_writeframeserver.h index b7d601ea769..2f8bce31e41 100644 --- a/source/blender/blenkernel/BKE_writeframeserver.h +++ b/source/blender/blenkernel/BKE_writeframeserver.h @@ -40,11 +40,14 @@ struct RenderData; struct ReportList; struct Scene; -int BKE_frameserver_start(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview); -void BKE_frameserver_end(void); -int BKE_frameserver_append(struct RenderData *rd, int start_frame, int frame, int *pixels, - int rectx, int recty, struct ReportList *reports); -int BKE_frameserver_loop(struct RenderData *rd, struct ReportList *reports); +int BKE_frameserver_start(void *context_v, struct Scene *scene, struct RenderData *rd, int rectx, int recty, + struct ReportList *reports, bool preview, const char *suffix); +void BKE_frameserver_end(void *context_v); +int BKE_frameserver_append(void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels, + int rectx, int recty, const char*suffix, struct ReportList *reports); +int BKE_frameserver_loop(void *context_v, struct RenderData *rd, struct ReportList *reports); +void *BKE_frameserver_context_create(void); +void BKE_frameserver_context_free(void *context_v); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index e94f30da0c5..bb3731218ed 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -423,10 +423,10 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int { Image *ima; ima = (Image *)id; - if (ima->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) { + if (BKE_image_has_packedfile(ima) == false || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) { if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { if (rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data)) { - if (!ima->packedfile) { + if (!BKE_image_has_packedfile(ima)) { BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); BKE_image_walk_all_users(bmain, ima, bpath_traverse_image_user_cb); } diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 5b4d7ba8214..fec6542ac47 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -30,16 +30,19 @@ */ #include +#include #include "DNA_camera_types.h" #include "DNA_lamp_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_view3d_types.h" +#include "DNA_ID.h" #include "BLI_math.h" -#include "BLI_utildefines.h" #include "BLI_rect.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" #include "BKE_animsys.h" #include "BKE_camera.h" @@ -47,6 +50,7 @@ #include "BKE_global.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_scene.h" #include "BKE_screen.h" #include "GPU_compositing.h" @@ -71,6 +75,10 @@ void *BKE_camera_add(Main *bmain, const char *name) GPU_fx_compositor_init_dof_settings(&cam->gpu_dof); + /* stereoscopy 3d */ + cam->stereo.interocular_distance = 0.065f; + cam->stereo.convergence_distance = 30.f * 0.065f; + return cam; } @@ -695,6 +703,250 @@ bool BKE_camera_view_frame_fit_to_coords( return camera_frame_fit_calc_from_data(¶ms, &data_cb, r_co, r_scale); } +/******************* multiview matrix functions ***********************/ + +static void camera_model_matrix(Object *camera, float r_modelmat[4][4]) +{ + copy_m4_m4(r_modelmat, camera->obmat); +} + +static void camera_stereo3d_model_matrix(Object *camera, const bool is_left, float r_modelmat[4][4]) +{ + Camera *data = (Camera *)camera->data; + float interocular_distance, convergence_distance; + short convergence_mode, pivot; + float sizemat[4][4]; + + float fac = 1.0f; + float fac_signed; + + interocular_distance = data->stereo.interocular_distance; + convergence_distance = data->stereo.convergence_distance; + convergence_mode = data->stereo.convergence_mode; + pivot = data->stereo.pivot; + + if (((pivot == CAM_S3D_PIVOT_LEFT) && is_left) || + ((pivot == CAM_S3D_PIVOT_RIGHT) && !is_left)) + { + return camera_model_matrix(camera, r_modelmat); + } + else { + float size[3]; + mat4_to_size(size, camera->obmat); + size_to_mat4(sizemat, size); + } + + if (pivot == CAM_S3D_PIVOT_CENTER) + fac = 0.5f; + + fac_signed = is_left ? fac : -fac; + + /* rotation */ + if (convergence_mode == CAM_S3D_TOE) { + float angle; + float angle_sin, angle_cos; + float toeinmat[4][4]; + float rotmat[4][4]; + + unit_m4(rotmat); + + if (pivot == CAM_S3D_PIVOT_CENTER) { + fac = -fac; + fac_signed = -fac_signed; + } + + angle = atanf((interocular_distance * 0.5f) / convergence_distance) / fac; + + angle_cos = cosf(angle * fac_signed); + angle_sin = sinf(angle * fac_signed); + + rotmat[0][0] = angle_cos; + rotmat[2][0] = -angle_sin; + rotmat[0][2] = angle_sin; + rotmat[2][2] = angle_cos; + + if (pivot == CAM_S3D_PIVOT_CENTER) { + /* set the rotation */ + copy_m4_m4(toeinmat, rotmat); + /* set the translation */ + toeinmat[3][0] = interocular_distance * fac_signed; + + /* transform */ + normalize_m4_m4(r_modelmat, camera->obmat); + mul_m4_m4m4(r_modelmat, r_modelmat, toeinmat); + + /* scale back to the original size */ + mul_m4_m4m4(r_modelmat, r_modelmat, sizemat); + } + else { /* CAM_S3D_PIVOT_LEFT, CAM_S3D_PIVOT_RIGHT */ + /* rotate perpendicular to the interocular line */ + normalize_m4_m4(r_modelmat, camera->obmat); + mul_m4_m4m4(r_modelmat, r_modelmat, rotmat); + + /* translate along the interocular line */ + unit_m4(toeinmat); + toeinmat[3][0] = -interocular_distance * fac_signed; + mul_m4_m4m4(r_modelmat, r_modelmat, toeinmat); + + /* rotate to toe-in angle */ + mul_m4_m4m4(r_modelmat, r_modelmat, rotmat); + + /* scale back to the original size */ + mul_m4_m4m4(r_modelmat, r_modelmat, sizemat); + } + } + else { + normalize_m4_m4(r_modelmat, camera->obmat); + + /* translate - no rotation in CAM_S3D_OFFAXIS, CAM_S3D_PARALLEL */ + translate_m4(r_modelmat, -interocular_distance * fac_signed, 0.0f, 0.0f); + + /* scale back to the original size */ + mul_m4_m4m4(r_modelmat, r_modelmat, sizemat); + } +} + +/* the view matrix is used by the viewport drawing, it is basically the inverted model matrix */ +void BKE_camera_multiview_view_matrix(RenderData *rd, Object *camera, const bool is_left, float r_viewmat[4][4]) +{ + BKE_camera_multiview_model_matrix(rd, camera, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, r_viewmat); + invert_m4(r_viewmat); +} + +/* left is the default */ +static bool camera_is_left(const char *viewname) +{ + if (viewname && viewname[0] != '\0') { + return !STREQ(viewname, STEREO_RIGHT_NAME); + } + return true; +} + +void BKE_camera_multiview_model_matrix(RenderData *rd, Object *camera, const char *viewname, float r_modelmat[4][4]) +{ + const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0; + + if (!is_multiview) { + camera_model_matrix(camera, r_modelmat); + } + else if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW) { + camera_model_matrix(camera, r_modelmat); + } + else { /* SCE_VIEWS_SETUP_BASIC */ + const bool is_left = camera_is_left(viewname); + camera_stereo3d_model_matrix(camera, is_left, r_modelmat); + } + normalize_m4(r_modelmat); +} + +static Object *camera_multiview_advanced(Scene *scene, Object *camera, const char *suffix) +{ + SceneRenderView *srv; + char name[MAX_NAME]; + const char *camera_name = camera->id.name + 2; + const int len_name = strlen(camera_name); + + name[0] = '\0'; + + for (srv = scene->r.views.first; srv; srv = srv->next) { + const int len_suffix = strlen(srv->suffix); + + if (len_name < len_suffix) + continue; + + if (STREQ(camera_name + (len_name - len_suffix), srv->suffix)) { + BLI_snprintf(name, sizeof(name), "%.*s%s", (len_name - len_suffix), camera_name, suffix); + break; + } + } + + if (name[0] != '\0') { + Base *base = BKE_scene_base_find_by_name(scene, name); + if (base) { + return base->object; + } + } + + return camera; +} + +/* returns the camera to be used for render */ +Object *BKE_camera_multiview_render(Scene *scene, Object *camera, const char *viewname) +{ + const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0; + + if (!is_multiview) { + return camera; + } + else if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { + return camera; + } + else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ + const char *suffix = BKE_scene_multiview_view_suffix_get(&scene->r, viewname); + return camera_multiview_advanced(scene, camera, suffix); + } +} + +static float camera_stereo3d_shift_x(Object *camera, const char *viewname) +{ + Camera *data = camera->data; + float shift = data->shiftx; + float interocular_distance, convergence_distance; + short convergence_mode, pivot; + bool is_left = true; + + float fac = 1.0f; + float fac_signed; + + if (viewname && viewname[0]) { + is_left = STREQ(viewname, STEREO_LEFT_NAME); + } + + interocular_distance = data->stereo.interocular_distance; + convergence_distance = data->stereo.convergence_distance; + convergence_mode = data->stereo.convergence_mode; + pivot = data->stereo.pivot; + + if (((pivot == CAM_S3D_PIVOT_LEFT) && is_left) || + ((pivot == CAM_S3D_PIVOT_RIGHT) && !is_left)) + { + return shift; + } + + if (pivot == CAM_S3D_PIVOT_CENTER) + fac = 0.5f; + + fac_signed = is_left ? fac : -fac; + + /* Note: in viewport, parallel renders as offaxis, but in render it does parallel */ + if (ELEM(convergence_mode, CAM_S3D_OFFAXIS, CAM_S3D_PARALLEL)) { + shift += ((interocular_distance / data->sensor_x) * (data->lens / convergence_distance)) * fac_signed; + } + + return shift; +} + +float BKE_camera_multiview_shift_x(RenderData *rd, Object *camera, const char *viewname) +{ + const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0; + Camera *data = camera->data; + + if (!is_multiview) { + return data->shiftx; + } + else if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW) { + return data->shiftx; + } + else { /* SCE_VIEWS_SETUP_BASIC */ + return camera_stereo3d_shift_x(camera, viewname); + } +} + +void BKE_camera_multiview_params(RenderData *rd, CameraParams *params, Object *camera, const char *viewname) +{ + params->shiftx = BKE_camera_multiview_shift_x(rd, camera, viewname); +} + void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings) { if (camera->type == OB_CAMERA) { diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 9b00a0150ad..f852d886ae9 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -99,6 +99,12 @@ static SpinLock image_spin; +/* prototypes */ +static size_t image_num_files(struct Image *ima); +static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r); +static void image_update_views_format(Image *ima, ImageUser *iuser); +static void image_add_view(Image *ima, const char *viewname, const char *filepath); + /* max int, to indicate we don't store sequences in ibuf */ #define IMA_NO_INDEX 0x7FEFEFEF @@ -257,6 +263,46 @@ static void image_free_cached_frames(Image *image) } } +static void image_free_packedfiles(Image *ima) +{ + while (ima->packedfiles.last) { + ImagePackedFile *imapf = ima->packedfiles.last; + if (imapf->packedfile) { + freePackedFile(imapf->packedfile); + } + BLI_remlink(&ima->packedfiles, imapf); + MEM_freeN(imapf); + } +} + +void BKE_image_free_packedfiles(Image *ima) +{ + image_free_packedfiles(ima); +} + +static void image_free_views(Image *ima) +{ + BLI_freelistN(&ima->views); +} + +void BKE_image_free_views(Image *image) +{ + image_free_views(image); +} + +static void image_free_anims(Image *ima) +{ + while (ima->anims.last) { + ImageAnim *ia = ima->anims.last; + if (ia->anim) { + IMB_free_anim(ia->anim); + ia->anim = NULL; + } + BLI_remlink(&ima->anims, ia); + MEM_freeN(ia); + } +} + /** * Simply free the image data from memory, * on display the image can load again (except for render buffers). @@ -265,8 +311,7 @@ void BKE_image_free_buffers(Image *ima) { image_free_cached_frames(ima); - if (ima->anim) IMB_free_anim(ima->anim); - ima->anim = NULL; + image_free_anims(ima); if (ima->rr) { RE_FreeRenderResult(ima->rr); @@ -290,10 +335,9 @@ void BKE_image_free(Image *ima) int a; BKE_image_free_buffers(ima); - if (ima->packedfile) { - freePackedFile(ima->packedfile); - ima->packedfile = NULL; - } + + image_free_packedfiles(ima); + BKE_icon_delete(&ima->id); ima->id.icon_id = 0; @@ -305,6 +349,9 @@ void BKE_image_free(Image *ima) ima->renders[a] = NULL; } } + + image_free_views(ima); + MEM_freeN(ima->stereo3d_format); } /* only image block itself */ @@ -328,7 +375,9 @@ static Image *image_alloc(Main *bmain, const char *name, short source, short typ ima->flag |= IMA_VIEW_AS_RENDER; BKE_color_managed_colorspace_settings_init(&ima->colorspace_settings); + ima->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Image Stereo Format"); } + return ima; } @@ -359,6 +408,22 @@ static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame) } } +static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src) +{ + const ImagePackedFile *imapf_src; + + BLI_listbase_clear(lb_dst); + for (imapf_src = lb_src->first; imapf_src; imapf_src = imapf_src->next) { + ImagePackedFile *imapf_dst = MEM_mallocN(sizeof(ImagePackedFile), "Image Packed Files (copy)"); + BLI_strncpy(imapf_dst->filepath, imapf_src->filepath, sizeof(imapf_dst->filepath)); + + if (imapf_src->packedfile) + imapf_dst->packedfile = dupPackedFile(imapf_src->packedfile); + + BLI_addtail(lb_dst, imapf_dst); + } +} + /* empty image block, of similar type and filename */ Image *BKE_image_copy(Main *bmain, Image *ima) { @@ -381,8 +446,10 @@ Image *BKE_image_copy(Main *bmain, Image *ima) BKE_color_managed_colorspace_settings_copy(&nima->colorspace_settings, &ima->colorspace_settings); - if (ima->packedfile) - nima->packedfile = dupPackedFile(ima->packedfile); + copy_image_packedfiles(&nima->packedfiles, &ima->packedfiles); + + nima->stereo3d_format = MEM_dupallocN(ima->stereo3d_format); + BLI_duplicatelist(&nima->views, &ima->views); if (ima->id.lib) { BKE_id_lib_local_paths(bmain, ima->id.lib, &nima->id); @@ -686,7 +753,9 @@ Image *BKE_image_load_exists_ex(const char *filepath, bool *r_exists) BLI_path_abs(strtest, ID_BLEND_PATH(G.main, &ima->id)); if (BLI_path_cmp(strtest, str) == 0) { - if (ima->anim == NULL || ima->id.us == 0) { + if ((BKE_image_has_anim(ima) == false) || + (ima->id.us == 0)) + { ima->id.us++; /* officially should not, it doesn't link here! */ if (ima->ok == 0) ima->ok = IMA_OK; @@ -774,13 +843,14 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char } /* adds new image block, creates ImBuf and initializes color */ -Image *BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4]) +Image *BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4], const bool stereo3d) { /* on save, type is changed to FILE in editsima.c */ Image *ima = image_alloc(bmain, name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST); if (ima) { - ImBuf *ibuf; + size_t view_id; + const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; /* BLI_strncpy(ima->name, name, FILE_MAX); */ /* don't do this, this writes in ain invalid filepath! */ ima->gen_x = width; @@ -790,13 +860,21 @@ Image *BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int hei ima->gen_depth = depth; copy_v4_v4(ima->gen_color, color); - ibuf = add_ibuf_size(width, height, ima->name, depth, floatbuf, gen_type, color, &ima->colorspace_settings); - image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + for (view_id = 0; view_id < 2; view_id++) { + ImBuf *ibuf; + ibuf = add_ibuf_size(width, height, ima->name, depth, floatbuf, gen_type, color, &ima->colorspace_settings); + image_assign_ibuf(ima, ibuf, stereo3d ? view_id : IMA_NO_INDEX, 0); - /* image_assign_ibuf puts buffer to the cache, which increments user counter. */ - IMB_freeImBuf(ibuf); + /* image_assign_ibuf puts buffer to the cache, which increments user counter. */ + IMB_freeImBuf(ibuf); + if (!stereo3d) break; + + image_add_view(ima, names[view_id], ""); + } ima->ok = IMA_OK_LOADED; + if (stereo3d) + ima->flag |= IMA_IS_STEREO | IMA_IS_MULTIVIEW; } return ima; @@ -821,17 +899,76 @@ Image *BKE_image_add_from_imbuf(ImBuf *ibuf) return ima; } +/* packs rects from memory as PNG + * convert multiview images to R_IMF_VIEWS_INDIVIDUAL + */ +static void image_memorypack_multiview(Image *ima) +{ + ImageView *iv; + size_t i; + + image_free_packedfiles(ima); + + for (i = 0, iv = ima->views.first; iv; iv = iv->next, i++) { + ImBuf *ibuf = image_get_cached_ibuf_for_index_frame(ima, i, 0); + + ibuf->ftype = PNG; + ibuf->planes = R_IMF_PLANES_RGBA; + + /* if the image was a R_IMF_VIEWS_STEREO_3D we force _L, _R suffices */ + if (ima->views_format == R_IMF_VIEWS_STEREO_3D) { + const char *suffix[2] = {STEREO_LEFT_SUFFIX, STEREO_RIGHT_SUFFIX}; + BLI_path_suffix(iv->filepath, FILE_MAX, suffix[i], ""); + } + + IMB_saveiff(ibuf, iv->filepath, IB_rect | IB_mem); + + if (ibuf->encodedbuffer == NULL) { + printf("memory save for pack error\n"); + IMB_freeImBuf(ibuf); + image_free_packedfiles(ima); + return; + } + else { + ImagePackedFile *imapf; + PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile"); + + pf->data = ibuf->encodedbuffer; + pf->size = ibuf->encodedsize; + + imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile"); + BLI_strncpy(imapf->filepath, iv->filepath, sizeof(imapf->filepath)); + imapf->packedfile = pf; + BLI_addtail(&ima->packedfiles, imapf); + + ibuf->encodedbuffer = NULL; + ibuf->encodedsize = 0; + ibuf->userflags &= ~IB_BITMAPDIRTY; + } + IMB_freeImBuf(ibuf); + } + + if (ima->source == IMA_SRC_GENERATED) { + ima->source = IMA_SRC_FILE; + ima->type = IMA_TYPE_IMAGE; + } + ima->views_format = R_IMF_VIEWS_INDIVIDUAL; +} + /* packs rect from memory as PNG */ void BKE_image_memorypack(Image *ima) { - ImBuf *ibuf = image_get_cached_ibuf_for_index_frame(ima, IMA_NO_INDEX, 0); + ImBuf *ibuf; + + if ((ima->flag & IMA_IS_MULTIVIEW)) + return image_memorypack_multiview(ima); + + ibuf = image_get_cached_ibuf_for_index_frame(ima, IMA_NO_INDEX, 0); if (ibuf == NULL) return; - if (ima->packedfile) { - freePackedFile(ima->packedfile); - ima->packedfile = NULL; - } + + image_free_packedfiles(ima); ibuf->ftype = PNG; ibuf->planes = R_IMF_PLANES_RGBA; @@ -841,11 +978,17 @@ void BKE_image_memorypack(Image *ima) printf("memory save for pack error\n"); } else { + ImagePackedFile *imapf; PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile"); pf->data = ibuf->encodedbuffer; pf->size = ibuf->encodedsize; - ima->packedfile = pf; + + imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile"); + BLI_strncpy(imapf->filepath, ima->name, sizeof(imapf->filepath)); + imapf->packedfile = pf; + BLI_addtail(&ima->packedfiles, imapf); + ibuf->encodedbuffer = NULL; ibuf->encodedsize = 0; ibuf->userflags &= ~IB_BITMAPDIRTY; @@ -859,6 +1002,28 @@ void BKE_image_memorypack(Image *ima) IMB_freeImBuf(ibuf); } +void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath) +{ + const size_t totfiles = image_num_files(ima); + + if (totfiles == 1) { + ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image packed file"); + BLI_addtail(&ima->packedfiles, imapf); + imapf->packedfile = newPackedFile(reports, ima->name, basepath); + BLI_strncpy(imapf->filepath, ima->name, sizeof(imapf->filepath)); + } + else { + ImageView *iv; + for (iv = ima->views.first; iv; iv = iv->next) { + ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image packed file"); + BLI_addtail(&ima->packedfiles, imapf); + + imapf->packedfile = newPackedFile(reports, iv->filepath, basepath); + BLI_strncpy(imapf->filepath, iv->filepath, sizeof(imapf->filepath)); + } + } +} + void BKE_image_tag_time(Image *ima) { ima->lastused = PIL_check_seconds_timer_i(); @@ -1259,7 +1424,7 @@ char BKE_imtype_from_arg(const char *imtype_arg) else return R_IMF_IMTYPE_INVALID; } -static bool image_path_ensure_ext(char *string, const char imtype, const ImageFormatData *im_format) +static bool do_add_image_extension(char *string, const char imtype, const ImageFormatData *im_format) { const char *extension = NULL; const char *extension_test; @@ -1311,7 +1476,7 @@ static bool image_path_ensure_ext(char *string, const char imtype, const ImageFo } #endif #ifdef WITH_OPENEXR - else if (ELEM(imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) { + else if (imtype == R_IMF_IMTYPE_OPENEXR || imtype == R_IMF_IMTYPE_MULTILAYER) { if (!BLI_testextensie(string, extension_test = ".exr")) extension = extension_test; } @@ -1369,14 +1534,14 @@ static bool image_path_ensure_ext(char *string, const char imtype, const ImageFo } } -bool BKE_image_path_ensure_ext_from_imformat(char *string, const ImageFormatData *im_format) +int BKE_image_path_ensure_ext_from_imformat(char *string, const ImageFormatData *im_format) { - return image_path_ensure_ext(string, im_format->imtype, im_format); + return do_add_image_extension(string, im_format->imtype, im_format); } -bool BKE_image_path_ensure_ext_from_imtype(char *string, const char imtype) +int BKE_image_path_ensure_ext_from_imtype(char *string, const char imtype) { - return image_path_ensure_ext(string, imtype, NULL); + return do_add_image_extension(string, imtype, NULL); } void BKE_imformat_defaults(ImageFormatData *im_format) @@ -1908,14 +2073,12 @@ bool BKE_imbuf_alpha_test(ImBuf *ibuf) /* note: imf->planes is ignored here, its assumed the image channels * are already set */ -int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf) +void BKE_imbuf_write_prepare(ImBuf *ibuf, ImageFormatData *imf) { char imtype = imf->imtype; char compress = imf->compress; char quality = imf->quality; - int ok; - if (imtype == R_IMF_IMTYPE_IRIS) { ibuf->ftype = IMAGIC; } @@ -1952,7 +2115,7 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf) } #endif #ifdef WITH_OPENEXR - else if (imtype == R_IMF_IMTYPE_OPENEXR || imtype == R_IMF_IMTYPE_MULTILAYER) { + else if (ELEM(imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) { ibuf->ftype = OPENEXR; if (imf->depth == R_IMF_CHAN_DEPTH_16) ibuf->ftype |= OPENEXR_HALF; @@ -2036,6 +2199,13 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf) if (quality < 10) quality = 90; ibuf->ftype = JPG | quality; } +} + +int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf) +{ + int ok; + + BKE_imbuf_write_prepare(ibuf, imf); BLI_make_existing_file(name); @@ -2079,9 +2249,10 @@ int BKE_imbuf_write_stamp(Scene *scene, struct Object *camera, ImBuf *ibuf, cons } -static void image_path_makepicstring( +static void do_makepicstring( char *string, const char *base, const char *relbase, int frame, const char imtype, - const ImageFormatData *im_format, const short use_ext, const short use_frames) + const ImageFormatData *im_format, const short use_ext, const short use_frames, + const char *suffix) { if (string == NULL) return; BLI_strncpy(string, base, FILE_MAX - 10); /* weak assumption */ @@ -2090,22 +2261,25 @@ static void image_path_makepicstring( if (use_frames) BLI_path_frame(string, frame, 4); + if (suffix) + BLI_path_suffix(string, FILE_MAX, suffix, ""); + if (use_ext) - image_path_ensure_ext(string, imtype, im_format); + do_add_image_extension(string, imtype, im_format); } void BKE_image_path_from_imformat( char *string, const char *base, const char *relbase, int frame, - const ImageFormatData *im_format, const bool use_ext, const bool use_frames) + const ImageFormatData *im_format, const bool use_ext, const bool use_frames, const char *suffix) { - image_path_makepicstring(string, base, relbase, frame, im_format->imtype, im_format, use_ext, use_frames); + do_makepicstring(string, base, relbase, frame, im_format->imtype, im_format, use_ext, use_frames, suffix); } void BKE_image_path_from_imtype( char *string, const char *base, const char *relbase, int frame, - const char imtype, const bool use_ext, const bool use_frames) + const char imtype, const bool use_ext, const bool use_frames, const char *view) { - image_path_makepicstring(string, base, relbase, frame, imtype, NULL, use_ext, use_frames); + do_makepicstring(string, base, relbase, frame, imtype, NULL, use_ext, use_frames, view); } struct anim *openanim_noload(const char *name, int flags, int streamindex, char colorspace[IMA_MAX_SPACE]) @@ -2181,6 +2355,59 @@ Image *BKE_image_verify_viewer(int type, const char *name) return ima; } +static void image_viewer_create_views(const RenderData *rd, Image *ima) +{ + SceneRenderView *srv; + for (srv = rd->views.first; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) + continue; + image_add_view(ima, srv->name, ""); + } +} + +/* Reset the image cache and views when the Viewer Nodes views don't match the scene views */ +void BKE_image_verify_viewer_views(const RenderData *rd, Image *ima, ImageUser *iuser) +{ + bool do_reset; + + BLI_lock_thread(LOCK_DRAW_IMAGE); + + if (BKE_scene_multiview_is_stereo3d(rd)) { + ima->flag |= IMA_IS_STEREO; + ima->flag |= IMA_IS_MULTIVIEW; + } + else { + ima->flag &= ~IMA_IS_STEREO; + ima->flag &= ~IMA_IS_MULTIVIEW; + iuser->flag &= ~IMA_SHOW_STEREO; + } + + /* see if all scene render views are in the image view list */ + do_reset = (BKE_scene_multiview_num_views_get(rd) != BLI_listbase_count(&ima->views)); + if (!do_reset) { + SceneRenderView *srv; + ImageView *iv; + + for (iv = ima->views.first; iv; iv = iv->next) { + srv = BLI_findstring(&rd->views, iv->name, offsetof(SceneRenderView, name)); + if ((srv == NULL) || (BKE_scene_multiview_is_render_view_active(rd, srv) == false)) { + do_reset = true; + break; + } + } + } + + if (do_reset) { + image_free_cached_frames(ima); + BKE_image_free_views(ima); + + /* add new views */ + image_viewer_create_views(rd, ima); + } + + BLI_unlock_thread(LOCK_DRAW_IMAGE); +} + void BKE_image_walk_all_users(const Main *mainp, void *customdata, void callback(Image *ima, ImageUser *iuser, void *customdata)) { @@ -2238,6 +2465,33 @@ static void image_tag_frame_recalc(Image *ima, ImageUser *iuser, void *customdat } } +static void image_init_imageuser(Image *ima, ImageUser *iuser) +{ + RenderResult *rr = ima->rr; + + iuser->multi_index = 0; + iuser->layer = iuser->pass = iuser->view = 0; + iuser->passtype = SCE_PASS_COMBINED; + + if (rr) { + RenderLayer *rl = rr->layers.first; + + if (rl) { + RenderPass *rp = rl->passes.first; + + if (rp) + iuser->passtype = rp->passtype; + } + + BKE_image_multilayer_index(rr, iuser); + } +} + +void BKE_image_init_imageuser(Image *ima, ImageUser *iuser) +{ + return image_init_imageuser(ima, iuser); +} + void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) { if (ima == NULL) @@ -2248,8 +2502,13 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) switch (signal) { case IMA_SIGNAL_FREE: BKE_image_free_buffers(ima); - if (iuser) + + if (iuser) { iuser->ok = 1; + if (iuser->scene) { + image_update_views_format(ima, iuser); + } + } break; case IMA_SIGNAL_SRC_CHANGE: if (ima->type == IMA_TYPE_UV_TEST) @@ -2301,23 +2560,41 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) case IMA_SIGNAL_RELOAD: /* try to repack file */ - if (ima->packedfile) { - PackedFile *pf; - pf = newPackedFile(NULL, ima->name, ID_BLEND_PATH(G.main, &ima->id)); - if (pf) { - freePackedFile(ima->packedfile); - ima->packedfile = pf; - BKE_image_free_buffers(ima); + if (BKE_image_has_packedfile(ima)) { + const size_t totfiles = image_num_files(ima); + + if (totfiles != BLI_listbase_count_ex(&ima->packedfiles, totfiles + 1)) { + /* in case there are new available files to be loaded */ + image_free_packedfiles(ima); + BKE_image_packfiles(NULL, ima, ID_BLEND_PATH(G.main, &ima->id)); } else { - printf("ERROR: Image not available. Keeping packed image\n"); + ImagePackedFile *imapf; + for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) { + PackedFile *pf; + pf = newPackedFile(NULL, imapf->filepath, ID_BLEND_PATH(G.main, &ima->id)); + if (pf) { + freePackedFile(imapf->packedfile); + imapf->packedfile = pf; + } + else { + printf("ERROR: Image \"%s\" not available. Keeping packed image\n", imapf->filepath); + } + } } + + if (BKE_image_has_packedfile(ima)) + BKE_image_free_buffers(ima); } else BKE_image_free_buffers(ima); - if (iuser) + if (iuser) { iuser->ok = 1; + if (iuser->scene) { + image_update_views_format(ima, iuser); + } + } break; case IMA_SIGNAL_USER_NEW_IMAGE: @@ -2325,8 +2602,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) 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; + image_init_imageuser(ima, iuser); } } } @@ -2368,21 +2644,34 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser) return NULL; if (iuser) { - short index = 0, rl_index = 0, rp_index; + short index = 0, rv_index, rl_index = 0, rp_index; + bool is_stereo = (iuser->flag & IMA_SHOW_STEREO) && RE_RenderResult_is_stereo(rr); + + rv_index = is_stereo ? iuser->multiview_eye : iuser->view; 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) + + for (rpass = rl->passes.first; rpass; rpass = rpass->next, index++, rp_index++) { + if (iuser->layer == rl_index && + iuser->passtype == rpass->passtype && + rv_index == rpass->view_id) + { break; + } + } if (rpass) break; } - if (rpass) + if (rpass) { iuser->multi_index = index; - else + iuser->pass = rp_index; + } + else { iuser->multi_index = 0; + iuser->pass = 0; + } } if (rpass == NULL) { rl = rr->layers.first; @@ -2393,19 +2682,80 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser) return rpass; } +void BKE_image_multiview_index(Image *ima, ImageUser *iuser) +{ + if (iuser) { + bool is_stereo = (ima->flag & IMA_IS_STEREO) && (iuser->flag & IMA_SHOW_STEREO); + if (is_stereo) { + iuser->multi_index = iuser->multiview_eye; + } + else { + if ((iuser->view < 0) || (iuser->view >= BLI_listbase_count_ex(&ima->views, iuser->view + 1))) { + iuser->multi_index = iuser->view = 0; + } + else { + iuser->multi_index = iuser->view; + } + } + } +} + +/* 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 */ +bool BKE_image_is_multilayer(Image *ima) +{ + if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_SEQUENCE)) { + if (ima->type == IMA_TYPE_MULTILAYER) { + return true; + } + } + else if (ima->source == IMA_SRC_VIEWER) { + if (ima->type == IMA_TYPE_R_RESULT) { + return true; + } + } + return false; +} + +static void image_init_multilayer_multiview_flag(Image *ima, RenderResult *rr) +{ + if (rr) { + if (RE_RenderResult_is_stereo(rr)) { + ima->flag |= IMA_IS_STEREO; + ima->flag |= IMA_IS_MULTIVIEW; + } + else { + ima->flag &= ~IMA_IS_STEREO; + if (BLI_listbase_count_ex(&rr->views, 2) > 1) + ima->flag |= IMA_IS_MULTIVIEW; + else + ima->flag &= ~IMA_IS_MULTIVIEW; + } + } + else { + ima->flag &= ~IMA_IS_STEREO; + ima->flag &= ~IMA_IS_MULTIVIEW; + } +} + RenderResult *BKE_image_acquire_renderresult(Scene *scene, Image *ima) { + RenderResult *rr = NULL; if (ima->rr) { - return ima->rr; + rr = ima->rr; } else if (ima->type == IMA_TYPE_R_RESULT) { if (ima->render_slot == ima->last_render_slot) - return RE_AcquireResultRead(RE_GetRender(scene->id.name)); + rr = RE_AcquireResultRead(RE_GetRender(scene->id.name)); else - return ima->renders[ima->render_slot]; + rr = ima->renders[ima->render_slot]; + + /* set proper multiview flag */ + image_init_multilayer_multiview_flag(ima, rr); } - else - return NULL; + + return rr; } void BKE_image_release_renderresult(Scene *scene, Image *ima) @@ -2419,6 +2769,18 @@ void BKE_image_release_renderresult(Scene *scene, Image *ima) } } +bool BKE_image_is_openexr(struct Image *ima) +{ +#ifdef WITH_OPENEXR + if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_SEQUENCE)) { + return BLI_testextensie(ima->name, ".exr"); + } +#else + UNUSED_VARS(ima); +#endif + return false; +} + void BKE_image_backup_render(Scene *scene, Image *ima) { /* called right before rendering, ima->renders contains render @@ -2439,8 +2801,155 @@ void BKE_image_backup_render(Scene *scene, Image *ima) ima->last_render_slot = slot; } +/**************************** multiview save openexr *********************************/ +#ifdef WITH_OPENEXR +static const char *image_get_view_cb(void *base, const size_t view_id) +{ + Image *ima = base; + ImageView *iv = BLI_findlink(&ima->views, view_id); + return iv ? iv->name : ""; +} +#endif /* WITH_OPENEXR */ + +#ifdef WITH_OPENEXR +static ImBuf *image_get_buffer_cb(void *base, const size_t view_id) +{ + Image *ima = base; + ImageUser iuser = {0}; + + iuser.view = view_id; + iuser.ok = 1; + + BKE_image_multiview_index(ima, &iuser); + + return image_acquire_ibuf(ima, &iuser, NULL); +} +#endif /* WITH_OPENEXR */ + +bool BKE_image_save_openexr_multiview(Image *ima, ImBuf *ibuf, const char *filepath, const int flags) +{ +#ifdef WITH_OPENEXR + char name[FILE_MAX]; + bool ok; + + BLI_strncpy(name, filepath, sizeof(name)); + BLI_path_abs(name, G.main->name); + + ibuf->userdata = ima; + ok = IMB_exr_multiview_save(ibuf, name, flags, BLI_listbase_count(&ima->views), image_get_view_cb, image_get_buffer_cb); + ibuf->userdata = NULL; + + return ok; +#else + UNUSED_VARS(ima, ibuf, filepath, flags); + return false; +#endif +} + +/**************************** multiview load openexr *********************************/ + +static void image_add_view(Image *ima, const char *viewname, const char *filepath) +{ + ImageView *iv; + + iv = MEM_mallocN(sizeof(ImageView), "Viewer Image View"); + BLI_strncpy(iv->name, viewname, sizeof(iv->name)); + BLI_strncpy(iv->filepath, filepath, sizeof(iv->filepath)); + + /* For stereo drawing we need to ensure: + * STEREO_LEFT_NAME == STEREO_LEFT_ID and + * STEREO_RIGHT_NAME == STEREO_RIGHT_ID */ + + if (STREQ(viewname, STEREO_LEFT_NAME)) { + BLI_addhead(&ima->views, iv); + } + else if (STREQ(viewname, STEREO_RIGHT_NAME)) { + ImageView *left_iv = BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name)); + + if (left_iv == NULL) { + BLI_addhead(&ima->views, iv); + } + else { + BLI_insertlinkafter(&ima->views, left_iv, iv); + } + } + else { + BLI_addtail(&ima->views, iv); + } +} + +#ifdef WITH_OPENEXR +static void image_add_view_cb(void *base, const char *str) +{ + Image *ima = base; + image_add_view(ima, str, ima->name); +} + +static void image_add_buffer_cb(void *base, const char *str, ImBuf *ibuf, const int frame) +{ + Image *ima = base; + size_t id; + bool predivide = (ima->alpha_mode == IMA_ALPHA_PREMUL); + const char *colorspace = ima->colorspace_settings.name; + const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); + + if (ibuf == NULL) + return; + + id = BLI_findstringindex(&ima->views, str, offsetof(ImageView, name)); + + if (id == -1) + return; + + if (ibuf->channels >= 3) + IMB_colormanagement_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + colorspace, to_colorspace, predivide); + + image_assign_ibuf(ima, ibuf, id, frame); + IMB_freeImBuf(ibuf); +} +#endif /* WITH_OPENEXR */ + +#ifdef WITH_OPENEXR +static void image_update_multiview_flags(Image *ima) +{ + if (BLI_listbase_count_ex(&ima->views, 2) > 1) { + ima->flag |= IMA_IS_MULTIVIEW; + + if (BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name)) && + BLI_findstring(&ima->views, STEREO_RIGHT_NAME, offsetof(ImageView, name))) + { + ima->flag |= IMA_IS_STEREO; + } + else { + ima->flag &= ~IMA_IS_STEREO; + } + } + else { + ima->flag &= ~IMA_IS_STEREO; + ima->flag &= ~IMA_IS_MULTIVIEW; + } +} +#endif /* WITH_OPENEXR */ + /* after imbuf load, openexr type can return with a exrhandle open */ /* in that case we have to build a render-result */ +#ifdef WITH_OPENEXR +static void image_create_multiview(Image *ima, ImBuf *ibuf, const int frame) +{ + image_free_views(ima); + + IMB_exr_multiview_convert(ibuf->userdata, ima, image_add_view_cb, image_add_buffer_cb, frame); + + image_update_multiview_flags(ima); + + IMB_exr_close(ibuf->userdata); +} +#endif /* WITH_OPENEXR */ + +/* after imbuf load, openexr type can return with a exrhandle open */ +/* in that case we have to build a render-result */ +#ifdef WITH_OPENEXR static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) { const char *colorspace = ima->colorspace_settings.name; @@ -2448,14 +2957,16 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) ima->rr = RE_MultilayerConvert(ibuf->userdata, colorspace, predivide, ibuf->x, ibuf->y); -#ifdef WITH_OPENEXR IMB_exr_close(ibuf->userdata); -#endif ibuf->userdata = NULL; if (ima->rr) ima->rr->framenr = framenr; + + /* set proper multiview flag */ + image_init_multilayer_multiview_flag(ima, ima->rr); } +#endif /* WITH_OPENEXR */ /* common stuff to do with images after loading */ static void image_initialize_after_load(Image *ima, ImBuf *ibuf) @@ -2488,18 +2999,41 @@ static int imbuf_alpha_flags_for_image(Image *ima) return flag; } -static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) +/* the number of files will vary according to the stereo format */ +static size_t image_num_files(Image *ima) +{ + const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0; + + if (!is_multiview) { + return 1; + } + else if (ima->views_format == R_IMF_VIEWS_STEREO_3D) { + return 1; + } + /* R_IMF_VIEWS_INDIVIDUAL */ + else { + return BLI_listbase_count(&ima->views); + } +} + +static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, const size_t view_id, bool *r_assign) { struct ImBuf *ibuf; char name[FILE_MAX]; int flag; + ImageUser iuser_t; /* XXX temp stuff? */ if (ima->lastframe != frame) ima->tpageflag |= IMA_TPAGE_REFRESH; ima->lastframe = frame; - BKE_image_user_file_path(iuser, ima, name); + + if (iuser) + iuser_t = *iuser; + + iuser_t.view = view_id; + BKE_image_user_file_path(&iuser_t, ima, name); flag = IB_rect | IB_multilayer; flag |= imbuf_alpha_flags_for_image(ima); @@ -2520,25 +3054,78 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) #ifdef WITH_OPENEXR /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */ if (ibuf->ftype == OPENEXR && ibuf->userdata) { - image_create_multilayer(ima, ibuf, frame); - ima->type = IMA_TYPE_MULTILAYER; - IMB_freeImBuf(ibuf); - ibuf = NULL; + /* handle singlelayer multiview case assign ibuf based on available views */ + if (IMB_exr_has_singlelayer_multiview(ibuf->userdata)) { + image_create_multiview(ima, ibuf, frame); + IMB_freeImBuf(ibuf); + ibuf = NULL; + } + else if (IMB_exr_has_multilayer(ibuf->userdata)) { + /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */ + image_create_multilayer(ima, ibuf, frame); + ima->type = IMA_TYPE_MULTILAYER; + IMB_freeImBuf(ibuf); + ibuf = NULL; + } } else { image_initialize_after_load(ima, ibuf); - image_assign_ibuf(ima, ibuf, 0, frame); + *r_assign = true; } #else image_initialize_after_load(ima, ibuf); - image_assign_ibuf(ima, ibuf, 0, frame); + *r_assign = true; #endif } - else - ima->ok = 0; - if (iuser) - iuser->ok = ima->ok; + return ibuf; +} + +static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) +{ + struct ImBuf *ibuf = NULL; + const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0; + const size_t totfiles = image_num_files(ima); + bool assign = false; + + if (!is_multiview) { + ibuf = load_sequence_single(ima, iuser, frame, 0, &assign); + if (assign) { + image_assign_ibuf(ima, ibuf, 0, frame); + } + } + else { + size_t i; + struct ImBuf **ibuf_arr; + const size_t totviews = BLI_listbase_count(&ima->views); + + ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * totviews, "Image Views Imbufs"); + + for (i = 0; i < totfiles; i++) + ibuf_arr[i] = load_sequence_single(ima, iuser, frame, i, &assign); + + if ((ima->flag & IMA_IS_STEREO) && ima->views_format == R_IMF_VIEWS_STEREO_3D) + IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]); + + /* return the original requested ImBuf */ + ibuf = ibuf_arr[(iuser ? iuser->multi_index : 0)]; + + if (assign) { + for (i = 0; i < totviews; i++) { + image_assign_ibuf(ima, ibuf_arr[i], i, frame); + } + } + + /* "remove" the others (decrease their refcount) */ + for (i = 0; i < totviews; i++) { + if (ibuf_arr[i] != ibuf) { + IMB_freeImBuf(ibuf_arr[i]); + } + } + + /* cleanup */ + MEM_freeN(ibuf_arr); + } return ibuf; } @@ -2595,46 +3182,52 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f return ibuf; } - -static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) +static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const size_t view_id) { struct ImBuf *ibuf = NULL; + ImageAnim *ia; - ima->lastframe = frame; + ia = BLI_findlink(&ima->anims, view_id); - if (ima->anim == NULL) { + if (ia->anim == NULL) { char str[FILE_MAX]; int flags = IB_rect; + ImageUser iuser_t; + if (ima->flag & IMA_DEINTERLACE) { flags |= IB_animdeinterlace; } - BKE_image_user_file_path(iuser, ima, str); + if (iuser) + iuser_t = *iuser; + + iuser_t.view = view_id; + + BKE_image_user_file_path(&iuser_t, ima, str); /* FIXME: make several stream accessible in image editor, too*/ - ima->anim = openanim(str, flags, 0, ima->colorspace_settings.name); + ia->anim = openanim(str, flags, 0, ima->colorspace_settings.name); /* let's initialize this user */ - if (ima->anim && iuser && iuser->frames == 0) - iuser->frames = IMB_anim_get_duration(ima->anim, + if (ia->anim && iuser && iuser->frames == 0) + iuser->frames = IMB_anim_get_duration(ia->anim, IMB_TC_RECORD_RUN); } - if (ima->anim) { - int dur = IMB_anim_get_duration(ima->anim, + if (ia->anim) { + int dur = IMB_anim_get_duration(ia->anim, IMB_TC_RECORD_RUN); int fra = frame - 1; if (fra < 0) fra = 0; if (fra > (dur - 1)) fra = dur - 1; ibuf = IMB_makeSingleUser( - IMB_anim_absolute(ima->anim, fra, + IMB_anim_absolute(ia->anim, fra, IMB_TC_RECORD_RUN, IMB_PROXY_NONE)); if (ibuf) { image_initialize_after_load(ima, ibuf); - image_assign_ibuf(ima, ibuf, 0, frame); } else ima->ok = 0; @@ -2642,67 +3235,223 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) else ima->ok = 0; + return ibuf; +} + +static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) +{ + struct ImBuf *ibuf = NULL; + const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0; + const size_t totfiles = image_num_files(ima); + size_t i; + + if (totfiles != BLI_listbase_count_ex(&ima->anims, totfiles + 1)) { + image_free_anims(ima); + + for (i = 0; i < totfiles; i++) { + /* allocate the ImageAnim */ + ImageAnim *ia = MEM_callocN(sizeof(ImageAnim), "Image Anim"); + BLI_addtail(&ima->anims, ia); + } + } + + if (!is_multiview) { + ibuf = load_movie_single(ima, iuser, frame, 0); + image_assign_ibuf(ima, ibuf, 0, frame); + } + else { + struct ImBuf **ibuf_arr; + const size_t totviews = BLI_listbase_count(&ima->views); + + ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * totviews, "Image Views (movie) Imbufs"); + + for (i = 0; i < totfiles; i++) { + ibuf_arr[i] = load_movie_single(ima, iuser, frame, i); + } + + if ((ima->flag & IMA_IS_STEREO) && ima->views_format == R_IMF_VIEWS_STEREO_3D) + IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]); + + for (i = 0; i < totviews; i++) { + if (ibuf_arr[i]) { + image_assign_ibuf(ima, ibuf_arr[i], i, frame); + } + else { + ima->ok = 0; + } + } + + /* return the original requested ImBuf */ + ibuf = ibuf_arr[(iuser ? iuser->multi_index : 0)]; + + /* "remove" the others (decrease their refcount) */ + for (i = 0; i < totviews; i++) { + if (ibuf_arr[i] != ibuf) { + IMB_freeImBuf(ibuf_arr[i]); + } + } + + /* cleanup */ + MEM_freeN(ibuf_arr); + } + if (iuser) iuser->ok = ima->ok; return ibuf; } -/* warning, 'iuser' can be NULL */ -static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) +static ImBuf *load_image_single( + Image *ima, ImageUser *iuser, int cfra, + const size_t view_id, + const bool has_packed, + bool *r_assign) { - struct ImBuf *ibuf; - char str[FILE_MAX]; - int assign = 0, flag; - - /* always ensure clean ima */ - BKE_image_free_buffers(ima); + char filepath[FILE_MAX]; + struct ImBuf *ibuf = NULL; + int flag; /* is there a PackedFile with this image ? */ - if (ima->packedfile) { + if (has_packed) { + ImagePackedFile *imapf; + flag = IB_rect | IB_multilayer; flag |= imbuf_alpha_flags_for_image(ima); - ibuf = IMB_ibImageFromMemory((unsigned char *)ima->packedfile->data, ima->packedfile->size, flag, - ima->colorspace_settings.name, ""); + imapf = BLI_findlink(&ima->packedfiles, view_id); + ibuf = IMB_ibImageFromMemory( + (unsigned char *)imapf->packedfile->data, imapf->packedfile->size, flag, + ima->colorspace_settings.name, ""); } else { + ImageUser iuser_t; + flag = IB_rect | IB_multilayer | IB_metadata; flag |= imbuf_alpha_flags_for_image(ima); - /* get the right string */ + /* get the correct filepath */ BKE_image_user_frame_calc(iuser, cfra, 0); - BKE_image_user_file_path(iuser, ima, str); + + if (iuser) + iuser_t = *iuser; + else + iuser_t.framenr = ima->lastframe; + + iuser_t.view = view_id; + + BKE_image_user_file_path(&iuser_t, ima, filepath); /* read ibuf */ - ibuf = IMB_loadiffname(str, flag, ima->colorspace_settings.name); + ibuf = IMB_loadiffname(filepath, flag, ima->colorspace_settings.name); } if (ibuf) { - /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */ +#ifdef WITH_OPENEXR if (ibuf->ftype == OPENEXR && ibuf->userdata) { - image_create_multilayer(ima, ibuf, cfra); - ima->type = IMA_TYPE_MULTILAYER; - IMB_freeImBuf(ibuf); - ibuf = NULL; + if (IMB_exr_has_singlelayer_multiview(ibuf->userdata)) { + /* handle singlelayer multiview case assign ibuf based on available views */ + image_create_multiview(ima, ibuf, cfra); + IMB_freeImBuf(ibuf); + ibuf = NULL; + } + else if (IMB_exr_has_multilayer(ibuf->userdata)) { + /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */ + image_create_multilayer(ima, ibuf, cfra); + ima->type = IMA_TYPE_MULTILAYER; + IMB_freeImBuf(ibuf); + ibuf = NULL; + } } else { image_initialize_after_load(ima, ibuf); - assign = 1; + *r_assign = true; /* 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(NULL, str, ID_BLEND_PATH(G.main, &ima->id)); + if ((has_packed == false) && (G.fileflags & G_AUTOPACK)) { + ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image Packefile"); + BLI_addtail(&ima->packedfiles, imapf); + + BLI_strncpy(imapf->filepath, filepath, sizeof(imapf->filepath)); + imapf->packedfile = newPackedFile(NULL, filepath, ID_BLEND_PATH(G.main, &ima->id)); + } } +#else + image_initialize_after_load(ima, ibuf); + *r_assign = true; +#endif } - else + else { ima->ok = 0; + } - if (assign) - image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + return ibuf; +} + +/* warning, 'iuser' can be NULL + * note: Image->views was already populated (in image_update_views_format) + */ +static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) +{ + struct ImBuf *ibuf = NULL; + bool assign = false; + const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0; + const size_t totfiles = image_num_files(ima); + bool has_packed = BKE_image_has_packedfile(ima); + + /* always ensure clean ima */ + BKE_image_free_buffers(ima); + + /* this should never happen, but just playing safe */ + if (has_packed) { + if (totfiles != BLI_listbase_count_ex(&ima->packedfiles, totfiles + 1)) { + image_free_packedfiles(ima); + has_packed = false; + } + } + + if (!is_multiview) { + ibuf = load_image_single(ima, iuser, cfra, 0, has_packed, &assign); + if (assign) { + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + } + } + else { + size_t i; + struct ImBuf **ibuf_arr; + const size_t totviews = BLI_listbase_count(&ima->views); + BLI_assert(totviews > 0); + + ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * totviews, "Image Views Imbufs"); + + for (i = 0; i < totfiles; i++) + ibuf_arr[i] = load_image_single(ima, iuser, cfra, i, has_packed, &assign); + + if ((ima->flag & IMA_IS_STEREO) && ima->views_format == R_IMF_VIEWS_STEREO_3D) + IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]); + + /* return the original requested ImBuf */ + i = iuser && iuser->multi_index < totviews ? iuser->multi_index : 0; + ibuf = ibuf_arr[i]; + + if (assign) { + for (i = 0; i < totviews; i++) { + image_assign_ibuf(ima, ibuf_arr[i], i, 0); + } + } + + /* "remove" the others (decrease their refcount) */ + for (i = 0; i < totviews; i++) { + if (ibuf_arr[i] != ibuf) { + IMB_freeImBuf(ibuf_arr[i]); + } + } + + /* cleanup */ + MEM_freeN(ibuf_arr); + } if (iuser) iuser->ok = ima->ok; @@ -2756,9 +3505,10 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ float *rectf, *rectz; unsigned int *rect; float dither; - int channels, layer, pass; + int channels, layer, passtype; ImBuf *ibuf; int from_render = (ima->render_slot == ima->last_render_slot); + int actview; bool byte_buffer_in_display_space = false; if (!(iuser && iuser->scene)) @@ -2772,14 +3522,18 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ channels = 4; layer = iuser->layer; - pass = iuser->pass; + passtype = iuser->passtype; + actview = iuser->view; + + if ((ima->flag & IMA_IS_STEREO) && (iuser->flag & IMA_SHOW_STEREO)) + actview = iuser->multiview_eye; if (from_render) { - RE_AcquireResultImage(re, &rres); + RE_AcquireResultImage(re, &rres, actview); } else if (ima->renders[ima->render_slot]) { rres = *(ima->renders[ima->render_slot]); - rres.have_combined = rres.rectf != NULL; + rres.have_combined = RE_RenderViewGetRectf(&rres, actview) != NULL; } else memset(&rres, 0, sizeof(RenderResult)); @@ -2819,24 +3573,18 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ if (rl) { RenderPass *rpass; - /* there's no combined pass, is in renderlayer itself */ - if (pass == 0) { - rectf = rl->rectf; - if (rectf == NULL) { - /* Happens when Save Buffers is enabled. - * Use display buffer stored in the render layer. - */ - rect = (unsigned int *) rl->display_buffer; - byte_buffer_in_display_space = true; + for (rpass = rl->passes.first; rpass; rpass = rpass->next) { + if (passtype == rpass->passtype && + actview == rpass->view_id) + { + break; } } - else { - rpass = BLI_findlink(&rl->passes, pass - 1); - if (rpass) { - channels = rpass->channels; - rectf = rpass->rect; - dither = 0.0f; /* don't dither passes */ - } + + if (rpass) { + channels = rpass->channels; + rectf = rpass->rect; + dither = 0.0f; /* don't dither passes */ } for (rpass = rl->passes.first; rpass; rpass = rpass->next) @@ -2925,9 +3673,31 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ return ibuf; } +static size_t image_get_multiview_index(Image *ima, ImageUser *iuser) +{ + const bool is_multilayer = BKE_image_is_multilayer(ima); + const bool is_backdrop = (ima->source == IMA_SRC_VIEWER) && (ima->type == IMA_TYPE_COMPOSITE) && (iuser == NULL); + + if (is_multilayer) { + return iuser ? iuser->multi_index : IMA_NO_INDEX; + } + else if (is_backdrop) { + if ((ima->flag & IMA_IS_STEREO)) { + /* backdrop hackaround (since there is no iuser */ + return ima->eye; + } + } + else if ((ima->flag & IMA_IS_MULTIVIEW)) { + return iuser ? iuser->multi_index : 0; + } + + return IMA_NO_INDEX; +} + static void image_get_frame_and_index(Image *ima, ImageUser *iuser, int *r_frame, int *r_index) { int frame = 0, index = 0; + index = image_get_multiview_index(ima, iuser); /* see if we already have an appropriate ibuf, with image source and type */ if (ima->source == IMA_SRC_MOVIE) { @@ -2939,7 +3709,6 @@ static void image_get_frame_and_index(Image *ima, ImageUser *iuser, int *r_frame } else if (ima->type == IMA_TYPE_MULTILAYER) { frame = iuser ? iuser->framenr : ima->lastframe; - index = iuser ? iuser->multi_index : IMA_NO_INDEX; } } @@ -2958,10 +3727,12 @@ static ImBuf *image_get_cached_ibuf(Image *ima, ImageUser *iuser, int *r_frame, ImBuf *ibuf = NULL; int frame = 0, index = 0; + index = image_get_multiview_index(ima, iuser); + /* see if we already have an appropriate ibuf, with image source and type */ if (ima->source == IMA_SRC_MOVIE) { frame = iuser ? iuser->framenr : ima->lastframe; - ibuf = image_get_cached_ibuf_for_index_frame(ima, 0, frame); + ibuf = image_get_cached_ibuf_for_index_frame(ima, index, frame); /* XXX temp stuff? */ if (ima->lastframe != frame) ima->tpageflag |= IMA_TPAGE_REFRESH; @@ -2970,7 +3741,7 @@ static ImBuf *image_get_cached_ibuf(Image *ima, ImageUser *iuser, int *r_frame, else if (ima->source == IMA_SRC_SEQUENCE) { if (ima->type == IMA_TYPE_IMAGE) { frame = iuser ? iuser->framenr : ima->lastframe; - ibuf = image_get_cached_ibuf_for_index_frame(ima, 0, frame); + ibuf = image_get_cached_ibuf_for_index_frame(ima, index, frame); /* XXX temp stuff? */ if (ima->lastframe != frame) { @@ -2990,18 +3761,17 @@ static ImBuf *image_get_cached_ibuf(Image *ima, ImageUser *iuser, int *r_frame, } else if (ima->type == IMA_TYPE_MULTILAYER) { frame = iuser ? iuser->framenr : ima->lastframe; - index = iuser ? iuser->multi_index : IMA_NO_INDEX; ibuf = image_get_cached_ibuf_for_index_frame(ima, index, frame); } } else if (ima->source == IMA_SRC_FILE) { if (ima->type == IMA_TYPE_IMAGE) - ibuf = image_get_cached_ibuf_for_index_frame(ima, IMA_NO_INDEX, 0); + ibuf = image_get_cached_ibuf_for_index_frame(ima, index, 0); else if (ima->type == IMA_TYPE_MULTILAYER) - ibuf = image_get_cached_ibuf_for_index_frame(ima, iuser ? iuser->multi_index : IMA_NO_INDEX, 0); + ibuf = image_get_cached_ibuf_for_index_frame(ima, index, 0); } else if (ima->source == IMA_SRC_GENERATED) { - ibuf = image_get_cached_ibuf_for_index_frame(ima, IMA_NO_INDEX, 0); + ibuf = image_get_cached_ibuf_for_index_frame(ima, index, 0); } else if (ima->source == IMA_SRC_VIEWER) { /* always verify entirely, not that this shouldn't happen @@ -3085,7 +3855,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) if (ima->gen_depth == 0) ima->gen_depth = 24; ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, ima->gen_depth, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, ima->gen_color, &ima->colorspace_settings); - image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + image_assign_ibuf(ima, ibuf, index, 0); ima->ok = IMA_OK_LOADED; } else if (ima->source == IMA_SRC_VIEWER) { @@ -3103,13 +3873,13 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) /* XXX anim play for viewer nodes not yet supported */ frame = 0; // XXX iuser ? iuser->framenr : 0; - ibuf = image_get_cached_ibuf_for_index_frame(ima, 0, frame); + ibuf = image_get_cached_ibuf_for_index_frame(ima, index, frame); if (!ibuf) { /* Composite Viewer, all handled in compositor */ /* fake ibuf, will be filled in compositor */ - ibuf = IMB_allocImBuf(256, 256, 32, IB_rect); - image_assign_ibuf(ima, ibuf, 0, frame); + ibuf = IMB_allocImBuf(256, 256, 32, IB_rect | IB_rectfloat); + image_assign_ibuf(ima, ibuf, index, frame); } } } @@ -3409,7 +4179,13 @@ void BKE_image_update_frame(const Main *bmain, int cfra) void BKE_image_user_file_path(ImageUser *iuser, Image *ima, char *filepath) { - BLI_strncpy(filepath, ima->name, FILE_MAX); + if ((ima->flag & IMA_IS_MULTIVIEW) && (ima->rr == NULL)) { + ImageView *iv = BLI_findlink(&ima->views, iuser->view); + BLI_strncpy(filepath, iv->filepath, FILE_MAX); + } + else { + BLI_strncpy(filepath, ima->name, FILE_MAX); + } if (ima->source == IMA_SRC_SEQUENCE) { char head[FILE_MAX], tail[FILE_MAX]; @@ -3545,6 +4321,16 @@ int BKE_image_sequence_guess_offset(Image *image) return atoi(num); } +bool BKE_image_has_anim(Image *ima) +{ + return (BLI_listbase_is_empty(&ima->anims) == false); +} + +bool BKE_image_has_packedfile(Image *ima) +{ + return (BLI_listbase_is_empty(&ima->packedfiles) == false); +} + /** * Checks the image buffer changes (not keyframed values) * @@ -3675,3 +4461,88 @@ ImBuf *BKE_image_get_first_ibuf(Image *image) return ibuf; } + +static void image_update_views_format(Image *ima, ImageUser *iuser) +{ + SceneRenderView *srv; + ImageView *iv; + Scene *scene = iuser->scene; + const bool is_multiview = ((scene->r.scemode & R_MULTIVIEW) != 0) && + ((ima->flag & IMA_USE_VIEWS) != 0); + + /* reset the image views */ + BKE_image_free_views(ima); + + if (!is_multiview) { + goto monoview; + } + else if (ima->views_format == R_IMF_VIEWS_STEREO_3D) { + size_t i; + const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + + ima->flag |= IMA_IS_MULTIVIEW; + ima->flag |= IMA_IS_STEREO; + + for (i = 0; i < 2; i++) { + image_add_view(ima, names[i], ima->name); + } + return; + } + else { + /* R_IMF_VIEWS_INDIVIDUAL */ + char prefix[FILE_MAX] = {'\0'}; + char *name = ima->name; + char *ext = NULL; + + BKE_scene_multiview_view_prefix_get(scene, name, prefix, &ext); + + if (prefix[0] == '\0') { + goto monoview; + } + + /* create all the image views */ + for (srv = scene->r.views.first; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) { + char filepath[FILE_MAX]; + BLI_snprintf(filepath, sizeof(filepath), "%s%s%s", prefix, srv->suffix, ext); + image_add_view(ima, srv->name, filepath); + } + } + + /* check if the files are all available */ + iv = ima->views.last; + while (iv) { + int file; + char str[FILE_MAX]; + + BLI_strncpy(str, iv->filepath, sizeof(str)); + BLI_path_abs(str, G.main->name); + + /* exists? */ + file = BLI_open(str, O_BINARY | O_RDONLY, 0); + if (file == -1) { + ImageView *iv_del = iv; + iv = iv->prev; + BLI_remlink(&ima->views, iv_del); + MEM_freeN(iv_del); + } + else { + iv = iv->prev; + } + close(file); + } + + /* all good */ + if (BLI_listbase_count_ex(&ima->views, 2) > 1) { + ima->flag |= IMA_IS_MULTIVIEW; + if (BKE_scene_multiview_is_stereo3d(&scene->r)) + ima->flag |= IMA_IS_STEREO; + } + else { +monoview: + ima->flag &= ~IMA_IS_STEREO; + ima->flag &= ~IMA_IS_MULTIVIEW; + BKE_image_free_views(ima); + } + } +} diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 7f3db700534..0d375b0dbeb 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -3475,6 +3475,7 @@ static void registerCompositNodes(void) register_node_type_cmp_bokehimage(); register_node_type_cmp_bokehblur(); register_node_type_cmp_switch(); + register_node_type_cmp_switch_view(); register_node_type_cmp_pixelate(); register_node_type_cmp_mask(); diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 81460ecdcc9..b89b5ab4bbc 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -1002,7 +1002,7 @@ static void cache_filename(char *string, const char *path, const char *relbase, BLI_join_dirfile(cachepath, sizeof(cachepath), path, fname); - BKE_image_path_from_imtype(string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, true, true); + BKE_image_path_from_imtype(string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, true, true, ""); } /* silly functions but useful to inline when the args do a lot of indirections */ diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 9b429b356b4..61e39d0ad47 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -128,8 +128,8 @@ int countPackedFiles(Main *bmain) /* let's check if there are packed files... */ for (ima = bmain->image.first; ima; ima = ima->id.next) - if (ima->packedfile) - count++; + if (BKE_image_has_packedfile(ima)) + count ++; for (vf = bmain->vfont.first; vf; vf = vf->id.next) if (vf->packedfile) @@ -232,9 +232,9 @@ void packAll(Main *bmain, ReportList *reports) int tot = 0; for (ima = bmain->image.first; ima; ima = ima->id.next) { - if (ima->packedfile == NULL && ima->id.lib == NULL) { + if (BKE_image_has_packedfile(ima) == false && ima->id.lib == NULL) { if (ima->source == IMA_SRC_FILE) { - ima->packedfile = newPackedFile(reports, ima->name, ID_BLEND_PATH(bmain, &ima->id)); + BKE_image_packfiles(reports, ima, ID_BLEND_PATH(bmain, &ima->id)); tot ++; } else if (BKE_image_is_animated(ima)) { @@ -564,23 +564,47 @@ int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how) int unpackImage(ReportList *reports, Image *ima, int how) { - char localname[FILE_MAX], absname[FILE_MAX]; - char *newname; int ret_value = RET_ERROR; - + if (ima != NULL && ima->name[0]) { - unpack_generate_paths(ima->name, (ID *)ima, absname, localname, sizeof(absname), sizeof(localname)); - newname = unpackFile(reports, absname, localname, ima->packedfile, how); - if (newname != NULL) { - ret_value = RET_OK; - freePackedFile(ima->packedfile); - ima->packedfile = NULL; - BLI_strncpy(ima->name, newname, sizeof(ima->name)); - MEM_freeN(newname); - BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); + while (ima->packedfiles.last) { + char localname[FILE_MAX], absname[FILE_MAX]; + char *newname; + ImagePackedFile *imapf = ima->packedfiles.last; + + unpack_generate_paths(imapf->filepath, (ID *)ima, absname, localname, sizeof(absname), sizeof(localname)); + newname = unpackFile(reports, absname, localname, imapf->packedfile, how); + + if (newname != NULL) { + ImageView *iv; + + ret_value = ret_value == RET_ERROR ? RET_ERROR : RET_OK; + freePackedFile(imapf->packedfile); + imapf->packedfile = NULL; + + /* update the new corresponding view filepath */ + iv = BLI_findstring(&ima->views, imapf->filepath, offsetof(ImageView, filepath)); + if (iv) { + BLI_strncpy(iv->filepath, newname, sizeof(imapf->filepath)); + } + + /* keep the new name in the image for non-pack specific reasons */ + BLI_strncpy(ima->name, newname, sizeof(imapf->filepath)); + MEM_freeN(newname); + } + else { + ret_value = RET_ERROR; + } + + BLI_remlink(&ima->packedfiles, imapf); + MEM_freeN(imapf); } } - + + if (ret_value == RET_OK) { + BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); + } + return(ret_value); } @@ -636,7 +660,7 @@ void unpackAll(Main *bmain, ReportList *reports, int how) bSound *sound; for (ima = bmain->image.first; ima; ima = ima->id.next) - if (ima->packedfile) + if (BKE_image_has_packedfile(ima)) unpackImage(reports, ima, how); for (vf = bmain->vfont.first; vf; vf = vf->id.next) @@ -655,7 +679,7 @@ bool BKE_pack_check(ID *id) case ID_IM: { Image *ima = (Image *)id; - return ima->packedfile != NULL; + return BKE_image_has_packedfile(ima); } case ID_VF: { @@ -683,7 +707,7 @@ void BKE_unpack_id(Main *bmain, ID *id, ReportList *reports, int how) case ID_IM: { Image *ima = (Image *)id; - if (ima->packedfile) { + if (BKE_image_has_packedfile(ima)) { unpackImage(reports, ima, how); } break; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 3b48de13553..443671f5a61 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -92,6 +92,7 @@ #include "PIL_time.h" #include "IMB_colormanagement.h" +#include "IMB_imbuf.h" #include "bmesh.h" @@ -157,14 +158,16 @@ Scene *BKE_scene_copy(Scene *sce, int type) Base *base, *obase; if (type == SCE_COPY_EMPTY) { - ListBase lb; + ListBase rl, rv; /* XXX. main should become an arg */ scen = BKE_scene_add(G.main, sce->id.name + 2); - lb = scen->r.layers; + rl = scen->r.layers; + rv = scen->r.views; scen->r = sce->r; - scen->r.layers = lb; + scen->r.layers = rl; scen->r.actlay = 0; + scen->r.views = rv; scen->unit = sce->unit; scen->physics_settings = sce->physics_settings; scen->gm = sce->gm; @@ -197,6 +200,7 @@ Scene *BKE_scene_copy(Scene *sce, int type) BLI_duplicatelist(&(scen->markers), &(sce->markers)); BLI_duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces)); BLI_duplicatelist(&(scen->r.layers), &(sce->r.layers)); + BLI_duplicatelist(&(scen->r.views), &(sce->r.views)); BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets)); if (sce->nodetree) { @@ -390,6 +394,7 @@ void BKE_scene_free(Scene *sce) BLI_freelistN(&sce->markers); BLI_freelistN(&sce->transform_spaces); BLI_freelistN(&sce->r.layers); + BLI_freelistN(&sce->r.views); if (sce->toolsettings) { if (sce->toolsettings->vpaint) { @@ -437,6 +442,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name) ParticleEditSettings *pset; int a; const char *colorspace_name; + SceneRenderView *srv; sce = BKE_libblock_alloc(bmain, ID_SCE, name); sce->lay = sce->layact = 1; @@ -628,7 +634,16 @@ Scene *BKE_scene_add(Main *bmain, const char *name) /* note; in header_info.c the scene copy happens..., if you add more to renderdata it has to be checked there */ BKE_scene_add_render_layer(sce, NULL); - + + /* multiview - stereo */ + BKE_scene_add_render_view(sce, STEREO_LEFT_NAME); + srv = sce->r.views.first; + BLI_strncpy(srv->suffix, STEREO_LEFT_SUFFIX, sizeof(srv->suffix)); + + BKE_scene_add_render_view(sce, STEREO_RIGHT_NAME); + srv = sce->r.views.last; + BLI_strncpy(srv->suffix, STEREO_RIGHT_SUFFIX, sizeof(srv->suffix)); + /* game data */ sce->gm.stereoflag = STEREO_NOSTEREO; sce->gm.stereomode = STEREO_ANAGLYPH; @@ -701,6 +716,19 @@ Scene *BKE_scene_add(Main *bmain, const char *name) return sce; } +Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name) +{ + Base *base; + + for (base = scene->base.first; base; base = base->next) { + if (STREQ(base->object->id.name + 2, name)) { + break; + } + } + + return base; +} + Base *BKE_scene_base_find(Scene *scene, Object *ob) { return BLI_findptr(&scene->base, ob, offsetof(Base, object)); @@ -1892,6 +1920,42 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer * return true; } +/* return default view */ +SceneRenderView *BKE_scene_add_render_view(Scene *sce, const char *name) +{ + SceneRenderView *srv; + + if (!name) + name = DATA_("RenderView"); + + srv = MEM_callocN(sizeof(SceneRenderView), "new render view"); + BLI_strncpy(srv->name, name, sizeof(srv->name)); + BLI_uniquename(&sce->r.views, srv, DATA_("RenderView"), '.', offsetof(SceneRenderView, name), sizeof(srv->name)); + BLI_addtail(&sce->r.views, srv); + + return srv; +} + +bool BKE_scene_remove_render_view(Scene *scene, SceneRenderView *srv) +{ + const int act = BLI_findindex(&scene->r.views, srv); + + if (act == -1) { + return false; + } + else if (scene->r.views.first == scene->r.views.last) { + /* ensure 1 view is kept */ + return false; + } + + BLI_remlink(&scene->r.views, srv); + MEM_freeN(srv); + + scene->r.actview = 0; + + return true; +} + /* render simplification */ int get_render_subsurf_level(const RenderData *r, int lvl) @@ -2062,3 +2126,281 @@ double BKE_scene_unit_scale(const UnitSettings *unit, const int unit_type, doubl return value; } } + +/******************** multiview *************************/ + +size_t BKE_scene_multiview_num_views_get(const RenderData *rd) +{ + SceneRenderView *srv; + size_t totviews = 0; + + if ((rd->scemode & R_MULTIVIEW) == 0) + return 1; + + if (rd->views_format == SCE_VIEWS_FORMAT_STEREO_3D) { + if (BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name))) { + totviews++; + } + + if (BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name))) { + totviews++; + } + } + else { + for (srv = rd->views.first; srv; srv = srv->next) { + if ((srv->viewflag & SCE_VIEW_DISABLE) == 0) { + totviews++; + } + } + } + return totviews; +} + +bool BKE_scene_multiview_is_stereo3d(const RenderData *rd) +{ + SceneRenderView *srv[2]; + + if ((rd->scemode & R_MULTIVIEW) == 0) + return false; + + srv[0] = (SceneRenderView *)BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name)); + srv[1] = (SceneRenderView *)BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name)); + + return (srv[0] && ((srv[0]->viewflag & SCE_VIEW_DISABLE) == 0) && + srv[1] && ((srv[1]->viewflag & SCE_VIEW_DISABLE) == 0)); +} + +/* return whether to render this SceneRenderView */ +bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const SceneRenderView *srv) +{ + if (srv == NULL) + return false; + + if ((rd->scemode & R_MULTIVIEW) == 0) + return false; + + if ((srv->viewflag & SCE_VIEW_DISABLE)) + return false; + + if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW) + return true; + + /* SCE_VIEWS_SETUP_BASIC */ + if (STREQ(srv->name, STEREO_LEFT_NAME) || + STREQ(srv->name, STEREO_RIGHT_NAME)) + { + return true; + } + + return false; +} + +/* return true if viewname is the first or if the name is NULL or not found */ +bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char *viewname) +{ + SceneRenderView *srv; + + if ((rd->scemode & R_MULTIVIEW) == 0) + return true; + + if ((!viewname) || (!viewname[0])) + return true; + + for (srv = rd->views.first; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(rd, srv)) { + return STREQ(viewname, srv->name); + } + } + + return true; +} + +/* return true if viewname is the last or if the name is NULL or not found */ +bool BKE_scene_multiview_is_render_view_last(const RenderData *rd, const char *viewname) +{ + SceneRenderView *srv; + + if ((rd->scemode & R_MULTIVIEW) == 0) + return true; + + if ((!viewname) || (!viewname[0])) + return true; + + for (srv = rd->views.last; srv; srv = srv->prev) { + if (BKE_scene_multiview_is_render_view_active(rd, srv)) { + return STREQ(viewname, srv->name); + } + } + + return true; +} + +SceneRenderView *BKE_scene_multiview_render_view_findindex(const RenderData *rd, const int view_id) +{ + SceneRenderView *srv; + size_t nr; + + if ((rd->scemode & R_MULTIVIEW) == 0) + return NULL; + + nr = 0; + for (srv = rd->views.first, nr = 0; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(rd, srv)) { + if (nr++ == view_id) + return srv; + } + } + return srv; +} + +const char *BKE_scene_multiview_render_view_name_get(const RenderData *rd, const int view_id) +{ + SceneRenderView *srv = BKE_scene_multiview_render_view_findindex(rd, view_id); + + if (srv) + return srv->name; + else + return ""; +} + +size_t BKE_scene_multiview_view_id_get(const RenderData *rd, const char *viewname) +{ + SceneRenderView *srv; + size_t nr; + + if ((!rd) || ((rd->scemode & R_MULTIVIEW) == 0)) + return 0; + + if ((!viewname) || (!viewname[0])) + return 0; + + nr = 0; + for (srv = rd->views.first, nr = 0; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(rd, srv)) { + if (STREQ(viewname, srv->name)) { + return nr; + } + else { + nr += 1; + } + } + } + + return 0; +} + +void BKE_scene_multiview_filepath_get( + SceneRenderView *srv, const char *filepath, + char *r_filepath) +{ + BLI_strncpy(r_filepath, filepath, FILE_MAX); + BLI_path_suffix(r_filepath, FILE_MAX, srv->suffix, ""); +} + +/** + * When multiview is not used the filepath is as usual (e.g., ``Image.jpg``). + * When multiview is on, even if only one view is enabled the view is incorporated + * into the file name (e.g., ``Image_L.jpg``). That allows for the user to re-render + * individual views. + */ +void BKE_scene_multiview_view_filepath_get( + const RenderData *rd, const char *filepath, const char *viewname, + char *r_filepath) +{ + SceneRenderView *srv; + char suffix[FILE_MAX]; + + srv = BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name)); + if (srv) + BLI_strncpy(suffix, srv->suffix, sizeof(suffix)); + else + BLI_strncpy(suffix, viewname, sizeof(suffix)); + + BLI_strncpy(r_filepath, filepath, FILE_MAX); + BLI_path_suffix(r_filepath, FILE_MAX, suffix, ""); +} + +const char *BKE_scene_multiview_view_suffix_get(const RenderData *rd, const char *viewname) +{ + SceneRenderView *srv; + + if ((viewname == NULL) || (viewname[0] == '\0')) + return viewname; + + srv = BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name)); + if (srv) + return srv->suffix; + else + return viewname; +} + +const char *BKE_scene_multiview_view_id_suffix_get(const RenderData *rd, const size_t view_id) +{ + if ((rd->scemode & R_MULTIVIEW) == 0) { + return ""; + } + else { + const char *viewname = BKE_scene_multiview_render_view_name_get(rd, view_id); + return BKE_scene_multiview_view_suffix_get(rd, viewname); + } +} + +void BKE_scene_multiview_view_prefix_get(Scene *scene, const char *name, char *rprefix, char **rext) +{ + SceneRenderView *srv; + size_t index_act; + char *suf_act; + const char delims[] = {'.', '\0'}; + + rprefix[0] = '\0'; + + /* begin of extension */ + index_act = BLI_str_rpartition(name, delims, rext, &suf_act); + BLI_assert(index_act > 0); + + for (srv = scene->r.views.first; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) { + size_t len = strlen(srv->suffix); + if (STREQLEN(*rext - len, srv->suffix, len)) { + BLI_strncpy(rprefix, name, strlen(name) - strlen(*rext) - len + 1); + break; + } + } + } +} + +void BKE_scene_multiview_videos_dimensions_get( + const RenderData *rd, const size_t width, const size_t height, + size_t *r_width, size_t *r_height) +{ + if ((rd->scemode & R_MULTIVIEW) && + rd->im_format.views_format == R_IMF_VIEWS_STEREO_3D) + { + IMB_stereo3d_write_dimensions( + rd->im_format.stereo3d_format.display_mode, + (rd->im_format.stereo3d_format.flag & S3D_SQUEEZED_FRAME) != 0, + width, height, + r_width, r_height); + } + else { + *r_width = width; + *r_height = height; + } +} + +size_t BKE_scene_multiview_num_videos_get(const RenderData *rd) +{ + if (BKE_imtype_is_movie(rd->im_format.imtype) == false) + return 0; + + if ((rd->scemode & R_MULTIVIEW) == 0) + return 1; + + if (rd->im_format.views_format == R_IMF_VIEWS_STEREO_3D) { + return 1; + } + else { + /* R_IMF_VIEWS_INDIVIDUAL */ + return BKE_scene_multiview_num_views_get(rd); + } +} diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c index 41f17665065..abfc858fd03 100644 --- a/source/blender/blenkernel/intern/seqcache.c +++ b/source/blender/blenkernel/intern/seqcache.c @@ -33,6 +33,7 @@ #include "MEM_guardedalloc.h" #include "DNA_sequence_types.h" +#include "DNA_scene_types.h" #include "IMB_moviecache.h" #include "IMB_imbuf.h" @@ -41,6 +42,7 @@ #include "BLI_listbase.h" #include "BKE_sequencer.h" +#include "BKE_scene.h" typedef struct SeqCacheKey { struct Sequence *seq; @@ -77,7 +79,9 @@ static bool seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b) (a->bmain != b->bmain) || (a->scene != b->scene) || (a->motion_blur_shutter != b->motion_blur_shutter) || - (a->motion_blur_samples != b->motion_blur_samples)); + (a->motion_blur_samples != b->motion_blur_samples) || + (a->scene->r.views_format != b->scene->r.views_format) || + (a->view_id != b->view_id)); } static unsigned int seq_hash_render_data(const SeqRenderData *a) @@ -89,6 +93,7 @@ static unsigned int seq_hash_render_data(const SeqRenderData *a) rval ^= ((intptr_t) a->scene) << 6; rval ^= (int)(a->motion_blur_shutter * 100.0f) << 10; rval ^= a->motion_blur_samples << 24; + rval ^= ((a->scene->r.views_format * 2) + a->view_id) << 32; return rval; } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 721555097d7..942426febdd 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -53,6 +53,12 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" +#ifdef WIN32 +# include "BLI_winstuff.h" +#else +# include +#endif + #include "BLF_translation.h" #include "BKE_animsys.h" @@ -89,6 +95,8 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seq static ImBuf *seq_render_strip(const SeqRenderData *context, Sequence *seq, float cfra); static void seq_free_animdata(Scene *scene, Sequence *seq); static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr, bool make_float); +static size_t seq_num_files(Scene *scene, char views_format, const bool is_multiview); +static void seq_anim_add_suffix(Scene *scene, struct anim *anim, const size_t view_id); /* **** XXX ******** */ #define SELECT 1 @@ -181,10 +189,7 @@ static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const bool do_cach if (seq->strip) seq_free_strip(seq->strip); - if (seq->anim) { - IMB_free_anim(seq->anim); - seq->anim = NULL; - } + BKE_sequence_free_anim(seq); if (seq->type & SEQ_TYPE_EFFECT) { struct SeqEffectHandle sh = BKE_sequence_get_effect(seq); @@ -196,6 +201,10 @@ static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const bool do_cach ((ID *)seq->sound)->us--; } + if (seq->stereo3d_format) { + MEM_freeN(seq->stereo3d_format); + } + /* clipboard has no scene and will never have a sound handle or be active * same goes to sequences copy for proxy rebuild job */ @@ -240,6 +249,22 @@ void BKE_sequence_free(Scene *scene, Sequence *seq) BKE_sequence_free_ex(scene, seq, true); } +/* Function to free imbuf and anim data on changes */ +void BKE_sequence_free_anim(Sequence *seq) +{ + while (seq->anims.last) { + StripAnim *sanim = seq->anims.last; + BLI_remlink(&seq->anims, sanim); + + if (sanim->anim) { + IMB_free_anim(sanim->anim); + sanim->anim = NULL; + } + + MEM_freeN(sanim); + } +} + /* cache must be freed before calling this function * since it leaves the seqbase in an invalid state */ static void seq_free_sequence_recurse(Scene *scene, Sequence *seq) @@ -537,6 +562,7 @@ void BKE_sequencer_new_render_data( r_context->motion_blur_shutter = 0; r_context->skip_cache = false; r_context->is_proxy_render = false; + r_context->view_id = 0; } /* ************************* iterator ************************** */ @@ -771,10 +797,17 @@ void BKE_sequence_calc(Scene *scene, Sequence *seq) } } +static void seq_multiview_name(Scene *scene, const size_t view_id, const char *prefix, + const char *ext, char *r_path, size_t r_size) +{ + const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id); + BLI_snprintf(r_path, r_size, "%s%s%s", prefix, suffix, ext); +} + /* note: caller should run BKE_sequence_calc(scene, seq) after */ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_range) { - char str[FILE_MAX]; + char path[FILE_MAX]; int prev_startdisp = 0, prev_enddisp = 0; /* note: don't rename the strip, will break animation curves */ @@ -807,22 +840,67 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r break; } case SEQ_TYPE_MOVIE: - BLI_join_dirfile(str, sizeof(str), seq->strip->dir, + { + StripAnim *sanim; + bool is_multiview_loaded = false; + const bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 && + (scene->r.scemode & R_MULTIVIEW) != 0; + + BLI_join_dirfile(path, sizeof(path), seq->strip->dir, seq->strip->stripdata->name); - BLI_path_abs(str, G.main->name); + BLI_path_abs(path, G.main->name); + + BKE_sequence_free_anim(seq); + + if (is_multiview && (seq->views_format == R_IMF_VIEWS_INDIVIDUAL)) { + char prefix[FILE_MAX]; + char *ext = NULL; + size_t totfiles = seq_num_files(scene, seq->views_format, true); + int i = 0; + + BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext); - if (seq->anim) IMB_free_anim(seq->anim); + if (prefix[0] != '\0') { + for (i = 0; i < totfiles; i++) { + struct anim *anim; + char str[FILE_MAX]; - seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), - seq->streamindex, seq->strip->colorspace_settings.name); + seq_multiview_name(scene, i, prefix, ext, str, FILE_MAX); + anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + seq_anim_add_suffix(scene, anim, i); - if (!seq->anim) { + if (anim) { + sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); + BLI_addtail(&seq->anims, sanim); + sanim->anim = anim; + } + } + is_multiview_loaded = true; + } + } + + if (is_multiview_loaded == false) { + struct anim *anim; + anim = openanim(path, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + if (anim) { + sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); + BLI_addtail(&seq->anims, sanim); + sanim->anim = anim; + } + } + + /* use the first video as reference for everything */ + sanim = seq->anims.first; + + if ((!sanim) || (!sanim->anim)) { return; } - seq->len = IMB_anim_get_duration(seq->anim, seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN); - - seq->anim_preseek = IMB_anim_get_preseek(seq->anim); + seq->len = IMB_anim_get_duration(sanim->anim, seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN); + + seq->anim_preseek = IMB_anim_get_preseek(sanim->anim); seq->len -= seq->anim_startofs; seq->len -= seq->anim_endofs; @@ -830,6 +908,7 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r seq->len = 0; } break; + } case SEQ_TYPE_MOVIECLIP: if (seq->clip == NULL) return; @@ -1297,6 +1376,7 @@ typedef struct SeqIndexBuildContext { int size_flags; int quality; bool overwrite; + size_t view_id; Main *bmain; Scene *scene; @@ -1336,44 +1416,59 @@ static double seq_rendersize_to_scale_factor(int size) return 0.25; } -static void seq_open_anim_file(Editing *ed, Sequence *seq, bool openfile) +/* the number of files will vary according to the stereo format */ +static size_t seq_num_files(Scene *scene, char views_format, const bool is_multiview) +{ + if (!is_multiview) { + return 1; + } + else if (views_format == R_IMF_VIEWS_STEREO_3D) { + return 1; + } + /* R_IMF_VIEWS_INDIVIDUAL */ + else { + return BKE_scene_multiview_num_views_get(&scene->r); + } +} + +static void seq_proxy_index_dir_set(struct anim *anim, const char *base_dir) +{ + char dir[FILE_MAX]; + char fname[FILE_MAXFILE]; + + IMB_anim_get_fname(anim, fname, FILE_MAXFILE); + BLI_strncpy(dir, base_dir, sizeof(dir)); + BLI_path_append(dir, sizeof(dir), fname); + IMB_anim_set_index_dir(anim, dir); +} + +static void seq_open_anim_file(Scene *scene, Sequence *seq, bool openfile) { + char dir[FILE_MAX]; char name[FILE_MAX]; StripProxy *proxy; + bool use_proxy; + bool is_multiview_loaded = false; + Editing *ed = scene->ed; + const bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 && (scene->r.scemode & R_MULTIVIEW) != 0; - if (seq->anim != NULL) { + if ((seq->anims.first != NULL) && (((StripAnim *)seq->anims.first)->anim != NULL)) { return; } + /* reset all the previously created anims */ + BKE_sequence_free_anim(seq); + BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name); BLI_path_abs(name, G.main->name); - - if (openfile) { - seq->anim = openanim(name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), - seq->streamindex, seq->strip->colorspace_settings.name); - } - else { - seq->anim = openanim_noload(name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), - seq->streamindex, seq->strip->colorspace_settings.name); - } - - if (seq->anim == NULL) { - return; - } proxy = seq->strip->proxy; - if (proxy == NULL) { - return; - } - - if ((proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) || - (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE)) - { - char dir[FILE_MAX]; - char fname[FILE_MAXFILE]; + use_proxy = proxy && ((proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) != 0 || + (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE)); + if (use_proxy) { if (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) { if (ed->proxy_dir[0] == 0) BLI_strncpy(dir, "//BL_proxy", sizeof(dir)); @@ -1383,21 +1478,93 @@ static void seq_open_anim_file(Editing *ed, Sequence *seq, bool openfile) else { BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); } + BLI_path_abs(dir, G.main->name); + } - IMB_anim_get_fname(seq->anim, fname, FILE_MAXFILE); - BLI_path_append(dir, sizeof(dir), fname); + if (is_multiview && seq->views_format == R_IMF_VIEWS_INDIVIDUAL) { + size_t totfiles = seq_num_files(scene, seq->views_format, true); + char prefix[FILE_MAX]; + char *ext = NULL; + int i; - BLI_path_abs(dir, G.main->name); + BKE_scene_multiview_view_prefix_get(scene, name, prefix, &ext); + + if (prefix[0] != '\0') { + for (i = 0; i < totfiles; i++) { + const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, i); + char str[FILE_MAX]; + StripAnim *sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); - IMB_anim_set_index_dir(seq->anim, dir); + BLI_addtail(&seq->anims, sanim); + + BLI_snprintf(str, sizeof(str), "%s%s%s", prefix, suffix, ext); + + if (openfile) { + sanim->anim = openanim( + str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + } + else { + sanim->anim = openanim_noload( + str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + } + + seq_anim_add_suffix(scene, sanim->anim, i); + + if (sanim->anim == NULL) { + if (openfile) { + sanim->anim = openanim( + name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + } + else { + sanim->anim = openanim_noload( + name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + } + + /* no individual view files - monoscopic, stereo 3d or exr multiview */ + totfiles = 1; + } + + if (sanim->anim && use_proxy) { + seq_proxy_index_dir_set(sanim->anim, dir); + } + } + is_multiview_loaded = true; + } } -} + if (is_multiview_loaded == false) { + StripAnim *sanim; + + sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); + BLI_addtail(&seq->anims, sanim); -static bool seq_proxy_get_fname(Editing *ed, Sequence *seq, int cfra, int render_size, char *name) + if (openfile) { + sanim->anim = openanim( + name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + } + else { + sanim->anim = openanim_noload( + name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); + } + + if (sanim->anim && use_proxy) { + seq_proxy_index_dir_set(sanim->anim, dir); + } + } +} + +static bool seq_proxy_get_fname(Editing *ed, Sequence *seq, int cfra, int render_size, char *name, const size_t view_id) { int frameno; char dir[PROXY_MAXFILE]; + StripAnim *sanim; + char suffix[24] = {'\0'}; StripProxy *proxy = seq->strip->proxy; if (!proxy) { @@ -1412,23 +1579,25 @@ static bool seq_proxy_get_fname(Editing *ed, Sequence *seq, int cfra, int render * have both, a directory full of jpeg files and proxy avis, so * sorry folks, please rebuild your proxies... */ - if (seq->anim && ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) { + sanim = BLI_findlink(&seq->anims, view_id); + + if (sanim && sanim->anim && ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) { char fname[FILE_MAXFILE]; if (ed->proxy_dir[0] == 0) BLI_strncpy(dir, "//BL_proxy", sizeof(dir)); else BLI_strncpy(dir, ed->proxy_dir, sizeof(dir)); - IMB_anim_get_fname(seq->anim, fname, FILE_MAXFILE); + IMB_anim_get_fname(sanim->anim, fname, FILE_MAXFILE); BLI_path_append(dir, sizeof(dir), fname); BLI_path_abs(name, G.main->name); } else if ((proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE)) { BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); } - else if (seq->anim && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR)) { + else if (sanim && sanim->anim && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR)) { char fname[FILE_MAXFILE]; BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); - IMB_anim_get_fname(seq->anim, fname, FILE_MAXFILE); + IMB_anim_get_fname(sanim->anim, fname, FILE_MAXFILE); BLI_path_append(dir, sizeof(dir), fname); } else if (seq->type == SEQ_TYPE_IMAGE) { @@ -1438,12 +1607,16 @@ static bool seq_proxy_get_fname(Editing *ed, Sequence *seq, int cfra, int render return false; } - if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE && seq->anim && + if (view_id > 0) + BLI_snprintf(suffix, sizeof(suffix), "_%zu", view_id); + + if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE && sanim && sanim->anim && ed->proxy_storage != SEQ_EDIT_PROXY_DIR_STORAGE) { BLI_join_dirfile(name, PROXY_MAXFILE, dir, proxy->file); BLI_path_abs(name, G.main->name); + BLI_snprintf(name, PROXY_MAXFILE, "%s_%s", name, suffix); return true; } @@ -1451,13 +1624,13 @@ static bool seq_proxy_get_fname(Editing *ed, Sequence *seq, int cfra, int render /* generate a separate proxy directory for each preview size */ if (seq->type == SEQ_TYPE_IMAGE) { - BLI_snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy", dir, render_size, - BKE_sequencer_give_stripelem(seq, cfra)->name); + BLI_snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy%s", dir, render_size, + BKE_sequencer_give_stripelem(seq, cfra)->name, suffix); frameno = 1; } else { frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs; - BLI_snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir, render_size); + BLI_snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####%s", dir, render_size, suffix); } BLI_path_abs(name, G.main->name); @@ -1476,6 +1649,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c int render_size = context->preview_render_size; StripProxy *proxy = seq->strip->proxy; Editing *ed = context->scene->ed; + StripAnim *sanim; if (!(seq->flag & SEQ_USE_PROXY)) { return NULL; @@ -1496,7 +1670,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) { int frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs; if (proxy->anim == NULL) { - if (seq_proxy_get_fname(ed, seq, cfra, render_size, name) == 0) { + if (seq_proxy_get_fname(ed, seq, cfra, render_size, name, context->view_id) == 0) { return NULL; } @@ -1506,14 +1680,15 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c return NULL; } - seq_open_anim_file(context->scene->ed, seq, true); + seq_open_anim_file(context->scene, seq, true); + sanim = seq->anims.first; - frameno = IMB_anim_index_get_frame_index(seq->anim, proxy->tc, frameno); + frameno = IMB_anim_index_get_frame_index(sanim ? sanim->anim : NULL, seq->strip->proxy->tc, frameno); return IMB_anim_absolute(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE); } - if (seq_proxy_get_fname(ed, seq, cfra, render_size, name) == 0) { + if (seq_proxy_get_fname(ed, seq, cfra, render_size, name, context->view_id) == 0) { return NULL; } @@ -1540,7 +1715,7 @@ static void seq_proxy_build_frame(const SeqRenderData *context, Sequence *seq, i ImBuf *ibuf_tmp, *ibuf; Editing *ed = context->scene->ed; - if (!seq_proxy_get_fname(ed, seq, cfra, proxy_render_size, name)) { + if (!seq_proxy_get_fname(ed, seq, cfra, proxy_render_size, name, context->view_id)) { return; } @@ -1581,44 +1756,130 @@ static void seq_proxy_build_frame(const SeqRenderData *context, Sequence *seq, i IMB_freeImBuf(ibuf); } -SeqIndexBuildContext *BKE_sequencer_proxy_rebuild_context(Main *bmain, Scene *scene, Sequence *seq, struct GSet *file_list) +/* returns whether the file this context would read from even exist, if not, don't create the context +*/ +static bool seq_proxy_multiview_context_invalid(Sequence *seq, Scene *scene, const size_t view_id) +{ + if ((scene->r.scemode & R_MULTIVIEW) == 0) + return false; + + if ((seq->type == SEQ_TYPE_IMAGE) && (seq->views_format == R_IMF_VIEWS_INDIVIDUAL)) { + static char prefix[FILE_MAX]; + static char *ext = NULL; + char str[FILE_MAX]; + + if (view_id == 0) { + char path[FILE_MAX]; + BLI_join_dirfile(path, sizeof(path), seq->strip->dir, + seq->strip->stripdata->name); + BLI_path_abs(path, G.main->name); + BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext); + } + + if (prefix[0] == '\0') + return view_id != 0; + + seq_multiview_name(scene, view_id, prefix, ext, str, FILE_MAX); + + if (BLI_access(str, R_OK) == 0) + return false; + else + return view_id != 0; + } + return false; +} + +/** This returns the maximum possible number of required contexts +*/ +static size_t seq_proxy_context_count(Sequence *seq, Scene *scene) +{ + size_t num_views = 1; + + if ((scene->r.scemode & R_MULTIVIEW) == 0) + return 1; + + switch (seq->type) { + case SEQ_TYPE_MOVIE: + { + num_views = BLI_listbase_count(&seq->anims); + break; + } + case SEQ_TYPE_IMAGE: + { + switch (seq->views_format) { + case R_IMF_VIEWS_INDIVIDUAL: + num_views = BKE_scene_multiview_num_views_get(&scene->r); + break; + case R_IMF_VIEWS_STEREO_3D: + num_views = 2; + break; + case R_IMF_VIEWS_MULTIVIEW: + /* not supported at the moment */ + /* pass through */ + default: + num_views = 1; + } + break; + } + } + + return num_views; +} + +void BKE_sequencer_proxy_rebuild_context(Main *bmain, Scene *scene, Sequence *seq, struct GSet *file_list, ListBase *queue) { SeqIndexBuildContext *context; Sequence *nseq; + LinkData *link; + size_t i; + size_t num_files; if (!seq->strip || !seq->strip->proxy) { - return NULL; + return; } if (!(seq->flag & SEQ_USE_PROXY)) { - return NULL; + return; } - context = MEM_callocN(sizeof(SeqIndexBuildContext), "seq proxy rebuild context"); + num_files = seq_proxy_context_count(seq, scene); + + for (i = 0; i < num_files; i++) { + if (seq_proxy_multiview_context_invalid(seq, scene, i)) + continue; + + context = MEM_callocN(sizeof(SeqIndexBuildContext), "seq proxy rebuild context"); + + nseq = BKE_sequence_dupli_recursive(scene, scene, seq, 0); - nseq = BKE_sequence_dupli_recursive(scene, scene, seq, 0); + context->tc_flags = nseq->strip->proxy->build_tc_flags; + context->size_flags = nseq->strip->proxy->build_size_flags; + context->quality = nseq->strip->proxy->quality; + context->overwrite = (nseq->strip->proxy->build_flags & SEQ_PROXY_SKIP_EXISTING) == 0; - context->tc_flags = nseq->strip->proxy->build_tc_flags; - context->size_flags = nseq->strip->proxy->build_size_flags; - context->quality = nseq->strip->proxy->quality; - context->overwrite = (nseq->strip->proxy->build_flags & SEQ_PROXY_SKIP_EXISTING) == 0; + context->bmain = bmain; + context->scene = scene; + context->orig_seq = seq; + context->seq = nseq; - context->bmain = bmain; - context->scene = scene; - context->orig_seq = seq; - context->seq = nseq; + context->view_id = i; /* only for images */ - if (nseq->type == SEQ_TYPE_MOVIE) { - seq_open_anim_file(scene->ed, nseq, true); + link = BLI_genericNodeN(context); + BLI_addtail(queue, link); - if (nseq->anim) { - context->index_context = IMB_anim_index_rebuild_context(nseq->anim, - context->tc_flags, context->size_flags, context->quality, - context->overwrite, file_list); + if (nseq->type == SEQ_TYPE_MOVIE) { + StripAnim *sanim; + + seq_open_anim_file(scene, nseq, true); + sanim = BLI_findlink(&nseq->anims, i); + + if (sanim->anim) { + context->index_context = IMB_anim_index_rebuild_context(sanim->anim, + context->tc_flags, context->size_flags, context->quality, + context->overwrite, file_list); + } } } - - return context; } void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, short *do_update, float *progress) @@ -1657,6 +1918,7 @@ void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, sho render_context.skip_cache = true; render_context.is_proxy_render = true; + render_context.view_id = context->view_id; for (cfra = seq->startdisp + seq->startstill; cfra < seq->enddisp - seq->endstill; cfra++) { if (context->size_flags & IMB_PROXY_25) { @@ -1683,8 +1945,14 @@ void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, sho void BKE_sequencer_proxy_rebuild_finish(SeqIndexBuildContext *context, bool stop) { if (context->index_context) { - IMB_close_anim_proxies(context->seq->anim); - IMB_close_anim_proxies(context->orig_seq->anim); + StripAnim *sanim; + + for (sanim = context->seq->anims.first; sanim; sanim = sanim->next) + IMB_close_anim_proxies(sanim->anim); + + for (sanim = context->orig_seq->anims.first; sanim; sanim = sanim->next) + IMB_close_anim_proxies(sanim->anim); + IMB_anim_index_rebuild_finish(context->index_context, stop); } @@ -2429,6 +2697,234 @@ static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context, Sequenc return out; } +static ImBuf *seq_render_image_strip(const SeqRenderData *context, Sequence *seq, float nr, float cfra) +{ + ImBuf *ibuf = NULL; + char name[FILE_MAX]; + bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 && + (context->scene->r.scemode & R_MULTIVIEW) != 0; + StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra); + int flag; + + if (s_elem) { + BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name); + BLI_path_abs(name, G.main->name); + } + + flag = IB_rect; + if (seq->alpha_mode == SEQ_ALPHA_PREMUL) + flag |= IB_alphamode_premul; + + if (!s_elem) { + /* don't do anything */ + } + else if (is_multiview) { + size_t totfiles = seq_num_files(context->scene, seq->views_format, true); + size_t totviews; + struct ImBuf **ibufs_arr; + char prefix[FILE_MAX]; + char *ext = NULL; + int i; + + if (totfiles > 1) { + BKE_scene_multiview_view_prefix_get(context->scene, name, prefix, &ext); + if (prefix[0] == '\0') { + goto monoview_image; + } + } + + totviews = BKE_scene_multiview_num_views_get(&context->scene->r); + ibufs_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Sequence Image Views Imbufs"); + + for (i = 0; i < totfiles; i++) { + + if (prefix[0] == '\0') { + ibufs_arr[i] = IMB_loadiffname(name, flag, seq->strip->colorspace_settings.name); + } + else { + char str[FILE_MAX]; + seq_multiview_name(context->scene, i, prefix, ext, str, FILE_MAX); + ibufs_arr[i] = IMB_loadiffname(str, flag, seq->strip->colorspace_settings.name); + } + + if (ibufs_arr[i]) { + /* we don't need both (speed reasons)! */ + if (ibufs_arr[i]->rect_float && ibufs_arr[i]->rect) + imb_freerectImBuf(ibufs_arr[i]); + } + } + + if (seq->views_format == R_IMF_VIEWS_STEREO_3D && ibufs_arr[0]) + IMB_ImBufFromStereo3d(seq->stereo3d_format, ibufs_arr[0], &ibufs_arr[0], &ibufs_arr[1]); + + for (i = 0; i < totviews; i++) { + if (ibufs_arr[i]) { + SeqRenderData localcontext = *context; + localcontext.view_id = i; + + /* all sequencer color is done in SRGB space, linear gives odd crossfades */ + BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibufs_arr[i], false); + + if (i != context->view_id) { + copy_to_ibuf_still(&localcontext, seq, nr, ibufs_arr[i]); + BKE_sequencer_cache_put(&localcontext, seq, cfra, SEQ_STRIPELEM_IBUF, ibufs_arr[i]); + } + } + } + + /* return the original requested ImBuf */ + ibuf = ibufs_arr[context->view_id]; + if (ibuf) { + s_elem->orig_width = ibufs_arr[0]->x; + s_elem->orig_height = ibufs_arr[0]->y; + } + + /* "remove" the others (decrease their refcount) */ + for (i = 0; i < totviews; i++) { + if (ibufs_arr[i] != ibuf) { + IMB_freeImBuf(ibufs_arr[i]); + } + } + + MEM_freeN(ibufs_arr); + } + else { +monoview_image: + if ((ibuf = IMB_loadiffname(name, flag, seq->strip->colorspace_settings.name))) { + /* we don't need both (speed reasons)! */ + if (ibuf->rect_float && ibuf->rect) + imb_freerectImBuf(ibuf); + + /* all sequencer color is done in SRGB space, linear gives odd crossfades */ + BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false); + + s_elem->orig_width = ibuf->x; + s_elem->orig_height = ibuf->y; + } + } + + return ibuf; +} + +static ImBuf *seq_render_movie_strip(const SeqRenderData *context, Sequence *seq, float nr, float cfra) +{ + ImBuf *ibuf = NULL; + StripAnim *sanim; + bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 && + (context->scene->r.scemode & R_MULTIVIEW) != 0; + + /* load all the videos */ + seq_open_anim_file(context->scene, seq, false); + + if (is_multiview) { + ImBuf **ibuf_arr; + size_t totviews; + size_t totfiles = seq_num_files(context->scene, seq->views_format, true); + int i; + + if (totfiles != BLI_listbase_count_ex(&seq->anims, totfiles + 1)) + goto monoview_movie; + + totviews = BKE_scene_multiview_num_views_get(&context->scene->r); + ibuf_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Sequence Image Views Imbufs"); + + for (i = 0, sanim = seq->anims.first; sanim; sanim = sanim->next, i++) { + if (sanim->anim) { + IMB_Proxy_Size proxy_size = seq_rendersize_to_proxysize(context->preview_render_size); + IMB_anim_set_preseek(sanim->anim, seq->anim_preseek); + + ibuf_arr[i] = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs, + seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, + proxy_size); + + /* fetching for requested proxy size failed, try fetching the original instead */ + if (!ibuf_arr[i] && proxy_size != IMB_PROXY_NONE) { + ibuf_arr[i] = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs, + seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, + IMB_PROXY_NONE); + } + if (ibuf_arr[i]) { + /* we don't need both (speed reasons)! */ + if (ibuf_arr[i]->rect_float && ibuf_arr[i]->rect) + imb_freerectImBuf(ibuf_arr[i]); + } + } + } + + if (seq->views_format == R_IMF_VIEWS_STEREO_3D) { + if (ibuf_arr[0]) { + IMB_ImBufFromStereo3d(seq->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]); + } + else { + /* probably proxy hasn't been created yet */ + MEM_freeN(ibuf_arr); + return NULL; + } + } + + for (i = 0; i < totviews; i++) { + SeqRenderData localcontext = *context; + localcontext.view_id = i; + + if (ibuf_arr[i]) { + /* all sequencer color is done in SRGB space, linear gives odd crossfades */ + BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf_arr[i], false); + } + if (i != context->view_id) { + copy_to_ibuf_still(&localcontext, seq, nr, ibuf_arr[i]); + BKE_sequencer_cache_put(&localcontext, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf_arr[i]); + } + } + + /* return the original requested ImBuf */ + ibuf = ibuf_arr[context->view_id]; + if (ibuf) { + seq->strip->stripdata->orig_width = ibuf->x; + seq->strip->stripdata->orig_height = ibuf->y; + } + + /* "remove" the others (decrease their refcount) */ + for (i = 0; i < totviews; i++) { + if (ibuf_arr[i] != ibuf) { + IMB_freeImBuf(ibuf_arr[i]); + } + } + + MEM_freeN(ibuf_arr); + } + else { +monoview_movie: + sanim = seq->anims.first; + if (sanim && sanim->anim) { + IMB_Proxy_Size proxy_size = seq_rendersize_to_proxysize(context->preview_render_size); + IMB_anim_set_preseek(sanim->anim, seq->anim_preseek); + + ibuf = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs, + seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, + proxy_size); + + /* fetching for requested proxy size failed, try fetching the original instead */ + if (!ibuf && proxy_size != IMB_PROXY_NONE) { + ibuf = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs, + seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, + IMB_PROXY_NONE); + } + if (ibuf) { + BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false); + + /* we don't need both (speed reasons)! */ + if (ibuf->rect_float && ibuf->rect) { + imb_freerectImBuf(ibuf); + } + + seq->strip->stripdata->orig_width = ibuf->x; + seq->strip->stripdata->orig_height = ibuf->y; + } + } + } + return ibuf; +} + static ImBuf *seq_render_movieclip_strip(const SeqRenderData *context, Sequence *seq, float nr) { ImBuf *ibuf = NULL; @@ -2560,7 +3056,7 @@ static ImBuf *seq_render_mask_strip(const SeqRenderData *context, Sequence *seq, return seq_render_mask(context, seq->mask, nr, make_float); } -static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq, float nr) +static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq, float nr, float cfra) { ImBuf *ibuf = NULL; float frame; @@ -2658,6 +3154,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq char err_out[256] = "unknown"; int width = (scene->r.xsch * scene->r.size) / 100; int height = (scene->r.ysch * scene->r.size) / 100; + const char *viewname = BKE_scene_multiview_render_view_name_get(&scene->r, context->view_id); /* for old scened this can be uninitialized, * should probably be added to do_versions at some point if the functionality stays */ @@ -2669,14 +3166,18 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq ibuf = sequencer_view3d_cb(scene, camera, width, height, IB_rect, context->scene->r.seq_prev_type, (context->scene->r.seq_flag & R_SEQ_SOLID_TEX) != 0, - use_gpencil, true, scene->r.alphamode, err_out); + use_gpencil, true, scene->r.alphamode, viewname, err_out); if (ibuf == NULL) { fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out); } } else { Render *re = RE_GetRender(scene->id.name); - RenderResult rres; + size_t totviews = BKE_scene_multiview_num_views_get(&scene->r); + int i; + ImBuf **ibufs_arr; + + ibufs_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Sequence Image Views Imbufs"); /* XXX: this if can be removed when sequence preview rendering uses the job system * @@ -2696,27 +3197,51 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq /* restore previous state after it was toggled on & off by RE_BlenderFrame */ G.is_rendering = is_rendering; } - - RE_AcquireResultImage(re, &rres); - - if (rres.rectf) { - ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat); - memcpy(ibuf->rect_float, rres.rectf, 4 * sizeof(float) * rres.rectx * rres.recty); - if (rres.rectz) { - addzbuffloatImBuf(ibuf); - memcpy(ibuf->zbuf_float, rres.rectz, sizeof(float) * rres.rectx * rres.recty); + + for (i = 0; i < totviews; i++) { + SeqRenderData localcontext = *context; + RenderResult rres; + + localcontext.view_id = i; + + RE_AcquireResultImage(re, &rres, i); + + if (rres.rectf) { + ibufs_arr[i] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat); + memcpy(ibufs_arr[i]->rect_float, rres.rectf, 4 * sizeof(float) * rres.rectx * rres.recty); + + if (rres.rectz) { + addzbuffloatImBuf(ibufs_arr[i]); + memcpy(ibufs_arr[i]->zbuf_float, rres.rectz, sizeof(float) * rres.rectx * rres.recty); + } + + /* float buffers in the sequencer are not linear */ + BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibufs_arr[i], false); + } + else if (rres.rect32) { + ibufs_arr[i] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect); + memcpy(ibufs_arr[i]->rect, rres.rect32, 4 * rres.rectx * rres.recty); } - /* float buffers in the sequencer are not linear */ - BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false); + if (i != context->view_id) { + copy_to_ibuf_still(&localcontext, seq, nr, ibufs_arr[i]); + BKE_sequencer_cache_put(&localcontext, seq, cfra, SEQ_STRIPELEM_IBUF, ibufs_arr[i]); + } + + RE_ReleaseResultImage(re); } - else if (rres.rect32) { - ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect); - memcpy(ibuf->rect, rres.rect32, 4 * rres.rectx * rres.recty); + + /* return the original requested ImBuf */ + ibuf = ibufs_arr[context->view_id]; + + /* "remove" the others (decrease their refcount) */ + for (i = 0; i < totviews; i++) { + if (ibufs_arr[i] != ibuf) { + IMB_freeImBuf(ibufs_arr[i]); + } } - - RE_ReleaseResultImage(re); - + MEM_freeN(ibufs_arr); + // BIF_end_render_callbacks(); } @@ -2743,7 +3268,6 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *s float nr = give_stripelem_index(seq, cfra); int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type; bool use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra); - char name[FILE_MAX]; switch (type) { case SEQ_TYPE_META: @@ -2802,64 +3326,14 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *s case SEQ_TYPE_IMAGE: { - StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra); - int flag; - - if (s_elem) { - BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name); - BLI_path_abs(name, G.main->name); - } - - flag = IB_rect; - if (seq->alpha_mode == SEQ_ALPHA_PREMUL) - flag |= IB_alphamode_premul; - - if (s_elem && (ibuf = IMB_loadiffname(name, flag, seq->strip->colorspace_settings.name))) { - /* we don't need both (speed reasons)! */ - if (ibuf->rect_float && ibuf->rect) - imb_freerectImBuf(ibuf); - - /* all sequencer color is done in SRGB space, linear gives odd crossfades */ - BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false); - - copy_to_ibuf_still(context, seq, nr, ibuf); - - s_elem->orig_width = ibuf->x; - s_elem->orig_height = ibuf->y; - } + ibuf = seq_render_image_strip(context, seq, nr, cfra); + copy_to_ibuf_still(context, seq, nr, ibuf); break; } case SEQ_TYPE_MOVIE: { - seq_open_anim_file(context->scene->ed, seq, false); - - if (seq->anim) { - IMB_Proxy_Size proxy_size = seq_rendersize_to_proxysize(context->preview_render_size); - IMB_anim_set_preseek(seq->anim, seq->anim_preseek); - - ibuf = IMB_anim_absolute(seq->anim, nr + seq->anim_startofs, - seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, - proxy_size); - - /* fetching for requested proxy size failed, try fetching the original instead */ - if (!ibuf && proxy_size != IMB_PROXY_NONE) { - ibuf = IMB_anim_absolute(seq->anim, nr + seq->anim_startofs, - seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, - IMB_PROXY_NONE); - } - if (ibuf) { - BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false); - - /* we don't need both (speed reasons)! */ - if (ibuf->rect_float && ibuf->rect) { - imb_freerectImBuf(ibuf); - } - - seq->strip->stripdata->orig_width = ibuf->x; - seq->strip->stripdata->orig_height = ibuf->y; - } - } + ibuf = seq_render_movie_strip(context, seq, nr, cfra); copy_to_ibuf_still(context, seq, nr, ibuf); break; } @@ -2867,7 +3341,7 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *s case SEQ_TYPE_SCENE: { /* scene can be NULL after deletions */ - ibuf = seq_render_scene_strip(context, seq, nr); + ibuf = seq_render_scene_strip(context, seq, nr, cfra); /* Scene strips update all animation, so we need to restore original state.*/ BKE_animsys_evaluate_all_animation(context->bmain, context->scene, cfra); @@ -3364,16 +3838,6 @@ ImBuf *BKE_sequencer_give_ibuf_threaded(const SeqRenderData *context, float cfra return e ? e->ibuf : NULL; } -/* Functions to free imbuf and anim data on changes */ - -static void free_anim_seq(Sequence *seq) -{ - if (seq->anim) { - IMB_free_anim(seq->anim); - seq->anim = NULL; - } -} - /* check whether sequence cur depends on seq */ bool BKE_sequence_check_depend(Sequence *seq, Sequence *cur) { @@ -3425,15 +3889,11 @@ static void sequence_invalidate_cache(Scene *scene, Sequence *seq, bool invalida /* invalidate cache for current sequence */ if (invalidate_self) { - if (seq->anim) { - /* Animation structure holds some buffers inside, - * so for proper cache invalidation we need to - * re-open the animation. - */ - IMB_free_anim(seq->anim); - seq->anim = NULL; - } - + /* Animation structure holds some buffers inside, + * so for proper cache invalidation we need to + * re-open the animation. + */ + BKE_sequence_free_anim(seq); BKE_sequencer_cache_cleanup_sequence(seq); } @@ -3480,7 +3940,7 @@ void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, bool for_render) if (seq->strip) { if (seq->type == SEQ_TYPE_MOVIE) { - free_anim_seq(seq); + BKE_sequence_free_anim(seq); } if (seq->type == SEQ_TYPE_SPEED) { BKE_sequence_effect_speed_rebuild_map(scene, seq, true); @@ -3527,7 +3987,7 @@ static bool update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *cha if (free_imbuf) { if (ibuf_change) { if (seq->type == SEQ_TYPE_MOVIE) - free_anim_seq(seq); + BKE_sequence_free_anim(seq); if (seq->type == SEQ_TYPE_SPEED) { BKE_sequence_effect_speed_rebuild_map(scene, seq, true); } @@ -4415,6 +4875,8 @@ Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine) seq->pitch = 1.0f; seq->scene_sound = NULL; + seq->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Sequence Stereo Format"); + return seq; } @@ -4472,6 +4934,12 @@ Sequence *BKE_sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoad strip->stripdata = MEM_callocN(seq->len * sizeof(StripElem), "stripelem"); BLI_strncpy(strip->dir, seq_load->path, sizeof(strip->dir)); + if (seq_load->stereo3d_format) + *seq->stereo3d_format = *seq_load->stereo3d_format; + + seq->views_format = seq_load->views_format; + seq->flag |= seq_load->flag & SEQ_USE_VIEWS; + seq_load_apply(scene, seq, seq_load); return seq; @@ -4551,6 +5019,12 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad } #endif // WITH_AUDASPACE +static void seq_anim_add_suffix(Scene *scene, struct anim *anim, const size_t view_id) +{ + const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id); + IMB_suffix_anim(anim, suffix); +} + Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) { Scene *scene = CTX_data_scene(C); /* only for sound */ @@ -4560,29 +5034,84 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad Strip *strip; StripElem *se; char colorspace[64] = "\0"; /* MAX_COLORSPACE_NAME */ - - struct anim *an; + bool is_multiview_loaded = false; + const bool is_multiview = (seq_load->flag & SEQ_USE_VIEWS) != 0; + size_t totfiles = seq_num_files(scene, seq_load->views_format, is_multiview); + struct anim **anim_arr; + int i; BLI_strncpy(path, seq_load->path, sizeof(path)); BLI_path_abs(path, G.main->name); - an = openanim(path, IB_rect, 0, colorspace); + anim_arr = MEM_callocN(sizeof(struct anim *) * totfiles, "Video files"); - if (an == NULL) - return NULL; + if (is_multiview && (seq_load->views_format == R_IMF_VIEWS_INDIVIDUAL)) { + char prefix[FILE_MAX]; + char *ext = NULL; + size_t j = 0; + + BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext); + + if (prefix[0] != '\0') { + for (i = 0; i < totfiles; i++) { + char str[FILE_MAX]; + + seq_multiview_name(scene, i, prefix, ext, str, FILE_MAX); + anim_arr[j] = openanim(str, IB_rect, 0, colorspace); + seq_anim_add_suffix(scene, anim_arr[j], i); + + if (anim_arr[j]) { + j++; + } + } + + if (j == 0) { + MEM_freeN(anim_arr); + return NULL; + } + is_multiview_loaded = true; + } + } + + if (is_multiview_loaded == false) { + anim_arr[0] = openanim(path, IB_rect, 0, colorspace); + + if (anim_arr[0] == NULL) { + MEM_freeN(anim_arr); + return NULL; + } + } seq = BKE_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel); + + /* multiview settings */ + if (seq_load->stereo3d_format) { + *seq->stereo3d_format = *seq_load->stereo3d_format; + seq->views_format = seq_load->views_format; + } + seq->flag |= seq_load->flag & SEQ_USE_VIEWS; + seq->type = SEQ_TYPE_MOVIE; seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */ - seq->anim = an; - seq->anim_preseek = IMB_anim_get_preseek(an); + for (i = 0; i < totfiles; i++) { + if (anim_arr[i]) { + StripAnim *sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); + BLI_addtail(&seq->anims, sanim); + sanim->anim = anim_arr[i]; + } + else { + break; + } + } + + seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]); BLI_strncpy(seq->name + 2, "Movie", SEQ_NAME_MAXSTR - 2); BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); /* basic defaults */ seq->strip = strip = MEM_callocN(sizeof(Strip), "strip"); - seq->len = IMB_anim_get_duration(an, IMB_TC_RECORD_RUN); + seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN); strip->us = 1; BLI_strncpy(seq->strip->colorspace_settings.name, colorspace, sizeof(seq->strip->colorspace_settings.name)); @@ -4610,6 +5139,7 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad /* can be NULL */ seq_load_apply(scene, seq, seq_load); + MEM_freeN(anim_arr); return seq; } @@ -4621,6 +5151,8 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup seq->tmp = seqn; seqn->strip = MEM_dupallocN(seq->strip); + seqn->stereo3d_format = MEM_dupallocN(seq->stereo3d_format); + /* XXX: add F-Curve duplication stuff? */ if (seq->strip->crop) { @@ -4667,7 +5199,7 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup else if (seq->type == SEQ_TYPE_MOVIE) { seqn->strip->stripdata = MEM_dupallocN(seq->strip->stripdata); - seqn->anim = NULL; + BLI_listbase_clear(&seqn->anims); } else if (seq->type == SEQ_TYPE_SOUND_RAM) { seqn->strip->stripdata = diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index a86ffacfdbd..cec455e01b9 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -50,26 +50,34 @@ /* ********************** general blender movie support ***************************** */ -static int start_stub(Scene *UNUSED(scene), RenderData *UNUSED(rd), int UNUSED(rectx), int UNUSED(recty), - ReportList *UNUSED(reports), bool UNUSED(preview)) +static int start_stub(void *UNUSED(context_v), Scene *UNUSED(scene), RenderData *UNUSED(rd), int UNUSED(rectx), int UNUSED(recty), + ReportList *UNUSED(reports), bool UNUSED(preview), const char *UNUSED(suffix)) { return 0; } -static void end_stub(void) +static void end_stub(void *UNUSED(context_v)) {} -static int append_stub(RenderData *UNUSED(rd), int UNUSED(start_frame), int UNUSED(frame), int *UNUSED(pixels), - int UNUSED(rectx), int UNUSED(recty), ReportList *UNUSED(reports)) +static int append_stub(void *UNUSED(context_v), RenderData *UNUSED(rd), int UNUSED(start_frame), int UNUSED(frame), int *UNUSED(pixels), + int UNUSED(rectx), int UNUSED(recty), const char *UNUSED(suffix), ReportList *UNUSED(reports)) { return 0; } +static void *context_create_stub(void) +{ return NULL; } + +static void context_free_stub(void *UNUSED(context_v)) +{} + #ifdef WITH_AVI # include "AVI_avi.h" /* callbacks */ -static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview); -static void end_avi(void); -static int append_avi(RenderData *rd, int start_frame, int frame, int *pixels, - int rectx, int recty, ReportList *reports); -static void filepath_avi(char *string, RenderData *rd, bool preview); +static int start_avi(void *context_v, Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview, const char *suffix); +static void end_avi(void *context_v); +static int append_avi(void *context_v, RenderData *rd, int start_frame, int frame, int *pixels, + int rectx, int recty, const char *suffix, ReportList *reports); +static void filepath_avi(char *string, RenderData *rd, bool preview, const char *suffix); +static void *context_create_avi(void); +static void context_free_avi(void *context_v); #endif /* WITH_AVI */ #ifdef WITH_QUICKTIME @@ -93,13 +101,17 @@ bMovieHandle *BKE_movie_handle_get(const char imtype) mh.end_movie = end_stub; mh.get_next_frame = NULL; mh.get_movie_path = NULL; - + mh.context_create = context_create_stub; + mh.context_free = context_free_stub; + /* set the default handle, as builtin */ #ifdef WITH_AVI mh.start_movie = start_avi; mh.append_movie = append_avi; mh.end_movie = end_avi; mh.get_movie_path = filepath_avi; + mh.context_create = context_create_avi; + mh.context_free = context_free_avi; #endif /* do the platform specific handles */ @@ -109,6 +121,8 @@ bMovieHandle *BKE_movie_handle_get(const char imtype) mh.append_movie = append_qt; mh.end_movie = end_qt; mh.get_movie_path = filepath_qt; + mh.context_create = context_create_qt; + mh.context_free = context_free_qt; } #endif #ifdef WITH_FFMPEG @@ -117,6 +131,8 @@ bMovieHandle *BKE_movie_handle_get(const char imtype) mh.append_movie = BKE_ffmpeg_append; mh.end_movie = BKE_ffmpeg_end; mh.get_movie_path = BKE_ffmpeg_filepath_get; + mh.context_create = BKE_ffmpeg_context_create; + mh.context_free = BKE_ffmpeg_context_free; } #endif #ifdef WITH_FRAMESERVER @@ -125,6 +141,8 @@ bMovieHandle *BKE_movie_handle_get(const char imtype) mh.append_movie = BKE_frameserver_append; mh.end_movie = BKE_frameserver_end; mh.get_next_frame = BKE_frameserver_loop; + mh.context_create = BKE_frameserver_context_create; + mh.context_free = BKE_frameserver_context_free; } #endif @@ -137,9 +155,7 @@ bMovieHandle *BKE_movie_handle_get(const char imtype) #ifdef WITH_AVI -static AviMovie *avi = NULL; - -static void filepath_avi(char *string, RenderData *rd, bool preview) +static void filepath_avi(char *string, RenderData *rd, bool preview, const char *suffix) { int sfra, efra; @@ -170,27 +186,27 @@ static void filepath_avi(char *string, RenderData *rd, bool preview) BLI_path_frame_range(string, sfra, efra, 4); } } + + BLI_path_suffix(string, FILE_MAX, suffix, ""); } -static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview) +static int start_avi(void *context_v, Scene *UNUSED(scene), RenderData *rd, int rectx, int recty, + ReportList *reports, bool preview, const char *suffix) { int x, y; char name[256]; AviFormat format; int quality; double framerate; - - (void)scene; /* unused */ - - filepath_avi(name, rd, preview); + AviMovie *avi = context_v; + + filepath_avi(name, rd, preview, suffix); x = rectx; y = recty; quality = rd->im_format.quality; framerate = (double) rd->frs_sec / (double) rd->frs_sec_base; - - avi = MEM_mallocN(sizeof(AviMovie), "avimovie"); if (rd->im_format.imtype != R_IMF_IMTYPE_AVIJPEG) format = AVI_FORMAT_AVI_RGB; else format = AVI_FORMAT_MJPEG; @@ -216,12 +232,13 @@ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportL return 1; } -static int append_avi(RenderData *UNUSED(rd), int start_frame, int frame, int *pixels, - int rectx, int recty, ReportList *UNUSED(reports)) +static int append_avi(void *context_v, RenderData *UNUSED(rd), int start_frame, int frame, int *pixels, + int rectx, int recty, const char *UNUSED(suffix), ReportList *UNUSED(reports)) { unsigned int *rt1, *rt2, *rectot; int x, y; char *cp, rt; + AviMovie *avi = context_v; if (avi == NULL) return 0; @@ -252,22 +269,37 @@ static int append_avi(RenderData *UNUSED(rd), int start_frame, int frame, int *p return 1; } -static void end_avi(void) +static void end_avi(void *context_v) { + AviMovie *avi = context_v; + if (avi == NULL) return; AVI_close_compress(avi); - MEM_freeN(avi); - avi = NULL; } + +static void *context_create_avi(void) +{ + AviMovie *avi = MEM_mallocN(sizeof(AviMovie), "avimovie"); + return avi; +} + +static void context_free_avi(void *context_v) +{ + AviMovie *avi = context_v; + if (avi) { + MEM_freeN(avi); + } +} + #endif /* WITH_AVI */ /* similar to BKE_image_path_from_imformat() */ -void BKE_movie_filepath_get(char *string, RenderData *rd, bool preview) +void BKE_movie_filepath_get(char *string, RenderData *rd, bool preview, const char *suffix) { bMovieHandle *mh = BKE_movie_handle_get(rd->im_format.imtype); if (mh->get_movie_path) - mh->get_movie_path(string, rd, preview); + mh->get_movie_path(string, rd, preview, suffix); else string[0] = '\0'; } diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 0717369cde8..af71f19c226 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -61,36 +61,38 @@ #include "ffmpeg_compat.h" -static int ffmpeg_type = 0; -static int ffmpeg_codec = AV_CODEC_ID_MPEG4; -static int ffmpeg_audio_codec = AV_CODEC_ID_NONE; -static int ffmpeg_video_bitrate = 1150; -static int ffmpeg_audio_bitrate = 128; -static int ffmpeg_gop_size = 12; -static int ffmpeg_autosplit = 0; -static int ffmpeg_autosplit_count = 0; -static bool ffmpeg_preview = false; - -static AVFormatContext *outfile = 0; -static AVStream *video_stream = 0; -static AVStream *audio_stream = 0; -static AVFrame *current_frame = 0; -static struct SwsContext *img_convert_ctx = 0; - -static uint8_t *audio_input_buffer = 0; -static uint8_t *audio_deinterleave_buffer = 0; -static int audio_input_samples = 0; +typedef struct FFMpegContext { + int ffmpeg_type; + int ffmpeg_codec; + int ffmpeg_audio_codec; + int ffmpeg_video_bitrate; + int ffmpeg_audio_bitrate; + int ffmpeg_gop_size; + int ffmpeg_autosplit; + int ffmpeg_autosplit_count; + bool ffmpeg_preview; + + AVFormatContext *outfile; + AVStream *video_stream; + AVStream *audio_stream; + AVFrame *current_frame; + struct SwsContext *img_convert_ctx; + + uint8_t *audio_input_buffer; + uint8_t *audio_deinterleave_buffer; + int audio_input_samples; #ifndef FFMPEG_HAVE_ENCODE_AUDIO2 -static uint8_t *audio_output_buffer = 0; -static int audio_outbuf_size = 0; + uint8_t *audio_output_buffer; + int audio_outbuf_size; #endif -static double audio_time = 0.0f; -static bool audio_deinterleave = false; -static int audio_sample_size = 0; + double audio_time; + bool audio_deinterleave; + int audio_sample_size; #ifdef WITH_AUDASPACE -static AUD_Device *audio_mixdown_device = 0; + AUD_Device *audio_mixdown_device; #endif +} FFMpegContext; #define FFMPEG_AUTOSPLIT_SIZE 2000000000 @@ -99,6 +101,7 @@ static AUD_Device *audio_mixdown_device = 0; static void ffmpeg_dict_set_int(AVDictionary **dict, const char *key, int value); static void ffmpeg_dict_set_float(AVDictionary **dict, const char *key, float value); static void ffmpeg_set_expert_options(RenderData *rd); +static void ffmpeg_filepath_get(FFMpegContext *context, char *string, struct RenderData *rd, bool preview, const char *suffix); /* Delete a picture buffer */ @@ -117,50 +120,50 @@ static int request_float_audio_buffer(int codec_id) } #ifdef WITH_AUDASPACE -static int write_audio_frame(void) +static int write_audio_frame(FFMpegContext *context) { AVCodecContext *c = NULL; AVPacket pkt; AVFrame *frame = NULL; int got_output = 0; - c = audio_stream->codec; + c = context->audio_stream->codec; av_init_packet(&pkt); pkt.size = 0; pkt.data = NULL; - AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_samples); - audio_time += (double) audio_input_samples / (double) c->sample_rate; + AUD_readDevice(context->audio_mixdown_device, context->audio_input_buffer, context->audio_input_samples); + context->audio_time += (double) context->audio_input_samples / (double) c->sample_rate; #ifdef FFMPEG_HAVE_ENCODE_AUDIO2 frame = avcodec_alloc_frame(); avcodec_get_frame_defaults(frame); - frame->pts = audio_time / av_q2d(c->time_base); - frame->nb_samples = audio_input_samples; + frame->pts = context->audio_time / av_q2d(c->time_base); + frame->nb_samples = context->audio_input_samples; frame->format = c->sample_fmt; #ifdef FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT frame->channel_layout = c->channel_layout; #endif - if (audio_deinterleave) { + if (context->audio_deinterleave) { int channel, i; uint8_t *temp; for (channel = 0; channel < c->channels; channel++) { for (i = 0; i < frame->nb_samples; i++) { - memcpy(audio_deinterleave_buffer + (i + channel * frame->nb_samples) * audio_sample_size, - audio_input_buffer + (c->channels * i + channel) * audio_sample_size, audio_sample_size); + memcpy(context->audio_deinterleave_buffer + (i + channel * frame->nb_samples) * context->audio_sample_size, + context->audio_input_buffer + (c->channels * i + channel) * context->audio_sample_size, context->audio_sample_size); } } - temp = audio_deinterleave_buffer; - audio_deinterleave_buffer = audio_input_buffer; - audio_input_buffer = temp; + temp = context->audio_deinterleave_buffer; + context->audio_deinterleave_buffer = context->audio_input_buffer; + context->audio_input_buffer = temp; } - avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, audio_input_buffer, - audio_input_samples * c->channels * audio_sample_size, 1); + avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, context->audio_input_buffer, + context->audio_input_samples * c->channels * context->audio_sample_size, 1); if (avcodec_encode_audio2(c, &pkt, frame, &got_output) < 0) { // XXX error("Error writing audio packet"); @@ -172,30 +175,30 @@ static int write_audio_frame(void) return 0; } #else - pkt.size = avcodec_encode_audio(c, audio_output_buffer, audio_outbuf_size, (short *) audio_input_buffer); + pkt.size = avcodec_encode_audio(c, context->audio_output_buffer, context->audio_outbuf_size, (short *) context->audio_input_buffer); if (pkt.size < 0) { // XXX error("Error writing audio packet"); return -1; } - pkt.data = audio_output_buffer; + pkt.data = context->audio_output_buffer; got_output = 1; #endif if (got_output) { if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts = av_rescale_q(pkt.pts, c->time_base, audio_stream->time_base); + pkt.pts = av_rescale_q(pkt.pts, c->time_base, context->audio_stream->time_base); if (pkt.dts != AV_NOPTS_VALUE) - pkt.dts = av_rescale_q(pkt.dts, c->time_base, audio_stream->time_base); + pkt.dts = av_rescale_q(pkt.dts, c->time_base, context->audio_stream->time_base); if (pkt.duration > 0) - pkt.duration = av_rescale_q(pkt.duration, c->time_base, audio_stream->time_base); + pkt.duration = av_rescale_q(pkt.duration, c->time_base, context->audio_stream->time_base); - pkt.stream_index = audio_stream->index; + pkt.stream_index = context->audio_stream->index; pkt.flags |= AV_PKT_FLAG_KEY; - if (av_interleaved_write_frame(outfile, &pkt) != 0) { + if (av_interleaved_write_frame(context->outfile, &pkt) != 0) { fprintf(stderr, "Error writing audio packet!\n"); if (frame) avcodec_free_frame(&frame); @@ -302,11 +305,11 @@ static const char **get_file_extensions(int format) } /* Write a frame to the output file */ -static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportList *reports) +static int write_video_frame(FFMpegContext *context, RenderData *rd, int cfra, AVFrame *frame, ReportList *reports) { int got_output; int ret, success = 1; - AVCodecContext *c = video_stream->codec; + AVCodecContext *c = context->video_stream->codec; AVPacket packet = { 0 }; av_init_packet(&packet); @@ -321,22 +324,22 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportLis if (ret >= 0 && got_output) { if (packet.pts != AV_NOPTS_VALUE) { - packet.pts = av_rescale_q(packet.pts, c->time_base, video_stream->time_base); + packet.pts = av_rescale_q(packet.pts, c->time_base, context->video_stream->time_base); PRINT("Video Frame PTS: %d\n", (int)packet.pts); } else { PRINT("Video Frame PTS: not set\n"); } if (packet.dts != AV_NOPTS_VALUE) { - packet.dts = av_rescale_q(packet.dts, c->time_base, video_stream->time_base); + packet.dts = av_rescale_q(packet.dts, c->time_base, context->video_stream->time_base); PRINT("Video Frame DTS: %d\n", (int)packet.dts); } else { PRINT("Video Frame DTS: not set\n"); } - packet.stream_index = video_stream->index; - ret = av_interleaved_write_frame(outfile, &packet); + packet.stream_index = context->video_stream->index; + ret = av_interleaved_write_frame(context->outfile, &packet); success = (ret == 0); } else if (ret < 0) { @@ -350,11 +353,11 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportLis } /* read and encode a frame of audio from the buffer */ -static AVFrame *generate_video_frame(uint8_t *pixels, ReportList *reports) +static AVFrame *generate_video_frame(FFMpegContext *context, uint8_t *pixels, ReportList *reports) { uint8_t *rendered_frame; - AVCodecContext *c = video_stream->codec; + AVCodecContext *c = context->video_stream->codec; int width = c->width; int height = c->height; AVFrame *rgb_frame; @@ -367,7 +370,7 @@ static AVFrame *generate_video_frame(uint8_t *pixels, ReportList *reports) } } else { - rgb_frame = current_frame; + rgb_frame = context->current_frame; } rendered_frame = pixels; @@ -411,17 +414,17 @@ static AVFrame *generate_video_frame(uint8_t *pixels, ReportList *reports) } if (c->pix_fmt != PIX_FMT_BGR32) { - sws_scale(img_convert_ctx, (const uint8_t *const *) rgb_frame->data, + sws_scale(context->img_convert_ctx, (const uint8_t *const *) rgb_frame->data, rgb_frame->linesize, 0, c->height, - current_frame->data, current_frame->linesize); + context->current_frame->data, context->current_frame->linesize); delete_picture(rgb_frame); } - current_frame->format = PIX_FMT_BGR32; - current_frame->width = width; - current_frame->height = height; + context->current_frame->format = PIX_FMT_BGR32; + context->current_frame->width = width; + context->current_frame->height = height; - return current_frame; + return context->current_frame; } static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop, AVDictionary **dictionary) @@ -516,7 +519,7 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char /* prepare a video stream for the output file */ -static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContext *of, +static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int codec_id, AVFormatContext *of, int rectx, int recty, char *error, int error_size) { AVStream *st; @@ -542,7 +545,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex c->height = recty; /* FIXME: Really bad hack (tm) for NTSC support */ - if (ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) { + if (context->ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) { c->time_base.den = 2997; c->time_base.num = 100; } @@ -555,8 +558,8 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex c->time_base.num = ((double) rd->frs_sec_base) * 100000; } - c->gop_size = ffmpeg_gop_size; - c->bit_rate = ffmpeg_video_bitrate * 1000; + c->gop_size = context->ffmpeg_gop_size; + c->bit_rate = context->ffmpeg_video_bitrate * 1000; c->rc_max_rate = rd->ffcodecdata.rc_max_rate * 1000; c->rc_min_rate = rd->ffcodecdata.rc_min_rate * 1000; c->rc_buffer_size = rd->ffcodecdata.rc_buffer_size * 1024; @@ -585,7 +588,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex c->pix_fmt = PIX_FMT_YUV422P; } - if (ffmpeg_type == FFMPEG_XVID) { + if (context->ffmpeg_type == FFMPEG_XVID) { /* arghhhh ... */ c->pix_fmt = PIX_FMT_YUV420P; c->codec_tag = (('D' << 24) + ('I' << 16) + ('V' << 8) + 'X'); @@ -655,14 +658,14 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex } av_dict_free(&opts); - current_frame = alloc_picture(c->pix_fmt, c->width, c->height); + context->current_frame = alloc_picture(c->pix_fmt, c->width, c->height); - img_convert_ctx = sws_getContext(c->width, c->height, PIX_FMT_BGR32, c->width, c->height, c->pix_fmt, SWS_BICUBIC, + context->img_convert_ctx = sws_getContext(c->width, c->height, PIX_FMT_BGR32, c->width, c->height, c->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL); return st; } -static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size) +static AVStream *alloc_audio_stream(FFMpegContext *context, RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size) { AVStream *st; AVCodecContext *c; @@ -680,7 +683,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex c->codec_type = AVMEDIA_TYPE_AUDIO; c->sample_rate = rd->ffcodecdata.audio_mixrate; - c->bit_rate = ffmpeg_audio_bitrate * 1000; + c->bit_rate = context->ffmpeg_audio_bitrate * 1000; c->sample_fmt = AV_SAMPLE_FMT_S16; c->channels = rd->ffcodecdata.audio_channels; @@ -747,35 +750,35 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex st->codec->time_base.den = st->codec->sample_rate; #ifndef FFMPEG_HAVE_ENCODE_AUDIO2 - audio_outbuf_size = FF_MIN_BUFFER_SIZE; + context->audio_outbuf_size = FF_MIN_BUFFER_SIZE; #endif if (c->frame_size == 0) // used to be if ((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD)) // not sure if that is needed anymore, so let's try out if there are any // complaints regarding some ffmpeg versions users might have - audio_input_samples = FF_MIN_BUFFER_SIZE * 8 / c->bits_per_coded_sample / c->channels; + context->audio_input_samples = FF_MIN_BUFFER_SIZE * 8 / c->bits_per_coded_sample / c->channels; else { - audio_input_samples = c->frame_size; + context->audio_input_samples = c->frame_size; #ifndef FFMPEG_HAVE_ENCODE_AUDIO2 - if (c->frame_size * c->channels * sizeof(int16_t) * 4 > audio_outbuf_size) - audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4; + if (c->frame_size * c->channels * sizeof(int16_t) * 4 > context->audio_outbuf_size) + context->audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4; #endif } - audio_deinterleave = av_sample_fmt_is_planar(c->sample_fmt); + context->audio_deinterleave = av_sample_fmt_is_planar(c->sample_fmt); - audio_sample_size = av_get_bytes_per_sample(c->sample_fmt); + context->audio_sample_size = av_get_bytes_per_sample(c->sample_fmt); - audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * audio_sample_size); + context->audio_input_buffer = (uint8_t *) av_malloc(context->audio_input_samples * c->channels * context->audio_sample_size); #ifndef FFMPEG_HAVE_ENCODE_AUDIO2 - audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size); + context->audio_output_buffer = (uint8_t *) av_malloc(context->audio_outbuf_size); #endif - if (audio_deinterleave) - audio_deinterleave_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * audio_sample_size); + if (context->audio_deinterleave) + context->audio_deinterleave_buffer = (uint8_t *) av_malloc(context->audio_input_samples * c->channels * context->audio_sample_size); - audio_time = 0.0f; + context->audio_time = 0.0f; return st; } @@ -799,7 +802,7 @@ static void ffmpeg_dict_set_float(AVDictionary **dict, const char *key, float va av_dict_set(dict, key, buffer, 0); } -static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, ReportList *reports) +static int start_ffmpeg_impl(FFMpegContext *context, struct RenderData *rd, int rectx, int recty, const char *suffix, ReportList *reports) { /* Handle to the output file */ AVFormatContext *of; @@ -808,26 +811,26 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report char name[256], error[1024]; const char **exts; - ffmpeg_type = rd->ffcodecdata.type; - ffmpeg_codec = rd->ffcodecdata.codec; - ffmpeg_audio_codec = rd->ffcodecdata.audio_codec; - ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate; - ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate; - ffmpeg_gop_size = rd->ffcodecdata.gop_size; - ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT; - + context->ffmpeg_type = rd->ffcodecdata.type; + context->ffmpeg_codec = rd->ffcodecdata.codec; + context->ffmpeg_audio_codec = rd->ffcodecdata.audio_codec; + context->ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate; + context->ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate; + context->ffmpeg_gop_size = rd->ffcodecdata.gop_size; + context->ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT; + /* Determine the correct filename */ - BKE_ffmpeg_filepath_get(name, rd, ffmpeg_preview); + ffmpeg_filepath_get(context, name, rd, context->ffmpeg_preview, suffix); PRINT("Starting output to %s(ffmpeg)...\n" " Using type=%d, codec=%d, audio_codec=%d,\n" " video_bitrate=%d, audio_bitrate=%d,\n" " gop_size=%d, autosplit=%d\n" " render width=%d, render height=%d\n", - name, ffmpeg_type, ffmpeg_codec, ffmpeg_audio_codec, - ffmpeg_video_bitrate, ffmpeg_audio_bitrate, - ffmpeg_gop_size, ffmpeg_autosplit, rectx, recty); + name, context->ffmpeg_type, context->ffmpeg_codec, context->ffmpeg_audio_codec, + context->ffmpeg_video_bitrate, context->ffmpeg_audio_bitrate, + context->ffmpeg_gop_size, context->ffmpeg_autosplit, rectx, recty); - exts = get_file_extensions(ffmpeg_type); + exts = get_file_extensions(context->ffmpeg_type); if (!exts) { BKE_report(reports, RPT_ERROR, "No valid formats found"); return 0; @@ -846,7 +849,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report of->oformat = fmt; of->packet_size = rd->ffcodecdata.mux_packet_size; - if (ffmpeg_audio_codec != AV_CODEC_ID_NONE) { + if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE) { ffmpeg_dict_set_int(&opts, "muxrate", rd->ffcodecdata.mux_rate); } else { @@ -857,15 +860,15 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report of->max_delay = (int)(0.7 * AV_TIME_BASE); - fmt->audio_codec = ffmpeg_audio_codec; + fmt->audio_codec = context->ffmpeg_audio_codec; BLI_strncpy(of->filename, name, sizeof(of->filename)); /* set the codec to the user's selection */ - switch (ffmpeg_type) { + switch (context->ffmpeg_type) { case FFMPEG_AVI: case FFMPEG_MOV: case FFMPEG_MKV: - fmt->video_codec = ffmpeg_codec; + fmt->video_codec = context->ffmpeg_codec; break; case FFMPEG_OGG: fmt->video_codec = AV_CODEC_ID_THEORA; @@ -908,9 +911,9 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report } } - if (ffmpeg_type == FFMPEG_DV) { + if (context->ffmpeg_type == FFMPEG_DV) { fmt->audio_codec = AV_CODEC_ID_PCM_S16LE; - if (ffmpeg_audio_codec != AV_CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000 && rd->ffcodecdata.audio_channels != 2) { + if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000 && rd->ffcodecdata.audio_channels != 2) { BKE_report(reports, RPT_ERROR, "FFMPEG only supports 48khz / stereo audio for DV!"); av_dict_free(&opts); return 0; @@ -918,9 +921,9 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report } if (fmt->video_codec != AV_CODEC_ID_NONE) { - video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty, error, sizeof(error)); - PRINT("alloc video stream %p\n", video_stream); - if (!video_stream) { + context->video_stream = alloc_video_stream(context, rd, fmt->video_codec, of, rectx, recty, error, sizeof(error)); + PRINT("alloc video stream %p\n", context->video_stream); + if (!context->video_stream) { if (error[0]) BKE_report(reports, RPT_ERROR, error); else @@ -931,9 +934,9 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report } } - if (ffmpeg_audio_codec != AV_CODEC_ID_NONE) { - audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of, error, sizeof(error)); - if (!audio_stream) { + if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE) { + context->audio_stream = alloc_audio_stream(context, rd, fmt->audio_codec, of, error, sizeof(error)); + if (!context->audio_stream) { if (error[0]) BKE_report(reports, RPT_ERROR, error); else @@ -956,7 +959,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report return 0; } - outfile = of; + context->outfile = of; av_dump_format(of, 0, name, 1); av_dict_free(&opts); @@ -980,11 +983,11 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report * parameter. *

*/ -static void flush_ffmpeg(void) +static void flush_ffmpeg(FFMpegContext *context) { int ret = 0; - AVCodecContext *c = video_stream->codec; + AVCodecContext *c = context->video_stream->codec; /* get the delayed frames */ while (1) { int got_output; @@ -1000,28 +1003,28 @@ static void flush_ffmpeg(void) break; } if (packet.pts != AV_NOPTS_VALUE) { - packet.pts = av_rescale_q(packet.pts, c->time_base, video_stream->time_base); + packet.pts = av_rescale_q(packet.pts, c->time_base, context->video_stream->time_base); PRINT("Video Frame PTS: %d\n", (int) packet.pts); } else { PRINT("Video Frame PTS: not set\n"); } if (packet.dts != AV_NOPTS_VALUE) { - packet.dts = av_rescale_q(packet.dts, c->time_base, video_stream->time_base); + packet.dts = av_rescale_q(packet.dts, c->time_base, context->video_stream->time_base); PRINT("Video Frame DTS: %d\n", (int) packet.dts); } else { PRINT("Video Frame DTS: not set\n"); } - packet.stream_index = video_stream->index; - ret = av_interleaved_write_frame(outfile, &packet); + packet.stream_index = context->video_stream->index; + ret = av_interleaved_write_frame(context->outfile, &packet); if (ret != 0) { fprintf(stderr, "Error writing delayed frame %d\n", ret); break; } } - avcodec_flush_buffers(video_stream->codec); + avcodec_flush_buffers(context->video_stream->codec); } /* ********************************************************************** @@ -1029,7 +1032,7 @@ static void flush_ffmpeg(void) * ********************************************************************** */ /* Get the output filename-- similar to the other output formats */ -void BKE_ffmpeg_filepath_get(char *string, RenderData *rd, bool preview) +static void ffmpeg_filepath_get(FFMpegContext *context, char *string, RenderData *rd, bool preview, const char *suffix) { char autosplit[20]; @@ -1056,7 +1059,9 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd, bool preview) autosplit[0] = 0; if ((rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT) != 0) { - sprintf(autosplit, "_%03d", ffmpeg_autosplit_count); + if (context) { + sprintf(autosplit, "_%03d", context->ffmpeg_autosplit_count); + } } if (rd->scemode & R_EXTENSION) { @@ -1086,19 +1091,28 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd, bool preview) strcat(string, autosplit); } + + BLI_path_suffix(string, FILE_MAX, suffix, ""); } -int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview) +void BKE_ffmpeg_filepath_get(char *string, RenderData *rd, bool preview, const char *suffix) +{ + ffmpeg_filepath_get(NULL, string, rd, preview, suffix); +} + +int BKE_ffmpeg_start(void *context_v, struct Scene *scene, RenderData *rd, int rectx, int recty, + ReportList *reports, bool preview, const char *suffix) { int success; + FFMpegContext *context = context_v; - ffmpeg_autosplit_count = 0; - ffmpeg_preview = preview; + context->ffmpeg_autosplit_count = 0; + context->ffmpeg_preview = preview; - success = start_ffmpeg_impl(rd, rectx, recty, reports); + success = start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports); #ifdef WITH_AUDASPACE - if (audio_stream) { - AVCodecContext *c = audio_stream->codec; + if (context->audio_stream) { + AVCodecContext *c = context->audio_stream->codec; AUD_DeviceSpecs specs; specs.channels = c->channels; @@ -1123,7 +1137,7 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, } specs.rate = rd->ffcodecdata.audio_mixrate; - audio_mixdown_device = BKE_sound_mixdown(scene, specs, preview ? rd->psfra : rd->sfra, rd->ffcodecdata.audio_volume); + context->audio_mixdown_device = BKE_sound_mixdown(scene, specs, preview ? rd->psfra : rd->sfra, rd->ffcodecdata.audio_volume); #ifdef FFMPEG_CODEC_TIME_BASE c->time_base.den = specs.rate; c->time_base.num = 1; @@ -1133,16 +1147,16 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, return success; } -static void end_ffmpeg_impl(int is_autosplit); +static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit); #ifdef WITH_AUDASPACE -static void write_audio_frames(double to_pts) +static void write_audio_frames(FFMpegContext *context, double to_pts) { int finished = 0; - while (audio_stream && !finished) { - if ((audio_time >= to_pts) || - (write_audio_frame())) + while (context->audio_stream && !finished) { + if ((context->audio_time >= to_pts) || + (write_audio_frame(context))) { finished = 1; } @@ -1150,8 +1164,10 @@ static void write_audio_frames(double to_pts) } #endif -int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, ReportList *reports) +int BKE_ffmpeg_append(void *context_v, RenderData *rd, int start_frame, int frame, int *pixels, + int rectx, int recty, const char *suffix, ReportList *reports) { + FFMpegContext *context = context_v; AVFrame *avframe; int success = 1; @@ -1160,111 +1176,112 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i /* why is this done before writing the video frame and again at end_ffmpeg? */ // write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base)); - if (video_stream) { - avframe = generate_video_frame((unsigned char *) pixels, reports); - success = (avframe && write_video_frame(rd, frame - start_frame, avframe, reports)); + if (context->video_stream) { + avframe = generate_video_frame(context, (unsigned char *) pixels, reports); + success = (avframe && write_video_frame(context, rd, frame - start_frame, avframe, reports)); - if (ffmpeg_autosplit) { - if (avio_tell(outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) { - end_ffmpeg_impl(true); - ffmpeg_autosplit_count++; - success &= start_ffmpeg_impl(rd, rectx, recty, reports); + if (context->ffmpeg_autosplit) { + if (avio_tell(context->outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) { + end_ffmpeg_impl(context, true); + context->ffmpeg_autosplit_count++; + success &= start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports); } } } #ifdef WITH_AUDASPACE - write_audio_frames((frame - start_frame) / (((double)rd->frs_sec) / (double)rd->frs_sec_base)); + write_audio_frames(context, (frame - start_frame) / (((double)rd->frs_sec) / (double)rd->frs_sec_base)); #endif return success; } -static void end_ffmpeg_impl(int is_autosplit) +static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit) { unsigned int i; PRINT("Closing ffmpeg...\n"); #if 0 - if (audio_stream) { /* SEE UPPER */ - write_audio_frames(); + if (context->audio_stream) { /* SEE UPPER */ + write_audio_frames(context); } #endif #ifdef WITH_AUDASPACE if (is_autosplit == false) { - if (audio_mixdown_device) { - AUD_closeReadDevice(audio_mixdown_device); - audio_mixdown_device = 0; + if (context->audio_mixdown_device) { + AUD_closeReadDevice(context->audio_mixdown_device); + context->audio_mixdown_device = 0; } } #endif - if (video_stream && video_stream->codec) { + if (context->video_stream && context->video_stream->codec) { PRINT("Flushing delayed frames...\n"); - flush_ffmpeg(); + flush_ffmpeg(context); } - if (outfile) { - av_write_trailer(outfile); + if (context->outfile) { + av_write_trailer(context->outfile); } /* Close the video codec */ - if (video_stream && video_stream->codec) { - avcodec_close(video_stream->codec); - PRINT("zero video stream %p\n", video_stream); - video_stream = 0; + if (context->video_stream && context->video_stream->codec) { + avcodec_close(context->video_stream->codec); + PRINT("zero video stream %p\n", context->video_stream); + context->video_stream = 0; } /* Close the output file */ - if (outfile) { - for (i = 0; i < outfile->nb_streams; i++) { - if (&outfile->streams[i]) { - av_freep(&outfile->streams[i]); + if (context->outfile) { + for (i = 0; i < context->outfile->nb_streams; i++) { + if (&context->outfile->streams[i]) { + av_freep(&context->outfile->streams[i]); } } } /* free the temp buffer */ - if (current_frame) { - delete_picture(current_frame); - current_frame = 0; + if (context->current_frame) { + delete_picture(context->current_frame); + context->current_frame = 0; } - if (outfile && outfile->oformat) { - if (!(outfile->oformat->flags & AVFMT_NOFILE)) { - avio_close(outfile->pb); + if (context->outfile && context->outfile->oformat) { + if (!(context->outfile->oformat->flags & AVFMT_NOFILE)) { + avio_close(context->outfile->pb); } } - if (outfile) { - av_free(outfile); - outfile = 0; + if (context->outfile) { + av_free(context->outfile); + context->outfile = 0; } - if (audio_input_buffer) { - av_free(audio_input_buffer); - audio_input_buffer = 0; + if (context->audio_input_buffer) { + av_free(context->audio_input_buffer); + context->audio_input_buffer = 0; } #ifndef FFMPEG_HAVE_ENCODE_AUDIO2 - if (audio_output_buffer) { - av_free(audio_output_buffer); - audio_output_buffer = 0; + if (context->audio_output_buffer) { + av_free(context->audio_output_buffer); + context->audio_output_buffer = 0; } #endif - if (audio_deinterleave_buffer) { - av_free(audio_deinterleave_buffer); - audio_deinterleave_buffer = 0; + if (context->audio_deinterleave_buffer) { + av_free(context->audio_deinterleave_buffer); + context->audio_deinterleave_buffer = 0; } - if (img_convert_ctx) { - sws_freeContext(img_convert_ctx); - img_convert_ctx = 0; + if (context->img_convert_ctx) { + sws_freeContext(context->img_convert_ctx); + context->img_convert_ctx = 0; } } -void BKE_ffmpeg_end(void) +void BKE_ffmpeg_end(void *context_v) { - end_ffmpeg_impl(false); + FFMpegContext *context = context_v; + end_ffmpeg_impl(context, false); } /* properties */ @@ -1658,4 +1675,31 @@ bool BKE_ffmpeg_alpha_channel_is_supported(RenderData *rd) return false; } -#endif +void *BKE_ffmpeg_context_create(void) +{ + FFMpegContext *context; + + /* new ffmpeg data struct */ + context = MEM_callocN(sizeof(FFMpegContext), "new ffmpeg context"); + + context->ffmpeg_codec = AV_CODEC_ID_MPEG4; + context->ffmpeg_audio_codec = AV_CODEC_ID_NONE; + context->ffmpeg_video_bitrate = 1150; + context->ffmpeg_audio_bitrate = 128; + context->ffmpeg_gop_size = 12; + context->ffmpeg_autosplit = 0; + context->ffmpeg_autosplit_count = 0; + context->ffmpeg_preview = false; + + return context; +} + +void BKE_ffmpeg_context_free(void *context_v) +{ + FFMpegContext *context = context_v; + if (context) { + MEM_freeN(context); + } +} + +#endif /* WITH_FFMPEG */ diff --git a/source/blender/blenkernel/intern/writeframeserver.c b/source/blender/blenkernel/intern/writeframeserver.c index 9cac86d62bd..ba58038bbd8 100644 --- a/source/blender/blenkernel/intern/writeframeserver.c +++ b/source/blender/blenkernel/intern/writeframeserver.c @@ -66,12 +66,15 @@ #include "BKE_report.h" #include "DNA_scene_types.h" +#include "MEM_guardedalloc.h" -static int sock; -static int connsock; -static int write_ppm; -static int render_width; -static int render_height; +typedef struct FrameserverContext { + int sock; + int connsock; + int write_ppm; + int render_width; + int render_height; +} FrameserverContext; #if defined(_WIN32) @@ -110,10 +113,11 @@ static int closesocket(int fd) } #endif -int BKE_frameserver_start(struct Scene *scene, RenderData *UNUSED(rd), int rectx, int recty, ReportList *reports, bool UNUSED(preview)) +int BKE_frameserver_start(void *context_v, struct Scene *scene, RenderData *UNUSED(rd), int rectx, int recty, ReportList *reports, bool UNUSED(preview), const char *UNUSED(suffix)) { struct sockaddr_in addr; int arg = 1; + FrameserverContext *context = context_v; (void)scene; /* unused */ @@ -122,33 +126,33 @@ int BKE_frameserver_start(struct Scene *scene, RenderData *UNUSED(rd), int rectx return 0; } - if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + if ((context->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { shutdown_socket_system(); BKE_report(reports, RPT_ERROR, "Cannot open socket"); return 0; } - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &arg, sizeof(arg)); + setsockopt(context->sock, SOL_SOCKET, SO_REUSEADDR, (char *) &arg, sizeof(arg)); addr.sin_family = AF_INET; addr.sin_port = htons(U.frameserverport); addr.sin_addr.s_addr = INADDR_ANY; - if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + if (bind(context->sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { shutdown_socket_system(); BKE_report(reports, RPT_ERROR, "Cannot bind to socket"); return 0; } - if (listen(sock, SOMAXCONN) < 0) { + if (listen(context->sock, SOMAXCONN) < 0) { shutdown_socket_system(); BKE_report(reports, RPT_ERROR, "Cannot establish listen backlog"); return 0; } - connsock = -1; + context->connsock = -1; - render_width = rectx; - render_height = recty; + context->render_width = rectx; + context->render_height = recty; return 1; } @@ -177,7 +181,7 @@ static char good_bye[] = "
\n"
 "Render stopped. Goodbye
"; -static int safe_write(char *s, int tosend) +static int safe_write(const int connsock, char *s, int tosend) { int total = tosend; do { @@ -192,12 +196,12 @@ static int safe_write(char *s, int tosend) return total; } -static int safe_puts(char *s) +static int safe_puts(const int connsock, char *s) { - return safe_write(s, strlen(s)); + return safe_write(connsock, s, strlen(s)); } -static int handle_request(RenderData *rd, char *req) +static int handle_request(FrameserverContext *context, RenderData *rd, char *req) { char *p; char *path; @@ -214,16 +218,16 @@ static int handle_request(RenderData *rd, char *req) *p = 0; - if (STREQ(path, "/index.html") || STREQ(path, "/")) { - safe_puts(index_page); + if (STREQ(path, "/index.html") || strcmp(path, "/")) { + safe_puts(context->connsock, index_page); return -1; } - write_ppm = 0; + context->write_ppm = 0; pathlen = strlen(path); if (pathlen > 12 && memcmp(path, "/images/ppm/", 12) == 0) { - write_ppm = 1; + context->write_ppm = 1; return atoi(path + 12); } if (STREQ(path, "/info.txt")) { @@ -241,24 +245,24 @@ static int handle_request(RenderData *rd, char *req) "ratescale %d\n", rd->sfra, rd->efra, - render_width, - render_height, + context->render_width, + context->render_height, rd->frs_sec, 1 ); - safe_puts(buf); + safe_puts(context->connsock, buf); return -1; } if (STREQ(path, "/close.txt")) { - safe_puts(good_bye); + safe_puts(context->connsock, good_bye); G.is_break = true; /* Abort render */ return -1; } return -1; } -int BKE_frameserver_loop(RenderData *rd, ReportList *UNUSED(reports)) +int BKE_frameserver_loop(void *context_v, RenderData *rd, ReportList *UNUSED(reports)) { fd_set readfds; struct timeval tv; @@ -271,18 +275,20 @@ int BKE_frameserver_loop(RenderData *rd, ReportList *UNUSED(reports)) #endif char buf[4096]; - if (connsock != -1) { - closesocket(connsock); - connsock = -1; + FrameserverContext *context = context_v; + + if (context->connsock != -1) { + closesocket(context->connsock); + context->connsock = -1; } tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO(&readfds); - FD_SET(sock, &readfds); + FD_SET(context->sock, &readfds); - rval = select(sock + 1, &readfds, NULL, NULL, &tv); + rval = select(context->sock + 1, &readfds, NULL, NULL, &tv); if (rval < 0) { return -1; } @@ -293,19 +299,19 @@ int BKE_frameserver_loop(RenderData *rd, ReportList *UNUSED(reports)) socklen = sizeof(addr); - if ((connsock = accept(sock, (struct sockaddr *)&addr, &socklen)) < 0) { + if ((context->connsock = accept(context->sock, (struct sockaddr *)&addr, &socklen)) < 0) { return -1; } FD_ZERO(&readfds); - FD_SET(connsock, &readfds); + FD_SET(context->connsock, &readfds); for (;;) { /* give 10 seconds for telnet testing... */ tv.tv_sec = 10; tv.tv_usec = 0; - rval = select(connsock + 1, &readfds, NULL, NULL, &tv); + rval = select(context->connsock + 1, &readfds, NULL, NULL, &tv); if (rval > 0) { break; } @@ -319,7 +325,7 @@ int BKE_frameserver_loop(RenderData *rd, ReportList *UNUSED(reports)) } } - len = recv(connsock, buf, sizeof(buf) - 1, 0); + len = recv(context->connsock, buf, sizeof(buf) - 1, 0); if (len < 0) { return -1; @@ -327,13 +333,13 @@ int BKE_frameserver_loop(RenderData *rd, ReportList *UNUSED(reports)) buf[len] = 0; - return handle_request(rd, buf); + return handle_request(context, rd, buf); } -static void serve_ppm(int *pixels, int rectx, int recty) +static void serve_ppm(FrameserverContext *context, int *pixels, int rectx, int recty) { unsigned char *rendered_frame; - unsigned char *row = (unsigned char *) malloc(render_width * 3); + unsigned char *row = (unsigned char *) malloc(context->render_width * 3); int y; char header[1024]; @@ -348,7 +354,7 @@ static void serve_ppm(int *pixels, int rectx, int recty) "255\n", rectx, recty); - safe_puts(header); + safe_puts(context->connsock, header); rendered_frame = (unsigned char *)pixels; @@ -364,36 +370,54 @@ static void serve_ppm(int *pixels, int rectx, int recty) target += 3; src += 4; } - safe_write((char *)row, 3 * rectx); + safe_write(context->connsock, (char *)row, 3 * rectx); } free(row); - closesocket(connsock); - connsock = -1; + closesocket(context->connsock); + context->connsock = -1; } -int BKE_frameserver_append(RenderData *UNUSED(rd), int UNUSED(start_frame), int frame, int *pixels, - int rectx, int recty, ReportList *UNUSED(reports)) +int BKE_frameserver_append(void *context_v, RenderData *UNUSED(rd), int UNUSED(start_frame), int frame, int *pixels, + int rectx, int recty, const char *UNUSED(suffix), ReportList *UNUSED(reports)) { + FrameserverContext *context = context_v; + fprintf(stderr, "Serving frame: %d\n", frame); - if (write_ppm) { - serve_ppm(pixels, rectx, recty); + if (context->write_ppm) { + serve_ppm(context, pixels, rectx, recty); } - if (connsock != -1) { - closesocket(connsock); - connsock = -1; + if (context->connsock != -1) { + closesocket(context->connsock); + context->connsock = -1; } return 1; } -void BKE_frameserver_end(void) +void BKE_frameserver_end(void *context_v) { - if (connsock != -1) { - closesocket(connsock); - connsock = -1; + FrameserverContext *context = context_v; + + if (context->connsock != -1) { + closesocket(context->connsock); + context->connsock = -1; } - closesocket(sock); + closesocket(context->sock); shutdown_socket_system(); } +void *BKE_frameserver_context_create(void) +{ + FrameserverContext *context = MEM_mallocN(sizeof(FrameserverContext), "Frameserver Context"); + return context; +} + +void BKE_frameserver_context_free(void *context_v) +{ + FrameserverContext *context = context_v; + if (context) { + MEM_freeN(context); + } +} + #endif /* WITH_FRAMESERVER */ diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index 74291ca305e..18b8feaa99c 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -89,6 +89,7 @@ int BLI_system_num_threads_override_get(void); #define LOCK_MOVIECLIP 7 #define LOCK_COLORMANAGE 8 #define LOCK_FFTW 9 +#define LOCK_VIEW3D 10 void BLI_lock_thread(int type); void BLI_unlock_thread(int type); diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index ded2fd7e06d..da06500565c 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -122,6 +122,7 @@ static pthread_mutex_t _nodes_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _movieclip_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _colormanage_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _fftw_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t _view3d_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_t mainid; static int thread_levels = 0; /* threads can be invoked inside threads */ static int num_threads_override = 0; @@ -402,6 +403,8 @@ void BLI_lock_thread(int type) pthread_mutex_lock(&_colormanage_lock); else if (type == LOCK_FFTW) pthread_mutex_lock(&_fftw_lock); + else if (type == LOCK_VIEW3D) + pthread_mutex_lock(&_view3d_lock); } void BLI_unlock_thread(int type) @@ -426,6 +429,8 @@ void BLI_unlock_thread(int type) pthread_mutex_unlock(&_colormanage_lock); else if (type == LOCK_FFTW) pthread_mutex_unlock(&_fftw_lock); + else if (type == LOCK_VIEW3D) + pthread_mutex_unlock(&_view3d_lock); } /* Mutex Locks */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8c5959f20bf..4eb7413adc1 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1533,9 +1533,15 @@ void blo_make_packed_pointer_map(FileData *fd, Main *oldmain) fd->packedmap = oldnewmap_new(); - for (ima = oldmain->image.first; ima; ima = ima->id.next) + for (ima = oldmain->image.first; ima; ima = ima->id.next) { + ImagePackedFile *imapf; if (ima->packedfile) insert_packedmap(fd, ima->packedfile); + + for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) + if (imapf->packedfile) + insert_packedmap(fd, imapf->packedfile); + } for (vfont = oldmain->vfont.first; vfont; vfont = vfont->id.next) if (vfont->packedfile) @@ -1568,8 +1574,13 @@ void blo_end_packed_pointer_map(FileData *fd, Main *oldmain) entry->newp = NULL; } - for (ima = oldmain->image.first; ima; ima = ima->id.next) + for (ima = oldmain->image.first; ima; ima = ima->id.next) { + ImagePackedFile *imapf; ima->packedfile = newpackedadr(fd, ima->packedfile); + + for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) + imapf->packedfile = newpackedadr(fd, imapf->packedfile); + } for (vfont = oldmain->vfont.first; vfont; vfont = vfont->id.next) vfont->packedfile = newpackedadr(fd, vfont->packedfile); @@ -3391,6 +3402,8 @@ static void lib_link_image(FileData *fd, Main *main) static void direct_link_image(FileData *fd, Image *ima) { + ImagePackedFile *imapf; + /* for undo system, pointers could be restored */ if (fd->imamap) ima->cache = newimaadr(fd, ima->cache); @@ -3404,8 +3417,7 @@ static void direct_link_image(FileData *fd, Image *ima) ima->gputexture = NULL; ima->rr = NULL; } - - ima->anim = NULL; + ima->repbind = NULL; /* undo system, try to restore render buffers */ @@ -3419,9 +3431,18 @@ static void direct_link_image(FileData *fd, Image *ima) memset(ima->renders, 0, sizeof(ima->renders)); ima->last_render_slot = ima->render_slot; } - + + link_list(fd, &(ima->views)); + link_list(fd, &(ima->packedfiles)); + + for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) { + imapf->packedfile = direct_link_packedfile(fd, imapf->packedfile); + } + + ima->anims.first = ima->anims.last = NULL; ima->packedfile = direct_link_packedfile(fd, ima->packedfile); ima->preview = direct_link_preview_image(fd, ima->preview); + ima->stereo3d_format = newdataadr(fd, ima->stereo3d_format); ima->ok = 1; } @@ -5378,7 +5399,7 @@ static void lib_link_scene(FileData *fd, Main *main) seq->scene_sound = BKE_sound_add_scene_sound_defaults(sce, seq); } } - seq->anim = NULL; + seq->anims.first = seq->anims.last = NULL; lib_link_sequence_modifiers(fd, sce, &seq->modifiers); } @@ -5610,6 +5631,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) if (seq->seq3 == NULL) seq->seq3 = seq->seq2; seq->effectdata = newdataadr(fd, seq->effectdata); + seq->stereo3d_format = newdataadr(fd, seq->stereo3d_format); if (seq->type & SEQ_TYPE_EFFECT) seq->flag |= SEQ_EFFECT_NOT_LOADED; @@ -5722,6 +5744,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) link_list(fd, &(sce->markers)); link_list(fd, &(sce->transform_spaces)); link_list(fd, &(sce->r.layers)); + link_list(fd, &(sce->r.views)); for (srl = sce->r.layers.first; srl; srl = srl->next) { link_list(fd, &(srl->freestyleConfig.modules)); @@ -5785,8 +5808,8 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) BLI_listbase_clear(&win->modalhandlers); BLI_listbase_clear(&win->subwindows); BLI_listbase_clear(&win->gesture); + BLI_listbase_clear(&win->drawdata); - win->drawdata = NULL; win->drawmethod = -1; win->drawfail = 0; win->active = 0; @@ -5794,6 +5817,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) win->cursor = 0; win->lastcursor = 0; win->modalcursor = 0; + win->stereo3d_format = newdataadr(fd, win->stereo3d_format); } BLI_listbase_clear(&wm->timers); @@ -7765,7 +7789,6 @@ static void do_versions_userdef(FileData *fd, BlendFileData *bfd) user->walk_navigation.jump_height = 0.4f; /* m */ user->walk_navigation.teleport_time = 0.2f; /* s */ } - } static void do_versions(FileData *fd, Library *lib, Main *main) @@ -7888,7 +7911,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) link_list(fd, &user->user_keymaps); link_list(fd, &user->addons); link_list(fd, &user->autoexec_paths); - + for (keymap=user->user_keymaps.first; keymap; keymap=keymap->next) { keymap->modal_items= NULL; keymap->poll = NULL; diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 50cd39352a8..371ce495b07 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -27,6 +27,7 @@ #include "BLI_utildefines.h" #include "BLI_compiler_attrs.h" +#include "BLI_string.h" /* for MinGW32 definition of NULL, could use BLI_blenlib.h instead too */ #include @@ -48,14 +49,18 @@ #include "DNA_particle_types.h" #include "DNA_linestyle_types.h" #include "DNA_actuator_types.h" +#include "DNA_camera_types.h" +#include "DNA_view3d_types.h" #include "DNA_genfile.h" #include "BKE_main.h" #include "BKE_modifier.h" #include "BKE_node.h" +#include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_screen.h" +#include "BKE_sequencer.h" #include "BLI_math.h" #include "BLI_listbase.h" @@ -460,10 +465,10 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) br->mtex.random_angle = 2.0 * M_PI; br->mask_mtex.random_angle = 2.0 * M_PI; } + } #undef BRUSH_RAKE #undef BRUSH_RANDOM_ROTATION - } /* Customizable Safe Areas */ if (!MAIN_VERSION_ATLEAST(main, 273, 2)) { @@ -724,4 +729,85 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) #undef SEQ_USE_PROXY_CUSTOM_DIR #undef SEQ_USE_PROXY_CUSTOM_FILE } + + if (!MAIN_VERSION_ATLEAST(main, 274, 3)) + { + SceneRenderView *srv; + wmWindowManager *wm; + bScreen *screen; + wmWindow *win; + Scene *scene; + Camera *cam; + Image *ima; + + for (scene = main->scene.first; scene; scene = scene->id.next) { + Sequence *seq; + + BKE_scene_add_render_view(scene, STEREO_LEFT_NAME); + srv = scene->r.views.first; + BLI_strncpy(srv->suffix, STEREO_LEFT_SUFFIX, sizeof(srv->suffix)); + + BKE_scene_add_render_view(scene, STEREO_RIGHT_NAME); + srv = scene->r.views.last; + BLI_strncpy(srv->suffix, STEREO_RIGHT_SUFFIX, sizeof(srv->suffix)); + + SEQ_BEGIN (scene->ed, seq) + { + seq->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo Display 3d Format"); + } + SEQ_END + } + + for (screen = main->screen.first; screen; screen = screen->id.next) { + ScrArea *sa; + for (sa = screen->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; + + for (sl = sa->spacedata.first; sl; sl = sl->next) { + switch (sl->spacetype) { + case SPACE_VIEW3D: + { + View3D *v3d = (View3D *)sl; + v3d->stereo3d_camera = STEREO_3D_ID; + v3d->stereo3d_flag |= V3D_S3D_DISPPLANE; + v3d->stereo3d_convergence_alpha = 0.15f; + v3d->stereo3d_volume_alpha = 0.05f; + break; + } + case SPACE_IMAGE: + { + SpaceImage *sima = (SpaceImage *) sl; + sima->iuser.flag |= IMA_SHOW_STEREO; + sima->iuser.passtype = SCE_PASS_COMBINED; + break; + } + } + } + } + } + + for (cam = main->camera.first; cam; cam = cam->id.next) { + cam->stereo.interocular_distance = 0.065; + cam->stereo.convergence_distance = 30.f * 0.065; + } + + for (ima = main->image.first; ima; ima = ima->id.next) { + ima->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Image Stereo 3d Format"); + + if (ima->packedfile) { + ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image Packed File"); + BLI_addtail(&ima->packedfiles, imapf); + + imapf->packedfile = ima->packedfile; + BLI_strncpy(imapf->filepath, ima->name, FILE_MAX); + ima->packedfile = NULL; + } + } + + for (wm = main->wm.first; wm; wm = wm->id.next) { + for (win = wm->windows.first; win; win = win->next) { + win->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo Display 3d Format"); + } + } + } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index c616436d584..2580ba64622 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2124,7 +2124,8 @@ static void write_images(WriteData *wd, ListBase *idbase) { Image *ima; PackedFile * pf; - + ImageView *iv; + ImagePackedFile *imapf; ima= idbase->first; while (ima) { @@ -2133,13 +2134,20 @@ static void write_images(WriteData *wd, ListBase *idbase) writestruct(wd, ID_IM, "Image", 1, ima); if (ima->id.properties) IDP_WriteProperty(ima->id.properties, wd); - if (ima->packedfile) { - pf = ima->packedfile; - writestruct(wd, DATA, "PackedFile", 1, pf); - writedata(wd, DATA, pf->size, pf->data); + for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) { + writestruct(wd, DATA, "ImagePackedFile", 1, imapf); + if (imapf->packedfile) { + pf = imapf->packedfile; + writestruct(wd, DATA, "PackedFile", 1, pf); + writedata(wd, DATA, pf->size, pf->data); + } } write_previews(wd, ima->preview); + + for (iv = ima->views.first; iv; iv = iv->next) + writestruct(wd, DATA, "ImageView", 1, iv); + writestruct(wd, DATA, "Stereo3dFormat", 1, ima->stereo3d_format); } ima= ima->id.next; } @@ -2340,6 +2348,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase) TimeMarker *marker; TransformOrientation *ts; SceneRenderLayer *srl; + SceneRenderView *srv; ToolSettings *tos; FreestyleModuleConfig *fmc; FreestyleLineSet *fls; @@ -2421,7 +2430,9 @@ static void write_scenes(WriteData *wd, ListBase *scebase) break; } } - + + writestruct(wd, DATA, "Stereo3dFormat", 1, seq->stereo3d_format); + strip= seq->strip; writestruct(wd, DATA, "Strip", 1, strip); if (seq->flag & SEQ_USE_CROP && strip->crop) { @@ -2486,6 +2497,10 @@ static void write_scenes(WriteData *wd, ListBase *scebase) writestruct(wd, DATA, "FreestyleLineSet", 1, fls); } } + + /* writing MultiView to the blend file */ + for (srv = sce->r.views.first; srv; srv = srv->next) + writestruct(wd, DATA, "SceneRenderView", 1, srv); if (sce->nodetree) { writestruct(wd, DATA, "bNodeTree", 1, sce->nodetree); @@ -2548,8 +2563,10 @@ static void write_windowmanagers(WriteData *wd, ListBase *lb) for (wm= lb->first; wm; wm= wm->id.next) { writestruct(wd, ID_WM, "wmWindowManager", 1, wm); - for (win= wm->windows.first; win; win= win->next) + for (win= wm->windows.first; win; win= win->next) { writestruct(wd, DATA, "wmWindow", 1, win); + writestruct(wd, DATA, "Stereo3dFormat", 1, win->stereo3d_format); + } } } diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp index a5c1493208b..aac41e2e93c 100644 --- a/source/blender/collada/ImageExporter.cpp +++ b/source/blender/collada/ImageExporter.cpp @@ -74,7 +74,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) short image_source = image->source; bool is_generated = image_source == IMA_SRC_GENERATED; - bool is_packed = image->packedfile != NULL; + bool is_packed = BKE_image_has_packedfile(image); char export_path[FILE_MAX]; char source_path[FILE_MAX]; diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 048c974423f..c23aa4ec734 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -119,6 +119,8 @@ set(SRC nodes/COM_TimeNode.h nodes/COM_SwitchNode.cpp nodes/COM_SwitchNode.h + nodes/COM_SwitchViewNode.cpp + nodes/COM_SwitchViewNode.h nodes/COM_MovieClipNode.cpp nodes/COM_MovieClipNode.h nodes/COM_OutputFileNode.cpp @@ -370,6 +372,8 @@ set(SRC operations/COM_CompositorOperation.cpp operations/COM_OutputFileOperation.h operations/COM_OutputFileOperation.cpp + operations/COM_OutputFileMultiViewOperation.h + operations/COM_OutputFileMultiViewOperation.cpp operations/COM_ViewerOperation.h operations/COM_ViewerOperation.cpp operations/COM_PreviewOperation.h diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h index 9b22444cf7f..8b0a617f889 100644 --- a/source/blender/compositor/COM_compositor.h +++ b/source/blender/compositor/COM_compositor.h @@ -316,7 +316,8 @@ extern "C" { * generation in display space */ void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rendering, - const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings); + const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, + const char *viewName); /** * @brief Deinitialize the compositor caches and allocated memory. diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h index 3fbafa0a029..d7ec653f480 100644 --- a/source/blender/compositor/intern/COM_CompositorContext.h +++ b/source/blender/compositor/intern/COM_CompositorContext.h @@ -87,6 +87,11 @@ private: const ColorManagedViewSettings *m_viewSettings; const ColorManagedDisplaySettings *m_displaySettings; + /** + * @brief active rendering view name + */ + const char *m_viewName; + public: /** * @brief constructor initializes the context with default values. @@ -180,7 +185,17 @@ public: * @brief set has this system active openclDevices? */ void setHasActiveOpenCLDevices(bool hasAvtiveOpenCLDevices) { this->m_hasActiveOpenCLDevices = hasAvtiveOpenCLDevices; } - + + /** + * @brief get the active rendering view + */ + const char *getViewName() const { return this->m_viewName; } + + /** + * @brief set the active rendering view + */ + void setViewName(const char *viewName) { this->m_viewName = viewName; } + int getChunksize() const { return this->getbNodeTree()->chunksize; } void setFastCalculation(bool fastCalculation) {this->m_fastCalculation = fastCalculation;} diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 99f66bcb5b4..9de22612bdc 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -101,6 +101,7 @@ extern "C" { #include "COM_Stabilize2dNode.h" #include "COM_SunBeamsNode.h" #include "COM_SwitchNode.h" +#include "COM_SwitchViewNode.h" #include "COM_TextureNode.h" #include "COM_TimeNode.h" #include "COM_TonemapNode.h" @@ -328,6 +329,9 @@ Node *Converter::convert(bNode *b_node) case CMP_NODE_SWITCH: node = new SwitchNode(b_node); break; + case CMP_NODE_SWITCH_VIEW: + node = new SwitchViewNode(b_node); + break; case CMP_NODE_GLARE: node = new GlareNode(b_node); break; diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index 2ed9e6187ba..caeaa07d9f9 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -43,8 +43,10 @@ extern "C" { #endif ExecutionSystem::ExecutionSystem(RenderData *rd, Scene *scene, bNodeTree *editingtree, bool rendering, bool fastcalculation, - const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) + const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, + const char *viewName) { + this->m_context.setViewName(viewName); this->m_context.setScene(scene); this->m_context.setbNodeTree(editingtree); this->m_context.setPreviewHash(editingtree->previews); diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h index 555964f7b0c..41d63fb3a72 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.h +++ b/source/blender/compositor/intern/COM_ExecutionSystem.h @@ -151,7 +151,8 @@ public: * @param rendering [true false] */ ExecutionSystem(RenderData *rd, Scene *scene, bNodeTree *editingtree, bool rendering, bool fastcalculation, - const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings); + const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, + const char *viewName); /** * Destructor diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp index ff601e6f58e..7f7fc141aca 100644 --- a/source/blender/compositor/intern/COM_compositor.cpp +++ b/source/blender/compositor/intern/COM_compositor.cpp @@ -45,7 +45,8 @@ static void intern_freeCompositorCaches() void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rendering, const ColorManagedViewSettings *viewSettings, - const ColorManagedDisplaySettings *displaySettings) + const ColorManagedDisplaySettings *displaySettings, + const char *viewName) { /* initialize mutex, TODO this mutex init is actually not thread safe and * should be done somewhere as part of blender startup, all the other @@ -82,7 +83,7 @@ void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rende bool twopass = (editingtree->flag & NTREE_TWO_PASS) > 0 && !rendering; /* initialize execution system */ if (twopass) { - ExecutionSystem *system = new ExecutionSystem(rd, scene, editingtree, rendering, twopass, viewSettings, displaySettings); + ExecutionSystem *system = new ExecutionSystem(rd, scene, editingtree, rendering, twopass, viewSettings, displaySettings, viewName); system->execute(); delete system; @@ -95,7 +96,7 @@ void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rende } ExecutionSystem *system = new ExecutionSystem(rd, scene, editingtree, rendering, false, - viewSettings, displaySettings); + viewSettings, displaySettings, viewName); system->execute(); delete system; diff --git a/source/blender/compositor/nodes/COM_CompositorNode.cpp b/source/blender/compositor/nodes/COM_CompositorNode.cpp index 933b8d0282b..9e8b40d8af4 100644 --- a/source/blender/compositor/nodes/COM_CompositorNode.cpp +++ b/source/blender/compositor/nodes/COM_CompositorNode.cpp @@ -43,6 +43,7 @@ void CompositorNode::convertToOperations(NodeConverter &converter, const Composi CompositorOperation *compositorOperation = new CompositorOperation(); compositorOperation->setSceneName(context.getScene()->id.name); compositorOperation->setRenderData(context.getRenderData()); + compositorOperation->setViewName(context.getViewName()); compositorOperation->setbNodeTree(context.getbNodeTree()); /* alpha socket gives either 1 or a custom alpha value if "use alpha" is enabled */ compositorOperation->setUseAlphaInput(ignore_alpha || alphaSocket->isLinked()); diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp index cb7ccfaedf9..93ab6dd765a 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cpp +++ b/source/blender/compositor/nodes/COM_ImageNode.cpp @@ -40,19 +40,19 @@ ImageNode::ImageNode(bNode *editorNode) : Node(editorNode) } NodeOperation *ImageNode::doMultilayerCheck(NodeConverter &converter, RenderLayer *rl, Image *image, ImageUser *user, - int framenumber, int outputsocketIndex, int passindex, DataType datatype) const + int framenumber, int outputsocketIndex, int passtype, int view, DataType datatype) const { NodeOutput *outputSocket = this->getOutputSocket(outputsocketIndex); MultilayerBaseOperation *operation = NULL; switch (datatype) { case COM_DT_VALUE: - operation = new MultilayerValueOperation(passindex); + operation = new MultilayerValueOperation(passtype, view); break; case COM_DT_VECTOR: - operation = new MultilayerVectorOperation(passindex); + operation = new MultilayerVectorOperation(passtype, view); break; case COM_DT_COLOR: - operation = new MultilayerColorOperation(passindex); + operation = new MultilayerColorOperation(passtype, view); break; default: break; @@ -96,6 +96,10 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo NodeOperation *operation = NULL; socket = this->getOutputSocket(index); bNodeSocket *bnodeSocket = socket->getbNodeSocket(); + RenderPass *rpass = (RenderPass *)BLI_findstring(&rl->passes, bnodeSocket->identifier, offsetof(RenderPass, internal_name)); + + int view = (rpass ? rpass->view_id : 0); + /* Passes in the file can differ from passes stored in sockets (#36755). * Look up the correct file pass using the socket identifier instead. */ @@ -104,8 +108,22 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo int passindex = storage->pass_index;*/ RenderPass *rpass = (RenderPass *)BLI_findlink(&rl->passes, passindex); #endif - int passindex; - RenderPass *rpass; + + /* returns the image view to use for the current active view */ + if (BLI_listbase_count_ex(&image->rr->views, 2) > 1) { + const int view_image = imageuser->view; + const bool is_allview = (view_image == 0); /* if view selected == All (0) */ + + if (is_allview) { + /* heuristic to match image name with scene names + * check if the view name exists in the image */ + view = BLI_findstringindex(&image->rr->views, context.getViewName(), offsetof(RenderView, name)); + } + else { + view = view_image - 1; + } + } + if (STREQ(bnodeSocket->identifier, "Alpha")) { BLI_assert(combined_operation != NULL); NodeOutput *outputSocket = this->getOutputSocket(index); @@ -118,22 +136,21 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo operation = separate_operation; } else { - for (rpass = (RenderPass *)rl->passes.first, passindex = 0; rpass; rpass = rpass->next, ++passindex) - if (STREQ(rpass->name, bnodeSocket->identifier)) - break; if (rpass) { - imageuser->pass = passindex; switch (rpass->channels) { case 1: - operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, passindex, COM_DT_VALUE); + operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, + rpass->passtype, view, COM_DT_VALUE); break; /* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */ /* XXX any way to detect actual vector images? */ case 3: - operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, passindex, COM_DT_VECTOR); + operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, + rpass->passtype, view, COM_DT_VECTOR); break; case 4: - operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, passindex, COM_DT_COLOR); + operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, + rpass->passtype, view, COM_DT_COLOR); break; default: /* dummy operation is added below */ @@ -168,6 +185,8 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo operation->setImage(image); operation->setImageUser(imageuser); operation->setFramenumber(framenumber); + operation->setRenderData(context.getRenderData()); + operation->setViewName(context.getViewName()); converter.addOperation(operation); if (outputStraightAlpha) { @@ -190,6 +209,8 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo alphaOperation->setImage(image); alphaOperation->setImageUser(imageuser); alphaOperation->setFramenumber(framenumber); + alphaOperation->setRenderData(context.getRenderData()); + alphaOperation->setViewName(context.getViewName()); converter.addOperation(alphaOperation); converter.mapOutputSocket(alphaImage, alphaOperation->getOutputSocket()); @@ -200,6 +221,8 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo depthOperation->setImage(image); depthOperation->setImageUser(imageuser); depthOperation->setFramenumber(framenumber); + depthOperation->setRenderData(context.getRenderData()); + depthOperation->setViewName(context.getViewName()); converter.addOperation(depthOperation); converter.mapOutputSocket(depthImage, depthOperation->getOutputSocket()); @@ -239,6 +262,7 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo } if (operation) { + /* not supporting multiview for this generic case */ converter.addOperation(operation); converter.mapOutputSocket(output, operation->getOutputSocket()); } diff --git a/source/blender/compositor/nodes/COM_ImageNode.h b/source/blender/compositor/nodes/COM_ImageNode.h index 1daa39a2a1f..267794510e1 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.h +++ b/source/blender/compositor/nodes/COM_ImageNode.h @@ -36,7 +36,7 @@ extern "C" { class ImageNode : public Node { private: NodeOperation *doMultilayerCheck(NodeConverter &converter, RenderLayer *rl, Image *image, ImageUser *user, - int framenumber, int outputsocketIndex, int passindex, DataType datatype) const; + int framenumber, int outputsocketIndex, int passtype, int view, DataType datatype) const; public: ImageNode(bNode *editorNode); void convertToOperations(NodeConverter &converter, const CompositorContext &context) const; diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cpp b/source/blender/compositor/nodes/COM_OutputFileNode.cpp index 92fa74b9a2e..acd2602e216 100644 --- a/source/blender/compositor/nodes/COM_OutputFileNode.cpp +++ b/source/blender/compositor/nodes/COM_OutputFileNode.cpp @@ -23,8 +23,11 @@ #include "COM_OutputFileNode.h" #include "COM_OutputFileOperation.h" +#include "COM_OutputFileMultiViewOperation.h" #include "COM_ExecutionSystem.h" +#include "BKE_scene.h" + #include "BLI_path_util.h" OutputFileNode::OutputFileNode(bNode *editorNode) : Node(editorNode) @@ -35,6 +38,7 @@ OutputFileNode::OutputFileNode(bNode *editorNode) : Node(editorNode) void OutputFileNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const { NodeImageMultiFile *storage = (NodeImageMultiFile *)this->getbNode()->storage; + const bool is_multiview = (context.getRenderData()->scemode & R_MULTIVIEW) != 0; if (!context.isRendering()) { /* only output files when rendering a sequence - @@ -46,10 +50,18 @@ void OutputFileNode::convertToOperations(NodeConverter &converter, const Composi if (storage->format.imtype == R_IMF_IMTYPE_MULTILAYER) { /* single output operation for the multilayer file */ - OutputOpenExrMultiLayerOperation *outputOperation = new OutputOpenExrMultiLayerOperation( - context.getRenderData(), context.getbNodeTree(), storage->base_path, storage->format.exr_codec); + OutputOpenExrMultiLayerOperation *outputOperation; + + if (is_multiview && storage->format.views_format == R_IMF_VIEWS_MULTIVIEW) { + outputOperation = new OutputOpenExrMultiLayerMultiViewOperation( + context.getRenderData(), context.getbNodeTree(), storage->base_path, storage->format.exr_codec, context.getViewName()); + } + else { + outputOperation = new OutputOpenExrMultiLayerOperation( + context.getRenderData(), context.getbNodeTree(), storage->base_path, storage->format.exr_codec, context.getViewName()); + } converter.addOperation(outputOperation); - + int num_inputs = getNumberOfInputSockets(); bool previewAdded = false; for (int i = 0; i < num_inputs; ++i) { @@ -76,17 +88,31 @@ void OutputFileNode::convertToOperations(NodeConverter &converter, const Composi NodeImageMultiFileSocket *sockdata = (NodeImageMultiFileSocket *)input->getbNodeSocket()->storage; ImageFormatData *format = (sockdata->use_node_format ? &storage->format : &sockdata->format); char path[FILE_MAX]; - + /* combine file path for the input */ BLI_join_dirfile(path, FILE_MAX, storage->base_path, sockdata->path); - - OutputSingleLayerOperation *outputOperation = new OutputSingleLayerOperation( - context.getRenderData(), context.getbNodeTree(), input->getDataType(), format, path, - context.getViewSettings(), context.getDisplaySettings()); + + NodeOperation *outputOperation = NULL; + + if (is_multiview && format->views_format == R_IMF_VIEWS_MULTIVIEW) { + outputOperation = new OutputOpenExrSingleLayerMultiViewOperation( + context.getRenderData(), context.getbNodeTree(), input->getDataType(), format, path, + context.getViewSettings(), context.getDisplaySettings(), context.getViewName()); + } + else if ((!is_multiview) || (format->views_format == R_IMF_VIEWS_INDIVIDUAL)) { + outputOperation = new OutputSingleLayerOperation( + context.getRenderData(), context.getbNodeTree(), input->getDataType(), format, path, + context.getViewSettings(), context.getDisplaySettings(), context.getViewName()); + } + else { /* R_IMF_VIEWS_STEREO_3D */ + outputOperation = new OutputStereoOperation( + context.getRenderData(), context.getbNodeTree(), input->getDataType(), format, path, + sockdata->layer, context.getViewSettings(), context.getDisplaySettings(), context.getViewName()); + } + converter.addOperation(outputOperation); - converter.mapInputSocket(input, outputOperation->getInputSocket(0)); - + if (!previewAdded) { converter.addNodeInputPreview(input); previewAdded = true; diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp index cc66c688379..02bf1ec8cfb 100644 --- a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp +++ b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp @@ -42,7 +42,8 @@ void RenderLayersNode::testSocketLink(NodeConverter &converter, const Compositor operation->setScene(scene); operation->setLayerId(layerId); operation->setRenderData(context.getRenderData()); - + operation->setViewName(context.getViewName()); + converter.mapOutputSocket(outputSocket, operation->getOutputSocket()); converter.addOperation(operation); diff --git a/source/blender/compositor/nodes/COM_SplitViewerNode.cpp b/source/blender/compositor/nodes/COM_SplitViewerNode.cpp index 15eca0a97e5..0f917d317f9 100644 --- a/source/blender/compositor/nodes/COM_SplitViewerNode.cpp +++ b/source/blender/compositor/nodes/COM_SplitViewerNode.cpp @@ -22,6 +22,8 @@ #include "COM_SplitViewerNode.h" #include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_scene.h" #include "COM_SplitOperation.h" #include "COM_ViewerOperation.h" @@ -55,6 +57,8 @@ void SplitViewerNode::convertToOperations(NodeConverter &converter, const Compos viewerOperation->setImageUser(imageUser); viewerOperation->setViewSettings(context.getViewSettings()); viewerOperation->setDisplaySettings(context.getDisplaySettings()); + viewerOperation->setRenderData(context.getRenderData()); + viewerOperation->setViewName(context.getViewName()); /* defaults - the viewer node has these options but not exposed for split view * we could use the split to define an area of interest on one axis at least */ diff --git a/source/blender/compositor/nodes/COM_SwitchViewNode.cpp b/source/blender/compositor/nodes/COM_SwitchViewNode.cpp new file mode 100644 index 00000000000..5a23b8b4d9e --- /dev/null +++ b/source/blender/compositor/nodes/COM_SwitchViewNode.cpp @@ -0,0 +1,42 @@ +/* + * Copyright 2015, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Dalai Felinto + */ + +#include "COM_SwitchViewNode.h" +#include "BLI_listbase.h" + +SwitchViewNode::SwitchViewNode(bNode *editorNode) : Node(editorNode) +{ + /* pass */ +} + +void SwitchViewNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const +{ + NodeOperationOutput *result; + const char *viewName = context.getViewName(); + bNode *bnode = this->getbNode(); + + /* get the internal index of the socket with a matching name */ + int nr = BLI_findstringindex(&bnode->inputs, viewName, offsetof(bNodeSocket, name)); + nr = max(nr, 0); + + result = converter.addInputProxy(getInputSocket(nr), false); + converter.mapOutputSocket(getOutputSocket(0), result); +} diff --git a/source/blender/compositor/nodes/COM_SwitchViewNode.h b/source/blender/compositor/nodes/COM_SwitchViewNode.h new file mode 100644 index 00000000000..6ab5145bed5 --- /dev/null +++ b/source/blender/compositor/nodes/COM_SwitchViewNode.h @@ -0,0 +1,37 @@ +/* + * Copyright 2015, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Dalai Felinto + */ + +#ifndef _COM_SwitchViewNode_h_ +#define _COM_SwitchViewNode_h_ + +#include "COM_Node.h" +#include "COM_NodeOperation.h" +#include "DNA_node_types.h" +/** + * @brief SwitchViewNode + * @ingroup Node + */ +class SwitchViewNode : public Node { +public: + SwitchViewNode(bNode *editorNode); + void convertToOperations(NodeConverter &converter, const CompositorContext &context) const; +}; +#endif diff --git a/source/blender/compositor/nodes/COM_ViewerNode.cpp b/source/blender/compositor/nodes/COM_ViewerNode.cpp index ff0b8fb1706..ab819ce6e30 100644 --- a/source/blender/compositor/nodes/COM_ViewerNode.cpp +++ b/source/blender/compositor/nodes/COM_ViewerNode.cpp @@ -22,6 +22,9 @@ #include "COM_ViewerNode.h" #include "BKE_global.h" +#include "BKE_image.h" +#include "BLI_listbase.h" +#include "BKE_scene.h" #include "COM_ViewerOperation.h" #include "COM_ExecutionSystem.h" @@ -51,6 +54,8 @@ void ViewerNode::convertToOperations(NodeConverter &converter, const CompositorC viewerOperation->setCenterY(editorNode->custom4); /* alpha socket gives either 1 or a custom alpha value if "use alpha" is enabled */ viewerOperation->setUseAlphaInput(ignore_alpha || alphaSocket->isLinked()); + viewerOperation->setRenderData(context.getRenderData()); + viewerOperation->setViewName(context.getViewName()); viewerOperation->setViewSettings(context.getViewSettings()); viewerOperation->setDisplaySettings(context.getDisplaySettings()); diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp index ffef81d0323..eacbdf91be2 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.cpp +++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp @@ -52,6 +52,7 @@ CompositorOperation::CompositorOperation() : NodeOperation() this->m_active = false; this->m_sceneName[0] = '\0'; + this->m_viewName = NULL; } void CompositorOperation::initExecution() @@ -81,14 +82,16 @@ void CompositorOperation::deinitExecution() RenderResult *rr = RE_AcquireResultWrite(re); if (rr) { - if (rr->rectf != NULL) { - MEM_freeN(rr->rectf); + RenderView *rv = (RenderView *)BLI_findstring(&rr->views, this->m_viewName, offsetof(RenderView, name)); + + if (rv->rectf != NULL) { + MEM_freeN(rv->rectf); } - rr->rectf = this->m_outputBuffer; - if (rr->rectz != NULL) { - MEM_freeN(rr->rectz); + rv->rectf = this->m_outputBuffer; + if (rv->rectz != NULL) { + MEM_freeN(rv->rectz); } - rr->rectz = this->m_depthBuffer; + rv->rectz = this->m_depthBuffer; } else { if (this->m_outputBuffer) { diff --git a/source/blender/compositor/operations/COM_CompositorOperation.h b/source/blender/compositor/operations/COM_CompositorOperation.h index 447d74131b3..e81ba520695 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.h +++ b/source/blender/compositor/operations/COM_CompositorOperation.h @@ -75,11 +75,17 @@ private: * @brief operation is active for calculating final compo result */ bool m_active; + + /** + * @brief View name, used for multiview + */ + const char *m_viewName; public: CompositorOperation(); const bool isActiveCompositorOutput() const { return this->m_active; } void executeRegion(rcti *rect, unsigned int tileNumber); void setSceneName(const char *sceneName) { BLI_strncpy(this->m_sceneName, sceneName, sizeof(this->m_sceneName)); } + void setViewName(const char *viewName) { this->m_viewName = viewName; } void setRenderData(const RenderData *rd) { this->m_rd = rd; } bool isOutputOperation(bool /*rendering*/) const { return this->isActiveCompositorOutput(); } void initExecution(); diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp index 624fdf8b626..c140b7afbd7 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.cpp +++ b/source/blender/compositor/operations/COM_ImageOperation.cpp @@ -25,6 +25,7 @@ #include "BLI_listbase.h" #include "DNA_image_types.h" #include "BKE_image.h" +#include "BKE_scene.h" #include "BLI_math.h" extern "C" { @@ -48,6 +49,8 @@ BaseImageOperation::BaseImageOperation() : NodeOperation() this->m_framenumber = 0; this->m_depthBuffer = NULL; this->m_numberOfChannels = 0; + this->m_rd = NULL; + this->m_viewName = NULL; } ImageOperation::ImageOperation() : BaseImageOperation() { @@ -65,8 +68,12 @@ ImageDepthOperation::ImageDepthOperation() : BaseImageOperation() ImBuf *BaseImageOperation::getImBuf() { ImBuf *ibuf; - - ibuf = BKE_image_acquire_ibuf(this->m_image, this->m_imageUser, NULL); + ImageUser iuser = *this->m_imageUser; + + /* local changes to the original ImageUser */ + iuser.multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName); + + ibuf = BKE_image_acquire_ibuf(this->m_image, &iuser, NULL); if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) { BKE_image_release_ibuf(this->m_image, ibuf, NULL); return NULL; diff --git a/source/blender/compositor/operations/COM_ImageOperation.h b/source/blender/compositor/operations/COM_ImageOperation.h index 206f1509f60..75222559810 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.h +++ b/source/blender/compositor/operations/COM_ImageOperation.h @@ -49,7 +49,9 @@ protected: int m_imagewidth; int m_framenumber; int m_numberOfChannels; - + const RenderData *m_rd; + const char *m_viewName; + BaseImageOperation(); /** * Determine the output resolution. The resolution is retrieved from the Renderer @@ -64,7 +66,8 @@ public: void deinitExecution(); void setImage(Image *image) { this->m_image = image; } void setImageUser(ImageUser *imageuser) { this->m_imageUser = imageuser; } - + void setRenderData(const RenderData *rd) { this->m_rd = rd; } + void setViewName(const char *viewName) { this->m_viewName = viewName; } void setFramenumber(int framenumber) { this->m_framenumber = framenumber; } }; class ImageOperation : public BaseImageOperation { diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp index 513140e2f62..00be3b1cdde 100644 --- a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp +++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp @@ -27,18 +27,27 @@ extern "C" { # include "IMB_imbuf_types.h" } -MultilayerBaseOperation::MultilayerBaseOperation(int passindex) : BaseImageOperation() +MultilayerBaseOperation::MultilayerBaseOperation(int passtype, int view) : BaseImageOperation() { - this->m_passId = passindex; + this->m_passtype = passtype; + this->m_view = view; } + ImBuf *MultilayerBaseOperation::getImBuf() { - RenderPass *rpass = (RenderPass *)BLI_findlink(&this->m_renderlayer->passes, this->m_passId); - if (rpass) { - this->m_imageUser->pass = m_passId; - BKE_image_multilayer_index(this->m_image->rr, this->m_imageUser); - return BaseImageOperation::getImBuf(); + /* temporarily changes the view to get the right ImBuf */ + int view = this->m_imageUser->view; + + this->m_imageUser->view = this->m_view; + this->m_imageUser->passtype = this->m_passtype; + + if (BKE_image_multilayer_index(this->m_image->rr, this->m_imageUser)) { + ImBuf *ibuf = BaseImageOperation::getImBuf(); + this->m_imageUser->view = view; + return ibuf; } + + this->m_imageUser->view = view; return NULL; } diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.h b/source/blender/compositor/operations/COM_MultilayerImageOperation.h index 37bee1b6a8c..2e140577d74 100644 --- a/source/blender/compositor/operations/COM_MultilayerImageOperation.h +++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.h @@ -29,7 +29,8 @@ class MultilayerBaseOperation : public BaseImageOperation { private: - int m_passId; + int m_passtype; + int m_view; RenderLayer *m_renderlayer; protected: ImBuf *getImBuf(); @@ -37,13 +38,13 @@ public: /** * Constructor */ - MultilayerBaseOperation(int passindex); + MultilayerBaseOperation(int passtype, int view); void setRenderLayer(RenderLayer *renderlayer) { this->m_renderlayer = renderlayer; } }; class MultilayerColorOperation : public MultilayerBaseOperation { public: - MultilayerColorOperation(int passindex) : MultilayerBaseOperation(passindex) { + MultilayerColorOperation(int passtype, int view) : MultilayerBaseOperation(passtype, view) { this->addOutputSocket(COM_DT_COLOR); } void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); @@ -51,7 +52,7 @@ public: class MultilayerValueOperation : public MultilayerBaseOperation { public: - MultilayerValueOperation(int passindex) : MultilayerBaseOperation(passindex) { + MultilayerValueOperation(int passtype, int view) : MultilayerBaseOperation(passtype, view) { this->addOutputSocket(COM_DT_VALUE); } void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); @@ -59,7 +60,7 @@ public: class MultilayerVectorOperation : public MultilayerBaseOperation { public: - MultilayerVectorOperation(int passindex) : MultilayerBaseOperation(passindex) { + MultilayerVectorOperation(int passtype, int view) : MultilayerBaseOperation(passtype, view) { this->addOutputSocket(COM_DT_VECTOR); } void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp new file mode 100644 index 00000000000..c927dfa89a1 --- /dev/null +++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp @@ -0,0 +1,317 @@ +/* + * Copyright 2015, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Lukas Tönne + * Dalai Felinto + */ + +#include "COM_OutputFileOperation.h" +#include "COM_OutputFileMultiViewOperation.h" + +#include +#include "BLI_listbase.h" +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BKE_image.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_scene.h" + +#include "DNA_color_types.h" +#include "MEM_guardedalloc.h" + +extern "C" { +#include "IMB_imbuf.h" +#include "IMB_colormanagement.h" +#include "IMB_imbuf_types.h" +} + +/************************************ OpenEXR Singlelayer Multiview *****************************************/ + +OutputOpenExrSingleLayerMultiViewOperation::OutputOpenExrSingleLayerMultiViewOperation( + const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path, + const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, + const char *viewName) + : OutputSingleLayerOperation(rd, tree, datatype, format, path, viewSettings, displaySettings, viewName) +{ +} + +void *OutputOpenExrSingleLayerMultiViewOperation::get_handle(const char *filename) +{ + size_t width = this->getWidth(); + size_t height = this->getHeight(); + SceneRenderView *srv; + + if (width != 0 && height != 0) { + void *exrhandle; + + exrhandle = IMB_exr_get_handle_name(filename); + + if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName)) + return exrhandle; + + IMB_exr_clear_channels(exrhandle); + + for (srv = (SceneRenderView *)this->m_rd->views.first; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(this->m_rd, srv) == false) + continue; + + IMB_exr_add_view(exrhandle, srv->name); + add_exr_channels(exrhandle, NULL, this->m_datatype, srv->name, width, NULL); + } + + BLI_make_existing_file(filename); + + /* prepare the file with all the channels */ + + if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_format->exr_codec) == 0) { + printf("Error Writing Singlelayer Multiview Openexr\n"); + IMB_exr_close(exrhandle); + } + else { + IMB_exr_clear_channels(exrhandle); + return exrhandle; + } + } + return NULL; +} + +void OutputOpenExrSingleLayerMultiViewOperation::deinitExecution() +{ + unsigned int width = this->getWidth(); + unsigned int height = this->getHeight(); + + if (width != 0 && height != 0) { + void *exrhandle; + Main *bmain = G.main; /* TODO, have this passed along */ + char filename[FILE_MAX]; + + BKE_image_path_from_imtype( + filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_OPENEXR, + (this->m_rd->scemode & R_EXTENSION) != 0, true, NULL); + + exrhandle = this->get_handle(filename); + add_exr_channels(exrhandle, NULL, this->m_datatype, this->m_viewName, width, this->m_outputBuffer); + + /* memory can only be freed after we write all views to the file */ + this->m_outputBuffer = NULL; + this->m_imageInput = NULL; + + /* ready to close the file */ + if (BKE_scene_multiview_is_render_view_last(this->m_rd, this->m_viewName)) { + IMB_exr_write_channels(exrhandle); + + /* free buffer memory for all the views */ + free_exr_channels(exrhandle, this->m_rd, NULL, this->m_datatype); + + /* remove exr handle and data */ + IMB_exr_close(exrhandle); + } + } +} + +/************************************ OpenEXR Multilayer Multiview *****************************************/ + +OutputOpenExrMultiLayerMultiViewOperation::OutputOpenExrMultiLayerMultiViewOperation( + const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec, const char *viewName) + : OutputOpenExrMultiLayerOperation(rd, tree, path, exr_codec, viewName) +{ +} + +void *OutputOpenExrMultiLayerMultiViewOperation::get_handle(const char *filename) +{ + unsigned int width = this->getWidth(); + unsigned int height = this->getHeight(); + + if (width != 0 && height != 0) { + + void *exrhandle; + SceneRenderView *srv; + + /* get a new global handle */ + exrhandle = IMB_exr_get_handle_name(filename); + + if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName)) + return exrhandle; + + IMB_exr_clear_channels(exrhandle); + + /* check renderdata for amount of views */ + for (srv = (SceneRenderView *) this->m_rd->views.first; srv; srv = srv->next) { + + if (BKE_scene_multiview_is_render_view_active(this->m_rd, srv) == false) + continue; + + IMB_exr_add_view(exrhandle, srv->name); + + for (unsigned int i = 0; i < this->m_layers.size(); ++i) + add_exr_channels(exrhandle, this->m_layers[i].name, this->m_layers[i].datatype, srv->name, width, NULL); + } + + BLI_make_existing_file(filename); + + /* prepare the file with all the channels for the header */ + if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec) == 0) { + printf("Error Writing Multilayer Multiview Openexr\n"); + IMB_exr_close(exrhandle); + } + else { + IMB_exr_clear_channels(exrhandle); + return exrhandle; + } + } + return NULL; +} + +void OutputOpenExrMultiLayerMultiViewOperation::deinitExecution() +{ + unsigned int width = this->getWidth(); + unsigned int height = this->getHeight(); + + if (width != 0 && height != 0) { + void *exrhandle; + Main *bmain = G.main; /* TODO, have this passed along */ + char filename[FILE_MAX]; + + BKE_image_path_from_imtype( + filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER, + (this->m_rd->scemode & R_EXTENSION) != 0, true, NULL); + + exrhandle = this->get_handle(filename); + + for (unsigned int i = 0; i < this->m_layers.size(); ++i) + add_exr_channels(exrhandle, this->m_layers[i].name, this->m_layers[i].datatype, this->m_viewName, width, this->m_layers[i].outputBuffer); + + for (unsigned int i = 0; i < this->m_layers.size(); ++i) { + /* memory can only be freed after we write all views to the file */ + this->m_layers[i].outputBuffer = NULL; + this->m_layers[i].imageInput = NULL; + } + + /* ready to close the file */ + if (BKE_scene_multiview_is_render_view_last(this->m_rd, this->m_viewName)) { + IMB_exr_write_channels(exrhandle); + + /* free buffer memory for all the views */ + for (unsigned int i = 0; i < this->m_layers.size(); ++i) { + free_exr_channels(exrhandle, this->m_rd, this->m_layers[i].name, this->m_layers[i].datatype); + } + + IMB_exr_close(exrhandle); + } + } +} + + +/******************************** Stereo3D ******************************/ + +OutputStereoOperation::OutputStereoOperation( + const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path, + const char *name, const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, + const char *viewName) + : OutputSingleLayerOperation(rd, tree, datatype, format, path, viewSettings, displaySettings, viewName) +{ + BLI_strncpy(this->m_name, name, sizeof(this->m_name)); + this->m_channels = get_datatype_size(datatype); +} + +void *OutputStereoOperation::get_handle(const char *filename) +{ + size_t width = this->getWidth(); + size_t height = this->getHeight(); + const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + size_t i; + + if (width != 0 && height != 0) { + void *exrhandle; + + exrhandle = IMB_exr_get_handle_name(filename); + + if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName)) + return exrhandle; + + IMB_exr_clear_channels(exrhandle); + + for (i = 0; i < 2; i++) + IMB_exr_add_view(exrhandle, names[i]); + + return exrhandle; + } + return NULL; +} + +void OutputStereoOperation::deinitExecution() +{ + unsigned int width = this->getWidth(); + unsigned int height = this->getHeight(); + + if (width != 0 && height != 0) { + void *exrhandle; + + exrhandle = this->get_handle(this->m_path); + float *buf = this->m_outputBuffer; + + /* populate single EXR channel with view data */ + IMB_exr_add_channel(exrhandle, NULL, this->m_name, this->m_viewName, 1, this->m_channels * width * height, buf); + + this->m_imageInput = NULL; + this->m_outputBuffer = NULL; + + /* create stereo ibuf */ + if (BKE_scene_multiview_is_render_view_last(this->m_rd, this->m_viewName)) { + ImBuf *ibuf[3] = {NULL}; + const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + Main *bmain = G.main; /* TODO, have this passed along */ + char filename[FILE_MAX]; + int i; + + /* get rectf from EXR */ + for (i = 0; i < 2; i++) { + float *rectf = IMB_exr_channel_rect(exrhandle, NULL, this->m_name, names[i]); + ibuf[i] = IMB_allocImBuf(width, height, this->m_format->planes, 0); + + ibuf[i]->channels = this->m_channels; + ibuf[i]->rect_float = rectf; + ibuf[i]->mall |= IB_rectfloat; + ibuf[i]->dither = this->m_rd->dither_intensity; + + /* do colormanagement in the individual views, so it doesn't need to do in the stereo */ + IMB_colormanagement_imbuf_for_write(ibuf[i], true, false, this->m_viewSettings, + this->m_displaySettings, this->m_format); + IMB_prepare_write_ImBuf(IMB_isfloat(ibuf[i]), ibuf[i]); + } + + /* create stereo buffer */ + ibuf[2] = IMB_stereo3d_ImBuf(this->m_format, ibuf[0], ibuf[1]); + + BKE_image_path_from_imformat( + filename, this->m_path, bmain->name, this->m_rd->cfra, this->m_format, + (this->m_rd->scemode & R_EXTENSION) != 0, true, NULL); + + BKE_imbuf_write(ibuf[2], filename, this->m_format); + + /* imbuf knows which rects are not part of ibuf */ + for (i = 0; i < 3; i++) + IMB_freeImBuf(ibuf[i]); + + IMB_exr_close(exrhandle); + } + } +} diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h new file mode 100644 index 00000000000..25716fdb9e1 --- /dev/null +++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h @@ -0,0 +1,74 @@ +/* + * Copyright 2015, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Lukas Tönne + * Dalai Felinto + */ + +#ifndef _COM_OutputFileMultiViewOperation_h +#define _COM_OutputFileMultiViewOperation_h +#include "COM_NodeOperation.h" + +#include "BLI_rect.h" +#include "BLI_path_util.h" + +#include "DNA_color_types.h" +#include "DNA_userdef_types.h" + +#include "intern/openexr/openexr_multi.h" + +class OutputOpenExrSingleLayerMultiViewOperation : public OutputSingleLayerOperation { +private: +public: + OutputOpenExrSingleLayerMultiViewOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype, + ImageFormatData *format, const char *path, + const ColorManagedViewSettings *viewSettings, + const ColorManagedDisplaySettings *displaySettings, + const char *viewName); + + void *get_handle(const char *filename); + void deinitExecution(); +}; + +/* Writes inputs into OpenEXR multilayer channels. */ +class OutputOpenExrMultiLayerMultiViewOperation : public OutputOpenExrMultiLayerOperation { +private: +public: + OutputOpenExrMultiLayerMultiViewOperation(const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec, const char *viewName); + + void *get_handle(const char *filename); + void deinitExecution(); +}; + +/**/ +class OutputStereoOperation : public OutputSingleLayerOperation { +private: + char m_name[FILE_MAX]; + size_t m_channels; +public: + OutputStereoOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype, + struct ImageFormatData *format, const char *path, const char *name, + const ColorManagedViewSettings *viewSettings, + const ColorManagedDisplaySettings *displaySettings, const char *viewName); + void *get_handle(const char *filename); + void deinitExecution(); +}; + +#endif diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp index b1c90a6355f..1a7a356f5b4 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp +++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp @@ -29,6 +29,7 @@ #include "BKE_image.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_scene.h" #include "DNA_color_types.h" @@ -39,7 +40,60 @@ extern "C" { # include "IMB_imbuf_types.h" } -static int get_datatype_size(DataType datatype) +void add_exr_channels(void *exrhandle, const char *layerName, const DataType datatype, const char *viewName, const size_t width, float *buf) +{ + /* create channels */ + switch (datatype) { + case COM_DT_VALUE: + IMB_exr_add_channel(exrhandle, layerName, "V", viewName, 1, width, buf ? buf : NULL); + break; + case COM_DT_VECTOR: + IMB_exr_add_channel(exrhandle, layerName, "X", viewName, 3, 3 * width, buf ? buf : NULL); + IMB_exr_add_channel(exrhandle, layerName, "Y", viewName, 3, 3 * width, buf ? buf + 1 : NULL); + IMB_exr_add_channel(exrhandle, layerName, "Z", viewName, 3, 3 * width, buf ? buf + 2 : NULL); + break; + case COM_DT_COLOR: + IMB_exr_add_channel(exrhandle, layerName, "R", viewName, 4, 4 * width, buf ? buf : NULL); + IMB_exr_add_channel(exrhandle, layerName, "G", viewName, 4, 4 * width, buf ? buf + 1 : NULL); + IMB_exr_add_channel(exrhandle, layerName, "B", viewName, 4, 4 * width, buf ? buf + 2 : NULL); + IMB_exr_add_channel(exrhandle, layerName, "A", viewName, 4, 4 * width, buf ? buf + 3 : NULL); + break; + default: + break; + } +} + +void free_exr_channels(void *exrhandle, const RenderData *rd, const char *layerName, const DataType datatype) +{ + SceneRenderView *srv; + + /* check renderdata for amount of views */ + for (srv = (SceneRenderView *) rd->views.first; srv; srv = srv->next) { + float *rect = NULL; + + if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) + continue; + + /* the pointer is stored in the first channel of each datatype */ + switch (datatype) { + case COM_DT_VALUE: + rect = IMB_exr_channel_rect(exrhandle, layerName, "V", srv->name); + break; + case COM_DT_VECTOR: + rect = IMB_exr_channel_rect(exrhandle, layerName, "X", srv->name); + break; + case COM_DT_COLOR: + rect = IMB_exr_channel_rect(exrhandle, layerName, "R", srv->name); + break; + default: + break; + } + if (rect) + MEM_freeN(rect); + } +} + +int get_datatype_size(DataType datatype) { switch (datatype) { case COM_DT_VALUE: return 1; @@ -94,7 +148,7 @@ static void write_buffer_rect(rcti *rect, const bNodeTree *tree, OutputSingleLayerOperation::OutputSingleLayerOperation( const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path, - const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) + const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, const char *viewName) { this->m_rd = rd; this->m_tree = tree; @@ -110,6 +164,7 @@ OutputSingleLayerOperation::OutputSingleLayerOperation( this->m_viewSettings = viewSettings; this->m_displaySettings = displaySettings; + this->m_viewName = viewName; } void OutputSingleLayerOperation::initExecution() @@ -131,6 +186,7 @@ void OutputSingleLayerOperation::deinitExecution() ImBuf *ibuf = IMB_allocImBuf(this->getWidth(), this->getHeight(), this->m_format->planes, 0); Main *bmain = G.main; /* TODO, have this passed along */ char filename[FILE_MAX]; + const char *suffix; ibuf->channels = size; ibuf->rect_float = this->m_outputBuffer; @@ -140,10 +196,12 @@ void OutputSingleLayerOperation::deinitExecution() IMB_colormanagement_imbuf_for_write(ibuf, true, false, m_viewSettings, m_displaySettings, this->m_format); + suffix = BKE_scene_multiview_view_suffix_get(this->m_rd, this->m_viewName); + BKE_image_path_from_imformat( - filename, this->m_path, bmain->name, this->m_rd->cfra, - this->m_format, (this->m_rd->scemode & R_EXTENSION) != 0, true); - + filename, this->m_path, bmain->name, this->m_rd->cfra, this->m_format, + (this->m_rd->scemode & R_EXTENSION) != 0, true, suffix); + if (0 == BKE_imbuf_write(ibuf, filename, this->m_format)) printf("Cannot save Node File Output to %s\n", filename); else @@ -155,6 +213,7 @@ void OutputSingleLayerOperation::deinitExecution() this->m_imageInput = NULL; } +/******************************* MultiLayer *******************************/ OutputOpenExrLayer::OutputOpenExrLayer(const char *name_, DataType datatype_, bool use_layer_) { @@ -168,13 +227,14 @@ OutputOpenExrLayer::OutputOpenExrLayer(const char *name_, DataType datatype_, bo } OutputOpenExrMultiLayerOperation::OutputOpenExrMultiLayerOperation( - const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec) + const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec, const char *viewName) { this->m_rd = rd; this->m_tree = tree; BLI_strncpy(this->m_path, path, sizeof(this->m_path)); this->m_exr_codec = exr_codec; + this->m_viewName = viewName; } void OutputOpenExrMultiLayerOperation::add_layer(const char *name, DataType datatype, bool use_layer) @@ -210,52 +270,21 @@ void OutputOpenExrMultiLayerOperation::deinitExecution() if (width != 0 && height != 0) { Main *bmain = G.main; /* TODO, have this passed along */ char filename[FILE_MAX]; + const char *suffix; void *exrhandle = IMB_exr_get_handle(); - + + suffix = BKE_scene_multiview_view_suffix_get(this->m_rd, this->m_viewName); BKE_image_path_from_imtype( filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER, - (this->m_rd->scemode & R_EXTENSION) != 0, true); + (this->m_rd->scemode & R_EXTENSION) != 0, true, suffix); BLI_make_existing_file(filename); - + for (unsigned int i = 0; i < this->m_layers.size(); ++i) { OutputOpenExrLayer &layer = this->m_layers[i]; if (!layer.imageInput) continue; /* skip unconnected sockets */ - char channelname[EXR_TOT_MAXNAME]; - BLI_strncpy(channelname, this->m_layers[i].name, sizeof(channelname) - 2); - char *channelname_ext = channelname + strlen(channelname); - - float *buf = this->m_layers[i].outputBuffer; - - /* create channels */ - switch (this->m_layers[i].datatype) { - case COM_DT_VALUE: - strcpy(channelname_ext, ".V"); - IMB_exr_add_channel(exrhandle, 0, channelname, 1, width, buf); - break; - case COM_DT_VECTOR: - strcpy(channelname_ext, ".X"); - IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3 * width, buf); - strcpy(channelname_ext, ".Y"); - IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3 * width, buf + 1); - strcpy(channelname_ext, ".Z"); - IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3 * width, buf + 2); - break; - case COM_DT_COLOR: - strcpy(channelname_ext, ".R"); - IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf); - strcpy(channelname_ext, ".G"); - IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf + 1); - strcpy(channelname_ext, ".B"); - IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf + 2); - strcpy(channelname_ext, ".A"); - IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf + 3); - break; - default: - break; - } - + add_exr_channels(exrhandle, this->m_layers[i].name, this->m_layers[i].datatype, "", width, this->m_layers[i].outputBuffer); } /* when the filename has no permissions, this can fail */ @@ -279,3 +308,4 @@ void OutputOpenExrMultiLayerOperation::deinitExecution() } } } + diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h index af16f186d9d..58ebf055583 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.h +++ b/source/blender/compositor/operations/COM_OutputFileOperation.h @@ -34,7 +34,7 @@ /* Writes the image to a single-layer file. */ class OutputSingleLayerOperation : public NodeOperation { -private: +protected: const RenderData *m_rd; const bNodeTree *m_tree; @@ -47,9 +47,11 @@ private: const ColorManagedViewSettings *m_viewSettings; const ColorManagedDisplaySettings *m_displaySettings; + + const char *m_viewName; public: OutputSingleLayerOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path, - const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings); + const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, const char *viewName); void executeRegion(rcti *rect, unsigned int tileNumber); bool isOutputOperation(bool /*rendering*/) const { return true; } @@ -75,7 +77,7 @@ struct OutputOpenExrLayer { /* Writes inputs into OpenEXR multilayer channels. */ class OutputOpenExrMultiLayerOperation : public NodeOperation { -private: +protected: typedef std::vector LayerList; const RenderData *m_rd; @@ -84,9 +86,10 @@ private: char m_path[FILE_MAX]; char m_exr_codec; LayerList m_layers; + const char *m_viewName; public: - OutputOpenExrMultiLayerOperation(const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec); + OutputOpenExrMultiLayerOperation(const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec, const char *viewName); void add_layer(const char *name, DataType datatype, bool use_layer); @@ -99,4 +102,8 @@ public: bool isFileOutputOperation() const { return true; } }; +void add_exr_channels(void *exrhandle, const char *layerName, const DataType datatype, const char *viewName, const size_t width, float *buf); +void free_exr_channels(void *exrhandle, const RenderData *rd, const char *layerName, const DataType datatype); +int get_datatype_size(DataType datatype); + #endif diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp index defbc2ab57f..af176a766ff 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp +++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp @@ -23,6 +23,7 @@ #include "COM_RenderLayersProg.h" #include "BLI_listbase.h" +#include "BKE_scene.h" #include "DNA_scene_types.h" extern "C" { @@ -57,11 +58,10 @@ void RenderLayersBaseProg::initExecution() if (srl) { RenderLayer *rl = RE_GetRenderLayer(rr, srl->name); - if (rl && rl->rectf) { - this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_renderpass); - + if (rl) { + this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_renderpass, this->m_viewName); if (this->m_inputBuffer == NULL && this->m_renderpass == SCE_PASS_COMBINED) { - this->m_inputBuffer = rl->rectf; + this->m_inputBuffer = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, this->m_viewName); } } } @@ -195,7 +195,7 @@ void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsig SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&sce->r.layers, getLayerId()); if (srl) { RenderLayer *rl = RE_GetRenderLayer(rr, srl->name); - if (rl && rl->rectf) { + if (rl) { resolution[0] = rl->rectx; resolution[1] = rl->recty; } diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h index f73d9de3e27..2ddbc968c01 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.h +++ b/source/blender/compositor/operations/COM_RenderLayersProg.h @@ -51,7 +51,12 @@ private: * layerId of the layer where this operation needs to get its data from */ short m_layerId; - + + /** + * viewName of the view to use (unless another view is specified by the node + */ + const char *m_viewName; + /** * cached instance to the float buffer inside the layer */ @@ -97,6 +102,8 @@ public: void setRenderData(const RenderData *rd) { this->m_rd = rd; } void setLayerId(short layerId) { this->m_layerId = layerId; } short getLayerId() { return this->m_layerId; } + void setViewName(const char *viewName) { this->m_viewName = viewName; } + const char *getViewName() { return this->m_viewName; } void initExecution(); void deinitExecution(); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp index da2706a2244..96ee5ecbb03 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp @@ -23,6 +23,7 @@ #include "COM_ViewerOperation.h" #include "BLI_listbase.h" #include "BKE_image.h" +#include "BKE_scene.h" #include "WM_api.h" #include "WM_types.h" #include "PIL_time.h" @@ -57,6 +58,8 @@ ViewerOperation::ViewerOperation() : NodeOperation() this->m_imageInput = NULL; this->m_alphaInput = NULL; this->m_depthInput = NULL; + this->m_rd = NULL; + this->m_viewName = NULL; } void ViewerOperation::initExecution() @@ -123,8 +126,18 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/) void ViewerOperation::initImage() { Image *ima = this->m_image; + ImageUser iuser = *this->m_imageUser; void *lock; - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, this->m_imageUser, &lock); + ImBuf *ibuf; + + /* make sure the image has the correct number of views */ + if (ima && BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName)) { + BKE_image_verify_viewer_views(this->m_rd, ima, this->m_imageUser); + } + + /* local changes to the original ImageUser */ + iuser.multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName); + ibuf = BKE_image_acquire_ibuf(ima, &iuser, &lock); if (!ibuf) return; BLI_lock_thread(LOCK_DRAW_IMAGE); diff --git a/source/blender/compositor/operations/COM_ViewerOperation.h b/source/blender/compositor/operations/COM_ViewerOperation.h index a17375c2de9..107aee3a82f 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.h +++ b/source/blender/compositor/operations/COM_ViewerOperation.h @@ -40,7 +40,9 @@ private: bool m_doDepthBuffer; ImBuf *m_ibuf; bool m_useAlphaInput; - + const RenderData *m_rd; + const char *m_viewName; + const ColorManagedViewSettings *m_viewSettings; const ColorManagedDisplaySettings *m_displaySettings; @@ -67,6 +69,8 @@ public: const CompositorPriority getRenderPriority() const; bool isViewerOperation() const { return true; } void setUseAlphaInput(bool value) { this->m_useAlphaInput = value; } + void setRenderData(const RenderData *rd) { this->m_rd = rd; } + void setViewName(const char *viewName) { this->m_viewName = viewName; } void setViewSettings(const ColorManagedViewSettings *viewSettings) { this->m_viewSettings = viewSettings; } void setDisplaySettings(const ColorManagedDisplaySettings *displaySettings) { this->m_displaySettings = displaySettings; } diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index b4f7d806079..90b0b3510bc 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -112,6 +112,7 @@ void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa); void ED_screen_full_restore(struct bContext *C, ScrArea *sa); struct ScrArea *ED_screen_state_toggle(struct bContext *C, struct wmWindow *win, struct ScrArea *sa, const short state); void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg); +bool ED_screen_stereo3d_required(struct bScreen *screen); /* anim */ void ED_update_for_newframe(struct Main *bmain, struct Scene *scene, int mute); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 84ac3a7c938..ff4b8a5b631 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -323,12 +323,13 @@ void ED_view3d_draw_offscreen( struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int winx, int winy, float viewmat[4][4], float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp, struct GPUOffScreen *ofs, - struct GPUFX *fx, struct GPUFXSettings *fx_settings); + struct GPUFX *fx, struct GPUFXSettings *fx_settings, + const char *viewname); struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag, - bool draw_background, int alpha_mode, char err_out[256]); + bool draw_background, int alpha_mode, const char *viewname, char err_out[256]); struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype, - bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, char err_out[256]); + bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, const char *viewname, char err_out[256]); struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]); void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 814bbf94c79..4ca0be7c80d 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -889,6 +889,9 @@ void uiTemplateGameStates(uiLayout *layout, struct PointerRNA *ptr, const char * PointerRNA *used_ptr, const char *used_propname, int active_state); void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr, int compact); void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr, int color_management); +void uiTemplateImageStereo3d(uiLayout *layout, struct PointerRNA *stereo3d_format_ptr); +void uiTemplateImageViews(uiLayout *layout, struct PointerRNA *imaptr); +void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA *ptr); void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser); void uiTemplateImageInfo(uiLayout *layout, struct bContext *C, Image *ima, ImageUser *iuser); void uiTemplateRunningJobs(uiLayout *layout, struct bContext *C); diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 41d2a90e548..72abfcb9293 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -613,6 +613,7 @@ static int editsource_exec(bContext *C, wmOperator *op) /* redraw and get active button python info */ ED_region_do_draw(C, ar); + ar->do_draw = false; for (BLI_ghashIterator_init(&ghi, ui_editsource_info->hash); BLI_ghashIterator_done(&ghi) == false; diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index fe9ee71aa8e..d492a4b9dda 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -929,7 +929,7 @@ cage_cleanup: BakeData *bake = &scene->r.bake; char name[FILE_MAX]; - BKE_image_path_from_imtype(name, filepath, bmain->name, 0, bake->im_format.imtype, true, false); + BKE_image_path_from_imtype(name, filepath, bmain->name, 0, bake->im_format.imtype, true, false, NULL); if (is_automatic_name) { BLI_path_suffix(name, FILE_MAX, ob_low->id.name + 2, "_"); diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h index ee0046b49dc..5c6744b0248 100644 --- a/source/blender/editors/render/render_intern.h +++ b/source/blender/editors/render/render_intern.h @@ -55,6 +55,9 @@ void MATERIAL_OT_paste(struct wmOperatorType *ot); void SCENE_OT_render_layer_add(struct wmOperatorType *ot); void SCENE_OT_render_layer_remove(struct wmOperatorType *ot); +void SCENE_OT_render_view_add(struct wmOperatorType *ot); +void SCENE_OT_render_view_remove(struct wmOperatorType *ot); + #ifdef WITH_FREESTYLE void SCENE_OT_freestyle_module_add(struct wmOperatorType *ot); void SCENE_OT_freestyle_module_remove(struct wmOperatorType *ot); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 1c9f32697d4..f76f7cad1ae 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -48,6 +48,7 @@ #include "DNA_userdef_types.h" #include "BKE_blender.h" +#include "BKE_camera.h" #include "BKE_context.h" #include "BKE_colortools.h" #include "BKE_depsgraph.h" @@ -116,7 +117,7 @@ typedef struct RenderJob { } RenderJob; /* called inside thread! */ -static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibuf, ImageUser *iuser, volatile rcti *renrect) +static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibuf, ImageUser *iuser, volatile rcti *renrect, const char *viewname) { Scene *scene = rj->scene; const float *rectf = NULL; @@ -188,11 +189,11 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu */ /* TODO(sergey): Need to check has_combined here? */ if (iuser->pass == 0) { + size_t view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname); /* find current float rect for display, first case is after composite... still weak */ - if (rr->rectf) - rectf = rr->rectf; - else { - if (rr->rect32) { + rectf = RE_RenderViewGetRectf(rr, view_id); + if (rectf == NULL) { + if (RE_RenderViewGetRect32(rr, view_id)) { /* special case, currently only happens with sequencer rendering, * which updates the whole frame, so we can only mark display buffer * as invalid here (sergey) @@ -201,8 +202,8 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu return; } else { - if (rr->renlay == NULL || rr->renlay->rectf == NULL) return; - rectf = rr->renlay->rectf; + if (rr->renlay == NULL) return; + rectf = RE_RenderLayerGetPass(rr->renlay, SCE_PASS_COMBINED, viewname); } } if (rectf == NULL) return; @@ -531,6 +532,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec Image *ima = rj->image; ImBuf *ibuf; void *lock; + const char *viewname = RE_GetActiveRenderView(rj->re); /* only update if we are displaying the slot being rendered */ if (ima->render_slot != ima->last_render_slot) { @@ -563,7 +565,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec ibuf->channels == 1 || U.image_draw_method != IMAGE_DRAW_METHOD_GLSL) { - image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect); + image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect, viewname); } /* make jobs timer to send notifier */ @@ -1487,7 +1489,8 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C) if (re == NULL) return; } - RE_AcquireResultImage(re, &rres); + /* Viewport render preview doesn't support multiview, view hardcoded to 0 */ + RE_AcquireResultImage(re, &rres, 0); if (rres.rectf) { RegionView3D *rv3d = CTX_wm_region_view3d(C); diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 5c8bee07420..b59fd10870e 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -39,6 +39,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_jitter.h" +#include "BLI_threads.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" @@ -103,11 +104,17 @@ typedef struct OGLRender { bMovieHandle *mh; int cfrao, nfra; + size_t totvideos; + + /* quick lookup */ + int view_id; + /* wm vars for timer and progress cursor */ wmWindowManager *wm; wmWindow *win; wmTimer *timer; /* use to check if running modal or not (invoke'd or exec'd)*/ + void **movie_ctx_arr; } OGLRender; /* added because v3d is not always valid */ @@ -121,16 +128,125 @@ static unsigned int screen_opengl_layers(OGLRender *oglrender) } } -static void screen_opengl_render_apply(OGLRender *oglrender) +static bool screen_opengl_is_multiview(OGLRender *oglrender) +{ + View3D *v3d = oglrender->v3d; + RegionView3D *rv3d = oglrender->rv3d; + RenderData *rd = &oglrender->scene->r; + + if ((rd == NULL) || ((!oglrender->is_sequencer) && ((rv3d == NULL) || (v3d == NULL)))) + return false; + + return (rd->scemode & R_MULTIVIEW) && ((oglrender->is_sequencer) || (rv3d->persp == RV3D_CAMOB && v3d->camera)); +} + +static void screen_opengl_views_setup(OGLRender *oglrender) +{ + RenderResult *rr; + RenderView *rv; + SceneRenderView *srv; + bool is_multiview; + View3D *v3d = oglrender->v3d; + + RenderData *rd = &oglrender->scene->r; + + rr = RE_AcquireResultWrite(oglrender->re); + + is_multiview = screen_opengl_is_multiview(oglrender); + + if (!is_multiview) { + /* we only have one view when multiview is off */ + rv = rr->views.first; + + if (rv == NULL) { + rv = MEM_callocN(sizeof(RenderView), "new opengl render view"); + BLI_addtail(&rr->views, rv); + } + + while (rv->next) { + RenderView *rv_del = rv->next; + BLI_remlink(&rr->views, rv_del); + + if (rv_del->rectf) + MEM_freeN(rv_del->rectf); + + if (rv_del->rectz) + MEM_freeN(rv_del->rectz); + + MEM_freeN(rv_del); + } + } + else { + if (!oglrender->is_sequencer) + RE_SetOverrideCamera(oglrender->re, V3D_CAMERA_SCENE(oglrender->scene, v3d)); + + /* remove all the views that are not needed */ + rv = rr->views.last; + while (rv) { + srv = BLI_findstring(&rd->views, rv->name, offsetof(SceneRenderView, name)); + if (BKE_scene_multiview_is_render_view_active(rd, srv)) { + if (rv->rectf == NULL) + rv->rectf = MEM_callocN(sizeof(float) * 4 * oglrender->sizex * oglrender->sizey, "screen_opengl_render_init rect"); + rv = rv->prev; + } + else { + RenderView *rv_del = rv; + rv = rv_del->prev; + + BLI_remlink(&rr->views, rv_del); + + if (rv_del->rectf) + MEM_freeN(rv_del->rectf); + + if (rv_del->rectz) + MEM_freeN(rv_del->rectz); + + MEM_freeN(rv_del); + } + } + + /* create all the views that are needed */ + for (srv = rd->views.first; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) + continue; + + rv = BLI_findstring(&rr->views, srv->name, offsetof(SceneRenderView, name)); + + if (rv == NULL) { + rv = MEM_callocN(sizeof(RenderView), "new opengl render view"); + BLI_strncpy(rv->name, srv->name, sizeof(rv->name)); + BLI_addtail(&rr->views, rv); + } + } + } + + for (rv = rr->views.first; rv; rv = rv->next) { + if (rv->rectf == NULL) { + rv->rectf = MEM_callocN(sizeof(float) * 4 * oglrender->sizex * oglrender->sizey, "screen_opengl_render_init rect"); + } + } + + BLI_lock_thread(LOCK_DRAW_IMAGE); + if (is_multiview && BKE_scene_multiview_is_stereo3d(rd)) { + oglrender->ima->flag |= IMA_IS_STEREO; + } + else { + oglrender->ima->flag &= ~IMA_IS_STEREO; + oglrender->iuser.flag &= ~IMA_SHOW_STEREO; + } + BLI_unlock_thread(LOCK_DRAW_IMAGE); + + RE_ReleaseResult(oglrender->re); +} + +static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) { Scene *scene = oglrender->scene; ARegion *ar = oglrender->ar; View3D *v3d = oglrender->v3d; RegionView3D *rv3d = oglrender->rv3d; - RenderResult *rr; Object *camera = NULL; ImBuf *ibuf; - void *lock; float winmat[4][4]; int sizex = oglrender->sizex; int sizey = oglrender->sizey; @@ -138,8 +254,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) bool draw_bgpic = true; bool draw_sky = (scene->r.alphamode == R_ADDSKY); unsigned char *rect = NULL; - - rr = RE_AcquireResultRead(oglrender->re); + const char *viewname = RE_GetActiveRenderView(oglrender->re); if (oglrender->is_sequencer) { SeqRenderData context; @@ -152,9 +267,11 @@ static void screen_opengl_render_apply(OGLRender *oglrender) oglrender->sizex, oglrender->sizey, 100.0f, &context); + context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname); ibuf = BKE_sequencer_give_ibuf(&context, CFRA, chanshown); if (ibuf) { + float *rectf; ImBuf *linear_ibuf; BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y)); @@ -175,7 +292,8 @@ static void screen_opengl_render_apply(OGLRender *oglrender) BKE_sequencer_imbuf_from_sequencer_space(scene, linear_ibuf); } - memcpy(rr->rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey); + rectf = RE_RenderViewGetRectf(rr, oglrender->view_id); + memcpy(rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey); IMB_freeImBuf(linear_ibuf); } @@ -221,7 +339,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) /* render 3d view */ if (rv3d->persp == RV3D_CAMOB && v3d->camera) { /*int is_ortho = scene->r.mode & R_ORTHO;*/ - camera = v3d->camera; + camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, viewname); RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat); if (camera->type == OB_CAMERA) { Camera *cam = camera->data; @@ -248,7 +366,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) ED_view3d_draw_offscreen( scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky, is_persp, - oglrender->ofs, oglrender->fx, &fx_settings); + oglrender->ofs, oglrender->fx, &fx_settings, viewname); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); } else { @@ -264,7 +382,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) ED_view3d_draw_offscreen( scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky, is_persp, - oglrender->ofs, oglrender->fx, &fx_settings); + oglrender->ofs, oglrender->fx, &fx_settings, viewname); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); for (i = 0; i < sizex * sizey * 4; i++) @@ -280,7 +398,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) ED_view3d_draw_offscreen( scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, draw_bgpic, draw_sky, is_persp, - oglrender->ofs, oglrender->fx, &fx_settings); + oglrender->ofs, oglrender->fx, &fx_settings, viewname); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); for (i = 0; i < sizex * sizey * 4; i++) @@ -300,7 +418,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) char err_out[256] = "unknown"; ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey, IB_rect, OB_SOLID, false, true, true, - (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL, err_out); + (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL, viewname, err_out); camera = scene->camera; if (ibuf_view) { @@ -325,6 +443,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) if (rect) { int profile_to; + float *rectf = RE_RenderViewGetRectf(rr, oglrender->view_id); if (BKE_scene_check_color_management_enabled(scene)) profile_to = IB_PROFILE_LINEAR_RGB; @@ -333,47 +452,60 @@ static void screen_opengl_render_apply(OGLRender *oglrender) /* sequencer has got trickier conversion happened above * also assume opengl's space matches byte buffer color space */ - IMB_buffer_float_from_byte(rr->rectf, rect, + IMB_buffer_float_from_byte(rectf, rect, profile_to, IB_PROFILE_SRGB, true, oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); - } - /* rr->rectf is now filled with image data */ + /* rr->rectf is now filled with image data */ - if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) { - BKE_image_stamp_buf(scene, camera, rect, rr->rectf, rr->rectx, rr->recty, 4); + if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) + BKE_image_stamp_buf(scene, camera, rect, rectf, rr->rectx, rr->recty, 4); + + MEM_freeN(rect); } +} - RE_ReleaseResult(oglrender->re); +static void screen_opengl_render_write(OGLRender *oglrender) +{ + Scene *scene = oglrender->scene; + RenderResult *rr; + bool ok; + char name[FILE_MAX]; + Object *camera = RE_GetCamera(oglrender->re); + + rr = RE_AcquireResultRead(oglrender->re); - /* update byte from float buffer */ - ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); + BKE_image_path_from_imformat( + name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, + &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false, NULL); - if (ibuf) { - ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + /* write images as individual images or stereo */ + ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, camera, false, name); - /* write file for animation */ - if (oglrender->write_still) { - char name[FILE_MAX]; - int ok; + RE_ReleaseResultImage(oglrender->re); - if (scene->r.im_format.planes == R_IMF_CHAN_DEPTH_8) { - IMB_color_to_bw(ibuf); - } + if (ok) printf("OpenGL Render written to '%s'\n", name); + else printf("OpenGL Render failed to write '%s'\n", name); +} - BKE_image_path_from_imformat( - name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, - &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false); - ok = BKE_imbuf_write_as(ibuf, name, &scene->r.im_format, true); /* no need to stamp here */ - if (ok) printf("OpenGL Render written to '%s'\n", name); - else printf("OpenGL Render failed to write '%s'\n", name); - } +static void screen_opengl_render_apply(OGLRender *oglrender) +{ + RenderResult *rr; + RenderView *rv; + int view_id; + + rr = RE_AcquireResultRead(oglrender->re); + for (rv = rr->views.first, view_id = 0; rv; rv = rv->next, view_id++) { + RE_SetActiveRenderView(oglrender->re, rv->name); + oglrender->view_id = view_id; + screen_opengl_render_doit(oglrender, rr); } - - BKE_image_release_ibuf(oglrender->ima, ibuf, lock); - if (rect) - MEM_freeN(rect); + RE_ReleaseResult(oglrender->re); + + if (oglrender->write_still) { + screen_opengl_render_write(oglrender); + } } static bool screen_opengl_render_init(bContext *C, wmOperator *op) @@ -385,7 +517,6 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); ScrArea *prevsa = CTX_wm_area(C); ARegion *prevar = CTX_wm_region(C); - RenderResult *rr; GPUOffScreen *ofs; OGLRender *oglrender; int sizex, sizey; @@ -458,7 +589,6 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) oglrender->sseq = CTX_wm_space_seq(C); } - oglrender->prevsa = prevsa; oglrender->prevar = prevar; @@ -492,15 +622,17 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) /* create render result */ RE_InitState(oglrender->re, NULL, &scene->r, NULL, sizex, sizey, NULL); - rr = RE_AcquireResultWrite(oglrender->re); - if (rr->rectf == NULL) - rr->rectf = MEM_callocN(sizeof(float) * 4 * sizex * sizey, "screen_opengl_render_init rect"); - RE_ReleaseResult(oglrender->re); + /* create render views */ + screen_opengl_views_setup(oglrender); /* wm vars */ oglrender->wm = wm; oglrender->win = win; + oglrender->totvideos = 0; + oglrender->mh = NULL; + oglrender->movie_ctx_arr = NULL; + return true; } @@ -508,10 +640,19 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender) { Main *bmain = CTX_data_main(C); Scene *scene = oglrender->scene; + size_t i; if (oglrender->mh) { - if (BKE_imtype_is_movie(scene->r.im_format.imtype)) - oglrender->mh->end_movie(); + if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { + for (i = 0; i < oglrender->totvideos; i++) { + oglrender->mh->end_movie(oglrender->movie_ctx_arr[i]); + oglrender->mh->context_free(oglrender->movie_ctx_arr[i]); + } + } + + if (oglrender->movie_ctx_arr) { + MEM_freeN(oglrender->movie_ctx_arr); + } } if (oglrender->timer) { /* exec will not have a timer */ @@ -552,13 +693,27 @@ static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op) oglrender = op->customdata; scene = oglrender->scene; + oglrender->totvideos = BKE_scene_multiview_num_videos_get(&scene->r); oglrender->reports = op->reports; - oglrender->mh = BKE_movie_handle_get(scene->r.im_format.imtype); + if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { - if (!oglrender->mh->start_movie(scene, &scene->r, oglrender->sizex, oglrender->sizey, oglrender->reports, PRVRANGEON != 0)) { - screen_opengl_render_end(C, oglrender); - return 0; + size_t i, width, height; + + BKE_scene_multiview_videos_dimensions_get(&scene->r, oglrender->sizex, oglrender->sizey, &width, &height); + oglrender->movie_ctx_arr = MEM_mallocN(sizeof(void *) * oglrender->totvideos, "Movies"); + oglrender->mh = BKE_movie_handle_get(scene->r.im_format.imtype); + + for (i = 0; i < oglrender->totvideos; i++) { + const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, i); + + oglrender->movie_ctx_arr[i] = oglrender->mh->context_create(); + if (!oglrender->mh->start_movie(oglrender->movie_ctx_arr[i], scene, &scene->r, oglrender->sizex, + oglrender->sizey, oglrender->reports, PRVRANGEON != 0, suffix)) + { + screen_opengl_render_end(C, oglrender); + return 0; + } } } @@ -568,18 +723,17 @@ static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op) return 1; } + static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); OGLRender *oglrender = op->customdata; Scene *scene = oglrender->scene; - ImBuf *ibuf, *ibuf_save = NULL; - void *lock; char name[FILE_MAX]; bool ok = false; const bool view_context = (oglrender->v3d != NULL); - Object *camera = NULL; bool is_movie; + RenderResult *rr; /* go to next frame */ if (CFRA < oglrender->nfra) @@ -599,7 +753,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) if (!is_movie) { BKE_image_path_from_imformat( name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, - &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true); + &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL); if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) { BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name); @@ -619,89 +773,40 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) if (BKE_scene_camera_switch_update(scene)) { oglrender->v3d->camera = scene->camera; } - - camera = oglrender->v3d->camera; } } else { BKE_scene_camera_switch_update(scene); - - camera = scene->camera; } /* render into offscreen buffer */ screen_opengl_render_apply(oglrender); /* save to disk */ - ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); - - if (ibuf) { - bool needs_free = false; - - ibuf_save = ibuf; - - if (is_movie || !BKE_imtype_requires_linear_float(scene->r.im_format.imtype)) { - ibuf_save = IMB_colormanagement_imbuf_for_write(ibuf, true, true, &scene->view_settings, - &scene->display_settings, &scene->r.im_format); - - needs_free = true; - } - - /* color -> grayscale */ - /* editing directly would alter the render view */ - if (scene->r.im_format.planes == R_IMF_PLANES_BW) { - ImBuf *ibuf_bw = IMB_dupImBuf(ibuf_save); - IMB_color_to_bw(ibuf_bw); - - if (needs_free) - IMB_freeImBuf(ibuf_save); - - ibuf_save = ibuf_bw; - } - else { - /* this is lightweight & doesnt re-alloc the buffers, only do this - * to save the correct bit depth since the image is always RGBA */ - ImBuf *ibuf_cpy = IMB_allocImBuf(ibuf_save->x, ibuf_save->y, scene->r.im_format.planes, 0); - - ibuf_cpy->rect = ibuf_save->rect; - ibuf_cpy->rect_float = ibuf_save->rect_float; - ibuf_cpy->zbuf_float = ibuf_save->zbuf_float; - - if (needs_free) { - ibuf_cpy->mall = ibuf_save->mall; - ibuf_save->mall = 0; - IMB_freeImBuf(ibuf_save); - } + rr = RE_AcquireResultRead(oglrender->re); - ibuf_save = ibuf_cpy; + if (is_movie) { + ok = RE_WriteRenderViewsMovie(oglrender->reports, rr, scene, &scene->r, oglrender->mh, oglrender->sizex, + oglrender->sizey, oglrender->movie_ctx_arr, oglrender->totvideos); + if (ok) { + printf("Append frame %d", scene->r.cfra); + BKE_reportf(op->reports, RPT_INFO, "Appended frame: %d", scene->r.cfra); } - - if (is_movie) { - ok = oglrender->mh->append_movie(&scene->r, PSFRA, CFRA, (int *)ibuf_save->rect, - oglrender->sizex, oglrender->sizey, oglrender->reports); - if (ok) { - printf("Append frame %d", scene->r.cfra); - BKE_reportf(op->reports, RPT_INFO, "Appended frame: %d", scene->r.cfra); - } + } + else { + ok = RE_WriteRenderViewsImage(op->reports, rr, scene, scene->camera, true, name); + if (ok) { + printf("Saved: %s", name); + BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name); } else { - ok = BKE_imbuf_write_stamp(scene, camera, ibuf_save, name, &scene->r.im_format); - - if (ok == 0) { - printf("Write error: cannot save %s\n", name); - BKE_reportf(op->reports, RPT_ERROR, "Write error: cannot save %s", name); - } - else { - printf("Saved: %s", name); - BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name); - } + printf("Write error: cannot save %s\n", name); + BKE_reportf(op->reports, RPT_ERROR, "Write error: cannot save %s", name); } - - if (needs_free) - IMB_freeImBuf(ibuf_save); } - BKE_image_release_ibuf(oglrender->ima, ibuf, lock); + RE_ReleaseResult(oglrender->re); + /* movie stats prints have no line break */ printf("\n"); diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c index 0d334082a2b..6aaad98f946 100644 --- a/source/blender/editors/render/render_ops.c +++ b/source/blender/editors/render/render_ops.c @@ -58,6 +58,9 @@ void ED_operatortypes_render(void) WM_operatortype_append(SCENE_OT_render_layer_add); WM_operatortype_append(SCENE_OT_render_layer_remove); + WM_operatortype_append(SCENE_OT_render_view_add); + WM_operatortype_append(SCENE_OT_render_view_remove); + #ifdef WITH_FREESTYLE WM_operatortype_append(SCENE_OT_freestyle_module_add); WM_operatortype_append(SCENE_OT_freestyle_module_remove); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 9dbd2e88563..e6fbfda3067 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -548,7 +548,9 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, /* test if something rendered ok */ re = RE_GetRender(name); - RE_AcquireResultImage(re, &rres); + + /* material preview only needs monoscopy (view 0) */ + RE_AcquireResultImage(re, &rres, 0); if (rres.rectf) { @@ -561,9 +563,11 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, unsigned char *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect"); float fx = rect->xmin + offx; float fy = rect->ymin; + + /* material preview only needs monoscopy (view 0) */ if (re) - RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte); - + RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte, 0); + glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte); MEM_freeN(rect_byte); diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index cf712a653e6..3de21536148 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -605,6 +605,70 @@ void SCENE_OT_render_layer_remove(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } +/********************** render view operators *********************/ + +static int render_view_remove_poll(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + + /* don't allow user to remove "left" and "right" views */ + return scene->r.actview > 1; +} + +static int render_view_add_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + + BKE_scene_add_render_view(scene, NULL); + scene->r.actview = BLI_listbase_count(&scene->r.views) - 1; + + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + + return OPERATOR_FINISHED; +} + +void SCENE_OT_render_view_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Render View"; + ot->idname = "SCENE_OT_render_view_add"; + ot->description = "Add a render view"; + + /* api callbacks */ + ot->exec = render_view_add_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int render_view_remove_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + SceneRenderView *rv = BLI_findlink(&scene->r.views, scene->r.actview); + + if (!BKE_scene_remove_render_view(scene, rv)) + return OPERATOR_CANCELLED; + + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + + return OPERATOR_FINISHED; +} + +void SCENE_OT_render_view_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Render View"; + ot->idname = "SCENE_OT_render_view_remove"; + ot->description = "Remove the selected render view"; + + /* api callbacks */ + ot->exec = render_view_remove_exec; + ot->poll = render_view_remove_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + #ifdef WITH_FREESTYLE static bool freestyle_linestyle_check_report(FreestyleLineSet *lineset, ReportList *reports) diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index be9336cc984..d786c0cfc36 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -493,7 +493,6 @@ void ED_region_do_draw(bContext *C, ARegion *ar) glDisable(GL_BLEND); #endif - ar->do_draw = 0; memset(&ar->drawrct, 0, sizeof(ar->drawrct)); UI_blocklist_free_inactive(C, &ar->uiblocks); diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index e1c414b0031..3d76070f197 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -59,6 +59,7 @@ #include "ED_screen.h" #include "ED_screen_types.h" #include "ED_clip.h" +#include "ED_node.h" #include "ED_render.h" #include "UI_interface.h" @@ -2122,4 +2123,85 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute)) } +/* + * return true if any active area requires to see in 3D + */ +bool ED_screen_stereo3d_required(bScreen *screen) +{ + ScrArea *sa; + Scene *sce = screen->scene; + const bool is_multiview = (sce->r.scemode & R_MULTIVIEW) != 0; + + for (sa = screen->areabase.first; sa; sa = sa->next) { + switch (sa->spacetype) { + case SPACE_VIEW3D: + { + View3D *v3d; + + if (!is_multiview) + continue; + + v3d = sa->spacedata.first; + if (v3d->camera && v3d->stereo3d_camera == STEREO_3D_ID) { + ARegion *ar; + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->regiondata && ar->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3d = ar->regiondata; + if (rv3d->persp == RV3D_CAMOB) { + return true; + } + } + } + } + break; + } + case SPACE_IMAGE: + { + SpaceImage *sima; + + /* images should always show in stereo, even if + * the file doesn't have views enabled */ + sima = sa->spacedata.first; + if (sima->image && (sima->image->flag & IMA_IS_STEREO) && + (sima->iuser.flag & IMA_SHOW_STEREO)) + { + return true; + } + break; + } + case SPACE_NODE: + { + SpaceNode *snode; + + if (!is_multiview) + continue; + snode = sa->spacedata.first; + if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) { + return true; + } + break; + } + case SPACE_SEQ: + { + SpaceSeq *sseq; + + if (!is_multiview) + continue; + + sseq = sa->spacedata.first; + if (ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW)) { + return true; + } + + if (sseq->draw_flag & SEQ_DRAW_BACKDROP) { + return true; + } + + break; + } + } + } + + return false; +} diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 894a801b677..67c18ac287e 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -990,6 +990,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event) rect.ymax = rect.ymin + BLI_rcti_size_y(&rect) / U.pixelsize; newwin = WM_window_open(C, &rect); + *newwin->stereo3d_format = *win->stereo3d_format; /* allocs new screen and adds to newly created window, using window size */ newsc = ED_screen_add(newwin, CTX_data_scene(C), sc->id.name + 2); diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 330bc7e3395..4644f0ae0b8 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -303,6 +303,7 @@ typedef struct ScreenshotJob { const short *stop; const short *do_update; ReportList reports; + void *movie_ctx; } ScreenshotJob; @@ -312,7 +313,10 @@ static void screenshot_freejob(void *sjv) if (sj->dumprect) MEM_freeN(sj->dumprect); - + + if (sj->movie_ctx) + MEM_freeN(sj->movie_ctx); + MEM_freeN(sj); } @@ -337,20 +341,21 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float { ScreenshotJob *sj = sjv; RenderData rd = sj->scene->r; - bMovieHandle *mh = BKE_movie_handle_get(sj->scene->r.im_format.imtype); - + bMovieHandle *mh = NULL; + /* we need this as local variables for renderdata */ rd.frs_sec = U.scrcastfps; rd.frs_sec_base = 1.0f; if (BKE_imtype_is_movie(rd.im_format.imtype)) { - if (!mh->start_movie(sj->scene, &rd, sj->dumpsx, sj->dumpsy, &sj->reports, false)) { + mh = BKE_movie_handle_get(sj->scene->r.im_format.imtype); + sj->movie_ctx = mh->context_create(); + + if (!mh->start_movie(sj->movie_ctx, sj->scene, &rd, sj->dumpsx, sj->dumpsy, &sj->reports, false, "")) { printf("screencast job stopped\n"); return; } } - else - mh = NULL; sj->stop = stop; sj->do_update = do_update; @@ -362,8 +367,8 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float if (sj->dumprect) { if (mh) { - if (mh->append_movie(&rd, rd.sfra, rd.cfra, (int *)sj->dumprect, - sj->dumpsx, sj->dumpsy, &sj->reports)) + if (mh->append_movie(sj->movie_ctx, &rd, rd.sfra, rd.cfra, (int *)sj->dumprect, + sj->dumpsx, sj->dumpsy, "", &sj->reports)) { BKE_reportf(&sj->reports, RPT_INFO, "Appended frame: %d", rd.cfra); printf("Appended frame %d\n", rd.cfra); @@ -379,7 +384,7 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float BKE_image_path_from_imformat( name, rd.pic, sj->bmain->name, rd.cfra, - &rd.im_format, (rd.scemode & R_EXTENSION) != 0, true); + &rd.im_format, (rd.scemode & R_EXTENSION) != 0, true, NULL); ibuf->rect = sj->dumprect; ok = BKE_imbuf_write(ibuf, name, &rd.im_format); @@ -410,8 +415,10 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float PIL_sleep_ms(U.scrcastwait); } - if (mh) - mh->end_movie(); + if (mh) { + mh->end_movie(sj->movie_ctx); + mh->context_free(sj->movie_ctx); + } BKE_report(&sj->reports, RPT_INFO, "Screencast job stopped"); } diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 097ffe3523b..7992767072a 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -499,7 +499,7 @@ void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short te int w = imapaintpartial.x2 - imapaintpartial.x1; int h = imapaintpartial.y2 - imapaintpartial.y1; /* Testing with partial update in uv editor too */ - GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h); //!texpaint); + GPU_paint_update_image(image, (sima ? &sima->iuser : NULL), imapaintpartial.x1, imapaintpartial.y1, w, h); //!texpaint); } } diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index 4f71bea7cd2..9d39eea7b96 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -1109,7 +1109,7 @@ static int paint_2d_canvas_set(ImagePaintState *s, Image *ima) if (ima == NULL) { return 0; } - else if (ima->packedfile && ima->rr) { + else if (BKE_image_has_packedfile(ima) && ima->rr) { s->warnpackedfile = ima->id.name + 2; return 0; } diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 9ee15f3a532..b01d315650f 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -5233,7 +5233,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) if (w > maxsize) w = maxsize; if (h > maxsize) h = maxsize; - ibuf = ED_view3d_draw_offscreen_imbuf(scene, CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, false, R_ALPHAPREMUL, err_out); + ibuf = ED_view3d_draw_offscreen_imbuf(scene, CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, false, R_ALPHAPREMUL, NULL, err_out); if (!ibuf) { /* Mostly happens when OpenGL offscreen buffer was failed to create, */ /* but could be other reasons. Should be handled in the future. nazgul */ @@ -5444,7 +5444,7 @@ static Image *proj_paint_image_create(wmOperator *op, Main *bmain) RNA_string_get(op->ptr, "name", imagename); } ima = BKE_image_add_generated(bmain, width, height, imagename, alpha ? 32 : 24, use_float, - gen_type, color); + gen_type, color, false); return ima; } diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index fb3c140fddf..a02f64d68d8 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -44,6 +44,7 @@ #include "BKE_image.h" #include "BKE_node.h" #include "BKE_screen.h" +#include "BKE_scene.h" #include "RE_pipeline.h" @@ -82,9 +83,9 @@ static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, else { if (ima->source == IMA_SRC_MOVIE) { ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Movie"), len - ofs); - if (ima->anim) + if (BKE_image_has_anim(ima)) ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(" %d frs"), - IMB_anim_get_duration(ima->anim, IMB_TC_RECORD_RUN)); + IMB_anim_get_duration(((ImageAnim *)ima->anims.first)->anim, IMB_TC_RECORD_RUN)); } else { ofs += BLI_strncpy_rlen(str, IFACE_("Image"), len - ofs); @@ -311,10 +312,10 @@ static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void * static const char *ui_imageuser_layer_fake_name(RenderResult *rr) { - if (rr->rectf) { + if (RE_RenderViewGetRectf(rr, 0)) { return IFACE_("Composite"); } - else if (rr->rect32) { + else if (RE_RenderViewGetRect32(rr, 0)) { return IFACE_("Sequence"); } else { @@ -375,7 +376,7 @@ final: static const char *ui_imageuser_pass_fake_name(RenderLayer *rl) { - if (rl == NULL || rl->rectf) { + if (rl == NULL) { return IFACE_("Combined"); } else { @@ -383,9 +384,9 @@ static const char *ui_imageuser_pass_fake_name(RenderLayer *rl) } } -static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *ptrpair_p) +static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt) { - void **rnd_data = ptrpair_p; + void **rnd_data = rnd_pt; uiBlock *block = uiLayoutGetBlock(layout); Image *image = rnd_data[0]; ImageUser *iuser = rnd_data[1]; @@ -398,6 +399,7 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void * RenderPass *rpass; const char *fake_name; int nr; + int passflag = 0; /* may have been freed since drawing */ rr = BKE_image_acquire_renderresult(scene, image); @@ -419,15 +421,22 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void * fake_name = ui_imageuser_pass_fake_name(rl); if (fake_name) { - BLI_strncpy(rpass_fake.name, fake_name, sizeof(rpass_fake.name)); + BLI_strncpy(rpass_fake.internal_name, fake_name, sizeof(rpass_fake.internal_name)); nr += 1; } /* rendered results don't have a Combined pass */ for (rpass = rl ? rl->passes.last : NULL; rpass; rpass = rpass->prev, nr--) { + + /* just show one pass of each kind */ + if (passflag & rpass->passtype) + continue; + + passflag |= rpass->passtype; + final: - uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->name), 0, 0, - UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, (float) nr, 0.0, 0, -1, ""); + uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->internal_name), 0, 0, + UI_UNIT_X * 5, UI_UNIT_X, &iuser->passtype, (float) rpass->passtype, 0.0, 0, -1, ""); } if (fake_name) { @@ -441,21 +450,81 @@ final: BKE_image_release_renderresult(scene, image); } +/**************************** view menus *****************************/ +static void ui_imageuser_view_menu_rr(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt) +{ + void **rnd_data = rnd_pt; + uiBlock *block = uiLayoutGetBlock(layout); + Image *image = rnd_data[0]; + ImageUser *iuser = rnd_data[1]; + RenderResult *rr; + RenderView *rview; + int nr; + Scene *scene = iuser->scene; + + /* may have been freed since drawing */ + rr = BKE_image_acquire_renderresult(scene, image); + if (UNLIKELY(rr == NULL)) { + return; + } + + UI_block_layout_set_current(block, layout); + uiLayoutColumn(layout, false); + + uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("View"), + 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); + + uiItemS(layout); + + nr = (rr ? BLI_listbase_count(&rr->views) : 0) - 1; + for (rview = rr ? rr->views.last : NULL; rview; rview = rview->prev, nr--) { + uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rview->name), 0, 0, + UI_UNIT_X * 5, UI_UNIT_X, &iuser->view, (float) nr, 0.0, 0, -1, ""); + } + + BKE_image_release_renderresult(scene, image); +} + +static void ui_imageuser_view_menu_multiview(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt) +{ + void **rnd_data = rnd_pt; + uiBlock *block = uiLayoutGetBlock(layout); + Image *image = rnd_data[0]; + ImageUser *iuser = rnd_data[1]; + int nr; + ImageView *iv; + + UI_block_layout_set_current(block, layout); + uiLayoutColumn(layout, false); + + uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("View"), + 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); + + uiItemS(layout); + + nr = BLI_listbase_count(&image->views) - 1; + for (iv = image->views.last; iv; iv = iv->prev, nr--) { + uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(iv->name), 0, 0, + UI_UNIT_X * 5, UI_UNIT_X, &iuser->view, (float) nr, 0.0, 0, -1, ""); + } +} + /* 5 layer button callbacks... */ static void image_multi_cb(bContext *C, void *rr_v, void *iuser_v) { ImageUser *iuser = iuser_v; - BKE_image_multilayer_index(rr_v, iuser); + BKE_image_multilayer_index(rr_v, iuser); WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); } + static void image_multi_inclay_cb(bContext *C, void *rr_v, void *iuser_v) { RenderResult *rr = rr_v; ImageUser *iuser = iuser_v; int tot = BLI_listbase_count(&rr->layers); - if (rr->rectf || rr->rect32) + if (RE_HasFakeLayer(rr)) tot++; /* fake compo/sequencer layer */ if (iuser->layer < tot - 1) { @@ -483,7 +552,7 @@ static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v) if (rl) { int tot = BLI_listbase_count(&rl->passes); - if (rr->rectf || rr->rect32) + if (RE_HasFakeLayer(rr)) tot++; /* fake compo/sequencer layer */ if (iuser->pass < tot - 1) { @@ -504,6 +573,16 @@ static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) } } +/* 5 view button callbacks... */ +static void image_multiview_cb(bContext *C, void *ima_v, void *iuser_v) +{ + Image *ima = ima_v; + ImageUser *iuser = iuser_v; + + BKE_image_multiview_index(ima, iuser); + WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); +} + #if 0 static void image_freecache_cb(bContext *C, void *ima_v, void *unused) { @@ -523,13 +602,14 @@ static void image_user_change(bContext *C, void *iuser_v, void *unused) static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser, int w, short *render_slot) { - static void *rnd_pt[3]; /* XXX, workaround */ + static void *rnd_pt[4]; /* XXX, workaround */ uiBlock *block = uiLayoutGetBlock(layout); uiBut *but; RenderLayer *rl = NULL; - int wmenu1, wmenu2, wmenu3; + int wmenu1, wmenu2, wmenu3, wmenu4; const char *fake_name; - const char *display_name; + const char *display_name = ""; + const bool show_stereo = (iuser->flag & IMA_SHOW_STEREO); uiLayoutRow(layout, true); @@ -537,6 +617,7 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes wmenu1 = (2 * w) / 5; wmenu2 = (3 * w) / 5; wmenu3 = (3 * w) / 6; + wmenu4 = (3 * w) / 6; rnd_pt[0] = image; rnd_pt[1] = iuser; @@ -558,6 +639,7 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes if (rr) { RenderPass *rpass; + RenderView *rview; int rpass_index; /* layer */ @@ -566,20 +648,50 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes rl = BLI_findlink(&rr->layers, rpass_index); rnd_pt[2] = SET_INT_IN_POINTER(rpass_index); - display_name = rl ? rl->name : (fake_name ? fake_name : ""); - but = uiDefMenuBut(block, ui_imageuser_layer_menu, rnd_pt, display_name, 0, 0, wmenu2, UI_UNIT_Y, TIP_("Select Layer")); - UI_but_func_set(but, image_multi_cb, rr, iuser); - UI_but_type_set_menu_from_pulldown(but); - + if (RE_layers_have_name(rr)) { + display_name = rl ? rl->name : (fake_name ? fake_name : ""); + but = uiDefMenuBut(block, ui_imageuser_layer_menu, rnd_pt, display_name, 0, 0, wmenu2, UI_UNIT_Y, TIP_("Select Layer")); + UI_but_func_set(but, image_multi_cb, rr, iuser); + UI_but_type_set_menu_from_pulldown(but); + } /* pass */ fake_name = ui_imageuser_pass_fake_name(rl); rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass - (fake_name ? 1 : 0)) : NULL); - display_name = rpass ? rpass->name : (fake_name ? fake_name : ""); + display_name = rpass ? rpass->internal_name : (fake_name ? fake_name : ""); but = uiDefMenuBut(block, ui_imageuser_pass_menu, rnd_pt, display_name, 0, 0, wmenu3, UI_UNIT_Y, TIP_("Select Pass")); UI_but_func_set(but, image_multi_cb, rr, iuser); UI_but_type_set_menu_from_pulldown(but); + + /* view */ + if (BLI_listbase_count_ex(&rr->views, 2) > 1 && !show_stereo) { + rview = BLI_findlink(&rr->views, iuser->view); + display_name = rview ? rview->name : ""; + + but = uiDefMenuBut(block, ui_imageuser_view_menu_rr, rnd_pt, display_name, 0, 0, wmenu4, UI_UNIT_Y, TIP_("Select View")); + UI_but_func_set(but, image_multi_cb, rr, iuser); + UI_but_type_set_menu_from_pulldown(but); + } + } + + /* stereo image */ + else if (((image->flag & IMA_IS_STEREO) && (!show_stereo)) || + ((image->flag & IMA_IS_MULTIVIEW) && ((image->flag & IMA_IS_STEREO) == 0))) + { + ImageView *iv; + int nr = 0; + + for (iv = image->views.first; iv; iv = iv->next) { + if (nr++ == iuser->view) { + display_name = iv->name; + break; + } + } + + but = uiDefMenuBut(block, ui_imageuser_view_menu_multiview, rnd_pt, display_name, 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select View")); + UI_but_func_set(but, image_multiview_cb, image, iuser); + UI_but_type_set_menu_from_pulldown(but); } } @@ -734,13 +846,13 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char if (ima->source != IMA_SRC_GENERATED) { row = uiLayoutRow(layout, true); - if (ima->packedfile) + if (BKE_image_has_packedfile(ima)) uiItemO(row, "", ICON_PACKAGE, "image.unpack"); else uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack"); row = uiLayoutRow(row, true); - uiLayoutSetEnabled(row, ima->packedfile == NULL); + uiLayoutSetEnabled(row, BKE_image_has_packedfile(ima) == false); uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE); uiItemO(row, "", ICON_FILE_REFRESH, "image.reload"); } @@ -792,6 +904,17 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char uiItemR(row, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE); } + if ((scene->r.scemode & R_MULTIVIEW) != 0) { + uiItemS(layout); + + col = uiLayoutColumn(layout, false); + uiItemR(col, &imaptr, "use_multiview", 0, NULL, ICON_NONE); + + col = uiLayoutColumn(layout, false); + uiLayoutSetActive(col, RNA_boolean_get(&imaptr, "use_multiview")); + uiTemplateImageViews(col, &imaptr); + } + if (ima->source == IMA_SRC_MOVIE) { col = uiLayoutColumn(layout, false); uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE); @@ -962,6 +1085,101 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man } } +void uiTemplateImageStereo3d(uiLayout *layout, PointerRNA *stereo3d_format_ptr) +{ + Stereo3dFormat *stereo3d_format = stereo3d_format_ptr->data; + uiLayout *col; + + col = uiLayoutColumn(layout, false); + uiItemR(col, stereo3d_format_ptr, "display_mode", 0, NULL, ICON_NONE); + + switch (stereo3d_format->display_mode) { + case S3D_DISPLAY_ANAGLYPH: + { + uiItemR(col, stereo3d_format_ptr, "anaglyph_type", 0, NULL, ICON_NONE); + break; + } + case S3D_DISPLAY_INTERLACE: + { + uiItemR(col, stereo3d_format_ptr, "interlace_type", 0, NULL, ICON_NONE); + uiItemR(col, stereo3d_format_ptr, "use_interlace_swap", 0, NULL, ICON_NONE); + break; + } + case S3D_DISPLAY_SIDEBYSIDE: + { + uiItemR(col, stereo3d_format_ptr, "use_sidebyside_crosseyed", 0, NULL, ICON_NONE); + /* fall-through */ + } + case S3D_DISPLAY_TOPBOTTOM: + { + uiItemR(col, stereo3d_format_ptr, "use_squeezed_frame", 0, NULL, ICON_NONE); + break; + } + } +} + +static void uiTemplateViewsFormat(uiLayout *layout, PointerRNA *ptr, PointerRNA *stereo3d_format_ptr) +{ + uiLayout *col, *box; + + col = uiLayoutColumn(layout, false); + + uiItemL(col, IFACE_("Views Format:"), ICON_NONE); + uiItemR(uiLayoutRow(col, false), ptr, "views_format", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + + if (stereo3d_format_ptr) { + box = uiLayoutBox(col); + uiLayoutSetActive(box, RNA_enum_get(ptr, "views_format") == R_IMF_VIEWS_STEREO_3D); + uiTemplateImageStereo3d(box, stereo3d_format_ptr); + } +} + +void uiTemplateImageViews(uiLayout *layout, PointerRNA *imaptr) +{ + Image *ima = imaptr->data; + + if (ima->type != IMA_TYPE_MULTILAYER) { + PropertyRNA *prop; + PointerRNA stereo3d_format_ptr; + + prop = RNA_struct_find_property(imaptr, "stereo_3d_format"); + stereo3d_format_ptr = RNA_property_pointer_get(imaptr, prop); + + uiTemplateViewsFormat(layout, imaptr, &stereo3d_format_ptr); + } + else { + uiTemplateViewsFormat(layout, imaptr, NULL); + } +} + +void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA *ptr) +{ + ImageFormatData *imf = imfptr->data; + uiLayout *col; + + if (ptr) { + uiItemR(layout, ptr, "use_multiview", 0, NULL, ICON_NONE); + col = uiLayoutColumn(layout, false); + uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_multiview")); + } + else { + col = uiLayoutColumn(layout, false); + } + + if (imf->imtype != R_IMF_IMTYPE_MULTILAYER) { + PropertyRNA *prop; + PointerRNA stereo3d_format_ptr; + + prop = RNA_struct_find_property(imfptr, "stereo_3d_format"); + stereo3d_format_ptr = RNA_property_pointer_get(imfptr, prop); + + uiTemplateViewsFormat(col, imfptr, &stereo3d_format_ptr); + } + else { + uiTemplateViewsFormat(col, imfptr, NULL); + } +} + void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser) { Scene *scene = CTX_data_scene(C); diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 517cf64214c..5a3c3e90618 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -783,7 +783,7 @@ void draw_image_main(const bContext *C, ARegion *ar) Image *ima; ImBuf *ibuf; float zoomx, zoomy; - bool show_viewer, show_render, show_paint; + bool show_viewer, show_render, show_paint, show_stereo3d, show_multilayer; void *lock; /* XXX can we do this in refresh? */ @@ -813,6 +813,8 @@ void draw_image_main(const bContext *C, ARegion *ar) show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0; show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0; show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) && (show_render == false)); + show_stereo3d = (ima && (ima->flag & IMA_IS_STEREO) && (sima->iuser.flag & IMA_SHOW_STEREO)); + show_multilayer = ima && BKE_image_is_multilayer(ima); if (show_viewer) { /* use locked draw for drawing viewer image buffer since the compositor @@ -823,6 +825,14 @@ void draw_image_main(const bContext *C, ARegion *ar) BLI_lock_thread(LOCK_DRAW_IMAGE); } + if (show_stereo3d) { + if (show_multilayer) + /* update multiindex and pass for the current eye */ + BKE_image_multilayer_index(ima->rr, &sima->iuser); + else + BKE_image_multiview_index(ima, &sima->iuser); + } + ibuf = ED_space_image_acquire_buffer(sima, &lock); /* draw the image or grid */ diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 5890ed61118..6a5462bff45 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -30,14 +30,21 @@ #include #include +#include #include #include +#ifndef WIN32 +# include +#else +# include +#endif #include "MEM_guardedalloc.h" #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_string_utf8.h" #include "BLF_translation.h" @@ -60,6 +67,7 @@ #include "BKE_report.h" #include "BKE_screen.h" #include "BKE_sound.h" +#include "BKE_scene.h" #include "GPU_draw.h" #include "GPU_buffers.h" @@ -68,6 +76,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "IMB_moviecache.h" +#include "intern/openexr/openexr_multi.h" #include "RE_pipeline.h" @@ -936,6 +945,7 @@ static void image_filesel(bContext *C, wmOperator *op, const char *path) typedef struct ImageOpenData { PropertyPointerRNA pprop; ImageUser *iuser; + ImageFormatData im_format; } ImageOpenData; typedef struct ImageFrame { @@ -946,7 +956,6 @@ typedef struct ImageFrame { static void image_open_init(bContext *C, wmOperator *op) { ImageOpenData *iod; - op->customdata = iod = MEM_callocN(sizeof(ImageOpenData), __func__); iod->iuser = CTX_data_pointer_get_type(C, "image_user", &RNA_ImageUser).data; UI_context_active_but_prop_get_templateID(C, &iod->pprop.ptr, &iod->pprop.prop); @@ -1048,7 +1057,7 @@ static int image_open_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); ImageUser *iuser = NULL; - ImageOpenData *iod; + ImageOpenData *iod = op->customdata; PointerRNA idptr; Image *ima = NULL; char path[FILE_MAX]; @@ -1085,6 +1094,21 @@ static int image_open_exec(bContext *C, wmOperator *op) if (!op->customdata) image_open_init(C, op); + /* handle multiview images */ + if (RNA_boolean_get(op->ptr, "use_multiview")) { + ImageFormatData *imf = &iod->im_format; + + ima->flag |= IMA_USE_VIEWS; + ima->views_format = imf->views_format; + *ima->stereo3d_format = imf->stereo3d_format; + } + else { + ima->flag &= ~IMA_USE_VIEWS; + ima->flag &= ~IMA_IS_STEREO; + ima->flag &= ~IMA_IS_MULTIVIEW; + BKE_image_free_views(ima); + } + /* only image path after save, never ibuf */ if (is_relative_path) { if (!exists) { @@ -1128,6 +1152,8 @@ static int image_open_exec(bContext *C, wmOperator *op) iuser->framenr = 1; iuser->offset = frame_ofs - 1; iuser->fie_ima = 2; + iuser->scene = scene; + BKE_image_init_imageuser(ima, iuser); } /* XXX unpackImage frees image buffers */ @@ -1146,7 +1172,8 @@ static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED( SpaceImage *sima = CTX_wm_space_image(C); /* XXX other space types can call */ const char *path = U.textudir; Image *ima = NULL; - + Scene *scene = CTX_data_scene(C); + PropertyRNA *prop; if (sima) { ima = sima->image; } @@ -1185,11 +1212,44 @@ static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED( image_open_init(C, op); + /* show multiview save options only if scene has multiviews */ + prop = RNA_struct_find_property(op->ptr, "show_multiview"); + RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0); + image_filesel(C, op, path); return OPERATOR_RUNNING_MODAL; } +static bool image_open_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop) +{ + const char *prop_id = RNA_property_identifier(prop); + + return !(STREQ(prop_id, "filepath") || + STREQ(prop_id, "directory") || + STREQ(prop_id, "filename") + ); +} + +static void image_open_draw(bContext *UNUSED(C), wmOperator *op) +{ + uiLayout *layout = op->layout; + ImageOpenData *iod = op->customdata; + ImageFormatData *imf = &iod->im_format; + PointerRNA imf_ptr, ptr; + + /* main draw call */ + RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); + uiDefAutoButsRNA(layout, &ptr, image_open_draw_check_prop, '\0'); + + /* image template */ + RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr); + + /* multiview template */ + if (RNA_boolean_get(op->ptr, "show_multiview")) + uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr); +} + /* called by other space types too */ void IMAGE_OT_open(wmOperatorType *ot) { @@ -1202,6 +1262,7 @@ void IMAGE_OT_open(wmOperatorType *ot) ot->exec = image_open_exec; ot->invoke = image_open_invoke; ot->cancel = image_open_cancel; + ot->ui = image_open_draw; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1233,10 +1294,10 @@ static int image_match_len_exec(bContext *C, wmOperator *UNUSED(op)) } - if (!ima || !iuser || !ima->anim) + if (!ima || !iuser || !BKE_image_has_anim(ima)) return OPERATOR_CANCELLED; - iuser->frames = IMB_anim_get_duration(ima->anim, IMB_TC_RECORD_RUN); + iuser->frames = IMB_anim_get_duration(((ImageAnim *) ima->anims.first)->anim, IMB_TC_RECORD_RUN); BKE_image_user_frame_calc(iuser, scene->r.cfra, 0); return OPERATOR_FINISHED; @@ -1433,6 +1494,10 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima, } } + /* use the multiview image settings as the default */ + simopts->im_format.stereo3d_format = *ima->stereo3d_format; + simopts->im_format.views_format = ima->views_format; + /* color management */ BKE_color_managed_display_settings_copy(&simopts->im_format.display_settings, &scene->display_settings); BKE_color_managed_view_settings_copy(&simopts->im_format.view_settings, &scene->view_settings); @@ -1468,30 +1533,131 @@ static void save_image_options_to_op(SaveImageOptions *simopts, wmOperator *op) RNA_string_set(op->ptr, "filepath", simopts->filepath); } +/* returns the pass index for the view_id */ +static int get_multiview_pass_id(RenderResult *rr, ImageUser *iuser, const int view_id) +{ + RenderLayer *rl; + RenderPass *rpass; + int passtype; + short rl_index = 0, rp_index; + + if (rr == NULL || iuser == NULL) + return 0; + + if (BLI_listbase_count_ex(&rr->views, 2) < 2) + return iuser->pass; + + if (RE_HasFakeLayer(rr)) + rl_index ++; /* fake compo/sequencer layer */ + + rl = BLI_findlink(&rr->layers, rl_index); + if (!rl) return iuser->pass; + + rpass = BLI_findlink(&rl->passes, iuser->pass); + passtype = rpass->passtype; + + rp_index = 0; + for (rpass = rl->passes.first; rpass; rpass = rpass->next, rp_index++) { + if (rpass->passtype == passtype && + rpass->view_id == view_id) + { + return rp_index; + } + } + + return iuser->pass; +} + +static void save_image_post(wmOperator *op, ImBuf *ibuf, Image *ima, int ok, int save_copy, const char *relbase, int relative, int do_newpath, const char *filepath) +{ + if (ok) { + if (!save_copy) { + if (do_newpath) { + BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name)); + BLI_strncpy(ima->name, filepath, sizeof(ima->name)); + } + + ibuf->userflags &= ~IB_BITMAPDIRTY; + + /* change type? */ + if (ima->type == IMA_TYPE_R_RESULT) { + ima->type = IMA_TYPE_IMAGE; + + /* workaround to ensure the render result buffer is no longer used + * by this image, otherwise can crash when a new render result is + * created. */ + if (ibuf->rect && !(ibuf->mall & IB_rect)) + imb_freerectImBuf(ibuf); + if (ibuf->rect_float && !(ibuf->mall & IB_rectfloat)) + imb_freerectfloatImBuf(ibuf); + if (ibuf->zbuf && !(ibuf->mall & IB_zbuf)) + IMB_freezbufImBuf(ibuf); + if (ibuf->zbuf_float && !(ibuf->mall & IB_zbuffloat)) + IMB_freezbuffloatImBuf(ibuf); + } + if (ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER)) { + ima->source = IMA_SRC_FILE; + ima->type = IMA_TYPE_IMAGE; + } + + /* only image path, never ibuf */ + if (relative) { + BLI_path_rel(ima->name, relbase); /* only after saving */ + } + + IMB_colormanagment_colorspace_from_ibuf_ftype(&ima->colorspace_settings, ibuf); + + } + } + else { + BKE_reportf(op->reports, RPT_ERROR, "Could not write image %s", filepath); + } +} + +static void save_imbuf_post(ImBuf *ibuf, ImBuf *colormanaged_ibuf) +{ + if (colormanaged_ibuf != ibuf) { + /* This guys might be modified by image buffer write functions, + * need to copy them back from color managed image buffer to an + * original one, so file type of image is being properly updated. + */ + ibuf->ftype = colormanaged_ibuf->ftype; + ibuf->planes = colormanaged_ibuf->planes; + + IMB_freeImBuf(colormanaged_ibuf); + } +} + /** * \return success. * \note ``ima->name`` and ``ibuf->name`` should end up the same. + * \note for multiview the first ``ibuf`` is important to get the settings. */ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveImageOptions *simopts, bool do_newpath) { Image *ima = ED_space_image(sima); void *lock; ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock); + Scene *scene; + RenderResult *rr = NULL; bool ok = false; + WM_cursor_wait(1); + if (ibuf) { - ImBuf *colormanaged_ibuf; + ImBuf *colormanaged_ibuf = NULL; const char *relbase = ID_BLEND_PATH(CTX_data_main(C), &ima->id); const bool relative = (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path")); const bool save_copy = (RNA_struct_find_property(op->ptr, "copy") && RNA_boolean_get(op->ptr, "copy")); const bool save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render")); ImageFormatData *imf = &simopts->im_format; + const bool is_multilayer = imf->imtype == R_IMF_IMTYPE_MULTILAYER; + bool is_mono; + /* old global to ensure a 2nd save goes to same dir */ BLI_strncpy(G.ima, simopts->filepath, sizeof(G.ima)); - WM_cursor_wait(1); - if (ima->type == IMA_TYPE_R_RESULT) { /* enforce user setting for RGB or RGBA, but skip BW */ if (simopts->im_format.planes == R_IMF_PLANES_RGBA) { @@ -1512,83 +1678,197 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI } } - colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf); + /* we need renderresult for exr and rendered multiview */ + scene = CTX_data_scene(C); + rr = BKE_image_acquire_renderresult(scene, ima); + is_mono = rr ? BLI_listbase_count_ex(&rr->views, 2) < 2 : (ima->flag & IMA_IS_MULTIVIEW) == 0; - if (simopts->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) { - Scene *scene = CTX_data_scene(C); - RenderResult *rr = BKE_image_acquire_renderresult(scene, ima); - if (rr) { - ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, simopts->im_format.exr_codec); - } - else { + /* error handling */ + if (!rr) { + if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) { BKE_report(op->reports, RPT_ERROR, "Did not write, no Multilayer Image"); + goto cleanup; } - BKE_image_release_renderresult(scene, ima); } else { - ok = BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, &simopts->im_format, save_copy); - } - - if (ok) { - if (!save_copy) { - if (do_newpath) { - BLI_strncpy(ibuf->name, simopts->filepath, sizeof(ibuf->name)); - BLI_strncpy(ima->name, simopts->filepath, sizeof(ima->name)); + if (imf->views_format == R_IMF_VIEWS_STEREO_3D) { + if ((ima->flag & IMA_IS_STEREO) == 0) { + BKE_reportf(op->reports, RPT_ERROR, "Did not write, the image doesn't have a \"%s\" and \"%s\" views", + STEREO_LEFT_NAME, STEREO_RIGHT_NAME); + goto cleanup; } - ibuf->userflags &= ~IB_BITMAPDIRTY; - - /* change type? */ - if (ima->type == IMA_TYPE_R_RESULT) { - ima->type = IMA_TYPE_IMAGE; - - /* workaround to ensure the render result buffer is no longer used - * by this image, otherwise can crash when a new render result is - * created. */ - if (ibuf->rect && !(ibuf->mall & IB_rect)) - imb_freerectImBuf(ibuf); - if (ibuf->rect_float && !(ibuf->mall & IB_rectfloat)) - imb_freerectfloatImBuf(ibuf); - if (ibuf->zbuf && !(ibuf->mall & IB_zbuf)) - IMB_freezbufImBuf(ibuf); - if (ibuf->zbuf_float && !(ibuf->mall & IB_zbuffloat)) - IMB_freezbuffloatImBuf(ibuf); + /* it shouldn't ever happen*/ + if ((BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name)) == NULL) || + (BLI_findstring(&rr->views, STEREO_RIGHT_NAME, offsetof(RenderView, name)) == NULL)) + { + BKE_reportf(op->reports, RPT_ERROR, "Did not write, the image doesn't have a \"%s\" and \"%s\" views", + STEREO_LEFT_NAME, STEREO_RIGHT_NAME); + goto cleanup; } - if (ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER)) { - ima->source = IMA_SRC_FILE; - ima->type = IMA_TYPE_IMAGE; + } + } + + /* fancy multiview OpenEXR */ + if ((imf->imtype == R_IMF_IMTYPE_MULTILAYER) && (imf->views_format == R_IMF_VIEWS_MULTIVIEW)) { + ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, true, NULL); + save_image_post(op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath); + ED_space_image_release_buffer(sima, ibuf, lock); + } + else if ((imf->imtype == R_IMF_IMTYPE_OPENEXR) && (imf->views_format == R_IMF_VIEWS_MULTIVIEW)) { + /* treat special Openexr case separetely (this is the singlelayer multiview OpenEXR */ + BKE_imbuf_write_prepare(ibuf, imf); + ok = BKE_image_save_openexr_multiview(ima, ibuf, simopts->filepath, (IB_rect | IB_zbuf | IB_zbuffloat | IB_multiview)); + ED_space_image_release_buffer(sima, ibuf, lock); + } + /* regular mono pipeline */ + else if (is_mono) { + if (is_multilayer) { + ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, false, NULL); + } + else { + colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf); + ok = BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, imf, save_copy); + save_imbuf_post(ibuf, colormanaged_ibuf); + } + save_image_post(op, ibuf, ima, ok, (is_multilayer ? true : save_copy), relbase, relative, do_newpath, simopts->filepath); + ED_space_image_release_buffer(sima, ibuf, lock); + } + /* individual multiview images */ + else if (imf->views_format == R_IMF_VIEWS_INDIVIDUAL) { + size_t i; + unsigned char planes = ibuf->planes; + const size_t totviews = (rr ? BLI_listbase_count(&rr->views) : BLI_listbase_count(&ima->views)); + + if (!is_multilayer) { + ED_space_image_release_buffer(sima, ibuf, lock); + } + + for (i = 0; i < totviews; i++) { + char filepath[FILE_MAX]; + bool ok_view = false; + const char *view = rr ? ((RenderView *) BLI_findlink(&rr->views, i))->name : + ((ImageView *) BLI_findlink(&ima->views, i))->name; + + if (is_multilayer) { + BKE_scene_multiview_view_filepath_get(&scene->r, simopts->filepath, view, filepath); + ok_view = RE_WriteRenderResult(op->reports, rr, filepath, imf, false, view); + save_image_post(op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath); } + else { + /* copy iuser to get the correct ibuf for this view */ + ImageUser iuser = sima->iuser; + iuser.view = i; + iuser.flag &= ~IMA_SHOW_STEREO; + + if (rr) { + iuser.pass = get_multiview_pass_id(rr, &sima->iuser, i); + BKE_image_multilayer_index(rr, &iuser); + } + else { + BKE_image_multiview_index(ima, &iuser); + } + + ibuf = BKE_image_acquire_ibuf(sima->image, &iuser, &lock); + ibuf->planes = planes; - /* only image path, never ibuf */ - if (relative) { - BLI_path_rel(ima->name, relbase); /* only after saving */ + BKE_scene_multiview_view_filepath_get(&scene->r, simopts->filepath, view, filepath); + + colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf); + ok_view = BKE_imbuf_write_as(colormanaged_ibuf, filepath, &simopts->im_format, save_copy); + save_imbuf_post(ibuf, colormanaged_ibuf); + save_image_post(op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath); + BKE_image_release_ibuf(sima->image, ibuf, lock); } + ok &= ok_view; + } - IMB_colormanagment_colorspace_from_ibuf_ftype(&ima->colorspace_settings, ibuf); + if (is_multilayer) { + ED_space_image_release_buffer(sima, ibuf, lock); } } - else { - BKE_reportf(op->reports, RPT_ERROR, "Could not write image %s", simopts->filepath); - } + /* stereo (multiview) images */ + else if (simopts->im_format.views_format == R_IMF_VIEWS_STEREO_3D) { + if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) { + ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, false, NULL); + save_image_post(op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath); + ED_space_image_release_buffer(sima, ibuf, lock); + } + else { + ImBuf *ibuf_stereo[2] = {NULL}; + unsigned char planes = ibuf->planes; + const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + int i; - WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image); + /* we need to get the specific per-view buffers */ + ED_space_image_release_buffer(sima, ibuf, lock); + + for (i = 0; i < 2; i ++) { + ImageUser iuser = sima->iuser; + iuser.flag &= ~IMA_SHOW_STEREO; + + if (rr) { + int id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name)); + iuser.pass = get_multiview_pass_id(rr, &sima->iuser, id); + iuser.view = id; + + BKE_image_multilayer_index(rr, &iuser); + } + else { + iuser.view = i; + BKE_image_multiview_index(ima, &iuser); + } + + ibuf = BKE_image_acquire_ibuf(sima->image, &iuser, &lock); + + if (ibuf == NULL) { + BKE_report(op->reports, RPT_ERROR, "Did not write, unexpected error when saving stereo image"); + goto cleanup; + } - WM_cursor_wait(0); + ibuf->planes = planes; - if (colormanaged_ibuf != ibuf) { - /* This guys might be modified by image buffer write functions, - * need to copy them back from color managed image buffer to an - * original one, so file type of image is being properly updated. - */ - ibuf->ftype = colormanaged_ibuf->ftype; - ibuf->planes = colormanaged_ibuf->planes; + /* color manage the ImBuf leaving it ready for saving */ + colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, + &imf->view_settings, &imf->display_settings, imf); - IMB_freeImBuf(colormanaged_ibuf); + BKE_imbuf_write_prepare(colormanaged_ibuf, imf); + IMB_prepare_write_ImBuf(IMB_isfloat(colormanaged_ibuf), colormanaged_ibuf); + + /* duplicate buffer to prevent locker issue when using render result */ + ibuf_stereo[i] = IMB_dupImBuf(colormanaged_ibuf); + + save_imbuf_post(ibuf, colormanaged_ibuf); + BKE_image_release_ibuf(sima->image, ibuf, lock); + } + + ibuf = IMB_stereo3d_ImBuf(imf, ibuf_stereo[0], ibuf_stereo[1]); + + /* save via traditional path */ + ok = BKE_imbuf_write_as(ibuf, simopts->filepath, imf, save_copy); + + IMB_freeImBuf(ibuf); + + for (i = 0; i < 2; i ++) { + IMB_freeImBuf(ibuf_stereo[i]); + } + } } + + WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image); + + } + else { +cleanup: + ED_space_image_release_buffer(sima, ibuf, lock); } - ED_space_image_release_buffer(sima, ibuf, lock); + if (rr) { + BKE_image_release_renderresult(scene, ima); + } + + WM_cursor_wait(0); return ok; } @@ -1636,6 +1916,7 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS Image *ima = ED_space_image(sima); Scene *scene = CTX_data_scene(C); SaveImageOptions simopts; + PropertyRNA *prop; const bool save_as_render = ((ima->source == IMA_SRC_VIEWER) || (ima->flag & IMA_VIEW_AS_RENDER)); if (RNA_struct_property_is_set(op->ptr, "filepath")) @@ -1657,6 +1938,12 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS op->customdata = MEM_mallocN(sizeof(simopts.im_format), __func__); memcpy(op->customdata, &simopts.im_format, sizeof(simopts.im_format)); + /* show multiview save options only if image has multiviews */ + prop = RNA_struct_find_property(op->ptr, "show_multiview"); + RNA_property_boolean_set(op->ptr, prop, (ima->flag & IMA_IS_MULTIVIEW) != 0); + prop = RNA_struct_find_property(op->ptr, "use_multiview"); + RNA_property_boolean_set(op->ptr, prop, (ima->flag & IMA_IS_MULTIVIEW) != 0); + image_filesel(C, op, simopts.filepath); return OPERATOR_RUNNING_MODAL; @@ -1683,15 +1970,20 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) { uiLayout *layout = op->layout; ImageFormatData *imf = op->customdata; - PointerRNA ptr; + PointerRNA imf_ptr, ptr; + const bool is_multiview = RNA_boolean_get(op->ptr, "use_multiview"); /* image template */ - RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &ptr); - uiTemplateImageSettings(layout, &ptr, false); + RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr); + uiTemplateImageSettings(layout, &imf_ptr, false); /* main draw call */ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); uiDefAutoButsRNA(layout, &ptr, image_save_as_draw_check_prop, '\0'); + + /* multiview template */ + if (is_multiview) + uiTemplateImageFormatViews(layout, &imf_ptr, NULL); } static int image_save_as_poll(bContext *C) @@ -1714,8 +2006,6 @@ static int image_save_as_poll(bContext *C) void IMAGE_OT_save_as(wmOperatorType *ot) { -// PropertyRNA *prop; - /* identifiers */ ot->name = "Save As Image"; ot->idname = "IMAGE_OT_save_as"; @@ -1932,6 +2222,7 @@ static int image_new_exec(bContext *C, wmOperator *op) float color[4]; int width, height, floatbuf, gen_type, alpha; int gen_context; + int stereo3d; /* retrieve state */ sima = CTX_wm_space_image(C); @@ -1952,11 +2243,12 @@ static int image_new_exec(bContext *C, wmOperator *op) RNA_float_get_array(op->ptr, "color", color); alpha = RNA_boolean_get(op->ptr, "alpha"); gen_context = RNA_enum_get(op->ptr, "gen_context"); + stereo3d = RNA_boolean_get(op->ptr, "use_stereo_3d"); if (!alpha) color[3] = 1.0f; - ima = BKE_image_add_generated(bmain, width, height, name, alpha ? 32 : 24, floatbuf, gen_type, color); + ima = BKE_image_add_generated(bmain, width, height, name, alpha ? 32 : 24, floatbuf, gen_type, color, stereo3d); if (!ima) return OPERATOR_CANCELLED; @@ -2036,6 +2328,53 @@ static int image_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, 5 * UI_UNIT_Y); } +static void image_new_draw(bContext *UNUSED(C), wmOperator *op) +{ + uiLayout *split, *col[2]; + uiLayout *layout = op->layout; + PointerRNA ptr; +#if 0 + Scene *scene = CTX_data_scene(C); + const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0; +#endif + + RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); + + /* copy of WM_operator_props_dialog_popup() layout */ + + split = uiLayoutSplit(layout, 0.5f, false); + col[0] = uiLayoutColumn(split, false); + col[1] = uiLayoutColumn(split, false); + + uiItemL(col[0], IFACE_("Name"), ICON_NONE); + uiItemR(col[1], &ptr, "name", 0, "", ICON_NONE); + + uiItemL(col[0], IFACE_("Width"), ICON_NONE); + uiItemR(col[1], &ptr, "width", 0, "", ICON_NONE); + + uiItemL(col[0], IFACE_("Height"), ICON_NONE); + uiItemR(col[1], &ptr, "height", 0, "", ICON_NONE); + + uiItemL(col[0], IFACE_("Color"), ICON_NONE); + uiItemR(col[1], &ptr, "color", 0, "", ICON_NONE); + + uiItemL(col[0], "", ICON_NONE); + uiItemR(col[1], &ptr, "alpha", 0, NULL, ICON_NONE); + + uiItemL(col[0], IFACE_("Generated Type"), ICON_NONE); + uiItemR(col[1], &ptr, "generated_type", 0, "", ICON_NONE); + + uiItemL(col[0], "", ICON_NONE); + uiItemR(col[1], &ptr, "float", 0, NULL, ICON_NONE); + +#if 0 + if (is_multiview) { + uiItemL(col[0], "", ICON_NONE); + uiItemR(col[1], &ptr, "use_stereo_3d", 0, NULL, ICON_NONE); + } +#endif +} + void IMAGE_OT_new(wmOperatorType *ot) { PropertyRNA *prop; @@ -2056,6 +2395,7 @@ void IMAGE_OT_new(wmOperatorType *ot) /* api callbacks */ ot->exec = image_new_exec; ot->invoke = image_new_invoke; + ot->ui = image_new_draw; /* flags */ ot->flag = OPTYPE_UNDO; @@ -2075,7 +2415,8 @@ void IMAGE_OT_new(wmOperatorType *ot) RNA_def_boolean(ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth"); prop = RNA_def_enum(ot->srna, "gen_context", gen_context_items, 0, "Gen Context", "Generation context"); RNA_def_property_flag(prop, PROP_HIDDEN); - + prop = RNA_def_boolean(ot->srna, "use_stereo_3d", 0, "Stereo 3D", "Create an image with left and right views"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); } #undef IMA_DEF_NAME @@ -2200,7 +2541,7 @@ static bool image_pack_test(bContext *C, wmOperator *op) if (!ima) return 0; - if (!as_png && ima->packedfile) + if (!as_png && BKE_image_has_packedfile(ima)) return 0; if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) { @@ -2229,7 +2570,7 @@ static int image_pack_exec(bContext *C, wmOperator *op) if (as_png) BKE_image_memorypack(ima); else - ima->packedfile = newPackedFile(op->reports, ima->name, ID_BLEND_PATH(bmain, &ima->id)); + BKE_image_packfiles(op->reports, ima, ID_BLEND_PATH(bmain, &ima->id)); WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); @@ -2301,7 +2642,7 @@ static int image_unpack_exec(bContext *C, wmOperator *op) if (!ima) ima = CTX_data_edit_image(C); } - if (!ima || !ima->packedfile) + if (!ima || !BKE_image_has_packedfile(ima)) return OPERATOR_CANCELLED; if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) { @@ -2329,7 +2670,7 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE if (RNA_struct_property_is_set(op->ptr, "id")) return image_unpack_exec(C, op); - if (!ima || !ima->packedfile) + if (!ima || !BKE_image_has_packedfile(ima)) return OPERATOR_CANCELLED; if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) { @@ -2340,7 +2681,7 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE if (G.fileflags & G_AUTOPACK) BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save"); - unpack_menu(C, "IMAGE_OT_unpack", ima->id.name + 2, ima->name, "textures", ima->packedfile); + unpack_menu(C, "IMAGE_OT_unpack", ima->id.name + 2, ima->name, "textures", BKE_image_has_packedfile(ima) ? ((ImagePackedFile *)ima->packedfiles.first)->packedfile : NULL); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index bd3d76bbaba..1023f9641b3 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -156,7 +156,8 @@ static SpaceLink *image_new(const bContext *UNUSED(C)) simage->iuser.ok = true; simage->iuser.fie_ima = 2; simage->iuser.frames = 100; - + simage->iuser.flag = IMA_SHOW_STEREO; + scopes_new(&simage->scopes); simage->sample_line_hist.height = 100; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 6fa164a483f..d08a8bacd29 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -703,7 +703,9 @@ static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *ptr, uiItemR(col, ptr, "use_auto_refresh", 0, NULL, ICON_NONE); } - if (RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER) { + if (RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER && + RNA_boolean_get(ptr, "has_layers")) + { col = uiLayoutColumn(layout, false); uiItemR(col, ptr, "layer", 0, NULL, ICON_NONE); } @@ -1214,6 +1216,24 @@ static void node_shader_set_butfunc(bNodeType *ntype) /* ****************** BUTTON CALLBACKS FOR COMPOSITE NODES ***************** */ +static void node_buts_image_views(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr, + PointerRNA *imaptr) +{ + uiLayout *col; + + if (!imaptr->data) + return; + + col = uiLayoutColumn(layout, false); + + if (RNA_boolean_get(ptr, "has_views")) { + if (RNA_enum_get(ptr, "view") == 0) + uiItemR(col, ptr, "view", 0, NULL, ICON_CAMERA_STEREO); + else + uiItemR(col, ptr, "view", 0, NULL, ICON_SCENE); + } +} + static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr) { bNode *node = ptr->data; @@ -1227,6 +1247,8 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA * imaptr = RNA_pointer_get(ptr, "image"); node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr); + + node_buts_image_views(layout, C, ptr, &imaptr); } static void node_composit_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -1717,8 +1739,8 @@ static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), Po static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { PointerRNA imfptr = RNA_pointer_get(ptr, "format"); - int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER); - + const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER; + if (multilayer) uiItemL(layout, IFACE_("Path:"), ICON_NONE); else @@ -1727,15 +1749,22 @@ static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C) } static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) { + Scene *scene = CTX_data_scene(C); PointerRNA imfptr = RNA_pointer_get(ptr, "format"); PointerRNA active_input_ptr, op_ptr; uiLayout *row, *col; int active_index; - int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER); + const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER; + const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0; node_composit_buts_file_output(layout, C, ptr); uiTemplateImageSettings(layout, &imfptr, false); + /* disable stereo output for multilayer, too much work for something that no one will use */ + /* if someone asks for that we can implement it */ + if (is_multiview) + uiTemplateImageFormatViews(layout, &imfptr, NULL); + uiItemS(layout); uiItemO(layout, IFACE_("Add Input"), ICON_ZOOMIN, "NODE_OT_output_file_add_socket"); @@ -1797,6 +1826,9 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi col = uiLayoutColumn(layout, false); uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == false); uiTemplateImageSettings(col, &imfptr, false); + + if (is_multiview) + uiTemplateImageFormatViews(layout, &imfptr, NULL); } } } @@ -2090,6 +2122,18 @@ static void node_composit_buts_switch(uiLayout *layout, bContext *UNUSED(C), Poi uiItemR(layout, ptr, "check", 0, NULL, ICON_NONE); } +static void node_composit_buts_switch_view_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *UNUSED(ptr)) +{ + PointerRNA op_ptr; + wmOperatorType *ot = WM_operatortype_find("NODE_OT_switch_view_update", 1); + + BLI_assert(ot != 0); + + WM_operator_properties_create_ptr(&op_ptr, ot); + + uiItemFullO_ptr(layout, ot, "Update Views", ICON_FILE_REFRESH, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); +} + static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *row; @@ -2587,6 +2631,9 @@ static void node_composit_set_butfunc(bNodeType *ntype) case CMP_NODE_SWITCH: ntype->draw_buttons = node_composit_buts_switch; break; + case CMP_NODE_SWITCH_VIEW: + ntype->draw_buttons_ex = node_composit_buts_switch_view_ex; + break; case CMP_NODE_MASK_BOX: ntype->draw_buttons = node_composit_buts_boxmask; ntype->draw_backdrop = node_composit_backdrop_boxmask; @@ -2959,6 +3006,7 @@ static void node_file_output_socket_draw(bContext *C, uiLayout *layout, PointerR imfptr = RNA_pointer_get(node_ptr, "format"); imtype = RNA_enum_get(&imfptr, "file_format"); + if (imtype == R_IMF_IMTYPE_MULTILAYER) { NodeImageMultiFileSocket *input = sock->storage; RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotLayer, input, &inputptr); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 27af4e7490b..80ecab09442 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -212,13 +212,13 @@ static void compo_progressjob(void *cjv, float progress) *(cj->progress) = progress; } - /* only this runs inside thread */ static void compo_startjob(void *cjv, short *stop, short *do_update, float *progress) { CompoJob *cj = cjv; bNodeTree *ntree = cj->localtree; Scene *scene = cj->scene; + SceneRenderView *srv; if (scene->use_nodes == false) return; @@ -238,7 +238,11 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog // XXX BIF_store_spare(); /* 1 is do_previews */ - ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings); + + for (srv = scene->r.views.first; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(&scene->r, srv) == false) continue; + ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings, srv->name); + } ntree->test_break = NULL; ntree->stats_draw = NULL; @@ -1660,6 +1664,54 @@ void NODE_OT_delete(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/* ****************** Switch View ******************* */ + +static int node_switch_view_poll(bContext *C) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + if (snode && snode->edittree) + return true; + + return false; +} + +static int node_switch_view_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNode *node, *next; + + for (node = snode->edittree->nodes.first; node; node = next) { + next = node->next; + if (node->flag & SELECT) { + /* call the update function from the Switch View node */ + node->update = NODE_UPDATE_OPERATOR; + } + } + + ntreeUpdateTree(CTX_data_main(C), snode->edittree); + + snode_notify(C, snode); + snode_dag_update(C, snode); + + return OPERATOR_FINISHED; +} + +void NODE_OT_switch_view_update(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Update Views"; + ot->description = "Update views of selected node"; + ot->idname = "NODE_OT_switch_view_update"; + + /* api callbacks */ + ot->exec = node_switch_view_exec; + ot->poll = node_switch_view_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + /* ****************** Delete with reconnect ******************* */ static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op)) { diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index d49d37c651e..b15e9025a82 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -200,6 +200,8 @@ void NODE_OT_output_file_add_socket(struct wmOperatorType *ot); void NODE_OT_output_file_remove_active_socket(struct wmOperatorType *ot); void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot); +void NODE_OT_switch_view_update (struct wmOperatorType *ot); + /* Note: clipboard_cut is a simple macro of copy + delete */ void NODE_OT_clipboard_copy(struct wmOperatorType *ot); void NODE_OT_clipboard_paste(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index e2d83c243a2..474ad4db4af 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -123,6 +123,8 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_viewer_border); WM_operatortype_append(NODE_OT_clear_viewer_border); + WM_operatortype_append(NODE_OT_switch_view_update); + WM_operatortype_append(NODE_OT_tree_socket_add); WM_operatortype_append(NODE_OT_tree_socket_remove); WM_operatortype_append(NODE_OT_tree_socket_move); diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 329e6db4cd0..373095d68f9 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -60,6 +60,7 @@ #include "ED_screen.h" #include "ED_sequencer.h" +#include "UI_interface.h" #include "BKE_sound.h" @@ -70,6 +71,10 @@ /* own include */ #include "sequencer_intern.h" +typedef struct SequencerAddData { + ImageFormatData im_format; +} SequencerAddData; + /* Generic functions, reused by add strip operators */ /* avoid passing multiple args and be more verbose */ @@ -222,6 +227,19 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, wmOperator *op) } RNA_PROP_END; } + + if ((prop = RNA_struct_find_property(op->ptr, "use_multiview")) && RNA_property_boolean_get(op->ptr, prop)) { + if (op->customdata) { + SequencerAddData *sad = op->customdata; + ImageFormatData *imf = &sad->im_format; + + seq_load->views_format = imf->views_format; + seq_load->flag |= SEQ_USE_VIEWS; + + /* operator custom data is always released after the SeqLoadInfo, no need to handle the memory here */ + seq_load->stereo3d_format = &imf->stereo3d_format; + } + } } /** @@ -573,6 +591,9 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad return OPERATOR_CANCELLED; } + if (op->customdata) + MEM_freeN(op->customdata); + BKE_sequencer_sort(scene); BKE_sequencer_update_muting(ed); @@ -581,15 +602,40 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad return OPERATOR_FINISHED; } +/* add sequencer operators */ +static void sequencer_add_init(bContext *UNUSED(C), wmOperator *op) +{ + op->customdata = MEM_callocN(sizeof(SequencerAddData), __func__); +} + +static void sequencer_add_cancel(bContext *UNUSED(C), wmOperator *op) +{ + if (op->customdata) + MEM_freeN(op->customdata); + op->customdata = NULL; +} + +static bool sequencer_add_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop) +{ + const char *prop_id = RNA_property_identifier(prop); + + return !(STREQ(prop_id, "filepath") || + STREQ(prop_id, "directory") || + STREQ(prop_id, "filename") + ); +} + /* add movie operator */ static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op) { return sequencer_add_generic_strip_exec(C, op, BKE_sequencer_add_movie_strip); } - static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { + PropertyRNA *prop; + Scene *scene = CTX_data_scene(C); + /* This is for drag and drop */ if ((RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) || RNA_struct_property_is_set(op->ptr, "filepath")) @@ -599,13 +645,37 @@ static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, const w } sequencer_generic_invoke_xy__internal(C, op, 0, SEQ_TYPE_MOVIE); - + + sequencer_add_init(C, op); + + /* show multiview save options only if scene has multiviews */ + prop = RNA_struct_find_property(op->ptr, "show_multiview"); + RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0); + WM_event_add_fileselect(C, op); return OPERATOR_RUNNING_MODAL; //return sequencer_add_movie_strip_exec(C, op); } +static void sequencer_add_draw(bContext *UNUSED(C), wmOperator *op) +{ + uiLayout *layout = op->layout; + SequencerAddData *sad = op->customdata; + ImageFormatData *imf = &sad->im_format; + PointerRNA imf_ptr, ptr; + + /* main draw call */ + RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); + uiDefAutoButsRNA(layout, &ptr, sequencer_add_draw_check_prop, '\0'); + + /* image template */ + RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr); + + /* multiview template */ + if (RNA_boolean_get(op->ptr, "show_multiview")) + uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr); +} void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot) { @@ -618,9 +688,11 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot) /* api callbacks */ ot->invoke = sequencer_add_movie_strip_invoke; ot->exec = sequencer_add_movie_strip_exec; + ot->cancel = sequencer_add_cancel; + ot->ui = sequencer_add_draw; ot->poll = ED_operator_sequencer_active_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -735,6 +807,9 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) sequencer_add_apply_overlap(C, op, seq); + if (op->customdata) + MEM_freeN(op->customdata); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -742,6 +817,9 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { + PropertyRNA *prop; + Scene *scene = CTX_data_scene(C); + /* drag drop has set the names */ if (RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) { sequencer_generic_invoke_xy__internal(C, op, SEQPROP_ENDFRAME | SEQPROP_NOPATHS, SEQ_TYPE_IMAGE); @@ -750,6 +828,12 @@ static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, const w sequencer_generic_invoke_xy__internal(C, op, SEQPROP_ENDFRAME, SEQ_TYPE_IMAGE); + sequencer_add_init(C, op); + + /* show multiview save options only if scene has multiviews */ + prop = RNA_struct_find_property(op->ptr, "show_multiview"); + RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0); + WM_event_add_fileselect(C, op); return OPERATOR_RUNNING_MODAL; } @@ -766,6 +850,8 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot) /* api callbacks */ ot->invoke = sequencer_add_image_strip_invoke; ot->exec = sequencer_add_image_strip_exec; + ot->cancel = sequencer_add_cancel; + ot->ui = sequencer_add_draw; ot->poll = ED_operator_sequencer_active_editable; diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index ec4ae5a3a62..baadc28cd65 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -50,6 +50,7 @@ #include "BKE_main.h" #include "BKE_sequencer.h" #include "BKE_sound.h" +#include "BKE_scene.h" #include "IMB_colormanagement.h" #include "IMB_imbuf.h" @@ -860,7 +861,7 @@ void ED_sequencer_special_preview_clear(void) sequencer_special_update_set(NULL); } -ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int cfra, int frame_ofs) +ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int cfra, int frame_ofs, const char *viewname) { SeqRenderData context; ImBuf *ibuf; @@ -888,6 +889,7 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int bmain->eval_ctx, bmain, scene, rectx, recty, proxy_size, &context); + context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname); /* sequencer could start rendering, in this case we need to be sure it wouldn't be canceled * by Esc pressed somewhere in the past @@ -994,6 +996,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq const bool is_imbuf = ED_space_sequencer_check_show_imbuf(sseq); int format, type; bool glsl_used = false; + const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; if (G.is_rendering == false && (scene->r.seq_flag & R_SEQ_GL_PREV) == 0) { /* stop all running jobs, except screen one. currently previews frustrate Render @@ -1023,8 +1026,9 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq return; } - ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs); - + /* for now we only support Left/Right */ + ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs, names[sseq->multiview_eye]); + if (ibuf == NULL) return; diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index ad38cb66946..138d9b943fc 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -180,8 +180,6 @@ static void seq_proxy_build_job(const bContext *C) Scene *scene = CTX_data_scene(C); Editing *ed = BKE_sequencer_editing_get(scene, false); ScrArea *sa = CTX_wm_area(C); - struct SeqIndexBuildContext *context; - LinkData *link; Sequence *seq; GSet *file_list; @@ -209,9 +207,7 @@ static void seq_proxy_build_job(const bContext *C) SEQP_BEGIN (ed, seq) { if ((seq->flag & SELECT)) { - context = BKE_sequencer_proxy_rebuild_context(pj->main, pj->scene, seq, file_list); - link = BLI_genericNodeN(context); - BLI_addtail(&pj->queue, link); + BKE_sequencer_proxy_rebuild_context(pj->main, pj->scene, seq, file_list, &pj->queue); } } SEQ_END @@ -3442,12 +3438,18 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op)) SEQP_BEGIN(ed, seq) { if ((seq->flag & SELECT)) { - struct SeqIndexBuildContext *context; + ListBase queue = {NULL, NULL}; + LinkData *link; short stop = 0, do_update; float progress; - context = BKE_sequencer_proxy_rebuild_context(bmain, scene, seq, file_list); - BKE_sequencer_proxy_rebuild(context, &stop, &do_update, &progress); - BKE_sequencer_proxy_rebuild_finish(context, 0); + + BKE_sequencer_proxy_rebuild_context(bmain, scene, seq, file_list, &queue); + + for (link = queue.first; link; link = link->next) { + struct SeqIndexBuildContext *context = link->data; + BKE_sequencer_proxy_rebuild(context, &stop, &do_update, &progress); + BKE_sequencer_proxy_rebuild_finish(context, 0); + } BKE_sequencer_free_imbuf(scene, &ed->seqbase, false); } } diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index b02e254370a..78255507321 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -62,7 +62,7 @@ void sequencer_special_update_set(Sequence *seq); /* UNUSED */ // void seq_reset_imageofs(struct SpaceSeq *sseq); -struct ImBuf *sequencer_ibuf_get(struct Main *bmain, struct Scene *scene, struct SpaceSeq *sseq, int cfra, int frame_ofs); +struct ImBuf *sequencer_ibuf_get(struct Main *bmain, struct Scene *scene, struct SpaceSeq *sseq, int cfra, int frame_ofs, const char *viewname); /* sequencer_edit.c */ struct View2D; diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index 7fdbc9cc7de..4eafd2f86a8 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -94,7 +94,7 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event) Scene *scene = CTX_data_scene(C); SpaceSeq *sseq = (SpaceSeq *) CTX_wm_space_data(C); ARegion *ar = CTX_wm_region(C); - ImBuf *ibuf = sequencer_ibuf_get(bmain, scene, sseq, CFRA, 0); + ImBuf *ibuf = sequencer_ibuf_get(bmain, scene, sseq, CFRA, 0, NULL); ImageSampleInfo *info = op->customdata; float fx, fy; diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index f14c19dc07e..f0b78649307 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -1741,6 +1741,238 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, GPU_select_load_id(base->selcol); } +static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], const GLenum mode) +{ + glBegin(mode); + glVertex3fv(near_plane[0]); + glVertex3fv(far_plane[0]); + glVertex3fv(far_plane[1]); + glVertex3fv(near_plane[1]); + glEnd(); + + glBegin(mode); + glVertex3fv(near_plane[1]); + glVertex3fv(far_plane[1]); + glVertex3fv(far_plane[2]); + glVertex3fv(near_plane[2]); + glEnd(); + + glBegin(mode); + glVertex3fv(near_plane[2]); + glVertex3fv(near_plane[1]); + glVertex3fv(far_plane[1]); + glVertex3fv(far_plane[2]); + glEnd(); + + glBegin(mode); + glVertex3fv(far_plane[0]); + glVertex3fv(near_plane[0]); + glVertex3fv(near_plane[3]); + glVertex3fv(far_plane[3]); + glEnd(); +} + +/* camera frame */ +static void drawcamera_frame(float vec[4][3], const GLenum mode) +{ + glBegin(mode); + glVertex3fv(vec[0]); + glVertex3fv(vec[1]); + glVertex3fv(vec[2]); + glVertex3fv(vec[3]); + glEnd(); +} + +/* center point to camera frame */ +static void drawcamera_framelines(float vec[4][3], float origin[3]) +{ + glBegin(GL_LINE_STRIP); + glVertex3fv(vec[1]); + glVertex3fv(origin); + glVertex3fv(vec[0]); + glVertex3fv(vec[3]); + glVertex3fv(origin); + glVertex3fv(vec[2]); + glEnd(); +} + +static bool drawcamera_is_stereo3d(Scene *scene, View3D *v3d, Object *ob) +{ + return (ob == v3d->camera) && + (scene->r.scemode & R_MULTIVIEW) != 0 && + (v3d->stereo3d_flag); +} + +static void drawcamera_stereo3d( + Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const Camera *cam, + float vec[4][3], float drawsize, const float scale[3]) +{ + int i, j; + float obmat[4][4]; + float vec_lr[2][4][3]; + const float fac = (cam->stereo.pivot == CAM_S3D_PIVOT_CENTER) ? 2.0f : 1.0f; + float origin[2][3] = {{0}}; + float tvec[3]; + const Camera *cam_lr[2]; + const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + + const bool is_stereo3d_cameras = (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS) && (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D); + const bool is_stereo3d_plane = (v3d->stereo3d_flag & V3D_S3D_DISPPLANE) && (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D); + const bool is_stereo3d_volume = (v3d->stereo3d_flag & V3D_S3D_DISPVOLUME); + + zero_v3(tvec); + + glPushMatrix(); + + for (i = 0; i < 2; i++) { + ob = BKE_camera_multiview_render(scene, ob, names[i]); + cam_lr[i] = ob->data; + + glLoadMatrixf(rv3d->viewmat); + BKE_camera_multiview_model_matrix(&scene->r, ob, names[i], obmat); + glMultMatrixf(obmat); + + copy_m3_m3(vec_lr[i], vec); + copy_v3_v3(vec_lr[i][3], vec[3]); + + if (cam->stereo.convergence_mode == CAM_S3D_OFFAXIS) { + const float shift_x = + ((BKE_camera_multiview_shift_x(&scene->r, ob, names[i]) - cam->shiftx) * + (drawsize * scale[0] * fac)); + + for (j = 0; j < 4; j++) { + vec_lr[i][j][0] += shift_x; + } + } + + if (is_stereo3d_cameras) { + /* camera frame */ + drawcamera_frame(vec_lr[i], GL_LINE_LOOP); + + /* center point to camera frame */ + drawcamera_framelines(vec_lr[i], tvec); + } + + /* connecting line */ + mul_m4_v3(obmat, origin[i]); + + /* convergence plane */ + if (is_stereo3d_plane || is_stereo3d_volume) { + for (j = 0; j < 4; j++) { + mul_m4_v3(obmat, vec_lr[i][j]); + } + } + } + + + /* the remaining drawing takes place in the view space */ + glLoadMatrixf(rv3d->viewmat); + + if (is_stereo3d_cameras) { + /* draw connecting lines */ + glPushAttrib(GL_ENABLE_BIT); + + glLineStipple(2, 0xAAAA); + glEnable(GL_LINE_STIPPLE); + + glBegin(GL_LINES); + glVertex3fv(origin[0]); + glVertex3fv(origin[1]); + glEnd(); + glPopAttrib(); + } + + /* draw convergence plane*/ + if (is_stereo3d_plane) { + float axis_center[3], screen_center[3]; + float world_plane[4][3]; + float local_plane[4][3]; + float offset; + + mid_v3_v3v3(axis_center, origin[0], origin[1]); + + for (i = 0; i < 4; i++) { + mid_v3_v3v3(world_plane[i], vec_lr[0][i], vec_lr[1][i]); + sub_v3_v3v3(local_plane[i], world_plane[i], axis_center); + } + + mid_v3_v3v3(screen_center, world_plane[0], world_plane[2]); + offset = cam->stereo.convergence_distance / len_v3v3(screen_center, axis_center); + + for (i = 0; i < 4; i++) { + mul_v3_fl(local_plane[i], offset); + add_v3_v3(local_plane[i], axis_center); + } + + glColor3f(0.0f, 0.0f, 0.0f); + + /* camera frame */ + drawcamera_frame(local_plane, GL_LINE_LOOP); + + if (v3d->stereo3d_convergence_alpha > 0.0f) { + glEnable(GL_BLEND); + glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + + glColor4f(0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha); + + drawcamera_frame(local_plane, GL_QUADS); + + glDisable(GL_BLEND); + glDepthMask(1); /* restore write in zbuffer */ + } + } + + /* draw convergence plane*/ + if (is_stereo3d_volume) { + float screen_center[3]; + float near_plane[4][3], far_plane[4][3]; + float offset; + int j; + + for (i = 0; i < 2; i++) { + mid_v3_v3v3(screen_center, vec_lr[i][0], vec_lr[i][2]); + + offset = len_v3v3(screen_center, origin[i]); + + for (j = 0; j < 4; j++) { + sub_v3_v3v3(near_plane[j], vec_lr[i][j], origin[i]); + mul_v3_fl(near_plane[j], cam_lr[i]->clipsta / offset); + add_v3_v3(near_plane[j], origin[i]); + + sub_v3_v3v3(far_plane[j], vec_lr[i][j], origin[i]); + mul_v3_fl(far_plane[j], cam_lr[i]->clipend / offset); + add_v3_v3(far_plane[j], origin[i]); + } + + /* camera frame */ + glColor3f(0.0f, 0.0f, 0.0f); + + drawcamera_frame(near_plane, GL_LINE_LOOP); + drawcamera_frame(far_plane, GL_LINE_LOOP); + drawcamera_volume(near_plane, far_plane, GL_LINE_LOOP); + + if (v3d->stereo3d_volume_alpha > 0.0f) { + glEnable(GL_BLEND); + glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + + if (i == 0) + glColor4f(0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha); + else + glColor4f(1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha); + + drawcamera_frame(near_plane, GL_QUADS); + drawcamera_frame(far_plane, GL_QUADS); + drawcamera_volume(near_plane, far_plane, GL_QUADS); + + glDisable(GL_BLEND); + glDepthMask(1); /* restore write in zbuffer */ + } + } + } + + glPopMatrix(); +} + /* flag similar to draw_object() */ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const short dflag, const unsigned char ob_wire_col[4]) @@ -1755,6 +1987,12 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base const bool is_view = (rv3d->persp == RV3D_CAMOB && ob == v3d->camera); MovieClip *clip = BKE_object_movieclip_get(scene, base->object, false); + const bool is_stereo3d = drawcamera_is_stereo3d(scene, v3d, ob); + const bool is_stereo3d_cameras = (ob == scene->camera) && + (scene->r.scemode & R_MULTIVIEW) && + (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) && + (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS); + /* draw data for movie clip set as active for scene */ if (clip) { draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, false); @@ -1791,12 +2029,8 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base glDisable(GL_CULL_FACE); /* camera frame */ - glBegin(GL_LINE_LOOP); - glVertex3fv(vec[0]); - glVertex3fv(vec[1]); - glVertex3fv(vec[2]); - glVertex3fv(vec[3]); - glEnd(); + if (!is_stereo3d_cameras) + drawcamera_frame(vec, GL_LINE_LOOP); if (is_view) return; @@ -1804,20 +2038,12 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base zero_v3(tvec); /* center point to camera frame */ - glBegin(GL_LINE_STRIP); - glVertex3fv(vec[1]); - glVertex3fv(tvec); - glVertex3fv(vec[0]); - glVertex3fv(vec[3]); - glVertex3fv(tvec); - glVertex3fv(vec[2]); - glEnd(); - + if (!is_stereo3d_cameras) + drawcamera_framelines(vec, tvec); /* arrow on top */ tvec[2] = vec[1][2]; /* copy the depth */ - /* draw an outline arrow for inactive cameras and filled * for active cameras. We actually draw both outline+filled * for active cameras so the wire can be seen side-on */ @@ -1867,6 +2093,11 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base glPopMatrix(); } } + + /* stereo cameras drawing */ + if (is_stereo3d) { + drawcamera_stereo3d(scene, v3d, rv3d, ob, cam, vec, drawsize, scale); + } } /* flag similar to draw_object() */ diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index ddb3e2f20c5..f8345e91afd 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -344,7 +344,13 @@ static SpaceLink *view3d_new(const bContext *C) v3d->bundle_size = 0.2f; v3d->bundle_drawtype = OB_PLAINAXES; - + + /* stereo */ + v3d->stereo3d_camera = STEREO_3D_ID; + v3d->stereo3d_flag |= V3D_S3D_DISPPLANE; + v3d->stereo3d_convergence_alpha = 0.15f; + v3d->stereo3d_volume_alpha = 0.05f; + /* header */ ar = MEM_callocN(sizeof(ARegion), "header for view3d"); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index e480593b1e5..95a1ab87348 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -50,6 +50,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_endian_switch.h" +#include "BLI_threads.h" #include "BKE_anim.h" #include "BKE_camera.h" @@ -100,6 +101,11 @@ #include "view3d_intern.h" /* own include */ +/* prototypes */ +static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar); +static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar, + float winmat[4][4], const char *viewname); + /* handy utility for drawing shapes in the viewport for arbitrary code. * could add lines and points too */ // #define DEBUG_DRAW @@ -1603,6 +1609,24 @@ exit: /* ************************************************************* */ +static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser) +{ + if ((ima->flag & IMA_IS_STEREO)) { + iuser->flag |= IMA_SHOW_STEREO; + + if ((scene->r.scemode & R_MULTIVIEW) == 0) + iuser->multiview_eye = STEREO_LEFT_ID; + + /* show only left or right camera */ + else if (v3d->stereo3d_camera != STEREO_3D_ID) + iuser->multiview_eye = v3d->stereo3d_camera; + + BKE_image_multiview_index(ima, iuser); + } + else + iuser->flag &= ~IMA_SHOW_STEREO; +} + static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, const bool do_foreground, const bool do_camera_frame) { @@ -1646,6 +1670,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, ibuf = NULL; /* frame is out of range, dont show */ } else { + view3d_stereo_bgpic_setup(scene, v3d, ima, &bgpic->iuser); ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, &lock); releaseibuf = ibuf; } @@ -2551,7 +2576,7 @@ static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d) ED_view3d_draw_offscreen( scene, v3d, &ar, winsize, winsize, viewmat, winmat, false, false, true, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); GPU_lamp_shadow_buffer_unbind(shadow->lamp); v3d->drawtype = drawtype; @@ -3097,7 +3122,8 @@ void ED_view3d_draw_offscreen( float viewmat[4][4], float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp, GPUOffScreen *ofs, - GPUFX *fx, GPUFXSettings *fx_settings) + GPUFX *fx, GPUFXSettings *fx_settings, + const char *viewname) { struct bThemeState theme_state; int bwinx, bwiny; @@ -3132,7 +3158,10 @@ void ED_view3d_draw_offscreen( } /* setup view matrices before fx or unbinding the offscreen buffers will cause issues */ - view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat); + if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL)) + view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname); + else + view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat); /* framebuffer fx needed, we need to draw offscreen first */ if (v3d->fx_settings.fx_flag && fx) { @@ -3196,7 +3225,7 @@ void ED_view3d_draw_offscreen( /* utility func for ED_view3d_draw_offscreen */ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey, unsigned int flag, - bool draw_background, int alpha_mode, char err_out[256]) + bool draw_background, int alpha_mode, const char *viewname, char err_out[256]) { RegionView3D *rv3d = ar->regiondata; ImBuf *ibuf; @@ -3221,28 +3250,29 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in if (rv3d->persp == RV3D_CAMOB && v3d->camera) { CameraParams params; GPUFXSettings fx_settings = {NULL}; - Object *camera = v3d->camera; + Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); BKE_camera_params_init(¶ms); /* fallback for non camera objects */ params.clipsta = v3d->near; params.clipend = v3d->far; - BKE_camera_params_from_object(¶ms, v3d->camera); + BKE_camera_params_from_object(¶ms, camera); + BKE_camera_multiview_params(&scene->r, ¶ms, camera, viewname); BKE_camera_params_compute_viewplane(¶ms, sizex, sizey, scene->r.xasp, scene->r.yasp); BKE_camera_params_compute_matrix(¶ms); BKE_camera_to_gpu_dof(camera, &fx_settings); ED_view3d_draw_offscreen( - scene, v3d, ar, sizex, sizey, NULL, params.winmat, + scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background, draw_sky, !params.is_ortho, - ofs, NULL, &fx_settings); + ofs, NULL, &fx_settings, viewname); } else { ED_view3d_draw_offscreen( scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background, draw_sky, true, - ofs, NULL, NULL); + ofs, NULL, NULL, viewname); } /* read in pixels & stamp */ @@ -3267,7 +3297,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in /* creates own 3d views, used by the sequencer */ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int width, int height, unsigned int flag, int drawtype, - bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, char err_out[256]) + bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, + const char *viewname, char err_out[256]) { View3D v3d = {NULL}; ARegion ar = {NULL}; @@ -3297,9 +3328,11 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w { CameraParams params; + Object *camera = BKE_camera_multiview_render(scene, v3d.camera, viewname); BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, v3d.camera); + BKE_camera_params_from_object(¶ms, camera); + BKE_camera_multiview_params(&scene->r, ¶ms, camera, viewname); BKE_camera_params_compute_viewplane(¶ms, width, height, scene->r.xasp, scene->r.yasp); BKE_camera_params_compute_matrix(¶ms); @@ -3313,7 +3346,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w invert_m4_m4(rv3d.persinv, rv3d.viewinv); return ED_view3d_draw_offscreen_imbuf(scene, &v3d, &ar, width, height, flag, - draw_background, alpha_mode, err_out); + draw_background, alpha_mode, viewname, err_out); // seq_view3d_cb(scene, cfra, render_size, seqrectx, seqrecty); } @@ -3518,6 +3551,104 @@ static void view3d_main_area_draw_engine_info(View3D *v3d, RegionView3D *rv3d, A ED_region_info_draw(ar, rv3d->render_engine->text, 1, fill_color); } +static bool view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d) +{ + wmWindow *win = CTX_wm_window(C); + + if ((scene->r.scemode & R_MULTIVIEW) == 0) + return false; + + if (WM_stereo3d_enabled(win, true) == false) + return false; + + if ((v3d->camera == NULL) || rv3d->persp != RV3D_CAMOB) + return false; + + if (scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) { + if (v3d->stereo3d_camera == STEREO_MONO_ID) + return false; + + return BKE_scene_multiview_is_stereo3d(&scene->r); + } + + return true; +} + +/* setup the view and win matrices for the multiview cameras + * + * unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called + * we have no winmatrix (i.e., projection matrix) defined at that time. + * Since the camera and the camera shift are needed for the winmat calculation + * we do a small hack to replace it temporarily so we don't need to change the + * view3d)main_area_setup_view() code to account for that. + */ +static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar) +{ + bool is_left; + const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + const char *viewname; + + /* show only left or right camera */ + if (v3d->stereo3d_camera != STEREO_3D_ID) + v3d->multiview_eye = v3d->stereo3d_camera; + + is_left = v3d->multiview_eye == STEREO_LEFT_ID; + viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID]; + + /* update the viewport matrices with the new camera */ + if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { + Camera *data; + float viewmat[4][4]; + float shiftx; + + data = (Camera *)v3d->camera->data; + shiftx = data->shiftx; + + BLI_lock_thread(LOCK_VIEW3D); + data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname); + + BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); + view3d_main_area_setup_view(scene, v3d, ar, viewmat, NULL); + + data->shiftx = shiftx; + BLI_unlock_thread(LOCK_VIEW3D); + } + else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ + float viewmat[4][4]; + Object *view_ob = v3d->camera; + Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); + + BLI_lock_thread(LOCK_VIEW3D); + v3d->camera = camera; + + BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); + view3d_main_area_setup_view(scene, v3d, ar, viewmat, NULL); + + v3d->camera = view_ob; + BLI_unlock_thread(LOCK_VIEW3D); + } +} + +static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar, + float winmat[4][4], const char *viewname) +{ + /* update the viewport matrices with the new camera */ + if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { + float viewmat[4][4]; + const bool is_left = STREQ(viewname, STEREO_LEFT_NAME); + + BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); + view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat); + } + else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ + float viewmat[4][4]; + Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); + + BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); + view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat); + } +} + #ifdef WITH_GAMEENGINE static void update_lods(Scene *scene, float camera_pos[3]) { @@ -3551,8 +3682,11 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3 GPU_default_lights(); } - /* setup view matrices */ - view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL); + /* setup the view matrix */ + if (view3d_stereo3d_active(C, scene, v3d, rv3d)) + view3d_stereo3d_setup(scene, v3d, ar); + else + view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL); rv3d->rflag &= ~RV3D_IS_GAME_ENGINE; #ifdef WITH_GAMEENGINE diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index d1285cf2c18..6b102410aa6 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -494,13 +494,14 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r return; rl = render_get_active_layer( freestyle_render, freestyle_render->result ); - if (!rl || rl->rectf == NULL) { + if (!rl) { if (G.debug & G_DEBUG_FREESTYLE) { cout << "No Freestyle result image to composite" << endl; } return; } - src = rl->rectf; + + src = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname); #if 0 if (G.debug & G_DEBUG_FREESTYLE) { cout << "src: " << rl->rectx << " x " << rl->recty << endl; @@ -508,13 +509,13 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r #endif rl = RE_GetRenderLayer(re->result, srl->name); - if (!rl || rl->rectf == NULL) { + if (!rl || src == NULL) { if (G.debug & G_DEBUG_FREESTYLE) { cout << "No layer to composite to" << endl; } return; } - dest = rl->rectf; + dest = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname); #if 0 if (G.debug & G_DEBUG_FREESTYLE) { cout << "dest: " << rl->rectx << " x " << rl->recty << endl; diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index cc1a63d6256..20aa4919416 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -121,7 +121,7 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap); /* Image updates and free * - these deal with images bound as opengl textures */ -void GPU_paint_update_image(struct Image *ima, int x, int y, int w, int h); +void GPU_paint_update_image(struct Image *ima, ImageUser *iuser, int x, int y, int w, int h); void GPU_update_images_framechange(void); int GPU_update_image_time(struct Image *ima, double time); int GPU_verify_image(struct Image *ima, struct ImageUser *iuser, int tftile, bool compare, bool mipmap, bool is_data); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 7f3a9981a5c..daf6b90f604 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -1040,11 +1040,11 @@ static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, return false; } -void GPU_paint_update_image(Image *ima, int x, int y, int w, int h) +void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, int h) { ImBuf *ibuf; - ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); + ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if (ima->repbind || (GPU_get_mipmap() && !GTS.gpu_mipmap) || !ima->bindcode || !ibuf || (w == 0) || (h == 0)) diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt index e8977913948..eadedbd5e00 100644 --- a/source/blender/imbuf/CMakeLists.txt +++ b/source/blender/imbuf/CMakeLists.txt @@ -62,6 +62,7 @@ set(SRC intern/rectop.c intern/rotate.c intern/scaling.c + intern/stereoimbuf.c intern/targa.c intern/thumbs.c intern/thumbs_blend.c diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 18682302b3a..a39832dd1cb 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -87,6 +87,13 @@ struct anim; struct ColorManagedDisplay; struct GSet; +/** + * + * \attention defined in DNA_scene_types.h + */ +struct ImageFormatData; +struct Stereo3dFormat; + /** * * \attention Defined in allocimbuf.c @@ -279,10 +286,10 @@ bool IMB_anim_get_fps(struct anim *anim, * \attention Defined in anim_movie.c */ struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex, char colorspace[IM_MAX_SPACE]); +void IMB_suffix_anim(struct anim *anim, const char *suffix); void IMB_close_anim(struct anim *anim); void IMB_close_anim_proxies(struct anim *anim); - /** * * \attention Defined in anim_movie.c @@ -377,6 +384,7 @@ void IMB_scaleImBuf_threaded(struct ImBuf *ibuf, unsigned int newx, unsigned int * \attention Defined in writeimage.c */ short IMB_saveiff(struct ImBuf *ibuf, const char *filepath, int flags); +struct ImBuf *IMB_prepare_write_ImBuf(const bool isfloat, struct ImBuf *ibuf); /** * @@ -397,6 +405,12 @@ bool IMB_isanim(const char *name); */ int imb_get_anim_type(const char *name); +/** + * + * \attention Defined in util.c + */ +bool IMB_isfloat(struct ImBuf *ibuf); + /** * * \attention Defined in divers.c @@ -557,5 +571,27 @@ void IMB_processor_apply_threaded(int buffer_lines, int handle_size, void *init_ void IMB_ffmpeg_init(void); const char *IMB_ffmpeg_last_error(void); -#endif +/** + * + * \attention defined in stereoimbuf.c + */ +void IMB_stereo3d_write_dimensions( + const char mode, const bool is_squeezed, const size_t width, const size_t height, + size_t *r_width, size_t *r_height); +void IMB_stereo3d_read_dimensions( + const char mode, const bool is_squeezed, const size_t width, const size_t height, + size_t *r_width, size_t *r_height); +int *IMB_stereo3d_from_rect( + struct ImageFormatData *im_format, const size_t x, const size_t y, const size_t channels, + int *rect_left, int *rect_right); +float *IMB_stereo3d_from_rectf( + struct ImageFormatData *im_format, const size_t x, const size_t y, const size_t channels, + float *rectf_left, float *rectf_right); +struct ImBuf *IMB_stereo3d_ImBuf( + struct ImageFormatData *im_format, + struct ImBuf *ibuf_left, struct ImBuf *ibuf_right); +void IMB_ImBufFromStereo3d( + struct Stereo3dFormat *s3d, struct ImBuf *ibuf_stereo, + struct ImBuf **r_ibuf_left, struct ImBuf **r_ibuf_right); +#endif diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 9e7201f53b4..862c587f75b 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -110,7 +110,7 @@ typedef struct ImBuf { int index; /* reference index for ImBuf lists */ int userflags; /* used to set imbuf to dirty and other stuff */ struct IDProperty *metadata; /* image metadata */ - void *userdata; /* temporary storage, only used by baking at the moment */ + void *userdata; /* temporary storage */ /* file information */ int ftype; /* file type we are going to save as */ @@ -172,6 +172,8 @@ typedef struct ImBuf { #define IB_alphamode_premul (1 << 12) /* indicates whether image on disk have premul alpha */ #define IB_alphamode_detect (1 << 13) /* if this flag is set, alpha mode would be guessed from file */ #define IB_ignore_alpha (1 << 14) /* ignore alpha on load and substitude it with 1.0f */ +#define IB_thumbnail (1 << 15) +#define IB_multiview (1 << 16) /* * The bit flag is stored in the ImBuf.ftype variable. diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h index ed349e8f7eb..1fc43e22f68 100644 --- a/source/blender/imbuf/intern/IMB_anim.h +++ b/source/blender/imbuf/intern/IMB_anim.h @@ -194,6 +194,7 @@ struct anim { struct anim_index *curr_idx[IMB_TC_MAX_SLOT]; char colorspace[64]; + char suffix[64]; /* MAX_NAME - multiview */ }; #endif diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index ffdecb793aa..0bb9f0fce51 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -288,6 +288,11 @@ struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex, char return(anim); } +void IMB_suffix_anim(struct anim *anim, const char *suffix) +{ + BLI_strncpy(anim->suffix, suffix, sizeof(anim->suffix)); +} + #ifdef WITH_AVI static int startavi(struct anim *anim) { diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 183159f7d6c..150ea0995ac 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -398,7 +398,7 @@ static void get_proxy_filename(struct anim *anim, IMB_Proxy_Size preview_size, } BLI_snprintf(proxy_name, sizeof(proxy_name), name, - (int) (proxy_fac[i] * 100), stream_suffix); + (int) (proxy_fac[i] * 100), stream_suffix, anim->suffix); get_index_dir(anim, index_dir, sizeof(index_dir)); @@ -411,10 +411,10 @@ static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc, char index_dir[FILE_MAXDIR]; int i = IMB_timecode_to_array_index(tc); const char *index_names[] = { - "record_run%s.blen_tc", - "free_run%s.blen_tc", - "interp_free_run%s.blen_tc", - "record_run_no_gaps%s.blen_tc" + "record_run%s%s.blen_tc", + "free_run%s%s.blen_tc", + "interp_free_run%s%s.blen_tc", + "record_run_no_gaps%s%s.blen_tc" }; char stream_suffix[20]; @@ -426,7 +426,7 @@ static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc, BLI_snprintf(stream_suffix, 20, "_st%d", anim->streamindex); } - BLI_snprintf(index_name, 256, index_names[i], stream_suffix); + BLI_snprintf(index_name, 256, index_names[i], stream_suffix, anim->suffix); get_index_dir(anim, index_dir, sizeof(index_dir)); diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 45eae89ad9d..1262f0af95d 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -92,9 +92,32 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) #include #include +/* multiview/multipart */ +#include +#include +#include +#include +#include +#include +#include +#include + using namespace Imf; using namespace Imath; +extern "C" +{ +/* prototype */ +static struct ExrPass *imb_exr_get_pass(ListBase *lb, char *passname); +static bool exr_has_multiview(MultiPartInputFile& file); +static bool exr_has_multipart_file(MultiPartInputFile& file); +static int exr_has_alpha(MultiPartInputFile& file); +static int exr_has_zbuffer(MultiPartInputFile& file); +static void exr_printf(const char *__restrict format, ...); +static void imb_exr_type_by_channels(ChannelList& channels, StringVector& views, + bool *r_singlelayer, bool *r_multilayer, bool *r_multiview); +} + /* Memory Input Stream */ class Mem_IStream : public Imf::IStream @@ -340,13 +363,21 @@ static void openexr_header_metadata(Header *header, struct ImBuf *ibuf) addXDensity(*header, ibuf->ppm[0] / 39.3700787); /* 1 meter = 39.3700787 inches */ } -static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags) +static bool imb_save_openexr_half(ImBuf *ibuf, const char *name, const int flags, const size_t totviews, + const char * (*getview)(void *base, size_t view_id), + ImBuf * (*getbuffer)(void *base, const size_t view_id)) { const int channels = ibuf->channels; const int is_alpha = (channels >= 4) && (ibuf->planes == 32); const int is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ const int width = ibuf->x; const int height = ibuf->y; + const bool is_multiview = (flags & IB_multiview) && ibuf->userdata; + + BLI_assert((!is_multiview) || (getview && getbuffer)); + + std::vector views; + size_t view_id; try { @@ -355,13 +386,22 @@ static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags openexr_header_compression(&header, ibuf->ftype & OPENEXR_COMPRESS); openexr_header_metadata(&header, ibuf); - header.channels().insert("R", Channel(HALF)); - header.channels().insert("G", Channel(HALF)); - header.channels().insert("B", Channel(HALF)); - if (is_alpha) - header.channels().insert("A", Channel(HALF)); - if (is_zbuf) // z we do as float always - header.channels().insert("Z", Channel(Imf::FLOAT)); + /* create views when possible */ + for (view_id = 0; view_id < totviews; view_id ++) + views.push_back(is_multiview ? getview(ibuf->userdata, view_id) : ""); + + if (is_multiview) + addMultiView(header, views); + + for (view_id = 0; view_id < totviews; view_id ++) { + header.channels().insert(insertViewName("R", views, view_id), Channel(HALF)); + header.channels().insert(insertViewName("G", views, view_id), Channel(HALF)); + header.channels().insert(insertViewName("B", views, view_id), Channel(HALF)); + if (is_alpha) + header.channels().insert(insertViewName("A", views, view_id), Channel(HALF)); + if (is_zbuf) // z we do as float always + header.channels().insert(insertViewName("Z", views, view_id), Channel(Imf::FLOAT)); + } FrameBuffer frameBuffer; @@ -370,75 +410,91 @@ static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags OutputFile file(file_stream, header); /* we store first everything in half array */ - RGBAZ *pixels = new RGBAZ[height * width]; - RGBAZ *to = pixels; + RGBAZ *pixels = new RGBAZ[height * width * totviews]; int xstride = sizeof(RGBAZ); int ystride = xstride * width; - /* indicate used buffers */ - frameBuffer.insert("R", Slice(HALF, (char *) &pixels[0].r, xstride, ystride)); - frameBuffer.insert("G", Slice(HALF, (char *) &pixels[0].g, xstride, ystride)); - frameBuffer.insert("B", Slice(HALF, (char *) &pixels[0].b, xstride, ystride)); - if (is_alpha) - frameBuffer.insert("A", Slice(HALF, (char *) &pixels[0].a, xstride, ystride)); - if (is_zbuf) - frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *)(ibuf->zbuf_float + (height - 1) * width), - sizeof(float), sizeof(float) * -width)); - if (ibuf->rect_float) { - float *from; - - for (int i = ibuf->y - 1; i >= 0; i--) { - from = ibuf->rect_float + channels * i * width; - - for (int j = ibuf->x; j > 0; j--) { - to->r = from[0]; - to->g = (channels >= 2) ? from[1] : from[0]; - to->b = (channels >= 3) ? from[2] : from[0]; - to->a = (channels >= 4) ? from[3] : 1.0f; - to++; from += channels; + for (view_id = 0; view_id < totviews; view_id ++) { + ImBuf *view_ibuf = is_multiview ? getbuffer(ibuf->userdata, view_id) : ibuf; + const size_t offset = view_id * width * height; + RGBAZ *to = pixels + offset; + + /* indicate used buffers */ + frameBuffer.insert(insertViewName("R", views, view_id), Slice(HALF, (char *) &pixels[offset].r, xstride, ystride)); + frameBuffer.insert(insertViewName("G", views, view_id), Slice(HALF, (char *) &pixels[offset].g, xstride, ystride)); + frameBuffer.insert(insertViewName("B", views, view_id), Slice(HALF, (char *) &pixels[offset].b, xstride, ystride)); + if (is_alpha) + frameBuffer.insert(insertViewName("A", views, view_id), Slice(HALF, (char *) &pixels[offset].a, xstride, ystride)); + if (is_zbuf) + frameBuffer.insert(insertViewName("Z", views, view_id), Slice(Imf::FLOAT, (char *)(view_ibuf->zbuf_float + (height - 1) * width), + sizeof(float), sizeof(float) * -width)); + if (view_ibuf->rect_float) { + float *from; + + for (int i = view_ibuf->y - 1; i >= 0; i--) { + from = view_ibuf->rect_float + channels * i * width; + + for (int j = view_ibuf->x; j > 0; j--) { + to->r = from[0]; + to->g = (channels >= 2) ? from[1] : from[0]; + to->b = (channels >= 3) ? from[2] : from[0]; + to->a = (channels >= 4) ? from[3] : 1.0f; + to++; from += channels; + } } } - } - else { - unsigned char *from; - - for (int i = ibuf->y - 1; i >= 0; i--) { - from = (unsigned char *)ibuf->rect + 4 * i * width; - - for (int j = ibuf->x; j > 0; j--) { - to->r = srgb_to_linearrgb((float)from[0] / 255.0f); - to->g = srgb_to_linearrgb((float)from[1] / 255.0f); - to->b = srgb_to_linearrgb((float)from[2] / 255.0f); - to->a = channels >= 4 ? (float)from[3] / 255.0f : 1.0f; - to++; from += 4; + else { + unsigned char *from; + + for (int i = view_ibuf->y - 1; i >= 0; i--) { + from = (unsigned char *)view_ibuf->rect + 4 * i * width; + + for (int j = view_ibuf->x; j > 0; j--) { + to->r = srgb_to_linearrgb((float)from[0] / 255.0f); + to->g = srgb_to_linearrgb((float)from[1] / 255.0f); + to->b = srgb_to_linearrgb((float)from[2] / 255.0f); + to->a = channels >= 4 ? (float)from[3] / 255.0f : 1.0f; + to++; from += 4; + } } } + + if (is_multiview) + IMB_freeImBuf(view_ibuf); } -// printf("OpenEXR-save: Writing OpenEXR file of height %d.\n", height); + exr_printf("OpenEXR-save: Writing OpenEXR file of height %d.\n", height); file.setFrameBuffer(frameBuffer); file.writePixels(height); delete[] pixels; } - catch (const std::exception &exc) + catch (const std::exception& exc) { printf("OpenEXR-save: ERROR: %s\n", exc.what()); - return (0); + return false; } - return (1); + return true; } -static int imb_save_openexr_float(struct ImBuf *ibuf, const char *name, int flags) +static bool imb_save_openexr_float(ImBuf *ibuf, const char *name, const int flags, const size_t totviews, + const char * (*getview)(void *base, const size_t view_id), + ImBuf * (*getbuffer)(void *base, const size_t view_id)) { const int channels = ibuf->channels; const int is_alpha = (channels >= 4) && (ibuf->planes == 32); const int is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ const int width = ibuf->x; const int height = ibuf->y; + const bool is_multiview = (flags & IB_multiview) && ibuf->userdata; + + BLI_assert((!is_multiview) || (getview && getbuffer)); + + std::vector views; + size_t view_id; try { @@ -447,13 +503,22 @@ static int imb_save_openexr_float(struct ImBuf *ibuf, const char *name, int flag openexr_header_compression(&header, ibuf->ftype & OPENEXR_COMPRESS); openexr_header_metadata(&header, ibuf); - header.channels().insert("R", Channel(Imf::FLOAT)); - header.channels().insert("G", Channel(Imf::FLOAT)); - header.channels().insert("B", Channel(Imf::FLOAT)); - if (is_alpha) - header.channels().insert("A", Channel(Imf::FLOAT)); - if (is_zbuf) - header.channels().insert("Z", Channel(Imf::FLOAT)); + /* create views when possible */ + for (view_id = 0; view_id < totviews; view_id ++) + views.push_back(is_multiview ? getview(ibuf->userdata, view_id) : ""); + + if (is_multiview) + addMultiView(header, views); + + for (view_id = 0; view_id < totviews; view_id ++) { + header.channels().insert(insertViewName("R", views, view_id), Channel(Imf::FLOAT)); + header.channels().insert(insertViewName("G", views, view_id), Channel(Imf::FLOAT)); + header.channels().insert(insertViewName("B", views, view_id), Channel(Imf::FLOAT)); + if (is_alpha) + header.channels().insert(insertViewName("A", views, view_id), Channel(Imf::FLOAT)); + if (is_zbuf) + header.channels().insert(insertViewName("Z", views, view_id), Channel(Imf::FLOAT)); + } FrameBuffer frameBuffer; @@ -463,37 +528,41 @@ static int imb_save_openexr_float(struct ImBuf *ibuf, const char *name, int flag int xstride = sizeof(float) * channels; int ystride = -xstride * width; - float *rect[4] = {NULL, NULL, NULL, NULL}; - /* last scanline, stride negative */ - rect[0] = ibuf->rect_float + channels * (height - 1) * width; - rect[1] = (channels >= 2) ? rect[0] + 1 : rect[0]; - rect[2] = (channels >= 3) ? rect[0] + 2 : rect[0]; - rect[3] = (channels >= 4) ? rect[0] + 3 : rect[0]; /* red as alpha, is this needed since alpha isn't written? */ - - frameBuffer.insert("R", Slice(Imf::FLOAT, (char *)rect[0], xstride, ystride)); - frameBuffer.insert("G", Slice(Imf::FLOAT, (char *)rect[1], xstride, ystride)); - frameBuffer.insert("B", Slice(Imf::FLOAT, (char *)rect[2], xstride, ystride)); - if (is_alpha) - frameBuffer.insert("A", Slice(Imf::FLOAT, (char *)rect[3], xstride, ystride)); - if (is_zbuf) - frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *) (ibuf->zbuf_float + (height - 1) * width), - sizeof(float), sizeof(float) * -width)); + for (view_id = 0; view_id < totviews; view_id ++) { + float *rect[4] = {NULL, NULL, NULL, NULL}; + ImBuf *view_ibuf = is_multiview ? getbuffer(ibuf->userdata, view_id) : ibuf; + + /* last scanline, stride negative */ + rect[0] = view_ibuf->rect_float + channels * (height - 1) * width; + rect[1] = (channels >= 2) ? rect[0] + 1 : rect[0]; + rect[2] = (channels >= 3) ? rect[0] + 2 : rect[0]; + rect[3] = (channels >= 4) ? rect[0] + 3 : rect[0]; /* red as alpha, is this needed since alpha isn't written? */ + + frameBuffer.insert(insertViewName("R", views, view_id), Slice(Imf::FLOAT, (char *)rect[0], xstride, ystride)); + frameBuffer.insert(insertViewName("G", views, view_id), Slice(Imf::FLOAT, (char *)rect[1], xstride, ystride)); + frameBuffer.insert(insertViewName("B", views, view_id), Slice(Imf::FLOAT, (char *)rect[2], xstride, ystride)); + if (is_alpha) + frameBuffer.insert(insertViewName("A", views, view_id), Slice(Imf::FLOAT, (char *)rect[3], xstride, ystride)); + if (is_zbuf) + frameBuffer.insert(insertViewName("Z", views, view_id), Slice(Imf::FLOAT, (char *) (view_ibuf->zbuf_float + (height - 1) * width), + sizeof(float), sizeof(float) * -width)); + + if (is_multiview) + IMB_freeImBuf(view_ibuf); + } file.setFrameBuffer(frameBuffer); file.writePixels(height); } - catch (const std::exception &exc) + catch (const std::exception& exc) { printf("OpenEXR-save: ERROR: %s\n", exc.what()); - - return (0); + return false; } - return (1); - // printf("OpenEXR-save: Done.\n"); + return true; } - int imb_save_openexr(struct ImBuf *ibuf, const char *name, int flags) { if (flags & IB_mem) { @@ -504,16 +573,48 @@ int imb_save_openexr(struct ImBuf *ibuf, const char *name, int flags) } if (ibuf->ftype & OPENEXR_HALF) - return imb_save_openexr_half(ibuf, name, flags); + return (int) imb_save_openexr_half(ibuf, name, flags, 1, NULL, NULL); + else { + /* when no float rect, we save as half (16 bits is sufficient) */ + if (ibuf->rect_float == NULL) + return (int) imb_save_openexr_half(ibuf, name, flags, 1, NULL, NULL); + else + return (int) imb_save_openexr_float(ibuf, name, flags, 1, NULL, NULL); + } +} + +static bool imb_save_openexr_multiview(ImBuf *ibuf, const char *name, const int flags, const size_t totviews, + const char * (*getview)(void *base, const size_t view_id), + ImBuf * (*getbuffer)(void *base, const size_t view_id)) +{ + if (flags & IB_mem) { + printf("OpenEXR-save: Create multiview EXR in memory CURRENTLY NOT SUPPORTED !\n"); + imb_addencodedbufferImBuf(ibuf); + ibuf->encodedsize = 0; + return false; + } + + if (ibuf->ftype & OPENEXR_HALF) + return imb_save_openexr_half(ibuf, name, flags, totviews, getview, getbuffer); else { /* when no float rect, we save as half (16 bits is sufficient) */ if (ibuf->rect_float == NULL) - return imb_save_openexr_half(ibuf, name, flags); + return imb_save_openexr_half(ibuf, name, flags, totviews, getview, getbuffer); else - return imb_save_openexr_float(ibuf, name, flags); + return imb_save_openexr_float(ibuf, name, flags, totviews, getview, getbuffer); } } +/* Save single-layer multiview OpenEXR + * If we have more multiview formats in the future, the function below could be incorporated + * in our ImBuf write functions, meanwhile this is an OpenEXR special case only */ +bool IMB_exr_multiview_save(ImBuf *ibuf, const char *name, const int flags, const size_t totviews, + const char * (*getview)(void *base, size_t view_id), + ImBuf * (*getbuffer)(void *base, const size_t view_id)) +{ + return imb_save_openexr_multiview(ibuf, name, flags, totviews, getview, getbuffer); +} + /* ********************* Nicer API, MultiLayer and with Tile file support ************************************ */ /* naming rules: @@ -527,18 +628,22 @@ static ListBase exrhandles = {NULL, NULL}; typedef struct ExrHandle { struct ExrHandle *next, *prev; + char name[FILE_MAX]; IFileStream *ifile_stream; - InputFile *ifile; + MultiPartInputFile *ifile; OFileStream *ofile_stream; - TiledOutputFile *tofile; + MultiPartOutputFile *mpofile; OutputFile *ofile; int tilex, tiley; int width, height; int mipmap; + StringVector *multiView; /* it needs to be a pointer due to Windows release builds of EXR2.0 segfault when opening EXR bug */ + int parts; + ListBase channels; /* flattened out, ExrChannel */ ListBase layers; /* hierarchical, pointing in end to ExrChannel */ } ExrHandle; @@ -547,10 +652,12 @@ typedef struct ExrHandle { typedef struct ExrChannel { struct ExrChannel *next, *prev; - char name[EXR_TOT_MAXNAME + 1]; /* full name of layer+pass */ + char name[EXR_TOT_MAXNAME + 1]; /* full name with everything */ + struct MultiViewChannelName *m; /* struct to store all multipart channel info */ 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 */ + int view_id; /* quick lookup of channel view */ } ExrChannel; @@ -562,6 +669,10 @@ typedef struct ExrPass { float *rect; struct ExrChannel *chan[EXR_PASS_MAXCHAN]; char chan_id[EXR_PASS_MAXCHAN]; + + char internal_name[EXR_PASS_MAXNAME]; /* name with no view */ + char view[EXR_VIEW_MAXNAME]; + int view_id; } ExrPass; typedef struct ExrLayer { @@ -575,39 +686,141 @@ typedef struct ExrLayer { void *IMB_exr_get_handle(void) { ExrHandle *data = (ExrHandle *)MEM_callocN(sizeof(ExrHandle), "exr handle"); + data->multiView = new StringVector(); + BLI_addtail(&exrhandles, data); return data; } +void *IMB_exr_get_handle_name(const char *name) +{ + ExrHandle *data = (ExrHandle *) BLI_rfindstring(&exrhandles, name, offsetof(ExrHandle, name)); + + if (data == NULL) { + data = (ExrHandle *)IMB_exr_get_handle(); + BLI_strncpy(data->name, name, strlen(name) + 1); + } + return data; +} + +/* multiview functions */ +} // extern "C" + +extern "C" +{ + +void IMB_exr_add_view(void *handle, const char *name) +{ + ExrHandle *data = (ExrHandle *)handle; + data->multiView->push_back(name); +} + +static int imb_exr_get_multiView_id(StringVector& views, const std::string& name) +{ + int count = 0; + for (StringVector::const_iterator i = views.begin(); count < views.size(); ++i) { + if (name == *i) + return count; + else + count ++; + } + + /* no views or wrong name */ + return -1; +} + +static void imb_exr_get_views(MultiPartInputFile& file, StringVector& views) +{ + if (exr_has_multipart_file(file) == false) { + if (exr_has_multiview(file)) { + StringVector sv = multiView(file.header(0)); + for (StringVector::const_iterator i = sv.begin(); i != sv.end(); ++i) + views.push_back(*i); + } + } + + else { + for (int p = 0; p < file.parts(); p++) { + std::string view = ""; + if (file.header(p).hasView()) + view = file.header(p).view(); + + if (imb_exr_get_multiView_id(views, view) == -1) + views.push_back(view); + } + } +} + +/* Multilayer Blender files have the view name in all the passes (even the default view one) */ +static const char *imb_exr_insert_view_name(const char *passname, const char *viewname) +{ + if (viewname == NULL || viewname[0] == '\0') + return passname; + + static char retstr[EXR_PASS_MAXNAME]; + const char *end = passname + strlen(passname); + const char *token; + + int len = IMB_exr_split_token(passname, end, &token); + + if (len == 0) + BLI_snprintf(retstr, sizeof(retstr), "%s.%s", passname, viewname); + else + BLI_snprintf(retstr, sizeof(retstr), "%.*s%s.%s", + (int)(end - passname) - len, passname, viewname, token); + + return retstr; +} + /* 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) +/* passname does not include view */ +void IMB_exr_add_channel(void *handle, const char *layname, const char *passname, const char *viewname, int xstride, int ystride, float *rect) { ExrHandle *data = (ExrHandle *)handle; ExrChannel *echan; - echan = (ExrChannel *)MEM_callocN(sizeof(ExrChannel), "exr tile channel"); + echan = (ExrChannel *)MEM_callocN(sizeof(ExrChannel), "exr channel"); + echan->m = new MultiViewChannelName (); - if (layname) { - 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); + if (layname && layname[0] != '\0') { + echan->m->name = layname; + echan->m->name.append("."); + echan->m->name.append(passname); + } + else { + echan->m->name.assign(passname); + } - BLI_snprintf(echan->name, sizeof(echan->name), "%s.%s", lay, pass); + echan->m->internal_name = echan->m->name; + + echan->m->view.assign(viewname ? viewname : ""); + + /* quick look up */ + echan->view_id = std::max(0, imb_exr_get_multiView_id(*data->multiView, echan->m->view)); + + /* name has to be unique, thus it's a combination of layer, pass, view, and channel */ + if (layname && layname[0] != '\0') { + std::string raw_name = imb_exr_insert_view_name(echan->m->name.c_str(), echan->m->view.c_str()); + BLI_strncpy(echan->name, raw_name.c_str(), sizeof(echan->name)); + } + else if (data->multiView->size() > 1) { + std::string raw_name = insertViewName(echan->m->name, *data->multiView, echan->view_id); + BLI_strncpy(echan->name, raw_name.c_str(), sizeof(echan->name)); } else { - BLI_strncpy(echan->name, passname, EXR_TOT_MAXNAME - 1); + BLI_strncpy(echan->name, echan->m->name.c_str(), sizeof(echan->name)); } echan->xstride = xstride; echan->ystride = ystride; echan->rect = rect; - // printf("added channel %s\n", echan->name); + exr_printf("added channel %s\n", echan->name); BLI_addtail(&data->channels, echan); } -/* only used for writing temp. render results (not image files) */ +/* used for output files (from RenderResult) (single and multilayer, single and multiview) */ int IMB_exr_begin_write(void *handle, const char *filename, int width, int height, int compress) { ExrHandle *data = (ExrHandle *)handle; @@ -617,6 +830,8 @@ int IMB_exr_begin_write(void *handle, const char *filename, int width, int heigh data->width = width; data->height = height; + bool is_singlelayer, is_multilayer, is_multiview; + for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) header.channels().insert(echan->name, Channel(Imf::FLOAT)); @@ -624,7 +839,13 @@ int IMB_exr_begin_write(void *handle, const char *filename, int width, int heigh // openexr_header_metadata(&header, ibuf); // no imbuf. cant write /* header.lineOrder() = DECREASING_Y; this crashes in windows for file read! */ - header.insert("BlenderMultiChannel", StringAttribute("Blender V2.55.1 and newer")); + imb_exr_type_by_channels(header.channels(), *data->multiView, &is_singlelayer, &is_multilayer, &is_multiview); + + if (is_multilayer) + header.insert("BlenderMultiChannel", StringAttribute("Blender V2.55.1 and newer")); + + if (is_multiview) + addMultiView(header, *data->multiView); /* avoid crash/abort when we don't have permission to write here */ /* manually create ofstream, so we can handle utf-8 filepaths on windows */ @@ -632,7 +853,7 @@ int IMB_exr_begin_write(void *handle, const char *filename, int width, int heigh data->ofile_stream = new OFileStream(filename); data->ofile = new OutputFile(*(data->ofile_stream), header); } - catch (const std::exception &exc) { + catch (const std::exception& exc) { std::cerr << "IMB_exr_begin_write: ERROR: " << exc.what() << std::endl; delete data->ofile; @@ -645,10 +866,13 @@ int IMB_exr_begin_write(void *handle, const char *filename, int width, int heigh return (data->ofile != NULL); } +/* only used for writing temp. render results (not image files) + * (FSA and Save Buffers) */ void IMB_exrtile_begin_write(void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { ExrHandle *data = (ExrHandle *)handle; Header header(width, height); + std::vector
headers; ExrChannel *echan; data->tilex = tilex; @@ -657,26 +881,47 @@ void IMB_exrtile_begin_write(void *handle, const char *filename, int mipmap, int data->height = height; data->mipmap = mipmap; - for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) - header.channels().insert(echan->name, Channel(Imf::FLOAT)); - header.setTileDescription(TileDescription(tilex, tiley, (mipmap) ? MIPMAP_LEVELS : ONE_LEVEL)); - header.lineOrder() = RANDOM_Y; header.compression() = RLE_COMPRESSION; + header.setType(TILEDIMAGE); header.insert("BlenderMultiChannel", StringAttribute("Blender V2.43")); + int numparts = data->multiView->size(); + + /* copy header from all parts of input to our header array + * those temporary files have one part per view */ + for (int i = 0; i < numparts; i++) { + headers.push_back (header); + headers[headers.size() - 1].setView((*(data->multiView))[i]); + headers[headers.size() - 1].setName((*(data->multiView))[i]); + } + + exr_printf("\nIMB_exrtile_begin_write\n"); + exr_printf("%s %-6s %-22s \"%s\"\n", "p", "view", "name", "internal_name"); + exr_printf("---------------------------------------------------------------\n"); + + /* assign channels */ + for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { + + echan->m->internal_name = echan->m->name; + echan->m->part_number = echan->view_id; + + headers[echan->view_id].channels().insert(echan->m->internal_name, Channel(Imf::FLOAT)); + exr_printf("%d %-6s %-22s \"%s\"\n", echan->m->part_number, echan->m->view.c_str(), echan->m->name.c_str(), echan->m->internal_name.c_str()); + } + /* avoid crash/abort when we don't have permission to write here */ /* manually create ofstream, so we can handle utf-8 filepaths on windows */ try { data->ofile_stream = new OFileStream(filename); - data->tofile = new TiledOutputFile(*(data->ofile_stream), header); + data->mpofile = new MultiPartOutputFile(*(data->ofile_stream), &headers[0], headers.size()); } catch (const std::exception &) { - delete data->tofile; + delete data->mpofile; delete data->ofile_stream; - data->tofile = NULL; + data->mpofile = NULL; data->ofile_stream = NULL; } } @@ -685,12 +930,13 @@ void IMB_exrtile_begin_write(void *handle, const char *filename, int mipmap, int int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *height) { ExrHandle *data = (ExrHandle *)handle; + ExrChannel *echan; if (BLI_exists(filename) && BLI_file_size(filename) > 32) { /* 32 is arbitrary, but zero length files crashes exr */ /* avoid crash/abort when we don't have permission to write here */ try { data->ifile_stream = new IFileStream(filename); - data->ifile = new InputFile(*(data->ifile_stream)); + data->ifile = new MultiPartInputFile(*(data->ifile_stream)); } catch (const std::exception &) { delete data->ifile; @@ -701,14 +947,24 @@ int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *heig } if (data->ifile) { - Box2i dw = data->ifile->header().dataWindow(); + Box2i dw = data->ifile->header(0).dataWindow(); data->width = *width = dw.max.x - dw.min.x + 1; data->height = *height = dw.max.y - dw.min.y + 1; - const ChannelList &channels = data->ifile->header().channels(); + imb_exr_get_views(*data->ifile, *data->multiView); + + std::vector channels; + GetChannelsInMultiPartFile(*data->ifile, channels); - for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) - IMB_exr_add_channel(data, NULL, i.name(), 0, 0, NULL); + for (size_t i = 0; i < channels.size(); i++) { + IMB_exr_add_channel(data, NULL, channels[i].name.c_str(), channels[i].view.c_str(), 0, 0, NULL); + + echan = (ExrChannel *)data->channels.last; + echan->m->name = channels[i].name; + echan->m->view = channels[i].view; + echan->m->part_number = channels[i].part_number; + echan->m->internal_name = channels[i].internal_name; + } return 1; } @@ -717,6 +973,7 @@ int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *heig } /* still clumsy name handling, layers/channels can be ordered as list in list later */ +/* passname here is the raw channel name without the layer */ void IMB_exr_set_channel(void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect) { ExrHandle *data = (ExrHandle *)handle; @@ -741,37 +998,53 @@ void IMB_exr_set_channel(void *handle, const char *layname, const char *passname echan->rect = rect; } else - printf("IMB_exrtile_set_channel error %s\n", name); -} - -void IMB_exrtile_clear_channels(void *handle) -{ - ExrHandle *data = (ExrHandle *)handle; - BLI_freelistN(&data->channels); + printf("IMB_exr_set_channel error %s\n", name); } -void IMB_exrtile_write_channels(void *handle, int partx, int party, int level) +float *IMB_exr_channel_rect(void *handle, const char *layname, const char *passname, const char *viewname) { ExrHandle *data = (ExrHandle *)handle; - FrameBuffer frameBuffer; ExrChannel *echan; + char name[EXR_TOT_MAXNAME + 1]; - for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { - float *rect = echan->rect - echan->xstride * partx - echan->ystride * party; + if (layname) { + 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); - frameBuffer.insert(echan->name, Slice(Imf::FLOAT, (char *)rect, - echan->xstride * sizeof(float), echan->ystride * sizeof(float))); + BLI_snprintf(name, sizeof(name), "%s.%s", lay, pass); } + else + BLI_strncpy(name, passname, EXR_TOT_MAXNAME - 1); - data->tofile->setFrameBuffer(frameBuffer); - - try { - // printf("write tile %d %d\n", partx/data->tilex, party/data->tiley); - data->tofile->writeTile(partx / data->tilex, party / data->tiley, level); + /* name has to be unique, thus it's a combination of layer, pass, view, and channel */ + if (layname && layname[0] != '\0') { + std::string raw_name = imb_exr_insert_view_name(name, viewname); + BLI_strncpy(name, raw_name.c_str(), sizeof(name)); } - catch (const std::exception &exc) { - std::cerr << "OpenEXR-writeTile: ERROR: " << exc.what() << std::endl; + else if (data->multiView->size() > 1) { + size_t view_id = std::max(0, imb_exr_get_multiView_id(*data->multiView, viewname)); + std::string raw_name = insertViewName(name, *data->multiView, view_id); + BLI_strncpy(name, raw_name.c_str(), sizeof(name)); } + + echan = (ExrChannel *)BLI_findstring(&data->channels, name, offsetof(ExrChannel, name)); + + if (echan) + return echan->rect; + + return NULL; +} + +void IMB_exr_clear_channels(void *handle) +{ + ExrHandle *data = (ExrHandle *)handle; + ExrChannel *chan; + + for (chan = (ExrChannel *)data->channels.first; chan; chan = chan->next) + delete chan->m; + + BLI_freelistN(&data->channels); } void IMB_exr_write_channels(void *handle) @@ -793,7 +1066,7 @@ void IMB_exr_write_channels(void *handle) try { data->ofile->writePixels(data->height); } - catch (const std::exception &exc) { + catch (const std::exception& exc) { std::cerr << "OpenEXR-writePixels: ERROR: " << exc.what() << std::endl; } } @@ -802,49 +1075,171 @@ void IMB_exr_write_channels(void *handle) } } -void IMB_exr_read_channels(void *handle) +/* temporary function, used for FSA and Save Buffers */ +/* called once per tile * view */ +void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, const char *viewname) { ExrHandle *data = (ExrHandle *)handle; FrameBuffer frameBuffer; ExrChannel *echan; + std::string view(viewname); + const size_t view_id = imb_exr_get_multiView_id(*data->multiView, view); + + exr_printf("\nIMB_exrtile_write_channels(view: %s)\n", viewname); + exr_printf("%s %-6s %-22s \"%s\"\n", "p", "view", "name", "internal_name"); + exr_printf("---------------------------------------------------------------------\n"); + + for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { + + /* eventually we can make the parts' channels to include + only the current view TODO */ + if (strcmp(viewname, echan->m->view.c_str()) != 0) + continue; + + exr_printf("%d %-6s %-22s \"%s\"\n", + echan->m->part_number, + echan->m->view.c_str(), + echan->m->name.c_str(), + echan->m->internal_name.c_str() + ); + + float *rect = echan->rect - echan->xstride * partx - echan->ystride * party; + frameBuffer.insert(echan->m->internal_name, + Slice(Imf::FLOAT, + (char *)rect, + echan->xstride * sizeof(float), + echan->ystride * sizeof(float) + ) + ); + } + + TiledOutputPart out (*data->mpofile, view_id); + out.setFrameBuffer(frameBuffer); + + try { + // printf("write tile %d %d\n", partx/data->tilex, party/data->tiley); + out.writeTile(partx / data->tilex, party / data->tiley, level); + } + catch (const std::exception& exc) { + std::cerr << "OpenEXR-writeTile: ERROR: " << exc.what() << std::endl; + } +} + +/* called only when handle has all views */ +void IMB_exrmultiview_write_channels(void *handle, const char *viewname) +{ + ExrHandle *data = (ExrHandle *)handle; + const size_t view_id = viewname ? imb_exr_get_multiView_id(*data->multiView, viewname) : -1; + int numparts = (view_id == -1 ? data->parts : view_id + 1); + std::vector frameBuffers(numparts); + std::vector outputParts; + ExrChannel *echan; + int i, part; + + if (data->channels.first == NULL) + return; + + exr_printf("\nIMB_exrmultiview_write_channels()\n"); + + for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { + if (view_id != -1 && echan->view_id != view_id) + continue; + + part = (view_id == -1 ? echan->m->part_number : echan->view_id); + + /* last scanline, stride negative */ + float *rect = echan->rect + echan->xstride * (data->height - 1) * data->width; + frameBuffers[part].insert(echan->m->internal_name, + Slice(Imf::FLOAT, + (char *)rect, + echan->xstride * sizeof(float), + -echan->ystride * sizeof(float)) + ); + } + + for (i = 0; i < numparts; i++) { + OutputPart out(*data->mpofile, i); + out.setFrameBuffer(frameBuffers[i]); + outputParts.push_back(out); + } + + try { + for (i = 0; i < numparts; i++) { + if (view_id != -1 && i != view_id) + continue; + + outputParts[i].writePixels(data->height); + } + } + catch (const std::exception& exc) { + std::cerr << "OpenEXR-write Multi Part: ERROR: " << exc.what() << std::endl; + } +} + +void IMB_exr_read_channels(void *handle) +{ + ExrHandle *data = (ExrHandle *)handle; + ExrChannel *echan; + int numparts = data->ifile->parts(); + std::vector frameBuffers(numparts); + std::vector inputParts; /* check if exr was saved with previous versions of blender which flipped images */ - const StringAttribute *ta = data->ifile->header().findTypedAttribute ("BlenderMultiChannel"); + const StringAttribute *ta = data->ifile->header(0).findTypedAttribute ("BlenderMultiChannel"); short flip = (ta && STREQLEN(ta->value().c_str(), "Blender V2.43", 13)); /* 'previous multilayer attribute, flipped */ + exr_printf("\nIMB_exr_read_channels\n%s %-6s %-22s \"%s\"\n---------------------------------------------------------------------\n", "p", "view", "name", "internal_name"); + for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { + exr_printf("%d %-6s %-22s \"%s\"\n", echan->m->part_number, echan->m->view.c_str(), echan->m->name.c_str(), echan->m->internal_name.c_str()); if (echan->rect) { if (flip) - frameBuffer.insert(echan->name, Slice(Imf::FLOAT, (char *)echan->rect, + frameBuffers[echan->m->part_number].insert(echan->m->internal_name, Slice(Imf::FLOAT, (char *)echan->rect, echan->xstride * sizeof(float), echan->ystride * sizeof(float))); else - frameBuffer.insert(echan->name, Slice(Imf::FLOAT, (char *)(echan->rect + echan->xstride * (data->height - 1) * data->width), + frameBuffers[echan->m->part_number].insert(echan->m->internal_name, Slice(Imf::FLOAT, (char *)(echan->rect + echan->xstride * (data->height - 1) * data->width), echan->xstride * sizeof(float), -echan->ystride * sizeof(float))); } else - printf("warning, channel with no rect set %s\n", echan->name); + printf("warning, channel with no rect set %s\n", echan->m->internal_name.c_str()); } - data->ifile->setFrameBuffer(frameBuffer); + for (int i = 0; i < numparts; i++) { + InputPart in (*data->ifile, i); + in.setFrameBuffer(frameBuffers[i]); + inputParts.push_back(in); + } try { - data->ifile->readPixels(0, data->height - 1); + for (int i = 0; i < numparts; i++) { + Header header = inputParts[i].header(); + exr_printf("readPixels:readPixels[%d]: min.y: %d, max.y: %d\n", i, header.dataWindow().min.y, header.dataWindow().max.y); + inputParts[i].readPixels(header.dataWindow().min.y, header.dataWindow().max.y); + inputParts[i].readPixels(0, data->height - 1); + } } - catch (const std::exception &exc) { + catch (const std::exception& exc) { std::cerr << "OpenEXR-readPixels: ERROR: " << exc.what() << std::endl; } } void IMB_exr_multilayer_convert(void *handle, void *base, + void * (*addview)(void *base, const char *str), void * (*addlayer)(void *base, const char *str), void (*addpass)(void *base, void *lay, const char *str, - float *rect, int totchan, const char *chan_id)) + float *rect, int totchan, const char *chan_id, + const char *view)) { ExrHandle *data = (ExrHandle *)handle; ExrLayer *lay; ExrPass *pass; + /* add views to RenderResult */ + for (StringVector::const_iterator i = data->multiView->begin(); i != data->multiView->end(); ++i) { + addview(base, (*i).c_str()); + } + if (BLI_listbase_is_empty(&data->layers)) { printf("cannot convert multilayer, no layers in handle\n"); return; @@ -854,32 +1249,98 @@ void IMB_exr_multilayer_convert(void *handle, void *base, 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); + addpass(base, laybase, pass->internal_name, pass->rect, pass->totchan, pass->chan_id, pass->view); pass->rect = NULL; } } } } +void IMB_exr_multiview_convert(void *handle, void *base, + void (*addview)(void *base, const char *str), + void (*addbuffer)(void *base, const char *str, ImBuf *ibuf, const int frame), + const int frame) +{ + ExrHandle *data = (ExrHandle *)handle; + MultiPartInputFile *file = data->ifile; + ExrLayer *lay; + ExrPass *pass; + ImBuf *ibuf = NULL; + const int is_alpha = exr_has_alpha(*file); + Box2i dw = file->header(0).dataWindow(); + const size_t width = dw.max.x - dw.min.x + 1; + const size_t height = dw.max.y - dw.min.y + 1; + const bool is_depth = exr_has_zbuffer(*file); + + /* add views to RenderResult */ + for (StringVector::const_iterator i = data->multiView->begin(); i != data->multiView->end(); ++i) { + addview(base, (*i).c_str()); + } + + if (BLI_listbase_is_empty(&data->layers)) { + printf("cannot convert multiviews, no views in handle\n"); + return; + } + + /* there is one float/pass per layer (layer here is a view) */ + BLI_assert(BLI_listbase_count_ex(&data->layers, 2) == 1); + lay = (ExrLayer *)data->layers.first; + for (pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) { + if (STREQ(pass->chan_id, "RGB") || STREQ(pass->chan_id, "RGBA")) { + ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, IB_rectfloat); + + if (!ibuf) { + printf("error creating multiview buffer\n"); + return; + } + + IMB_buffer_float_from_float( + ibuf->rect_float, pass->rect, pass->totchan, + IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); + + if (hasXDensity(file->header(0))) { + ibuf->ppm[0] = xDensity(file->header(0)) * 39.3700787f; + ibuf->ppm[1] = ibuf->ppm[0] * (double)file->header(0).pixelAspectRatio(); + } + + if (is_depth) { + ExrPass *zpass; + for (zpass = (ExrPass *)lay->passes.first; zpass; zpass = zpass->next) { + if (STREQ(zpass->chan_id, "Z") && STREQ(zpass->view, pass->view)) { + addzbuffloatImBuf(ibuf); + memcpy(ibuf->zbuf_float, zpass->rect, sizeof(float) * ibuf->x * ibuf->y); + } + } + } + + addbuffer(base, pass->view, ibuf, frame); + } + } +} void IMB_exr_close(void *handle) { ExrHandle *data = (ExrHandle *)handle; ExrLayer *lay; ExrPass *pass; + ExrChannel *chan; delete data->ifile; delete data->ifile_stream; delete data->ofile; - delete data->tofile; + delete data->mpofile; delete data->ofile_stream; data->ifile = NULL; data->ifile_stream = NULL; data->ofile = NULL; - data->tofile = NULL; + data->mpofile = NULL; data->ofile_stream = NULL; + for (chan = (ExrChannel *)data->channels.first; chan; chan = chan->next) { + delete chan->m; + } BLI_freelistN(&data->channels); for (lay = (ExrLayer *)data->layers.first; lay; lay = lay->next) { @@ -897,7 +1358,7 @@ void IMB_exr_close(void *handle) /* ********* */ /* get a substring from the end of the name, separated by '.' */ -static int imb_exr_split_token(const char *str, const char *end, const char **token) +int IMB_exr_split_token(const char *str, const char *end, const char **token) { ptrdiff_t maxlen = end - str; int len = 0; @@ -911,7 +1372,7 @@ static int imb_exr_split_token(const char *str, const char *end, const char **to static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *passname) { - const char *name = echan->name; + const char *name = echan->m->name.c_str(); const char *end = name + strlen(name); const char *token; char tokenbuf[EXR_TOT_MAXNAME]; @@ -933,7 +1394,7 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa } /* last token is single character channel identifier */ - len = imb_exr_split_token(name, end, &token); + len = IMB_exr_split_token(name, end, &token); if (len == 0) { printf("multilayer read: bad channel name: %s\n", name); return 0; @@ -971,7 +1432,7 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa end -= len + 1; /* +1 to skip '.' separator */ /* second token is pass name */ - len = imb_exr_split_token(name, end, &token); + len = IMB_exr_split_token(name, end, &token); if (len == 0) { printf("multilayer read: bad channel name: %s\n", name); return 0; @@ -1020,7 +1481,7 @@ static ExrPass *imb_exr_get_pass(ListBase *lb, char *passname) } /* creates channels, makes a hierarchy and assigns memory to channels */ -static ExrHandle *imb_exr_begin_read_mem(InputFile *file, int width, int height) +static ExrHandle *imb_exr_begin_read_mem(MultiPartInputFile& file, int width, int height) { ExrLayer *lay; ExrPass *pass; @@ -1029,30 +1490,57 @@ static ExrHandle *imb_exr_begin_read_mem(InputFile *file, int width, int height) int a; char layname[EXR_TOT_MAXNAME], passname[EXR_TOT_MAXNAME]; - data->ifile = file; + data->ifile = &file; data->width = width; data->height = height; - const ChannelList &channels = data->ifile->header().channels(); + std::vector channels; + GetChannelsInMultiPartFile(*data->ifile, channels); - for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) - IMB_exr_add_channel(data, NULL, i.name(), 0, 0, NULL); + data->multiView = new StringVector(); + imb_exr_get_views(*data->ifile, *data->multiView); + + for (size_t i = 0; i < channels.size(); i++) { + IMB_exr_add_channel(data, NULL, channels[i].name.c_str(), channels[i].view.c_str(), 0, 0, NULL); + + echan = (ExrChannel *)data->channels.last; + echan->m->name = channels[i].name; + echan->m->view = channels[i].view; + echan->m->part_number = channels[i].part_number; + echan->m->internal_name = channels[i].internal_name; + } /* 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) ) { + if (imb_exr_split_channel_name(echan, layname, passname)) { + + const char *view = echan->m->view.c_str(); + char internal_name[EXR_PASS_MAXNAME]; + + BLI_strncpy(internal_name, passname, EXR_PASS_MAXNAME); + + if (view[0] != '\0') { + char tmp_pass[EXR_PASS_MAXNAME]; + BLI_snprintf(tmp_pass, sizeof(tmp_pass), "%s.%s", passname, view); + BLI_strncpy(passname, tmp_pass, sizeof(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++; + pass->view_id = echan->view_id; + BLI_strncpy(pass->view, view, sizeof(pass->view)); + BLI_strncpy(pass->internal_name, internal_name, EXR_PASS_MAXNAME); + if (pass->totchan >= EXR_PASS_MAXCHAN) break; } } if (echan) { - printf("error, too many channels in one pass: %s\n", echan->name); + printf("error, too many channels in one pass: %s\n", echan->m->name.c_str()); IMB_exr_close(data); return NULL; } @@ -1122,20 +1610,52 @@ static ExrHandle *imb_exr_begin_read_mem(InputFile *file, int width, int height) /* ********************************************************* */ /* debug only */ -static void exr_print_filecontents(InputFile *file) +static void exr_printf(const char *fmt, ...) { - const ChannelList &channels = file->header().channels(); +#if 0 + char output[1024]; + va_list args; + va_start(args, fmt); + std::vsprintf(output, fmt, args); + va_end(args); + printf("%s", output); +#else + (void)fmt; +#endif +} - for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) { - const Channel &channel = i.channel(); - printf("OpenEXR-load: Found channel %s of type %d\n", i.name(), channel.type); +static void exr_print_filecontents(MultiPartInputFile& file) +{ + int numparts = file.parts(); + if (numparts == 1 && hasMultiView(file.header(0))) { + const StringVector views = multiView(file.header(0)); + printf("OpenEXR-load: MultiView file\n"); + printf("OpenEXR-load: Default view: %s\n", defaultViewName(views).c_str()); + for (StringVector::const_iterator i = views.begin(); i != views.end(); ++i) { + printf("OpenEXR-load: Found view %s\n", (*i).c_str()); + } + } + else if (numparts > 1) { + printf("OpenEXR-load: MultiPart file\n"); + for (int i = 0; i < numparts; i++) { + if (file.header(i).hasView()) + printf("OpenEXR-load: Part %d: view = \"%s\"\n", i, file.header(i).view().c_str()); + } + } + + for (int j = 0; j < numparts; j++) { + const ChannelList& channels = file.header(j).channels(); + for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) { + const Channel& channel = i.channel(); + printf("OpenEXR-load: Found channel %s of type %d\n", i.name(), channel.type); + } } } /* for non-multilayer, map R G B A channel names to something that's in this file */ -static const char *exr_rgba_channelname(InputFile *file, const char *chan) +static const char *exr_rgba_channelname(MultiPartInputFile& file, const char *chan) { - const ChannelList &channels = file->header().channels(); + const ChannelList& channels = file.header(0).channels(); for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) { /* const Channel &channel = i.channel(); */ /* Not used yet */ @@ -1150,48 +1670,48 @@ static const char *exr_rgba_channelname(InputFile *file, const char *chan) return chan; } -static bool exr_has_rgb(InputFile *file) +static bool exr_has_rgb(MultiPartInputFile& file) { - return file->header().channels().findChannel("R") != NULL && - file->header().channels().findChannel("G") != NULL && - file->header().channels().findChannel("B") != NULL; + return file.header(0).channels().findChannel("R") != NULL && + file.header(0).channels().findChannel("G") != NULL && + file.header(0).channels().findChannel("B") != NULL; } -static bool exr_has_luma(InputFile *file) +static bool exr_has_luma(MultiPartInputFile& file) { /* Y channel is the luma and should always present fir luma space images, * optionally it could be also channels for chromas called BY and RY. */ - return file->header().channels().findChannel("Y") != NULL; + return file.header(0).channels().findChannel("Y") != NULL; } -static bool exr_has_chroma(InputFile *file) +static bool exr_has_chroma(MultiPartInputFile& file) { - return file->header().channels().findChannel("BY") != NULL && - file->header().channels().findChannel("RY") != NULL; + return file.header(0).channels().findChannel("BY") != NULL && + file.header(0).channels().findChannel("RY") != NULL; } -static int exr_has_zbuffer(InputFile *file) +static int exr_has_zbuffer(MultiPartInputFile& file) { - return !(file->header().channels().findChannel("Z") == NULL); + return !(file.header(0).channels().findChannel("Z") == NULL); } -static int exr_has_alpha(InputFile *file) +static int exr_has_alpha(MultiPartInputFile& file) { - return !(file->header().channels().findChannel("A") == NULL); + return !(file.header(0).channels().findChannel("A") == NULL); } -static bool exr_is_multilayer(InputFile *file) +static bool imb_exr_is_multilayer_file(MultiPartInputFile& file) { - const StringAttribute *comments = file->header().findTypedAttribute("BlenderMultiChannel"); - const ChannelList &channels = file->header().channels(); + const StringAttribute *comments = file.header(0).findTypedAttribute("BlenderMultiChannel"); + const ChannelList& channels = file.header(0).channels(); std::set layerNames; /* will not include empty layer names */ channels.layers(layerNames); if (comments || layerNames.size() > 1) - return 1; + return true; if (layerNames.size()) { /* if layerNames is not empty, it means at least one layer is non-empty, @@ -1206,17 +1726,122 @@ static bool exr_is_multilayer(InputFile *file) size_t pos = layerName.rfind ('.'); if (pos == std::string::npos) - return 1; + return true; } } - return 0; + return false; +} + +static void imb_exr_type_by_channels(ChannelList& channels, StringVector& views, + bool *r_singlelayer, bool *r_multilayer, bool *r_multiview) +{ + std::set layerNames; + + *r_singlelayer = true; + *r_multilayer = *r_multiview = false; + + /* will not include empty layer names */ + channels.layers(layerNames); + + if (views.size() && views[0] != "") + *r_multiview = true; + + if (layerNames.size()) { + /* if layerNames is not empty, it means at least one layer is non-empty, + * but it also could be layers without names in the file and such case + * shall be considered a multilayer exr + * + * that's what we do here: test whether there're empty layer names together + * with non-empty ones in the file + */ + for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); i++) + for (std::set::iterator i = layerNames.begin(); i != layerNames.end(); i++) + /* see if any layername differs from a viewname */ + if (imb_exr_get_multiView_id(views, *i) == -1) { + std::string layerName = *i; + size_t pos = layerName.rfind ('.'); + + if (pos != std::string::npos) { + *r_multilayer = true; + *r_singlelayer = false; + return; + } + } + } + else { + *r_singlelayer = true; + *r_multilayer = false; + *r_multiview = false; + } + + BLI_assert(r_singlelayer != r_multilayer); +} + +bool IMB_exr_has_singlelayer_multiview(void *handle) +{ + ExrHandle *data = (ExrHandle *)handle; + MultiPartInputFile *file = data->ifile; + std::set layerNames; + const ChannelList& channels = file->header(0).channels(); + const StringAttribute *comments; + + if (exr_has_multiview(*file) == false) + return false; + + comments = file->header(0).findTypedAttribute("BlenderMultiChannel"); + + if (comments) + return false; + + /* will not include empty layer names */ + channels.layers(layerNames); + + /* returns false if any layer differs from views list */ + if (layerNames.size()) + for (std::set::iterator i = layerNames.begin(); i != layerNames.end(); i++) + if (imb_exr_get_multiView_id(*data->multiView, *i) == -1) + return false; + + return true; +} + +bool IMB_exr_has_multilayer(void *handle) +{ + ExrHandle *data = (ExrHandle *)handle; + return imb_exr_is_multilayer_file(*data->ifile); +} + +static bool exr_has_multiview(MultiPartInputFile& file) +{ + return hasMultiView(file.header(0)); +} + +static bool exr_has_multipart_file(MultiPartInputFile& file) +{ + return file.parts() > 1; +} + +/* it returns true if the file is multilayer or multiview */ +static bool imb_exr_is_multi(MultiPartInputFile& file) +{ + /* multipart files are treated as multilayer in blender - even if they are single layer openexr with multiview */ + if (exr_has_multipart_file(file)) + return true; + + if (exr_has_multiview(file)) + return true; + + if (imb_exr_is_multilayer_file(file)) + return true; + + return false; } struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { struct ImBuf *ibuf = NULL; - InputFile *file = NULL; + MultiPartInputFile *file = NULL; if (imb_is_a_openexr(mem) == 0) return(NULL); @@ -1226,9 +1851,9 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char { Mem_IStream *membuf = new Mem_IStream(mem, size); bool is_multi; - file = new InputFile(*membuf); + file = new MultiPartInputFile(*membuf); - Box2i dw = file->header().dataWindow(); + Box2i dw = file->header(0).dataWindow(); const int width = dw.max.x - dw.min.x + 1; const int height = dw.max.y - dw.min.y + 1; @@ -1236,38 +1861,38 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char // dw.min.x, dw.min.y, dw.max.x, dw.max.y); if (0) // debug - exr_print_filecontents(file); + exr_print_filecontents(*file); - is_multi = exr_is_multilayer(file); + is_multi = imb_exr_is_multi(*file); /* 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 { - const int is_alpha = exr_has_alpha(file); + const int is_alpha = exr_has_alpha(*file); ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, 0); - if (hasXDensity(file->header())) { - ibuf->ppm[0] = xDensity(file->header()) * 39.3700787f; - ibuf->ppm[1] = ibuf->ppm[0] * (double)file->header().pixelAspectRatio(); + if (hasXDensity(file->header(0))) { + ibuf->ppm[0] = xDensity(file->header(0)) * 39.3700787f; + ibuf->ppm[1] = ibuf->ppm[0] * (double)file->header(0).pixelAspectRatio(); } ibuf->ftype = OPENEXR; if (!(flags & IB_test)) { - if (is_multi) { /* only enters with IB_multilayer flag set */ + if (is_multi && ((flags & IB_thumbnail) == 0)) { /* only enters with IB_multilayer flag set */ /* constructs channels for reading, allocates memory in channels */ - ExrHandle *handle = imb_exr_begin_read_mem(file, width, height); + 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! */ } } else { - const bool has_rgb = exr_has_rgb(file); - const bool has_luma = exr_has_luma(file); + const bool has_rgb = exr_has_rgb(*file); + const bool has_luma = exr_has_luma(*file); FrameBuffer frameBuffer; float *first; int xstride = sizeof(float) * 4; @@ -1281,27 +1906,27 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char first += 4 * (height - 1) * width; if (has_rgb) { - frameBuffer.insert(exr_rgba_channelname(file, "R"), + frameBuffer.insert(exr_rgba_channelname(*file, "R"), Slice(Imf::FLOAT, (char *) first, xstride, ystride)); - frameBuffer.insert(exr_rgba_channelname(file, "G"), + frameBuffer.insert(exr_rgba_channelname(*file, "G"), Slice(Imf::FLOAT, (char *) (first + 1), xstride, ystride)); - frameBuffer.insert(exr_rgba_channelname(file, "B"), + frameBuffer.insert(exr_rgba_channelname(*file, "B"), Slice(Imf::FLOAT, (char *) (first + 2), xstride, ystride)); } else if (has_luma) { - frameBuffer.insert(exr_rgba_channelname(file, "Y"), + frameBuffer.insert(exr_rgba_channelname(*file, "Y"), Slice(Imf::FLOAT, (char *) first, xstride, ystride)); - frameBuffer.insert(exr_rgba_channelname(file, "BY"), + frameBuffer.insert(exr_rgba_channelname(*file, "BY"), Slice(Imf::FLOAT, (char *) (first + 1), xstride, ystride, 1, 1, 0.5f)); - frameBuffer.insert(exr_rgba_channelname(file, "RY"), + frameBuffer.insert(exr_rgba_channelname(*file, "RY"), Slice(Imf::FLOAT, (char *) (first + 2), xstride, ystride, 1, 1, 0.5f)); } /* 1.0 is fill value, this still needs to be assigned even when (is_alpha == 0) */ - frameBuffer.insert(exr_rgba_channelname(file, "A"), + frameBuffer.insert(exr_rgba_channelname(*file, "A"), Slice(Imf::FLOAT, (char *) (first + 3), xstride, ystride, 1, 1, 1.0f)); - if (exr_has_zbuffer(file)) { + if (exr_has_zbuffer(*file)) { float *firstz; addzbuffloatImBuf(ibuf); @@ -1310,8 +1935,9 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *)firstz, sizeof(float), -width * sizeof(float))); } - file->setFrameBuffer(frameBuffer); - file->readPixels(dw.min.y, dw.max.y); + InputPart in (*file, 0); + in.setFrameBuffer(frameBuffer); + in.readPixels(dw.min.y, dw.max.y); // XXX, ImBuf has no nice way to deal with this. // ideally IM_rect would be used when the caller wants a rect BUT @@ -1325,7 +1951,7 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char if (!has_rgb && has_luma) { size_t a; - if (exr_has_chroma(file)) { + if (exr_has_chroma(*file)) { for (a = 0; a < (size_t) ibuf->x * ibuf->y; ++a) { float *color = ibuf->rect_float + a * 4; ycc_to_rgb(color[0] * 255.0f, color[1] * 255.0f, color[2] * 255.0f, @@ -1351,7 +1977,7 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char } return(ibuf); } - catch (const std::exception &exc) + catch (const std::exception& exc) { std::cerr << exc.what() << std::endl; if (ibuf) IMB_freeImBuf(ibuf); diff --git a/source/blender/imbuf/intern/openexr/openexr_multi.h b/source/blender/imbuf/intern/openexr/openexr_multi.h index 376d2401b1c..45ab0ed37c7 100644 --- a/source/blender/imbuf/intern/openexr/openexr_multi.h +++ b/source/blender/imbuf/intern/openexr/openexr_multi.h @@ -39,8 +39,9 @@ /* This api also supports max 8 channels per pass now. easy to fix! */ #define EXR_LAY_MAXNAME 64 #define EXR_PASS_MAXNAME 64 +#define EXR_VIEW_MAXNAME 64 #define EXR_TOT_MAXNAME 64 -#define EXR_PASS_MAXCHAN 8 +#define EXR_PASS_MAXCHAN 24 #ifdef __cplusplus @@ -48,25 +49,49 @@ extern "C" { #endif void *IMB_exr_get_handle(void); -void IMB_exr_add_channel(void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect); +void *IMB_exr_get_handle_name(const char *name); +void IMB_exr_add_channel(void *handle, const char *layname, const char *passname, const char *view, int xstride, int ystride, float *rect); int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *height); int IMB_exr_begin_write(void *handle, const char *filename, int width, int height, int compress); void IMB_exrtile_begin_write(void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley); void IMB_exr_set_channel(void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect); +float *IMB_exr_channel_rect(void *handle, const char *layname, const char *passname, const char *view); 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, int level); -void IMB_exrtile_clear_channels(void *handle); +void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, const char *viewname); +void IMB_exrmultiview_write_channels(void *handle, const char *viewname); +void IMB_exr_clear_channels(void *handle); -void IMB_exr_multilayer_convert(void *handle, void *base, - void * (*addlayer)(void *base, const char *str), - void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id)); +void IMB_exr_multilayer_convert( + void *handle, void *base, + void * (*addview)(void *base, const char *str), + void * (*addlayer)(void *base, const char *str), + void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, + const char *chan_id, const char *view)); + +void IMB_exr_multiview_convert( + void *handle, void *base, + void (*addview)(void *base, const char *str), + void (*addbuffer)(void *base, const char *str, struct ImBuf *ibuf, const int frame), + const int frame); + +bool IMB_exr_multiview_save( + struct ImBuf *ibuf, const char *name, const int flags, const size_t totviews, + const char * (*getview)(void *base, size_t view_id), + struct ImBuf * (*getbuffer)(void *base, const size_t view_id)); void IMB_exr_close(void *handle); +void IMB_exr_add_view(void *handle, const char *name); + +int IMB_exr_split_token(const char *str, const char *end, const char **token); + +bool IMB_exr_has_multilayer(void *handle); +bool IMB_exr_has_singlelayer_multiview(void *handle); + #ifdef __cplusplus } // extern "C" #endif diff --git a/source/blender/imbuf/intern/openexr/openexr_stub.cpp b/source/blender/imbuf/intern/openexr/openexr_stub.cpp index 21fa878c08a..c326efd2427 100644 --- a/source/blender/imbuf/intern/openexr/openexr_stub.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_stub.cpp @@ -31,27 +31,55 @@ #include "openexr_api.h" #include "openexr_multi.h" - +#include "BLI_utildefines.h" /* UNUSED_VARS */ void *IMB_exr_get_handle (void) {return NULL;} -void IMB_exr_add_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } +void *IMB_exr_get_handle_name (const char *name) {(void)name; return NULL;} +void IMB_exr_add_channel (void *handle, const char *layname, const char *passname, const char *view, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)passname; (void)xstride; (void)ystride; (void)rect; } int IMB_exr_begin_read (void *handle, const char *filename, int *width, int *height) { (void)handle; (void)filename; (void)width; (void)height; return 0;} int IMB_exr_begin_write (void *handle, const char *filename, int width, int height, int compress) { (void)handle; (void)filename; (void)width; (void)height; (void)compress; return 0;} void IMB_exrtile_begin_write (void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { (void)handle; (void)filename; (void)mipmap; (void)width; (void)height; (void)tilex; (void)tiley; } -void IMB_exr_set_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } +void IMB_exr_set_channel (void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)passname; (void)xstride; (void)ystride; (void)rect; } +float *IMB_exr_channel_rect (void *handle, const char *layname, const char *passname, const char *view) { (void)handle; (void)layname; (void)passname; (void)view; return NULL; } void IMB_exr_read_channels (void *handle) { (void)handle; } void IMB_exr_write_channels (void *handle) { (void)handle; } -void IMB_exrtile_write_channels (void *handle, int partx, int party, int level) { (void)handle; (void)partx; (void)party; (void)level; } -void IMB_exrtile_clear_channels (void *handle) { (void)handle; } +void IMB_exrtile_write_channels (void *handle, int partx, int party, int level, const char *viewname) { UNUSED_VARS(handle, partx, party, level, viewname); } +void IMB_exrmultiview_write_channels(void *handle, const char *viewname) { UNUSED_VARS(handle, viewname); } +void IMB_exr_clear_channels (void *handle) { (void)handle; } + +void IMB_exr_multilayer_convert( + void *handle, void *base, + void * (*addview)(void *base, const char *str), + void * (*addlayer)(void *base, const char *str), + void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, + const char *chan_id, const char *view)) +{ + UNUSED_VARS(handle, base, addview, addlayer, addpass); +} -void IMB_exr_multilayer_convert (void *handle, void *base, - void * (*addlayer)(void *base, const char *str), - void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id)) +void IMB_exr_multiview_convert( + void *handle, void *base, + void (*addview)(void *base, const char *str), + void (*addbuffer)(void *base, const char *str, struct ImBuf *ibuf, const int frame), const int frame) { - (void)handle; (void)base; (void)addlayer; (void)addpass; + UNUSED_VARS(handle, base, addview, addbuffer, frame); +} + +bool IMB_exr_multiview_save( + struct ImBuf *ibuf, const char *name, const int flags, const size_t totviews, + const char * (*getview)(void *base, size_t view_id), + struct ImBuf * (*getbuffer)(void *base, const size_t view_id)) +{ + UNUSED_VARS(ibuf, name, flags, totviews, getview, getbuffer); + return false; } void IMB_exr_close (void *handle) { (void)handle; } + +void IMB_exr_add_view(void *handle, const char *name) { UNUSED_VARS(handle, name); } +int IMB_exr_split_token(const char *str, const char *end, const char **token) { UNUSED_VARS(str, end, token); return 1; } +bool IMB_exr_has_multilayer(void *handle) { UNUSED_VARS(handle); return false; } +bool IMB_exr_has_singlelayer_multiview(void *handle) { UNUSED_VARS(handle); return false; } diff --git a/source/blender/imbuf/intern/stereoimbuf.c b/source/blender/imbuf/intern/stereoimbuf.c new file mode 100644 index 00000000000..cf9c6b388ff --- /dev/null +++ b/source/blender/imbuf/intern/stereoimbuf.c @@ -0,0 +1,1292 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015 by Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/imbuf/intern/stereoimbuf.c + * \ingroup imbuf + */ + +#include + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "IMB_allocimbuf.h" +#include "IMB_filetype.h" +#include "IMB_metadata.h" +#include "IMB_colormanagement_intern.h" + +#include "imbuf.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_threads.h" +#include "BLI_utildefines.h" + +#include "BLI_math.h" + +#include "DNA_userdef_types.h" +#include "DNA_scene_types.h" + +/* prototypes */ +struct Stereo3DData; +static void imb_stereo3d_write_doit(struct Stereo3DData *s3d_data, struct Stereo3dFormat *s3d); +static void imb_stereo3d_read_doit(struct Stereo3DData *s3d_data, struct Stereo3dFormat *s3d); + +typedef struct Stereo3DData { + struct { float *left, *right, *stereo; } rectf; + struct { uchar *left, *right, *stereo; } rect; + size_t x, y, channels; + bool is_float; +} Stereo3DData; + +static void imb_stereo3d_write_anaglyph(Stereo3DData *s3d, enum eStereo3dAnaglyphType mode) +{ + int x, y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width; + const int stride_to = width; + + int anaglyph_encoding[3][3] = { + {0, 1, 1}, + {1, 0, 1}, + {0, 0, 1}, + }; + + int r, g, b; + + r = anaglyph_encoding[mode][0]; + g = anaglyph_encoding[mode][1]; + b = anaglyph_encoding[mode][2]; + + if (s3d->is_float) { + float *rect_left = s3d->rectf.left; + float *rect_right = s3d->rectf.right; + float *rect_to = s3d->rectf.stereo; + + if (channels == 3) { + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * 3; + float *from[2] = { + rect_left + stride_from * y * 3, + rect_right + stride_from * y * 3, + }; + + for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { + to[0] = from[r][0]; + to[1] = from[g][1]; + to[2] = from[b][2]; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * 4; + float *from[2] = { + rect_left + stride_from * y * 4, + rect_right + stride_from * y * 4, + }; + + for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { + to[0] = from[r][0]; + to[1] = from[g][1]; + to[2] = from[b][2]; + to[3] = MAX2(from[0][2], from[0][2]); + } + } + } + } + else { + uchar *rect_left = s3d->rect.left; + uchar *rect_right = s3d->rect.right; + uchar *rect_to = s3d->rect.stereo; + + if (channels == 3) { + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * 3; + uchar *from[2] = { + rect_left + stride_from * y * 3, + rect_right + stride_from * y * 3, + }; + + for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { + to[0] = from[r][0]; + to[1] = from[g][1]; + to[2] = from[b][2]; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * 4; + uchar *from[2] = { + rect_left + stride_from * y * 4, + rect_right + stride_from * y * 4, + }; + + for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { + to[0] = from[r][0]; + to[1] = from[g][1]; + to[2] = from[b][2]; + to[3] = MAX2(from[0][2], from[0][2]); + } + } + } + } +} + +static void imb_stereo3d_write_interlace(Stereo3DData *s3d, enum eStereo3dInterlaceType mode, const bool swap) +{ + int x, y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width; + const int stride_to = width; + + if (s3d->is_float) { + const float *rect_left = s3d->rectf.left; + const float *rect_right = s3d->rectf.right; + float *rect_to = s3d->rectf.stereo; + + switch (mode) { + case S3D_INTERLACE_ROW: + { + char i = (char) swap; + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * channels; + const float *from[2] = { + rect_left + stride_from * y * channels, + rect_right + stride_from * y * channels, + }; + memcpy(to, from[i], sizeof(float) * channels * stride_from); + i = !i; + } + break; + } + case S3D_INTERLACE_COLUMN: + { + if (channels == 1) { + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y; + const float *from[2] = { + rect_left + stride_from * y, + rect_right + stride_from * y, + }; + + char i = (char) swap; + for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) { + to[0] = from[i][0]; + i = !i; + } + } + } + else if (channels == 3) { + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * 3; + const float *from[2] = { + rect_left + stride_from * y * 3, + rect_right + stride_from * y * 3, + }; + + char i = (char) swap; + for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { + copy_v3_v3(to, from[i]); + i = !i; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * channels; + const float *from[2] = { + rect_left + stride_from * y * channels, + rect_right + stride_from * y * channels, + }; + + char i = (char) swap; + for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { + copy_v4_v4(to, from[i]); + i = !i; + } + } + } + break; + } + case S3D_INTERLACE_CHECKERBOARD: + { + if (channels == 1) { + char i = (char) swap; + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y; + const float *from[2] = { + rect_left + stride_from * y, + rect_right + stride_from * y, + }; + char j = i; + for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) { + to[0] = from[j][0]; + j = !j; + } + i = !i; + } + } + else if (channels == 3) { + char i = (char) swap; + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * 3; + const float *from[2] = { + rect_left + stride_from * y * 3, + rect_right + stride_from * y * 3, + }; + char j = i; + for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { + copy_v3_v3(to, from[j]); + j = !j; + } + i = !i; + } + } + else if (channels == 4) { + char i = (char) swap; + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * 4; + const float *from[2] = { + rect_left + stride_from * y * 4, + rect_right + stride_from * y * 4, + }; + char j = i; + for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { + copy_v4_v4(to, from[j]); + j = !j; + } + i = !i; + } + } + break; + } + default: + { + break; + } + } + } + else { + const uchar *rect_left = s3d->rect.left; + const uchar *rect_right = s3d->rect.right; + uchar *rect_to = s3d->rect.stereo; + + switch (mode) { + case S3D_INTERLACE_ROW: + { + char i = (char) swap; + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * channels; + const uchar *from[2] = { + rect_left + stride_from * y * channels, + rect_right + stride_from * y * channels, + }; + memcpy(to, from[i], sizeof(uchar) * channels * stride_from); + i = !i; + } + break; + } + case S3D_INTERLACE_COLUMN: + { + if (channels == 1) { + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y; + const uchar *from[2] = { + rect_left + stride_from * y, + rect_right + stride_from * y, + }; + char i = (char) swap; + for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) { + to[0] = from[i][0]; + i = !i; + } + } + } + else if (channels == 3) { + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * 3; + const uchar *from[2] = { + rect_left + stride_from * y * 3, + rect_right + stride_from * y * 3, + }; + char i = (char) swap; + for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { + copy_v3_v3_char((char *)to, (char *)from[i]); + i = !i; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * 4; + const uchar *from[2] = { + rect_left + stride_from * y * 4, + rect_right + stride_from * y * 4, + }; + char i = (char) swap; + for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { + copy_v4_v4_char((char *)to, (char *)from[i]); + i = !i; + } + } + } + break; + } + case S3D_INTERLACE_CHECKERBOARD: + { + if (channels == 1) { + char i = (char) swap; + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y; + const uchar *from[2] = { + rect_left + stride_from * y, + rect_right + stride_from * y, + }; + char j = i; + for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) { + to[0] = from[j][0]; + j = !j; + } + i = !i; + } + } + else if (channels == 3) { + char i = (char) swap; + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * 3; + const uchar *from[2] = { + rect_left + stride_from * y * 3, + rect_right + stride_from * y * 3, + }; + char j = i; + for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { + copy_v3_v3_char((char *)to, (char *)from[j]); + j = !j; + } + i = !i; + } + } + else if (channels == 4) { + char i = (char) swap; + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * 4; + const uchar *from[2] = { + rect_left + stride_from * y * 4, + rect_right + stride_from * y * 4, + }; + char j = i; + for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { + copy_v4_v4_char((char *)to, (char *)from[j]); + j = !j; + } + i = !i; + } + } + break; + } + default: + { + break; + } + } + } +} + +/* stereo3d output (s3d->rectf.stereo) is always unsqueezed */ +static void imb_stereo3d_write_sidebyside(Stereo3DData *s3d, const bool crosseyed) +{ + int y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width; + const int stride_to = width * 2; + + const int l = (int) crosseyed; + const int r = !l; + + if (s3d->is_float) { + const float *rect_left = s3d->rectf.left; + const float *rect_right = s3d->rectf.right; + float *rect_to = s3d->rectf.stereo; + + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * channels; + const float *from[2] = { + rect_left + stride_from * y * channels, + rect_right + stride_from * y * channels, + }; + + memcpy(to, from[l], sizeof(float) * channels * stride_from); + memcpy(to + channels * stride_from, from[r], sizeof(float) * channels * stride_from); + } + } + else { + const uchar *rect_left = s3d->rect.left; + const uchar *rect_right = s3d->rect.right; + uchar *rect_to = s3d->rect.stereo; + + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * channels; + const uchar *from[2] = { + rect_left + stride_from * y * channels, + rect_right + stride_from * y * channels, + }; + + memcpy(to, from[l], sizeof(uchar) * channels * stride_from); + memcpy(to + channels * stride_from, from[r], sizeof(uchar) * channels * stride_from); + } + } +} + +/* stereo3d output (s3d->rectf.stereo) is always unsqueezed */ +static void imb_stereo3d_write_topbottom(Stereo3DData *s3d) +{ + int y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width; + const int stride_to = width; + + if (s3d->is_float) { + const float *rect_left = s3d->rectf.left; + const float *rect_right = s3d->rectf.right; + float *rect_to = s3d->rectf.stereo; + + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * channels; + const float *from[2] = { + rect_left + stride_from * y * channels, + rect_right + stride_from * y * channels, + }; + + memcpy(to, from[1], sizeof(float) * channels * stride_from); + memcpy(to + channels * height * stride_from, from[0], sizeof(float) * channels * stride_from); + } + } + else { + const uchar *rect_left = s3d->rect.left; + const uchar *rect_right = s3d->rect.right; + uchar *rect_to = s3d->rect.stereo; + + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * channels; + const uchar *from[2] = { + rect_left + stride_from * y * channels, + rect_right + stride_from * y * channels, + }; + + memcpy(to, from[1], sizeof(uchar) * channels * stride_from); + memcpy(to + channels * height * stride_from, from[0], sizeof(uchar) * channels * stride_from); + } + } +} + +/**************************** dimension utils ****************************************/ + +void IMB_stereo3d_write_dimensions( + const char mode, const bool is_squeezed, const size_t width, const size_t height, + size_t *r_width, size_t *r_height) +{ + switch (mode) { + case S3D_DISPLAY_SIDEBYSIDE: + { + *r_width = is_squeezed ? width : width * 2; + *r_height = height; + break; + } + case S3D_DISPLAY_TOPBOTTOM: + { + *r_width = width; + *r_height = is_squeezed ? height : height * 2; + break; + } + case S3D_DISPLAY_ANAGLYPH: + case S3D_DISPLAY_INTERLACE: + default: + { + *r_width = width; + *r_height = height; + break; + } + } +} + +void IMB_stereo3d_read_dimensions( + const char mode, const bool is_squeezed, const size_t width, const size_t height, + size_t *r_width, size_t *r_height) +{ + switch (mode) { + case S3D_DISPLAY_SIDEBYSIDE: + { + *r_width = is_squeezed ? width / 2 : width; + *r_height = height; + break; + } + case S3D_DISPLAY_TOPBOTTOM: + { + *r_width = width; + *r_height = is_squeezed ? height / 2 : height; + break; + } + case S3D_DISPLAY_ANAGLYPH: + case S3D_DISPLAY_INTERLACE: + default: + { + *r_width = width; + *r_height = height; + break; + } + } +} + +/**************************** un/squeeze frame ****************************************/ + +static void imb_stereo3d_squeeze_ImBuf(ImBuf *ibuf, Stereo3dFormat *s3d, const size_t x, const size_t y) +{ + if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false) + return; + + if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) + return; + + IMB_scaleImBuf_threaded(ibuf, x, y); +} + +static void imb_stereo3d_unsqueeze_ImBuf(ImBuf *ibuf, Stereo3dFormat *s3d, const size_t x, const size_t y) +{ + if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false) + return; + + if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) + return; + + IMB_scaleImBuf_threaded(ibuf, x, y); +} + +static void imb_stereo3d_squeeze_rectf(float *rectf, Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels) +{ + ImBuf *ibuf; + size_t width, height; + + if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false) + return; + + if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) + return; + + /* creates temporary imbuf to store the rectf */ + IMB_stereo3d_write_dimensions(s3d->display_mode, false, x, y, &width, &height); + ibuf = IMB_allocImBuf(width, height, channels, IB_rectfloat); + + IMB_buffer_float_from_float( + ibuf->rect_float, rectf, channels, + IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false, + width, height, width, width); + + IMB_scaleImBuf_threaded(ibuf, x, y); + rectf = MEM_dupallocN(ibuf->rect_float); + IMB_freeImBuf(ibuf); +} + +static void imb_stereo3d_squeeze_rect(int *rect, Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels) +{ + ImBuf *ibuf; + size_t width, height; + + if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false) + return; + + if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) + return; + + /* creates temporary imbuf to store the rectf */ + IMB_stereo3d_write_dimensions(s3d->display_mode, false, x, y, &width, &height); + ibuf = IMB_allocImBuf(width, height, channels, IB_rect); + + IMB_buffer_byte_from_byte( + (unsigned char *)ibuf->rect, (unsigned char *)rect, + IB_PROFILE_SRGB, IB_PROFILE_SRGB, false, + width, height, width, width); + + IMB_scaleImBuf_threaded(ibuf, x, y); + rect = MEM_dupallocN(ibuf->rect); + IMB_freeImBuf(ibuf); +} + + +/*************************** preparing to call the write functions **************************/ + +static void imb_stereo3d_data_initialize( + Stereo3DData *s3d_data, const bool is_float, + const size_t x, const size_t y, const size_t channels, + int *rect_left, int *rect_right, int *rect_stereo, + float *rectf_left, float *rectf_right, float *rectf_stereo) +{ + s3d_data->is_float = is_float; + s3d_data->x = x; + s3d_data->y = y; + s3d_data->channels = channels; + s3d_data->rect.left = (uchar *)rect_left; + s3d_data->rect.right = (uchar *)rect_right; + s3d_data->rect.stereo = (uchar *)rect_stereo; + s3d_data->rectf.left = rectf_left; + s3d_data->rectf.right = rectf_right; + s3d_data->rectf.stereo = rectf_stereo; +} + +int *IMB_stereo3d_from_rect( + ImageFormatData *im_format, const size_t x, const size_t y, const size_t channels, + int *rect_left, int *rect_right) +{ + int *r_rect; + Stereo3DData s3d_data = {{NULL}}; + size_t width, height; + const bool is_float = im_format->depth > 8; + + IMB_stereo3d_write_dimensions(im_format->stereo3d_format.display_mode, false, x, y, &width, &height); + r_rect = MEM_mallocN(channels * sizeof(int) * width * height, __func__); + + imb_stereo3d_data_initialize(&s3d_data, is_float, x, y, channels, rect_left, rect_right, r_rect, NULL, NULL, NULL); + imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format); + imb_stereo3d_squeeze_rect(r_rect, &im_format->stereo3d_format, x, y, channels); + + return r_rect; +} + +float *IMB_stereo3d_from_rectf( + ImageFormatData *im_format, const size_t x, const size_t y, const size_t channels, + float *rectf_left, float *rectf_right) +{ + float *r_rectf; + Stereo3DData s3d_data = {{NULL}}; + size_t width, height; + const bool is_float = im_format->depth > 8; + + IMB_stereo3d_write_dimensions(im_format->stereo3d_format.display_mode, false, x, y, &width, &height); + r_rectf = MEM_mallocN(channels * sizeof(float) * width * height, __func__); + + imb_stereo3d_data_initialize(&s3d_data, is_float, x, y, channels, NULL, NULL, NULL, rectf_left, rectf_right, r_rectf); + imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format); + imb_stereo3d_squeeze_rectf(r_rectf, &im_format->stereo3d_format, x, y, channels); + + return r_rectf; +} + +/* left/right are always float */ +ImBuf *IMB_stereo3d_ImBuf(ImageFormatData *im_format, ImBuf *ibuf_left, ImBuf *ibuf_right) +{ + ImBuf *ibuf_stereo = NULL; + Stereo3DData s3d_data = {{NULL}}; + size_t width, height; + const bool is_float = im_format->depth > 8; + + IMB_stereo3d_write_dimensions(im_format->stereo3d_format.display_mode, false, ibuf_left->x, ibuf_left->y, &width, &height); + ibuf_stereo = IMB_allocImBuf(width, height, ibuf_left->planes, (is_float ? IB_rectfloat : IB_rect)); + + /* copy flags for IB_fields and other settings */ + ibuf_stereo->flags = ibuf_left->flags; + + imb_stereo3d_data_initialize( + &s3d_data, is_float, ibuf_left->x, ibuf_left->y, 4, + (int *)ibuf_left->rect, (int *)ibuf_right->rect, (int *)ibuf_stereo->rect, + ibuf_left->rect_float, ibuf_right->rect_float, ibuf_stereo->rect_float); + + imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format); + imb_stereo3d_squeeze_ImBuf(ibuf_stereo, &im_format->stereo3d_format, ibuf_left->x, ibuf_left->y); + + return ibuf_stereo; +} + +static void imb_stereo3d_write_doit(Stereo3DData *s3d_data, Stereo3dFormat *s3d) +{ + switch (s3d->display_mode) { + case S3D_DISPLAY_ANAGLYPH: + imb_stereo3d_write_anaglyph(s3d_data, s3d->anaglyph_type); + break; + case S3D_DISPLAY_INTERLACE: + imb_stereo3d_write_interlace(s3d_data, s3d->interlace_type, (s3d->flag & S3D_INTERLACE_SWAP) != 0); + break; + case S3D_DISPLAY_SIDEBYSIDE: + imb_stereo3d_write_sidebyside(s3d_data, (s3d->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0); + break; + case S3D_DISPLAY_TOPBOTTOM: + imb_stereo3d_write_topbottom(s3d_data); + break; + default: + break; + } +} + +/******************************** reading stereo imbufs **********************/ + +static void imb_stereo3d_read_anaglyph(Stereo3DData *s3d, enum eStereo3dAnaglyphType mode) +{ + int x, y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width; + const int stride_to = width; + + int anaglyph_encoding[3][3] = { + {0, 1, 1}, + {1, 0, 1}, + {0, 0, 1}, + }; + + int r, g, b; + + r = anaglyph_encoding[mode][0]; + g = anaglyph_encoding[mode][1]; + b = anaglyph_encoding[mode][2]; + + if (s3d->is_float) { + float *rect_left = s3d->rectf.left; + float *rect_right = s3d->rectf.right; + float *rect_from = s3d->rectf.stereo; + + if (channels == 3) { + for (y = 0; y < height; y++) { + float *from = rect_from + stride_from * y * 3; + float *to[2] = { + rect_left + stride_to * y * 3, + rect_right + stride_to * y * 3, + }; + + for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { + to[r][0] = from[0]; + to[g][1] = from[1]; + to[b][2] = from[2]; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + float *from = rect_from + stride_from * y * 4; + float *to[2] = { + rect_left + stride_to * y * 4, + rect_right + stride_to * y * 4, + }; + + for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { + to[r][0] = from[0]; + to[g][1] = from[1]; + to[b][2] = from[2]; + to[0][3] = to[1][3] = from[3]; + } + } + } + } + else { + uchar *rect_left = s3d->rect.left; + uchar *rect_right = s3d->rect.right; + uchar *rect_from = s3d->rect.stereo; + + if (channels == 3) { + for (y = 0; y < height; y++) { + uchar *from = rect_from + stride_from * y * 3; + uchar *to[2] = { + rect_left + stride_to * y * 3, + rect_right + stride_to * y * 3, + }; + + for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { + to[r][0] = from[0]; + to[g][1] = from[1]; + to[b][2] = from[2]; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + uchar *from = rect_from + stride_from * y * 4; + uchar *to[2] = { + rect_left + stride_to * y * 4, + rect_right + stride_to * y * 4, + }; + + for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { + to[r][0] = from[0]; + to[g][1] = from[1]; + to[b][2] = from[2]; + to[0][3] = to[1][3] = from[3]; + } + } + } + } +} + +static void imb_stereo3d_read_interlace(Stereo3DData *s3d, enum eStereo3dInterlaceType mode, const bool swap) +{ + int x, y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width; + const int stride_to = width; + + if (s3d->is_float) { + float *rect_left = s3d->rectf.left; + float *rect_right = s3d->rectf.right; + const float *rect_from = s3d->rectf.stereo; + + switch (mode) { + case S3D_INTERLACE_ROW: + { + char i = (char) swap; + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y * channels; + float *to[2] = { + rect_left + stride_to * y * channels, + rect_right + stride_to * y * channels, + }; + memcpy(to[i], from, sizeof(float) * channels * stride_to); + i = !i; + } + break; + } + case S3D_INTERLACE_COLUMN: + { + if (channels == 1) { + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y; + float *to[2] = { + rect_left + stride_to * y, + rect_right + stride_to * y, + }; + + char i = (char) swap; + for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) { + to[i][0] = from[0]; + i = !i; + } + } + } + else if (channels == 3) { + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y * 3; + float *to[2] = { + rect_left + stride_to * y * 3, + rect_right + stride_to * y * 3, + }; + + char i = (char) swap; + for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { + copy_v3_v3(to[i], from); + i = !i; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y * channels; + float *to[2] = { + rect_left + stride_to * y * channels, + rect_right + stride_to * y * channels, + }; + + char i = (char) swap; + for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { + copy_v4_v4(to[i], from); + i = !i; + } + } + } + break; + } + case S3D_INTERLACE_CHECKERBOARD: + { + if (channels == 1) { + char i = (char) swap; + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y; + float *to[2] = { + rect_left + stride_to * y, + rect_right + stride_to * y, + }; + char j = i; + for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) { + to[j][0] = from[0]; + j = !j; + } + i = !i; + } + } + else if (channels == 3) { + char i = (char) swap; + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y * 3; + float *to[2] = { + rect_left + stride_to * y * 3, + rect_right + stride_to * y * 3, + }; + char j = i; + for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { + copy_v3_v3(to[j], from); + j = !j; + } + i = !i; + } + } + else if (channels == 4) { + char i = (char) swap; + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y * 4; + float *to[2] = { + rect_left + stride_to * y * 4, + rect_right + stride_to * y * 4, + }; + char j = i; + for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { + copy_v4_v4(to[j], from); + j = !j; + } + i = !i; + } + } + break; + } + default: + { + break; + } + } + } + else { + uchar *rect_left = s3d->rect.right; + uchar *rect_right = s3d->rect.left; + const uchar *rect_from = s3d->rect.stereo; + + switch (mode) { + case S3D_INTERLACE_ROW: + { + char i = (char) swap; + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y * channels; + uchar *to[2] = { + rect_left + stride_to * y * channels, + rect_right + stride_to * y * channels, + }; + memcpy(to[i], from, sizeof(uchar) * channels * stride_to); + i = !i; + } + break; + } + case S3D_INTERLACE_COLUMN: + { + if (channels == 1) { + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y; + uchar *to[2] = { + rect_left + stride_to * y, + rect_right + stride_to * y, + }; + char i = (char) swap; + for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) { + to[i][0] = from[0]; + i = !i; + } + } + } + else if (channels == 3) { + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y * 3; + uchar *to[2] = { + rect_left + stride_to * y * 3, + rect_right + stride_to * y * 3, + }; + char i = (char) swap; + for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { + copy_v3_v3_char((char *)to[i], (char *)from); + i = !i; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y * 4; + uchar *to[2] = { + rect_left + stride_to * y * 4, + rect_right + stride_to * y * 4, + }; + char i = (char) swap; + for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { + copy_v4_v4_char((char *)to[i], (char *)from); + i = !i; + } + } + } + break; + } + case S3D_INTERLACE_CHECKERBOARD: + { + if (channels == 1) { + char i = (char) swap; + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y; + uchar *to[2] = { + rect_left + stride_to * y, + rect_right + stride_to * y, + }; + char j = i; + for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) { + to[j][0] = from[0]; + j = !j; + } + i = !i; + } + } + else if (channels == 3) { + char i = (char) swap; + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y * 3; + uchar *to[2] = { + rect_left + stride_to * y * 3, + rect_right + stride_to * y * 3, + }; + char j = i; + for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { + copy_v3_v3_char((char *)to[j], (char *)from); + j = !j; + } + i = !i; + } + } + else if (channels == 4) { + char i = (char) swap; + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y * 4; + uchar *to[2] = { + rect_left + stride_to * y * 4, + rect_right + stride_to * y * 4, + }; + char j = i; + for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { + copy_v4_v4_char((char *)to[j], (char *)from); + j = !j; + } + i = !i; + } + } + break; + } + default: + { + break; + } + } + } +} + +/* stereo input (s3d->rectf.stereo) is always unsqueezed */ +static void imb_stereo3d_read_sidebyside(Stereo3DData *s3d, const bool crosseyed) +{ + int y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width * 2; + const int stride_to = width; + + const int l = (int) crosseyed; + const int r = !l; + + if (s3d->is_float) { + float *rect_left = s3d->rectf.left; + float *rect_right = s3d->rectf.right; + const float *rect_from = s3d->rectf.stereo; + + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y * channels; + float *to[2] = { + rect_left + stride_to * y * channels, + rect_right + stride_to * y * channels, + }; + + memcpy(to[l], from, sizeof(float) * channels * stride_to); + memcpy(to[r], from + channels * stride_to, sizeof(float) * channels * stride_to); + } + } + else { + uchar *rect_left = s3d->rect.left; + uchar *rect_right = s3d->rect.right; + const uchar *rect_from = s3d->rect.stereo; + + /* always RGBA input/output */ + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y * channels; + uchar *to[2] = { + rect_left + stride_to * y * channels, + rect_right + stride_to * y * channels, + }; + + memcpy(to[l], from, sizeof(uchar) * channels * stride_to); + memcpy(to[r], from + channels * stride_to, sizeof(uchar) * channels * stride_to); + } + } +} + +/* stereo input (s3d->rectf.stereo) is always unsqueezed */ +static void imb_stereo3d_read_topbottom(Stereo3DData *s3d) +{ + int y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width; + const int stride_to = width; + + if (s3d->is_float) { + float *rect_left = s3d->rectf.left; + float *rect_right = s3d->rectf.right; + const float *rect_from = s3d->rectf.stereo; + + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y * channels; + float *to[2] = { + rect_left + stride_to * y * channels, + rect_right + stride_to * y * channels, + }; + + memcpy(to[1], from, sizeof(float) * channels * stride_to); + memcpy(to[0], from + channels * height * stride_to, sizeof(float) * channels * stride_to); + } + } + else { + uchar *rect_left = s3d->rect.left; + uchar *rect_right = s3d->rect.right; + const uchar *rect_from = s3d->rect.stereo; + + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y * channels; + uchar *to[2] = { + rect_left + stride_to * y * channels, + rect_right + stride_to * y * channels, + }; + + memcpy(to[1], from, sizeof(uchar) * channels * stride_to); + memcpy(to[0], from + channels * height * stride_to, sizeof(uchar) * channels * stride_to); + } + } +} + + +/*************************** preparing to call the read functions **************************/ + +/* reading a stereo encoded ibuf (*left) and generating two ibufs from it (*left and *right) */ +void IMB_ImBufFromStereo3d( + Stereo3dFormat *s3d, ImBuf *ibuf_stereo3d, + ImBuf **r_ibuf_left, ImBuf **r_ibuf_right) +{ + Stereo3DData s3d_data = {{NULL}}; + ImBuf *ibuf_left, *ibuf_right; + size_t width, height; + const bool is_float = (ibuf_stereo3d->rect_float != NULL); + + IMB_stereo3d_read_dimensions( + s3d->display_mode, ((s3d->flag & S3D_SQUEEZED_FRAME) == 0), ibuf_stereo3d->x, ibuf_stereo3d->y, + &width, &height); + + ibuf_left = IMB_allocImBuf(width, height, ibuf_stereo3d->planes, (is_float ? IB_rectfloat : IB_rect)); + ibuf_right = IMB_allocImBuf(width, height, ibuf_stereo3d->planes, (is_float ? IB_rectfloat : IB_rect)); + + /* copy flags for IB_fields and other settings */ + ibuf_left->flags = ibuf_stereo3d->flags; + ibuf_right->flags = ibuf_stereo3d->flags; + + /* we always work with unsqueezed formats */ + IMB_stereo3d_write_dimensions( + s3d->display_mode, ((s3d->flag & S3D_SQUEEZED_FRAME) == 0), ibuf_stereo3d->x, ibuf_stereo3d->y, + &width, &height); + imb_stereo3d_unsqueeze_ImBuf(ibuf_stereo3d, s3d, width, height); + + imb_stereo3d_data_initialize( + &s3d_data, is_float, ibuf_left->x, ibuf_left->y, 4, + (int *)ibuf_left->rect, (int *)ibuf_right->rect, (int *)ibuf_stereo3d->rect, + ibuf_left->rect_float, ibuf_right->rect_float, ibuf_stereo3d->rect_float); + + imb_stereo3d_read_doit(&s3d_data, s3d); + + if (ibuf_stereo3d->flags & (IB_zbuf | IB_zbuffloat)) { + if (is_float) { + addzbuffloatImBuf(ibuf_left); + addzbuffloatImBuf(ibuf_right); + } + else { + addzbufImBuf(ibuf_left); + addzbufImBuf(ibuf_right); + } + + imb_stereo3d_data_initialize( + &s3d_data, is_float, ibuf_left->x, ibuf_left->y, 1, + (int *)ibuf_left->zbuf, (int *)ibuf_right->zbuf, (int *)ibuf_stereo3d->zbuf, + ibuf_left->zbuf_float, ibuf_right->zbuf_float, ibuf_stereo3d->zbuf_float); + + imb_stereo3d_read_doit(&s3d_data, s3d); + } + + IMB_freeImBuf(ibuf_stereo3d); + + *r_ibuf_left = ibuf_left; + *r_ibuf_right = ibuf_right; +} + +static void imb_stereo3d_read_doit(Stereo3DData *s3d_data, Stereo3dFormat *s3d) +{ + switch (s3d->display_mode) { + case S3D_DISPLAY_ANAGLYPH: + imb_stereo3d_read_anaglyph(s3d_data, s3d->anaglyph_type); + break; + case S3D_DISPLAY_INTERLACE: + imb_stereo3d_read_interlace(s3d_data, s3d->interlace_type, (s3d->flag & S3D_INTERLACE_SWAP) != 0); + break; + case S3D_DISPLAY_SIDEBYSIDE: + imb_stereo3d_read_sidebyside(s3d_data, (s3d->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0); + break; + case S3D_DISPLAY_TOPBOTTOM: + imb_stereo3d_read_topbottom(s3d_data); + break; + default: + break; + } +} diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 118f0405303..21f440a8232 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -338,7 +338,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im img = IMB_loadblend_thumb(path); } else { - img = IMB_loadiffname(path, IB_rect | IB_metadata, NULL); + img = IMB_loadiffname(path, IB_rect | IB_metadata | IB_thumbnail, NULL); } } diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index 32100aa2288..3fee6688014 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -439,3 +439,15 @@ bool IMB_isanim(const char *filename) return (type && type != ANIM_SEQUENCE); } + +bool IMB_isfloat(ImBuf *ibuf) +{ + ImFileType *type; + + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { + if (type->ftype(type, ibuf)) { + return (type->flag & IM_FTYPE_FLOAT) != 0; + } + } + return false; +} diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c index 087330d10d2..5e9ccf4437e 100644 --- a/source/blender/imbuf/intern/writeimage.c +++ b/source/blender/imbuf/intern/writeimage.c @@ -43,19 +43,7 @@ static ImBuf *prepare_write_imbuf(ImFileType *type, ImBuf *ibuf) { - ImBuf *write_ibuf = ibuf; - - if (type->flag & IM_FTYPE_FLOAT) { - /* pass */ - } - else { - if (ibuf->rect == NULL && ibuf->rect_float) { - ibuf->rect_colorspace = colormanage_colorspace_get_roled(COLOR_ROLE_DEFAULT_BYTE); - IMB_rect_from_float(ibuf); - } - } - - return write_ibuf; + return IMB_prepare_write_ImBuf((type->flag & IM_FTYPE_FLOAT), ibuf); } short IMB_saveiff(struct ImBuf *ibuf, const char *name, int flags) @@ -86,3 +74,19 @@ short IMB_saveiff(struct ImBuf *ibuf, const char *name, int flags) return false; } +ImBuf *IMB_prepare_write_ImBuf(const bool isfloat, ImBuf *ibuf) +{ + ImBuf *write_ibuf = ibuf; + + if (isfloat) { + /* pass */ + } + else { + if (ibuf->rect == NULL && ibuf->rect_float) { + ibuf->rect_colorspace = colormanage_colorspace_get_roled(COLOR_ROLE_DEFAULT_BYTE); + IMB_rect_from_float(ibuf); + } + } + + return write_ibuf; +} diff --git a/source/blender/makesdna/DNA_camera_types.h b/source/blender/makesdna/DNA_camera_types.h index c67a356a708..6a9942aea66 100644 --- a/source/blender/makesdna/DNA_camera_types.h +++ b/source/blender/makesdna/DNA_camera_types.h @@ -44,6 +44,16 @@ struct Object; struct AnimData; struct Ipo; +/* ------------------------------------------- */ +/* Stereo Settings */ +typedef struct CameraStereoSettings { + float interocular_distance; + float convergence_distance; + short convergence_mode; + short pivot; + short pad, pad2; +} CameraStereoSettings; + typedef struct Camera { ID id; struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */ @@ -69,6 +79,9 @@ typedef struct Camera { char sensor_fit; char pad[7]; + + /* Stereo settings */ + struct CameraStereoSettings stereo; } Camera; /* **************** CAMERA ********************* */ @@ -123,6 +136,20 @@ enum { #define DEFAULT_SENSOR_WIDTH 32.0f #define DEFAULT_SENSOR_HEIGHT 18.0f +/* stereo->convergence_mode */ +enum { + CAM_S3D_OFFAXIS = 0, + CAM_S3D_PARALLEL = 1, + CAM_S3D_TOE = 2, +}; + +/* stereo->pivot */ +enum { + CAM_S3D_PIVOT_LEFT = 0, + CAM_S3D_PIVOT_RIGHT = 1, + CAM_S3D_PIVOT_CENTER = 2, +}; + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index 7444abb6d11..79980c6d2d5 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -43,7 +43,6 @@ struct MovieCache; struct RenderResult; struct GPUTexture; - /* ImageUser is in Texture, in Nodes, Background Image, Image Window, .... */ /* should be used in conjunction with an ID * to Image. */ typedef struct ImageUser { @@ -53,16 +52,34 @@ typedef struct ImageUser { int frames; /* total amount of frames to use */ int offset, sfra; /* offset within movie, start frame in global time */ char fie_ima, cycl; /* fields/image in movie, cyclic flag */ - char ok, pad; + char ok; + + char multiview_eye; /* multiview current eye - for internal use of drawing routines */ - short multi_index, layer, pass; /* listbase indices, for menu browsing or retrieve buffer */ + short multi_index, view, layer, pass; /* listbase indices, for menu browsing or retrieve buffer */ short flag; - - int pad2; + short passtype; } ImageUser; +typedef struct ImageAnim { + struct ImageAnim *next, *prev; + struct anim *anim; +} ImageAnim; + +typedef struct ImageView { + struct ImageView *next, *prev; + char name[64]; /* MAX_NAME */ + char filepath[1024]; /* 1024 = FILE_MAX */ +} ImageView; + +typedef struct ImagePackedFile { + struct ImagePackedFile *next, *prev; + struct PackedFile *packedfile; + char filepath[1024]; /* 1024 = FILE_MAX */ +} ImagePackedFile; + typedef struct RenderSlot { char name[64]; /* 64 = MAX_NAME */ } RenderSlot; @@ -72,6 +89,7 @@ typedef struct RenderSlot { #define IMA_ANIM_REFRESHED 2 /* #define IMA_DO_PREMUL 4 */ #define IMA_NEED_FRAME_RECALC 8 +#define IMA_SHOW_STEREO 16 typedef struct Image { ID id; @@ -82,13 +100,13 @@ typedef struct Image { struct GPUTexture *gputexture; /* not written in file */ /* sources from: */ - struct anim *anim; + ListBase anims; struct RenderResult *rr; struct RenderResult *renders[8]; /* IMA_MAX_RENDER_SLOT */ short render_slot, last_render_slot; - - short ok, flag; + + int flag; short source, type; int lastframe; @@ -99,14 +117,16 @@ typedef struct Image { unsigned int bindcode; /* only for current image... */ unsigned int *repbind; /* for repeat of parts of images */ - struct PackedFile *packedfile; + struct PackedFile *packedfile; /* deprecated */ + struct ListBase packedfiles; struct PreviewImage *preview; /* game engine tile animation */ float lastupdate; int lastused; short animspeed; - short pad2; + + short ok; /* for generated images */ int gen_x, gen_y; @@ -121,7 +141,14 @@ typedef struct Image { ColorManagedColorspaceSettings colorspace_settings; char alpha_mode; - char pad[7]; + char pad[5]; + + /* Multiview */ + char eye; /* for viewer node stereoscopy */ + char views_format; + ListBase views; + struct Stereo3dFormat *stereo3d_format; + RenderSlot render_slots[8]; /* 8 = IMA_MAX_RENDER_SLOT */ } Image; @@ -143,6 +170,9 @@ enum { IMA_VIEW_AS_RENDER = (1 << 11), IMA_IGNORE_ALPHA = (1 << 12), IMA_DEINTERLACE = (1 << 13), + IMA_USE_VIEWS = (1 << 14), + IMA_IS_STEREO = (1 << 15), + IMA_IS_MULTIVIEW = (1 << 16), /* similar to stereo, but a more general case */ }; #if (DNA_DEPRECATED_GCC_POISON == 1) diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 9ab6527daee..2a1a35d158a 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -263,6 +263,7 @@ typedef struct bNode { */ #define NODE_UPDATE 0xFFFF /* generic update flag (includes all others) */ #define NODE_UPDATE_ID 1 /* associated id data block has changed */ +#define NODE_UPDATE_OPERATOR 2 /* node update triggered from update operator */ /* Unique hash key for identifying node instances * Defined as a struct because DNA does not support other typedefs. diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index ac0803d494c..250bfe85ec2 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -47,6 +47,7 @@ extern "C" { #include "DNA_ID.h" #include "DNA_freestyle_types.h" #include "DNA_gpu_types.h" +#include "DNA_userdef_types.h" struct CurveMapping; struct Object; @@ -249,6 +250,73 @@ typedef enum ScenePassType { /* note, srl->passflag is treestore element 'nr' in outliner, short still... */ +/* View - MultiView */ +typedef struct SceneRenderView { + struct SceneRenderView *next, *prev; + + char name[64]; /* MAX_NAME */ + char suffix[64]; /* MAX_NAME */ + + int viewflag; + int pad[2]; + char pad2[4]; + +} SceneRenderView; + +/* srv->viewflag */ +#define SCE_VIEW_DISABLE (1<<0) + +/* scene.render.views_format */ +enum { + SCE_VIEWS_FORMAT_STEREO_3D = 0, + SCE_VIEWS_FORMAT_MULTIVIEW = 1, +}; + +/* ImageFormatData.views_output */ +enum { + R_IMF_VIEWS_INDIVIDUAL = 0, + R_IMF_VIEWS_STEREO_3D = 1, + R_IMF_VIEWS_MULTIVIEW = 2, +}; + +typedef struct Stereo3dFormat { + short flag; + char display_mode; /* encoding mode */ + char anaglyph_type; /* anaglyph scheme for the user display */ + char interlace_type; /* interlace type for the user display */ + char pad[3]; +} Stereo3dFormat; + +/* Stereo3dFormat.display_mode */ +typedef enum eStereoDisplayMode { + S3D_DISPLAY_ANAGLYPH = 0, + S3D_DISPLAY_INTERLACE = 1, + S3D_DISPLAY_PAGEFLIP = 2, + S3D_DISPLAY_SIDEBYSIDE = 3, + S3D_DISPLAY_TOPBOTTOM = 4, +} eStereoDisplayMode; + +/* Stereo3dFormat.flag */ +typedef enum eStereo3dFlag { + S3D_INTERLACE_SWAP = (1 << 0), + S3D_SIDEBYSIDE_CROSSEYED = (1 << 1), + S3D_SQUEEZED_FRAME = (1 << 2), +} eStereo3dFlag; + +/* Stereo3dFormat.anaglyph_type */ +typedef enum eStereo3dAnaglyphType { + S3D_ANAGLYPH_REDCYAN = 0, + S3D_ANAGLYPH_GREENMAGENTA = 1, + S3D_ANAGLYPH_YELLOWBLUE = 2, +} eStereo3dAnaglyphType; + +/* Stereo3dFormat.interlace_type */ +typedef enum eStereo3dInterlaceType { + S3D_INTERLACE_ROW = 0, + S3D_INTERLACE_COLUMN = 1, + S3D_INTERLACE_CHECKERBOARD = 2, +} eStereo3dInterlaceType; + /* *************************************************************** */ /* Generic image format settings, @@ -286,7 +354,11 @@ typedef struct ImageFormatData { char jp2_flag; char jp2_codec; - char pad[6]; + char pad[5]; + + /* Multiview */ + char views_format; + Stereo3dFormat stereo3d_format; /* color management */ ColorManagedViewSettings view_settings; @@ -616,6 +688,12 @@ typedef struct RenderData { int preview_start_resolution; int pad; + + /* MultiView */ + ListBase views; + short actview; + short views_format; + short pad8[2]; } RenderData; /* *************************************************************** */ @@ -810,6 +888,19 @@ enum { #define UV_SCULPT_TOOL_RELAX_LAPLACIAN 1 #define UV_SCULPT_TOOL_RELAX_HC 2 +/* Stereo Flags */ +#define STEREO_RIGHT_NAME "right" +#define STEREO_LEFT_NAME "left" +#define STEREO_RIGHT_SUFFIX "_R" +#define STEREO_LEFT_SUFFIX "_L" + +typedef enum StereoViews { + STEREO_LEFT_ID = 0, + STEREO_RIGHT_ID = 1, + STEREO_3D_ID = 2, + STEREO_MONO_ID = 3, +} StereoViews; + /* Markers */ typedef struct TimeMarker { @@ -1440,6 +1531,7 @@ typedef struct Scene { #define R_TEXNODE_PREVIEW 0x40000 #define R_VIEWPORT_PREVIEW 0x80000 #define R_EXR_CACHE_FILE 0x100000 +#define R_MULTIVIEW 0x200000 /* r->stamp */ #define R_STAMP_TIME 0x0001 diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 46a91cf6ceb..76c27fd3547 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -53,6 +53,11 @@ struct MovieClip; /* strlens; 256= FILE_MAXFILE, 768= FILE_MAXDIR */ +typedef struct StripAnim { + struct StripAnim *next, *prev; + struct anim *anim; +} StripAnim; + typedef struct StripElem { char name[256]; int orig_width, orig_height; @@ -156,8 +161,7 @@ typedef struct Sequence { struct Object *scene_camera; /* override scene camera */ struct MovieClip *clip; /* for MOVIECLIP strips */ struct Mask *mask; /* for MASK strips */ - - struct anim *anim; /* for MOVIE strips */ + ListBase anims; /* for MOVIE strips */ float effect_fader; float speed_fader; @@ -187,7 +191,11 @@ typedef struct Sequence { int sfra; /* starting frame according to the timeline of the scene. */ char alpha_mode; - char pad[3]; + char pad[2]; + + /* Multiview */ + char views_format; + struct Stereo3dFormat *stereo3d_format; struct IDProperty *prop; @@ -376,6 +384,7 @@ enum { /* don't include Grease Pencil in OpenGL previews of Scene strips */ SEQ_SCENE_NO_GPENCIL = (1 << 28), + SEQ_USE_VIEWS = (1 << 29), SEQ_INVALID_EFFECT = (1 << 31), }; diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index dff6d3cacb5..05127f176b4 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -500,6 +500,9 @@ typedef struct SpaceSeq { struct bGPdata *gpd; /* grease-pencil data */ struct SequencerScopes scopes; /* different scoped displayed in space */ + + char multiview_eye; /* multiview current eye - for internal use */ + char pad2[7]; } SpaceSeq; diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 93e61487000..66ee1fe4242 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -215,8 +215,10 @@ typedef struct View3D { /* drawflags, denoting state */ char zbuf, transp, xray; + char multiview_eye; /* multiview current eye - for internal use */ + /* built-in shader effects (eGPUFXFlags) */ - char pad3[5]; + char pad3[4]; /* note, 'fx_settings.dof' is currently _not_ allocated, * instead set (temporarily) from camera */ @@ -228,9 +230,21 @@ typedef struct View3D { /* XXX deprecated? */ struct bGPdata *gpd DNA_DEPRECATED; /* Grease-Pencil Data (annotation layers) */ + /* multiview - stereo 3d */ + short stereo3d_flag; + char stereo3d_camera; + char pad4; + float stereo3d_convergence_factor; + float stereo3d_volume_alpha; + float stereo3d_convergence_alpha; } View3D; +/* View3D->stereo_flag (short) */ +#define V3D_S3D_DISPCAMERAS (1 << 0) +#define V3D_S3D_DISPPLANE (1 << 1) +#define V3D_S3D_DISPVOLUME (1 << 2) + /* View3D->flag (short) */ /*#define V3D_DISPIMAGE 1*/ /*UNUSED*/ #define V3D_DISPBGPICS 2 diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index ebbafb19aa5..dca2faf0d54 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -33,6 +33,7 @@ #include "DNA_listBase.h" #include "DNA_vec_types.h" +#include "DNA_userdef_types.h" #include "DNA_ID.h" @@ -56,6 +57,7 @@ struct PointerRNA; struct ReportList; struct Report; struct uiLayout; +struct Stereo3dFormat; #define OP_MAX_TYPENAME 64 #define KMAP_MAX_NAME 64 @@ -206,7 +208,7 @@ typedef struct wmWindow { struct wmIMEData *ime_data; int drawmethod, drawfail; /* internal for wm_draw.c only */ - void *drawdata; /* internal for wm_draw.c only */ + ListBase drawdata; /* internal for wm_draw.c only */ ListBase queue; /* all events (ghost level events were handled) */ ListBase handlers; /* window+screen handlers, handled last */ @@ -214,6 +216,8 @@ typedef struct wmWindow { ListBase subwindows; /* opengl stuff for sub windows, see notes in wm_subwindow.c */ ListBase gesture; /* gesture stuff */ + + struct Stereo3dFormat *stereo3d_format; /* properties for stereoscopic displays */ } wmWindow; #ifdef ime_data diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 8aa1bc59b43..cff9e424f31 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -172,6 +172,7 @@ extern StructRNA RNA_CompositorNodeSepYCCA; extern StructRNA RNA_CompositorNodeSepYUVA; extern StructRNA RNA_CompositorNodeSetAlpha; extern StructRNA RNA_CompositorNodeSplitViewer; +extern StructRNA RNA_CompositorNodeSwitchView; extern StructRNA RNA_CompositorNodeTexture; extern StructRNA RNA_CompositorNodeTime; extern StructRNA RNA_CompositorNodeTonemap; @@ -566,6 +567,7 @@ extern StructRNA RNA_SpeedControlSequence; extern StructRNA RNA_Spline; extern StructRNA RNA_SplineIKConstraint; extern StructRNA RNA_SpotLamp; +extern StructRNA RNA_Stereo3dDisplay; extern StructRNA RNA_StretchToConstraint; extern StructRNA RNA_StringProperty; extern StructRNA RNA_Struct; diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index 4d836601ac4..d3d3578e8b0 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -72,6 +72,13 @@ extern EnumPropertyItem normal_space_items[]; extern EnumPropertyItem normal_swizzle_items[]; extern EnumPropertyItem bake_save_mode_items[]; +extern EnumPropertyItem views_format_items[]; +extern EnumPropertyItem views_format_multilayer_items[]; +extern EnumPropertyItem views_format_multiview_items[]; +extern EnumPropertyItem stereo3d_display_items[]; +extern EnumPropertyItem stereo3d_anaglyph_type_items[]; +extern EnumPropertyItem stereo3d_interlace_type_items[]; + extern EnumPropertyItem exr_codec_items[]; extern EnumPropertyItem color_sets_items[]; diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index 31e991dd2b6..b63e2f97da8 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -89,6 +89,60 @@ static void rna_Camera_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointer #else +static void rna_def_camera_stereo_data(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem convergence_mode_items[] = { + {CAM_S3D_OFFAXIS, "OFFAXIS", 0, "Off-Axis", "Off-axis frustrums converging in a plane"}, + {CAM_S3D_PARALLEL, "PARALLEL", 0, "Parallel", "Parallel cameras with no convergence"}, + {CAM_S3D_TOE, "TOE", 0, "Toe-in", "Rotated cameras, looking at the convergence distance"}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem pivot_items[] = { + {CAM_S3D_PIVOT_LEFT, "LEFT", 0, "Left", ""}, + {CAM_S3D_PIVOT_RIGHT, "RIGHT", 0, "Right", ""}, + {CAM_S3D_PIVOT_CENTER, "CENTER", 0, "Center", ""}, + {0, NULL, 0, NULL, NULL} + }; + + srna = RNA_def_struct(brna, "CameraStereoData", NULL); + RNA_def_struct_sdna(srna, "CameraStereoSettings"); + RNA_def_struct_nested(brna, srna, "Camera"); + RNA_def_struct_ui_text(srna, "Stereo", "Stereoscopy settings for a Camera datablock"); + + prop = RNA_def_property(srna, "convergence_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, convergence_mode_items); + RNA_def_property_ui_text(prop, "Mode", ""); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "pivot", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, pivot_items); + RNA_def_property_ui_text(prop, "Pivot", ""); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "interocular_distance", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_range(prop, 0.0f, 100.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.f, 1, 2); + RNA_def_property_ui_text(prop, "Interocular Distance", "Set the distance between the eyes - the stereo plane distance / 30 should be fine"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "convergence_distance", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_range(prop, 0.00001f, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0f, 15.f, 1, 2); + RNA_def_property_ui_text(prop, "Convergence Plane Distance", "The converge point for the stereo cameras (often the distance between a projector and the projection screen)"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "viewport_convergence", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_float_sdna(prop, NULL, "convergence_distance"); + RNA_def_property_range(prop, 0.00001f, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0f, 15.f, 1, 2); + RNA_def_property_ui_text(prop, "Viewport Convergence", "Preview convergence distance for the stereo effect in the viewport. It doesn't affect the render!"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); +} + void RNA_def_camera(BlenderRNA *brna) { StructRNA *srna; @@ -241,6 +295,13 @@ void RNA_def_camera(BlenderRNA *brna) RNA_def_property_ui_text(prop, "DOF Distance", "Distance to the focus point for depth of field"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + /* Stereo Settings */ + prop = RNA_def_property(srna, "stereo", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "stereo"); + RNA_def_property_struct_type(prop, "CameraStereoData"); + RNA_def_property_ui_text(prop, "Stereo", ""); + /* flag */ prop = RNA_def_property(srna, "show_limits", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_SHOWLIMITS); @@ -298,6 +359,12 @@ void RNA_def_camera(BlenderRNA *brna) rna_def_animdata_common(srna); + /* Nested Data */ + RNA_define_animate_sdna(true); + + /* *** Animated *** */ + rna_def_camera_stereo_data(brna); + /* Camera API */ RNA_api_camera(srna); } diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index e6193b31260..0c871317d04 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -620,10 +620,8 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *UNUSED(bmain) } if (seq_found) { - if (seq->anim) { - IMB_free_anim(seq->anim); - seq->anim = NULL; - } + BKE_sequence_free_anim(seq); + if (seq->strip->proxy && seq->strip->proxy->anim) { IMB_free_anim(seq->strip->proxy->anim); seq->strip->proxy->anim = NULL; @@ -635,10 +633,7 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *UNUSED(bmain) else { SEQ_BEGIN(scene->ed, seq); { - if (seq->anim) { - IMB_free_anim(seq->anim); - seq->anim = NULL; - } + BKE_sequence_free_anim(seq); } SEQ_END; diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index cf2973c49a7..bac5c4aadba 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -35,6 +35,7 @@ #include "BKE_depsgraph.h" #include "BKE_image.h" +#include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -137,6 +138,23 @@ static void rna_Image_colormanage_update(Main *UNUSED(bmain), Scene *UNUSED(scen WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id); } +static void rna_Image_views_format_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) +{ + Image *ima = ptr->id.data; + ImBuf *ibuf; + void *lock; + + ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + + if (ibuf) { + ImageUser iuser = {NULL}; + iuser.scene = scene; + BKE_image_signal(ima, &iuser, IMA_SIGNAL_FREE); + } + + BKE_image_release_ibuf(ima, ibuf, lock); +} + static void rna_ImageUser_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) { ImageUser *iuser = ptr->data; @@ -295,17 +313,16 @@ static int rna_Image_frame_duration_get(PointerRNA *ptr) Image *ima = ptr->id.data; int duration = 1; - if (!ima->anim) { + if (BKE_image_has_anim(ima)) { + duration = IMB_anim_get_duration(((ImageAnim *)ima->anims.first)->anim, IMB_TC_RECORD_RUN); + } + else { /* acquire ensures ima->anim is set, if possible! */ void *lock; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); BKE_image_release_ibuf(ima, ibuf, lock); } - if (ima->anim) { - duration = IMB_anim_get_duration(ima->anim, IMB_TC_RECORD_RUN); - } - return duration; } @@ -409,6 +426,19 @@ static int rna_Image_is_float_get(PointerRNA *ptr) return is_float; } +static PointerRNA rna_Image_packed_file_get(PointerRNA *ptr) +{ + Image *ima = (Image *)ptr->id.data; + + if (BKE_image_has_packedfile(ima)) { + ImagePackedFile *imapf = ima->packedfiles.first; + return rna_pointer_inherit_refine(ptr, &RNA_PackedFile, imapf->packedfile); + } + else { + return PointerRNA_NULL; + } +} + static void rna_Image_render_slots_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { Image *image = (Image *)ptr->id.data; @@ -512,6 +542,32 @@ static void rna_def_imageuser(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "pass"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* image_multi_cb */ RNA_def_property_ui_text(prop, "Pass", "Pass in multilayer image"); + + prop = RNA_def_property(srna, "multilayer_view", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "view"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* image_multi_cb */ + RNA_def_property_ui_text(prop, "View", "View in multilayer image"); +} + +/* image.packed_files */ +static void rna_def_image_packed_files(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "ImagePackedFile", NULL); + RNA_def_struct_sdna(srna, "ImagePackedFile"); + + prop = RNA_def_property(srna, "packed_file", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "packedfile"); + RNA_def_property_ui_text(prop, "Packed File", ""); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH); + RNA_def_property_string_sdna(prop, NULL, "filepath"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_struct_name_property(srna, prop); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); } static void rna_def_render_slot(BlenderRNA *brna) @@ -613,15 +669,23 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL); prop = RNA_def_property(srna, "packed_file", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "PackedFile"); RNA_def_property_pointer_sdna(prop, NULL, "packedfile"); - RNA_def_property_ui_text(prop, "Packed File", ""); - + RNA_def_property_pointer_funcs(prop, "rna_Image_packed_file_get", NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Packed File", "First packed file of the image"); + + prop = RNA_def_property(srna, "packed_files", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "packedfiles", NULL); + RNA_def_property_struct_type(prop, "ImagePackedFile"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Packed Files", "Collection of packed images"); + prop = RNA_def_property(srna, "field_order", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, prop_field_order_items); RNA_def_property_ui_text(prop, "Field Order", "Order of video fields (select which lines are displayed first)"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL); - + /* booleans */ prop = RNA_def_property(srna, "use_fields", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_FIELDS); @@ -645,6 +709,21 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Deinterlace", "Deinterlace movie file on load"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_reload_update"); + prop = RNA_def_property(srna, "use_multiview", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_USE_VIEWS); + RNA_def_property_ui_text(prop, "Use Multi-View", "Use Multiple Views (when available)"); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_views_format_update"); + + prop = RNA_def_property(srna, "is_stereo_3d", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_IS_STEREO); + RNA_def_property_ui_text(prop, "Stereo 3D", "Image has left and right views"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "is_multiview", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_IS_MULTIVIEW); + RNA_def_property_ui_text(prop, "Multiple Views", "Image has more than one view"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop = RNA_def_property(srna, "is_dirty", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_Image_dirty_get", NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -825,6 +904,19 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Alpha Mode", "Representation of alpha information in the RGBA pixels"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_colormanage_update"); + /* multiview */ + prop = RNA_def_property(srna, "views_format", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "views_format"); + RNA_def_property_enum_items(prop, views_format_items); + RNA_def_property_ui_text(prop, "Views Format", "Mode to load image views"); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_views_format_update"); + + prop = RNA_def_property(srna, "stereo_3d_format", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "stereo3d_format"); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "Stereo3dFormat"); + RNA_def_property_ui_text(prop, "Stereo 3D Format", "Settings for stereo 3d"); + RNA_api_image(srna); } @@ -834,6 +926,7 @@ void RNA_def_image(BlenderRNA *brna) rna_def_render_slots(brna); rna_def_image(brna); rna_def_imageuser(brna); + rna_def_image_packed_files(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index 7fb5885f709..47be7bec432 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -167,7 +167,7 @@ static void rna_Image_pack( image->packedfile = newPackedFileMemory(data_dup, data_len); } else { - image->packedfile = newPackedFile(reports, image->name, ID_BLEND_PATH(bmain, &image->id)); + BKE_image_packfiles(reports, image, ID_BLEND_PATH(bmain, &image->id)); } } diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 1d232720fc5..59c3befad9e 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -341,10 +341,10 @@ static void rna_Main_lamps_remove(Main *bmain, ReportList *reports, PointerRNA * } } -static Image *rna_Main_images_new(Main *bmain, const char *name, int width, int height, int alpha, int float_buffer) +static Image *rna_Main_images_new(Main *bmain, const char *name, int width, int height, int alpha, int float_buffer, int stereo3d) { float color[4] = {0.0, 0.0, 0.0, 1.0}; - Image *image = BKE_image_add_generated(bmain, width, height, name, alpha ? 32 : 24, float_buffer, 0, color); + Image *image = BKE_image_add_generated(bmain, width, height, name, alpha ? 32 : 24, float_buffer, 0, color, stereo3d); id_us_min(&image->id); return image; } @@ -1174,6 +1174,7 @@ void RNA_def_main_images(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_flag(parm, PROP_REQUIRED); RNA_def_boolean(func, "alpha", 0, "Alpha", "Use alpha channel"); RNA_def_boolean(func, "float_buffer", 0, "Float Buffer", "Create an image with floating point color"); + RNA_def_boolean(func, "stereo3d", 0, "Stereo 3D", "Create left and right views"); /* return type */ parm = RNA_def_pointer(func, "image", "Image", "", "New image datablock"); RNA_def_function_return(func, parm); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index e577f7635f1..075b139c6c4 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -2616,6 +2616,70 @@ static EnumPropertyItem *rna_Node_image_layer_itemf(bContext *UNUSED(C), Pointer return item; } +static int rna_Node_image_has_layers_get(PointerRNA *ptr) +{ + bNode *node = (bNode *)ptr->data; + Image *ima = (Image *)node->id; + + if (!ima || !(ima->rr)) return 0; + + return RE_layers_have_name(ima->rr); +} + +static int rna_Node_image_has_views_get(PointerRNA *ptr) +{ + bNode *node = (bNode *)ptr->data; + Image *ima = (Image *)node->id; + + if (!ima || !(ima->rr)) return 0; + + return BLI_listbase_count_ex(&ima->rr->views, 2) > 1; +} + +static EnumPropertyItem *renderresult_views_add_enum(RenderView *rv) +{ + EnumPropertyItem *item = NULL; + EnumPropertyItem tmp = {0, "ALL", 0, "All", ""}; + int i = 1, totitem = 0; + + /* option to use all views */ + RNA_enum_item_add(&item, &totitem, &tmp); + + while (rv) { + tmp.identifier = rv->name; + /* little trick: using space char instead empty string makes the item selectable in the dropdown */ + if (rv->name[0] == '\0') + tmp.name = " "; + else + tmp.name = rv->name; + tmp.value = i++; + RNA_enum_item_add(&item, &totitem, &tmp); + rv = rv->next; + } + + RNA_enum_item_end(&item, &totitem); + + return item; +} + +static EnumPropertyItem *rna_Node_image_view_itemf(bContext *UNUSED(C), PointerRNA *ptr, + PropertyRNA *UNUSED(prop), bool *free) +{ + bNode *node = (bNode *)ptr->data; + Image *ima = (Image *)node->id; + EnumPropertyItem *item = NULL; + RenderView *rv; + + if (!ima || !(ima->rr)) return NULL; + + rv = ima->rr->views.first; + item = renderresult_views_add_enum(rv); + + *free = true; + + return item; +} + static EnumPropertyItem *rna_Node_scene_layer_itemf(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { @@ -2907,6 +2971,11 @@ static EnumPropertyItem prop_image_layer_items[] = { {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem prop_image_view_items[] = { + { 0, "ALL", 0, "All", ""}, + {0, NULL, 0, NULL, NULL} +}; + static EnumPropertyItem prop_scene_layer_items[] = { { 0, "PLACEHOLDER", 0, "Placeholder", ""}, {0, NULL, 0, NULL, NULL} @@ -4263,6 +4332,24 @@ static void def_node_image_user(StructRNA *srna) RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE); RNA_def_property_ui_text(prop, "Layer", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_image_layer_update"); + + prop = RNA_def_property(srna, "has_layers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_Node_image_has_layers_get", NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Has Layers", "True if this image has any named layer"); + + prop = RNA_def_property(srna, "view", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "view"); + RNA_def_property_enum_items(prop, prop_image_view_items); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Node_image_view_itemf"); + RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE); + RNA_def_property_ui_text(prop, "View", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "has_views", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_Node_image_has_views_get", NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Has View", "True if this image has multiple views"); } static void def_cmp_image(StructRNA *srna) @@ -5811,6 +5898,16 @@ static void def_cmp_switch(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_cmp_switch_view(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "check", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "custom1", 0); + RNA_def_property_ui_text(prop, "Switch", "Off: first socket, On: second socket"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + static void def_cmp_colorcorrection(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 124a83a5f30..94fabb857e3 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -27,6 +27,7 @@ #include #include "DNA_scene_types.h" +#include "DNA_object_types.h" #include "BLI_utildefines.h" #include "BLI_path_util.h" @@ -322,38 +323,35 @@ static PointerRNA rna_RenderEngine_render_get(PointerRNA *ptr) } } -static void rna_RenderResult_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +static PointerRNA rna_RenderEngine_camera_override_get(PointerRNA *ptr) { - RenderResult *rr = (RenderResult *)ptr->data; - rna_iterator_listbase_begin(iter, &rr->layers, NULL); -} + RenderEngine *engine = (RenderEngine *)ptr->data; -static void rna_RenderLayer_passes_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) -{ - RenderLayer *rl = (RenderLayer *)ptr->data; - rna_iterator_listbase_begin(iter, &rl->passes, NULL); + if (engine->re) { + Object *cam = RE_GetCamera(engine->re); + return rna_pointer_inherit_refine(ptr, &RNA_Object, cam); + } + else { + return rna_pointer_inherit_refine(ptr, &RNA_Object, engine->camera_override); + } } -static int rna_RenderLayer_rect_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) +static void rna_RenderResult_views_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - RenderLayer *rl = (RenderLayer *)ptr->data; - - length[0] = rl->rectx * rl->recty; - length[1] = 4; - - return length[0] * length[1]; + RenderResult *rr = (RenderResult *)ptr->data; + rna_iterator_listbase_begin(iter, &rr->views, NULL); } -static void rna_RenderLayer_rect_get(PointerRNA *ptr, float *values) +static void rna_RenderResult_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - RenderLayer *rl = (RenderLayer *)ptr->data; - memcpy(values, rl->rectf, sizeof(float) * rl->rectx * rl->recty * 4); + RenderResult *rr = (RenderResult *)ptr->data; + rna_iterator_listbase_begin(iter, &rr->layers, NULL); } -void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values) +static void rna_RenderLayer_passes_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { RenderLayer *rl = (RenderLayer *)ptr->data; - memcpy(rl->rectf, values, sizeof(float) * rl->rectx * rl->recty * 4); + rna_iterator_listbase_begin(iter, &rl->passes, NULL); } static int rna_RenderPass_rect_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) @@ -384,6 +382,18 @@ static PointerRNA rna_BakePixel_next_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_BakePixel, bp + 1); } +static RenderPass *rna_RenderPass_find_by_type(RenderLayer *rl, int passtype, const char *view) +{ + RenderPass *rp; + for (rp = rl->passes.first; rp; rp = rp->next) { + if (rp->passtype == passtype) { + if (STREQ(rp->view, view)) + return rp; + } + } + return NULL; +} + #else /* RNA_RUNTIME */ static void rna_def_render_engine(BlenderRNA *brna) @@ -467,6 +477,7 @@ static void rna_def_render_engine(BlenderRNA *brna) prop = RNA_def_int(func, "h", 0, 0, INT_MAX, "Height", "", 0, INT_MAX); RNA_def_property_flag(prop, PROP_REQUIRED); RNA_def_string(func, "layer", NULL, 0, "Layer", "Single layer to get render result for"); /* NULL ok here */ + RNA_def_string(func, "view", NULL, 0, "View", "Single view to get render result for"); /* NULL ok here */ prop = RNA_def_pointer(func, "result", "RenderResult", "Result", ""); RNA_def_function_return(func, prop); @@ -487,6 +498,22 @@ static void rna_def_render_engine(BlenderRNA *brna) prop = RNA_def_boolean(func, "do_break", 0, "Break", ""); RNA_def_function_return(func, prop); + func = RNA_def_function(srna, "active_view_set", "RE_engine_active_view_set"); + RNA_def_string(func, "view", NULL, 0, "View", "Single view to set as active"); /* NULL ok here */ + RNA_def_property_flag(prop, PROP_REQUIRED); + + func = RNA_def_function(srna, "camera_shift_x", "RE_engine_get_camera_shift_x"); + prop = RNA_def_pointer(func, "camera", "Object", "", ""); + RNA_def_property_flag(prop, PROP_REQUIRED); + prop = RNA_def_float(func, "shift_x", 0.0f, 0.0f, FLT_MAX, "Shift X", "", 0.0f, FLT_MAX); + RNA_def_function_return(func, prop); + + func = RNA_def_function(srna, "camera_model_matrix", "RE_engine_get_camera_model_matrix"); + prop = RNA_def_pointer(func, "camera", "Object", "", ""); + RNA_def_property_flag(prop, PROP_REQUIRED); + prop = RNA_def_float_matrix(func, "r_model_matrix", 4, 4, NULL, 0.0f, 0.0f, "Model Matrix", "Normalized camera model matrix", 0.0f, 0.0f); + RNA_def_property_flag(prop, PROP_REQUIRED); + func = RNA_def_function(srna, "update_stats", "RE_engine_update_stats"); RNA_def_function_ui_description(func, "Update and signal to redraw render status text"); prop = RNA_def_string(func, "stats", NULL, 0, "Stats", ""); @@ -548,7 +575,7 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", RE_ENGINE_PREVIEW); prop = RNA_def_property(srna, "camera_override", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "camera_override"); + RNA_def_property_pointer_funcs(prop, "rna_RenderEngine_camera_override_get", NULL, NULL, NULL); RNA_def_property_struct_type(prop, "Object"); prop = RNA_def_property(srna, "layer_override", PROP_BOOLEAN, PROP_LAYER_MEMBER); @@ -647,9 +674,56 @@ static void rna_def_render_result(BlenderRNA *brna) "rna_iterator_listbase_end", "rna_iterator_listbase_get", NULL, NULL, NULL, NULL); + parm = RNA_def_property(srna, "views", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(parm, "RenderView"); + RNA_def_property_collection_funcs(parm, "rna_RenderResult_views_begin", "rna_iterator_listbase_next", + "rna_iterator_listbase_end", "rna_iterator_listbase_get", + NULL, NULL, NULL, NULL); + + RNA_define_verify_sdna(1); +} + +static void rna_def_render_view(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "RenderView", NULL); + RNA_def_struct_ui_text(srna, "Render View", ""); + + RNA_define_verify_sdna(0); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "name"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_struct_name_property(srna, prop); + RNA_define_verify_sdna(1); } +static void rna_def_render_passes(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "RenderPasses"); + srna = RNA_def_struct(brna, "RenderPasses", NULL); + RNA_def_struct_sdna(srna, "RenderLayer"); + RNA_def_struct_ui_text(srna, "Render Passes", "Collection of render passes"); + + func = RNA_def_function(srna, "find_by_type", "rna_RenderPass_find_by_type"); + RNA_def_function_ui_description(func, "Get the render pass for a given type and view"); + parm = RNA_def_enum(func, "pass_type", render_pass_type_items, SCE_PASS_COMBINED, "Pass", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm = RNA_def_string(func, "view", NULL, 0, "View", "Render view to get pass from"); /* NULL ok here */ + RNA_def_property_flag(parm, PROP_REQUIRED); + parm = RNA_def_pointer(func, "render_pass", "RenderPass", "", "The matching render pass"); + RNA_def_function_return(func, parm); + +} + static void rna_def_render_layer(BlenderRNA *brna) { StructRNA *srna; @@ -679,12 +753,7 @@ static void rna_def_render_layer(BlenderRNA *brna) RNA_def_property_collection_funcs(prop, "rna_RenderLayer_passes_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", NULL, NULL, NULL, NULL); - - prop = RNA_def_property(srna, "rect", PROP_FLOAT, PROP_NONE); - RNA_def_property_flag(prop, PROP_DYNAMIC); - RNA_def_property_multi_array(prop, 2, NULL); - RNA_def_property_dynamic_array_funcs(prop, "rna_RenderLayer_rect_get_length"); - RNA_def_property_float_funcs(prop, "rna_RenderLayer_rect_get", "rna_RenderLayer_rect_set", NULL); + rna_def_render_passes(brna, prop); RNA_define_verify_sdna(1); } @@ -728,6 +797,10 @@ static void rna_def_render_pass(BlenderRNA *brna) RNA_def_property_dynamic_array_funcs(prop, "rna_RenderPass_rect_get_length"); RNA_def_property_float_funcs(prop, "rna_RenderPass_rect_get", "rna_RenderPass_rect_set", NULL); + prop = RNA_def_property(srna, "view_id", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "view_id"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop = RNA_def_property(srna, "debug_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "debug_type"); RNA_def_property_enum_items(prop, render_pass_debug_type_items); @@ -783,6 +856,7 @@ void RNA_def_render(BlenderRNA *brna) { rna_def_render_engine(brna); rna_def_render_result(brna); + rna_def_render_view(brna); rna_def_render_layer(brna); rna_def_render_pass(brna); rna_def_render_bake_pixel(brna); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index c9d1a4b6429..a59724f4a16 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -36,6 +36,8 @@ #include "DNA_userdef_types.h" #include "DNA_world_types.h" +#include "IMB_imbuf_types.h" + #include "BLI_math.h" #include "BLF_translation.h" @@ -217,13 +219,13 @@ EnumPropertyItem snap_uv_element_items[] = { #endif #ifdef WITH_OPENEXR -# define R_IMF_ENUM_EXR_MULTI {R_IMF_IMTYPE_MULTILAYER, "OPEN_EXR_MULTILAYER", ICON_FILE_IMAGE, \ +# define R_IMF_ENUM_EXR_MULTILAYER {R_IMF_IMTYPE_MULTILAYER, "OPEN_EXR_MULTILAYER", ICON_FILE_IMAGE, \ "OpenEXR MultiLayer", \ "Output image in multilayer OpenEXR format"}, # define R_IMF_ENUM_EXR {R_IMF_IMTYPE_OPENEXR, "OPEN_EXR", ICON_FILE_IMAGE, "OpenEXR", \ "Output image in OpenEXR format"}, #else -# define R_IMF_ENUM_EXR_MULTI +# define R_IMF_ENUM_EXR_MULTILAYER # define R_IMF_ENUM_EXR #endif @@ -252,7 +254,7 @@ EnumPropertyItem snap_uv_element_items[] = { {0, "", 0, " ", NULL}, \ R_IMF_ENUM_CINEON \ R_IMF_ENUM_DPX \ - R_IMF_ENUM_EXR_MULTI \ + R_IMF_ENUM_EXR_MULTILAYER \ R_IMF_ENUM_EXR \ R_IMF_ENUM_HDR \ R_IMF_ENUM_TIFF \ @@ -336,6 +338,58 @@ EnumPropertyItem bake_save_mode_items[] = { {0, NULL, 0, NULL, NULL} }; +#define R_IMF_VIEWS_ENUM_IND {R_IMF_VIEWS_INDIVIDUAL, "INDIVIDUAL", 0, "Individual", "Individual files for each view with the prefix as defined by the scene views"}, +#define R_IMF_VIEWS_ENUM_S3D {R_IMF_VIEWS_STEREO_3D, "STEREO_3D", 0, "Stereo 3D", "Single file with an encoded stereo pair"}, +#define R_IMF_VIEWS_ENUM_MV {R_IMF_VIEWS_MULTIVIEW, "MULTIVIEW", 0, "Multi-View", "Single file with all the views"}, + +EnumPropertyItem views_format_items[] = { + R_IMF_VIEWS_ENUM_IND + R_IMF_VIEWS_ENUM_S3D + {0, NULL, 0, NULL, NULL} +}; + +EnumPropertyItem views_format_multilayer_items[] = { + R_IMF_VIEWS_ENUM_IND + R_IMF_VIEWS_ENUM_MV + {0, NULL, 0, NULL, NULL} +}; + +EnumPropertyItem views_format_multiview_items[] = { + R_IMF_VIEWS_ENUM_IND + R_IMF_VIEWS_ENUM_S3D + R_IMF_VIEWS_ENUM_MV + {0, NULL, 0, NULL, NULL} +}; + +#undef R_IMF_VIEWS_ENUM_IND +#undef R_IMF_VIEWS_ENUM_S3D +#undef R_IMF_VIEWS_ENUM_MV + +EnumPropertyItem stereo3d_display_items[] = { + {S3D_DISPLAY_ANAGLYPH, "ANAGLYPH", 0, "Anaglyph", "Render two differently filtered colored images for each eye. Anaglyph glasses are required"}, + {S3D_DISPLAY_INTERLACE, "INTERLACE", 0, "Interlace", "Render two images for each eye into one interlaced image. 3D-ready monitor is requiered"}, +#ifdef DEBUG /* MULTIVIEW_TODO: quadbuffer mode not fully working */ + {S3D_DISPLAY_PAGEFLIP, "TIMESEQUENTIAL", 0, "Time Sequential", "Renders alternate eyes (also known as pageflip). It requires Quadbuffer support in the graphic card"}, +#endif + {S3D_DISPLAY_SIDEBYSIDE, "SIDEBYSIDE", 0, "Side-by-Side", "Render images for left and right eye side-by-side"}, + {S3D_DISPLAY_TOPBOTTOM, "TOPBOTTOM", 0, "Top-Bottom", "Render images for left and right eye one above another"}, + {0, NULL, 0, NULL, NULL} +}; + +EnumPropertyItem stereo3d_anaglyph_type_items[] = { + {S3D_ANAGLYPH_REDCYAN, "RED_CYAN", 0, "Red-Cyan", ""}, + {S3D_ANAGLYPH_GREENMAGENTA, "GREEN_MAGENTA", 0, "Green-Magenta", ""}, + {S3D_ANAGLYPH_YELLOWBLUE, "YELLOW_BLUE", 0, "Yellow-Blue", ""}, + {0, NULL, 0, NULL, NULL} +}; + +EnumPropertyItem stereo3d_interlace_type_items[] = { + {S3D_INTERLACE_ROW, "ROW_INTERLEAVED", 0, "Row Interleaved", ""}, + {S3D_INTERLACE_COLUMN, "COLUMN_INTERLEAVED", 0, "Column Interleaved", ""}, + {S3D_INTERLACE_CHECKERBOARD, "CHECKERBOARD_INTERLEAVED", 0, "Checkerboard Interleaved", ""}, + {0, NULL, 0, NULL, NULL} +}; + #ifdef RNA_RUNTIME #include "DNA_anim_types.h" @@ -723,6 +777,26 @@ static void rna_Scene_all_keyingsets_next(CollectionPropertyIterator *iter) iter->valid = (internal->link != NULL); } +static int rna_RenderSettings_stereoViews_skip(CollectionPropertyIterator *iter, void *UNUSED(data)) +{ + ListBaseIterator *internal = &iter->internal.listbase; + SceneRenderView *srv = (SceneRenderView *)internal->link; + + if ((STREQ(srv->name, STEREO_LEFT_NAME)) || + (STREQ(srv->name, STEREO_RIGHT_NAME))) + { + return 0; + } + + return 1; +}; + +static void rna_RenderSettings_stereoViews_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + RenderData *rd = (RenderData *)ptr->data; + rna_iterator_listbase_begin(iter, &rd->views, rna_RenderSettings_stereoViews_skip); +} + static char *rna_RenderSettings_path(PointerRNA *UNUSED(ptr)) { return BLI_sprintfN("render"); @@ -945,6 +1019,25 @@ static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf(bContext *UNU } } +static EnumPropertyItem *rna_ImageFormatSettings_views_format_itemf(bContext *UNUSED(C), PointerRNA *ptr, +PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) +{ + ImageFormatData *imf = (ImageFormatData *)ptr->data; + + if (imf == NULL) { + return views_format_items; + } + else if (imf->imtype == R_IMF_IMTYPE_OPENEXR) { + return views_format_multiview_items; + } + else if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) { + return views_format_multilayer_items; + } + else { + return views_format_items; + } +} + #ifdef WITH_OPENEXR /* OpenEXR */ @@ -1158,6 +1251,69 @@ static void rna_RenderLayer_remove(ID *id, RenderData *UNUSED(rd), Main *bmain, WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL); } +static int rna_RenderSettings_active_view_index_get(PointerRNA *ptr) +{ + RenderData *rd = (RenderData *)ptr->data; + return rd->actview; +} + +static void rna_RenderSettings_active_view_index_set(PointerRNA *ptr, int value) +{ + RenderData *rd = (RenderData *)ptr->data; + rd->actview = value; +} + +static void rna_RenderSettings_active_view_index_range(PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) +{ + RenderData *rd = (RenderData *)ptr->data; + + *min = 0; + *max = max_ii(0, BLI_listbase_count(&rd->views) - 1); +} + +static PointerRNA rna_RenderSettings_active_view_get(PointerRNA *ptr) +{ + RenderData *rd = (RenderData *)ptr->data; + SceneRenderView *srv = BLI_findlink(&rd->views, rd->actview); + + return rna_pointer_inherit_refine(ptr, &RNA_SceneRenderView, srv); +} + +static void rna_RenderSettings_active_view_set(PointerRNA *ptr, PointerRNA value) +{ + RenderData *rd = (RenderData *)ptr->data; + SceneRenderView *srv = (SceneRenderView *)value.data; + const int index = BLI_findindex(&rd->views, srv); + if (index != -1) rd->actview = index; +} + +static SceneRenderView *rna_RenderView_new(ID *id, RenderData *UNUSED(rd), const char *name) +{ + Scene *scene = (Scene *)id; + SceneRenderView *srv = BKE_scene_add_render_view(scene, name); + + WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL); + + return srv; +} + +static void rna_RenderView_remove(ID *id, RenderData *UNUSED(rd), Main *UNUSED(bmain), ReportList *reports, + PointerRNA *srv_ptr) +{ + SceneRenderView *srv = srv_ptr->data; + Scene *scene = (Scene *)id; + + if (!BKE_scene_remove_render_view(scene, srv)) { + BKE_reportf(reports, RPT_ERROR, "Render view '%s' could not be removed from scene '%s'", + srv->name, scene->id.name + 2); + return; + } + + RNA_POINTER_INVALIDATE(srv_ptr); + + WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL); +} + static void rna_RenderSettings_engine_set(PointerRNA *ptr, int value) { RenderData *rd = (RenderData *)ptr->data; @@ -1263,6 +1419,34 @@ static char *rna_SceneRenderLayer_path(PointerRNA *ptr) return BLI_sprintfN("render.layers[\"%s\"]", name_esc); } +static void rna_SceneRenderView_name_set(PointerRNA *ptr, const char *value) +{ + Scene *scene = (Scene *)ptr->id.data; + SceneRenderView *rv = (SceneRenderView *)ptr->data; + BLI_strncpy_utf8(rv->name, value, sizeof(rv->name)); + BLI_uniquename(&scene->r.views, rv, DATA_("RenderView"), '.', offsetof(SceneRenderView, name), sizeof(rv->name)); +} + +static char *rna_SceneRenderView_path(PointerRNA *ptr) +{ + SceneRenderView *srv = (SceneRenderView *)ptr->data; + return BLI_sprintfN("render.views[\"%s\"]", srv->name); +} + +static void rna_RenderSettings_views_format_set(PointerRNA *ptr, int value) +{ + RenderData *rd = (RenderData *)ptr->data; + + if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW && + value == SCE_VIEWS_FORMAT_STEREO_3D) + { + /* make sure the actview is visible */ + if (rd->actview > 1) rd->actview = 1; + } + + rd->views_format = value; +} + static int rna_RenderSettings_multiple_engines_get(PointerRNA *UNUSED(ptr)) { return (BLI_listbase_count(&R_engines) > 1); @@ -1759,6 +1943,26 @@ static void rna_GPUDOFSettings_blades_set(PointerRNA *ptr, const int value) dofsettings->num_blades = value; } +static void rna_Stereo3dFormat_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + ID *id = ptr->id.data; + + if (id && GS(id->name) == ID_IM) { + Image *ima = (Image *)id; + ImBuf *ibuf; + void *lock; + + if ((ima->flag & IMA_IS_STEREO) == 0) + return; + + ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + + if (ibuf) { + BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); + } + BKE_image_release_ibuf(ima, ibuf, lock); + } +} static int rna_gpu_is_hq_supported_get(PointerRNA *UNUSED(ptr)) { @@ -4103,6 +4307,134 @@ static void rna_def_render_layers(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } +/* Render Views - MultiView */ +static void rna_def_scene_render_view(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "SceneRenderView", NULL); + RNA_def_struct_ui_text(srna, "Scene Render View", "Render viewpoint for 3D stereo and multiview rendering"); + RNA_def_struct_ui_icon(srna, ICON_RESTRICT_RENDER_OFF); + RNA_def_struct_path_func(srna, "rna_SceneRenderView_path"); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SceneRenderView_name_set"); + RNA_def_property_ui_text(prop, "Name", "Render view name"); + RNA_def_struct_name_property(srna, prop); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + prop = RNA_def_property(srna, "file_suffix", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "suffix"); + RNA_def_property_ui_text(prop, "File Suffix", "Suffix added to the render images for this view"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + prop = RNA_def_property(srna, "camera_suffix", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "suffix"); + RNA_def_property_ui_text(prop, "Camera Suffix", "Suffix to identify the cameras to use, and added to the render images for this view"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "viewflag", SCE_VIEW_DISABLE); + RNA_def_property_ui_text(prop, "Enabled", "Disable or enable the render view"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); +} + +static void rna_def_render_views(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + PropertyRNA *prop; + + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "RenderViews"); + srna = RNA_def_struct(brna, "RenderViews", NULL); + RNA_def_struct_sdna(srna, "RenderData"); + RNA_def_struct_ui_text(srna, "Render Views", "Collection of render views"); + + prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "actview"); + RNA_def_property_int_funcs(prop, "rna_RenderSettings_active_view_index_get", + "rna_RenderSettings_active_view_index_set", + "rna_RenderSettings_active_view_index_range"); + RNA_def_property_ui_text(prop, "Active View Index", "Active index in render view array"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "SceneRenderView"); + RNA_def_property_pointer_funcs(prop, "rna_RenderSettings_active_view_get", + "rna_RenderSettings_active_view_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL); + RNA_def_property_ui_text(prop, "Active Render View", "Active Render View"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + func = RNA_def_function(srna, "new", "rna_RenderView_new"); + RNA_def_function_ui_description(func, "Add a render view to scene"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + parm = RNA_def_string(func, "name", "RenderView", 0, "", "New name for the marker (not unique)"); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm = RNA_def_pointer(func, "result", "SceneRenderView", "", "Newly created render view"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_RenderView_remove"); + RNA_def_function_ui_description(func, "Remove a render view"); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS | FUNC_USE_SELF_ID); + parm = RNA_def_pointer(func, "view", "SceneRenderView", "", "Render view to remove"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); +} + +static void rna_def_image_format_stereo3d_format(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem stereo3d_display_items[] = { + {S3D_DISPLAY_ANAGLYPH, "ANAGLYPH", 0, "Anaglyph", "Render two differently filtered colored images for each eye. Anaglyph glasses are required"}, + {S3D_DISPLAY_INTERLACE, "INTERLACE", 0, "Interlace", "Render two images for each eye into one interlaced image. 3D-ready monitor is requiered"}, + {S3D_DISPLAY_SIDEBYSIDE, "SIDEBYSIDE", 0, "Side-by-Side", "Render images for left and right eye side-by-side"}, + {S3D_DISPLAY_TOPBOTTOM, "TOPBOTTOM", 0, "Top-Bottom", "Render images for left and right eye one above another"}, + {0, NULL, 0, NULL, NULL} + }; + + srna = RNA_def_struct(brna, "Stereo3dFormat", NULL); + RNA_def_struct_sdna(srna, "Stereo3dFormat"); + RNA_def_struct_clear_flag(srna, STRUCT_UNDO); + RNA_def_struct_ui_text(srna, "Stereo Output", "Settings for stereo output"); + + prop = RNA_def_property(srna, "display_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "display_mode"); + RNA_def_property_enum_items(prop, stereo3d_display_items); + RNA_def_property_ui_text(prop, "Stereo Mode", ""); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Stereo3dFormat_update"); + + prop = RNA_def_property(srna, "anaglyph_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, stereo3d_anaglyph_type_items); + RNA_def_property_ui_text(prop, "Anaglyph Type", ""); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Stereo3dFormat_update"); + + prop = RNA_def_property(srna, "interlace_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, stereo3d_interlace_type_items); + RNA_def_property_ui_text(prop, "Interlace Type", ""); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Stereo3dFormat_update"); + + prop = RNA_def_property(srna, "use_interlace_swap", PROP_BOOLEAN, PROP_BOOLEAN); + RNA_def_property_boolean_sdna(prop, NULL, "flag", S3D_INTERLACE_SWAP); + RNA_def_property_ui_text(prop, "Swap Left/Right", "Swap left and right stereo channels"); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Stereo3dFormat_update"); + + prop = RNA_def_property(srna, "use_sidebyside_crosseyed", PROP_BOOLEAN, PROP_BOOLEAN); + RNA_def_property_boolean_sdna(prop, NULL, "flag", S3D_SIDEBYSIDE_CROSSEYED); + RNA_def_property_ui_text(prop, "Cross-Eyed", "Right eye should see left image and vice-versa"); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Stereo3dFormat_update"); + + prop = RNA_def_property(srna, "use_squeezed_frame", PROP_BOOLEAN, PROP_BOOLEAN); + RNA_def_property_boolean_sdna(prop, NULL, "flag", S3D_SQUEEZED_FRAME); + RNA_def_property_ui_text(prop, "Squeezed Frame", "Combine both views in a squeezed image"); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Stereo3dFormat_update"); +} + /* use for render output and image save operator, * note: there are some cases where the members act differently when this is * used from a scene, video formats can only be selected for render output @@ -4122,6 +4454,8 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + rna_def_image_format_stereo3d_format(brna); + srna = RNA_def_struct(brna, "ImageFormatSettings", NULL); RNA_def_struct_sdna(srna, "ImageFormatData"); RNA_def_struct_nested(brna, srna, "Scene"); @@ -4190,7 +4524,6 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna) RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_ImageFormatSettings_exr_codec_itemf"); RNA_def_property_ui_text(prop, "Codec", "Codec settings for OpenEXR"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - #endif #ifdef WITH_OPENJPEG @@ -4242,6 +4575,20 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "G", "Log conversion gamma"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + /* multiview */ + prop = RNA_def_property(srna, "views_format", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "views_format"); + RNA_def_property_enum_items(prop, views_format_items); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_ImageFormatSettings_views_format_itemf"); + RNA_def_property_ui_text(prop, "Views Format", "Format of multiview media"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + prop = RNA_def_property(srna, "stereo_3d_format", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "stereo3d_format"); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "Stereo3dFormat"); + RNA_def_property_ui_text(prop, "Stereo 3D Format", "Settings for stereo 3d"); + /* color management */ prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "view_settings"); @@ -4644,6 +4991,16 @@ static void rna_def_scene_render_data(BlenderRNA *brna) "resolution to 480 pixels"}, {0, NULL, 0, NULL, NULL}}; + static EnumPropertyItem views_format_items[] = { + {SCE_VIEWS_FORMAT_STEREO_3D, "STEREO_3D", 0, "Stereo 3D", + "Single stereo camera system, adjust the stereo settings in the camera panel"}, + {SCE_VIEWS_FORMAT_MULTIVIEW, "MULTIVIEW", 0, "Multi-View", + "Multi camera system, adjust the cameras individually"}, + {0, NULL, 0, NULL, NULL} + }; + + + rna_def_scene_ffmpeg_settings(brna); #ifdef WITH_QUICKTIME rna_def_scene_quicktime_settings(brna); @@ -5326,6 +5683,32 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_UNPINNED, 1); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + /* views (stereoscopy et al) */ + prop = RNA_def_property(srna, "views", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "SceneRenderView"); + RNA_def_property_ui_text(prop, "Render Views", ""); + rna_def_render_views(brna, prop); + + prop = RNA_def_property(srna, "stereo_views", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "views", NULL); + RNA_def_property_collection_funcs(prop, "rna_RenderSettings_stereoViews_begin", "rna_iterator_listbase_next", + "rna_iterator_listbase_end", "rna_iterator_listbase_get", + NULL, NULL, NULL, NULL); + RNA_def_property_struct_type(prop, "SceneRenderView"); + RNA_def_property_ui_text(prop, "Render Views", ""); + + prop = RNA_def_property(srna, "use_multiview", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_MULTIVIEW); + RNA_def_property_ui_text(prop, "Multiple Views", "Use multiple views in the scene"); + RNA_def_property_update(prop, NC_WINDOW, NULL); + + prop = RNA_def_property(srna, "views_format", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, views_format_items); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Setup Stereo Mode", ""); + RNA_def_property_enum_funcs(prop, NULL, "rna_RenderSettings_views_format_set", NULL); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + /* engine */ prop = RNA_def_property(srna, "engine", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, engine_items); @@ -6076,8 +6459,8 @@ void RNA_def_scene(BlenderRNA *brna) /* *** Animated *** */ rna_def_scene_render_data(brna); rna_def_scene_render_layer(brna); - rna_def_gpu_fx(brna); + rna_def_scene_render_view(brna); /* Scene API */ RNA_api_scene(srna); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 0d8d58eae43..0d70b6f3ba8 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -119,15 +119,15 @@ static void rna_Scene_update_tagged(Scene *scene) #endif } -static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, int preview, char *name) +static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, int preview, const char *view, char *name) { if (BKE_imtype_is_movie(rd->im_format.imtype)) { - BKE_movie_filepath_get(name, rd, preview != 0); + BKE_movie_filepath_get(name, rd, preview != 0, view); } else { BKE_image_path_from_imformat( name, rd->pic, G.main->name, (frame == INT_MIN) ? rd->cfra : frame, - &rd->im_format, (rd->scemode & R_EXTENSION) != 0, true); + &rd->im_format, (rd->scemode & R_EXTENSION) != 0, true, view); } } @@ -288,6 +288,8 @@ void RNA_api_scene_render(StructRNA *srna) RNA_def_int(func, "frame", INT_MIN, INT_MIN, INT_MAX, "", "Frame number to use, if unset the current frame will be used", MINAFRAME, MAXFRAME); parm = RNA_def_boolean(func, "preview", 0, "Preview", "Use preview range"); + parm = RNA_def_string_file_path(func, "view", NULL, FILE_MAX, "View", + "The name of the view to use to replace the \"%\" chars"); parm = RNA_def_string_file_path(func, "filepath", NULL, FILE_MAX, "File Path", "The resulting filepath from the scenes render settings"); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index fc9a501dae8..ee4ec1cb659 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -186,6 +186,11 @@ static void rna_SequenceEditor_elements_begin(CollectionPropertyIterator *iter, rna_SequenceEditor_elements_length(ptr), 0, NULL); } +static void rna_Sequence_views_format_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + rna_Sequence_update(bmain, scene, ptr); +} + static void do_sequence_frame_change_update(Scene *scene, Sequence *seq) { Editing *ed = BKE_sequencer_editing_get(scene, false); @@ -1834,6 +1839,24 @@ static void rna_def_image(BlenderRNA *brna) "rna_SequenceEditor_elements_length", NULL, NULL, NULL); RNA_api_sequence_elements(brna, prop); + /* multiview */ + prop = RNA_def_property(srna, "use_multiview", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_VIEWS); + RNA_def_property_ui_text(prop, "Use Multi-View", "Use Multiple Views (when available)"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_views_format_update"); + + prop = RNA_def_property(srna, "views_format", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "views_format"); + RNA_def_property_enum_items(prop, views_format_items); + RNA_def_property_ui_text(prop, "Views Format", "Mode to load image views"); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Sequence_views_format_update"); + + prop = RNA_def_property(srna, "stereo_3d_format", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "stereo3d_format"); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "Stereo3dFormat"); + RNA_def_property_ui_text(prop, "Stereo 3D Format", "Settings for stereo 3d"); + rna_def_filter_video(srna); rna_def_proxy(srna); rna_def_input(srna); @@ -1925,6 +1948,24 @@ static void rna_def_movie(BlenderRNA *brna) "rna_Sequence_filepath_set"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_filepath_update"); + /* multiview */ + prop = RNA_def_property(srna, "use_multiview", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_VIEWS); + RNA_def_property_ui_text(prop, "Use Multi-View", "Use Multiple Views (when available)"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_views_format_update"); + + prop = RNA_def_property(srna, "views_format", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "views_format"); + RNA_def_property_enum_items(prop, views_format_items); + RNA_def_property_ui_text(prop, "Views Format", "Mode to load movie views"); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Sequence_views_format_update"); + + prop = RNA_def_property(srna, "stereo_3d_format", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "stereo3d_format"); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "Stereo3dFormat"); + RNA_def_property_ui_text(prop, "Stereo 3D Format", "Settings for stereo 3d"); + rna_def_filter_video(srna); rna_def_proxy(srna); rna_def_input(srna); diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index 2d3e3c56672..881688281f3 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -198,6 +198,7 @@ static Sequence *rna_Sequences_new_movie(ID *id, Editing *ed, ReportList *report { Scene *scene = (Scene *)id; Sequence *seq; + StripAnim *sanim; struct anim *an = openanim(file, IB_rect, 0, NULL); @@ -207,7 +208,11 @@ static Sequence *rna_Sequences_new_movie(ID *id, Editing *ed, ReportList *report } seq = alloc_generic_sequence(ed, name, frame_start, channel, SEQ_TYPE_MOVIE, file); - seq->anim = an; + + sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); + BLI_addtail(&seq->anims, sanim); + sanim->anim = an; + seq->anim_preseek = IMB_anim_get_preseek(an); seq->len = IMB_anim_get_duration(an, IMB_TC_RECORD_RUN); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 6aaa947e9e4..4a4c2a34fdf 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -31,6 +31,7 @@ #include "BLF_translation.h" +#include "BKE_image.h" #include "BKE_key.h" #include "BKE_movieclip.h" #include "BKE_node.h" @@ -90,6 +91,34 @@ EnumPropertyItem space_type_items[] = { {0, NULL, 0, NULL, NULL} }; +#define V3D_S3D_CAMERA_LEFT {STEREO_LEFT_ID, "LEFT", ICON_RESTRICT_RENDER_OFF, "Left", ""}, +#define V3D_S3D_CAMERA_RIGHT {STEREO_RIGHT_ID, "RIGHT", ICON_RESTRICT_RENDER_OFF, "Right", ""}, +#define V3D_S3D_CAMERA_S3D {STEREO_3D_ID, "S3D", ICON_CAMERA_STEREO, "3D", ""}, +#ifdef RNA_RUNTIME +#define V3D_S3D_CAMERA_VIEWS {STEREO_MONO_ID, "MONO", ICON_RESTRICT_RENDER_OFF, "Views", ""}, +#endif + +static EnumPropertyItem stereo3d_camera_items[] = { + V3D_S3D_CAMERA_LEFT + V3D_S3D_CAMERA_RIGHT + V3D_S3D_CAMERA_S3D + {0, NULL, 0, NULL, NULL} +}; + +#ifdef RNA_RUNTIME +static EnumPropertyItem multiview_camera_items[] = { + V3D_S3D_CAMERA_VIEWS + V3D_S3D_CAMERA_S3D + {0, NULL, 0, NULL, NULL} +}; +#endif + +#undef V3D_S3D_CAMERA_LEFT +#undef V3D_S3D_CAMERA_RIGHT +#undef V3D_S3D_CAMERA_S3D +#undef V3D_S3D_CAMERA_VIEWS + + static EnumPropertyItem pivot_items_full[] = { {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center", "Pivot around bounding box center of selected object(s)"}, @@ -659,6 +688,17 @@ static EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *UNUSED(C return item; } +static EnumPropertyItem *rna_SpaceView3D_stereo3d_camera_itemf(bContext *UNUSED(C), PointerRNA *ptr, + PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) +{ + Scene *scene = ((bScreen *)ptr->id.data)->scene; + + if (scene->r.views_format == SCE_VIEWS_FORMAT_MULTIVIEW) + return multiview_camera_items; + else + return stereo3d_camera_items; +} + /* Space Image Editor */ static PointerRNA rna_SpaceImageEditor_uvedit_get(PointerRNA *ptr) @@ -671,6 +711,38 @@ static void rna_SpaceImageEditor_mode_update(Main *bmain, Scene *scene, PointerR ED_space_image_paint_update(bmain->wm.first, scene->toolsettings); } + +static void rna_SpaceImageEditor_show_stereo_set(PointerRNA *ptr, int value) +{ + SpaceImage *sima = (SpaceImage *)(ptr->data); + + if (value) + sima->iuser.flag |= IMA_SHOW_STEREO; + else + sima->iuser.flag &= ~IMA_SHOW_STEREO; +} + +static int rna_SpaceImageEditor_show_stereo_get(PointerRNA *ptr) +{ + SpaceImage *sima = (SpaceImage *)(ptr->data); + return (sima->iuser.flag & IMA_SHOW_STEREO) != 0; +} + +static void rna_SpaceImageEditor_show_stereo_update(Main *UNUSED(bmain), Scene *UNUSED(unused), PointerRNA *ptr) +{ + SpaceImage *sima = (SpaceImage *)(ptr->data); + Image *ima = sima->image; + + if (ima) { + if (ima->rr) { + BKE_image_multilayer_index(ima->rr, &sima->iuser); + } + else { + BKE_image_multiview_index(ima, &sima->iuser); + } + } +} + static int rna_SpaceImageEditor_show_render_get(PointerRNA *ptr) { SpaceImage *sima = (SpaceImage *)(ptr->data); @@ -798,6 +870,24 @@ static void rna_SpaceImageEditor_cursor_location_set(PointerRNA *ptr, const floa } } +static void rna_SpaceImageEditor_image_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + SpaceImage *sima = (SpaceImage *)ptr->data; + Image *ima = sima->image; + + /* make sure all the iuser settings are valid for the sima image */ + if (ima) { + if (ima->rr) { + if (BKE_image_multilayer_index(sima->image->rr, &sima->iuser) == NULL) { + BKE_image_init_imageuser(sima->image, &sima->iuser); + } + } + else { + BKE_image_multiview_index(ima, &sima->iuser); + } + } +} + static void rna_SpaceImageEditor_scopes_update(struct bContext *C, struct PointerRNA *ptr) { SpaceImage *sima = (SpaceImage *)ptr->data; @@ -2472,6 +2562,41 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_ui_text(prop, "FX Options", "Options used for real time compositing"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + /* Stereo Settings */ + prop = RNA_def_property(srna, "stereo_3d_camera", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "stereo3d_camera"); + RNA_def_property_enum_items(prop, stereo3d_camera_items); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_SpaceView3D_stereo3d_camera_itemf"); + RNA_def_property_ui_text(prop, "Camera", ""); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "show_stereo_3d_cameras", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "stereo3d_flag", V3D_S3D_DISPCAMERAS); + RNA_def_property_ui_text(prop, "Cameras", "Show the left and right cameras"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "show_stereo_3d_convergence_plane", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "stereo3d_flag", V3D_S3D_DISPPLANE); + RNA_def_property_ui_text(prop, "Plane", "Show the stereo 3d convergence plane"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "stereo_3d_convergence_plane_alpha", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "stereo3d_convergence_alpha"); + RNA_def_property_ui_text(prop, "Plane Alpha", "Opacity (alpha) of the convergence plane"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "show_stereo_3d_volume", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "stereo3d_flag", V3D_S3D_DISPVOLUME); + RNA_def_property_ui_text(prop, "Volume", "Show the stereo 3d frustum volume"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "stereo_3d_volume_alpha", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "stereo3d_volume_alpha"); + RNA_def_property_ui_text(prop, "Volume Alpha", "Opacity (alpha) of the cameras frustum volume"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + /* *** Animated *** */ + RNA_define_animate_sdna(true); /* region */ srna = RNA_def_struct(brna, "RegionView3D", NULL); @@ -2645,7 +2770,7 @@ static void rna_def_space_image(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceImageEditor_image_set", NULL, NULL); RNA_def_property_ui_text(prop, "Image", "Image displayed and edited in this space"); RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_update(prop, NC_GEOM | ND_DATA, NULL); /* is handled in image editor too */ + RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_SpaceImageEditor_image_update"); /* is handled in image editor too */ prop = RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); @@ -2697,6 +2822,12 @@ static void rna_def_space_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Draw Channels", "Channels of the image to draw"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); + prop = RNA_def_property(srna, "show_stereo_3d", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_SpaceImageEditor_show_stereo_get", "rna_SpaceImageEditor_show_stereo_set"); + RNA_def_property_ui_text(prop, "Show Stereo", "Display the image in Stereo 3D"); + RNA_def_property_ui_icon(prop, ICON_CAMERA_STEREO, 0); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, "rna_SpaceImageEditor_show_stereo_update"); + /* uv */ prop = RNA_def_property(srna, "uv_editor", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index fea8b630af6..832a29a2761 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -779,6 +779,16 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL); RNA_def_boolean(func, "color_management", false, "", "Show color management settings"); + func = RNA_def_function(srna, "template_image_stereo_3d", "uiTemplateImageStereo3d"); + RNA_def_function_ui_description(func, "User interface for setting image stereo 3d options"); + parm = RNA_def_pointer(func, "stereo_3d_format", "Stereo3dFormat", "", ""); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL); + + func = RNA_def_function(srna, "template_image_views", "uiTemplateImageViews"); + RNA_def_function_ui_description(func, "User interface for setting image views output options"); + parm = RNA_def_pointer(func, "image_settings", "ImageFormatSettings", "", ""); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL); + func = RNA_def_function(srna, "template_movieclip", "uiTemplateMovieClip"); RNA_def_function_ui_description(func, "Item(s). User interface for selecting movie clips and their source paths"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index fc6d28e67c2..23412a549fa 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -4124,8 +4124,8 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "uiflag2", USER_REGION_OVERLAP); RNA_def_property_ui_text(prop, "Region Overlap", "Draw tool/property regions over the main region, when using Triple Buffer"); - RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); - + RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); + #ifdef WITH_CYCLES prop = RNA_def_property(srna, "compute_device_type", PROP_ENUM, PROP_NONE); RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 64ecf61f774..dcd77e5a0f6 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -1750,6 +1750,37 @@ static void rna_def_piemenu(BlenderRNA *brna) RNA_define_verify_sdna(1); /* not in sdna */ } +static void rna_def_window_stereo3d(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "Stereo3dDisplay", NULL); + RNA_def_struct_sdna(srna, "Stereo3dFormat"); + RNA_def_struct_clear_flag(srna, STRUCT_UNDO); + RNA_def_struct_ui_text(srna, "Stereo 3d Display", "Settings for stereo 3d display"); + + prop = RNA_def_property(srna, "display_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, stereo3d_display_items); + RNA_def_property_ui_text(prop, "Display Mode", ""); + + prop = RNA_def_property(srna, "anaglyph_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, stereo3d_anaglyph_type_items); + RNA_def_property_ui_text(prop, "Anaglyph Type", ""); + + prop = RNA_def_property(srna, "interlace_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, stereo3d_interlace_type_items); + RNA_def_property_ui_text(prop, "Interlace Type", ""); + + prop = RNA_def_property(srna, "use_interlace_swap", PROP_BOOLEAN, PROP_BOOLEAN); + RNA_def_property_boolean_sdna(prop, NULL, "flag", S3D_INTERLACE_SWAP); + RNA_def_property_ui_text(prop, "Swap Left/Right", "Swap left and right stereo channels"); + + prop = RNA_def_property(srna, "use_sidebyside_crosseyed", PROP_BOOLEAN, PROP_BOOLEAN); + RNA_def_property_boolean_sdna(prop, NULL, "flag", S3D_SIDEBYSIDE_CROSSEYED); + RNA_def_property_ui_text(prop, "Cross-Eyed", "Right eye should see left image and vice-versa"); +} + static void rna_def_window(BlenderRNA *brna) { StructRNA *srna; @@ -1759,6 +1790,8 @@ static void rna_def_window(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Window", "Open window"); RNA_def_struct_sdna(srna, "wmWindow"); + rna_def_window_stereo3d(brna); + prop = RNA_def_property(srna, "screen", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "Screen"); @@ -1788,6 +1821,12 @@ static void rna_def_window(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Height", "Window height"); + prop = RNA_def_property(srna, "stereo_3d_display", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "stereo3d_format"); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "Stereo3dDisplay"); + RNA_def_property_ui_text(prop, "Stereo 3D Display", "Settings for stereo 3d display"); + RNA_api_window(srna); } diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 9eb6c1674a3..c95daffe557 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -122,6 +122,7 @@ set(SRC composite/nodes/node_composite_boxmask.c composite/nodes/node_composite_ellipsemask.c composite/nodes/node_composite_switch.c + composite/nodes/node_composite_switchview.c composite/nodes/node_composite_colorcorrection.c composite/nodes/node_composite_pixelate.c diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index 961fdbfc0fb..0215db1dd55 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -133,6 +133,7 @@ void register_node_type_cmp_ellipsemask(void); void register_node_type_cmp_bokehimage(void); void register_node_type_cmp_bokehblur(void); void register_node_type_cmp_switch(void); +void register_node_type_cmp_switch_view(void); void register_node_type_cmp_pixelate(void); void register_node_type_cmp_trackpos(void); void register_node_type_cmp_planetrackdeform(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 6b9a97c0b18..b33bec51c2c 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -202,6 +202,7 @@ DefNode( CompositorNode, CMP_NODE_MASK_ELLIPSE, def_cmp_ellipsemask, "ELLIP DefNode( CompositorNode, CMP_NODE_BOKEHIMAGE, def_cmp_bokehimage, "BOKEHIMAGE", BokehImage, "Bokeh Image", "" ) DefNode( CompositorNode, CMP_NODE_BOKEHBLUR, def_cmp_bokehblur, "BOKEHBLUR", BokehBlur, "Bokeh Blur", "" ) DefNode( CompositorNode, CMP_NODE_SWITCH, def_cmp_switch, "SWITCH", Switch, "Switch", "" ) +DefNode( CompositorNode, CMP_NODE_SWITCH_VIEW, def_cmp_switch_view, "VIEWSWITCH", SwitchView, "View Switch", "" ) DefNode( CompositorNode, CMP_NODE_COLORCORRECTION,def_cmp_colorcorrection,"COLORCORRECTION",ColorCorrection, "Color Correction", "" ) DefNode( CompositorNode, CMP_NODE_MASK, def_cmp_mask, "MASK", Mask, "Mask", "" ) DefNode( CompositorNode, CMP_NODE_KEYINGSCREEN, def_cmp_keyingscreen, "KEYINGSCREEN", KeyingScreen, "Keying Screen", "" ) diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index e616680647e..8bc61862458 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -226,12 +226,13 @@ void *COM_linker_hack = NULL; void ntreeCompositExecTree(Scene *scene, bNodeTree *ntree, RenderData *rd, int rendering, int do_preview, const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) + const ColorManagedDisplaySettings *display_settings, + const char *view_name) { #ifdef WITH_COMPOSITOR - COM_execute(rd, scene, ntree, rendering, view_settings, display_settings); + COM_execute(rd, scene, ntree, rendering, view_settings, display_settings, view_name); #else - UNUSED_VARS(scene, ntree, rd, rendering, view_settings, display_settings); + UNUSED_VARS(scene, ntree, rd, rendering, view_settings, display_settings, view_name); #endif UNUSED_VARS(do_preview); diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 34f3350c2ff..23d47065f59 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -168,14 +168,21 @@ static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, NodeImageLayer *sockdata; RenderPass *rpass; int index; + int passflag = 0; for (rpass = rl->passes.first, index = 0; rpass; rpass = rpass->next, ++index) { int type; if (rpass->channels == 1) type = SOCK_FLOAT; else type = SOCK_RGBA; - - sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, rpass->name, rpass->name); + + /* we only need one socket per type */ + if (passflag & rpass->passtype) + continue; + + passflag |= rpass->passtype; + + sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, rpass->internal_name, rpass->internal_name); /* extra socket info */ sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); sock->storage = sockdata; diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c index 8e602c6179c..7d1087435c2 100644 --- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c +++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c @@ -127,7 +127,7 @@ bNodeSocket *ntreeCompositOutputFileAddSocket(bNodeTree *ntree, bNode *node, con BKE_imformat_defaults(&sockdata->format); /* use node data format by default */ sockdata->use_node_format = true; - + nimf->active_input = BLI_findindex(&node->inputs, sock); return sock; @@ -189,7 +189,7 @@ static void init_output_file(const bContext *C, PointerRNA *ptr) } else BKE_imformat_defaults(&nimf->format); - + /* add one socket by default */ ntreeCompositOutputFileAddSocket(ntree, node, "Image", format); } diff --git a/source/blender/nodes/composite/nodes/node_composite_switchview.c b/source/blender/nodes/composite/nodes/node_composite_switchview.c new file mode 100644 index 00000000000..d805cf4d87f --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_switchview.c @@ -0,0 +1,153 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): + * Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/composite/nodes/node_composite_switchview.c + * \ingroup cmpnodes + */ + +#include "BKE_context.h" +#include "../node_composite_util.h" + +/* **************** SWITCH VIEW ******************** */ +static bNodeSocketTemplate cmp_node_switch_view_out[] = { + { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocket *ntreeCompositSwitchViewAddSocket(bNodeTree *ntree, bNode *node, const char *name) +{ + bNodeSocket *sock = nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, NULL, name); + return sock; +} + +static void cmp_node_switch_view_sanitycheck(bNodeTree *ntree, bNode *node) +{ + bNodeSocket *sock; + + if (!BLI_listbase_is_empty(&node->inputs)) + return; + + sock = ntreeCompositSwitchViewAddSocket(ntree, node, "No View"); + sock->flag |= SOCK_HIDDEN; +} + +static void cmp_node_switch_view_update(bNodeTree *ntree, bNode *node) +{ + bNodeSocket *sock; + SceneRenderView *srv; + Scene *scene = (Scene *)node->id; + + /* only update when called from the operator button */ + if (node->update != NODE_UPDATE_OPERATOR) + return; + + if (scene == NULL) { + nodeRemoveAllSockets(ntree, node); + /* make sure there is always one socket */ + cmp_node_switch_view_sanitycheck(ntree, node); + return; + } + + /* remove the views that were removed */ + sock = node->inputs.last; + while (sock) { + srv = BLI_findstring(&scene->r.views, sock->name, offsetof(SceneRenderView, name)); + + if (srv == NULL) { + bNodeSocket *sock_del = sock; + sock = sock->prev; + nodeRemoveSocket(ntree, node, sock_del); + } + else { + if (srv->viewflag & SCE_VIEW_DISABLE) + sock->flag |= SOCK_HIDDEN; + else + sock->flag &= ~SOCK_HIDDEN; + + sock = sock->prev; + } + } + + /* add the new views */ + for (srv = scene->r.views.first; srv; srv = srv->next) { + sock = BLI_findstring(&node->inputs, srv->name, offsetof(bNodeSocket, name)); + + if (sock == NULL) + sock = ntreeCompositSwitchViewAddSocket(ntree, node, srv->name); + + if (srv->viewflag & SCE_VIEW_DISABLE) + sock->flag |= SOCK_HIDDEN; + else + sock->flag &= ~SOCK_HIDDEN; + } + + /* make sure there is always one socket */ + cmp_node_switch_view_sanitycheck(ntree, node); +} + +static void init_switch_view(const bContext *C, PointerRNA *ptr) +{ + Scene *scene = CTX_data_scene(C); + bNodeTree *ntree = ptr->id.data; + bNode *node = ptr->data; + SceneRenderView *srv; + bNodeSocket *sock; + int nr; + + /* store scene for updates */ + node->id = (ID *)scene; + + if (scene) { + RenderData *rd = &scene->r; + + for (nr = 0, srv = rd->views.first; srv; srv = srv->next, nr++) { + sock = ntreeCompositSwitchViewAddSocket(ntree, node, srv->name); + + if ((srv->viewflag & SCE_VIEW_DISABLE)) + sock->flag |= SOCK_HIDDEN; + } + } + + /* make sure there is always one socket */ + cmp_node_switch_view_sanitycheck(ntree, node); +} + +/* custom1 = mix type */ +void register_node_type_cmp_switch_view(void) +{ + static bNodeType ntype; + + cmp_node_type_base(&ntype, CMP_NODE_SWITCH_VIEW, "Switch View", NODE_CLASS_CONVERTOR, 0); + node_type_socket_templates(&ntype, NULL, cmp_node_switch_view_out); + + ntype.initfunc_api = init_switch_view; + + node_type_update(&ntype, cmp_node_switch_view_update, NULL); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/quicktime/apple/qtkit_export.m b/source/blender/quicktime/apple/qtkit_export.m index 4214fa9ac32..db2d4e72dc5 100644 --- a/source/blender/quicktime/apple/qtkit_export.m +++ b/source/blender/quicktime/apple/qtkit_export.m @@ -98,8 +98,6 @@ typedef struct QuicktimeExport { } QuicktimeExport; -static struct QuicktimeExport *qtexport; - #define AUDIOOUTPUTBUFFERSIZE 65536 #pragma mark rna helper functions @@ -245,7 +243,7 @@ void makeqtstring(RenderData *rd, char *string, bool preview) } } -void filepath_qt(char *string, RenderData *rd, bool preview) +void filepath_qt(char *string, RenderData *rd, bool preview, const char *suffix) { int sfra, efra; @@ -276,8 +274,23 @@ void filepath_qt(char *string, RenderData *rd, bool preview) BLI_path_frame_range(string, sfra, efra, 4); } } + + BLI_path_suffix(string, FILE_MAX, suffix, ""); } +void *context_create_qt(void) +{ + QuicktimeExport *qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport"); + return qtexport; +} + +void context_free_qt(void *context_v) +{ + QuicktimeExport *qtexport = context_v; + if (qtexport) { + MEM_freeN(qtexport); + } +} #pragma mark audio export functions @@ -302,12 +315,13 @@ static OSStatus write_cookie(AudioConverterRef converter, AudioFileID outfile) } /* AudioConverter input stream callback */ -static OSStatus AudioConverterInputCallback(AudioConverterRef inAudioConverter, +static OSStatus AudioConverterInputCallback(AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** outDataPacketDescription, void* inUserData) -{ +{ + QuicktimeExport *qtexport = inUserData; if (qtexport->audioTotalExportedFrames >= qtexport->audioLastFrame) { /* EOF */ *ioNumberDataPackets = 0; return noErr; @@ -334,7 +348,7 @@ static OSStatus AudioConverterInputCallback(AudioConverterRef inAudioConverter, #pragma mark export functions -int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, ReportList *reports, bool preview) +int start_qt(void *context_v, struct Scene *scene, struct RenderData *rd, int rectx, int recty, ReportList *reports, bool preview, const char *UNUSED(suffix)) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSError *error; @@ -342,9 +356,8 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R int success = 1; OSStatus err = noErr; int sfra, efra; + QuicktimeExport *qtexport = context_v; - if (qtexport == NULL) qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport"); - if (preview) { sfra = rd->psfra; efra = rd->pefra; @@ -639,7 +652,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R return success; } -int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, ReportList *reports) +int append_qt(void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, const char *UNUSED(suffix), ReportList *reports) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSBitmapImageRep *blBitmapFormatImage; @@ -647,6 +660,7 @@ int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, in OSStatus err = noErr; unsigned char *from_Ptr,*to_Ptr; int y,from_i,to_i; + QuicktimeExport *qtexport = context_v; /* Create bitmap image rep in blender format (32bit RGBA) */ blBitmapFormatImage = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL @@ -704,7 +718,7 @@ int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, in audioPacketsConverted = 1; err = AudioConverterFillComplexBuffer(qtexport->audioConverter, AudioConverterInputCallback, - NULL, &audioPacketsConverted, &qtexport->audioBufferList, qtexport->audioOutputPktDesc); + qtexport, &audioPacketsConverted, &qtexport->audioBufferList, qtexport->audioOutputPktDesc); if (audioPacketsConverted) { AudioFileWritePackets(qtexport->audioFile, false, qtexport->audioBufferList.mBuffers[0].mDataByteSize, qtexport->audioOutputPktDesc, qtexport->audioOutputPktPos, &audioPacketsConverted, qtexport->audioOutputBuffer); @@ -737,9 +751,11 @@ int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, in } -void end_qt(void) +void end_qt(void *context_v) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + QuicktimeExport *qtexport = context_v; + if (qtexport->movie) { if (qtexport->audioFile) @@ -830,11 +846,6 @@ void end_qt(void) } [QTMovie exitQTKitOnThread]; - - if (qtexport) { - MEM_freeN(qtexport); - qtexport = NULL; - } [pool drain]; } diff --git a/source/blender/quicktime/quicktime_export.h b/source/blender/quicktime/quicktime_export.h index 360c475fdb5..8a10a4a05d6 100644 --- a/source/blender/quicktime/quicktime_export.h +++ b/source/blender/quicktime/quicktime_export.h @@ -55,10 +55,12 @@ struct RenderData; struct ReportList; struct Scene; -int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview); //for movie handle (BKE writeavi.c now) -int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); -void end_qt(void); -void filepath_qt(char *string, struct RenderData *rd, bool preview); +int start_qt(void *context_v, struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview, const char *suffix); //for movie handle (BKE writeavi.c now) +int append_qt(void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, const char *suffix, struct ReportList *reports); +void end_qt(void *context_v); +void filepath_qt(char *string, struct RenderData *rd, bool preview, const char *suffix); +void *context_create_qt(void); +void context_free_qt(void *context_v); /*RNA helper functions */ void quicktime_verify_image_type(struct RenderData *rd, struct ImageFormatData *imf); //used by RNA for defaults values init, if needed diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index a52244ff87f..4857c409f08 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -135,10 +135,14 @@ void RE_engine_free(RenderEngine *engine); void RE_layer_load_from_file(struct RenderLayer *layer, struct ReportList *reports, const char *filename, int x, int y); void RE_result_load_from_file(struct RenderResult *result, struct ReportList *reports, const char *filename); -struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername); +struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname); void RE_engine_update_result(RenderEngine *engine, struct RenderResult *result); void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int merge_results); +void RE_engine_active_view_set(RenderEngine *engine, const char *viewname); +float RE_engine_get_camera_shift_x(RenderEngine *engine, struct Object *camera); +void RE_engine_get_camera_model_matrix(RenderEngine *engine, struct Object *camera, float *r_modelmat); + int RE_engine_test_break(RenderEngine *engine); void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info); void RE_engine_update_progress(RenderEngine *engine, float progress); diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index d1b6673c792..2a07246eaba 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -35,8 +35,10 @@ #include "DNA_listBase.h" #include "DNA_vec_types.h" +struct bMovieHandle; struct bNodeTree; struct Image; +struct ImageFormatData; struct Main; struct NodeBlurData; struct Object; @@ -46,6 +48,7 @@ struct ReportList; struct Scene; struct SceneRenderLayer; struct EnvMap; +struct RenderResult; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* this include is what is exposed of render to outside world */ @@ -65,6 +68,19 @@ typedef struct Render Render; * and how it's converted */ +typedef struct RenderView { + struct RenderView *next, *prev; + char name[64]; /* EXR_VIEW_MAXNAME */ + + /* if this exists, result of composited layers */ + float *rectf; + /* if this exists, result of composited layers */ + float *rectz; + /* optional, 32 bits version of picture, used for sequencer, ogl render and image curves */ + int *rect32; + +} RenderView; + typedef struct RenderPass { struct RenderPass *next, *prev; int passtype, channels; @@ -72,6 +88,11 @@ typedef struct RenderPass { char chan_id[8]; /* amount defined in openexr_multi.h */ float *rect; int rectx, recty; + + char internal_name[64]; /* EXR_PASS_MAXNAME */ + char view[64]; /* EXR_VIEW_MAXNAME */ + int view_id; /* quick lookup */ + int debug_type; } RenderPass; @@ -81,7 +102,7 @@ enum { /* 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 */ +/* after render, the Combined pass is in combined, for renderlayers read from files it is a real pass */ typedef struct RenderLayer { struct RenderLayer *next, *prev; @@ -92,8 +113,10 @@ typedef struct RenderLayer { struct Material *mat_override; struct Group *light_override; - - float *rectf; /* 4 float, standard rgba buffer (read not above!) */ + + /* MULTIVIEW_TODO: acolrect and scolrect are not supported by multiview at the moment. + * If they are really required they should be in RenderView instead */ + float *acolrect; /* 4 float, optional transparent buffer, needs storage for display updates */ float *scolrect; /* 4 float, optional strand buffer, needs storage for display updates */ int *display_buffer; /* 4 char, optional color managed display buffer which is used when @@ -129,6 +152,9 @@ typedef struct RenderResult { /* the main buffers */ ListBase layers; + /* multiView maps to a StringVector in OpenEXR */ + ListBase views; + /* allowing live updates: */ volatile rcti renrect; volatile RenderLayer *renlay; @@ -183,16 +209,18 @@ void RE_FreeRenderResult(struct RenderResult *rr); struct RenderResult *RE_AcquireResultRead(struct Render *re); struct RenderResult *RE_AcquireResultWrite(struct Render *re); void RE_ReleaseResult(struct Render *re); -void RE_AcquireResultImage(struct Render *re, struct RenderResult *rr); +void RE_AcquireResultImageViews(struct Render *re, struct RenderResult *rr); +void RE_ReleaseResultImageViews(struct Render *re, struct RenderResult *rr); +void RE_AcquireResultImage(struct Render *re, struct RenderResult *rr, const int view_id); void RE_ReleaseResultImage(struct Render *re); void RE_SwapResult(struct Render *re, struct RenderResult **rr); struct RenderStats *RE_GetStats(struct Render *re); void RE_ResultGet32(struct Render *re, unsigned int *rect); -void RE_AcquiredResultGet32(struct Render *re, struct RenderResult *result, unsigned int *rect); +void RE_AcquiredResultGet32(struct Render *re, struct RenderResult *result, unsigned int *rect, const int view_id); struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name); -float *RE_RenderLayerGetPass(struct RenderLayer *rl, int passtype); +float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, int passtype, const char *viewname); /* obligatory initialize call, disprect is optional */ void RE_InitState(struct Render *re, struct Render *source, struct RenderData *rd, @@ -203,6 +231,7 @@ void RE_ChangeModeFlag(struct Render *re, int flag, bool clear); /* set up the viewplane/perspective matrix, three choices */ struct Object *RE_GetCamera(struct Render *re); /* return camera override if set */ +void RE_SetOverrideCamera(struct Render *re, struct Object *camera); void RE_SetCamera(struct Render *re, struct Object *camera); void RE_SetEnvmapCamera(struct Render *re, struct Object *cam_ob, float viewscale, float clipsta, float clipend); void RE_SetWindow(struct Render *re, rctf *viewplane, float clipsta, float clipend); @@ -232,6 +261,11 @@ void RE_init_threadcount(Render *re); /* the main processor, assumes all was set OK! */ void RE_TileProcessor(struct Render *re); +bool RE_WriteRenderViewsImage(struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, struct Object *camera, const bool stamp, char *name); +bool RE_WriteRenderViewsMovie(struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, struct RenderData *rd, + struct bMovieHandle *mh, const size_t width, const size_t height, void **movie_ctx_arr, + const size_t totvideos); + /* only RE_NewRender() needed, main Blender render calls */ void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene, struct SceneRenderLayer *srl, struct Object *camera_override, @@ -243,6 +277,9 @@ void RE_RenderFreestyleStrokes(struct Render *re, struct Main *bmain, struct Sce void RE_RenderFreestyleExternal(struct Render *re); #endif +void RE_SetActiveRenderView(struct Render *re, const char *viewname); +const char *RE_GetActiveRenderView(struct Render *re); + /* error reporting */ void RE_SetReports(struct Render *re, struct ReportList *reports); @@ -250,7 +287,7 @@ void RE_SetReports(struct Render *re, struct ReportList *reports); void RE_PreviewRender(struct Render *re, struct Main *bmain, struct Scene *scene); bool RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode); -bool RE_WriteRenderResult(struct ReportList *reports, RenderResult *rr, const char *filename, int compress); +bool RE_WriteRenderResult(struct ReportList *reports, RenderResult *rr, const char *filename, struct ImageFormatData *imf, const bool multiview, const char *view); struct RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty); extern const float default_envmap_layout[]; @@ -276,6 +313,8 @@ void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nbd, int xsize, int ysize, int RE_seq_render_active(struct Scene *scene, struct RenderData *rd); +bool RE_layers_have_name(struct RenderResult *result); + /* shaded view or baking options */ #define RE_BAKE_LIGHT 0 /* not listed in rna_scene.c -> can't be enabled! */ #define RE_BAKE_ALL 1 @@ -297,6 +336,7 @@ void RE_Database_Baking(struct Render *re, struct Main *bmain, struct Scene *sce void RE_DataBase_GetView(struct Render *re, float mat[4][4]); void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, float mat[4][4]); +void RE_GetCameraModelMatrix(struct Render *re, struct Object *camera, float r_mat[4][4]); struct Scene *RE_GetScene(struct Render *re); bool RE_force_single_renderlayer(struct Scene *scene); @@ -304,5 +344,16 @@ bool RE_is_rendering_allowed(struct Scene *scene, struct Object *camera_override bool RE_allow_render_generic_object(struct Object *ob); +/******* defined in render_result.c *********/ + +bool RE_HasFakeLayer(RenderResult *res); +bool RE_RenderResult_is_stereo(RenderResult *res); + +float *RE_RenderViewGetRectf(struct RenderResult *rr, const int view_id); +float *RE_RenderViewGetRectz(struct RenderResult *rr, const int view_id); +int *RE_RenderViewGetRect32(struct RenderResult *rr, const int view_id); +void RE_RenderViewSetRectf(struct RenderResult *res, const int view_id, float *rect); +void RE_RenderViewSetRectz(struct RenderResult *res, const int view_id, float *rect); + #endif /* __RE_PIPELINE_H__ */ diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h index 90ff69dbfbe..e7a2cbf99cd 100644 --- a/source/blender/render/intern/include/render_result.h +++ b/source/blender/render/intern/include/render_result.h @@ -38,6 +38,7 @@ #define RR_USE_EXR 1 #define RR_ALL_LAYERS NULL +#define RR_ALL_VIEWS NULL struct ImBuf; struct ListBase; @@ -53,12 +54,14 @@ struct ColorManagedViewSettings; /* New */ struct RenderResult *render_result_new(struct Render *re, - struct rcti *partrct, int crop, int savebuffers, const char *layername); + struct rcti *partrct, int crop, int savebuffers, const char *layername, const char *viewname); struct RenderResult *render_result_new_full_sample(struct Render *re, - struct ListBase *lb, struct rcti *partrct, int crop, int savebuffers); + struct ListBase *lb, struct rcti *partrct, int crop, int savebuffers, const char *viewname); struct RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty); +void render_result_views_new(struct RenderResult *rr, struct RenderData *rd); + /* Merge */ void render_result_merge(struct RenderResult *rr, struct RenderResult *rrpart); @@ -78,7 +81,7 @@ void render_result_single_layer_end(struct Render *re); void render_result_exr_file_begin(struct Render *re); void render_result_exr_file_end(struct Render *re); -void render_result_exr_file_merge(struct RenderResult *rr, struct RenderResult *rrpart); +void render_result_exr_file_merge(struct RenderResult *rr, struct RenderResult *rrpart, const char *viewname); void render_result_exr_file_path(struct Scene *scene, const char *layname, int sample, char *filepath); int render_result_exr_file_read_sample(struct Render *re, int sample); @@ -91,15 +94,19 @@ bool render_result_exr_file_cache_read(struct Render *re); /* Combined Pixel Rect */ -struct ImBuf *render_result_rect_to_ibuf(struct RenderResult *rr, struct RenderData *rd); +struct ImBuf *render_result_rect_to_ibuf(struct RenderResult *rr, struct RenderData *rd, const int view_id); void render_result_rect_from_ibuf(struct RenderResult *rr, struct RenderData *rd, - struct ImBuf *ibuf); + struct ImBuf *ibuf, const int view_id); -void render_result_rect_fill_zero(struct RenderResult *rr); +void render_result_rect_fill_zero(struct RenderResult *rr, const int view_id); void render_result_rect_get_pixels(struct RenderResult *rr, unsigned int *rect, int rectx, int recty, const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings); + const struct ColorManagedDisplaySettings *display_settings, + const int view_id); + +void render_result_views_shallowcopy(struct RenderResult *dst, struct RenderResult *src); +void render_result_views_shallowdelete(struct RenderResult *rr); #endif /* __RENDER_RESULT_H__ */ diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 0d23c81afb0..8fe12015e87 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -275,6 +275,9 @@ struct Render struct ImagePool *pool; struct EvaluationContext *eval_ctx; + + void **movie_ctx_arr; + char viewname[MAX_NAME]; }; /* ------------------------------------------------------------------------- */ diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index c0ba2f43c36..d36ab46d145 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -5171,8 +5171,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l * above call to BKE_scene_update_for_newframe, fixes bug. [#22702]. * following calls don't depend on 'RE_SetCamera' */ RE_SetCamera(re, camera); - - normalize_m4_m4(mat, camera->obmat); + RE_GetCameraModelMatrix(re, camera, mat); invert_m4(mat); RE_SetView(re, mat); @@ -5342,7 +5341,8 @@ static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int la /* if no camera, viewmat should have been set! */ if (camera) { - normalize_m4_m4(mat, camera->obmat); + RE_GetCameraModelMatrix(re, camera, mat); + normalize_m4(mat); invert_m4(mat); RE_SetView(re, mat); } diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index 0698f849073..ed3033d8393 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -495,9 +495,11 @@ static void render_envmap(Render *re, EnvMap *env) RenderLayer *rl = envre->result->layers.first; int y; float *alpha; - + float *rect; + + rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname); ibuf = IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect | IB_rectfloat); - memcpy(ibuf->rect_float, rl->rectf, ibuf->channels * ibuf->x * ibuf->y * sizeof(float)); + memcpy(ibuf->rect_float, rect, ibuf->channels * ibuf->x * ibuf->y * sizeof(float)); /* envmap renders without alpha */ alpha = ibuf->rect_float + 3; diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index e56466bdf48..343c4a9387a 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -42,6 +42,7 @@ #include "BLI_string.h" #include "BLI_utildefines.h" +#include "BKE_camera.h" #include "BKE_global.h" #include "BKE_report.h" #include "BKE_scene.h" @@ -181,7 +182,7 @@ static RenderPart *get_part_from_result(Render *re, RenderResult *result) return NULL; } -RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername) +RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname) { Render *re = engine->re; RenderResult *result; @@ -204,7 +205,7 @@ RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, disprect.ymin = y; disprect.ymax = y + h; - result = render_result_new(re, &disprect, 0, RR_USE_MEM, layername); + result = render_result_new(re, &disprect, 0, RR_USE_MEM, layername, viewname); /* todo: make this thread safe */ @@ -269,7 +270,7 @@ void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel if (!cancel || merge_results) { if (re->result->do_exr_tile) { if (!cancel) { - render_result_exr_file_merge(re->result, result); + render_result_exr_file_merge(re->result, result, re->viewname); } } else if (!(re->test_break(re->tbh) && (re->r.scemode & R_BUTS_PREVIEW))) @@ -368,6 +369,24 @@ void RE_engine_set_error_message(RenderEngine *engine, const char *msg) } } +void RE_engine_active_view_set(RenderEngine *engine, const char *viewname) +{ + Render *re = engine->re; + RE_SetActiveRenderView(re, viewname); +} + +float RE_engine_get_camera_shift_x(RenderEngine *engine, Object *camera) +{ + Render *re = engine->re; + return BKE_camera_multiview_shift_x(re ? &re->r : NULL, camera, re->viewname); +} + +void RE_engine_get_camera_model_matrix(RenderEngine *engine, Object *camera, float *r_modelmat) +{ + Render *re = engine->re; + BKE_camera_multiview_model_matrix(re ? &re->r : NULL, camera, re->viewname, (float (*)[4])r_modelmat); +} + rcti* RE_engine_get_current_tiles(Render *re, int *r_total_tiles, bool *r_needs_free) { static rcti tiles_static[BLENDER_MAX_THREADS]; @@ -612,7 +631,7 @@ int RE_engine_render(Render *re, int do_all) if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE)) savebuffers = RR_USE_EXR; - re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS); + re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS, RR_ALL_VIEWS); } BLI_rw_mutex_unlock(&re->resultmutex); diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c index a0fcc7cdcd2..970a3937657 100644 --- a/source/blender/render/intern/source/initrender.c +++ b/source/blender/render/intern/source/initrender.c @@ -426,10 +426,10 @@ void make_sample_tables(Render *re) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - struct Object *RE_GetCamera(Render *re) { - return re->camera_override ? re->camera_override : re->scene->camera; + Object *camera = re->camera_override ? re->camera_override : re->scene->camera; + return BKE_camera_multiview_render(re->scene, camera, re->viewname); } static void re_camera_params_get(Render *re, CameraParams *params, Object *cam_ob) @@ -470,6 +470,16 @@ void RE_SetEnvmapCamera(Render *re, Object *cam_ob, float viewscale, float clips re_camera_params_get(re, ¶ms, cam_ob); } +void RE_SetOverrideCamera(Render *re, Object *camera) +{ + re->camera_override = camera; +} + +static void re_camera_params_stereo3d(Render *re, CameraParams *params, Object *cam_ob) +{ + BKE_camera_multiview_params(&re->r, params, cam_ob, re->viewname); +} + /* call this after InitState() */ /* per render, there's one persistent viewplane. Parts will set their own viewplanes */ void RE_SetCamera(Render *re, Object *cam_ob) @@ -479,6 +489,7 @@ void RE_SetCamera(Render *re, Object *cam_ob) /* setup parameters */ BKE_camera_params_init(¶ms); BKE_camera_params_from_object(¶ms, cam_ob); + re_camera_params_stereo3d(re, ¶ms, cam_ob); params.use_fields = (re->r.mode & R_FIELDS); params.field_second = (re->flag & R_SEC_FIELD); @@ -505,6 +516,11 @@ void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, flo copy_m4_m4(mat, re->winmat); } +void RE_GetCameraModelMatrix(Render *re, struct Object *camera, float r_mat[4][4]) +{ + BKE_camera_multiview_model_matrix(&re->r, camera, re->viewname, r_mat); +} + /* ~~~~~~~~~~~~~~~~ part (tile) calculus ~~~~~~~~~~~~~~~~~~~~~~ */ diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 4bde3dddaff..25adb4db4f7 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -70,6 +70,7 @@ #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */ +#include "BKE_object.h" #include "PIL_time.h" #include "IMB_colormanagement.h" @@ -131,7 +132,7 @@ Render R; /* ********* alloc and free ******** */ -static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const char *name_override); +static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const size_t totvideos, const char *name_override); static volatile int g_break = 0; static int thread_break(void *UNUSED(arg)) @@ -190,14 +191,23 @@ void RE_FreeRenderResult(RenderResult *res) render_result_free(res); } -float *RE_RenderLayerGetPass(RenderLayer *rl, int passtype) +float *RE_RenderLayerGetPass(volatile RenderLayer *rl, int passtype, const char *viewname) { RenderPass *rpass; - - for (rpass = rl->passes.first; rpass; rpass = rpass->next) - if (rpass->passtype == passtype) - return rpass->rect; - return NULL; + float *rect = NULL; + + for (rpass = rl->passes.last; rpass; rpass = rpass->prev) { + if (rpass->passtype == passtype) { + rect = rpass->rect; + + if (viewname == NULL) + break; + else if (strcmp(rpass->view, viewname) == 0) + break; + } + } + + return rect; } RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name) @@ -307,8 +317,69 @@ Scene *RE_GetScene(Render *re) return NULL; } +/** + * Same as #RE_AcquireResultImage but creating the necessary views to store the result + * fill provided result struct with a copy of thew views of what is done so far the + * #RenderResult.views #ListBase needs to be freed after with #RE_ReleaseResultImageViews +*/ +void RE_AcquireResultImageViews(Render *re, RenderResult *rr) +{ + memset(rr, 0, sizeof(RenderResult)); + + if (re) { + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ); + + if (re->result) { + RenderLayer *rl; + RenderView *rv, *rview; + + rr->rectx = re->result->rectx; + rr->recty = re->result->recty; + + /* creates a temporary duplication of views */ + render_result_views_shallowcopy(rr, re->result); + + rv = rr->views.first; + + rr->have_combined = (rv->rectf != NULL); + + /* active layer */ + rl = render_get_active_layer(re, re->result); + + if (rl) { + if (rv->rectf == NULL) { + for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) { + rview->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rview->name); + } + } + + if (rv->rectz == NULL) { + for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) { + rview->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rview->name); + } + } + } + + rr->layers = re->result->layers; + rr->xof = re->disprect.xmin; + rr->yof = re->disprect.ymin; + } + } +} + +/* clear temporary renderresult struct */ +void RE_ReleaseResultImageViews(Render *re, RenderResult *rr) +{ + if (re) { + if (rr) { + render_result_views_shallowdelete(rr); + } + BLI_rw_mutex_unlock(&re->resultmutex); + } +} + /* fill provided result struct with what's currently active or done */ -void RE_AcquireResultImage(Render *re, RenderResult *rr) +void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id) { memset(rr, 0, sizeof(RenderResult)); @@ -317,27 +388,35 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr) if (re->result) { RenderLayer *rl; + RenderView *rv; rr->rectx = re->result->rectx; rr->recty = re->result->recty; - rr->rectf = re->result->rectf; - rr->rectz = re->result->rectz; - rr->rect32 = re->result->rect32; - + /* actview view */ + rv = BLI_findlink(&re->result->views, view_id); + if (rv == NULL) + rv = (RenderView *)re->result->views.first; + + rr->rectf = rv ? rv->rectf : NULL; + rr->rectz = rv ? rv->rectz : NULL; + rr->rect32 = rv ? rv->rect32 : NULL; + /* active layer */ rl = render_get_active_layer(re, re->result); - if (rl) { - if (rr->rectf == NULL) - rr->rectf = rl->rectf; - if (rr->rectz == NULL) - rr->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z); + if (rl && rv) { + if (rv->rectf == NULL) + rr->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rv->name); + + if (rv->rectz == NULL) + rr->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rv->name); } - rr->have_combined = (re->result->rectf != NULL); + rr->have_combined = rv ? (rv->rectf != NULL) : false; rr->layers = re->result->layers; - + rr->views = re->result->views; + rr->xof = re->disprect.xmin; rr->yof = re->disprect.ymin; } @@ -354,17 +433,18 @@ void RE_ReleaseResultImage(Render *re) void RE_ResultGet32(Render *re, unsigned int *rect) { RenderResult rres; - - RE_AcquireResultImage(re, &rres); - render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings); + const size_t view_id = BKE_scene_multiview_view_id_get(&re->r, re->viewname); + + RE_AcquireResultImage(re, &rres, view_id); + render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings, 0); RE_ReleaseResultImage(re); } /* caller is responsible for allocating rect in correct size! */ /* Only for acquired results, for lock */ -void RE_AcquiredResultGet32(Render *re, RenderResult *result, unsigned int *rect) +void RE_AcquiredResultGet32(Render *re, RenderResult *result, unsigned int *rect, const int view_id) { - render_result_rect_get_pixels(result, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings); + render_result_rect_get_pixels(result, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings, view_id); } RenderStats *RE_GetStats(Render *re) @@ -683,6 +763,8 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, RE_init_threadcount(re); } +/* This function is only called by view3d rendering, which doesn't support + * multiview at the moment. so handle only one view here */ static void render_result_rescale(Render *re) { RenderResult *result = re->result; @@ -694,7 +776,7 @@ static void render_result_rescale(Render *re) if (src_rectf == NULL) { RenderLayer *rl = render_get_active_layer(re, re->result); if (rl != NULL) { - src_rectf = rl->rectf; + src_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, ""); } } @@ -704,7 +786,8 @@ static void render_result_rescale(Render *re) &re->disprect, 0, RR_USE_MEM, - RR_ALL_LAYERS); + RR_ALL_LAYERS, + ""); if (re->result != NULL) { dst_rectf = re->result->rectf; @@ -712,7 +795,7 @@ static void render_result_rescale(Render *re) RenderLayer *rl; rl = render_get_active_layer(re, re->result); if (rl != NULL) { - dst_rectf = rl->rectf; + dst_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, ""); } } @@ -910,9 +993,9 @@ static void *do_part_thread(void *pa_v) if (R.test_break(R.tbh) == 0) { if (!R.sss_points && (R.r.scemode & R_FULL_SAMPLE)) - pa->result = render_result_new_full_sample(&R, &pa->fullresult, &pa->disprect, pa->crop, RR_USE_MEM); + pa->result = render_result_new_full_sample(&R, &pa->fullresult, &pa->disprect, pa->crop, RR_USE_MEM, R.viewname); else - pa->result = render_result_new(&R, &pa->disprect, pa->crop, RR_USE_MEM, RR_ALL_LAYERS); + pa->result = render_result_new(&R, &pa->disprect, pa->crop, RR_USE_MEM, RR_ALL_LAYERS, R.viewname); /* Copy EXR tile settings, so pipeline knows whether this is a result * for Save Buffers enabled rendering. @@ -935,7 +1018,7 @@ static void *do_part_thread(void *pa_v) /* merge too on break! */ if (R.result->do_exr_tile) { - render_result_exr_file_merge(R.result, pa->result); + render_result_exr_file_merge(R.result, pa->result, R.viewname); } else if (render_display_update_enabled(&R)) { /* on break, don't merge in result for preview renders, looks nicer */ @@ -1115,16 +1198,23 @@ static void *do_render_thread(void *thread_v) return NULL; } -static void threaded_tile_processor(Render *re) +static void main_render_result_end(Render *re) +{ + if (re->result->do_exr_tile) { + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + render_result_exr_file_end(re); + BLI_rw_mutex_unlock(&re->resultmutex); + } + + if (re->r.scemode & R_EXR_CACHE_FILE) { + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + render_result_exr_file_cache_write(re); + BLI_rw_mutex_unlock(&re->resultmutex); + } +} + +static void main_render_result_new(Render *re) { - RenderThread thread[BLENDER_MAX_THREADS]; - ThreadQueue *workqueue, *donequeue; - ListBase threads; - RenderPart *pa; - rctf viewplane = re->viewplane; - double lastdraw, elapsed, redrawtime = 1.0f; - int totpart = 0, minx = 0, slice = 0, a, wait; - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); /* first step; free the entire render result, make new, and/or prepare exr buffer saving */ @@ -1132,25 +1222,35 @@ static void threaded_tile_processor(Render *re) render_result_free(re->result); if (re->sss_points && render_display_update_enabled(re)) - re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS); + re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); else if (re->r.scemode & R_FULL_SAMPLE) - re->result = render_result_new_full_sample(re, &re->fullresult, &re->disprect, 0, RR_USE_EXR); + re->result = render_result_new_full_sample(re, &re->fullresult, &re->disprect, 0, RR_USE_EXR, RR_ALL_VIEWS); else re->result = render_result_new(re, &re->disprect, 0, - (re->r.scemode & R_EXR_TILE_FILE) ? RR_USE_EXR : RR_USE_MEM, RR_ALL_LAYERS); + (re->r.scemode & R_EXR_TILE_FILE) ? RR_USE_EXR : RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); } BLI_rw_mutex_unlock(&re->resultmutex); + + if (re->result->do_exr_tile) + render_result_exr_file_begin(re); +} + +static void threaded_tile_processor(Render *re) +{ + RenderThread thread[BLENDER_MAX_THREADS]; + ThreadQueue *workqueue, *donequeue; + ListBase threads; + RenderPart *pa; + rctf viewplane = re->viewplane; + double lastdraw, elapsed, redrawtime = 1.0f; + int totpart = 0, minx = 0, slice = 0, a, wait; if (re->result == NULL) return; /* warning; no return here without closing exr file */ - RE_parts_init(re, true); - - if (re->result->do_exr_tile) - render_result_exr_file_begin(re); /* assuming no new data gets added to dbase... */ R = *re; @@ -1256,18 +1356,6 @@ static void threaded_tile_processor(Render *re) BLI_thread_queue_free(donequeue); BLI_thread_queue_free(workqueue); - if (re->result->do_exr_tile) { - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - render_result_exr_file_end(re); - BLI_rw_mutex_unlock(&re->resultmutex); - } - - if (re->r.scemode & R_EXR_CACHE_FILE) { - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - render_result_exr_file_cache_write(re); - BLI_rw_mutex_unlock(&re->resultmutex); - } - /* unset threadsafety */ g_break = 0; BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE); @@ -1284,6 +1372,7 @@ static void free_all_freestyle_renders(void); /* currently only called by preview renders and envmap */ void RE_TileProcessor(Render *re) { + main_render_result_new(re); threaded_tile_processor(re); re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime; @@ -1309,6 +1398,7 @@ void RE_TileProcessor(Render *re) static void do_render_3d(Render *re) { + RenderView *rv; int cfra_backup; re->current_scene_update(re->suh, re->scene); @@ -1325,40 +1415,49 @@ static void do_render_3d(Render *re) BKE_scene_frame_set(re->scene, (double)re->scene->r.cfra + (double)re->mblur_offs + (double)re->field_offs); - /* lock drawing in UI during data phase */ - if (re->draw_lock) - re->draw_lock(re->dlh, 1); - - /* make render verts/faces/halos/lamps */ - if (render_scene_needs_vector(re)) { - RE_Database_FromScene_Vectors(re, re->main, re->scene, re->lay); - } - else { - RE_Database_FromScene(re, re->main, re->scene, re->lay, 1); - RE_Database_Preprocess(re); - } + /* init main render result */ + main_render_result_new(re); + + /* we need a new database for each view */ + for (rv = re->result->views.first; rv; rv = rv->next) { + RE_SetActiveRenderView(re, rv->name); + + /* lock drawing in UI during data phase */ + if (re->draw_lock) + re->draw_lock(re->dlh, 1); + + /* make render verts/faces/halos/lamps */ + if (render_scene_needs_vector(re)) + RE_Database_FromScene_Vectors(re, re->main, re->scene, re->lay); + else { + RE_Database_FromScene(re, re->main, re->scene, re->lay, 1); + RE_Database_Preprocess(re); + } - /* clear UI drawing locks */ - if (re->draw_lock) - re->draw_lock(re->dlh, 0); + /* clear UI drawing locks */ + if (re->draw_lock) + re->draw_lock(re->dlh, 0); - threaded_tile_processor(re); + threaded_tile_processor(re); #ifdef WITH_FREESTYLE - /* Freestyle */ - if (re->r.mode & R_EDGE_FRS) - if (!re->test_break(re->tbh)) - add_freestyle(re, 1); + /* Freestyle */ + if (re->r.mode & R_EDGE_FRS) + if (!re->test_break(re->tbh)) + add_freestyle(re, 1); #endif - /* do left-over 3d post effects (flares) */ - if (re->flag & R_HALO) - if (!re->test_break(re->tbh)) - add_halo_flare(re); - - /* free all render verts etc */ - RE_Database_Free(re); - + /* do left-over 3d post effects (flares) */ + if (re->flag & R_HALO) + if (!re->test_break(re->tbh)) + add_halo_flare(re); + + /* free all render verts etc */ + RE_Database_Free(re); + } + + main_render_result_end(re); + re->scene->r.cfra = cfra_backup; re->scene->r.subframe = 0.f; } @@ -1431,19 +1530,13 @@ static void merge_renderresult_blur(RenderResult *rr, RenderResult *brr, float b rl1 = brr->layers.first; for (rl = rr->layers.first; rl && rl1; rl = rl->next, rl1 = rl1->next) { - - /* combined */ - if (rl->rectf && rl1->rectf) { - if (key_alpha) - addblur_rect_key(rr, rl->rectf, rl1->rectf, blurfac); - else - addblur_rect(rr, rl->rectf, rl1->rectf, blurfac, 4); - } - /* passes are allocated in sync */ rpass1 = rl1->passes.first; for (rpass = rl->passes.first; rpass && rpass1; rpass = rpass->next, rpass1 = rpass1->next) { - addblur_rect(rr, rpass->rect, rpass1->rect, blurfac, rpass->channels); + if ((rpass->passtype & SCE_PASS_COMBINED) && key_alpha) + addblur_rect_key(rr, rpass->rect, rpass1->rect, blurfac); + else + addblur_rect(rr, rpass->rect, rpass1->rect, blurfac, rpass->channels); } } } @@ -1456,7 +1549,7 @@ static void do_render_blur_3d(Render *re) int blur = re->r.mblur_samples; /* create accumulation render result */ - rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS); + rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); /* do the blur steps */ while (blur--) { @@ -1518,10 +1611,6 @@ static void merge_renderresult_fields(RenderResult *rr, RenderResult *rr1, Rende rl2 = rr2->layers.first; for (rl = rr->layers.first; rl && rl1 && rl2; rl = rl->next, rl1 = rl1->next, rl2 = rl2->next) { - /* combined */ - if (rl->rectf && rl1->rectf && rl2->rectf) - interleave_rect(rr, rl->rectf, rl1->rectf, rl2->rectf, 4); - /* passes are allocated in sync */ rpass1 = rl1->passes.first; rpass2 = rl2->passes.first; @@ -1589,7 +1678,7 @@ static void do_render_fields_3d(Render *re) re->disprect.ymax *= 2; BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS); + re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); if (rr2) { if (re->r.mode & R_ODDFIELD) @@ -1661,7 +1750,7 @@ static void do_render_fields_blur_3d(Render *re) /* weak is: it chances disprect from border */ render_result_disprect_to_full_resolution(re); - rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS); + rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); render_result_merge(rres, re->result); render_result_free(re->result); @@ -2068,11 +2157,14 @@ static void free_all_freestyle_renders(void) } #endif -/* reads all buffers, calls optional composite, merges in first result->rectf */ +/* reads all buffers, calls optional composite, merges in first result->views rectf */ static void do_merge_fullsample(Render *re, bNodeTree *ntree) { + ListBase *rectfs; + RenderView *rv; float *rectf, filt[3][3]; int x, y, sample; + int nr, numviews; /* interaction callbacks */ if (ntree) { @@ -2087,9 +2179,18 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) /* filtmask needs it */ R = *re; - /* we accumulate in here */ - rectf = MEM_mapallocN(re->rectx * re->recty * sizeof(float) * 4, "fullsample rgba"); - + /* temporary storage of the acccumulation buffers */ + rectfs = MEM_callocN(sizeof(ListBase), "fullsample accumulation buffers"); + + numviews = BLI_listbase_count(&re->result->views); + for (nr = 0; nr < numviews; nr++) { + rv = MEM_callocN(sizeof(RenderView), "fullsample renderview"); + + /* we accumulate in here */ + rv->rectf = MEM_mapallocN(re->rectx * re->recty * sizeof(float) * 4, "fullsample rgba"); + BLI_addtail(rectfs, rv); + } + for (sample = 0; sample < re->r.osa; sample++) { Scene *sce; Render *re1; @@ -2126,54 +2227,70 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) if (ntree) { ntreeCompositTagRender(re->scene); ntreeCompositTagAnimated(ntree); - - ntreeCompositExecTree(re->scene, ntree, &re->r, true, G.background == 0, &re->scene->view_settings, &re->scene->display_settings); + + for (rv = re->result->views.first; rv; rv = rv->next) { + ntreeCompositExecTree(re->scene, ntree, &re->r, true, G.background == 0, &re->scene->view_settings, &re->scene->display_settings, rv->name); + } } - - /* ensure we get either composited result or the active layer */ - RE_AcquireResultImage(re, &rres); - - /* accumulate with filter, and clip */ - mask = (1 << sample); - mask_array(mask, filt); - for (y = 0; y < re->recty; y++) { - float *rf = rectf + 4 * y * re->rectx; - float *col = rres.rectf + 4 * y * re->rectx; - - for (x = 0; x < re->rectx; x++, rf += 4, col += 4) { - /* clamping to 1.0 is needed for correct AA */ - if (col[0] < 0.0f) col[0] = 0.0f; else if (col[0] > 1.0f) col[0] = 1.0f; - if (col[1] < 0.0f) col[1] = 0.0f; else if (col[1] > 1.0f) col[1] = 1.0f; - if (col[2] < 0.0f) col[2] = 0.0f; else if (col[2] > 1.0f) col[2] = 1.0f; + for (nr = 0, rv = re->result->views.first; rv; rv = rv->next, nr++) { + rectf = rv->rectf; + + /* ensure we get either composited result or the active layer */ + RE_AcquireResultImage(re, &rres, nr); + + /* accumulate with filter, and clip */ + mask = (1 << sample); + mask_array(mask, filt); + + for (y = 0; y < re->recty; y++) { + float *rf = rectf + 4 * y * re->rectx; + float *col = rres.rectf + 4 * y * re->rectx; - add_filt_fmask_coord(filt, col, rf, re->rectx, re->recty, x, y); + for (x = 0; x < re->rectx; x++, rf += 4, col += 4) { + /* clamping to 1.0 is needed for correct AA */ + if (col[0] < 0.0f) col[0] = 0.0f; else if (col[0] > 1.0f) col[0] = 1.0f; + if (col[1] < 0.0f) col[1] = 0.0f; else if (col[1] > 1.0f) col[1] = 1.0f; + if (col[2] < 0.0f) col[2] = 0.0f; else if (col[2] > 1.0f) col[2] = 1.0f; + + add_filt_fmask_coord(filt, col, rf, re->rectx, re->recty, x, y); + } } - } - RE_ReleaseResultImage(re); + RE_ReleaseResultImage(re); - /* show stuff */ - if (sample != re->osa - 1) { - /* weak... the display callback wants an active renderlayer pointer... */ - re->result->renlay = render_get_active_layer(re, re->result); - re->display_update(re->duh, re->result, NULL); + /* show stuff */ + if (sample != re->osa - 1) { + /* weak... the display callback wants an active renderlayer pointer... */ + re->result->renlay = render_get_active_layer(re, re->result); + RE_SetActiveRenderView(re, rv->name); + re->display_update(re->duh, re->result, NULL); + } } - - if (re->test_break(re->tbh)) - break; } - /* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */ - for (y = 0; y < re->recty; y++) { - float *rf = rectf + 4 * y * re->rectx; + for (nr = 0; nr < numviews; nr++) { + rectf = ((RenderView *)BLI_findlink(rectfs, nr))->rectf; + + /* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */ + for (y = 0; y < re->recty; y++) { + float *rf = rectf + 4 * y * re->rectx; - for (x = 0; x < re->rectx; x++, rf += 4) { - rf[0] = MAX2(rf[0], 0.0f); - rf[1] = MAX2(rf[1], 0.0f); - rf[2] = MAX2(rf[2], 0.0f); - CLAMP(rf[3], 0.0f, 1.0f); + for (x = 0; x < re->rectx; x++, rf += 4) { + rf[0] = MAX2(rf[0], 0.0f); + rf[1] = MAX2(rf[1], 0.0f); + rf[2] = MAX2(rf[2], 0.0f); + CLAMP(rf[3], 0.0f, 1.0f); + } } + + /* store the final result */ + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + rv = BLI_findlink(&re->result->views, nr); + if (rv->rectf) + MEM_freeN(rv->rectf); + rv->rectf = rectf; + BLI_rw_mutex_unlock(&re->resultmutex); } /* clear interaction callbacks */ @@ -2186,12 +2303,14 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) /* disable full sample print */ R.i.curfsa = 0; - - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - if (re->result->rectf) - MEM_freeN(re->result->rectf); - re->result->rectf = rectf; - BLI_rw_mutex_unlock(&re->resultmutex); + + /* garbage collection */ + while (rectfs->first) { + RenderView *rv = rectfs->first; + BLI_remlink(rectfs, rv); + MEM_freeN(rv); + } + MEM_freeN(rectfs); } /* called externally, via compositor */ @@ -2267,7 +2386,11 @@ static void do_render_composite_fields_blur_3d(Render *re) if (composite_needs_render(re->scene, 1)) { /* save memory... free all cached images */ ntreeFreeCache(ntree); - + + /* render the frames + * it could be optimized to render only the needed view + * but what if a scene has a different number of views + * than the main scene? */ do_render_fields_blur_3d(re); } else { @@ -2280,7 +2403,7 @@ static void do_render_composite_fields_blur_3d(Render *re) if ((re->r.mode & R_CROP) == 0) { render_result_disprect_to_full_resolution(re); } - re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS); + re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); BLI_rw_mutex_unlock(&re->resultmutex); @@ -2325,7 +2448,10 @@ static void do_render_composite_fields_blur_3d(Render *re) if (re->r.scemode & R_FULL_SAMPLE) do_merge_fullsample(re, ntree); else { - ntreeCompositExecTree(re->scene, ntree, &re->r, true, G.background == 0, &re->scene->view_settings, &re->scene->display_settings); + RenderView *rv; + for (rv = re->result->views.first; rv; rv = rv->next) { + ntreeCompositExecTree(re->scene, ntree, &re->r, true, G.background == 0, &re->scene->view_settings, &re->scene->display_settings, rv->name); + } } ntree->stats_draw = NULL; @@ -2350,13 +2476,17 @@ static void do_render_composite_fields_blur_3d(Render *re) static void renderresult_stampinfo(Render *re) { RenderResult rres; + RenderView *rv; + int nr; /* this is the basic trick to get the displayed float or char rect from render result */ - RE_AcquireResultImage(re, &rres); - BKE_image_stamp_buf( - re->scene, RE_GetCamera(re), - (unsigned char *)rres.rect32, rres.rectf, rres.rectx, rres.recty, 4); - RE_ReleaseResultImage(re); + nr = 0; + for (rv = re->result->views.first;rv;rv = rv->next, nr++) { + RE_SetActiveRenderView(re, rv->name); + RE_AcquireResultImage(re, &rres, nr); + BKE_image_stamp_buf(re->scene, RE_GetCamera(re), (unsigned char *)rv->rect32, rv->rectf, rres.rectx, rres.recty, 4); + RE_ReleaseResultImage(re); + } } int RE_seq_render_active(Scene *scene, RenderData *rd) @@ -2380,10 +2510,12 @@ int RE_seq_render_active(Scene *scene, RenderData *rd) static void do_render_seq(Render *re) { static int recurs_depth = 0; - struct ImBuf *ibuf, *out; + struct ImBuf *out; RenderResult *rr; /* don't assign re->result here as it might change during give_ibuf_seq */ int cfra = re->r.cfra; SeqRenderData context; + size_t view_id, tot_views; + struct ImBuf **ibuf_arr; int re_x, re_y; re->i.cfra = cfra; @@ -2406,45 +2538,67 @@ static void do_render_seq(Render *re) re_y = re->result->recty; } + tot_views = BKE_scene_multiview_num_views_get(&re->r); + ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * tot_views, "Sequencer Views ImBufs"); + BKE_sequencer_new_render_data( re->eval_ctx, re->main, re->scene, re_x, re_y, 100, &context); - out = BKE_sequencer_give_ibuf(&context, cfra, 0); + /* the renderresult gets destroyed during the rendering, so we first collect all ibufs + * and then we populate the final renderesult */ - if (out) { - ibuf = IMB_dupImBuf(out); - IMB_freeImBuf(out); - BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf); - } - else { - ibuf = NULL; - } + for (view_id = 0; view_id < tot_views; view_id++) { + context.view_id = view_id; + out = BKE_sequencer_give_ibuf(&context, cfra, 0); - recurs_depth--; + if (out) { + ibuf_arr[view_id] = IMB_dupImBuf(out); + IMB_freeImBuf(out); + BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf_arr[view_id]); + } + else { + ibuf_arr[view_id] = NULL; + } + } rr = re->result; - + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + render_result_views_new(rr, &re->r); + BLI_rw_mutex_unlock(&re->resultmutex); - if (ibuf) { - /* copy ibuf into combined pixel rect */ - render_result_rect_from_ibuf(rr, &re->r, ibuf); - - if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */ - Editing *ed = re->scene->ed; - if (ed) - BKE_sequencer_free_imbuf(re->scene, &ed->seqbase, true); + for (view_id = 0; view_id < tot_views; view_id++) { + RenderView *rv = BLI_findlink(&rr->views, view_id); + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + + if (ibuf_arr[view_id]) { + /* copy ibuf into combined pixel rect */ + render_result_rect_from_ibuf(rr, &re->r, ibuf_arr[view_id], view_id); + + if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */ + Editing *ed = re->scene->ed; + if (ed) + BKE_sequencer_free_imbuf(re->scene, &ed->seqbase, true); + } + IMB_freeImBuf(ibuf_arr[view_id]); } - IMB_freeImBuf(ibuf); - } - else { - /* render result is delivered empty in most cases, nevertheless we handle all cases */ - render_result_rect_fill_zero(rr); + else { + /* render result is delivered empty in most cases, nevertheless we handle all cases */ + render_result_rect_fill_zero(rr, view_id); + } + + BLI_rw_mutex_unlock(&re->resultmutex); + + /* would mark display buffers as invalid */ + RE_SetActiveRenderView(re, rv->name); + re->display_update(re->duh, re->result, NULL); } - BLI_rw_mutex_unlock(&re->resultmutex); + MEM_freeN(ibuf_arr); + + recurs_depth--; /* just in case this flag went missing at some point */ re->r.scemode |= R_DOSEQ; @@ -2454,9 +2608,6 @@ static void do_render_seq(Render *re) re->progress(re->prh, (float)(cfra - re->r.sfra) / (re->r.efra - re->r.sfra)); else re->progress(re->prh, 1.0f); - - /* would mark display buffers as invalid */ - re->display_update(re->duh, re->result, NULL); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -2543,11 +2694,50 @@ static bool check_valid_compositing_camera(Scene *scene, Object *camera_override } } +static bool check_valid_camera_multiview(Scene *scene, Object *camera, ReportList *reports) +{ + SceneRenderView *srv; + bool active_view = false; + + if ((scene->r.scemode & R_MULTIVIEW) == 0) + return true; + + for (srv = scene->r.views.first; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) { + active_view = true; + + if (scene->r.views_format == SCE_VIEWS_FORMAT_MULTIVIEW) { + Object *view_camera; + view_camera = BKE_camera_multiview_render(scene, camera, srv->name); + + if (view_camera == camera) { + /* if the suffix is not in the camera, means we are using the fallback camera */ + if (!BLI_str_endswith(view_camera->id.name + 2, srv->suffix)) { + BKE_reportf(reports, RPT_ERROR, "Camera \"%s\" is not a multi-view camera", + camera->id.name + 2); + return false; + } + } + } + } + } + + if (!active_view) { + BKE_reportf(reports, RPT_ERROR, "No active view found in scene \"%s\"", scene->id.name + 2); + return false; + } + + return true; +} + static int check_valid_camera(Scene *scene, Object *camera_override, ReportList *reports) { if (camera_override == NULL && scene->camera == NULL) scene->camera = BKE_scene_camera_find(scene); + if (!check_valid_camera_multiview(scene, scene->camera, reports)) + return false; + if (RE_seq_render_active(scene, &scene->r)) { if (scene->ed) { Sequence *seq = scene->ed->seqbase.first; @@ -2565,6 +2755,8 @@ static int check_valid_camera(Scene *scene, Object *camera_override, ReportList } } } + else if (!check_valid_camera_multiview(seq->scene, seq->scene_camera, reports)) + return false; } seq = seq->next; @@ -2729,6 +2921,17 @@ static void update_physics_cache(Render *re, Scene *scene, int UNUSED(anim_init) BKE_ptcache_bake(&baker); } + +void RE_SetActiveRenderView(Render *re, const char *viewname) +{ + BLI_strncpy(re->viewname, viewname, sizeof(re->viewname)); +} + +const char *RE_GetActiveRenderView(Render *re) +{ + return re->viewname; +} + /* evaluating scene options for general Blender render */ static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, Scene *scene, SceneRenderLayer *srl, Object *camera_override, unsigned int lay_override, int anim, int anim_init) @@ -2764,7 +2967,8 @@ static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, re->lay = lay_override ? lay_override : scene->lay; re->layer_override = lay_override; re->i.localview = (re->lay & 0xFF000000) != 0; - + re->viewname[0] = '\0'; + /* not too nice, but it survives anim-border render */ if (anim) { render_update_anim_renderdata(re, &scene->r); @@ -2838,10 +3042,10 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr char name[FILE_MAX]; BKE_image_path_from_imformat( name, scene->r.pic, bmain->name, scene->r.cfra, - &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false); + &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false, NULL); /* reports only used for Movie */ - do_write_image_or_movie(re, bmain, scene, NULL, name); + do_write_image_or_movie(re, bmain, scene, NULL, 0, name); } } @@ -2879,96 +3083,269 @@ void RE_RenderFreestyleExternal(Render *re) } #endif -static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const char *name_override) +bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scene, struct Object *camera, const bool stamp, char *name) { - char name[FILE_MAX]; - RenderResult rres; - Object *camera = RE_GetCamera(re); - double render_time; - int ok = 1; - - RE_AcquireResultImage(re, &rres); + bool is_mono; + bool ok = true; + RenderData *rd = &scene->r; - /* write movie or image */ - if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { - bool do_free = false; - ImBuf *ibuf = render_result_rect_to_ibuf(&rres, &scene->r); + if (!rr) + return false; - /* note; the way it gets 32 bits rects is weak... */ - if (ibuf->rect == NULL) { - ibuf->rect = MEM_mapallocN(sizeof(int) * rres.rectx * rres.recty, "temp 32 bits rect"); - ibuf->mall |= IB_rect; - RE_AcquiredResultGet32(re, &rres, ibuf->rect); - do_free = true; - } + is_mono = BLI_listbase_count_ex(&rr->views, 2) < 2; + if (ELEM(rd->im_format.imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) && + rd->im_format.views_format == R_IMF_VIEWS_MULTIVIEW) + { + RE_WriteRenderResult(reports, rr, name, &rd->im_format, true, NULL); + printf("Saved: %s\n", name); + } - IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, - &scene->display_settings, &scene->r.im_format); + /* mono, legacy code */ + else if (is_mono || (rd->im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) + { + RenderView *rv; + size_t view_id; + char filepath[FILE_MAX]; - ok = mh->append_movie(&re->r, scene->r.sfra, scene->r.cfra, (int *) ibuf->rect, - ibuf->x, ibuf->y, re->reports); - if (do_free) { - MEM_freeN(ibuf->rect); - ibuf->rect = NULL; - ibuf->mall &= ~IB_rect; - } + BLI_strncpy(filepath, name, sizeof(filepath)); - /* imbuf knows which rects are not part of ibuf */ - IMB_freeImBuf(ibuf); + for (view_id = 0, rv = rr->views.first; rv; rv = rv->next, view_id++) { + BKE_scene_multiview_view_filepath_get(&scene->r, filepath, rv->name, name); - printf("Append frame %d", scene->r.cfra); - } - else { - if (name_override) - BLI_strncpy(name, name_override, sizeof(name)); - else - BKE_image_path_from_imformat( - name, scene->r.pic, bmain->name, scene->r.cfra, - &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true); - - if (re->r.im_format.imtype == R_IMF_IMTYPE_MULTILAYER) { - if (re->result) { - RE_WriteRenderResult(re->reports, re->result, name, scene->r.im_format.exr_codec); - printf("Saved: %s", name); + if (rd->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) { + + RE_WriteRenderResult(reports, rr, name, &rd->im_format, false, rv->name); + printf("Saved: %s\n", name); } + else { + ImBuf *ibuf = render_result_rect_to_ibuf(rr, rd, view_id); + + IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, + &scene->display_settings, &rd->im_format); + + if (stamp) { + /* writes the name of the individual cameras */ + Object *view_camera = BKE_camera_multiview_render(scene, camera, rv->name); + ok = BKE_imbuf_write_stamp(scene, view_camera, ibuf, name, &rd->im_format); + } + else { + ok = BKE_imbuf_write(ibuf, name, &rd->im_format); + } + + if (ok == false) { + printf("Render error: cannot save %s\n", name); + } + else printf("Saved: %s\n", name); + + /* optional preview images for exr */ + if (ok && rd->im_format.imtype == R_IMF_IMTYPE_OPENEXR && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) { + ImageFormatData imf = rd->im_format; + imf.imtype = R_IMF_IMTYPE_JPEG90; + + if (BLI_testextensie(name, ".exr")) + name[strlen(name) - 4] = 0; + BKE_image_path_ensure_ext_from_imformat(name, &imf); + ibuf->planes = 24; + + IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, + &scene->display_settings, &rd->im_format); + + if (stamp) { + /* writes the name of the individual cameras */ + Object *view_camera = BKE_camera_multiview_render(scene, camera, rv->name); + ok = BKE_imbuf_write_stamp(scene, view_camera, ibuf, name, &rd->im_format); + } + else { + ok = BKE_imbuf_write(ibuf, name, &rd->im_format); + } + printf("Saved: %s\n", name); + } + + /* imbuf knows which rects are not part of ibuf */ + IMB_freeImBuf(ibuf); + } + } + } + else { /* R_IMF_VIEWS_STEREO_3D */ + BLI_assert(scene->r.im_format.views_format == R_IMF_VIEWS_STEREO_3D); + + if (rd->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) { + printf("Stereo 3D not support for MultiLayer image: %s\n", name); } else { - ImBuf *ibuf = render_result_rect_to_ibuf(&rres, &scene->r); + ImBuf *ibuf_arr[3] = {NULL}; + const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + int i; + + for (i = 0; i < 2; i++) { + int view_id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name)); + ibuf_arr[i] = render_result_rect_to_ibuf(rr, rd, view_id); + IMB_colormanagement_imbuf_for_write(ibuf_arr[i], true, false, &scene->view_settings, + &scene->display_settings, &scene->r.im_format); + IMB_prepare_write_ImBuf(IMB_isfloat(ibuf_arr[i]), ibuf_arr[i]); + } - IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, - &scene->display_settings, &scene->r.im_format); + ibuf_arr[2] = IMB_stereo3d_ImBuf(&scene->r.im_format, ibuf_arr[0], ibuf_arr[1]); - ok = BKE_imbuf_write_stamp(scene, camera, ibuf, name, &scene->r.im_format); - - if (ok == 0) { + if (stamp) + ok = BKE_imbuf_write_stamp(scene, camera, ibuf_arr[2], name, &rd->im_format); + else + ok = BKE_imbuf_write(ibuf_arr[2], name, &rd->im_format); + + if (ok == false) printf("Render error: cannot save %s\n", name); - } - else printf("Saved: %s", name); - + else + printf("Saved: %s\n", name); + /* optional preview images for exr */ - if (ok && scene->r.im_format.imtype == R_IMF_IMTYPE_OPENEXR && (scene->r.im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) { - ImageFormatData imf = scene->r.im_format; + if (ok && rd->im_format.imtype == R_IMF_IMTYPE_OPENEXR && + (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) + { + ImageFormatData imf = rd->im_format; imf.imtype = R_IMF_IMTYPE_JPEG90; if (BLI_testextensie(name, ".exr")) name[strlen(name) - 4] = 0; + BKE_image_path_ensure_ext_from_imformat(name, &imf); - ibuf->planes = 24; + ibuf_arr[2]->planes = 24; - IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, + IMB_colormanagement_imbuf_for_write(ibuf_arr[2], true, false, &scene->view_settings, &scene->display_settings, &imf); - BKE_imbuf_write_stamp(scene, camera, ibuf, name, &imf); - printf("\nSaved: %s", name); + if (stamp) + ok = BKE_imbuf_write_stamp(scene, camera, ibuf_arr[2], name, &rd->im_format); + else + ok = BKE_imbuf_write(ibuf_arr[2], name, &imf); + + printf("Saved: %s\n", name); } - + + /* imbuf knows which rects are not part of ibuf */ + for (i = 0; i < 3; i++) { + IMB_freeImBuf(ibuf_arr[i]); + } + } + } + + return ok; +} + +bool RE_WriteRenderViewsMovie(ReportList *reports, RenderResult *rr, Scene *scene, RenderData *rd, bMovieHandle *mh, + const size_t width, const size_t height, void **movie_ctx_arr, const size_t totvideos) +{ + bool is_mono; + bool ok = true; + + if (!rr) + return false; + + is_mono = BLI_listbase_count_ex(&rr->views, 2) < 2; + + if (is_mono || (scene->r.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) { + size_t view_id; + for (view_id = 0; view_id < totvideos; view_id++) { + bool do_free = false; + const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id); + ImBuf *ibuf = render_result_rect_to_ibuf(rr, &scene->r, view_id); + + /* note; the way it gets 32 bits rects is weak... */ + if (ibuf->rect == NULL) { + ibuf->rect = MEM_mapallocN(sizeof(int) * rr->rectx * rr->recty, "temp 32 bits rect"); + ibuf->mall |= IB_rect; + render_result_rect_get_pixels(rr, ibuf->rect, width, height, &scene->view_settings, &scene->display_settings, view_id); + do_free = true; + } + + IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, + &scene->display_settings, &scene->r.im_format); + + ok &= mh->append_movie(movie_ctx_arr[view_id], rd, scene->r.sfra, scene->r.cfra, + (int *) ibuf->rect, ibuf->x, ibuf->y, suffix, reports); + + if (do_free) { + MEM_freeN(ibuf->rect); + ibuf->rect = NULL; + ibuf->mall &= ~IB_rect; + } + /* imbuf knows which rects are not part of ibuf */ IMB_freeImBuf(ibuf); } + printf("Append frame %d\n", scene->r.cfra); + } + else { /* R_IMF_VIEWS_STEREO_3D */ + const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + ImBuf *ibuf_arr[3] = {NULL}; + bool do_free[2] = {false, false}; + size_t i; + + BLI_assert((totvideos == 1) && (scene->r.im_format.views_format == R_IMF_VIEWS_STEREO_3D)); + + for (i = 0; i < 2; i++) { + int view_id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name)); + ibuf_arr[i] = render_result_rect_to_ibuf(rr, &scene->r, view_id); + + /* note; the way it gets 32 bits rects is weak... */ + if (ibuf_arr[i]->rect == NULL) { + ibuf_arr[i]->rect = MEM_mapallocN(sizeof(int) * width * height, "temp 32 bits rect"); + ibuf_arr[i]->mall |= IB_rect; + render_result_rect_get_pixels(rr, ibuf_arr[i]->rect, width, height, &scene->view_settings, &scene->display_settings, view_id); + do_free[i] = true; + } + + IMB_colormanagement_imbuf_for_write(ibuf_arr[i], true, false, &scene->view_settings, + &scene->display_settings, &scene->r.im_format); + } + + ibuf_arr[2] = IMB_stereo3d_ImBuf(&scene->r.im_format, ibuf_arr[0], ibuf_arr[1]); + + ok = mh->append_movie(movie_ctx_arr[0], rd, scene->r.sfra, scene->r.cfra, (int *) ibuf_arr[2]->rect, + ibuf_arr[2]->x, ibuf_arr[2]->y, "", reports); + + for (i = 0; i < 2; i++) { + if (do_free[i]) { + MEM_freeN(ibuf_arr[i]->rect); + ibuf_arr[i]->rect = NULL; + ibuf_arr[i]->mall &= ~IB_rect; + } + + /* imbuf knows which rects are not part of ibuf */ + IMB_freeImBuf(ibuf_arr[i]); + } + } + + return ok; +} + +static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const size_t totvideos, const char *name_override) +{ + char name[FILE_MAX]; + RenderResult rres; + double render_time; + bool ok = true; + Object *camera = RE_GetCamera(re); + + RE_AcquireResultImageViews(re, &rres); + + /* write movie or image */ + if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { + RE_WriteRenderViewsMovie(re->reports, &rres, scene, &re->r, mh, re->rectx, re->recty, re->movie_ctx_arr, totvideos); + } + else { + if (name_override) + BLI_strncpy(name, name_override, sizeof(name)); + else + BKE_image_path_from_imformat( + name, scene->r.pic, bmain->name, scene->r.cfra, + &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL); + + /* write images as individual images or stereo */ + ok = RE_WriteRenderViewsImage(re->reports, &rres, scene, camera, true, name); } - RE_ReleaseResultImage(re); + RE_ReleaseResultImageViews(re, &rres); render_time = re->i.lastframetime; re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime; @@ -2987,20 +3364,51 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie return ok; } +static void get_videos_dimensions(Render *re, RenderData *rd, size_t *r_width, size_t *r_height) +{ + size_t width, height; + if (re->r.mode & R_BORDER) { + if ((re->r.mode & R_CROP) == 0) { + width = re->winx; + height = re->winy; + } + else { + width = re->rectx; + height = re->recty; + } + } + else { + width = re->rectx; + height = re->recty; + } + + BKE_scene_multiview_videos_dimensions_get(rd, width, height, r_width, r_height); +} + /* saves images to disk */ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_override, unsigned int lay_override, int sfra, int efra, int tfra) { RenderData rd = scene->r; - bMovieHandle *mh = BKE_movie_handle_get(scene->r.im_format.imtype); + bMovieHandle *mh = NULL; int cfrao = scene->r.cfra; int nfra, totrendered = 0, totskipped = 0; - + const size_t totvideos = BKE_scene_multiview_num_videos_get(&rd); + const bool is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype); + const bool is_multiview_name = ((scene->r.scemode & R_MULTIVIEW) != 0 && + (scene->r.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)); + BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT); /* do not fully call for each frame, it initializes & pops output window */ if (!render_initialize_from_main(re, &rd, bmain, scene, NULL, camera_override, lay_override, 0, 1)) return; + + /* we don't support Frame Server and streaming of individual views */ + if ((rd.im_format.imtype == R_IMF_IMTYPE_FRAMESERVER) && (totvideos > 1)) { + BKE_report(re->reports, RPT_ERROR, "Frame Server only support stereo output for multiview rendering"); + return; + } /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */ /* is also set by caller renderwin.c */ @@ -3008,31 +3416,33 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri re->flag |= R_ANIMATION; - if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { - int width, height; - if (re->r.mode & R_BORDER) { - if ((re->r.mode & R_CROP) == 0) { - width = re->winx; - height = re->winy; - } - else { - width = re->rectx; - height = re->recty; - } - } - else { - width = re->rectx; - height = re->recty; - } + if (is_movie) { + size_t i, width, height; + + get_videos_dimensions(re, &rd, &width, &height); + + mh = BKE_movie_handle_get(scene->r.im_format.imtype); + re->movie_ctx_arr = MEM_mallocN(sizeof(void *) * totvideos, "Movies' Context"); + + for (i = 0; i < totvideos; i++) { + const char *suffix = BKE_scene_multiview_view_id_suffix_get(&re->r, i); - /* last argument here depends on users really, but no users using preview have been found so far */ - if (!mh->start_movie(scene, &re->r, width, height, re->reports, false)) - G.is_break = true; + re->movie_ctx_arr[i] = mh->context_create(); + + if (!mh->start_movie(re->movie_ctx_arr[i], scene, &re->r, width, height, re->reports, false, suffix)) + G.is_break = true; + } } - if (mh->get_next_frame) { + if (mh && mh->get_next_frame) { + /* MULTIVIEW_TODO: + * in case a new video format is added that implements get_next_frame multiview has to be addressed + * or the error throwing for R_IMF_IMTYPE_FRAMESERVER has to be extended for those cases as well + */ + BLI_assert(totvideos < 2); + while (!(G.is_break == 1)) { - int nf = mh->get_next_frame(&re->r, re->reports); + int nf = mh->get_next_frame(re->movie_ctx_arr[0], &re->r, re->reports); if (nf >= 0 && nf >= scene->r.sfra && nf <= scene->r.efra) { scene->r.cfra = re->r.cfra = nf; @@ -3042,7 +3452,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri totrendered++; if (re->test_break(re->tbh) == 0) { - if (!do_write_image_or_movie(re, bmain, scene, mh, NULL)) + if (!do_write_image_or_movie(re, bmain, scene, mh, totvideos, NULL)) G.is_break = true; } @@ -3085,20 +3495,67 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri nfra += tfra; /* Touch/NoOverwrite options are only valid for image's */ - if (BKE_imtype_is_movie(scene->r.im_format.imtype) == 0) { + if (is_movie == false) { if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH)) BKE_image_path_from_imformat( name, scene->r.pic, bmain->name, scene->r.cfra, - &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true); + &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL); + + if (scene->r.mode & R_NO_OVERWRITE) { + if (!is_multiview_name) { + if (BLI_exists(name)) { + printf("skipping existing frame \"%s\"\n", name); + totskipped++; + continue; + } + } + else { + SceneRenderView *srv; + bool is_skip = false; + char filepath[FILE_MAX]; - if (scene->r.mode & R_NO_OVERWRITE && BLI_exists(name)) { - printf("skipping existing frame \"%s\"\n", name); - totskipped++; - continue; + for (srv = scene->r.views.first; srv; srv = srv->next) { + if (!BKE_scene_multiview_is_render_view_active(&scene->r, srv)) + continue; + + BKE_scene_multiview_filepath_get(srv, name, filepath); + + if (BLI_exists(filepath)) { + is_skip = true; + printf("skipping existing frame \"%s\" for view \"%s\"\n", filepath, srv->name); + } + } + + if (is_skip) { + totskipped++; + continue; + } + } } - if (scene->r.mode & R_TOUCH && !BLI_exists(name)) { - BLI_make_existing_file(name); /* makes the dir if its not there */ - BLI_file_touch(name); + + if (scene->r.mode & R_TOUCH) { + if (!is_multiview_name) { + if (!BLI_exists(name)) { + BLI_make_existing_file(name); /* makes the dir if its not there */ + BLI_file_touch(name); + } + } + else { + SceneRenderView *srv; + char filepath[FILE_MAX]; + + for (srv = scene->r.views.first; srv; srv = srv->next) { + if (!BKE_scene_multiview_is_render_view_active(&scene->r, srv)) + continue; + + BKE_scene_multiview_filepath_get(srv, name, filepath); + + if (!BLI_exists(filepath)) { + BLI_make_existing_file(filepath); /* makes the dir if its not there */ + BLI_file_touch(filepath); + } + } + } } } @@ -3113,7 +3570,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri if (re->test_break(re->tbh) == 0) { if (!G.is_break) - if (!do_write_image_or_movie(re, bmain, scene, mh, NULL)) + if (!do_write_image_or_movie(re, bmain, scene, mh, totvideos, NULL)) G.is_break = true; } else @@ -3121,10 +3578,30 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri if (G.is_break == true) { /* remove touched file */ - if (BKE_imtype_is_movie(scene->r.im_format.imtype) == 0) { - if ((scene->r.mode & R_TOUCH) && (BLI_file_size(name) == 0)) { - /* BLI_exists(name) is implicit */ - BLI_delete(name, false, false); + if (is_movie == false) { + if ((scene->r.mode & R_TOUCH)) { + if (!is_multiview_name) { + if ((BLI_file_size(name) == 0)) { + /* BLI_exists(name) is implicit */ + BLI_delete(name, false, false); + } + } + else { + SceneRenderView *srv; + char filepath[FILE_MAX]; + + for (srv = scene->r.views.first; srv; srv = srv->next) { + if (!BKE_scene_multiview_is_render_view_active(&scene->r, srv)) + continue; + + BKE_scene_multiview_filepath_get(srv, name, filepath); + + if ((BLI_file_size(filepath) == 0)) { + /* BLI_exists(filepath) is implicit */ + BLI_delete(filepath, false, false); + } + } + } } } @@ -3139,8 +3616,17 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri } /* end movie */ - if (BKE_imtype_is_movie(scene->r.im_format.imtype)) - mh->end_movie(); + if (is_movie) { + size_t i; + for (i = 0; i < totvideos; i++) { + mh->end_movie(re->movie_ctx_arr[i]); + mh->context_free(re->movie_ctx_arr[i]); + } + + if (re->movie_ctx_arr) { + MEM_freeN(re->movie_ctx_arr); + } + } if (totskipped && totrendered == 0) BKE_report(re->reports, RPT_INFO, "No frames rendered, skipped to not overwrite"); @@ -3238,13 +3724,22 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char { /* OCIO_TODO: assume layer was saved in defaule color space */ ImBuf *ibuf = IMB_loadiffname(filename, IB_rect, NULL); + RenderPass *rpass = NULL; + + /* multiview: since the API takes no 'view', we use the first combined pass found */ + for (rpass = layer->passes.first; rpass; rpass = rpass->next) + if (rpass->passtype == SCE_PASS_COMBINED) + break; + + if (rpass == NULL) + BKE_reportf(reports, RPT_ERROR, "RE_layer_load_from_file: no Combined pass found in the render layer '%s'", filename); if (ibuf && (ibuf->rect || ibuf->rect_float)) { if (ibuf->x == layer->rectx && ibuf->y == layer->recty) { if (ibuf->rect_float == NULL) IMB_float_from_rect(ibuf); - memcpy(layer->rectf, ibuf->rect_float, sizeof(float) * 4 * layer->rectx * layer->recty); + memcpy(rpass->rect, ibuf->rect_float, sizeof(float) * 4 * layer->rectx * layer->recty); } else { if ((ibuf->x - x >= layer->rectx) && (ibuf->y - y >= layer->recty)) { @@ -3257,7 +3752,7 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char if (ibuf_clip) { IMB_rectcpy(ibuf_clip, ibuf, 0, 0, x, y, layer->rectx, layer->recty); - memcpy(layer->rectf, ibuf_clip->rect_float, sizeof(float) * 4 * layer->rectx * layer->recty); + memcpy(rpass->rect, ibuf_clip->rect_float, sizeof(float) * 4 * layer->rectx * layer->recty); IMB_freeImBuf(ibuf_clip); } else { @@ -3345,3 +3840,21 @@ bool RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env, } } +/* used in the interface to decide whether to show layers */ +bool RE_layers_have_name(struct RenderResult *rr) +{ + switch (BLI_listbase_count_ex(&rr->layers, 2)) { + case 0: + return false; + break; + case 1: + return (((RenderLayer *)rr->layers.first)->name[0] != '\0'); + break; + default: + return true; + break; + } + return false; +} + + diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 6486844bacf..90f6eab0cc1 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -48,9 +48,8 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BKE_report.h" -#ifdef WITH_CYCLES_DEBUG -# include "BKE_scene.h" -#endif +#include "BKE_camera.h" +#include "BKE_scene.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -63,14 +62,32 @@ /********************************** Free *************************************/ +static void render_result_views_free(RenderResult *res) +{ + while (res->views.first) { + RenderView *rv = res->views.first; + BLI_remlink(&res->views, rv); + + if (rv->rect32) + MEM_freeN(rv->rect32); + + if (rv->rectz) + MEM_freeN(rv->rectz); + + if (rv->rectf) + MEM_freeN(rv->rectf); + + MEM_freeN(rv); + } +} + void render_result_free(RenderResult *res) { if (res == NULL) return; while (res->layers.first) { RenderLayer *rl = res->layers.first; - - if (rl->rectf) MEM_freeN(rl->rectf); + /* acolrect and scolrect are optionally allocated in shade_tile, only free here since it can be used for drawing */ if (rl->acolrect) MEM_freeN(rl->acolrect); if (rl->scolrect) MEM_freeN(rl->scolrect); @@ -85,7 +102,9 @@ void render_result_free(RenderResult *res) BLI_remlink(&res->layers, rl); MEM_freeN(rl); } - + + render_result_views_free(res); + if (res->rect32) MEM_freeN(res->rect32); if (res->rectz) @@ -115,13 +134,44 @@ void render_result_free_list(ListBase *lb, RenderResult *rr) } } -/********************************* Names *************************************/ +/********************************* multiview *************************************/ -/* 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 const char *get_pass_name(int passtype, int channel) +/* create a new views Listbase in rr without duplicating the memory pointers */ +void render_result_views_shallowcopy(RenderResult *dst, RenderResult *src) +{ + RenderView *rview; + + if (dst == NULL || src == NULL) + return; + + for (rview = src->views.first; rview; rview = rview->next) { + RenderView *rv; + + rv = MEM_mallocN(sizeof(RenderView), "new render view"); + BLI_addtail(&dst->views, rv); + + BLI_strncpy(rv->name, rview->name, sizeof(rv->name)); + rv->rectf = rview->rectf; + rv->rectz = rview->rectz; + rv->rect32 = rview->rect32; + } +} + +/* free the views created temporarily */ +void render_result_views_shallowdelete(RenderResult *rr) +{ + if (rr == NULL) + return; + + while (rr->views.first) { + RenderView *rv = rr->views.first; + BLI_remlink(&rr->views, rv); + MEM_freeN(rv); + } +} + +static const char *name_from_passtype(int passtype, int channel) { - if (passtype == SCE_PASS_COMBINED) { if (channel == -1) return "Combined"; if (channel == 0) return "Combined.R"; @@ -308,108 +358,131 @@ static const char *get_pass_name(int passtype, int channel) static int passtype_from_name(const char *str) { - - if (STREQ(str, "Combined")) + if (STRPREFIX(str, "Combined")) return SCE_PASS_COMBINED; - if (STREQ(str, "Depth")) + if (STRPREFIX(str, "Depth")) return SCE_PASS_Z; - if (STREQ(str, "Vector")) + if (STRPREFIX(str, "Vector")) return SCE_PASS_VECTOR; - if (STREQ(str, "Normal")) + if (STRPREFIX(str, "Normal")) return SCE_PASS_NORMAL; - if (STREQ(str, "UV")) + if (STRPREFIX(str, "UV")) return SCE_PASS_UV; - if (STREQ(str, "Color")) + if (STRPREFIX(str, "Color")) return SCE_PASS_RGBA; - if (STREQ(str, "Emit")) + if (STRPREFIX(str, "Emit")) return SCE_PASS_EMIT; - if (STREQ(str, "Diffuse")) + if (STRPREFIX(str, "Diffuse")) return SCE_PASS_DIFFUSE; - if (STREQ(str, "Spec")) + if (STRPREFIX(str, "Spec")) return SCE_PASS_SPEC; - if (STREQ(str, "Shadow")) + if (STRPREFIX(str, "Shadow")) return SCE_PASS_SHADOW; - if (STREQ(str, "AO")) + if (STRPREFIX(str, "AO")) return SCE_PASS_AO; - if (STREQ(str, "Env")) + if (STRPREFIX(str, "Env")) return SCE_PASS_ENVIRONMENT; - if (STREQ(str, "Indirect")) + if (STRPREFIX(str, "Indirect")) return SCE_PASS_INDIRECT; - if (STREQ(str, "Reflect")) + if (STRPREFIX(str, "Reflect")) return SCE_PASS_REFLECT; - if (STREQ(str, "Refract")) + if (STRPREFIX(str, "Refract")) return SCE_PASS_REFRACT; - if (STREQ(str, "IndexOB")) + if (STRPREFIX(str, "IndexOB")) return SCE_PASS_INDEXOB; - if (STREQ(str, "IndexMA")) + if (STRPREFIX(str, "IndexMA")) return SCE_PASS_INDEXMA; - if (STREQ(str, "Mist")) + if (STRPREFIX(str, "Mist")) return SCE_PASS_MIST; - if (STREQ(str, "RayHits")) + if (STRPREFIX(str, "RayHits")) return SCE_PASS_RAYHITS; - if (STREQ(str, "DiffDir")) + if (STRPREFIX(str, "DiffDir")) return SCE_PASS_DIFFUSE_DIRECT; - if (STREQ(str, "DiffInd")) + if (STRPREFIX(str, "DiffInd")) return SCE_PASS_DIFFUSE_INDIRECT; - if (STREQ(str, "DiffCol")) + if (STRPREFIX(str, "DiffCol")) return SCE_PASS_DIFFUSE_COLOR; - if (STREQ(str, "GlossDir")) + if (STRPREFIX(str, "GlossDir")) return SCE_PASS_GLOSSY_DIRECT; - if (STREQ(str, "GlossInd")) + if (STRPREFIX(str, "GlossInd")) return SCE_PASS_GLOSSY_INDIRECT; - if (STREQ(str, "GlossCol")) + if (STRPREFIX(str, "GlossCol")) return SCE_PASS_GLOSSY_COLOR; - if (STREQ(str, "TransDir")) + if (STRPREFIX(str, "TransDir")) return SCE_PASS_TRANSM_DIRECT; - if (STREQ(str, "TransInd")) + if (STRPREFIX(str, "TransInd")) return SCE_PASS_TRANSM_INDIRECT; - if (STREQ(str, "TransCol")) + if (STRPREFIX(str, "TransCol")) return SCE_PASS_TRANSM_COLOR; - if (STREQ(str, "SubsurfaceDir")) + if (STRPREFIX(str, "SubsurfaceDir")) return SCE_PASS_SUBSURFACE_DIRECT; - if (STREQ(str, "SubsurfaceInd")) + if (STRPREFIX(str, "SubsurfaceInd")) return SCE_PASS_SUBSURFACE_INDIRECT; - if (STREQ(str, "SubsurfaceCol")) + if (STRPREFIX(str, "SubsurfaceCol")) return SCE_PASS_SUBSURFACE_COLOR; return 0; } + +static void set_pass_name(char *passname, int passtype, int channel, const char *view) +{ + const char *end; + const char *token; + int len; + + const char *passtype_name = name_from_passtype(passtype, channel); + + if (view == NULL || view[0] == '\0') { + BLI_strncpy(passname, passtype_name, EXR_PASS_MAXNAME); + return; + } + + end = passtype_name + strlen(passtype_name); + len = IMB_exr_split_token(passtype_name, end, &token); + + if (len == strlen(passtype_name)) + sprintf(passname, "%s.%s", passtype_name, view); + else + sprintf(passname, "%.*s%s.%s", (int)(end-passtype_name) - len, passtype_name, view, token); +} + /********************************** New **************************************/ -static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype) +static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype, const char *viewname) { - const char *typestr = get_pass_name(passtype, 0); + const size_t view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name)); + const char *typestr = name_from_passtype(passtype, -1); RenderPass *rpass = MEM_callocN(sizeof(RenderPass), typestr); int rectsize = rr->rectx * rr->recty * channels; @@ -418,12 +491,16 @@ static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int rpass->channels = channels; rpass->rectx = rl->rectx; rpass->recty = rl->recty; - BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name)); + rpass->view_id = view_id; + + set_pass_name(rpass->name, rpass->passtype, -1, viewname); + BLI_strncpy(rpass->internal_name, typestr, sizeof(rpass->internal_name)); + BLI_strncpy(rpass->view, viewname, sizeof(rpass->view)); if (rl->exrhandle) { int a; for (a = 0; a < channels; a++) - IMB_exr_add_channel(rl->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL); + IMB_exr_add_channel(rl->exrhandle, rl->name, name_from_passtype(passtype, a), viewname, 0, 0, NULL); } else { float *rect; @@ -460,9 +537,10 @@ static RenderPass *render_layer_add_debug_pass(RenderResult *rr, RenderLayer *rl, int channels, int pass_type, - int debug_type) + int debug_type, + const char *view) { - RenderPass *rpass = render_layer_add_pass(rr, rl, channels, pass_type); + RenderPass *rpass = render_layer_add_pass(rr, rl, channels, pass_type, view); rpass->debug_type = debug_type; BLI_strncpy(rpass->name, debug_pass_type_name_get(debug_type), @@ -475,12 +553,14 @@ static RenderPass *render_layer_add_debug_pass(RenderResult *rr, /* will read info from Render *re to define layers */ /* called in threads */ /* re->winx,winy is coordinate space of entire image, partrct the part within */ -RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers, const char *layername) +RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers, const char *layername, const char *viewname) { RenderResult *rr; RenderLayer *rl; + RenderView *rv; SceneRenderLayer *srl; - int rectx, recty, nr; + int rectx, recty; + int nr, i; rectx = BLI_rcti_size_x(partrct); recty = BLI_rcti_size_y(partrct); @@ -505,6 +585,8 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf rr->do_exr_tile = true; } + render_result_views_new(rr, &re->r); + /* check renderdata for amount of layers */ for (nr = 0, srl = re->r.layers.first; srl; srl = srl->next, nr++) { @@ -538,84 +620,90 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf if (rr->do_exr_tile) { rl->display_buffer = MEM_mapallocN(rectx * recty * sizeof(unsigned int), "Combined display space rgba"); - rl->exrhandle = IMB_exr_get_handle(); - - IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.R", 0, 0, NULL); - IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.G", 0, 0, NULL); - IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.B", 0, 0, NULL); - IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.A", 0, 0, NULL); } - else - rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba"); - - if (srl->passflag & SCE_PASS_Z) - render_layer_add_pass(rr, rl, 1, SCE_PASS_Z); - if (srl->passflag & SCE_PASS_VECTOR) - render_layer_add_pass(rr, rl, 4, SCE_PASS_VECTOR); - if (srl->passflag & SCE_PASS_NORMAL) - render_layer_add_pass(rr, rl, 3, SCE_PASS_NORMAL); - if (srl->passflag & SCE_PASS_UV) - render_layer_add_pass(rr, rl, 3, SCE_PASS_UV); - if (srl->passflag & SCE_PASS_RGBA) - render_layer_add_pass(rr, rl, 4, SCE_PASS_RGBA); - if (srl->passflag & SCE_PASS_EMIT) - render_layer_add_pass(rr, rl, 3, SCE_PASS_EMIT); - if (srl->passflag & SCE_PASS_DIFFUSE) - render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE); - if (srl->passflag & SCE_PASS_SPEC) - render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC); - if (srl->passflag & SCE_PASS_AO) - render_layer_add_pass(rr, rl, 3, SCE_PASS_AO); - if (srl->passflag & SCE_PASS_ENVIRONMENT) - render_layer_add_pass(rr, rl, 3, SCE_PASS_ENVIRONMENT); - if (srl->passflag & SCE_PASS_INDIRECT) - render_layer_add_pass(rr, rl, 3, SCE_PASS_INDIRECT); - if (srl->passflag & SCE_PASS_SHADOW) - render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW); - if (srl->passflag & SCE_PASS_REFLECT) - render_layer_add_pass(rr, rl, 3, SCE_PASS_REFLECT); - if (srl->passflag & SCE_PASS_REFRACT) - render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT); - if (srl->passflag & SCE_PASS_INDEXOB) - render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB); - if (srl->passflag & SCE_PASS_INDEXMA) - render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMA); - if (srl->passflag & SCE_PASS_MIST) - render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST); - if (rl->passflag & SCE_PASS_RAYHITS) - render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS); - if (srl->passflag & SCE_PASS_DIFFUSE_DIRECT) - render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_DIRECT); - if (srl->passflag & SCE_PASS_DIFFUSE_INDIRECT) - render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_INDIRECT); - if (srl->passflag & SCE_PASS_DIFFUSE_COLOR) - render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_COLOR); - if (srl->passflag & SCE_PASS_GLOSSY_DIRECT) - render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_DIRECT); - if (srl->passflag & SCE_PASS_GLOSSY_INDIRECT) - render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_INDIRECT); - if (srl->passflag & SCE_PASS_GLOSSY_COLOR) - render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_COLOR); - if (srl->passflag & SCE_PASS_TRANSM_DIRECT) - render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_DIRECT); - if (srl->passflag & SCE_PASS_TRANSM_INDIRECT) - render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_INDIRECT); - if (srl->passflag & SCE_PASS_TRANSM_COLOR) - render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_COLOR); - if (srl->passflag & SCE_PASS_SUBSURFACE_DIRECT) - render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_DIRECT); - if (srl->passflag & SCE_PASS_SUBSURFACE_INDIRECT) - render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_INDIRECT); - if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR) - render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_COLOR); + + for (rv = rr->views.first; rv; rv = rv->next) { + const char *view = rv->name; + + if (viewname && viewname[0]) + if (!STREQ(view, viewname)) + continue; + + if (rr->do_exr_tile) + IMB_exr_add_view(rl->exrhandle, view); + + /* a renderlayer should always have a Combined pass*/ + render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view); + + if (srl->passflag & SCE_PASS_Z) + render_layer_add_pass(rr, rl, 1, SCE_PASS_Z, view); + if (srl->passflag & SCE_PASS_VECTOR) + render_layer_add_pass(rr, rl, 4, SCE_PASS_VECTOR, view); + if (srl->passflag & SCE_PASS_NORMAL) + render_layer_add_pass(rr, rl, 3, SCE_PASS_NORMAL, view); + if (srl->passflag & SCE_PASS_UV) + render_layer_add_pass(rr, rl, 3, SCE_PASS_UV, view); + if (srl->passflag & SCE_PASS_RGBA) + render_layer_add_pass(rr, rl, 4, SCE_PASS_RGBA, view); + if (srl->passflag & SCE_PASS_EMIT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_EMIT, view); + if (srl->passflag & SCE_PASS_DIFFUSE) + render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE, view); + if (srl->passflag & SCE_PASS_SPEC) + render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC, view); + if (srl->passflag & SCE_PASS_AO) + render_layer_add_pass(rr, rl, 3, SCE_PASS_AO, view); + if (srl->passflag & SCE_PASS_ENVIRONMENT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_ENVIRONMENT, view); + if (srl->passflag & SCE_PASS_INDIRECT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_INDIRECT, view); + if (srl->passflag & SCE_PASS_SHADOW) + render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW, view); + if (srl->passflag & SCE_PASS_REFLECT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_REFLECT, view); + if (srl->passflag & SCE_PASS_REFRACT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT, view); + if (srl->passflag & SCE_PASS_INDEXOB) + render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB, view); + if (srl->passflag & SCE_PASS_INDEXMA) + render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMA, view); + if (srl->passflag & SCE_PASS_MIST) + render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST, view); + if (rl->passflag & SCE_PASS_RAYHITS) + render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS, view); + if (srl->passflag & SCE_PASS_DIFFUSE_DIRECT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_DIRECT, view); + if (srl->passflag & SCE_PASS_DIFFUSE_INDIRECT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_INDIRECT, view); + if (srl->passflag & SCE_PASS_DIFFUSE_COLOR) + render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_COLOR, view); + if (srl->passflag & SCE_PASS_GLOSSY_DIRECT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_DIRECT, view); + if (srl->passflag & SCE_PASS_GLOSSY_INDIRECT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_INDIRECT, view); + if (srl->passflag & SCE_PASS_GLOSSY_COLOR) + render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_COLOR, view); + if (srl->passflag & SCE_PASS_TRANSM_DIRECT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_DIRECT, view); + if (srl->passflag & SCE_PASS_TRANSM_INDIRECT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_INDIRECT, view); + if (srl->passflag & SCE_PASS_TRANSM_COLOR) + render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_COLOR, view); + if (srl->passflag & SCE_PASS_SUBSURFACE_DIRECT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_DIRECT, view); + if (srl->passflag & SCE_PASS_SUBSURFACE_INDIRECT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_INDIRECT, view); + if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR) + render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_COLOR, view); #ifdef WITH_CYCLES_DEBUG - if (BKE_scene_use_new_shading_nodes(re->scene)) { - render_layer_add_debug_pass(rr, rl, 1, SCE_PASS_DEBUG, - RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS); - } + if (BKE_scene_use_new_shading_nodes(re->scene)) { + render_layer_add_debug_pass(rr, rl, 1, SCE_PASS_DEBUG, + RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS, view); + } #endif + } } /* sss, previewrender and envmap don't do layers, so we make a default one */ if (BLI_listbase_is_empty(&rr->layers) && !(layername && layername[0])) { @@ -628,18 +716,27 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf /* duplicate code... */ if (rr->do_exr_tile) { rl->display_buffer = MEM_mapallocN(rectx * recty * sizeof(unsigned int), "Combined display space rgba"); - rl->exrhandle = IMB_exr_get_handle(); - - IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.R", 0, 0, NULL); - IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.G", 0, 0, NULL); - IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.B", 0, 0, NULL); - IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.A", 0, 0, NULL); } - else { - rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba"); + + for (rv = rr->views.first; rv; rv = rv->next) { + const char *view = rv->name; + + if (viewname && viewname[0]) + if (strcmp(view, viewname) != 0) + continue; + + if (rr->do_exr_tile) { + IMB_exr_add_view(rl->exrhandle, view); + + for (i=0; i < 4; i++) + IMB_exr_add_channel(rl->exrhandle, rl->name, name_from_passtype(SCE_PASS_COMBINED, i), view, 0, 0, NULL); + } + else { + render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view); + } } - + /* note, this has to be in sync with scene.c */ rl->lay = (1 << 20) - 1; rl->layflag = 0x7FFF; /* solid ztra halo strand */ @@ -657,15 +754,15 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf } /* allocate osa new results for samples */ -RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *partrct, int crop, int savebuffers) +RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *partrct, int crop, int savebuffers, const char *viewname) { int a; if (re->osa == 0) - return render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS); + return render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS, viewname); for (a = 0; a < re->osa; a++) { - RenderResult *rr = render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS); + RenderResult *rr = render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS, viewname); BLI_addtail(lb, rr); rr->sample_nr = a; } @@ -686,28 +783,98 @@ static void *ml_addlayer_cb(void *base, const char *str) return rl; } -static void ml_addpass_cb(void *UNUSED(base), void *lay, const char *str, float *rect, int totchan, const char *chan_id) +static void ml_addpass_cb(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id, const char *view) { + RenderResult *rr = base; 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; a < totchan; a++) rpass->chan_id[a] = chan_id[a]; - + rpass->rect = rect; + if (view[0] != '\0') { + BLI_snprintf(rpass->name, sizeof(rpass->name), "%s.%s", str, view); + rpass->view_id = BLI_findstringindex(&rr->views, view, offsetof(RenderView, name)); + } + else { + BLI_strncpy(rpass->name, str, sizeof(rpass->name)); + rpass->view_id = 0; + } + + BLI_strncpy(rpass->view, view, sizeof(rpass->view)); + BLI_strncpy(rpass->internal_name, str, sizeof(rpass->internal_name)); } -/* from imbuf, if a handle was returned we convert this to render result */ +static void *ml_addview_cb(void *base, const char *str) +{ + RenderResult *rr = base; + RenderView *rv; + + rv = MEM_callocN(sizeof(RenderView), "new render view"); + BLI_strncpy(rv->name, str, EXR_VIEW_MAXNAME); + + /* For stereo drawing we need to ensure: + * STEREO_LEFT_NAME == STEREO_LEFT_ID and + * STEREO_RIGHT_NAME == STEREO_RIGHT_ID */ + + if (STREQ(str, STEREO_LEFT_NAME)) { + BLI_addhead(&rr->views, rv); + } + else if (STREQ(str, STEREO_RIGHT_NAME)) { + RenderView *left_rv = BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name)); + + if (left_rv == NULL) { + BLI_addhead(&rr->views, rv); + } + else { + BLI_insertlinkafter(&rr->views, left_rv, rv); + } + } + else { + BLI_addtail(&rr->views, rv); + } + + return rv; +} + +static int order_render_passes(const void *a, const void *b) +{ + // 1 if a is after b + RenderPass *rpa = (RenderPass *) a; + RenderPass *rpb = (RenderPass *) b; + + if (rpa->passtype > rpb->passtype) + return 1; + else if (rpa->passtype < rpb->passtype) + return 0; + + /* they have the same type */ + /* left first */ + if (STREQ(rpa->view, STEREO_LEFT_NAME)) + return 0; + else if (STREQ(rpb->view, STEREO_LEFT_NAME)) + return 1; + + /* right second */ + if (STREQ(rpa->view, STEREO_RIGHT_NAME)) + return 0; + else if (STREQ(rpb->view, STEREO_RIGHT_NAME)) + return 1; + + /* remaining in ascending id order */ + return (rpa->view_id < rpb->view_id); +} + +/* from imbuf, if a handle was returned and it's not a singlelayer multiview we convert this to render result */ RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty) { RenderResult *rr = MEM_callocN(sizeof(RenderResult), __func__); @@ -718,13 +885,17 @@ RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace rr->rectx = rectx; rr->recty = recty; - IMB_exr_multilayer_convert(exrhandle, rr, ml_addlayer_cb, ml_addpass_cb); + IMB_exr_multilayer_convert(exrhandle, rr, ml_addview_cb, ml_addlayer_cb, ml_addpass_cb); for (rl = rr->layers.first; rl; rl = rl->next) { + int c=0; rl->rectx = rectx; rl->recty = recty; + BLI_listbase_sort(&rl->passes, order_render_passes); + for (rpass = rl->passes.first; rpass; rpass = rpass->next) { + printf("%d: %s\n", c++, rpass->name); rpass->rectx = rectx; rpass->recty = recty; @@ -738,6 +909,33 @@ RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace return rr; } +void render_result_views_new(RenderResult *rr, RenderData *rd) +{ + SceneRenderView *srv; + RenderView *rv; + + /* clear previously existing views - for sequencer */ + render_result_views_free(rr); + + /* check renderdata for amount of views */ + if ((rd->scemode & R_MULTIVIEW)) { + for (srv = rd->views.first; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) continue; + + rv = MEM_callocN(sizeof(RenderView), "new render view"); + BLI_addtail(&rr->views, rv); + + BLI_strncpy(rv->name, srv->name, sizeof(rv->name)); + } + } + + /* we always need at least one view */ + if (BLI_listbase_count_ex(&rr->views, 1) == 0) { + rv = MEM_callocN(sizeof(RenderView), "new render view"); + BLI_addtail(&rr->views, rv); + } +} + /*********************************** Merge ***********************************/ static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize) @@ -783,16 +981,19 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart) for (rl = rr->layers.first; rl; rl = rl->next) { rlp = RE_GetRenderLayer(rrpart, rl->name); if (rlp) { - /* combined */ - if (rl->rectf && rlp->rectf) - do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4); - /* passes are allocated in sync */ for (rpass = rl->passes.first, rpassp = rlp->passes.first; rpass && rpassp; - rpass = rpass->next, rpassp = rpassp->next) + rpass = rpass->next) { + /* renderresult have all passes, renderpart only the active view's passes */ + if (strcmp(rpassp->name, rpass->name) != 0) + continue; + do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels); + + /* manually get next render pass */ + rpassp = rpassp->next; } } } @@ -801,7 +1002,7 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart) /* for passes read from files, these have names stored */ static char *make_pass_name(RenderPass *rpass, int chan) { - static char name[16]; + static char name[EXR_PASS_MAXNAME]; int len; BLI_strncpy(name, rpass->name, EXR_PASS_MAXNAME); @@ -813,65 +1014,111 @@ static char *make_pass_name(RenderPass *rpass, int chan) return name; } -/* filename already made absolute */ -/* called from within UI, saves both rendered result as a file-read result */ -bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, int compress) +/* called from within UI and render pipeline, saves both rendered result as a file-read result + * if multiview is true saves all views in a multiview exr + * else if view is not NULL saves single view + * else saves stereo3d + */ +bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, ImageFormatData *imf, const bool multiview, const char *view) { RenderLayer *rl; RenderPass *rpass; + RenderView *rview; void *exrhandle = IMB_exr_get_handle(); - bool success; - - BLI_make_existing_file(filename); - - /* 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); + bool success = false; + int a, nr; + const char *chan_view = NULL; + int compress = (imf ? imf->exr_codec : 0); + size_t width, height; + + const bool is_mono = view && !multiview; + + width = rr->rectx; + height = rr->recty; + + if (imf && imf->imtype == R_IMF_IMTYPE_OPENEXR && multiview) { + /* single layer OpenEXR */ + const char *RGBAZ[] = {"R", "G", "B", "A", "Z"}; + for (nr = 0, rview = rr->views.first; rview; rview = rview->next, nr++) { + IMB_exr_add_view(exrhandle, rview->name); + + if (rview->rectf) { + for (a = 0; a < 4; a++) + IMB_exr_add_channel(exrhandle, "", RGBAZ[a], + rview->name, 4, 4 * width, rview->rectf + a); + if (rview->rectz) + IMB_exr_add_channel(exrhandle, "", RGBAZ[4], + rview->name, 1, width, rview->rectz); + } + } } - - /* 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; a < xstride; a++) { - IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), - xstride, xstride * rr->rectx, rl->rectf + a); + else { + for (nr = 0, rview = rr->views.first; rview; rview = rview->next, nr++) { + if (is_mono) { + if (!STREQ(view, rview->name)) { + continue; + } + chan_view = ""; + } + else { + /* if rendered only one view, we treat as a a non-view render */ + chan_view = rview->name; + } + + IMB_exr_add_view(exrhandle, rview->name); + + if (rview->rectf) { + for (a = 0; a < 4; a++) + IMB_exr_add_channel(exrhandle, "Composite", name_from_passtype(SCE_PASS_COMBINED, a), + chan_view, 4, 4 * width, rview->rectf + a); } } - - /* passes are allocated in sync */ - for (rpass = rl->passes.first; rpass; rpass = rpass->next) { - int a, xstride = rpass->channels; - for (a = 0; a < xstride; a++) { - if (rpass->passtype) { - IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), - xstride, xstride * rr->rectx, rpass->rect + a); + + /* add layers/passes and assign channels */ + for (rl = rr->layers.first; rl; rl = rl->next) { + + /* passes are allocated in sync */ + for (rpass = rl->passes.first; rpass; rpass = rpass->next) { + const int xstride = rpass->channels; + + if (is_mono) { + if (!STREQ(view, rpass->view)) { + continue; + } + chan_view = ""; } else { - IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), - xstride, xstride * rr->rectx, rpass->rect + a); + /* if rendered only one view, we treat as a a non-view render */ + chan_view = (nr > 1 ? rpass->view :""); + } + + for (a = 0; a < xstride; a++) { + + if (rpass->passtype) { + IMB_exr_add_channel(exrhandle, rl->name, name_from_passtype(rpass->passtype, a), chan_view, + xstride, xstride * width, rpass->rect + a); + } + else { + IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), chan_view, + xstride, xstride * width, rpass->rect + a); + } } } } } - /* when the filename has no permissions, this can fail */ - if (IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty, compress)) { + BLI_make_existing_file(filename); + + if (IMB_exr_begin_write(exrhandle, filename, width, height, compress)) { IMB_exr_write_channels(exrhandle); - success = true; } else { /* TODO, get the error from openexr's exception */ BKE_report(reports, RPT_ERROR, "Error writing render result (see console)"); success = false; } - IMB_exr_close(exrhandle); + IMB_exr_close(exrhandle); return success; } @@ -932,7 +1179,7 @@ void render_result_single_layer_end(Render *re) /************************* EXR Tile File Rendering ***************************/ -static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart) +static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, const char *viewname) { RenderLayer *rlp, *rl; RenderPass *rpassp; @@ -955,21 +1202,17 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart) else { offs = 0; } - - /* combined */ - if (rlp->rectf) { - int a, xstride = 4; - for (a = 0; a < xstride; a++) { - IMB_exr_set_channel(rl->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a), - xstride, xstride * rrpart->rectx, rlp->rectf + a + xstride * offs); - } - } - + /* passes are allocated in sync */ for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) { - int a, xstride = rpassp->channels; + const int xstride = rpassp->channels; + int a; + char passname[EXR_PASS_MAXNAME]; + for (a = 0; a < xstride; a++) { - IMB_exr_set_channel(rl->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), + set_pass_name(passname, rpassp->passtype, a, rpassp->view); + + IMB_exr_set_channel(rl->exrhandle, rlp->name, passname, xstride, xstride * rrpart->rectx, rpassp->rect + a + xstride * offs); } } @@ -988,7 +1231,7 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart) continue; } - IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0); + IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, viewname); } BLI_unlock_thread(LOCK_IMAGE); @@ -1002,13 +1245,13 @@ static void save_empty_result_tiles(Render *re) for (rr = re->result; rr; rr = rr->next) { for (rl = rr->layers.first; rl; rl = rl->next) { - IMB_exrtile_clear_channels(rl->exrhandle); + IMB_exr_clear_channels(rl->exrhandle); for (pa = re->parts.first; pa; pa = pa->next) { if (pa->status != PART_STATUS_READY) { int party = pa->disprect.ymin - re->disprect.ymin + pa->crop; int partx = pa->disprect.xmin - re->disprect.xmin + pa->crop; - IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0); + IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, re->viewname); } } } @@ -1055,10 +1298,10 @@ void render_result_exr_file_end(Render *re) } /* save part into exr file */ -void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart) +void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart, const char *viewname) { for (; rr && rrpart; rr = rr->next, rrpart = rrpart->next) - save_render_result_tile(rr, rrpart); + save_render_result_tile(rr, rrpart, viewname); } /* path to temporary exr file */ @@ -1088,7 +1331,7 @@ int render_result_exr_file_read_sample(Render *re, int sample) bool success = true; RE_FreeRenderResult(re->result); - re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS); + re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); for (rl = re->result->layers.first; rl; rl = rl->next) { render_result_exr_file_path(re->scene, rl->name, sample, str); @@ -1129,23 +1372,20 @@ int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, c for (rl = rr->layers.first; rl; rl = rl->next) { if (rl_single && rl_single != rl) continue; - - /* combined */ - if (rl->rectf) { - int a, xstride = 4; - for (a = 0; a < xstride; a++) - IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), - xstride, xstride * 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; a < xstride; a++) - IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), + const int xstride = rpass->channels; + int a; + char passname[EXR_PASS_MAXNAME]; + + for (a = 0; a < xstride; a++) { + set_pass_name(passname, rpass->passtype, a, rpass->view); + IMB_exr_set_channel(exrhandle, rl->name, passname, xstride, xstride * rectx, rpass->rect + a); + } - BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name)); + set_pass_name(rpass->name, rpass->passtype, -1, rpass->view); } } @@ -1191,7 +1431,8 @@ void render_result_exr_file_cache_write(Render *re) render_result_exr_file_cache_path(re->scene, root, str); printf("Caching exr file, %dx%d, %s\n", rr->rectx, rr->recty, str); - RE_WriteRenderResult(NULL, rr, str, 0); + + RE_WriteRenderResult(NULL, rr, str, NULL, true, NULL); } /* For cache, makes exact copy of render result */ @@ -1201,7 +1442,7 @@ bool render_result_exr_file_cache_read(Render *re) char *root = U.render_cachedir; RE_FreeRenderResult(re->result); - re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS); + re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); /* First try cache. */ render_result_exr_file_cache_path(re->scene, root, str); @@ -1216,14 +1457,14 @@ bool render_result_exr_file_cache_read(Render *re) /*************************** Combined Pixel Rect *****************************/ -ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd) +ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd, const int view_id) { ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0); /* if not exists, BKE_imbuf_write makes one */ - ibuf->rect = (unsigned int *)rr->rect32; - ibuf->rect_float = rr->rectf; - ibuf->zbuf_float = rr->rectz; + ibuf->rect = (unsigned int *) RE_RenderViewGetRect32(rr, view_id); + ibuf->rect_float = RE_RenderViewGetRectf(rr, view_id); + ibuf->zbuf_float = RE_RenderViewGetRectz(rr, view_id); /* float factor for random dither, imbuf takes care of it */ ibuf->dither = rd->dither_intensity; @@ -1259,53 +1500,73 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd) return ibuf; } -void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBuf *ibuf) +void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBuf *ibuf, const int view_id) { + RenderView *rv = BLI_findlink(&rr->views, view_id); + if (ibuf->rect_float) { - if (!rr->rectf) - rr->rectf = MEM_mallocN(4 * sizeof(float) * rr->rectx * rr->recty, "render_seq rectf"); + if (!rv->rectf) + rv->rectf = MEM_mallocN(4 * sizeof(float) * rr->rectx * rr->recty, "render_seq rectf"); - memcpy(rr->rectf, ibuf->rect_float, 4 * sizeof(float) * rr->rectx * rr->recty); + memcpy(rv->rectf, ibuf->rect_float, 4 * sizeof(float) * rr->rectx * rr->recty); /* TSK! Since sequence render doesn't free the *rr render result, the old rect32 * can hang around when sequence render has rendered a 32 bits one before */ - if (rr->rect32) { - MEM_freeN(rr->rect32); - rr->rect32 = NULL; + if (rv->rect32) { + MEM_freeN(rv->rect32); + rv->rect32 = NULL; } } else if (ibuf->rect) { - if (!rr->rect32) - rr->rect32 = MEM_mallocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect"); + if (!rv->rect32) + rv->rect32 = MEM_mallocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect"); - memcpy(rr->rect32, ibuf->rect, 4 * rr->rectx * rr->recty); + memcpy(rv->rect32, ibuf->rect, 4 * rr->rectx * rr->recty); /* Same things as above, old rectf can hang around from previous render. */ + if (rv->rectf) { + MEM_freeN(rv->rectf); + rv->rectf = NULL; + } + } + + /* clean up non-view buffers */ + if (rr) { if (rr->rectf) { MEM_freeN(rr->rectf); rr->rectf = NULL; } + + if (rr->rect32) { + MEM_freeN(rr->rect32); + rr->rect32 = NULL; + } } } -void render_result_rect_fill_zero(RenderResult *rr) +void render_result_rect_fill_zero(RenderResult *rr, const int view_id) { - if (rr->rectf) - memset(rr->rectf, 0, 4 * sizeof(float) * rr->rectx * rr->recty); - else if (rr->rect32) - memset(rr->rect32, 0, 4 * rr->rectx * rr->recty); + RenderView *rv = BLI_findlink(&rr->views, view_id); + + if (rv->rectf) + memset(rv->rectf, 0, 4 * sizeof(float) * rr->rectx * rr->recty); + else if (rv->rect32) + memset(rv->rect32, 0, 4 * rr->rectx * rr->recty); else - rr->rect32 = MEM_callocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect"); + rv->rect32 = MEM_callocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect"); } void render_result_rect_get_pixels(RenderResult *rr, unsigned int *rect, int rectx, int recty, - const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) + const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, + const int view_id) { if (rr->rect32) { - memcpy(rect, rr->rect32, sizeof(int) * rr->rectx * rr->recty); + int *rect32 = RE_RenderViewGetRect32(rr, view_id); + memcpy(rect, (rect32 ? rect32 : rr->rect32), sizeof(int) * rr->rectx * rr->recty); } else if (rr->rectf) { - IMB_display_buffer_transform_apply((unsigned char *) rect, rr->rectf, rr->rectx, rr->recty, 4, + float *rectf = RE_RenderViewGetRectf(rr, view_id); + IMB_display_buffer_transform_apply((unsigned char *) rect, (rectf ? rectf : rr->rectf), rr->rectx, rr->recty, 4, view_settings, display_settings, true); } else @@ -1313,3 +1574,75 @@ void render_result_rect_get_pixels(RenderResult *rr, unsigned int *rect, int rec memset(rect, 0, sizeof(int) * rectx * recty); } + +/*************************** multiview functions *****************************/ + +bool RE_HasFakeLayer(RenderResult *res) +{ + RenderView *rv; + + if (res == NULL) + return false; + + rv = res->views.first; + if (rv == NULL) + return false; + + return (rv->rect32 || rv->rectf); +} + +bool RE_RenderResult_is_stereo(RenderResult *res) +{ + if (! BLI_findstring(&res->views, STEREO_LEFT_NAME, offsetof(RenderView, name))) + return false; + + if (! BLI_findstring(&res->views, STEREO_RIGHT_NAME, offsetof(RenderView, name))) + return false; + + return true; +} + +void RE_RenderViewSetRectf(RenderResult *res, const int view_id, float *rect) +{ + RenderView *rv = BLI_findlink(&res->views, view_id); + if (rv) { + rv->rectf = rect; + } +} + +void RE_RenderViewSetRectz(RenderResult *res, const int view_id, float *rect) +{ + RenderView *rv = BLI_findlink(&res->views, view_id); + if (rv) { + rv->rectz = rect; + } +} + +float *RE_RenderViewGetRectz(RenderResult *res, const int view_id) +{ + RenderView *rv = BLI_findlink(&res->views, view_id); + if (rv) { + return rv->rectz; + } + return res->rectz; +} + +float *RE_RenderViewGetRectf(RenderResult *res, const int view_id) +{ + RenderView *rv = BLI_findlink(&res->views, view_id); + if (rv) { + return rv->rectf; + } + return res->rectf; +} + +int *RE_RenderViewGetRect32(RenderResult *res, const int view_id) +{ + RenderView *rv = BLI_findlink(&res->views, view_id); + if (rv) { + return rv->rect32; + } + return res->rect32; +} + + diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 5b054005bac..99611a9c5a8 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -181,8 +181,10 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in if (fullsample) { for (sample=0; samplemask & (1 << sample)) - addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add); + if (ps->mask & (1 << sample)) { + float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + addalphaAddfacFloat(pass + od*4, col, har->add); + } } else { fac= ((float)amountm)/(float)R.osa; @@ -214,8 +216,10 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in if (fullsample) { for (sample=0; samplerectf + od*4, col, har->add); + if (!(mask & (1 << sample))) { + float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + addalphaAddfacFloat(pass + od*4, col, har->add); + } } else { col[0]= accol[0]; @@ -223,8 +227,10 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in col[2]= accol[2]; col[3]= accol[3]; - for (sample=0; samplerectf + od*4, col, har->add); + for (sample=0; sampleadd); + } } } @@ -305,8 +311,10 @@ static void halo_tile(RenderPart *pa, RenderLayer *rl) zz= calchalo_z(har, *rz); if ((zz> har->zs) || (har->mat && (har->mat->mode & MA_HALO_SOFT))) { if (shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec)) { - for (sample=0; samplerectf + od*4, col, har->add); + for (sample=0; sampleadd); + } } } } @@ -359,7 +367,8 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) if (fullsample) { for (sample=0; samplemask & (1 << sample)) { - pass= rlpp[sample]->rectf + od*4; + pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + pass += od * 4; pass[0]+= col[0]; pass[1]+= col[1]; pass[2]+= col[2]; @@ -370,7 +379,8 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) } else { fac= ((float)count)/(float)R.osa; - pass= rl->rectf + od*4; + pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + pass += od * 4; pass[0]+= fac*col[0]; pass[1]+= fac*col[1]; pass[2]+= fac*col[2]; @@ -390,7 +400,9 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) if (fullsample) { for (sample=0; samplerectf + od*4; + + pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + pass += od * 4; pass[0]+= col[0]; pass[1]+= col[1]; pass[2]+= col[2]; @@ -401,7 +413,8 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) } else { fac= ((float)R.osa-totsamp)/(float)R.osa; - pass= rl->rectf + od*4; + pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + pass += od * 4; pass[0]+= fac*col[0]; pass[1]+= fac*col[1]; pass[2]+= fac*col[2]; @@ -420,7 +433,8 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) renderspothalo(&shi, col, 1.0f); for (sample=0; samplerectf + od*4; + pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + pass += od * 4; pass[0]+= col[0]; pass[1]+= col[1]; pass[2]+= col[2]; @@ -444,14 +458,14 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, { RenderPass *rpass; - /* combined rgb */ - add_filt_fmask(curmask, shr->combined, rl->rectf + 4*offset, rectx); - for (rpass= rl->passes.first; rpass; rpass= rpass->next) { float *fp, *col= NULL; int pixsize= 3; switch (rpass->passtype) { + case SCE_PASS_COMBINED: + add_filt_fmask(curmask, shr->combined, rpass->rect + 4*offset, rectx); + break; case SCE_PASS_Z: fp= rpass->rect + offset; *fp= shr->z; @@ -555,15 +569,16 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult { RenderPass *rpass; float *fp; - - fp= rl->rectf + 4*offset; - copy_v4_v4(fp, shr->combined); - + for (rpass= rl->passes.first; rpass; rpass= rpass->next) { float *col= NULL, uvcol[3]; int a, pixsize= 3; switch (rpass->passtype) { + case SCE_PASS_COMBINED: + /* copy combined to use for preview */ + copy_v4_v4(rpass->rect + 4*offset, shr->combined); + break; case SCE_PASS_Z: fp= rpass->rect + offset; *fp= shr->z; @@ -681,7 +696,8 @@ static void sky_tile(RenderPart *pa, RenderLayer *rl) bool done = false; for (sample= 0; samplerectf + od; + float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + pass += od; if (pass[3]<1.0f) { @@ -742,8 +758,8 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl) int sample; for (sample=0; samplerectf + 4*od; + const float *zrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_Z, R.viewname) + od; + float *rgbrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname) + 4*od; float rgb[3] = {0}; bool done = false; @@ -978,8 +994,8 @@ static void clamp_alpha_rgb_range(RenderPart *pa, RenderLayer *rl) return; for (sample= 0; samplerectf; - + float *rectf = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) { rectf[0] = MAX2(rectf[0], 0.0f); rectf[1] = MAX2(rectf[1], 0.0f); @@ -1060,7 +1076,7 @@ static void reset_sky_speed(RenderPart *pa, RenderLayer *rl) totsample= get_sample_layers(pa, rl, rlpp); for (sample= 0; samplerectx*pa->recty - 1; a>=0; a--) @@ -1171,6 +1187,8 @@ void zbufshadeDA_tile(RenderPart *pa) pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); for (rl= rr->layers.first; rl; rl= rl->next) { + float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK)) pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask"); @@ -1211,7 +1229,7 @@ void zbufshadeDA_tile(RenderPart *pa) if (R.flag & R_ZTRA || R.totstrand) { if (rl->layflag & (SCE_LAY_ZTRA|SCE_LAY_STRAND)) { if (pa->fullresult.first) { - zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist); + zbuffer_transp_shade(pa, rl, rect, &psmlist); } else { unsigned short *ztramask, *solidmask= NULL; /* 16 bits, MAX_OSA */ @@ -1220,9 +1238,9 @@ void zbufshadeDA_tile(RenderPart *pa) rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer"); /* swap for live updates, and it is used in zbuf.c!!! */ - SWAP(float *, rl->acolrect, rl->rectf); - ztramask= zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist); - SWAP(float *, rl->acolrect, rl->rectf); + SWAP(float *, rl->acolrect, rect); + ztramask = zbuffer_transp_shade(pa, rl, rect, &psmlist); + SWAP(float *, rl->acolrect, rect); /* zbuffer transp only returns ztramask if there's solid rendered */ if (ztramask) @@ -1231,7 +1249,8 @@ void zbufshadeDA_tile(RenderPart *pa) if (ztramask && solidmask) { unsigned short *sps= solidmask, *spz= ztramask; unsigned short fullmask= (1<rectf; float *acol= rl->acolrect; + float *fcol= rect; + float *acol= rl->acolrect; int x; for (x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4, sps++, spz++) { @@ -1242,7 +1261,8 @@ void zbufshadeDA_tile(RenderPart *pa) } } else { - float *fcol= rl->rectf; float *acol= rl->acolrect; + float *fcol= rect; + float *acol= rl->acolrect; int x; for (x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) { addAlphaOverFloat(fcol, acol); @@ -1265,7 +1285,7 @@ void zbufshadeDA_tile(RenderPart *pa) /* extra layers */ if (rl->layflag & SCE_LAY_EDGE) if (R.r.mode & R_EDGE) - edge_enhance_add(pa, rl->rectf, edgerect); + edge_enhance_add(pa, rect, edgerect); if (rl->passflag & SCE_PASS_VECTOR) reset_sky_speed(pa, rl); @@ -1319,6 +1339,7 @@ void zbufshade_tile(RenderPart *pa) pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); for (rl= rr->layers.first; rl; rl= rl->next) { + float *rect= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK)) pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask"); @@ -1342,7 +1363,7 @@ void zbufshade_tile(RenderPart *pa) rr->renlay= rl; if (rl->layflag & SCE_LAY_SOLID) { - const float *fcol= rl->rectf; + const float *fcol = rect; const int *ro= pa->recto, *rp= pa->rectp, *rz= pa->rectz; int x, y, offs=0, seed; @@ -1405,11 +1426,11 @@ void zbufshade_tile(RenderPart *pa) rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer"); /* swap for live updates */ - SWAP(float *, rl->acolrect, rl->rectf); - zbuffer_transp_shade(pa, rl, rl->rectf, NULL); - SWAP(float *, rl->acolrect, rl->rectf); + SWAP(float *, rl->acolrect, rect); + zbuffer_transp_shade(pa, rl, rect, NULL); + SWAP(float *, rl->acolrect, rect); - fcol= rl->rectf; acol= rl->acolrect; + fcol= rect; acol= rl->acolrect; for (x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) { addAlphaOverFloat(fcol, acol); } @@ -1427,7 +1448,7 @@ void zbufshade_tile(RenderPart *pa) if (!R.test_break(R.tbh)) { if (rl->layflag & SCE_LAY_EDGE) if (R.r.mode & R_EDGE) - edge_enhance_add(pa, rl->rectf, edgerect); + edge_enhance_add(pa, rect, edgerect); } if (rl->passflag & SCE_PASS_VECTOR) @@ -1654,7 +1675,7 @@ void zbufshade_sss_tile(RenderPart *pa) return; } - fcol= rl->rectf; + fcol= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); co= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSCo"); color= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSColor"); @@ -1938,6 +1959,7 @@ void add_halo_flare(Render *re) RenderLayer *rl; HaloRen *har; int a, mode; + float *rect; /* for now, we get the first renderlayer in list with halos set */ for (rl= rr->layers.first; rl; rl= rl->next) { @@ -1945,8 +1967,11 @@ void add_halo_flare(Render *re) if ((rl->layflag & SCE_LAY_HALO) == 0) continue; - if (rl->rectf==NULL) - continue; + + rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname); + + if (rl==NULL || rect) + return; mode= R.r.mode; R.r.mode &= ~R_PANORAMA; @@ -1958,7 +1983,7 @@ void add_halo_flare(Render *re) if (har->flarec && (har->lay & rl->lay)) { do_draw = true; - renderflare(rr, rl->rectf, har); + renderflare(rr, rect, har); } } diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index d5d8595bf3f..b6628796e0d 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -3959,7 +3959,7 @@ static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf float *fp, *col; int a; - fp= RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR); + fp = RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR, R.viewname); if (fp==NULL) return; col= rectf+3; @@ -4052,9 +4052,10 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas /* zero alpha pixels get speed vector max again */ if (addpassflag & SCE_PASS_VECTOR) - if (rl->layflag & SCE_LAY_SOLID) - reset_sky_speedvectors(pa, rl, rl->acolrect?rl->acolrect:rl->rectf); /* if acolrect is set we use it */ - + if (rl->layflag & SCE_LAY_SOLID) { + float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + reset_sky_speedvectors(pa, rl, rl->acolrect ? rl->acolrect : rect); /* if acolrect is set we use it */ + } /* filtered render, for now we assume only 1 filter size */ if (pa->crop) { crop= 1; @@ -4239,8 +4240,9 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas alpha= samp_shr[a].combined[3]; if (alpha!=0.0f) { RenderLayer *rl= ssamp.rlpp[a]; - - addAlphaOverFloat(rl->rectf + 4*od, samp_shr[a].combined); + + float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + addAlphaOverFloat(rect + 4 * od, samp_shr[a].combined); add_transp_passes(rl, od, &samp_shr[a], alpha); if (addpassflag & SCE_PASS_VECTOR) diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index 78b5d499644..86f5fff4aef 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -64,6 +64,7 @@ set(SRC intern/wm_operators.c intern/wm_subwindow.c intern/wm_window.c + intern/wm_stereo.c WM_api.h WM_keymap.h diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index e64d08f38e1..dbeea80ba82 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -103,6 +103,7 @@ void WM_window_open_temp (struct bContext *C, struct rcti *position, int type); /* returns true if draw method is triple buffer */ bool WM_is_draw_triple(struct wmWindow *win); +bool WM_stereo3d_enabled(struct wmWindow *win, bool only_fullscreen_test); /* files */ diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 7440570f4a0..16fe9ca5142 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -48,9 +48,11 @@ #include "BIF_gl.h" #include "BKE_context.h" +#include "BKE_image.h" #include "GHOST_C-api.h" +#include "ED_node.h" #include "ED_view3d.h" #include "ED_screen.h" @@ -165,6 +167,7 @@ static void wm_method_draw_full(bContext *C, wmWindow *win) if (ar->swinid) { CTX_wm_region_set(C, ar); ED_region_do_draw(C, ar); + ar->do_draw = false; wm_paintcursor_draw(C, ar); CTX_wm_region_set(C, NULL); } @@ -175,12 +178,14 @@ static void wm_method_draw_full(bContext *C, wmWindow *win) } ED_screen_draw(win); + win->screen->do_draw = false; /* draw overlapping regions */ for (ar = screen->regionbase.first; ar; ar = ar->next) { if (ar->swinid) { CTX_wm_menu_set(C, ar); ED_region_do_draw(C, ar); + ar->do_draw = false; CTX_wm_menu_set(C, NULL); } } @@ -278,6 +283,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange) if (ar->do_draw) { CTX_wm_region_set(C, ar); ED_region_do_draw(C, ar); + ar->do_draw = false; wm_paintcursor_draw(C, ar); CTX_wm_region_set(C, NULL); @@ -288,6 +294,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange) if (ar->swap == WIN_FRONT_OK) { CTX_wm_region_set(C, ar); ED_region_do_draw(C, ar); + ar->do_draw = false; wm_paintcursor_draw(C, ar); CTX_wm_region_set(C, NULL); @@ -300,7 +307,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange) } } } - + wm_area_mark_invalid_backbuf(sa); CTX_wm_area_set(C, NULL); } @@ -308,6 +315,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange) /* after area regions so we can do area 'overlay' drawing */ if (screen->do_draw) { ED_screen_draw(win); + win->screen->do_draw = false; if (exchange) screen->swap = WIN_FRONT_OK; @@ -315,6 +323,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange) else if (exchange) { if (screen->swap == WIN_FRONT_OK) { ED_screen_draw(win); + win->screen->do_draw = false; screen->swap = WIN_BOTH_OK; } else if (screen->swap == WIN_BACK_OK) @@ -328,6 +337,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange) if (ar->swinid && ar->do_draw) { CTX_wm_menu_set(C, ar); ED_region_do_draw(C, ar); + ar->do_draw = false; CTX_wm_menu_set(C, NULL); } } @@ -360,15 +370,6 @@ static void wm_method_draw_damage(bContext *C, wmWindow *win) /* used. if not, multiple smaller ones are used, with */ /* worst case wasted space being 23.4% for 3x3 textures */ -#define MAX_N_TEX 3 - -typedef struct wmDrawTriple { - GLuint bind[MAX_N_TEX * MAX_N_TEX]; - int x[MAX_N_TEX], y[MAX_N_TEX]; - int nx, ny; - GLenum target; -} wmDrawTriple; - static void split_width(int x, int n, int *splitx, int *nx) { int a, newnx, waste; @@ -405,16 +406,13 @@ static void split_width(int x, int n, int *splitx, int *nx) } } -static void wm_draw_triple_free(wmWindow *win) +static void wm_draw_triple_free(wmDrawTriple *triple) { - if (win->drawdata) { - wmDrawTriple *triple = win->drawdata; + if (triple) { glDeleteTextures(triple->nx * triple->ny, triple->bind); MEM_freeN(triple); - - win->drawdata = NULL; } } @@ -499,7 +497,7 @@ static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple) return 1; } -static void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha) +void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha) { const int winsize_x = WM_window_pixels_x(win); const int winsize_y = WM_window_pixels_y(win); @@ -571,7 +569,7 @@ static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple) glBindTexture(triple->target, 0); } -static void wm_draw_region_blend(wmWindow *win, ARegion *ar) +static void wm_draw_region_blend(wmWindow *win, ARegion *ar, wmDrawTriple *triple) { float fac = ED_region_blend_factor(ar); @@ -580,7 +578,7 @@ static void wm_draw_region_blend(wmWindow *win, ARegion *ar) wmSubWindowScissorSet(win, win->screen->mainwin, &ar->winrct, true); glEnable(GL_BLEND); - wm_triple_draw_textures(win, win->drawdata, 1.0f - fac); + wm_triple_draw_textures(win, triple, 1.0f - fac); glDisable(GL_BLEND); } } @@ -589,29 +587,46 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win) { wmWindowManager *wm = CTX_wm_manager(C); wmDrawTriple *triple; + wmDrawData *dd, *dd_next, *drawdata = win->drawdata.first; bScreen *screen = win->screen; ScrArea *sa; ARegion *ar; - int copytex = 0; + int copytex = false; - if (win->drawdata) { + if (drawdata && drawdata->triple) { glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); wmSubWindowSet(win, screen->mainwin); - wm_triple_draw_textures(win, win->drawdata, 1.0f); + wm_triple_draw_textures(win, drawdata->triple, 1.0f); } else { - win->drawdata = MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple"); + /* we run it when we start OR when we turn stereo on */ + if (drawdata == NULL) { + drawdata = MEM_callocN(sizeof(wmDrawData), "wmDrawData"); + BLI_addhead(&win->drawdata, drawdata); + } + + drawdata->triple = MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple"); - if (!wm_triple_gen_textures(win, win->drawdata)) { + if (!wm_triple_gen_textures(win, drawdata->triple)) { wm_draw_triple_fail(C, win); return; } } - triple = win->drawdata; + /* it means stereo was just turned off */ + /* note: we are removing all drawdatas that are not the first */ + for (dd = drawdata->next; dd; dd = dd_next) { + dd_next = dd->next; + + BLI_remlink(&win->drawdata, dd); + wm_draw_triple_free(dd->triple); + MEM_freeN(dd); + } + + triple = drawdata->triple; /* draw marked area regions */ for (sa = screen->areabase.first; sa; sa = sa->next) { @@ -619,16 +634,17 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win) for (ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->swinid && ar->do_draw) { - - if (ar->overlap == 0) { + + if (ar->overlap == false) { CTX_wm_region_set(C, ar); ED_region_do_draw(C, ar); + ar->do_draw = false; CTX_wm_region_set(C, NULL); - copytex = 1; + copytex = true; } } } - + wm_area_mark_invalid_backbuf(sa); CTX_wm_area_set(C, NULL); } @@ -662,14 +678,15 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win) /* draw overlapping area regions (always like popups) */ for (sa = screen->areabase.first; sa; sa = sa->next) { CTX_wm_area_set(C, sa); - + for (ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->swinid && ar->overlap) { CTX_wm_region_set(C, ar); ED_region_do_draw(C, ar); + ar->do_draw = false; CTX_wm_region_set(C, NULL); - - wm_draw_region_blend(win, ar); + + wm_draw_region_blend(win, ar, triple); } } @@ -678,12 +695,14 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win) /* after area regions so we can do area 'overlay' drawing */ ED_screen_draw(win); + win->screen->do_draw = false; /* draw floating regions (menus) */ for (ar = screen->regionbase.first; ar; ar = ar->next) { if (ar->swinid) { CTX_wm_menu_set(C, ar); ED_region_do_draw(C, ar); + ar->do_draw = false; CTX_wm_menu_set(C, NULL); } } @@ -691,13 +710,188 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win) /* always draw, not only when screen tagged */ if (win->gesture.first) wm_gesture_draw(win); - + /* needs pixel coords in screen */ if (wm->drags.first) { wm_drags_draw(C, win, NULL); } } +static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, StereoViews sview) +{ + wmWindowManager *wm = CTX_wm_manager(C); + wmDrawData *drawdata; + wmDrawTriple *triple_data, *triple_all; + bScreen *screen = win->screen; + ScrArea *sa; + ARegion *ar; + int copytex = false; + int id; + + /* we store the triple_data in sequence to triple_all */ + for (id = 0; id < 2; id++) { + drawdata = BLI_findlink(&win->drawdata, (sview * 2) + id); + + if (drawdata && drawdata->triple) { + if (id == 0) { + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + wmSubWindowSet(win, screen->mainwin); + + wm_triple_draw_textures(win, drawdata->triple, 1.0f); + } + } + else { + /* we run it when we start OR when we turn stereo on */ + if (drawdata == NULL) { + drawdata = MEM_callocN(sizeof(wmDrawData), "wmDrawData"); + BLI_addtail(&win->drawdata, drawdata); + } + + drawdata->triple = MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple"); + + if (!wm_triple_gen_textures(win, drawdata->triple)) { + wm_draw_triple_fail(C, win); + return; + } + } + } + + triple_data = ((wmDrawData *) BLI_findlink(&win->drawdata, sview * 2))->triple; + triple_all = ((wmDrawData *) BLI_findlink(&win->drawdata, (sview * 2) + 1))->triple; + + /* draw marked area regions */ + for (sa = screen->areabase.first; sa; sa = sa->next) { + CTX_wm_area_set(C, sa); + + switch (sa->spacetype) { + case SPACE_IMAGE: + { + SpaceImage *sima = sa->spacedata.first; + sima->iuser.multiview_eye = sview; + break; + } + case SPACE_VIEW3D: + { + View3D *v3d = sa->spacedata.first; + BGpic *bgpic = v3d->bgpicbase.first; + v3d->multiview_eye = sview; + if (bgpic) bgpic->iuser.multiview_eye = sview; + break; + } + case SPACE_NODE: + { + SpaceNode *snode = sa->spacedata.first; + if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) { + Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ima->eye = sview; + } + break; + } + case SPACE_SEQ: + { + SpaceSeq *sseq = sa->spacedata.first; + sseq->multiview_eye = sview; + break; + } + } + + /* draw marked area regions */ + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->swinid && ar->do_draw) { + + if (ar->overlap == false) { + CTX_wm_region_set(C, ar); + ED_region_do_draw(C, ar); + + if (sview == STEREO_RIGHT_ID) + ar->do_draw = false; + + CTX_wm_region_set(C, NULL); + copytex = true; + } + } + } + + wm_area_mark_invalid_backbuf(sa); + CTX_wm_area_set(C, NULL); + } + + if (copytex) { + wmSubWindowSet(win, screen->mainwin); + + wm_triple_copy_textures(win, triple_data); + } + + if (wm->paintcursors.first) { + for (sa = screen->areabase.first; sa; sa = sa->next) { + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->swinid && ar->swinid == screen->subwinactive) { + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, ar); + + /* make region ready for draw, scissor, pixelspace */ + ED_region_set(C, ar); + wm_paintcursor_draw(C, ar); + + CTX_wm_region_set(C, NULL); + CTX_wm_area_set(C, NULL); + } + } + } + + wmSubWindowSet(win, screen->mainwin); + } + + /* draw overlapping area regions (always like popups) */ + for (sa = screen->areabase.first; sa; sa = sa->next) { + CTX_wm_area_set(C, sa); + + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->swinid && ar->overlap) { + CTX_wm_region_set(C, ar); + ED_region_do_draw(C, ar); + if (sview == STEREO_RIGHT_ID) + ar->do_draw = false; + CTX_wm_region_set(C, NULL); + + wm_draw_region_blend(win, ar, triple_data); + } + } + + CTX_wm_area_set(C, NULL); + } + + /* after area regions so we can do area 'overlay' drawing */ + ED_screen_draw(win); + if (sview == STEREO_RIGHT_ID) + win->screen->do_draw = false; + + /* draw floating regions (menus) */ + for (ar = screen->regionbase.first; ar; ar = ar->next) { + if (ar->swinid) { + CTX_wm_menu_set(C, ar); + ED_region_do_draw(C, ar); + if (sview == STEREO_RIGHT_ID) + ar->do_draw = false; + CTX_wm_menu_set(C, NULL); + } + } + + /* always draw, not only when screen tagged */ + if (win->gesture.first) + wm_gesture_draw(win); + + /* needs pixel coords in screen */ + if (wm->drags.first) { + wm_drags_draw(C, win, NULL); + } + + /* copy the ui + overlays */ + wmSubWindowSet(win, screen->mainwin); + wm_triple_copy_textures(win, triple_all); +} /****************** main update call **********************/ @@ -848,8 +1042,16 @@ void wm_draw_update(bContext *C) wm_method_draw_overlap_all(C, win, 0); else if (drawmethod == USER_DRAW_OVERLAP_FLIP) wm_method_draw_overlap_all(C, win, 1); - else // if (drawmethod == USER_DRAW_TRIPLE) - wm_method_draw_triple(C, win); + else { /* USER_DRAW_TRIPLE */ + if ((WM_stereo3d_enabled(win, false)) == false) { + wm_method_draw_triple(C, win); + } + else { + wm_method_draw_triple_multiview(C, win, STEREO_LEFT_ID); + wm_method_draw_triple_multiview(C, win, STEREO_RIGHT_ID); + wm_method_draw_stereo3d(C, win); + } + } win->screen->do_draw_gesture = false; win->screen->do_draw_paintcursor = false; @@ -862,15 +1064,23 @@ void wm_draw_update(bContext *C) } } +void wm_draw_data_free(wmWindow *win) +{ + wmDrawData *dd; + + for (dd = win->drawdata.first; dd; dd = dd->next) { + wm_draw_triple_free(dd->triple); + } + BLI_freelistN(&win->drawdata); +} + void wm_draw_window_clear(wmWindow *win) { bScreen *screen = win->screen; ScrArea *sa; ARegion *ar; - int drawmethod = wm_automatic_draw_method(win); - if (drawmethod == USER_DRAW_TRIPLE) - wm_draw_triple_free(win); + wm_draw_data_free(win); /* clear screen swap flags */ if (screen) { diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 3fd1fe427c9..f3e9c416e7b 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -846,11 +846,11 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt) if (scene->camera) { ibuf = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2, - IB_rect, OB_SOLID, false, false, false, R_ALPHAPREMUL, err_out); + IB_rect, OB_SOLID, false, false, false, R_ALPHAPREMUL, NULL, err_out); } else { ibuf = ED_view3d_draw_offscreen_imbuf(scene, v3d, ar, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2, - IB_rect, false, R_ALPHAPREMUL, err_out); + IB_rect, false, R_ALPHAPREMUL, NULL, err_out); } if (ibuf) { diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index c2cd96165f3..499adf5704d 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1268,6 +1268,13 @@ void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type, if (flag & WM_FILESEL_RELPATH) RNA_def_boolean(ot->srna, "relative_path", true, "Relative Path", "Select the file relative to the blend file"); + if ((filter & FILE_TYPE_IMAGE) || (filter & FILE_TYPE_MOVIE)) { + prop = RNA_def_boolean(ot->srna, "show_multiview", 0, "Enable Multi-View", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "use_multiview", 0, "Use Multi-View", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + } + prop = RNA_def_enum(ot->srna, "display_type", file_display_items, display, "Display Type", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } @@ -4592,8 +4599,10 @@ static int redraw_timer_exec(bContext *C, wmOperator *op) for (a = 0; a < iter; a++) { if (type == 0) { - if (ar) + if (ar) { ED_region_do_draw(C, ar); + ar->do_draw = false; + } } else if (type == 1) { wmWindow *win = CTX_wm_window(C); @@ -4621,6 +4630,7 @@ static int redraw_timer_exec(bContext *C, wmOperator *op) if (ar_iter->swinid) { CTX_wm_region_set(C, ar_iter); ED_region_do_draw(C, ar_iter); + ar->do_draw = false; } } } @@ -4831,6 +4841,36 @@ static void operatortype_ghash_free_cb(wmOperatorType *ot) MEM_freeN(ot); } +/* ******************************************************* */ +/* toggle 3D for current window, turning it fullscreen if needed */ +static void WM_OT_stereo3d_set(wmOperatorType *ot) +{ + PropertyRNA *prop; + + ot->name = "Set Stereo 3D"; + ot->idname = "WM_OT_set_stereo_3d"; + ot->description = "Toggle 3D stereo support for current window (or change the display mode)"; + + ot->exec = wm_stereo3d_set_exec; + ot->invoke = wm_stereo3d_set_invoke; + ot->poll = WM_operator_winactive; + ot->ui = wm_stereo3d_set_draw; + ot->cancel = wm_stereo3d_set_cancel; + + prop = RNA_def_enum(ot->srna, "display_mode", stereo3d_display_items, S3D_DISPLAY_ANAGLYPH, "Display Mode", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "anaglyph_type", stereo3d_anaglyph_type_items, S3D_ANAGLYPH_REDCYAN, "Anaglyph Type", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "interlace_type", stereo3d_interlace_type_items, S3D_INTERLACE_ROW, "Interlace Type", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "use_interlace_swap", false, "Swap Left/Right", + "Swap left and right stereo channels"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "use_sidebyside_crosseyed", false, "Cross-Eyed", + "Right eye should see left image and vice-versa"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); +} + /* ******************************************************* */ /* called on initialize WM_exit() */ void wm_operatortype_free(void) @@ -4873,6 +4913,7 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_call_menu); WM_operatortype_append(WM_OT_call_menu_pie); WM_operatortype_append(WM_OT_radial_control); + WM_operatortype_append(WM_OT_stereo3d_set); #if defined(WIN32) WM_operatortype_append(WM_OT_console_toggle); #endif diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c new file mode 100644 index 00000000000..5d7b11272c6 --- /dev/null +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -0,0 +1,534 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015 by Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/windowmanager/intern/wm_stereo.c + * \ingroup wm + */ + + +#include +#include + +#include "DNA_listBase.h" + +#include "RNA_access.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_rect.h" +#include "BLI_utildefines.h" + +#include "BIF_gl.h" + +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_report.h" + +#include "GHOST_C-api.h" + +#include "ED_screen.h" + +#include "GPU_glew.h" + +#include "WM_api.h" +#include "WM_types.h" +#include "wm.h" +#include "wm_draw.h" /* wmDrawTriple */ +#include "wm_window.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +static void wm_method_draw_stereo3d_pageflip(wmWindow *win) +{ + wmDrawData *drawdata; + int view; + + for (view = 0; view < 2; view ++) { + drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1); + + if (view == STEREO_LEFT_ID) + glDrawBuffer(GL_BACK_LEFT); + else //STEREO_RIGHT_ID + glDrawBuffer(GL_BACK_RIGHT); + + wm_triple_draw_textures(win, drawdata->triple, 1.0f); + } +} + +static GLuint left_interlace_mask[32]; +static GLuint right_interlace_mask[32]; +static enum eStereo3dInterlaceType interlace_prev_type = -1; +static char interlace_prev_swap = -1; + +static void wm_interlace_masks_create(wmWindow *win) +{ + GLuint pattern; + char i; + bool swap = (win->stereo3d_format->flag & S3D_INTERLACE_SWAP) != 0; + enum eStereo3dInterlaceType interlace_type = win->stereo3d_format->interlace_type; + + if (interlace_prev_type == interlace_type && interlace_prev_swap == swap) + return; + + switch (interlace_type) { + case S3D_INTERLACE_ROW: + pattern = 0x00000000; + pattern = swap ? ~pattern : pattern; + for (i = 0; i < 32; i += 2) { + left_interlace_mask[i] = pattern; + right_interlace_mask[i] = ~pattern; + } + for (i = 1; i < 32; i += 2) { + left_interlace_mask[i] = ~pattern; + right_interlace_mask[i] = pattern; + } + break; + case S3D_INTERLACE_COLUMN: + pattern = 0x55555555; + pattern = swap ? ~pattern : pattern; + for (i = 0; i < 32; i++) { + left_interlace_mask[i] = pattern; + right_interlace_mask[i] = ~pattern; + } + break; + case S3D_INTERLACE_CHECKERBOARD: + default: + pattern = 0x55555555; + pattern = swap ? ~pattern : pattern; + for (i = 0; i < 32; i += 2) { + left_interlace_mask[i] = pattern; + right_interlace_mask[i] = ~pattern; + } + for (i = 1; i < 32; i += 2) { + left_interlace_mask[i] = ~pattern; + right_interlace_mask[i] = pattern; + } + break; + } + interlace_prev_type = interlace_type; + interlace_prev_swap = swap; +} + +static void wm_method_draw_stereo3d_interlace(wmWindow *win) +{ + wmDrawData *drawdata; + int view; + + wm_interlace_masks_create(win); + + for (view = 0; view < 2; view ++) { + drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1); + + glEnable(GL_POLYGON_STIPPLE); + glPolygonStipple(view ? (GLubyte *) right_interlace_mask : (GLubyte *) left_interlace_mask); + + wm_triple_draw_textures(win, drawdata->triple, 1.0f); + glDisable(GL_POLYGON_STIPPLE); + } +} + +static void wm_method_draw_stereo3d_anaglyph(wmWindow *win) +{ + wmDrawData *drawdata; + int view, bit; + + for (view = 0; view < 2; view ++) { + drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1); + + bit = view + 1; + switch (win->stereo3d_format->anaglyph_type) { + case S3D_ANAGLYPH_REDCYAN: + glColorMask((1&bit) ? GL_TRUE : GL_FALSE, + (2&bit) ? GL_TRUE : GL_FALSE, + (2&bit) ? GL_TRUE : GL_FALSE, + GL_FALSE); + break; + case S3D_ANAGLYPH_GREENMAGENTA: + glColorMask((2&bit) ? GL_TRUE : GL_FALSE, + (1&bit) ? GL_TRUE : GL_FALSE, + (2&bit) ? GL_TRUE : GL_FALSE, + GL_FALSE); + break; + case S3D_ANAGLYPH_YELLOWBLUE: + glColorMask((1&bit) ? GL_TRUE : GL_FALSE, + (1&bit) ? GL_TRUE : GL_FALSE, + (2&bit) ? GL_TRUE : GL_FALSE, + GL_FALSE); + break; + } + + wm_triple_draw_textures(win, drawdata->triple, 1.0f); + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } +} + +static void wm_method_draw_stereo3d_sidebyside(wmWindow *win) +{ + wmDrawData *drawdata; + wmDrawTriple *triple; + float halfx, halfy, ratiox, ratioy; + int x, y, offx, offy; + float alpha = 1.0f; + int view; + int soffx; + bool cross_eyed = (win->stereo3d_format->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0; + + for (view = 0; view < 2; view ++) { + drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1); + triple = drawdata->triple; + + soffx = WM_window_pixels_x(win) * 0.5f; + if (view == STEREO_LEFT_ID) { + if (!cross_eyed) + soffx = 0; + } + else { //RIGHT_LEFT_ID + if (cross_eyed) + soffx = 0; + } + + glEnable(triple->target); + + for (y = 0, offy = 0; y < triple->ny; offy += triple->y[y], y++) { + for (x = 0, offx = 0; x < triple->nx; offx += triple->x[x], x++) { + const int sizex = triple->x[x]; + const int sizey = triple->y[y]; + + /* wmOrtho for the screen has this same offset */ + ratiox = sizex; + ratioy = sizey; + halfx = GLA_PIXEL_OFS; + halfy = GLA_PIXEL_OFS; + + /* texture rectangle has unnormalized coordinates */ + if (triple->target == GL_TEXTURE_2D) { + ratiox /= triple->x[x]; + ratioy /= triple->y[y]; + halfx /= triple->x[x]; + halfy /= triple->y[y]; + } + + glBindTexture(triple->target, triple->bind[x + y * triple->nx]); + + glColor4f(1.0f, 1.0f, 1.0f, alpha); + glBegin(GL_QUADS); + glTexCoord2f(halfx, halfy); + glVertex2f(soffx + (offx * 0.5f), offy); + + glTexCoord2f(ratiox + halfx, halfy); + glVertex2f(soffx + ((offx + sizex) * 0.5f), offy); + + glTexCoord2f(ratiox + halfx, ratioy + halfy); + glVertex2f(soffx + ((offx + sizex) * 0.5f), offy + sizey); + + glTexCoord2f(halfx, ratioy + halfy); + glVertex2f(soffx + (offx * 0.5f), offy + sizey); + glEnd(); + } + } + + glBindTexture(triple->target, 0); + glDisable(triple->target); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } +} + +static void wm_method_draw_stereo3d_topbottom(wmWindow *win) +{ + wmDrawData *drawdata; + wmDrawTriple *triple; + float halfx, halfy, ratiox, ratioy; + int x, y, offx, offy; + float alpha = 1.0f; + int view; + int soffy; + + for (view = 0; view < 2; view ++) { + drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1); + triple = drawdata->triple; + + if (view == STEREO_LEFT_ID) { + soffy = WM_window_pixels_y(win) * 0.5f; + } + else { /* STEREO_RIGHT_ID */ + soffy = 0; + } + + glEnable(triple->target); + + for (y = 0, offy = 0; y < triple->ny; offy += triple->y[y], y++) { + for (x = 0, offx = 0; x < triple->nx; offx += triple->x[x], x++) { + const int sizex = triple->x[x]; + const int sizey = triple->y[y]; + + /* wmOrtho for the screen has this same offset */ + ratiox = sizex; + ratioy = sizey; + halfx = GLA_PIXEL_OFS; + halfy = GLA_PIXEL_OFS; + + /* texture rectangle has unnormalized coordinates */ + if (triple->target == GL_TEXTURE_2D) { + ratiox /= triple->x[x]; + ratioy /= triple->y[y]; + halfx /= triple->x[x]; + halfy /= triple->y[y]; + } + + glBindTexture(triple->target, triple->bind[x + y * triple->nx]); + + glColor4f(1.0f, 1.0f, 1.0f, alpha); + glBegin(GL_QUADS); + glTexCoord2f(halfx, halfy); + glVertex2f(offx, soffy + (offy * 0.5f)); + + glTexCoord2f(ratiox + halfx, halfy); + glVertex2f(offx + sizex, soffy + (offy * 0.5f)); + + glTexCoord2f(ratiox + halfx, ratioy + halfy); + glVertex2f(offx + sizex, soffy + ((offy + sizey) * 0.5f)); + + glTexCoord2f(halfx, ratioy + halfy); + glVertex2f(offx, soffy + ((offy + sizey) * 0.5f)); + glEnd(); + } + } + + glBindTexture(triple->target, 0); + glDisable(triple->target); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } +} + +void wm_method_draw_stereo3d(const bContext *UNUSED(C), wmWindow *win) +{ + switch (win->stereo3d_format->display_mode) { + case S3D_DISPLAY_ANAGLYPH: + wm_method_draw_stereo3d_anaglyph(win); + break; + case S3D_DISPLAY_INTERLACE: + wm_method_draw_stereo3d_interlace(win); + break; + case S3D_DISPLAY_PAGEFLIP: + wm_method_draw_stereo3d_pageflip(win); + break; + case S3D_DISPLAY_SIDEBYSIDE: + wm_method_draw_stereo3d_sidebyside(win); + break; + case S3D_DISPLAY_TOPBOTTOM: + wm_method_draw_stereo3d_topbottom(win); + break; + default: + break; + } +} + +static bool wm_stereo3d_is_fullscreen_required(eStereoDisplayMode stereo_display) +{ + return ELEM(stereo_display, + S3D_DISPLAY_SIDEBYSIDE, + S3D_DISPLAY_TOPBOTTOM, + S3D_DISPLAY_PAGEFLIP); +} + +bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check) +{ + bScreen *screen = win->screen; + + if ((skip_stereo3d_check == false) && (ED_screen_stereo3d_required(screen) == false)) + return false; + + if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) + return WM_window_is_fullscreen(win); + + return true; +} + +/************************** Stereo 3D operator **********************************/ +typedef struct Stereo3dData { + Stereo3dFormat stereo3d_format; +} Stereo3dData; + +static bool wm_stereo3d_set_properties(bContext *C, wmOperator *op) +{ + wmWindow *win = CTX_wm_window(C); + Stereo3dFormat *s3d = win->stereo3d_format; + PropertyRNA *prop; + bool is_set = false; + + prop = RNA_struct_find_property(op->ptr, "display_mode"); + if (RNA_property_is_set(op->ptr, prop)) { + s3d->display_mode = RNA_property_enum_get(op->ptr, prop); + is_set = true; + } + + prop = RNA_struct_find_property(op->ptr, "anaglyph_type"); + if (RNA_property_is_set(op->ptr, prop)) { + s3d->anaglyph_type = RNA_property_enum_get(op->ptr, prop); + is_set = true; + } + + prop = RNA_struct_find_property(op->ptr, "interlace_type"); + if (RNA_property_is_set(op->ptr, prop)) { + s3d->interlace_type = RNA_property_enum_get(op->ptr, prop); + is_set = true; + } + + prop = RNA_struct_find_property(op->ptr, "use_interlace_swap"); + if (RNA_property_is_set(op->ptr, prop)) { + if (RNA_property_boolean_get(op->ptr, prop)) + s3d->flag |= S3D_INTERLACE_SWAP; + else + s3d->flag &= ~S3D_INTERLACE_SWAP; + is_set = true; + } + + prop = RNA_struct_find_property(op->ptr, "use_sidebyside_crosseyed"); + if (RNA_property_is_set(op->ptr, prop)) { + if (RNA_property_boolean_get(op->ptr, prop)) + s3d->flag |= S3D_SIDEBYSIDE_CROSSEYED; + else + s3d->flag &= ~S3D_SIDEBYSIDE_CROSSEYED; + is_set = true; + } + + return is_set; +} + +static void wm_stereo3d_set_init(bContext *C, wmOperator *op) +{ + Stereo3dData *s3dd; + wmWindow *win = CTX_wm_window(C); + + op->customdata = s3dd = MEM_callocN(sizeof(Stereo3dData), __func__); + + /* store the original win stereo 3d settings in case of cancel */ + s3dd->stereo3d_format = *win->stereo3d_format; +} + +int wm_stereo3d_set_exec(bContext *C, wmOperator *op) +{ + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); + const bool is_fullscreen = WM_window_is_fullscreen(win); + + if (G.background) + return OPERATOR_CANCELLED; + + /* pagelfip requires a new window to be created with the proper OS flags */ + if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { + if (wm_window_duplicate_exec(C, op) == OPERATOR_FINISHED) { + wm_window_close(C, wm, win); + win = wm->windows.last; + } + else { + BKE_reportf(op->reports, RPT_ERROR, + "Fail to create a window compatible with time sequential (page-flip) display method"); + return OPERATOR_CANCELLED; + } + } + + if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) { + if (!is_fullscreen) { + wm_window_fullscreen_toggle_exec(C, op); + } + } + + if (op->customdata) { + MEM_freeN(op->customdata); + } + + WM_event_add_notifier(C, NC_WINDOW, NULL); + return OPERATOR_FINISHED; +} + +int wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + wm_stereo3d_set_init(C, op); + + if (wm_stereo3d_set_properties(C, op)) + return wm_stereo3d_set_exec(C, op); + else + return WM_operator_props_dialog_popup(C, op, 250, 100); +} + +void wm_stereo3d_set_draw(bContext *C, wmOperator *op) +{ + wmWindow *win = CTX_wm_window(C); + Stereo3dFormat *stereo3d_format; + PointerRNA stereo3d_format_ptr; + uiLayout *layout = op->layout; + uiLayout *col; + + stereo3d_format = win->stereo3d_format; + RNA_pointer_create(NULL, &RNA_Stereo3dDisplay, stereo3d_format, &stereo3d_format_ptr); + + col = uiLayoutColumn(layout, false); + uiItemR(col, &stereo3d_format_ptr, "display_mode", 0, NULL, ICON_NONE); + + switch (stereo3d_format->display_mode) { + case S3D_DISPLAY_ANAGLYPH: + { + uiItemR(col, &stereo3d_format_ptr, "anaglyph_type", 0, NULL, ICON_NONE); + break; + } + case S3D_DISPLAY_INTERLACE: + { + uiItemR(col, &stereo3d_format_ptr, "interlace_type", 0, NULL, ICON_NONE); + uiItemR(col, &stereo3d_format_ptr, "use_interlace_swap", 0, NULL, ICON_NONE); + break; + } + case S3D_DISPLAY_SIDEBYSIDE: + { + uiItemR(col, &stereo3d_format_ptr, "use_sidebyside_crosseyed", 0, NULL, ICON_NONE); + /* fall-through */ + } + case S3D_DISPLAY_PAGEFLIP: + case S3D_DISPLAY_TOPBOTTOM: + default: + { + break; + } + } +} + +void wm_stereo3d_set_cancel(bContext *C, wmOperator *op) +{ + Stereo3dData *s3dd = op->customdata; + wmWindow *win = CTX_wm_window(C); + + /* roll back to the original */ + if (win) { + *win->stereo3d_format = s3dd->stereo3d_format; + } + + MEM_freeN(op->customdata); + op->customdata = NULL; +} diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 1af20e6036d..4b98f8bf71d 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -206,12 +206,13 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win) wm_event_free_all(win); wm_subwindows_free(win); - - if (win->drawdata) - MEM_freeN(win->drawdata); - + + wm_draw_data_free(win); + wm_ghostwindow_destroy(win); - + + MEM_freeN(win->stereo3d_format); + MEM_freeN(win); } @@ -236,6 +237,8 @@ wmWindow *wm_window_new(bContext *C) BLI_addtail(&wm->windows, win); win->winid = find_free_winid(wm); + win->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo 3D Format (window)"); + return win; } @@ -259,8 +262,11 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *winorig) win->screen->do_draw = true; win->drawmethod = U.wmdrawmethod; - win->drawdata = NULL; - + + BLI_listbase_clear(&win->drawdata); + + *win->stereo3d_format = *winorig->stereo3d_format; + return win; } @@ -367,6 +373,10 @@ static void wm_window_add_ghostwindow(wmWindowManager *wm, const char *title, wm glSettings.numOfAASamples = multisamples; + /* a new window is created when pageflip mode is required for a window */ + if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) + glSettings.flags |= GHOST_glStereoVisual; + if (!(U.uiflag2 & USER_OPENGL_NO_WARN_SUPPORT)) glSettings.flags |= GHOST_glWarnSupport; @@ -519,8 +529,7 @@ wmWindow *WM_window_open(bContext *C, const rcti *rect) win->sizey = BLI_rcti_size_y(rect); win->drawmethod = U.wmdrawmethod; - win->drawdata = NULL; - + WM_check(C); return win; diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h index de04129a0ef..bc777b74b51 100644 --- a/source/blender/windowmanager/wm.h +++ b/source/blender/windowmanager/wm.h @@ -76,6 +76,13 @@ void wm_autosave_delete(void); void wm_autosave_read(bContext *C, struct ReportList *reports); void wm_autosave_location(char *filepath); +/* wm_stereo.c */ +void wm_method_draw_stereo3d(const bContext *C, wmWindow *win); +int wm_stereo3d_set_exec(bContext *C, wmOperator *op); +int wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *event); +void wm_stereo3d_set_draw(bContext *C, wmOperator *op); +void wm_stereo3d_set_cancel(bContext *C, wmOperator *op); + /* init operator properties */ void wm_open_init_load_ui(wmOperator *op, bool use_prefs); void wm_open_init_use_scripts(wmOperator *op, bool use_prefs); diff --git a/source/blender/windowmanager/wm_draw.h b/source/blender/windowmanager/wm_draw.h index 3d72fe17c79..5dc52b2e4fb 100644 --- a/source/blender/windowmanager/wm_draw.h +++ b/source/blender/windowmanager/wm_draw.h @@ -32,6 +32,23 @@ #ifndef __WM_DRAW_H__ #define __WM_DRAW_H__ +#include "GPU_glew.h" + + +#define MAX_N_TEX 3 + +typedef struct wmDrawTriple { + GLuint bind[MAX_N_TEX * MAX_N_TEX]; + int x[MAX_N_TEX], y[MAX_N_TEX]; + int nx, ny; + GLenum target; +} wmDrawTriple; + +typedef struct wmDrawData { + struct wmDrawData *next, *prev; + wmDrawTriple *triple; +} wmDrawData; + struct bContext; struct wmWindow; struct ARegion; @@ -43,5 +60,9 @@ void wm_draw_region_clear (struct wmWindow *win, struct ARegion *ar); void wm_tag_redraw_overlay (struct wmWindow *win, struct ARegion *ar); +void wm_triple_draw_textures (struct wmWindow *win, struct wmDrawTriple *triple, float alpha); + +void wm_draw_data_free (struct wmWindow *win); + #endif /* __WM_DRAW_H__ */ diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 893eae8485a..8fbc3c5be9c 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -221,12 +221,20 @@ void EDBM_mesh_normals_update(struct BMEditMesh *em) RET_NONE void *g_system; bool EDBM_mtexpoly_check(struct BMEditMesh *em) RET_ZERO -float *RE_RenderLayerGetPass(struct RenderLayer *rl, int passtype) RET_NULL +float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL float RE_filter_value(int type, float x) RET_ZERO struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name) RET_NULL void RE_init_texture_rng() RET_NONE void RE_exit_texture_rng() RET_NONE +float *RE_RenderViewGetRectf(struct RenderResult *rr, int view_id) {STUB_ASSERT(0); return (float *) NULL;} +float *RE_RenderViewGetRectz(struct RenderResult *rr, int view_id) {STUB_ASSERT(0); return (float *) NULL;} +bool RE_layers_have_name(struct RenderResult *result) {STUB_ASSERT(0); return 0;} +void RE_engine_active_view_set(struct RenderEngine *engine, const char *viewname) {STUB_ASSERT(0);} +void RE_engine_get_camera_model_matrix(struct RenderEngine *engine, struct Object *camera, float *r_modelmat) {STUB_ASSERT(0);} +float RE_engine_get_camera_shift_x(struct RenderEngine *engine, struct Object *camera) RET_ZERO +void RE_SetActiveRenderView(struct Render *re, const char *viewname) {STUB_ASSERT(0);} + /* zbuf.c stub */ void antialias_tagbuf(int xsize, int ysize, char *rectmove) RET_NONE void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nbd, int xsize, int ysize, float *newrect, float *imgrect, float *vecbufrect, float *zbufrect) RET_NONE @@ -250,6 +258,7 @@ void RE_sample_material_color(struct Material *mat, float color[3], float *alpha /* nodes */ struct Render *RE_GetRender(const char *name) RET_NULL +struct Object *RE_GetCamera(struct Render *re) RET_NULL float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]) RET_ZERO /* blenkernel */ @@ -584,9 +593,10 @@ void uiTemplateColormanagedViewSettings(struct uiLayout *layout, struct bContext void uiTemplateComponentMenu(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name) RET_NONE void uiTemplateNodeSocket(struct uiLayout *layout, struct bContext *C, float *color) RET_NONE void uiTemplatePalette(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, int color) RET_NONE +void uiTemplateImageStereo3d(struct uiLayout *layout, struct PointerRNA *stereo3d_format_ptr) RET_NONE /* rna render */ -struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername) RET_NULL +struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname) RET_NULL struct RenderResult *RE_AcquireResultRead(struct Render *re) RET_NULL struct RenderResult *RE_AcquireResultWrite(struct Render *re) RET_NULL struct RenderStats *RE_GetStats(struct Render *re) RET_NULL @@ -598,7 +608,7 @@ void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info) RET_NONE void RE_layer_load_from_file(struct RenderLayer *layer, struct ReportList *reports, const char *filename, int x, int y) RET_NONE void RE_result_load_from_file(struct RenderResult *result, struct ReportList *reports, const char *filename) RET_NONE -void RE_AcquireResultImage(struct Render *re, struct RenderResult *rr) RET_NONE +void RE_AcquireResultImage(struct Render *re, struct RenderResult *rr, const int view_id) RET_NONE void RE_ReleaseResult(struct Render *re) RET_NONE void RE_ReleaseResultImage(struct Render *re) RET_NONE int RE_engine_test_break(struct RenderEngine *engine) RET_ZERO @@ -713,6 +723,11 @@ struct CCLDeviceInfo *CCL_compute_device_list(int opencl) RET_NULL /* compositor */ void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rendering, - const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) RET_NONE + const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, + const char *viewName) RET_NONE + +/*multiview*/ +bool RE_RenderResult_is_stereo(RenderResult *res) RET_ZERO +void uiTemplateImageViews(uiLayout *layout, struct PointerRNA *imfptr) RET_NONE #endif // WITH_GAMEENGINE -- cgit v1.2.3 From 36f352a4e45202a6a45aa608ee083f30a4db2c81 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Mon, 6 Apr 2015 11:11:36 -0300 Subject: Fix doversion check - patch by Sergey Sharybin --- source/blender/blenloader/intern/versioning_270.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 371ce495b07..3201a81d90c 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -730,7 +730,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) #undef SEQ_USE_PROXY_CUSTOM_FILE } - if (!MAIN_VERSION_ATLEAST(main, 274, 3)) + if (!MAIN_VERSION_ATLEAST(main, 274, 4)) { SceneRenderView *srv; wmWindowManager *wm; -- cgit v1.2.3 From b5f58c1ad9b19f3fe7ee06a4ab5ec5498dfc0652 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 21 Feb 2015 21:55:24 +0500 Subject: Cycles: Experiment with making previews more interactive There were two major problems with the interactivity of material previews: - Beckmann tables were re-generated on every material tweak. This is because preview scene is not set to be persistent, so re-triggering the render leads to the full scene re-sync. - Images could take rather noticeable time to load with OIIO from the disk on every tweak. This patch addressed this two issues in the following way: - Beckmann tables are now static on CPU memory. They're couple of hundred kilobytes only, so wouldn't expect this to be an issue. And they're needed for almost every render anyway. This actually also makes blackbody table to be static, but it's even smaller than beckmann table. Not totally happy with this approach, but others seems to complicate things quite a bit with all this render engine life time and so.. - For preview rendering all images are considered to be built-in. This means instead of OIIO which re-loads images on every re-render they're coming from ImBuf cache which is fully manageable from blender side and unused images gets freed later. This would make it impossible to have mipmapping with OSL for now, but we'll be working on that later anyway and don't think mipmaps are really so crucial for the material preview. This seems to be a better alternative to making preview scene persistent, because of much optimal memory control from blender side. Reviewers: brecht, juicyfruit, campbellbarton, dingto Subscribers: eyecandy, venomgfx Differential Revision: https://developer.blender.org/D1132 --- intern/cycles/blender/blender_shader.cpp | 66 +++++++++++++++++++++++++------- intern/cycles/blender/blender_sync.cpp | 3 +- intern/cycles/render/shader.cpp | 13 ++++++- intern/cycles/render/shader.h | 6 ++- 4 files changed, 70 insertions(+), 18 deletions(-) diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index dda06616ac6..d3b01fbf1d4 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -179,7 +179,13 @@ static bool is_output_node(BL::Node b_node) || b_node.is_a(&RNA_ShaderNodeOutputLamp)); } -static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, BL::ShaderNode b_node) +static ShaderNode *add_node(Scene *scene, + BL::RenderEngine b_engine, + BL::BlendData b_data, + BL::Scene b_scene, + ShaderGraph *graph, + BL::ShaderNodeTree b_ntree, + BL::ShaderNode b_node) { ShaderNode *node = NULL; @@ -558,7 +564,8 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen */ bool is_builtin = b_image.packed_file() || b_image.source() == BL::Image::source_GENERATED || - b_image.source() == BL::Image::source_MOVIE; + b_image.source() == BL::Image::source_MOVIE || + b_engine.is_preview(); if(is_builtin) { /* for builtin images we're using image datablock name to find an image to @@ -601,7 +608,8 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen if(b_image) { bool is_builtin = b_image.packed_file() || b_image.source() == BL::Image::source_GENERATED || - b_image.source() == BL::Image::source_MOVIE; + b_image.source() == BL::Image::source_MOVIE || + b_engine.is_preview(); if(is_builtin) { int scene_frame = b_scene.frame_current(); @@ -805,8 +813,14 @@ static ShaderOutput *node_find_output_by_name(ShaderNode *node, BL::Node b_node, return node->output(name.c_str()); } -static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, - const ProxyMap &proxy_input_map, const ProxyMap &proxy_output_map) +static void add_nodes(Scene *scene, + BL::RenderEngine b_engine, + BL::BlendData b_data, + BL::Scene b_scene, + ShaderGraph *graph, + BL::ShaderNodeTree b_ntree, + const ProxyMap &proxy_input_map, + const ProxyMap &proxy_output_map) { /* add nodes */ BL::ShaderNodeTree::nodes_iterator b_node; @@ -883,8 +897,16 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha output_map[b_output->ptr.data] = proxy->outputs[0]; } - if(b_group_ntree) - add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_proxy_input_map, group_proxy_output_map); + if (b_group_ntree) { + add_nodes(scene, + b_engine, + b_data, + b_scene, + graph, + b_group_ntree, + group_proxy_input_map, + group_proxy_output_map); + } } else if(b_node->is_a(&RNA_NodeGroupInput)) { /* map each socket to a proxy node */ @@ -923,7 +945,13 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha } } else { - node = add_node(scene, b_data, b_scene, graph, b_ntree, BL::ShaderNode(*b_node)); + node = add_node(scene, + b_engine, + b_data, + b_scene, + graph, + b_ntree, + BL::ShaderNode(*b_node)); } if(node) { @@ -979,10 +1007,22 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha } } -static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree) +static void add_nodes(Scene *scene, + BL::RenderEngine b_engine, + BL::BlendData b_data, + BL::Scene b_scene, + ShaderGraph *graph, + BL::ShaderNodeTree b_ntree) { static const ProxyMap empty_proxy_map; - add_nodes(scene, b_data, b_scene, graph, b_ntree, empty_proxy_map, empty_proxy_map); + add_nodes(scene, + b_engine, + b_data, + b_scene, + graph, + b_ntree, + empty_proxy_map, + empty_proxy_map); } /* Sync Materials */ @@ -1008,7 +1048,7 @@ void BlenderSync::sync_materials(bool update_all) if(b_mat->use_nodes() && b_mat->node_tree()) { BL::ShaderNodeTree b_ntree(b_mat->node_tree()); - add_nodes(scene, b_data, b_scene, graph, b_ntree); + add_nodes(scene, b_engine, b_data, b_scene, graph, b_ntree); } else { ShaderNode *closure, *out; @@ -1051,7 +1091,7 @@ void BlenderSync::sync_world(bool update_all) if(b_world && b_world.use_nodes() && b_world.node_tree()) { BL::ShaderNodeTree b_ntree(b_world.node_tree()); - add_nodes(scene, b_data, b_scene, graph, b_ntree); + add_nodes(scene, b_engine, b_data, b_scene, graph, b_ntree); /* volume */ PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles"); @@ -1137,7 +1177,7 @@ void BlenderSync::sync_lamps(bool update_all) BL::ShaderNodeTree b_ntree(b_lamp->node_tree()); - add_nodes(scene, b_data, b_scene, graph, b_ntree); + add_nodes(scene, b_engine, b_data, b_scene, graph, b_ntree); } else { ShaderNode *closure, *out; diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index aaf7d7d58ef..266e170fa8f 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -385,7 +385,8 @@ void BlenderSync::sync_images() */ const bool is_builtin = b_image->packed_file() || b_image->source() == BL::Image::source_GENERATED || - b_image->source() == BL::Image::source_MOVIE; + b_image->source() == BL::Image::source_MOVIE || + b_engine.is_preview(); if(is_builtin == false) { b_image->buffers_free(); } diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 3ae1e80c2af..fba908ee447 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -32,6 +32,9 @@ CCL_NAMESPACE_BEGIN +vector ShaderManager::blackbody_table; +vector ShaderManager::beckmann_table; + /* Beckmann sampling precomputed table, see bsdf_microfacet.h */ /* 2D slope distribution (alpha = 1.0) */ @@ -394,7 +397,10 @@ void ShaderManager::device_update_common(Device *device, if(has_converter_blackbody && blackbody_table_offset == TABLE_OFFSET_INVALID) { if(blackbody_table.size() == 0) { - blackbody_table = blackbody_table_build(); + thread_scoped_lock lock(lookup_table_mutex); + if(blackbody_table.size() == 0) { + blackbody_table = blackbody_table_build(); + } } blackbody_table_offset = scene->lookup_tables->add_table(dscene, blackbody_table); @@ -408,7 +414,10 @@ void ShaderManager::device_update_common(Device *device, /* beckmann lookup table */ if(beckmann_table_offset == TABLE_OFFSET_INVALID) { if(beckmann_table.size() == 0) { - beckmann_table_build(beckmann_table); + thread_scoped_lock lock(lookup_table_mutex); + if(beckmann_table.size() == 0) { + beckmann_table_build(beckmann_table); + } } beckmann_table_offset = scene->lookup_tables->add_table(dscene, beckmann_table); ktables->beckmann_offset = (int)beckmann_table_offset; diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index 1dee47c7731..a1d697a7b7b 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -36,6 +36,7 @@ #include "util_map.h" #include "util_param.h" #include "util_string.h" +#include "util_thread.h" #include "util_types.h" CCL_NAMESPACE_BEGIN @@ -171,8 +172,9 @@ protected: typedef unordered_map AttributeIDMap; AttributeIDMap unique_attribute_id; - vector blackbody_table; - vector beckmann_table; + thread_mutex lookup_table_mutex; + static vector blackbody_table; + static vector beckmann_table; size_t blackbody_table_offset; size_t beckmann_table_offset; -- cgit v1.2.3 From d0aae79505ad2542677c0b4ed791e88a613c597e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 6 Apr 2015 19:28:25 +0500 Subject: Cycles: More instant feedback on progressive rendering for first sample Main purpose of this change is to make material preview appearing more instant after the shader tweaks. --- intern/cycles/render/session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 65b73eb2ad3..5b3826c0ea9 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -891,7 +891,7 @@ bool Session::update_progressive_refine(bool cancel) if(current_time - last_update_time < params.progressive_update_timeout) { /* if last sample was processed, we need to write buffers anyway */ - if(!write) + if(!write && sample != 1) return false; } -- cgit v1.2.3 From 3e5332bb959c686cb5bc5b6007d96088d5d1bc23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Mon, 6 Apr 2015 17:11:36 +0200 Subject: BGE: fixed nomenclature of KX_Scene::addObject and KX_Scene::AddReplicaObject KX_Scene::addObject: Changed the parameter "other" to "reference", as "other" doesn't mean anything. KX_Scene::AddReplicaObject: Changed the parameter "parentobject" to "referenceobject", as the parameter did NOT contain a parent object in any way. Now both functions use the same kind of name for the same thing. Thanks to panzergame / Porteries Tristan. --- doc/python_api/rst/bge_types/bge.types.KX_Scene.rst | 8 ++++---- source/gameengine/Ketsji/KX_Scene.cpp | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst b/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst index 255ff95ad37..a6135054058 100644 --- a/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst +++ b/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst @@ -131,14 +131,14 @@ base class --- :class:`PyObjectPlus` :type: Vector((gx, gy, gz)) - .. method:: addObject(object, other, time=0) + .. method:: addObject(object, reference, time=0) Adds an object to the scene like the Add Object Actuator would. - :arg object: The object to add + :arg object: The (name of the) object to add. :type object: :class:`KX_GameObject` or string - :arg other: The object's center to use when adding the object - :type other: :class:`KX_GameObject` or string + :arg reference: The (name of the) object which position, orientation, and scale to copy. + :type reference: :class:`KX_GameObject` or string :arg time: The lifetime of the added object, in frames. A time of 0 means the object will last forever. :type time: integer :return: The newly added object. diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 193a72ebd2a..fc61d2b5da4 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -869,7 +869,7 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, - class CValue* parentobject, + class CValue* referenceobject, int lifespan) { @@ -878,7 +878,7 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, m_groupGameObjects.clear(); KX_GameObject* originalobj = (KX_GameObject*) originalobject; - KX_GameObject* parentobj = (KX_GameObject*) parentobject; + KX_GameObject* referenceobj = (KX_GameObject*) referenceobject; m_ueberExecutionPriority++; @@ -916,14 +916,14 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, // At this stage all the objects in the hierarchy have been duplicated, // we can update the scenegraph, we need it for the duplication of logic - MT_Point3 newpos = ((KX_GameObject*) parentobject)->NodeGetWorldPosition(); + MT_Point3 newpos = referenceobj->NodeGetWorldPosition(); replica->NodeSetLocalPosition(newpos); - MT_Matrix3x3 newori = ((KX_GameObject*) parentobject)->NodeGetWorldOrientation(); + MT_Matrix3x3 newori = referenceobj->NodeGetWorldOrientation(); replica->NodeSetLocalOrientation(newori); // get the rootnode's scale - MT_Vector3 newscale = parentobj->GetSGNode()->GetRootSGParent()->GetLocalScale(); + MT_Vector3 newscale = referenceobj->GetSGNode()->GetRootSGParent()->GetLocalScale(); // set the replica's relative scale with the rootnode's scale replica->NodeSetRelativeScale(newscale); @@ -946,12 +946,12 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, // this will also relink the actuators in the hierarchy (*git)->Relink(&m_map_gameobject_to_replica); // add the object in the layer of the parent - (*git)->SetLayer(parentobj->GetLayer()); + (*git)->SetLayer(referenceobj->GetLayer()); // If the object was a light, we need to update it's RAS_LightObject as well if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) { KX_LightObject* lightobj = static_cast(*git); - lightobj->SetLayer(parentobj->GetLayer()); + lightobj->SetLayer(referenceobj->GetLayer()); } } -- cgit v1.2.3 From 593b4d84c460e4e159a8f111b8192289896ec5c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Mon, 6 Apr 2015 18:23:56 +0200 Subject: BGE: followup of renaming parameter "other" to "reference" See commit 3e5332bb959c686cb5bc5b6007d96088d5d1bc23 --- source/gameengine/Ketsji/KX_Scene.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index fc61d2b5da4..db4ed58d65f 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -945,7 +945,7 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, { // this will also relink the actuators in the hierarchy (*git)->Relink(&m_map_gameobject_to_replica); - // add the object in the layer of the parent + // add the object in the layer of the reference object (*git)->SetLayer(referenceobj->GetLayer()); // If the object was a light, we need to update it's RAS_LightObject as well if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) @@ -2493,23 +2493,23 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject, "addObject(object, other, time=0)\n" "Returns the added object.\n") { - PyObject *pyob, *pyother; - KX_GameObject *ob, *other; + PyObject *pyob, *pyreference; + KX_GameObject *ob, *reference; int time = 0; - if (!PyArg_ParseTuple(args, "OO|i:addObject", &pyob, &pyother, &time)) + if (!PyArg_ParseTuple(args, "OO|i:addObject", &pyob, &pyreference, &time)) return NULL; - if ( !ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, other, time): KX_Scene (first argument)") || - !ConvertPythonToGameObject(pyother, &other, false, "scene.addObject(object, other, time): KX_Scene (second argument)") ) + if ( !ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, reference, time): KX_Scene (first argument)") || + !ConvertPythonToGameObject(pyreference, &reference, false, "scene.addObject(object, reference, time): KX_Scene (second argument)") ) return NULL; if (!m_inactivelist->SearchValue(ob)) { - PyErr_Format(PyExc_ValueError, "scene.addObject(object, other, time): KX_Scene (first argument): object must be in an inactive layer"); + PyErr_Format(PyExc_ValueError, "scene.addObject(object, reference, time): KX_Scene (first argument): object must be in an inactive layer"); return NULL; } - SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, other, time); + SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, reference, time); // release here because AddReplicaObject AddRef's // the object is added to the scene so we don't want python to own a reference -- cgit v1.2.3 From 28e9058e7ad29844c111e02fd1b44c9fc57a9b1f Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Mon, 6 Apr 2015 19:12:23 +0200 Subject: OSX: add a license file for libiomp5 ( intel omp ) when compiled with --- build_files/scons/tools/Blender.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py index dbe1cafc14f..e751be3ebc5 100644 --- a/build_files/scons/tools/Blender.py +++ b/build_files/scons/tools/Blender.py @@ -816,6 +816,8 @@ def AppIt(target=None, source=None, env=None): instname = env['LCGDIR'][1:] # made libiomp5 part of blender libs cmd = 'ditto --arch %s %s/openmp/lib/libiomp5.dylib %s/%s.app/Contents/Resources/lib/'%(osxarch, instname, installdir, binary) # copy libiomp5 commands.getoutput(cmd) + cmd = 'cp %s/openmp/LICENSE.txt %s/LICENSE-libiomp5.txt'%(instname, installdir) # copy libiomp5 license + commands.getoutput(cmd) # extract copy system python, be sure to update other build systems # when making changes to the files that are copied. -- cgit v1.2.3 From 2aa79679dca564b47f5db868160508adba9e08ca Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Mon, 6 Apr 2015 19:55:51 +0200 Subject: OSX: add also license for iomp5 using cmake and fix all textfiles wrong destination --- source/creator/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 193737e9822..c0b0c2eadb6 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -843,7 +843,7 @@ elseif(APPLE) ) # install release and app files - set(BLENDER_TEXT_FILES_DESTINATION blender.app/Contents) + set(BLENDER_TEXT_FILES_DESTINATION ".") install( FILES ${OSX_APP_SOURCEDIR}/Contents/PkgInfo @@ -860,6 +860,11 @@ elseif(APPLE) FILES ${LIBDIR}/openmp/lib/libiomp5.dylib DESTINATION blender.app/Contents/Resources/lib/ ) + install( + FILES ${LIBDIR}/openmp/LICENSE.txt + DESTINATION "." + RENAME LICENSE-libiomp5.txt + ) endif() if(WITH_LLVM AND NOT LLVM_STATIC) -- cgit v1.2.3 From 7c19239bf96f2d264661e86999b7b0db678b8adc Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 6 Apr 2015 23:29:29 +0500 Subject: Cycles: Support bultin 3d textures with OSL backend --- intern/cycles/kernel/osl/osl_services.cpp | 32 ++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 22f48ee57f0..064edb6ead3 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -939,19 +939,33 @@ bool OSLRenderServices::texture3d(ustring filename, TextureOpt &options, OSL::TextureSystem *ts = osl_ts; ShaderData *sd = (ShaderData *)(sg->renderstate); KernelGlobals *kg = sd->osl_globals; - OSLThreadData *tdata = kg->osl_tdata; - OIIO::TextureSystem::Perthread *thread_info = tdata->oiio_thread_info; - - OIIO::TextureSystem::TextureHandle *th = ts->get_texture_handle(filename, thread_info); + bool status; + if(filename[0] == '@' && filename.find('.') == -1) { + int slot = atoi(filename.c_str() + 1); + float4 rgba = kernel_tex_image_interp_3d(slot, P.x, P.y, P.z); + result[0] = rgba[0]; + if(nchannels > 1) + result[1] = rgba[1]; + if(nchannels > 2) + result[2] = rgba[2]; + if(nchannels > 3) + result[3] = rgba[3]; + status = true; + } + else { + OSLThreadData *tdata = kg->osl_tdata; + OIIO::TextureSystem::Perthread *thread_info = tdata->oiio_thread_info; + OIIO::TextureSystem::TextureHandle *th = ts->get_texture_handle(filename, thread_info); #if OIIO_VERSION < 10500 - bool status = ts->texture3d(th, thread_info, - options, P, dPdx, dPdy, dPdz, result); + status = ts->texture3d(th, thread_info, + options, P, dPdx, dPdy, dPdz, result); #else - bool status = ts->texture3d(th, thread_info, - options, P, dPdx, dPdy, dPdz, - nchannels, result); + status = ts->texture3d(th, thread_info, + options, P, dPdx, dPdy, dPdz, + nchannels, result); #endif + } if(!status) { if(nchannels == 3 || nchannels == 4) { -- cgit v1.2.3 From c1d8ddacaf14c7cd3d287b3e85c8914ddf75780d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 7 Apr 2015 00:11:47 +0500 Subject: Cycles: Avoid doing paranoid checks in filepath of builtin images Originally we thought it's needed in order to distinguish builtin file from filename which starts with '@', but the filepath is actually full path there and it's unlikely to have file system where '@' is a proper root character. Surprisingly this does not give visible speed differences, but it's still nice to get rid of redundant check. --- intern/cycles/kernel/osl/osl_services.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 064edb6ead3..f865cfb326e 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -887,7 +887,7 @@ bool OSLRenderServices::texture(ustring filename, TextureOpt &options, #endif bool status; - if(filename[0] == '@' && filename.find('.') == -1) { + if(filename[0] == '@') { int slot = atoi(filename.c_str() + 1); float4 rgba = kernel_tex_image_interp(slot, s, 1.0f - t); @@ -940,7 +940,7 @@ bool OSLRenderServices::texture3d(ustring filename, TextureOpt &options, ShaderData *sd = (ShaderData *)(sg->renderstate); KernelGlobals *kg = sd->osl_globals; bool status; - if(filename[0] == '@' && filename.find('.') == -1) { + if(filename[0] == '@') { int slot = atoi(filename.c_str() + 1); float4 rgba = kernel_tex_image_interp_3d(slot, P.x, P.y, P.z); -- cgit v1.2.3 From e2354e64d2cd8b11bb3ace22a6ba353d7a1382d8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 7 Apr 2015 00:25:54 +0500 Subject: Cycles: Cleanup, spaces around assignment operator Did some bad spacing in recent commits, better to get rid of those so they does not confuse those who're working on sources. --- intern/cycles/blender/blender_curves.cpp | 2 +- intern/cycles/blender/blender_mesh.cpp | 12 ++++++------ intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h | 2 +- intern/cycles/kernel/geom/geom_bvh_shadow.h | 2 +- intern/cycles/kernel/geom/geom_motion_triangle.h | 2 +- intern/cycles/kernel/geom/geom_qbvh_shadow.h | 2 +- intern/cycles/kernel/kernel_shader.h | 4 ++-- intern/cycles/kernel/osl/osl_services.cpp | 4 ++-- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 91963ac3fe3..dba801fc4df 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -621,7 +621,7 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData) } /* check allocation */ - if((mesh->curve_keys.size() != num_keys) || (mesh->curves.size() != num_curves)) { + if((mesh->curve_keys.size() != num_keys) || (mesh->curves.size() != num_curves)) { VLOG(1) << "Allocation failed, clearing data"; mesh->curve_keys.clear(); mesh->curves.clear(); diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index ce2d2700901..deae36f0130 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -324,15 +324,15 @@ static void attr_create_uv_map(Scene *scene, size_t i = 0; for(l->data.begin(t); t != l->data.end(); ++t, ++i) { - fdata[0] = get_float3(t->uv1()); - fdata[1] = get_float3(t->uv2()); - fdata[2] = get_float3(t->uv3()); + fdata[0] = get_float3(t->uv1()); + fdata[1] = get_float3(t->uv2()); + fdata[2] = get_float3(t->uv3()); fdata += 3; if(nverts[i] == 4) { - fdata[0] = get_float3(t->uv1()); - fdata[1] = get_float3(t->uv3()); - fdata[2] = get_float3(t->uv4()); + fdata[0] = get_float3(t->uv1()); + fdata[1] = get_float3(t->uv3()); + fdata[2] = get_float3(t->uv4()); fdata += 3; } } diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h index 580f50d5dd6..0b6ce3c7030 100644 --- a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h @@ -114,7 +114,7 @@ ccl_device int bsdf_ashikhmin_velvet_sample(const ShaderClosure *sc, float3 Ng, float sinNH2 = 1 - cosNH * cosNH; float sinNH4 = sinNH2 * sinNH2; - float cotangent2 = (cosNH * cosNH) / sinNH2; + float cotangent2 = (cosNH * cosNH) / sinNH2; float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4; float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically diff --git a/intern/cycles/kernel/geom/geom_bvh_shadow.h b/intern/cycles/kernel/geom/geom_bvh_shadow.h index 030283e903e..d2609fc029a 100644 --- a/intern/cycles/kernel/geom/geom_bvh_shadow.h +++ b/intern/cycles/kernel/geom/geom_bvh_shadow.h @@ -264,7 +264,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, if(kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE) #endif { - shader = kernel_tex_fetch(__tri_shader, prim); + shader = kernel_tex_fetch(__tri_shader, prim); } #ifdef __HAIR__ else { diff --git a/intern/cycles/kernel/geom/geom_motion_triangle.h b/intern/cycles/kernel/geom/geom_motion_triangle.h index d3297e05c67..a5a25f4a9ae 100644 --- a/intern/cycles/kernel/geom/geom_motion_triangle.h +++ b/intern/cycles/kernel/geom/geom_motion_triangle.h @@ -236,7 +236,7 @@ ccl_device_inline float3 motion_triangle_refine_subsurface(KernelGlobals *kg, Sh ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, bool subsurface) { /* get shader */ - sd->shader = kernel_tex_fetch(__tri_shader, sd->prim); + sd->shader = kernel_tex_fetch(__tri_shader, sd->prim); /* get motion info */ int numsteps, numverts; diff --git a/intern/cycles/kernel/geom/geom_qbvh_shadow.h b/intern/cycles/kernel/geom/geom_qbvh_shadow.h index f9fda39c3fc..2adebb28c28 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_shadow.h +++ b/intern/cycles/kernel/geom/geom_qbvh_shadow.h @@ -279,7 +279,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, if(kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE) #endif { - shader = kernel_tex_fetch(__tri_shader, prim); + shader = kernel_tex_fetch(__tri_shader, prim); } #ifdef __HAIR__ else { diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 71b2f7469e2..e9d9f72dfcd 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -87,7 +87,7 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, if(sd->type & PRIMITIVE_TRIANGLE) { /* static triangle */ float3 Ng = triangle_normal(kg, sd); - sd->shader = kernel_tex_fetch(__tri_shader, sd->prim); + sd->shader = kernel_tex_fetch(__tri_shader, sd->prim); /* vectors */ sd->P = triangle_refine(kg, sd, isect, ray); @@ -166,7 +166,7 @@ ccl_device_inline void shader_setup_from_subsurface(KernelGlobals *kg, ShaderDat /* fetch triangle data */ if(sd->type == PRIMITIVE_TRIANGLE) { float3 Ng = triangle_normal(kg, sd); - sd->shader = kernel_tex_fetch(__tri_shader, sd->prim); + sd->shader = kernel_tex_fetch(__tri_shader, sd->prim); /* static triangle */ sd->P = triangle_refine_subsurface(kg, sd, isect, ray); diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index f865cfb326e..bc89b7eb6ef 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -956,7 +956,7 @@ bool OSLRenderServices::texture3d(ustring filename, TextureOpt &options, else { OSLThreadData *tdata = kg->osl_tdata; OIIO::TextureSystem::Perthread *thread_info = tdata->oiio_thread_info; - OIIO::TextureSystem::TextureHandle *th = ts->get_texture_handle(filename, thread_info); + OIIO::TextureSystem::TextureHandle *th = ts->get_texture_handle(filename, thread_info); #if OIIO_VERSION < 10500 status = ts->texture3d(th, thread_info, options, P, dPdx, dPdy, dPdz, result); @@ -993,7 +993,7 @@ bool OSLRenderServices::environment(ustring filename, TextureOpt &options, OSLThreadData *tdata = kg->osl_tdata; OIIO::TextureSystem::Perthread *thread_info = tdata->oiio_thread_info; - OIIO::TextureSystem::TextureHandle *th = ts->get_texture_handle(filename, thread_info); + OIIO::TextureSystem::TextureHandle *th = ts->get_texture_handle(filename, thread_info); #if OIIO_VERSION < 10500 bool status = ts->environment(th, thread_info, -- cgit v1.2.3 From 33a92473347a9b9ee4e95c20e579ec97fd67ef63 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 6 Apr 2015 20:43:34 +0200 Subject: UI i18n cleanup... And some general style cleanup as well (line length...). --- .../modules/bl_i18n_utils/utils_spell_check.py | 1 + source/blender/editors/armature/pose_slide.c | 21 ++-- source/blender/editors/object/object_modifier.c | 2 +- source/blender/makesrna/intern/rna_camera.c | 16 ++- source/blender/makesrna/intern/rna_scene.c | 126 ++++++++++++--------- source/blender/makesrna/intern/rna_space.c | 2 +- source/blender/makesrna/intern/rna_wm.c | 2 +- source/blender/render/intern/source/pipeline.c | 2 +- 8 files changed, 104 insertions(+), 68 deletions(-) diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py index cdb3a3fedb5..669794799e6 100644 --- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py +++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py @@ -125,6 +125,7 @@ class SpellChecker: "multisampling", "multitexture", "multiuser", + "multiview", "namespace", "keyconfig", "online", diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index 17ef62b49af..09c8b4c370c 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -1226,13 +1226,20 @@ static int pose_propagate_exec(bContext *C, wmOperator *op) void POSE_OT_propagate(wmOperatorType *ot) { static EnumPropertyItem terminate_items[] = { - {POSE_PROPAGATE_SMART_HOLDS, "WHILE_HELD", 0, "While Held", "Propagate pose to all keyframes after current frame that don't change (Default behavior)"}, - {POSE_PROPAGATE_NEXT_KEY, "NEXT_KEY", 0, "To Next Keyframe", "Propagate pose to first keyframe following the current frame only"}, - {POSE_PROPAGATE_LAST_KEY, "LAST_KEY", 0, "To Last Keyframe", "Propagate pose to the last keyframe only (i.e. making action cyclic)"}, - {POSE_PROPAGATE_BEFORE_FRAME, "BEFORE_FRAME", 0, "Before Frame", "Propagate pose to all keyframes between current frame and 'Frame' property"}, - {POSE_PROPAGATE_BEFORE_END, "BEFORE_END", 0, "Before Last Keyframe", "Propagate pose to all keyframes from current frame until no more are found"}, - {POSE_PROPAGATE_SELECTED_KEYS, "SELECTED_KEYS", 0, "On Selected Keyframes", "Propagate pose to all keyframes that are selected"}, - {POSE_PROPAGATE_SELECTED_MARKERS, "SELECTED_MARKERS", 0, "On Selected Markers", "Propagate pose to all keyframes occurring on frames with Scene Markers after the current frame"}, + {POSE_PROPAGATE_SMART_HOLDS, "WHILE_HELD", 0, "While Held", + "Propagate pose to all keyframes after current frame that don't change (Default behavior)"}, + {POSE_PROPAGATE_NEXT_KEY, "NEXT_KEY", 0, "To Next Keyframe", + "Propagate pose to first keyframe following the current frame only"}, + {POSE_PROPAGATE_LAST_KEY, "LAST_KEY", 0, "To Last Keyframe", + "Propagate pose to the last keyframe only (i.e. making action cyclic)"}, + {POSE_PROPAGATE_BEFORE_FRAME, "BEFORE_FRAME", 0, "Before Frame", + "Propagate pose to all keyframes between current frame and 'Frame' property"}, + {POSE_PROPAGATE_BEFORE_END, "BEFORE_END", 0, "Before Last Keyframe", + "Propagate pose to all keyframes from current frame until no more are found"}, + {POSE_PROPAGATE_SELECTED_KEYS, "SELECTED_KEYS", 0, "On Selected Keyframes", + "Propagate pose to all selected keyframes"}, + {POSE_PROPAGATE_SELECTED_MARKERS, "SELECTED_MARKERS", 0, "On Selected Markers", + "Propagate pose to all keyframes occurring on frames with Scene Markers after the current frame"}, {0, NULL, 0, NULL, NULL}}; /* identifiers */ diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 9a0377d28ad..ac5ec1976ab 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -1870,7 +1870,7 @@ void OBJECT_OT_correctivesmooth_bind(wmOperatorType *ot) { /* identifiers */ ot->name = "Corrective Smooth Bind"; - ot->description = "Bind base pose in delta mush modifier"; + ot->description = "Bind base pose in Corrective Smooth modifier"; ot->idname = "OBJECT_OT_correctivesmooth_bind"; /* api callbacks */ diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index b63e2f97da8..2baaa5f7cec 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -95,7 +95,7 @@ static void rna_def_camera_stereo_data(BlenderRNA *brna) PropertyRNA *prop; static EnumPropertyItem convergence_mode_items[] = { - {CAM_S3D_OFFAXIS, "OFFAXIS", 0, "Off-Axis", "Off-axis frustrums converging in a plane"}, + {CAM_S3D_OFFAXIS, "OFFAXIS", 0, "Off-Axis", "Off-axis frustums converging in a plane"}, {CAM_S3D_PARALLEL, "PARALLEL", 0, "Parallel", "Parallel cameras with no convergence"}, {CAM_S3D_TOE, "TOE", 0, "Toe-in", "Rotated cameras, looking at the convergence distance"}, {0, NULL, 0, NULL, NULL} @@ -126,20 +126,25 @@ static void rna_def_camera_stereo_data(BlenderRNA *brna) prop = RNA_def_property(srna, "interocular_distance", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_range(prop, 0.0f, 100.0f); RNA_def_property_ui_range(prop, 0.0f, 1.f, 1, 2); - RNA_def_property_ui_text(prop, "Interocular Distance", "Set the distance between the eyes - the stereo plane distance / 30 should be fine"); + RNA_def_property_ui_text(prop, "Interocular Distance", + "Set the distance between the eyes - the stereo plane distance / 30 should be fine"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); prop = RNA_def_property(srna, "convergence_distance", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_range(prop, 0.00001f, FLT_MAX); RNA_def_property_ui_range(prop, 0.0f, 15.f, 1, 2); - RNA_def_property_ui_text(prop, "Convergence Plane Distance", "The converge point for the stereo cameras (often the distance between a projector and the projection screen)"); + RNA_def_property_ui_text(prop, "Convergence Plane Distance", + "The converge point for the stereo cameras " + "(often the distance between a projector and the projection screen)"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); prop = RNA_def_property(srna, "viewport_convergence", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "convergence_distance"); RNA_def_property_range(prop, 0.00001f, FLT_MAX); RNA_def_property_ui_range(prop, 0.0f, 15.f, 1, 2); - RNA_def_property_ui_text(prop, "Viewport Convergence", "Preview convergence distance for the stereo effect in the viewport. It doesn't affect the render!"); + RNA_def_property_ui_text(prop, "Viewport Convergence", + "Preview convergence distance for the stereo effect in the viewport " + "(it does not affect the render!)"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); } @@ -326,7 +331,8 @@ void RNA_def_camera(BlenderRNA *brna) prop = RNA_def_property(srna, "show_safe_center", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_SHOW_SAFE_CENTER); - RNA_def_property_ui_text(prop, "Show Center-cut safe areas", "Show safe areas to fit content in a different aspect ratio"); + RNA_def_property_ui_text(prop, "Show Center-cut safe areas", + "Show safe areas to fit content in a different aspect ratio"); RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL); prop = RNA_def_property(srna, "show_name", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index a59724f4a16..3bcac9c6696 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -338,8 +338,10 @@ EnumPropertyItem bake_save_mode_items[] = { {0, NULL, 0, NULL, NULL} }; -#define R_IMF_VIEWS_ENUM_IND {R_IMF_VIEWS_INDIVIDUAL, "INDIVIDUAL", 0, "Individual", "Individual files for each view with the prefix as defined by the scene views"}, -#define R_IMF_VIEWS_ENUM_S3D {R_IMF_VIEWS_STEREO_3D, "STEREO_3D", 0, "Stereo 3D", "Single file with an encoded stereo pair"}, +#define R_IMF_VIEWS_ENUM_IND {R_IMF_VIEWS_INDIVIDUAL, "INDIVIDUAL", 0, "Individual", \ + "Individual files for each view with the prefix as defined by the scene views"}, +#define R_IMF_VIEWS_ENUM_S3D {R_IMF_VIEWS_STEREO_3D, "STEREO_3D", 0, "Stereo 3D", \ + "Single file with an encoded stereo pair"}, #define R_IMF_VIEWS_ENUM_MV {R_IMF_VIEWS_MULTIVIEW, "MULTIVIEW", 0, "Multi-View", "Single file with all the views"}, EnumPropertyItem views_format_items[] = { @@ -366,13 +368,17 @@ EnumPropertyItem views_format_multiview_items[] = { #undef R_IMF_VIEWS_ENUM_MV EnumPropertyItem stereo3d_display_items[] = { - {S3D_DISPLAY_ANAGLYPH, "ANAGLYPH", 0, "Anaglyph", "Render two differently filtered colored images for each eye. Anaglyph glasses are required"}, - {S3D_DISPLAY_INTERLACE, "INTERLACE", 0, "Interlace", "Render two images for each eye into one interlaced image. 3D-ready monitor is requiered"}, + {S3D_DISPLAY_ANAGLYPH, "ANAGLYPH", 0, "Anaglyph", + "Render views for left and right eyes as two differently filtered colors in a single image " + "(anaglyph glasses are required)"}, + {S3D_DISPLAY_INTERLACE, "INTERLACE", 0, "Interlace", + "Render views for left and right eyes interlaced in a single image (3D-ready monitor is required)"}, #ifdef DEBUG /* MULTIVIEW_TODO: quadbuffer mode not fully working */ - {S3D_DISPLAY_PAGEFLIP, "TIMESEQUENTIAL", 0, "Time Sequential", "Renders alternate eyes (also known as pageflip). It requires Quadbuffer support in the graphic card"}, + {S3D_DISPLAY_PAGEFLIP, "TIMESEQUENTIAL", 0, "Time Sequential", + "Render alternate eyes (also known as page flip, quad buffer support in the graphic card is required)"}, #endif - {S3D_DISPLAY_SIDEBYSIDE, "SIDEBYSIDE", 0, "Side-by-Side", "Render images for left and right eye side-by-side"}, - {S3D_DISPLAY_TOPBOTTOM, "TOPBOTTOM", 0, "Top-Bottom", "Render images for left and right eye one above another"}, + {S3D_DISPLAY_SIDEBYSIDE, "SIDEBYSIDE", 0, "Side-by-Side", "Render views for left and right eyes side-by-side"}, + {S3D_DISPLAY_TOPBOTTOM, "TOPBOTTOM", 0, "Top-Bottom", "Render views for left and right eyes one above another"}, {0, NULL, 0, NULL, NULL} }; @@ -899,8 +905,8 @@ static void rna_ImageFormatSettings_file_format_set(PointerRNA *ptr, int value) } } -static EnumPropertyItem *rna_ImageFormatSettings_file_format_itemf(bContext *UNUSED(C), PointerRNA *ptr, - PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) +static EnumPropertyItem *rna_ImageFormatSettings_file_format_itemf( + bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) { ID *id = ptr->id.data; if (id && GS(id->name) == ID_SCE) { @@ -911,8 +917,8 @@ static EnumPropertyItem *rna_ImageFormatSettings_file_format_itemf(bContext *UNU } } -static EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf(bContext *UNUSED(C), PointerRNA *ptr, - PropertyRNA *UNUSED(prop), bool *r_free) +static EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf( + bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { ImageFormatData *imf = (ImageFormatData *)ptr->data; ID *id = ptr->id.data; @@ -956,8 +962,8 @@ static EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf(bContext *UNUS } } -static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf(bContext *UNUSED(C), PointerRNA *ptr, - PropertyRNA *UNUSED(prop), bool *r_free) +static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf( + bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { ImageFormatData *imf = (ImageFormatData *)ptr->data; @@ -1019,8 +1025,8 @@ static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf(bContext *UNU } } -static EnumPropertyItem *rna_ImageFormatSettings_views_format_itemf(bContext *UNUSED(C), PointerRNA *ptr, -PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) +static EnumPropertyItem *rna_ImageFormatSettings_views_format_itemf( + bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) { ImageFormatData *imf = (ImageFormatData *)ptr->data; @@ -1041,8 +1047,8 @@ PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) #ifdef WITH_OPENEXR /* OpenEXR */ -static EnumPropertyItem *rna_ImageFormatSettings_exr_codec_itemf(bContext *UNUSED(C), PointerRNA *ptr, -PropertyRNA *UNUSED(prop), bool *r_free) +static EnumPropertyItem *rna_ImageFormatSettings_exr_codec_itemf( + bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { ImageFormatData *imf = (ImageFormatData *)ptr->data; @@ -1098,8 +1104,8 @@ static void rna_RenderSettings_qtcodecsettings_codecType_set(PointerRNA *ptr, in settings->codecType = quicktime_videocodecType_from_rnatmpvalue(value); } -static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_codecType_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), - PropertyRNA *UNUSED(prop), bool *r_free) +static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_codecType_itemf( + bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) { EnumPropertyItem *item = NULL; EnumPropertyItem tmp = {0, "", 0, "", ""}; @@ -1136,8 +1142,8 @@ static void rna_RenderSettings_qtcodecsettings_audiocodecType_set(PointerRNA *pt settings->audiocodecType = quicktime_audiocodecType_from_rnatmpvalue(value); } -static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_audiocodecType_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), - PropertyRNA *UNUSED(prop), bool *r_free) +static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_audiocodecType_itemf( + bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) { EnumPropertyItem *item = NULL; EnumPropertyItem tmp = {0, "", 0, "", ""}; @@ -1197,8 +1203,8 @@ static void rna_RenderSettings_active_layer_index_set(PointerRNA *ptr, int value rd->actlay = min_ff(value, num_layers - 1); } -static void rna_RenderSettings_active_layer_index_range(PointerRNA *ptr, int *min, int *max, - int *UNUSED(softmin), int *UNUSED(softmax)) +static void rna_RenderSettings_active_layer_index_range( + PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { RenderData *rd = (RenderData *)ptr->data; @@ -1233,8 +1239,8 @@ static SceneRenderLayer *rna_RenderLayer_new(ID *id, RenderData *UNUSED(rd), con return srl; } -static void rna_RenderLayer_remove(ID *id, RenderData *UNUSED(rd), Main *bmain, ReportList *reports, - PointerRNA *srl_ptr) +static void rna_RenderLayer_remove( + ID *id, RenderData *UNUSED(rd), Main *bmain, ReportList *reports, PointerRNA *srl_ptr) { SceneRenderLayer *srl = srl_ptr->data; Scene *scene = (Scene *)id; @@ -1263,7 +1269,8 @@ static void rna_RenderSettings_active_view_index_set(PointerRNA *ptr, int value) rd->actview = value; } -static void rna_RenderSettings_active_view_index_range(PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) +static void rna_RenderSettings_active_view_index_range( + PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { RenderData *rd = (RenderData *)ptr->data; @@ -1297,8 +1304,8 @@ static SceneRenderView *rna_RenderView_new(ID *id, RenderData *UNUSED(rd), const return srv; } -static void rna_RenderView_remove(ID *id, RenderData *UNUSED(rd), Main *UNUSED(bmain), ReportList *reports, - PointerRNA *srv_ptr) +static void rna_RenderView_remove( + ID *id, RenderData *UNUSED(rd), Main *UNUSED(bmain), ReportList *reports, PointerRNA *srv_ptr) { SceneRenderView *srv = srv_ptr->data; Scene *scene = (Scene *)id; @@ -1323,8 +1330,8 @@ static void rna_RenderSettings_engine_set(PointerRNA *ptr, int value) BLI_strncpy_utf8(rd->engine, type->idname, sizeof(rd->engine)); } -static EnumPropertyItem *rna_RenderSettings_engine_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), - PropertyRNA *UNUSED(prop), bool *r_free) +static EnumPropertyItem *rna_RenderSettings_engine_itemf( + bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) { RenderEngineType *type; EnumPropertyItem *item = NULL; @@ -1822,7 +1829,8 @@ static void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr, PointerRNA value lineset->linestyle->id.us++; } -static FreestyleLineSet *rna_FreestyleSettings_lineset_add(ID *id, FreestyleSettings *config, Main *bmain, const char *name) +static FreestyleLineSet *rna_FreestyleSettings_lineset_add( + ID *id, FreestyleSettings *config, Main *bmain, const char *name) { Scene *scene = (Scene *)id; FreestyleLineSet *lineset = BKE_freestyle_lineset_add(bmain, (FreestyleConfig *)config, name); @@ -1833,8 +1841,8 @@ static FreestyleLineSet *rna_FreestyleSettings_lineset_add(ID *id, FreestyleSett return lineset; } -static void rna_FreestyleSettings_lineset_remove(ID *id, FreestyleSettings *config, ReportList *reports, - PointerRNA *lineset_ptr) +static void rna_FreestyleSettings_lineset_remove( + ID *id, FreestyleSettings *config, ReportList *reports, PointerRNA *lineset_ptr) { FreestyleLineSet *lineset = lineset_ptr->data; Scene *scene = (Scene *)id; @@ -1857,8 +1865,8 @@ static PointerRNA rna_FreestyleSettings_active_lineset_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_FreestyleLineSet, lineset); } -static void rna_FreestyleSettings_active_lineset_index_range(PointerRNA *ptr, int *min, int *max, - int *UNUSED(softmin), int *UNUSED(softmax)) +static void rna_FreestyleSettings_active_lineset_index_range( + PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { FreestyleConfig *config = (FreestyleConfig *)ptr->data; @@ -1889,8 +1897,8 @@ static FreestyleModuleConfig *rna_FreestyleSettings_module_add(ID *id, Freestyle return module; } -static void rna_FreestyleSettings_module_remove(ID *id, FreestyleSettings *config, ReportList *reports, - PointerRNA *module_ptr) +static void rna_FreestyleSettings_module_remove( + ID *id, FreestyleSettings *config, ReportList *reports, PointerRNA *module_ptr) { Scene *scene = (Scene *)id; FreestyleModuleConfig *module = module_ptr->data; @@ -2054,9 +2062,11 @@ static void rna_def_tool_settings(BlenderRNA *brna) static EnumPropertyItem gpencil_source_3d_items[] = { {GP_TOOL_SOURCE_SCENE, "SCENE", 0, "Scene", - "Grease Pencil data attached to the current scene is used, unless the active object already has Grease Pencil data (i.e. for old files)"}, + "Grease Pencil data attached to the current scene is used, " + "unless the active object already has Grease Pencil data (i.e. for old files)"}, {GP_TOOL_SOURCE_OBJECT, "OBJECT", 0, "Object", - "Grease Pencil datablocks attached to the active object are used (required using pre 2.73 add-ons, e.g. BSurfaces)"}, + "Grease Pencil datablocks attached to the active object are used " + "(required using pre 2.73 add-ons, e.g. BSurfaces)"}, {0, NULL, 0, NULL, NULL} }; @@ -2338,7 +2348,8 @@ static void rna_def_tool_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "use_etch_autoname", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "skgen_retarget_options", SK_RETARGET_AUTONAME); - RNA_def_property_ui_text(prop, "Autoname Bones", "Automatically generate values to replace &N and &S suffix placeholders in template names"); + RNA_def_property_ui_text(prop, "Autoname Bones", + "Automatically generate values to replace &N and &S suffix placeholders in template names"); prop = RNA_def_property(srna, "etch_number", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "skgen_num_string"); @@ -3226,12 +3237,14 @@ static void rna_def_freestyle_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "face_mark_condition", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags"); RNA_def_property_enum_items(prop, face_mark_condition_items); - RNA_def_property_ui_text(prop, "Face Mark Condition", "Specify a feature edge selection condition based on face marks"); + RNA_def_property_ui_text(prop, "Face Mark Condition", + "Specify a feature edge selection condition based on face marks"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update"); prop = RNA_def_property(srna, "select_silhouette", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_SILHOUETTE); - RNA_def_property_ui_text(prop, "Silhouette", "Select silhouettes (edges at the boundary of visible and hidden faces)"); + RNA_def_property_ui_text(prop, "Silhouette", + "Select silhouettes (edges at the boundary of visible and hidden faces)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update"); prop = RNA_def_property(srna, "select_border", PROP_BOOLEAN, PROP_NONE); @@ -3241,12 +3254,14 @@ static void rna_def_freestyle_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "select_crease", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_CREASE); - RNA_def_property_ui_text(prop, "Crease", "Select crease edges (those between two faces making an angle smaller than the Crease Angle)"); + RNA_def_property_ui_text(prop, "Crease", + "Select crease edges (those between two faces making an angle smaller than the Crease Angle)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update"); prop = RNA_def_property(srna, "select_ridge_valley", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_RIDGE_VALLEY); - RNA_def_property_ui_text(prop, "Ridge & Valley", "Select ridges and valleys (boundary lines between convex and concave areas of surface)"); + RNA_def_property_ui_text(prop, "Ridge & Valley", + "Select ridges and valleys (boundary lines between convex and concave areas of surface)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update"); prop = RNA_def_property(srna, "select_suggestive_contour", PROP_BOOLEAN, PROP_NONE); @@ -3266,7 +3281,8 @@ static void rna_def_freestyle_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "select_external_contour", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_EXTERNAL_CONTOUR); - RNA_def_property_ui_text(prop, "External Contour", "Select external contours (outer silhouettes of occluding and occluded objects)"); + RNA_def_property_ui_text(prop, "External Contour", + "Select external contours (outer silhouettes of occluding and occluded objects)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update"); prop = RNA_def_property(srna, "select_edge_mark", PROP_BOOLEAN, PROP_NONE); @@ -3415,7 +3431,8 @@ static void rna_def_freestyle_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "use_view_map_cache", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_VIEW_MAP_CACHE); - RNA_def_property_ui_text(prop, "View Map Cache", "Keep the computed view map and avoid re-calculating it if mesh geometry is unchanged"); + RNA_def_property_ui_text(prop, "View Map Cache", + "Keep the computed view map and avoid re-calculating it if mesh geometry is unchanged"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_use_view_map_cache_update"); prop = RNA_def_property(srna, "sphere_radius", PROP_FLOAT, PROP_NONE); @@ -4223,7 +4240,8 @@ static void rna_def_gpu_fx(BlenderRNA *brna) prop = RNA_def_property(srna, "use_dof", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "fx_flag", GPU_FX_FLAG_DOF); - RNA_def_property_ui_text(prop, "Depth Of Field", "Use depth of field on viewport using the values from active camera"); + RNA_def_property_ui_text(prop, "Depth Of Field", + "Use depth of field on viewport using the values from active camera"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUFXSettings_fx_update"); @@ -4331,7 +4349,8 @@ static void rna_def_scene_render_view(BlenderRNA *brna) prop = RNA_def_property(srna, "camera_suffix", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "suffix"); - RNA_def_property_ui_text(prop, "Camera Suffix", "Suffix to identify the cameras to use, and added to the render images for this view"); + RNA_def_property_ui_text(prop, "Camera Suffix", + "Suffix to identify the cameras to use, and added to the render images for this view"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE); @@ -4391,10 +4410,13 @@ static void rna_def_image_format_stereo3d_format(BlenderRNA *brna) PropertyRNA *prop; static EnumPropertyItem stereo3d_display_items[] = { - {S3D_DISPLAY_ANAGLYPH, "ANAGLYPH", 0, "Anaglyph", "Render two differently filtered colored images for each eye. Anaglyph glasses are required"}, - {S3D_DISPLAY_INTERLACE, "INTERLACE", 0, "Interlace", "Render two images for each eye into one interlaced image. 3D-ready monitor is requiered"}, - {S3D_DISPLAY_SIDEBYSIDE, "SIDEBYSIDE", 0, "Side-by-Side", "Render images for left and right eye side-by-side"}, - {S3D_DISPLAY_TOPBOTTOM, "TOPBOTTOM", 0, "Top-Bottom", "Render images for left and right eye one above another"}, + {S3D_DISPLAY_ANAGLYPH, "ANAGLYPH", 0, "Anaglyph", + "Render views for left and right eyes as two differently filtered colors in a single image " + "(anaglyph glasses are required)"}, + {S3D_DISPLAY_INTERLACE, "INTERLACE", 0, "Interlace", + "Render views for left and right eyes interlaced in a single image (3D-ready monitor is required)"}, + {S3D_DISPLAY_SIDEBYSIDE, "SIDEBYSIDE", 0, "Side-by-Side", "Render views for left and right eyes side-by-side"}, + {S3D_DISPLAY_TOPBOTTOM, "TOPBOTTOM", 0, "Top-Bottom", "Render views for left and right eyes one above another"}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 4a4c2a34fdf..8e573e08815 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2592,7 +2592,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) prop = RNA_def_property(srna, "stereo_3d_volume_alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "stereo3d_volume_alpha"); - RNA_def_property_ui_text(prop, "Volume Alpha", "Opacity (alpha) of the cameras frustum volume"); + RNA_def_property_ui_text(prop, "Volume Alpha", "Opacity (alpha) of the cameras' frustum volume"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* *** Animated *** */ diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index dcd77e5a0f6..28881b0b40c 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -1758,7 +1758,7 @@ static void rna_def_window_stereo3d(BlenderRNA *brna) srna = RNA_def_struct(brna, "Stereo3dDisplay", NULL); RNA_def_struct_sdna(srna, "Stereo3dFormat"); RNA_def_struct_clear_flag(srna, STRUCT_UNDO); - RNA_def_struct_ui_text(srna, "Stereo 3d Display", "Settings for stereo 3d display"); + RNA_def_struct_ui_text(srna, "Stereo 3D Display", "Settings for stereo 3D display"); prop = RNA_def_property(srna, "display_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, stereo3d_display_items); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 25adb4db4f7..4a767184c44 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -3732,7 +3732,7 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char break; if (rpass == NULL) - BKE_reportf(reports, RPT_ERROR, "RE_layer_load_from_file: no Combined pass found in the render layer '%s'", filename); + BKE_reportf(reports, RPT_ERROR, "%s: no Combined pass found in the render layer '%s'", __func__, filename); if (ibuf && (ibuf->rect || ibuf->rect_float)) { if (ibuf->x == layer->rectx && ibuf->y == layer->recty) { -- cgit v1.2.3 From bcc9a235487e9607204475ce66140d4cef3d59bf Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 6 Apr 2015 23:10:21 +0200 Subject: Various Sticky fixes (tm) * Revert 776bfa64a53191b and c3dad7953afccd4 (some X11 systems are doing stupid things forcing me to do an extra check that completely breaks the click type handling on other systems using the slightly changed implementation from those commits - see T44278) * Fix sample lines in Compositor+VSE (And yes, this time I tested on both of my systems to make sure everything is fine) --- source/blender/editors/interface/interface_eyedropper.c | 4 ++++ source/blender/editors/mesh/editmesh_extrude.c | 4 ++++ source/blender/editors/space_image/image_ops.c | 10 +++++----- source/blender/editors/space_node/node_view.c | 7 +++++-- source/blender/editors/space_sequencer/sequencer_view.c | 6 ++++-- source/blender/windowmanager/intern/wm_event_system.c | 12 +----------- source/blender/windowmanager/intern/wm_window.c | 15 +++++++++++---- 7 files changed, 34 insertions(+), 24 deletions(-) diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index f5847a9d701..96f9b87611f 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -277,6 +277,10 @@ static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event) eyedropper_cancel(C, op); return OPERATOR_CANCELLED; case LEFTMOUSE: + /* two release events are sent on KM_CLICK, so ignore second one */ + if (event->click_type == KM_CLICK) { + break; + } if (event->val == KM_RELEASE) { if (eye->accum_tot == 0) { eyedropper_color_sample(C, eye, event->x, event->y); diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 5c7efcc40da..5cdd45061e1 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -511,6 +511,10 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w bool done = false; bool use_proj; + if (ELEM(event->click_type, KM_CLICK, KM_HOLD)) { + return OPERATOR_CANCELLED; + } + em_setup_viewcontext(C, &vc); ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 6a5462bff45..aa625210464 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -2950,11 +2950,11 @@ static int image_sample_modal(bContext *C, wmOperator *op, const wmEvent *event) switch (event->type) { case LEFTMOUSE: case RIGHTMOUSE: // XXX hardcoded - if (event->val == KM_RELEASE) { - image_sample_exit(C, op); - return OPERATOR_CANCELLED; - } - break; + if (event->val == KM_RELEASE) { + image_sample_exit(C, op); + return OPERATOR_CANCELLED; + } + break; case MOUSEMOVE: image_sample_apply(C, op, event); break; diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index 3491ecc86af..dda84eb0cbf 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -609,8 +609,11 @@ static int sample_modal(bContext *C, wmOperator *op, const wmEvent *event) switch (event->type) { case LEFTMOUSE: case RIGHTMOUSE: // XXX hardcoded - sample_exit(C, op); - return OPERATOR_CANCELLED; + if (event->val == KM_RELEASE) { + sample_exit(C, op); + return OPERATOR_CANCELLED; + } + break; case MOUSEMOVE: sample_apply(C, op, event); break; diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index 4eafd2f86a8..37ac600f22c 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -201,8 +201,10 @@ static int sample_modal(bContext *C, wmOperator *op, const wmEvent *event) switch (event->type) { case LEFTMOUSE: case RIGHTMOUSE: /* XXX hardcoded */ - sample_exit(C, op); - return OPERATOR_CANCELLED; + if (event->val == KM_RELEASE) { + sample_exit(C, op); + return OPERATOR_CANCELLED; + } case MOUSEMOVE: sample_apply(C, op, event); break; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 225e3138859..8c013eb7cd4 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2994,7 +2994,7 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi * - #KM_PRESS && time since first #KM_PRESS > U.click_timeout --> send #KM_HOLD * - #KM_PRESS after a #KM_RELEASE && time since previous #KM_PRESS < U.dbl_click_time --> send #KM_DBL_CLICK * - * \note: only #KM_DBL_CLICK and #KM_CLICK are handled here, #KM_HOLD in #wm_window_event_clicktype_init (wm_window.c) + * \note: only #KM_DBL_CLICK is handled here, rest in #wm_window_event_clicktype_init (wm_window.c) */ static void wm_event_clicktype_init(wmWindow *win, wmEvent *event, wmEvent *event_state) { @@ -3025,16 +3025,6 @@ static void wm_event_clicktype_init(wmWindow *win, wmEvent *event, wmEvent *even } } - /* click */ - if ((PIL_check_seconds_timer() - event->click_time) * 1000 <= U.click_timeout) { - if (event->val == KM_RELEASE) { - click_type = KM_CLICK; - if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) { - printf("%s Send click event\n", __func__); - } - } - } - if (click_type != event->click_type) { event_state->click_type = event->click_type = click_type; } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 4b98f8bf71d..61bddb144ae 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1107,9 +1107,9 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr } /** - * #KM_DBL_CLICK and #KM_CLICK are set in wm_event_clicktype_init (wm_event_system.c) - * Normally, #KM_HOLD should be there too, but we need a time precision of a few - * milliseconds for it, which we can't get from there + * #KM_DBL_CLICK is set in wm_event_clicktype_init (wm_event_system.c) + * Normally, this should be there too, but for #KM_CLICK/#KM_HOLD, we need a + * time precision of a few milliseconds, which we can't get from there */ static void wm_window_event_clicktype_init(const bContext *C) { @@ -1150,7 +1150,14 @@ static void wm_window_event_clicktype_init(const bContext *C) /* the actual test */ if ((PIL_check_seconds_timer() - event->click_time) * 1000 <= U.click_timeout) { - /* sending of KM_CLICK is handled in wm_event_clicktype_init (wm_event_system.c) */ + /* for any reason some X11 systems send two release events triggering two KM_CLICK + * events - making the rules more strict by checking for prevval resolves this */ + if (event->val == KM_RELEASE && event->prevval != KM_RELEASE) { + click_type = KM_CLICK; + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) { + printf("%s Send click event\n", __func__); + } + } } else if (event->is_key_pressed) { click_type = KM_HOLD; -- cgit v1.2.3 From d3388f0c7aa1e51821c9d0fcab92fb513aaff6cf Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 6 Apr 2015 23:15:57 +0200 Subject: Fix compilation error in Win Debug. --- intern/ghost/intern/GHOST_ContextWGL.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/intern/ghost/intern/GHOST_ContextWGL.cpp b/intern/ghost/intern/GHOST_ContextWGL.cpp index 979dc549498..4f4cab77602 100644 --- a/intern/ghost/intern/GHOST_ContextWGL.cpp +++ b/intern/ghost/intern/GHOST_ContextWGL.cpp @@ -120,9 +120,9 @@ GHOST_ContextWGL::~GHOST_ContextWGL() #endif #ifndef NDEBUG - free(m_dummyRenderer); - free(m_dummyVendor); - free(m_dummyVersion); + free((void*)m_dummyRenderer); + free((void*)m_dummyVendor); + free((void*)m_dummyVersion); #endif } @@ -393,9 +393,9 @@ void GHOST_ContextWGL::initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD) // the following are not technially WGLEW, but they also require a context to work #ifndef NDEBUG - free(m_dummyRenderer); - free(m_dummyVendor); - free(m_dummyVersion); + free((void*)m_dummyRenderer); + free((void*)m_dummyVendor); + free((void*)m_dummyVersion); m_dummyRenderer = _strdup(reinterpret_cast(glGetString(GL_RENDERER))); m_dummyVendor = _strdup(reinterpret_cast(glGetString(GL_VENDOR))); -- cgit v1.2.3 From 3dcdacffca031869737b8939d1957b0f4daca349 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 6 Apr 2015 23:23:13 +0200 Subject: This commit doesn't deserve a title Today just wasn't my day... --- source/blender/editors/space_sequencer/sequencer_view.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index 37ac600f22c..4d6ea865b40 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -205,6 +205,7 @@ static int sample_modal(bContext *C, wmOperator *op, const wmEvent *event) sample_exit(C, op); return OPERATOR_CANCELLED; } + break; case MOUSEMOVE: sample_apply(C, op, event); break; -- cgit v1.2.3 From 1b9f1519bc5c8d1739371f417cc8b23a8d483c8e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 7 Apr 2015 08:46:48 +1000 Subject: Cleanup --- source/blender/blenkernel/BKE_writeframeserver.h | 10 ++++++---- source/blender/blenkernel/intern/sequencer.c | 2 +- source/blender/blenlib/intern/BLI_filelist.c | 2 +- source/blender/blenloader/intern/versioning_270.c | 3 +-- source/blender/editors/space_view3d/view3d_draw.c | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/BKE_writeframeserver.h b/source/blender/blenkernel/BKE_writeframeserver.h index 2f8bce31e41..0837e9bce79 100644 --- a/source/blender/blenkernel/BKE_writeframeserver.h +++ b/source/blender/blenkernel/BKE_writeframeserver.h @@ -40,11 +40,13 @@ struct RenderData; struct ReportList; struct Scene; -int BKE_frameserver_start(void *context_v, struct Scene *scene, struct RenderData *rd, int rectx, int recty, - struct ReportList *reports, bool preview, const char *suffix); +int BKE_frameserver_start( + void *context_v, struct Scene *scene, struct RenderData *rd, int rectx, int recty, + struct ReportList *reports, bool preview, const char *suffix); void BKE_frameserver_end(void *context_v); -int BKE_frameserver_append(void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels, - int rectx, int recty, const char*suffix, struct ReportList *reports); +int BKE_frameserver_append( + void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels, + int rectx, int recty, const char *suffix, struct ReportList *reports); int BKE_frameserver_loop(void *context_v, struct RenderData *rd, struct ReportList *reports); void *BKE_frameserver_context_create(void); void BKE_frameserver_context_free(void *context_v); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 942426febdd..8c803f86979 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -867,7 +867,7 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r seq_multiview_name(scene, i, prefix, ext, str, FILE_MAX); anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), - seq->streamindex, seq->strip->colorspace_settings.name); + seq->streamindex, seq->strip->colorspace_settings.name); seq_anim_add_suffix(scene, anim, i); if (anim) { diff --git a/source/blender/blenlib/intern/BLI_filelist.c b/source/blender/blenlib/intern/BLI_filelist.c index f032b753a77..81813ce1f62 100644 --- a/source/blender/blenlib/intern/BLI_filelist.c +++ b/source/blender/blenlib/intern/BLI_filelist.c @@ -18,7 +18,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/blenlib/intern/filelist.c +/** \file blender/blenlib/intern/BLI_filelist.c * \ingroup bli */ diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 3201a81d90c..70c7cc9e878 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -730,8 +730,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) #undef SEQ_USE_PROXY_CUSTOM_FILE } - if (!MAIN_VERSION_ATLEAST(main, 274, 4)) - { + if (!MAIN_VERSION_ATLEAST(main, 274, 4)) { SceneRenderView *srv; wmWindowManager *wm; bScreen *screen; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 95a1ab87348..195dffe74a0 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -3264,7 +3264,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in BKE_camera_to_gpu_dof(camera, &fx_settings); ED_view3d_draw_offscreen( - scene, v3d, ar, sizex, sizey, NULL, params.winmat, + scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background, draw_sky, !params.is_ortho, ofs, NULL, &fx_settings, viewname); } -- cgit v1.2.3 From 808de65d9124d54ce82bcb1a4d84a78b3be7288c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 7 Apr 2015 10:53:20 +1000 Subject: EdgeHash: ensure function, avoids multiple lookups --- source/blender/blenlib/BLI_edgehash.h | 1 + source/blender/blenlib/intern/edgehash.c | 59 ++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/source/blender/blenlib/BLI_edgehash.h b/source/blender/blenlib/BLI_edgehash.h index ded4b163f71..20272dd97cd 100644 --- a/source/blender/blenlib/BLI_edgehash.h +++ b/source/blender/blenlib/BLI_edgehash.h @@ -54,6 +54,7 @@ bool BLI_edgehash_reinsert(EdgeHash *eh, unsigned int v0, unsigned in void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT; void *BLI_edgehash_lookup_default(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val_default) ATTR_WARN_UNUSED_RESULT; void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT; +bool BLI_edgehash_ensure_p(EdgeHash *eh, unsigned int v0, unsigned int v1, void ***r_val) ATTR_WARN_UNUSED_RESULT; bool BLI_edgehash_remove(EdgeHash *eh, unsigned int v0, unsigned int v1, EdgeHashFreeFP valfreefp); void *BLI_edgehash_popkey(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c index 82d57dad753..fd7ad4db44b 100644 --- a/source/blender/blenlib/intern/edgehash.c +++ b/source/blender/blenlib/intern/edgehash.c @@ -231,6 +231,31 @@ BLI_INLINE void edgehash_insert_ex_keyonly(EdgeHash *eh, unsigned int v0, unsign { EdgeEntry *e = BLI_mempool_alloc(eh->epool); + BLI_assert((eh->flag & EDGEHASH_FLAG_ALLOW_DUPES) || (BLI_edgehash_haskey(eh, v0, v1) == 0)); + IS_EDGEHASH_ASSERT(eh); + + /* this helps to track down errors with bad edge data */ + BLI_assert(v0 < v1); + BLI_assert(v0 != v1); + + e->next = eh->buckets[hash]; + e->v0 = v0; + e->v1 = v1; + eh->buckets[hash] = e; + + if (UNLIKELY(edgehash_test_expand_buckets(++eh->nentries, eh->nbuckets))) { + edgehash_resize_buckets(eh, _ehash_hashsizes[++eh->cursize]); + } +} + +/** + * Insert function that doesn't set the value (use for EdgeSet) + */ +BLI_INLINE void edgehash_insert_ex_keyonly_entry( + EdgeHash *eh, unsigned int v0, unsigned int v1, + unsigned int hash, + EdgeEntry *e) +{ BLI_assert((eh->flag & EDGEHASH_FLAG_ALLOW_DUPES) || (BLI_edgehash_haskey(eh, v0, v1) == 0)); /* this helps to track down errors with bad edge data */ @@ -372,6 +397,40 @@ void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1) return e ? &e->val : NULL; } +/** + * Ensure \a (v0, v1) is exists in \a eh. + * + * This handles the common situation where the caller needs ensure a key is added to \a eh, + * constructing a new value in the case the key isn't found. + * Otherwise use the existing value. + * + * Such situations typically incur multiple lookups, however this function + * avoids them by ensuring the key is added, + * returning a pointer to the value so it can be used or initialized by the caller. + * + * \returns true when the value didn't need to be added. + * (when false, the caller _must_ initialize the value). + */ +bool BLI_edgehash_ensure_p(EdgeHash *eh, unsigned int v0, unsigned int v1, void ***r_val) +{ + unsigned int hash; + EdgeEntry *e; + bool haskey; + + EDGE_ORD(v0, v1); /* ensure v0 is smaller */ + hash = edgehash_keyhash(eh, v0, v1); + e = edgehash_lookup_entry_ex(eh, v0, v1, hash); + haskey = (e != NULL); + + if (!haskey) { + e = BLI_mempool_alloc(eh->epool); + edgehash_insert_ex_keyonly_entry(eh, v0, v1, hash, e); + } + + *r_val = &e->val; + return haskey; +} + /** * Return value for given edge (\a v0, \a v1), or NULL if * if key does not exist in hash. (If need exists -- cgit v1.2.3 From 5217d2bc0e29695bea74950ff05a9215a85ff703 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 7 Apr 2015 10:53:58 +1000 Subject: Use BKE_edgehash_ensure_p where possible --- source/blender/blenkernel/intern/cdderivedmesh.c | 8 ++++---- source/blender/blenkernel/intern/mesh_validate.c | 5 +++-- source/blender/blenlib/intern/polyfill2d_beautify.c | 10 ++++++---- source/blender/bmesh/intern/bmesh_mesh_validate.c | 9 ++++----- source/blender/editors/armature/meshlaplacian.c | 6 +++--- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 1c2c6eb194b..bd5ee4b9851 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -2545,16 +2545,16 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int const unsigned int v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1; const unsigned int v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2; if (LIKELY(v1 != v2)) { - void **eh_p = BLI_edgehash_lookup_p(ehash, v1, v2); + void **val_p; - if (eh_p) { - newe[i] = GET_INT_FROM_POINTER(*eh_p); + if (BLI_edgehash_ensure_p(ehash, v1, v2, &val_p)) { + newe[i] = GET_INT_FROM_POINTER(*val_p); } else { STACK_PUSH(olde, i); STACK_PUSH(medge, *med); newe[i] = c; - BLI_edgehash_insert(ehash, v1, v2, SET_INT_IN_POINTER(c)); + *val_p = SET_INT_IN_POINTER(c); c++; } } diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index 7de993e1099..f758bcdf2f5 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -1475,8 +1475,9 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool update, const bool select) int j, v_prev = (l + (mp->totloop - 1))->v; for (j = 0; j < mp->totloop; j++, l++) { if (v_prev != l->v) { - if (!BLI_edgehash_haskey(eh, v_prev, l->v)) { - BLI_edgehash_insert(eh, v_prev, l->v, NULL); + void **val_p; + if (!BLI_edgehash_ensure_p(eh, v_prev, l->v, &val_p)) { + *val_p = NULL; } } v_prev = l->v; diff --git a/source/blender/blenlib/intern/polyfill2d_beautify.c b/source/blender/blenlib/intern/polyfill2d_beautify.c index ba71f52b530..46f9251bea7 100644 --- a/source/blender/blenlib/intern/polyfill2d_beautify.c +++ b/source/blender/blenlib/intern/polyfill2d_beautify.c @@ -430,17 +430,19 @@ void BLI_polyfill_beautify( } if (!is_boundary_edge(e_pair[0], e_pair[1], coord_last)) { - struct PolyEdge *e = BLI_edgehash_lookup(ehash, e_pair[0], e_pair[1]); - if (e == NULL) { + struct PolyEdge *e; + void **val_p; + + if (!BLI_edgehash_ensure_p(ehash, e_pair[0], e_pair[1], &val_p)) { e = &edges[edges_tot_used++]; - BLI_edgehash_insert(ehash, e_pair[0], e_pair[1], e); + *val_p = e; memcpy(e->verts, e_pair, sizeof(e->verts)); #ifndef NDEBUG e->faces[!e_index] = (unsigned int)-1; #endif } else { - + e = *val_p; /* ensure each edge only ever has 2x users */ #ifndef NDEBUG BLI_assert(e->faces[e_index] == (unsigned int)-1); diff --git a/source/blender/bmesh/intern/bmesh_mesh_validate.c b/source/blender/bmesh/intern/bmesh_mesh_validate.c index 3a7a4f85e99..494da3b889b 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_validate.c +++ b/source/blender/bmesh/intern/bmesh_mesh_validate.c @@ -86,20 +86,19 @@ bool BM_mesh_validate(BMesh *bm) /* check edges */ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { - BMEdge *e_other; + void **val_p; if (e->v1 == e->v2) { ERRMSG("edge %d: duplicate index: %d", i, BM_elem_index_get(e->v1)); } - /* build edgehash at the same time */ - e_other = BLI_edgehash_lookup(edge_hash, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2)); - if (e_other) { + if (BLI_edgehash_ensure_p(edge_hash, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2), &val_p)) { + BMEdge *e_other = *val_p; ERRMSG("edge %d, %d: are duplicates", i, BM_elem_index_get(e_other)); } else { - BLI_edgehash_insert(edge_hash, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2), e); + *val_p = e; } } diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index b7d14e089cf..fa774b0744a 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -127,12 +127,12 @@ struct LaplacianSystem { static void laplacian_increase_edge_count(EdgeHash *edgehash, int v1, int v2) { - void **p = BLI_edgehash_lookup_p(edgehash, v1, v2); + void **p; - if (p) + if (BLI_edgehash_ensure_p(edgehash, v1, v2, &p)) *p = (void *)((intptr_t)*p + (intptr_t)1); else - BLI_edgehash_insert(edgehash, v1, v2, (void *)(intptr_t)1); + *p = (void *)((intptr_t)1); } static int laplacian_edge_count(EdgeHash *edgehash, int v1, int v2) -- cgit v1.2.3 From e2eeb46a1bda8cf49a70e78a45d12fede27a1af9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 7 Apr 2015 11:01:47 +1000 Subject: Cleanup: rename treehash -> outliner_treehash This is an API specifically for the outliner, not some generic hierarchical hash structure. --- source/blender/blenkernel/BKE_outliner_treehash.h | 51 ++++++ source/blender/blenkernel/BKE_treehash.h | 51 ------ source/blender/blenkernel/CMakeLists.txt | 8 +- .../blender/blenkernel/intern/outliner_treehash.c | 174 +++++++++++++++++++++ source/blender/blenkernel/intern/treehash.c | 174 --------------------- source/blender/blenloader/intern/readfile.c | 6 +- .../blender/editors/space_outliner/outliner_tree.c | 14 +- .../editors/space_outliner/space_outliner.c | 4 +- 8 files changed, 241 insertions(+), 241 deletions(-) create mode 100644 source/blender/blenkernel/BKE_outliner_treehash.h delete mode 100644 source/blender/blenkernel/BKE_treehash.h create mode 100644 source/blender/blenkernel/intern/outliner_treehash.c delete mode 100644 source/blender/blenkernel/intern/treehash.c diff --git a/source/blender/blenkernel/BKE_outliner_treehash.h b/source/blender/blenkernel/BKE_outliner_treehash.h new file mode 100644 index 00000000000..454edb40c4e --- /dev/null +++ b/source/blender/blenkernel/BKE_outliner_treehash.h @@ -0,0 +1,51 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Foundation 2013 + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __BKE_OUTLINER_TREEHASH_H__ +#define __BKE_OUTLINER_TREEHASH_H__ + +/** \file BKE_outliner_treehash.h + * \ingroup bke + */ + +struct ID; +struct BLI_mempool; +struct TreeStoreElem; + +/* create and fill hashtable with treestore elements */ +void *BKE_outliner_treehash_create_from_treestore(struct BLI_mempool *treestore); + +/* full rebuild for already allocated hashtable */ +void *BKE_outliner_treehash_rebuild_from_treestore(void *treehash, struct BLI_mempool *treestore); + +/* full rebuild for already allocated hashtable */ +void BKE_outliner_treehash_add_element(void *treehash, struct TreeStoreElem *elem); + +/* find first unused element with specific type, nr and id */ +struct TreeStoreElem *BKE_outliner_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id); + +/* find user or unused element with specific type, nr and id */ +struct TreeStoreElem *BKE_outliner_treehash_lookup_any(void *treehash, short type, short nr, struct ID *id); + +/* free treehash structure */ +void BKE_outliner_treehash_free(void *treehash); + +#endif diff --git a/source/blender/blenkernel/BKE_treehash.h b/source/blender/blenkernel/BKE_treehash.h deleted file mode 100644 index 16ab02c0965..00000000000 --- a/source/blender/blenkernel/BKE_treehash.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): Blender Foundation 2013 - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef __BKE_TREEHASH_H__ -#define __BKE_TREEHASH_H__ - -/** \file BKE_treehash.h - * \ingroup bke - */ - -struct ID; -struct BLI_mempool; -struct TreeStoreElem; - -/* create and fill hashtable with treestore elements */ -void *BKE_treehash_create_from_treestore(struct BLI_mempool *treestore); - -/* full rebuild for already allocated hashtable */ -void *BKE_treehash_rebuild_from_treestore(void *treehash, struct BLI_mempool *treestore); - -/* full rebuild for already allocated hashtable */ -void BKE_treehash_add_element(void *treehash, struct TreeStoreElem *elem); - -/* find first unused element with specific type, nr and id */ -struct TreeStoreElem *BKE_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id); - -/* find user or unused element with specific type, nr and id */ -struct TreeStoreElem *BKE_treehash_lookup_any(void *treehash, short type, short nr, struct ID *id); - -/* free treehash structure */ -void BKE_treehash_free(void *treehash); - -#endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index f19c1066766..67c8f0fc558 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -135,6 +135,7 @@ set(SRC intern/object_deform.c intern/object_dupli.c intern/ocean.c + intern/outliner_treehash.c intern/packedFile.c intern/paint.c intern/particle.c @@ -172,7 +173,6 @@ set(SRC intern/tracking_solver.c intern/tracking_stabilize.c intern/tracking_util.c - intern/treehash.c intern/unit.c intern/world.c intern/writeavi.c @@ -211,6 +211,8 @@ set(SRC BKE_depsgraph.h BKE_displist.h BKE_dynamicpaint.h + BKE_editmesh.h + BKE_editmesh_bvh.h BKE_effect.h BKE_fcurve.h BKE_fluidsim.h @@ -246,6 +248,7 @@ set(SRC BKE_object.h BKE_object_deform.h BKE_ocean.h + BKE_outliner_treehash.h BKE_packedFile.h BKE_paint.h BKE_particle.h @@ -266,12 +269,9 @@ set(SRC BKE_speaker.h BKE_subsurf.h BKE_suggestions.h - BKE_editmesh.h - BKE_editmesh_bvh.h BKE_text.h BKE_texture.h BKE_tracking.h - BKE_treehash.h BKE_unit.h BKE_utildefines.h BKE_world.h diff --git a/source/blender/blenkernel/intern/outliner_treehash.c b/source/blender/blenkernel/intern/outliner_treehash.c new file mode 100644 index 00000000000..1cce61561e0 --- /dev/null +++ b/source/blender/blenkernel/intern/outliner_treehash.c @@ -0,0 +1,174 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Foundation 2013 + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file outliner_treehash.c + * \ingroup bke + * + * Tree hash for the outliner space. + */ + +#include + +#include "BKE_outliner_treehash.h" + +#include "BLI_utildefines.h" +#include "BLI_ghash.h" +#include "BLI_mempool.h" + +#include "DNA_outliner_types.h" + +#include "MEM_guardedalloc.h" + +typedef struct TseGroup +{ + TreeStoreElem **elems; + int size; + int allocated; +} TseGroup; + +/* Allocate structure for TreeStoreElements; + * Most of elements in treestore have no duplicates, + * so there is no need to preallocate memory for more than one pointer */ +static TseGroup *tse_group_create(void) +{ + TseGroup *tse_group = MEM_mallocN(sizeof(TseGroup), "TseGroup"); + tse_group->elems = MEM_mallocN(sizeof(TreeStoreElem *), "TseGroupElems"); + tse_group->size = 0; + tse_group->allocated = 1; + return tse_group; +} + +static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem) +{ + if (UNLIKELY(tse_group->size == tse_group->allocated)) { + tse_group->allocated *= 2; + tse_group->elems = MEM_reallocN(tse_group->elems, sizeof(TreeStoreElem *) * tse_group->allocated); + } + tse_group->elems[tse_group->size] = elem; + tse_group->size++; +} + +static void tse_group_free(TseGroup *tse_group) +{ + MEM_freeN(tse_group->elems); + MEM_freeN(tse_group); +} + +static unsigned int tse_hash(const void *ptr) +{ + const TreeStoreElem *tse = ptr; + union { + short h_pair[2]; + unsigned int u_int; + } hash; + + BLI_assert(tse->type || !tse->nr); + + hash.h_pair[0] = tse->type; + hash.h_pair[1] = tse->nr; + + hash.u_int ^= BLI_ghashutil_ptrhash(tse->id); + + return hash.u_int; +} + +static bool tse_cmp(const void *a, const void *b) +{ + const TreeStoreElem *tse_a = a; + const TreeStoreElem *tse_b = b; + return tse_a->type != tse_b->type || tse_a->nr != tse_b->nr || tse_a->id != tse_b->id; +} + +static void fill_treehash(void *treehash, BLI_mempool *treestore) +{ + TreeStoreElem *tselem; + BLI_mempool_iter iter; + BLI_mempool_iternew(treestore, &iter); + while ((tselem = BLI_mempool_iterstep(&iter))) { + BKE_outliner_treehash_add_element(treehash, tselem); + } +} + +void *BKE_outliner_treehash_create_from_treestore(BLI_mempool *treestore) +{ + GHash *treehash = BLI_ghash_new_ex(tse_hash, tse_cmp, "treehash", BLI_mempool_count(treestore)); + fill_treehash(treehash, treestore); + return treehash; +} + +static void free_treehash_group(void *key) +{ + tse_group_free(key); +} + +void *BKE_outliner_treehash_rebuild_from_treestore(void *treehash, BLI_mempool *treestore) +{ + BLI_ghash_clear_ex(treehash, NULL, free_treehash_group, BLI_mempool_count(treestore)); + fill_treehash(treehash, treestore); + return treehash; +} + +void BKE_outliner_treehash_add_element(void *treehash, TreeStoreElem *elem) +{ + TseGroup *group; + void **val_p; + + if (!BLI_ghash_ensure_p(treehash, elem, &val_p)) { + *val_p = tse_group_create(); + } + group = *val_p; + tse_group_add(group, elem); +} + +static TseGroup *BKE_outliner_treehash_lookup_group(GHash *th, short type, short nr, struct ID *id) +{ + TreeStoreElem tse_template; + tse_template.type = type; + tse_template.nr = type ? nr : 0; // we're picky! :) + tse_template.id = id; + return BLI_ghash_lookup(th, &tse_template); +} + +TreeStoreElem *BKE_outliner_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id) +{ + TseGroup *group = BKE_outliner_treehash_lookup_group(treehash, type, nr, id); + if (group) { + int i; + for (i = 0; i < group->size; i++) { + if (!group->elems[i]->used) { + return group->elems[i]; + } + } + } + return NULL; +} + +TreeStoreElem *BKE_outliner_treehash_lookup_any(void *treehash, short type, short nr, struct ID *id) +{ + TseGroup *group = BKE_outliner_treehash_lookup_group(treehash, type, nr, id); + return group ? group->elems[0] : NULL; +} + +void BKE_outliner_treehash_free(void *treehash) +{ + BLI_ghash_free(treehash, NULL, free_treehash_group); +} diff --git a/source/blender/blenkernel/intern/treehash.c b/source/blender/blenkernel/intern/treehash.c deleted file mode 100644 index 43eeae7329e..00000000000 --- a/source/blender/blenkernel/intern/treehash.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): Blender Foundation 2013 - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file treehash.c - * \ingroup bke - * - * Tree hash for the outliner space. - */ - -#include - -#include "BKE_treehash.h" - -#include "BLI_utildefines.h" -#include "BLI_ghash.h" -#include "BLI_mempool.h" - -#include "DNA_outliner_types.h" - -#include "MEM_guardedalloc.h" - -typedef struct TseGroup -{ - TreeStoreElem **elems; - int size; - int allocated; -} TseGroup; - -/* Allocate structure for TreeStoreElements; - * Most of elements in treestore have no duplicates, - * so there is no need to preallocate memory for more than one pointer */ -static TseGroup *tse_group_create(void) -{ - TseGroup *tse_group = MEM_mallocN(sizeof(TseGroup), "TseGroup"); - tse_group->elems = MEM_mallocN(sizeof(TreeStoreElem *), "TseGroupElems"); - tse_group->size = 0; - tse_group->allocated = 1; - return tse_group; -} - -static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem) -{ - if (UNLIKELY(tse_group->size == tse_group->allocated)) { - tse_group->allocated *= 2; - tse_group->elems = MEM_reallocN(tse_group->elems, sizeof(TreeStoreElem *) * tse_group->allocated); - } - tse_group->elems[tse_group->size] = elem; - tse_group->size++; -} - -static void tse_group_free(TseGroup *tse_group) -{ - MEM_freeN(tse_group->elems); - MEM_freeN(tse_group); -} - -static unsigned int tse_hash(const void *ptr) -{ - const TreeStoreElem *tse = ptr; - union { - short h_pair[2]; - unsigned int u_int; - } hash; - - BLI_assert(tse->type || !tse->nr); - - hash.h_pair[0] = tse->type; - hash.h_pair[1] = tse->nr; - - hash.u_int ^= BLI_ghashutil_ptrhash(tse->id); - - return hash.u_int; -} - -static bool tse_cmp(const void *a, const void *b) -{ - const TreeStoreElem *tse_a = a; - const TreeStoreElem *tse_b = b; - return tse_a->type != tse_b->type || tse_a->nr != tse_b->nr || tse_a->id != tse_b->id; -} - -static void fill_treehash(void *treehash, BLI_mempool *treestore) -{ - TreeStoreElem *tselem; - BLI_mempool_iter iter; - BLI_mempool_iternew(treestore, &iter); - while ((tselem = BLI_mempool_iterstep(&iter))) { - BKE_treehash_add_element(treehash, tselem); - } -} - -void *BKE_treehash_create_from_treestore(BLI_mempool *treestore) -{ - GHash *treehash = BLI_ghash_new_ex(tse_hash, tse_cmp, "treehash", BLI_mempool_count(treestore)); - fill_treehash(treehash, treestore); - return treehash; -} - -static void free_treehash_group(void *key) -{ - tse_group_free(key); -} - -void *BKE_treehash_rebuild_from_treestore(void *treehash, BLI_mempool *treestore) -{ - BLI_ghash_clear_ex(treehash, NULL, free_treehash_group, BLI_mempool_count(treestore)); - fill_treehash(treehash, treestore); - return treehash; -} - -void BKE_treehash_add_element(void *treehash, TreeStoreElem *elem) -{ - TseGroup *group; - void **val_p; - - if (!BLI_ghash_ensure_p(treehash, elem, &val_p)) { - *val_p = tse_group_create(); - } - group = *val_p; - tse_group_add(group, elem); -} - -static TseGroup *BKE_treehash_lookup_group(GHash *th, short type, short nr, struct ID *id) -{ - TreeStoreElem tse_template; - tse_template.type = type; - tse_template.nr = type ? nr : 0; // we're picky! :) - tse_template.id = id; - return BLI_ghash_lookup(th, &tse_template); -} - -TreeStoreElem *BKE_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id) -{ - TseGroup *group = BKE_treehash_lookup_group(treehash, type, nr, id); - if (group) { - int i; - for (i = 0; i < group->size; i++) { - if (!group->elems[i]->used) { - return group->elems[i]; - } - } - } - return NULL; -} - -TreeStoreElem *BKE_treehash_lookup_any(void *treehash, short type, short nr, struct ID *id) -{ - TseGroup *group = BKE_treehash_lookup_group(treehash, type, nr, id); - return group ? group->elems[0] : NULL; -} - -void BKE_treehash_free(void *treehash) -{ - BLI_ghash_free(treehash, NULL, free_treehash_group); -} diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 4eb7413adc1..9a269cad756 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -139,7 +139,7 @@ #include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_sequencer.h" -#include "BKE_treehash.h" +#include "BKE_outliner_treehash.h" #include "BKE_sound.h" @@ -6041,7 +6041,7 @@ static void lib_link_screen(FileData *fd, Main *main) } if (so->treehash) { /* rebuild hash table, because it depends on ids too */ - BKE_treehash_rebuild_from_treestore(so->treehash, so->treestore); + BKE_outliner_treehash_rebuild_from_treestore(so->treehash, so->treestore); } } } @@ -6392,7 +6392,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc } if (so->treehash) { /* rebuild hash table, because it depends on ids too */ - BKE_treehash_rebuild_from_treestore(so->treehash, so->treestore); + BKE_outliner_treehash_rebuild_from_treestore(so->treehash, so->treestore); } } } diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 9239d9cb27e..17a6e952ee1 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -66,7 +66,7 @@ #include "BKE_modifier.h" #include "BKE_sequencer.h" #include "BKE_idcode.h" -#include "BKE_treehash.h" +#include "BKE_outliner_treehash.h" #include "ED_armature.h" #include "ED_screen.h" @@ -114,7 +114,7 @@ static void outliner_storage_cleanup(SpaceOops *soops) BLI_mempool_destroy(ts); soops->treestore = NULL; if (soops->treehash) { - BKE_treehash_free(soops->treehash); + BKE_outliner_treehash_free(soops->treehash); soops->treehash = NULL; } } @@ -133,7 +133,7 @@ static void outliner_storage_cleanup(SpaceOops *soops) soops->treestore = new_ts; if (soops->treehash) { /* update hash table to fix broken pointers */ - BKE_treehash_rebuild_from_treestore(soops->treehash, soops->treestore); + BKE_outliner_treehash_rebuild_from_treestore(soops->treehash, soops->treestore); } } } @@ -151,12 +151,12 @@ static void check_persistent(SpaceOops *soops, TreeElement *te, ID *id, short ty } if (soops->treehash == NULL) { - soops->treehash = BKE_treehash_create_from_treestore(soops->treestore); + soops->treehash = BKE_outliner_treehash_create_from_treestore(soops->treestore); } /* find any unused tree element in treestore and mark it as used * (note that there may be multiple unused elements in case of linked objects) */ - tselem = BKE_treehash_lookup_unused(soops->treehash, type, nr, id); + tselem = BKE_outliner_treehash_lookup_unused(soops->treehash, type, nr, id); if (tselem) { te->store_elem = tselem; tselem->used = 1; @@ -171,7 +171,7 @@ static void check_persistent(SpaceOops *soops, TreeElement *te, ID *id, short ty tselem->used = 0; tselem->flag = TSE_CLOSED; te->store_elem = tselem; - BKE_treehash_add_element(soops->treehash, tselem); + BKE_outliner_treehash_add_element(soops->treehash, tselem); } /* ********************************************************* */ @@ -216,7 +216,7 @@ TreeElement *outliner_find_tse(SpaceOops *soops, TreeStoreElem *tse) if (tse->id == NULL) return NULL; /* check if 'tse' is in treestore */ - tselem = BKE_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id); + tselem = BKE_outliner_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id); if (tselem) return outliner_find_tree_element(&soops->tree, tselem); diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index e1aea8892b5..7b1ec174a6b 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -41,7 +41,7 @@ #include "BKE_context.h" #include "BKE_screen.h" #include "BKE_scene.h" -#include "BKE_treehash.h" +#include "BKE_outliner_treehash.h" #include "ED_space_api.h" #include "ED_screen.h" @@ -464,7 +464,7 @@ static void outliner_free(SpaceLink *sl) BLI_mempool_destroy(soutliner->treestore); } if (soutliner->treehash) { - BKE_treehash_free(soutliner->treehash); + BKE_outliner_treehash_free(soutliner->treehash); } } -- cgit v1.2.3 From 9510137d1237f0bb493313cb65a79479ec77e4ce Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 7 Apr 2015 11:25:42 +1000 Subject: Cleanup: brace placement /w structs --- source/blender/blenfont/BLF_translation.h | 3 +-- source/blender/blenkernel/BKE_node.h | 3 +-- .../blender/blenkernel/intern/outliner_treehash.c | 3 +-- source/blender/blenlib/intern/freetypefont.c | 3 +-- source/blender/blenlib/intern/hash_md5.c | 3 +-- .../COM_VariableSizeBokehBlurOperation.cpp | 3 +-- source/blender/editors/space_view3d/view3d_walk.c | 3 +-- source/blender/ikplugin/intern/itasc_plugin.cpp | 3 +-- source/blender/imbuf/intern/cineon/logImageCore.h | 6 ++---- source/blender/imbuf/intern/dds/BlockDXT.h | 24 ++++++++-------------- source/blender/imbuf/intern/dds/ColorBlock.h | 3 +-- .../blender/imbuf/intern/dds/DirectDrawSurface.cpp | 3 +-- .../blender/imbuf/intern/dds/DirectDrawSurface.h | 12 ++++------- source/blender/imbuf/intern/dds/Stream.h | 3 +-- source/blender/makesdna/DNA_brush_types.h | 12 ++++------- source/blender/makesdna/DNA_node_types.h | 3 +-- source/blender/makesdna/DNA_space_types.h | 3 +-- .../blender/python/intern/bpy_app_translations.c | 3 +-- .../blender/render/intern/include/render_types.h | 3 +-- 19 files changed, 33 insertions(+), 66 deletions(-) diff --git a/source/blender/blenfont/BLF_translation.h b/source/blender/blenfont/BLF_translation.h index b42e6f80022..49bfdbfe877 100644 --- a/source/blender/blenfont/BLF_translation.h +++ b/source/blender/blenfont/BLF_translation.h @@ -180,8 +180,7 @@ const char *BLF_translate_do_new_dataname(const char *msgctxt, const char *msgid #define BLF_I18NCONTEXT_ID_MASK "Mask" /* Helper for bpy.app.i18n object... */ -typedef struct -{ +typedef struct { const char *c_id; const char *py_id; const char *value; diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index eca15a62c70..d3a8687c615 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -507,8 +507,7 @@ const struct ListBase *BKE_node_clipboard_get_links(void); int BKE_node_clipboard_get_type(void); /* Node Instance Hash */ -typedef struct bNodeInstanceHash -{ +typedef struct bNodeInstanceHash { GHash *ghash; /* XXX should be made a direct member, GHash allocation needs to support it */ } bNodeInstanceHash; diff --git a/source/blender/blenkernel/intern/outliner_treehash.c b/source/blender/blenkernel/intern/outliner_treehash.c index 1cce61561e0..21664bfd285 100644 --- a/source/blender/blenkernel/intern/outliner_treehash.c +++ b/source/blender/blenkernel/intern/outliner_treehash.c @@ -38,8 +38,7 @@ #include "MEM_guardedalloc.h" -typedef struct TseGroup -{ +typedef struct TseGroup { TreeStoreElem **elems; int size; int allocated; diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c index b3392e28223..8719c92a2a6 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -507,8 +507,7 @@ VChar *BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character) /* Freetype2 Outline struct */ -typedef struct FT_Outline_ -{ +typedef struct FT_Outline_ { short n_contours; /* number of contours in glyph */ short n_points; /* number of points in the glyph */ diff --git a/source/blender/blenlib/intern/hash_md5.c b/source/blender/blenlib/intern/hash_md5.c index 4eec38278e9..d98b915983c 100644 --- a/source/blender/blenlib/intern/hash_md5.c +++ b/source/blender/blenlib/intern/hash_md5.c @@ -81,8 +81,7 @@ * 'BLI_hash_md5_stream' and 'BLI_hash_md5_buffer'. */ /* Structure to save state of computation between the single steps. */ -struct md5_ctx -{ +struct md5_ctx { md5_uint32 A; md5_uint32 B; md5_uint32 C; diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp index e4883d91bc3..1ec52571be8 100644 --- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp @@ -62,8 +62,7 @@ void VariableSizeBokehBlurOperation::initExecution() #endif QualityStepHelper::initExecution(COM_QH_INCREASE); } -struct VariableSizeBokehBlurTileData -{ +struct VariableSizeBokehBlurTileData { MemoryBuffer *color; MemoryBuffer *bokeh; MemoryBuffer *size; diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 191eeb05c71..11756e4feca 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -220,8 +220,7 @@ void walk_modal_keymap(wmKeyConfig *keyconf) } -typedef struct WalkTeleport -{ +typedef struct WalkTeleport { eWalkTeleportState state; float duration; /* from user preferences */ float origin[3]; diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index afff97a8409..d4814a4e3a2 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -89,8 +89,7 @@ struct IK_Target; typedef void (*ErrorCallback)(const iTaSC::ConstraintValues *values, unsigned int nvalues, IK_Target *iktarget); // one structure for each target in the scene -struct IK_Target -{ +struct IK_Target { struct Scene *blscene; iTaSC::MovingFrame* target; iTaSC::ConstraintSet* constraint; diff --git a/source/blender/imbuf/intern/cineon/logImageCore.h b/source/blender/imbuf/intern/cineon/logImageCore.h index 6b1435817d2..389e88a24de 100644 --- a/source/blender/imbuf/intern/cineon/logImageCore.h +++ b/source/blender/imbuf/intern/cineon/logImageCore.h @@ -52,8 +52,7 @@ enum format { format_Cineon }; -typedef struct LogImageElement -{ +typedef struct LogImageElement { int depth; int bitsPerSample; int dataOffset; @@ -67,8 +66,7 @@ typedef struct LogImageElement float maxValue; /* = 2^bitsPerSample - 1 (used internally, doesn't come from the file header) */ } LogImageElement; -typedef struct LogImageFile -{ +typedef struct LogImageFile { /* specified in header */ int width; int height; diff --git a/source/blender/imbuf/intern/dds/BlockDXT.h b/source/blender/imbuf/intern/dds/BlockDXT.h index 7e5a1e504b8..6aae9c9817c 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.h +++ b/source/blender/imbuf/intern/dds/BlockDXT.h @@ -64,8 +64,7 @@ #include /// DXT1 block. -struct BlockDXT1 -{ +struct BlockDXT1 { Color16 col0; Color16 col1; union { @@ -98,8 +97,7 @@ inline bool BlockDXT1::isFourColorMode() const /// DXT3 alpha block with explicit alpha. -struct AlphaBlockDXT3 -{ +struct AlphaBlockDXT3 { union { struct { uint alpha0 : 4; @@ -130,8 +128,7 @@ struct AlphaBlockDXT3 /// DXT3 block. -struct BlockDXT3 -{ +struct BlockDXT3 { AlphaBlockDXT3 alpha; BlockDXT1 color; @@ -144,8 +141,7 @@ struct BlockDXT3 /// DXT5 alpha block. -struct AlphaBlockDXT5 -{ +struct AlphaBlockDXT5 { // uint64 unions do not compile on all platforms #if 0 union { @@ -208,8 +204,7 @@ struct AlphaBlockDXT5 /// DXT5 block. -struct BlockDXT5 -{ +struct BlockDXT5 { AlphaBlockDXT5 alpha; BlockDXT1 color; @@ -221,8 +216,7 @@ struct BlockDXT5 }; /// ATI1 block. -struct BlockATI1 -{ +struct BlockATI1 { AlphaBlockDXT5 alpha; void decodeBlock(ColorBlock * block) const; @@ -232,8 +226,7 @@ struct BlockATI1 }; /// ATI2 block. -struct BlockATI2 -{ +struct BlockATI2 { AlphaBlockDXT5 x; AlphaBlockDXT5 y; @@ -244,8 +237,7 @@ struct BlockATI2 }; /// CTX1 block. -struct BlockCTX1 -{ +struct BlockCTX1 { uint8 col0[2]; uint8 col1[2]; union { diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h index 730a19d84fd..8d5031aa603 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.h +++ b/source/blender/imbuf/intern/dds/ColorBlock.h @@ -41,8 +41,7 @@ #include /// Uncompressed 4x4 color block. -struct ColorBlock -{ +struct ColorBlock { ColorBlock(); ColorBlock(const uint * linearImage); ColorBlock(const ColorBlock & block); diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index 028026527dc..15c8d86d61c 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -496,8 +496,7 @@ void mem_read(Stream & mem, DDSHeader & header) namespace { -struct FormatDescriptor -{ +struct FormatDescriptor { uint format; uint bitcount; uint rmask; diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h index 3d308ba1ff1..44c27a98c1d 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h @@ -63,8 +63,7 @@ #include #include -struct DDSPixelFormat -{ +struct DDSPixelFormat { uint size; uint flags; uint fourcc; @@ -75,8 +74,7 @@ struct DDSPixelFormat uint amask; }; -struct DDSCaps -{ +struct DDSCaps { uint caps1; uint caps2; uint caps3; @@ -84,8 +82,7 @@ struct DDSCaps }; /// DDS file header for DX10. -struct DDSHeader10 -{ +struct DDSHeader10 { uint dxgiFormat; uint resourceDimension; uint miscFlag; @@ -94,8 +91,7 @@ struct DDSHeader10 }; /// DDS file header. -struct DDSHeader -{ +struct DDSHeader { uint fourcc; uint size; uint flags; diff --git a/source/blender/imbuf/intern/dds/Stream.h b/source/blender/imbuf/intern/dds/Stream.h index a1ac49b58da..6557fb4f063 100644 --- a/source/blender/imbuf/intern/dds/Stream.h +++ b/source/blender/imbuf/intern/dds/Stream.h @@ -30,8 +30,7 @@ #ifndef __STREAM_H__ #define __STREAM_H__ -struct Stream -{ +struct Stream { unsigned char *mem; // location in memory unsigned int size; // size unsigned int pos; // current position diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index dd66acf2781..6d6d33a6f1b 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -137,16 +137,14 @@ typedef struct Brush { float mask_stencil_dimension[2]; } Brush; -typedef struct PaletteColor -{ +typedef struct PaletteColor { struct PaletteColor *next, *prev; /* two values, one to store rgb, other to store values for sculpt/weight */ float rgb[3]; float value; } PaletteColor; -typedef struct Palette -{ +typedef struct Palette { ID id; /* pointer to individual colours */ @@ -156,14 +154,12 @@ typedef struct Palette int pad; } Palette; -typedef struct PaintCurvePoint -{ +typedef struct PaintCurvePoint { BezTriple bez; /* bezier handle */ float pressure; /* pressure on that point */ } PaintCurvePoint; -typedef struct PaintCurve -{ +typedef struct PaintCurve { ID id; PaintCurvePoint *points; /* points of curve */ int tot_points; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 2a1a35d158a..ead822053b3 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -268,8 +268,7 @@ typedef struct bNode { /* Unique hash key for identifying node instances * Defined as a struct because DNA does not support other typedefs. */ -typedef struct bNodeInstanceKey -{ +typedef struct bNodeInstanceKey { unsigned int value; } bNodeInstanceKey; diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 05127f176b4..c2f49ea92b5 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -554,8 +554,7 @@ typedef enum eSpaceSeq_Proxy_RenderSize { SEQ_PROXY_RENDER_SIZE_FULL = 100 } eSpaceSeq_Proxy_RenderSize; -typedef struct MaskSpaceInfo -{ +typedef struct MaskSpaceInfo { /* **** mask editing **** */ struct Mask *mask; /* draw options */ diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c index ae5ea88abdf..72133badbbb 100644 --- a/source/blender/python/intern/bpy_app_translations.c +++ b/source/blender/python/intern/bpy_app_translations.c @@ -47,8 +47,7 @@ #include "../generic/python_utildefines.h" -typedef struct -{ +typedef struct { PyObject_HEAD /* The string used to separate context from actual message in PY_TRANSLATE RNA props. */ const char *context_separator; diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 8fe12015e87..e12a1575992 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -122,8 +122,7 @@ enum { }; /* controls state of render, everything that's read-only during render stage */ -struct Render -{ +struct Render { struct Render *next, *prev; char name[RE_MAXNAME]; int slot; -- cgit v1.2.3 From 98f41066943d8b1cf9236d6b358d1e84c9e7cc4b Mon Sep 17 00:00:00 2001 From: Krzysztof Recko Date: Tue, 7 Apr 2015 12:44:39 +1000 Subject: Metaball tessellation optimization (Octree to BVH) Speedup is non-linear, 2x-10x faster is quite normal. Patch T43678. - Switched from an Octree to BVH. - Finding first points of surface no longer "wastes" density function evaluation: every result is cached. - Use MemArena instead of using own memory management. - Correct calculation of metaelem bounding box. - Remove mball_count(): mballs are now counted "on the go". --- source/blender/blenkernel/BKE_mball.h | 2 - source/blender/blenkernel/BKE_mball_tessellate.h | 2 + .../blender/blenkernel/intern/mball_tessellate.c | 1988 +++++++------------- source/blender/windowmanager/intern/wm_init_exit.c | 2 +- 4 files changed, 673 insertions(+), 1321 deletions(-) diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index 70f932f3292..321cbbbd708 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -45,8 +45,6 @@ struct MetaBall *BKE_mball_copy(struct MetaBall *mb); void BKE_mball_make_local(struct MetaBall *mb); -void BKE_mball_cubeTable_free(void); - bool BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2); bool BKE_mball_is_basis(struct Object *ob); struct Object *BKE_mball_basis_find(struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_mball_tessellate.h b/source/blender/blenkernel/BKE_mball_tessellate.h index a3d3e1934b7..361f31b704c 100644 --- a/source/blender/blenkernel/BKE_mball_tessellate.h +++ b/source/blender/blenkernel/BKE_mball_tessellate.h @@ -31,4 +31,6 @@ void BKE_mball_polygonize( struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase); +void BKE_mball_cubeTable_free(void); + #endif /* __BKE_MBALL_TESSELLATE_H__ */ diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c index 04024943310..080a8cead7b 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.c +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -44,26 +44,21 @@ #include "BLI_path_util.h" #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLI_memarena.h" #include "BKE_global.h" #include "BKE_depsgraph.h" #include "BKE_scene.h" #include "BKE_displist.h" -#include "BKE_mball.h" #include "BKE_mball_tessellate.h" /* own include */ -/* Data types */ +#include "BLI_strict_flags.h" -typedef struct vertex { /* surface vertex */ - float co[3]; /* position and surface normal */ - float no[3]; -} VERTEX; +/* experimental (faster) normal calculation */ +// #define USE_ACCUM_NORMAL -typedef struct vertices { /* list of vertices in polygonization */ - int count, max; /* # vertices, max # allowed */ - VERTEX *ptr; /* dynamically allocated */ -} VERTICES; +/* Data types */ typedef struct corner { /* corner of a cube */ int i, j, k; /* (i, j, k) is index within lattice */ @@ -102,74 +97,161 @@ typedef struct intlists { /* list of list of integers */ struct intlists *next; /* remaining elements */ } INTLISTS; -/* dividing scene using octal tree makes polygonisation faster */ -typedef struct ml_pointer { - struct ml_pointer *next, *prev; - struct MetaElem *ml; -} ml_pointer; - -typedef struct octal_node { - struct octal_node *nodes[8];/* children of current node */ - struct octal_node *parent; /* parent of current node */ - struct ListBase elems; /* ListBase of MetaElem pointers (ml_pointer) */ - float x_min, y_min, z_min; /* 1st border point */ - float x_max, y_max, z_max; /* 7th border point */ - float x, y, z; /* center of node */ - int pos, neg; /* number of positive and negative MetaElements in the node */ - int count; /* number of MetaElems, which belongs to the node */ -} octal_node; - -typedef struct octal_tree { - struct octal_node *first; /* first node */ - int pos, neg; /* number of positive and negative MetaElements in the scene */ - short depth; /* number of scene subdivision */ -} octal_tree; - -struct pgn_elements { - struct pgn_elements *next, *prev; - char *data; -}; +typedef struct Box { /* an AABB with pointer to metalelem */ + float min[3], max[3]; + const MetaElem *ml; +} Box; + +typedef struct MetaballBVHNode { /* BVH node */ + Box bb[2]; /* AABB of children */ + struct MetaballBVHNode *child[2]; +} MetaballBVHNode; + +typedef struct process { /* parameters, storage */ + float thresh, size; /* mball threshold, single cube size */ + float delta; /* small delta for calculating normals */ + unsigned int converge_res; /* converge procedure resolution (more = slower) */ + + MetaElem **mainb; /* array of all metaelems */ + unsigned int totelem, mem; /* number of metaelems */ + + MetaballBVHNode metaball_bvh; /* The simplest bvh */ + Box allbb; /* Bounding box of all metaelems */ -typedef struct process { /* parameters, function, storage */ - /* ** old G_mb contents ** */ - float thresh; - int totelem; - MetaElem **mainb; - octal_tree *metaball_tree; - - /* ** old process contents ** */ - - /* what happens here? floats, I think. */ - /* float (*function)(void); */ /* implicit surface function */ - float (*function)(struct process *, float, float, float); - float size, delta; /* cube size, normal delta */ - int bounds; /* cube range within lattice */ - CUBES *cubes; /* active cubes */ - VERTICES vertices; /* surface vertices */ + MetaballBVHNode **bvh_queue; /* Queue used during bvh traversal */ + unsigned int bvh_queue_size; + + CUBES *cubes; /* stack of cubes waiting for polygonization */ CENTERLIST **centers; /* cube center hash table */ CORNER **corners; /* corner value hash table */ EDGELIST **edges; /* edge and vertex id hash table */ - /* Runtime things */ - int *indices; - int totindex, curindex; + int (*indices)[4]; /* output indices */ + unsigned int totindex; /* size of memory allocated for indices */ + unsigned int curindex; /* number of currently added indices */ + + float (*co)[3], (*no)[3]; /* surface vertices - positions and normals */ + unsigned int totvertex; /* memory size */ + unsigned int curvertex; /* currently added vertices */ - int pgn_offset; - struct pgn_elements *pgn_current; - ListBase pgn_list; + /* memory allocation from common pool */ + MemArena *pgn_elements; } PROCESS; /* Forward declarations */ -static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2, MetaBall *mb); -static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k); -static CORNER *setcorner(PROCESS *process, int i, int j, int k); -static void converge(PROCESS *process, const float p1[3], const float p2[3], float v1, float v2, - float p[3], MetaBall *mb, int f); +static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2); +static void add_cube(PROCESS *process, int i, int j, int k); +static void make_face(PROCESS *process, int i1, int i2, int i3, int i4); +static void converge(PROCESS *process, const CORNER *c1, const CORNER *c2, float r_p[3]); + +/* ******************* SIMPLE BVH ********************* */ + +static void make_box_union(const BoundBox *a, const Box *b, Box *r_out) +{ + r_out->min[0] = min_ff(a->vec[0][0], b->min[0]); + r_out->min[1] = min_ff(a->vec[0][1], b->min[1]); + r_out->min[2] = min_ff(a->vec[0][2], b->min[2]); + + r_out->max[0] = max_ff(a->vec[6][0], b->max[0]); + r_out->max[1] = max_ff(a->vec[6][1], b->max[1]); + r_out->max[2] = max_ff(a->vec[6][2], b->max[2]); +} + +static void make_box_from_metaelem(Box *r, const MetaElem *ml) +{ + copy_v3_v3(r->max, ml->bb->vec[6]); + copy_v3_v3(r->min, ml->bb->vec[0]); + r->ml = ml; +} + +/** + * Partitions part of mainb array [start, end) along axis s. Returns i, + * where centroids of elements in the [start, i) segment lie "on the right side" of div, + * and elements in the [i, end) segment lie "on the left" + */ +static unsigned int partition_mainb(MetaElem **mainb, unsigned int start, unsigned int end, unsigned int s, float div) +{ + unsigned int i = start, j = end - 1; + div *= 2.0f; + + while (1) { + while (i < j && div > (mainb[i]->bb->vec[6][s] + mainb[i]->bb->vec[0][s])) i++; + while (j > i && div < (mainb[j]->bb->vec[6][s] + mainb[j]->bb->vec[0][s])) j--; + + if (i >= j) + break; + + SWAP(MetaElem *, mainb[i], mainb[j]); + i++; + j--; + } + + if (i == start) { + i++; + } + + return i; +} + +/** + * Recursively builds a BVH, dividing elements along the middle of the longest axis of allbox. + */ +static void build_bvh_spatial( + PROCESS *process, MetaballBVHNode *node, + unsigned int start, unsigned int end, const Box *allbox) +{ + unsigned int part, j, s; + float dim[3], div; + + /* Maximum bvh queue size is number of nodes which are made, equals calls to this function. */ + process->bvh_queue_size++; + dim[0] = allbox->max[0] - allbox->min[0]; + dim[1] = allbox->max[1] - allbox->min[1]; + dim[2] = allbox->max[2] - allbox->min[2]; + + s = 0; + if (dim[1] > dim[0] && dim[1] > dim[2]) s = 1; + else if (dim[2] > dim[1] && dim[2] > dim[0]) s = 2; + + div = allbox->min[s] + (dim[s] / 2.0f); + + part = partition_mainb(process->mainb, start, end, s, div); + + make_box_from_metaelem(&node->bb[0], process->mainb[start]); + node->child[0] = NULL; + + if (part > start + 1) { + for (j = start; j < part; j++) { + make_box_union(process->mainb[j]->bb, &node->bb[0], &node->bb[0]); + } + + node->child[0] = BLI_memarena_alloc(process->pgn_elements, sizeof(MetaballBVHNode)); + build_bvh_spatial(process, node->child[0], start, part, &node->bb[0]); + } + + node->child[1] = NULL; + if (part < end) { + make_box_from_metaelem(&node->bb[1], process->mainb[part]); + + if (part < end - 1) { + for (j = part; j < end; j++) { + make_box_union(process->mainb[j]->bb, &node->bb[1], &node->bb[1]); + } + + node->child[1] = BLI_memarena_alloc(process->pgn_elements, sizeof(MetaballBVHNode)); + build_bvh_spatial(process, node->child[1], part, end, &node->bb[1]); + } + } + else { + INIT_MINMAX(node->bb[1].min, node->bb[1].max); + } +} /* ******************** ARITH ************************* */ -/* BASED AT CODE (but mostly rewritten) : +/** + * BASED AT CODE (but mostly rewritten) : * C code from the article * "An Implicit Surface Polygonizer" * by Jules Bloomenthal, jbloom@beauty.gmu.edu @@ -178,9 +260,8 @@ static void converge(PROCESS *process, const float p1[3], const float p2[3], flo * Authored by Jules Bloomenthal, Xerox PARC. * Copyright (c) Xerox Corporation, 1991. All rights reserved. * Permission is granted to reproduce, use and distribute this code for - * any and all purposes, provided that this notice appears in all copies. */ - -#define RES 12 /* # converge iterations */ + * any and all purposes, provided that this notice appears in all copies. + */ #define L 0 /* left direction: -x, -i */ #define R 1 /* right direction: +x, +i */ @@ -197,8 +278,10 @@ static void converge(PROCESS *process, const float p1[3], const float p2[3], flo #define RTN 6 /* right top near corner */ #define RTF 7 /* right top far corner */ -/* the LBN corner of cube (i, j, k), corresponds with location - * (i-0.5)*size, (j-0.5)*size, (k-0.5)*size) */ +/** + * the LBN corner of cube (i, j, k), corresponds with location + * (i-0.5)*size, (j-0.5)*size, (k-0.5)*size) + */ #define HASHBIT (5) #define HASHSIZE (size_t)(1 << (3 * HASHBIT)) /*! < hash table size (32768) */ @@ -206,19 +289,19 @@ static void converge(PROCESS *process, const float p1[3], const float p2[3], flo #define HASH(i, j, k) ((((( (i) & 31) << 5) | ( (j) & 31)) << 5) | ( (k) & 31) ) #define MB_BIT(i, bit) (((i) >> (bit)) & 1) -#define FLIP(i, bit) ((i) ^ 1 << (bit)) /* flip the given bit of i */ +// #define FLIP(i, bit) ((i) ^ 1 << (bit)) /* flip the given bit of i */ +/* ******************** DENSITY COPMPUTATION ********************* */ -/* **************** POLYGONIZATION ************************ */ - -static void calc_mballco(MetaElem *ml, float vec[3]) -{ - if (ml->mat) { - mul_m4_v3((float (*)[4])ml->mat, vec); - } -} - -static float densfunc(MetaElem *ball, float x, float y, float z) +/** + * Computes density from given metaball at given position. + * Metaball equation is: ``(1 - r^2 / R^2)^3 * s`` + * + * r = distance from center + * R = metaball radius + * s - metaball stiffness + */ +static float densfunc(const MetaElem *ball, float x, float y, float z) { float dist2; float dvec[3] = {x, y, z}; @@ -229,37 +312,26 @@ static float densfunc(MetaElem *ball, float x, float y, float z) case MB_BALL: /* do nothing */ break; - case MB_TUBE: - if (dvec[0] > ball->expx) dvec[0] -= ball->expx; - else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; - else dvec[0] = 0.0; - break; + case MB_CUBE: + if (dvec[2] > ball->expz) dvec[2] -= ball->expz; + else if (dvec[2] < -ball->expz) dvec[2] += ball->expz; + else dvec[2] = 0.0; + /* fall through */ case MB_PLANE: - if (dvec[0] > ball->expx) dvec[0] -= ball->expx; - else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; - else dvec[0] = 0.0; if (dvec[1] > ball->expy) dvec[1] -= ball->expy; else if (dvec[1] < -ball->expy) dvec[1] += ball->expy; else dvec[1] = 0.0; + /* fall through */ + case MB_TUBE: + if (dvec[0] > ball->expx) dvec[0] -= ball->expx; + else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; + else dvec[0] = 0.0; break; case MB_ELIPSOID: dvec[0] /= ball->expx; dvec[1] /= ball->expy; dvec[2] /= ball->expz; break; - case MB_CUBE: - if (dvec[0] > ball->expx) dvec[0] -= ball->expx; - else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; - else dvec[0] = 0.0; - - if (dvec[1] > ball->expy) dvec[1] -= ball->expy; - else if (dvec[1] < -ball->expy) dvec[1] += ball->expy; - else dvec[1] = 0.0; - - if (dvec[2] > ball->expz) dvec[2] -= ball->expz; - else if (dvec[2] < -ball->expz) dvec[2] += ball->expz; - else dvec[2] = 0.0; - break; /* *** deprecated, could be removed?, do-versioned at least *** */ case MB_TUBEX: @@ -277,208 +349,107 @@ static float densfunc(MetaElem *ball, float x, float y, float z) else if (dvec[2] < -ball->len) dvec[2] += ball->len; else dvec[2] = 0.0; break; - /* *** end deprecated *** */ + /* *** end deprecated *** */ } - dist2 = 1.0f - (len_squared_v3(dvec) / ball->rad2); + /* ball->rad2 is inverse of squared rad */ + dist2 = 1.0f - (len_squared_v3(dvec) * ball->rad2); - if ((ball->flag & MB_NEGATIVE) == 0) { - return (dist2 < 0.0f) ? -0.5f : (ball->s * dist2 * dist2 * dist2) - 0.5f; - } - else { - return (dist2 < 0.0f) ? 0.5f : 0.5f - (ball->s * dist2 * dist2 * dist2); - } -} - -static octal_node *find_metaball_octal_node(octal_node *node, float x, float y, float z, short depth) -{ - if (!depth) return node; - - if (z < node->z) { - if (y < node->y) { - if (x < node->x) { - if (node->nodes[0]) - return find_metaball_octal_node(node->nodes[0], x, y, z, depth--); - else - return node; - } - else { - if (node->nodes[1]) - return find_metaball_octal_node(node->nodes[1], x, y, z, depth--); - else - return node; - } - } - else { - if (x < node->x) { - if (node->nodes[3]) - return find_metaball_octal_node(node->nodes[3], x, y, z, depth--); - else - return node; - } - else { - if (node->nodes[2]) - return find_metaball_octal_node(node->nodes[2], x, y, z, depth--); - else - return node; - } - } - } - else { - if (y < node->y) { - if (x < node->x) { - if (node->nodes[4]) - return find_metaball_octal_node(node->nodes[4], x, y, z, depth--); - else - return node; - } - else { - if (node->nodes[5]) - return find_metaball_octal_node(node->nodes[5], x, y, z, depth--); - else - return node; - } - } - else { - if (x < node->x) { - if (node->nodes[7]) - return find_metaball_octal_node(node->nodes[7], x, y, z, depth--); - else - return node; - } - else { - if (node->nodes[6]) - return find_metaball_octal_node(node->nodes[6], x, y, z, depth--); - else - return node; - } - } - } - - /* all cases accounted for */ - BLI_assert(0); + /* ball->s is negative if metaball is negative */ + return (dist2 < 0.0f) ? 0.0f : (ball->s * dist2 * dist2 * dist2); } +/** + * Computes density at given position form all metaballs which contain this point in their box. + * Traverses BVH using a queue. + */ static float metaball(PROCESS *process, float x, float y, float z) -/* float x, y, z; */ { - octal_tree *metaball_tree = process->metaball_tree; - struct octal_node *node; - struct ml_pointer *ml_p; - float dens = 0; - int a; - - if (process->totelem > 1) { - node = find_metaball_octal_node(metaball_tree->first, x, y, z, metaball_tree->depth); - if (node) { - for (ml_p = node->elems.first; ml_p; ml_p = ml_p->next) { - dens += densfunc(ml_p->ml, x, y, z); - } - - dens += -0.5f * (metaball_tree->pos - node->pos); - dens += 0.5f * (metaball_tree->neg - node->neg); - } - else { - for (a = 0; a < process->totelem; a++) { - dens += densfunc(process->mainb[a], x, y, z); + int i; + float dens = 0.0f; + unsigned int front = 0, back = 0; + MetaballBVHNode *node; + + process->bvh_queue[front++] = &process->metaball_bvh; + + while (front != back) { + node = process->bvh_queue[back++]; + + for (i = 0; i < 2; i++) { + if ((node->bb[i].min[0] <= x) && (node->bb[i].max[0] >= x) && + (node->bb[i].min[1] <= y) && (node->bb[i].max[1] >= y) && + (node->bb[i].min[2] <= z) && (node->bb[i].max[2] >= z)) + { + if (node->child[i]) process->bvh_queue[front++] = node->child[i]; + else dens += densfunc(node->bb[i].ml, x, y, z); } } } - else { - dens += densfunc(process->mainb[0], x, y, z); - } return process->thresh - dens; } -/* ******************************************** */ - -static void accum_mballfaces(PROCESS *process, int i1, int i2, int i3, int i4) +/** + * Adds face to indices, expands memory if needed. + */ +static void make_face(PROCESS *process, int i1, int i2, int i3, int i4) { - int *newi, *cur; - /* static int i = 0; I would like to delete altogether, but I don't dare to, yet */ - - if (process->totindex == process->curindex) { - process->totindex += 256; - newi = MEM_mallocN(4 * sizeof(int) * process->totindex, "vertindex"); - - if (process->indices) { - memcpy(newi, process->indices, 4 * sizeof(int) * (process->totindex - 256)); - MEM_freeN(process->indices); - } - process->indices = newi; + int *cur; + +#ifdef USE_ACCUM_NORMAL + float n[3]; +#endif + + if (UNLIKELY(process->totindex == process->curindex)) { + process->totindex += 4096; + process->indices = MEM_reallocN(process->indices, sizeof(int[4]) * process->totindex); } - - cur = process->indices + 4 * process->curindex; + + cur = process->indices[process->curindex++]; /* displists now support array drawing, we treat tri's as fake quad */ - + cur[0] = i1; cur[1] = i2; cur[2] = i3; - if (i4 == 0) + + if (i4 == 0) { cur[3] = i3; - else + } + else { cur[3] = i4; - - process->curindex++; - -} - -/* ******************* MEMORY MANAGEMENT *********************** */ -static void *new_pgn_element(PROCESS *process, int size) -{ - /* during polygonize 1000s of elements are allocated - * and never freed in between. Freeing only done at the end. - */ - int blocksize = 16384; - void *adr; - - if (size > 10000 || size == 0) { - printf("incorrect use of new_pgn_element\n"); } - else if (size == -1) { - struct pgn_elements *cur = process->pgn_list.first; - while (cur) { - MEM_freeN(cur->data); - cur = cur->next; - } - BLI_freelistN(&process->pgn_list); - - return NULL; + +#ifdef USE_ACCUM_NORMAL + if (i4 == 0) { + normal_tri_v3(n, process->co[i1], process->co[i2], process->co[i3]); + accumulate_vertex_normals( + process->no[i1], process->no[i2], process->no[i3], NULL, n, + process->co[i1], process->co[i2], process->co[i3], NULL); } - - size = 4 * ( (size + 3) / 4); - - if (process->pgn_current) { - if (size + process->pgn_offset < blocksize) { - adr = (void *) (process->pgn_current->data + process->pgn_offset); - process->pgn_offset += size; - return adr; - } + else { + normal_quad_v3(n, process->co[i1], process->co[i2], process->co[i3], process->co[i4]); + accumulate_vertex_normals( + process->no[i1], process->no[i2], process->no[i3], process->no[i4], n, + process->co[i1], process->co[i2], process->co[i3], process->co[i4]); } - - process->pgn_current = MEM_callocN(sizeof(struct pgn_elements), "newpgn"); - process->pgn_current->data = MEM_callocN(blocksize, "newpgn"); - BLI_addtail(&process->pgn_list, process->pgn_current); - - process->pgn_offset = size; - return process->pgn_current->data; +#endif + } +/* Frees allocated memory */ static void freepolygonize(PROCESS *process) { - MEM_freeN(process->corners); - MEM_freeN(process->edges); - MEM_freeN(process->centers); - - new_pgn_element(process, -1); - - if (process->vertices.ptr) { - MEM_freeN(process->vertices.ptr); - } + if (process->corners) MEM_freeN(process->corners); + if (process->edges) MEM_freeN(process->edges); + if (process->centers) MEM_freeN(process->centers); + if (process->mainb) MEM_freeN(process->mainb); + if (process->bvh_queue) MEM_freeN(process->bvh_queue); + if (process->pgn_elements) BLI_memarena_free(process->pgn_elements); } +/* **************** POLYGONIZATION ************************ */ + /**** Cubical Polygonization (optional) ****/ #define LB 0 /* left bottom edge */ @@ -495,6 +466,7 @@ static void freepolygonize(PROCESS *process) #define TF 11 /* top far edge */ static INTLISTS *cubetable[256]; +static char faces[256]; /* edge: LB, LT, LN, LF, RB, RT, RN, RF, BN, BF, TN, TF */ static int corner1[12] = { @@ -504,77 +476,89 @@ static int corner2[12] = { LBF, LTF, LTN, LTF, RBF, RTF, RTN, RTF, RBN, RBF, RTN, RTF }; static int leftface[12] = { - B, L, L, F, R, T, N, R, N, B, T, F + B, L, L, F, R, T, N, R, N, B, T, F }; /* face on left when going corner1 to corner2 */ static int rightface[12] = { - L, T, N, L, B, R, R, F, B, F, N, T + L, T, N, L, B, R, R, F, B, F, N, T }; /* face on right when going corner1 to corner2 */ - -/* docube: triangulate the cube directly, without decomposition */ - -static void docube(PROCESS *process, CUBE *cube, MetaBall *mb) +/** + * triangulate the cube directly, without decomposition + */ +static void docube(PROCESS *process, CUBE *cube) { INTLISTS *polys; CORNER *c1, *c2; int i, index = 0, count, indexar[8]; - + + /* Determine which case cube falls into. */ for (i = 0; i < 8; i++) { if (cube->corners[i]->value > 0.0f) { index += (1 << i); } } - + + /* Using faces[] table, adds neighbouring cube if surface intersects face in this direction. */ + if (MB_BIT(faces[index], 0)) add_cube(process, cube->i - 1, cube->j, cube->k); + if (MB_BIT(faces[index], 1)) add_cube(process, cube->i + 1, cube->j, cube->k); + if (MB_BIT(faces[index], 2)) add_cube(process, cube->i, cube->j - 1, cube->k); + if (MB_BIT(faces[index], 3)) add_cube(process, cube->i, cube->j + 1, cube->k); + if (MB_BIT(faces[index], 4)) add_cube(process, cube->i, cube->j, cube->k - 1); + if (MB_BIT(faces[index], 5)) add_cube(process, cube->i, cube->j, cube->k + 1); + + /* Using cubetable[], determines polygons for output. */ for (polys = cubetable[index]; polys; polys = polys->next) { INTLIST *edges; - + count = 0; - + /* Sets needed vertex id's lying on the edges. */ for (edges = polys->list; edges; edges = edges->next) { c1 = cube->corners[corner1[edges->i]]; c2 = cube->corners[corner2[edges->i]]; - - indexar[count] = vertid(process, c1, c2, mb); + + indexar[count] = vertid(process, c1, c2); count++; } + + /* Adds faces to output. */ if (count > 2) { switch (count) { case 3: - accum_mballfaces(process, indexar[2], indexar[1], indexar[0], 0); + make_face(process, indexar[2], indexar[1], indexar[0], 0); break; case 4: - if (indexar[0] == 0) accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); - else accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); + if (indexar[0] == 0) make_face(process, indexar[0], indexar[3], indexar[2], indexar[1]); + else make_face(process, indexar[3], indexar[2], indexar[1], indexar[0]); break; case 5: - if (indexar[0] == 0) accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); - else accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); - - accum_mballfaces(process, indexar[4], indexar[3], indexar[0], 0); + if (indexar[0] == 0) make_face(process, indexar[0], indexar[3], indexar[2], indexar[1]); + else make_face(process, indexar[3], indexar[2], indexar[1], indexar[0]); + + make_face(process, indexar[4], indexar[3], indexar[0], 0); break; case 6: if (indexar[0] == 0) { - accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); - accum_mballfaces(process, indexar[0], indexar[5], indexar[4], indexar[3]); + make_face(process, indexar[0], indexar[3], indexar[2], indexar[1]); + make_face(process, indexar[0], indexar[5], indexar[4], indexar[3]); } else { - accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); - accum_mballfaces(process, indexar[5], indexar[4], indexar[3], indexar[0]); + make_face(process, indexar[3], indexar[2], indexar[1], indexar[0]); + make_face(process, indexar[5], indexar[4], indexar[3], indexar[0]); } break; case 7: if (indexar[0] == 0) { - accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); - accum_mballfaces(process, indexar[0], indexar[5], indexar[4], indexar[3]); + make_face(process, indexar[0], indexar[3], indexar[2], indexar[1]); + make_face(process, indexar[0], indexar[5], indexar[4], indexar[3]); } else { - accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); - accum_mballfaces(process, indexar[5], indexar[4], indexar[3], indexar[0]); + make_face(process, indexar[3], indexar[2], indexar[1], indexar[0]); + make_face(process, indexar[5], indexar[4], indexar[3], indexar[0]); } - - accum_mballfaces(process, indexar[6], indexar[5], indexar[0], 0); + + make_face(process, indexar[6], indexar[5], indexar[0], 0); break; } @@ -582,63 +566,10 @@ static void docube(PROCESS *process, CUBE *cube, MetaBall *mb) } } - -/* testface: given cube at lattice (i, j, k), and four corners of face, - * if surface crosses face, compute other four corners of adjacent cube - * and add new cube to cube stack */ - -static void testface(PROCESS *process, int i, int j, int k, CUBE *old, int bit, int c1, int c2, int c3, int c4) -{ - CUBE newc; - CUBES *oldcubes = process->cubes; - CORNER *corn1, *corn2, *corn3, *corn4; - int n, pos; - - corn1 = old->corners[c1]; - corn2 = old->corners[c2]; - corn3 = old->corners[c3]; - corn4 = old->corners[c4]; - - pos = corn1->value > 0.0f ? 1 : 0; - - /* test if no surface crossing */ - if ( (corn2->value > 0) == pos && (corn3->value > 0) == pos && (corn4->value > 0) == pos) return; - /* test if cube out of bounds */ - /*if ( abs(i) > p->bounds || abs(j) > p->bounds || abs(k) > p->bounds) return;*/ - /* test if already visited (always as last) */ - if (setcenter(process, process->centers, i, j, k)) { - return; - } - - /* create new cube and add cube to top of stack: */ - process->cubes = (CUBES *) new_pgn_element(process, sizeof(CUBES)); - process->cubes->next = oldcubes; - - newc.i = i; - newc.j = j; - newc.k = k; - for (n = 0; n < 8; n++) newc.corners[n] = NULL; - - newc.corners[FLIP(c1, bit)] = corn1; - newc.corners[FLIP(c2, bit)] = corn2; - newc.corners[FLIP(c3, bit)] = corn3; - newc.corners[FLIP(c4, bit)] = corn4; - - if (newc.corners[0] == NULL) newc.corners[0] = setcorner(process, i, j, k); - if (newc.corners[1] == NULL) newc.corners[1] = setcorner(process, i, j, k + 1); - if (newc.corners[2] == NULL) newc.corners[2] = setcorner(process, i, j + 1, k); - if (newc.corners[3] == NULL) newc.corners[3] = setcorner(process, i, j + 1, k + 1); - if (newc.corners[4] == NULL) newc.corners[4] = setcorner(process, i + 1, j, k); - if (newc.corners[5] == NULL) newc.corners[5] = setcorner(process, i + 1, j, k + 1); - if (newc.corners[6] == NULL) newc.corners[6] = setcorner(process, i + 1, j + 1, k); - if (newc.corners[7] == NULL) newc.corners[7] = setcorner(process, i + 1, j + 1, k + 1); - - process->cubes->cube = newc; -} - -/* setcorner: return corner with the given lattice location - * set (and cache) its function value */ - +/** + * return corner with the given lattice location + * set (and cache) its function value + */ static CORNER *setcorner(PROCESS *process, int i, int j, int k) { /* for speed, do corner value caching here */ @@ -648,32 +579,33 @@ static CORNER *setcorner(PROCESS *process, int i, int j, int k) /* does corner exist? */ index = HASH(i, j, k); c = process->corners[index]; - + for (; c != NULL; c = c->next) { if (c->i == i && c->j == j && c->k == k) { return c; } } - c = (CORNER *) new_pgn_element(process, sizeof(CORNER)); + c = BLI_memarena_alloc(process->pgn_elements, sizeof(CORNER)); - c->i = i; + c->i = i; c->co[0] = ((float)i - 0.5f) * process->size; - c->j = j; + c->j = j; c->co[1] = ((float)j - 0.5f) * process->size; - c->k = k; + c->k = k; c->co[2] = ((float)k - 0.5f) * process->size; - c->value = process->function(process, c->co[0], c->co[1], c->co[2]); - + + c->value = metaball(process, c->co[0], c->co[1], c->co[2]); + c->next = process->corners[index]; process->corners[index] = c; - + return c; } - -/* nextcwedge: return next clockwise edge from given edge around given face */ - +/** + * return next clockwise edge from given edge around given face + */ static int nextcwedge(int edge, int face) { switch (edge) { @@ -705,18 +637,18 @@ static int nextcwedge(int edge, int face) return 0; } - -/* otherface: return face adjoining edge that is not the given face */ - +/** + * \return the face adjoining edge that is not the given face + */ static int otherface(int edge, int face) { int other = leftface[edge]; return face == other ? rightface[edge] : other; } - -/* makecubetable: create the 256 entry table for cubical polygonization */ - +/** + * create the 256 entry table for cubical polygonization + */ static void makecubetable(void) { static bool is_done = false; @@ -731,22 +663,22 @@ static void makecubetable(void) for (e = 0; e < 12; e++) if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) { INTLIST *ints = NULL; - INTLISTS *lists = (INTLISTS *) MEM_callocN(sizeof(INTLISTS), "mball_intlist"); + INTLISTS *lists = MEM_callocN(sizeof(INTLISTS), "mball_intlist"); int start = e, edge = e; - + /* get face that is to right of edge from pos to neg corner: */ int face = pos[corner1[e]] ? rightface[e] : leftface[e]; - + while (1) { edge = nextcwedge(edge, face); done[edge] = 1; if (pos[corner1[edge]] != pos[corner2[edge]]) { INTLIST *tmp = ints; - - ints = (INTLIST *) MEM_callocN(sizeof(INTLIST), "mball_intlist"); + + ints = MEM_callocN(sizeof(INTLIST), "mball_intlist"); ints->i = edge; ints->next = tmp; /* add edge to head of list */ - + if (edge == start) break; face = otherface(edge, face); } @@ -756,6 +688,23 @@ static void makecubetable(void) cubetable[i] = lists; } } + + for (i = 0; i < 256; i++) { + INTLISTS *polys; + faces[i] = 0; + for (polys = cubetable[i]; polys; polys = polys->next) { + INTLIST *edges; + + for (edges = polys->list; edges; edges = edges->next) { + if (edges->i == LB || edges->i == LT || edges->i == LN || edges->i == LF) faces[i] |= 1 << L; + if (edges->i == RB || edges->i == RT || edges->i == RN || edges->i == RF) faces[i] |= 1 << R; + if (edges->i == LB || edges->i == RB || edges->i == BN || edges->i == BF) faces[i] |= 1 << B; + if (edges->i == LT || edges->i == RT || edges->i == TN || edges->i == TF) faces[i] |= 1 << T; + if (edges->i == LN || edges->i == RN || edges->i == BN || edges->i == TN) faces[i] |= 1 << N; + if (edges->i == LF || edges->i == RF || edges->i == BF || edges->i == TF) faces[i] |= 1 << F; + } + } + } } void BKE_mball_cubeTable_free(void) @@ -768,14 +717,14 @@ void BKE_mball_cubeTable_free(void) lists = cubetable[i]; while (lists) { nlists = lists->next; - + ints = lists->list; while (ints) { nints = ints->next; MEM_freeN(ints); ints = nints; } - + MEM_freeN(lists); lists = nlists; } @@ -785,9 +734,9 @@ void BKE_mball_cubeTable_free(void) /**** Storage ****/ -/* setcenter: set (i, j, k) entry of table[] - * return 1 if already set; otherwise, set and return 0 */ - +/** + * Inserts cube at lattice i, j, k into hash table, marking it as "done" + */ static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k) { int index; @@ -799,30 +748,29 @@ static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const i for (l = q; l != NULL; l = l->next) { if (l->i == i && l->j == j && l->k == k) return 1; } - - newc = (CENTERLIST *) new_pgn_element(process, sizeof(CENTERLIST)); - newc->i = i; - newc->j = j; - newc->k = k; + + newc = BLI_memarena_alloc(process->pgn_elements, sizeof(CENTERLIST)); + newc->i = i; + newc->j = j; + newc->k = k; newc->next = q; table[index] = newc; - + return 0; } - -/* setedge: set vertex id for edge */ - -static void setedge(PROCESS *process, - EDGELIST *table[], - int i1, int j1, - int k1, int i2, - int j2, int k2, - int vid) +/** + * Sets vid of vertex lying on given edge. + */ +static void setedge( + PROCESS *process, + int i1, int j1, int k1, + int i2, int j2, int k2, + int vid) { - unsigned int index; + int index; EDGELIST *newe; - + if (i1 > i2 || (i1 == i2 && (j1 > j2 || (j1 == j2 && k1 > k2)))) { int t = i1; i1 = i2; @@ -835,27 +783,28 @@ static void setedge(PROCESS *process, k2 = t; } index = HASH(i1, j1, k1) + HASH(i2, j2, k2); - newe = (EDGELIST *) new_pgn_element(process, sizeof(EDGELIST)); - newe->i1 = i1; - newe->j1 = j1; + newe = BLI_memarena_alloc(process->pgn_elements, sizeof(EDGELIST)); + + newe->i1 = i1; + newe->j1 = j1; newe->k1 = k1; - newe->i2 = i2; - newe->j2 = j2; + newe->i2 = i2; + newe->j2 = j2; newe->k2 = k2; newe->vid = vid; - newe->next = table[index]; - table[index] = newe; + newe->next = process->edges[index]; + process->edges[index] = newe; } - -/* getedge: return vertex id for edge; return -1 if not set */ - +/** + * \return vertex id for edge; return -1 if not set + */ static int getedge(EDGELIST *table[], int i1, int j1, int k1, int i2, int j2, int k2) { EDGELIST *q; - + if (i1 > i2 || (i1 == i2 && (j1 > j2 || (j1 == j2 && k1 > k2)))) { int t = i1; i1 = i2; @@ -878,62 +827,52 @@ static int getedge(EDGELIST *table[], return -1; } - -/**** Vertices ****/ - -#undef R - - - -/* vertid: return index for vertex on edge: - * c1->value and c2->value are presumed of different sign - * return saved index if any; else compute vertex and save */ - -/* addtovertices: add v to sequence of vertices */ - -static void addtovertices(VERTICES *vertices, VERTEX v) +/** + * Adds a vertex, expands memory if needed. + */ +static void addtovertices(PROCESS *process, const float v[3], const float no[3]) { - if (vertices->count == vertices->max) { - int i; - VERTEX *newv; - vertices->max = vertices->count == 0 ? 10 : 2 * vertices->count; - newv = (VERTEX *) MEM_callocN(vertices->max * sizeof(VERTEX), "addtovertices"); - - for (i = 0; i < vertices->count; i++) newv[i] = vertices->ptr[i]; - - if (vertices->ptr != NULL) MEM_freeN(vertices->ptr); - vertices->ptr = newv; + if (process->curvertex == process->totvertex) { + process->totvertex += 4096; + process->co = MEM_reallocN(process->co, process->totvertex * sizeof(float[3])); + process->no = MEM_reallocN(process->no, process->totvertex * sizeof(float[3])); } - vertices->ptr[vertices->count++] = v; -} -/* vnormal: compute unit length surface normal at point */ + copy_v3_v3(process->co[process->curvertex], v); + copy_v3_v3(process->no[process->curvertex], no); + process->curvertex++; +} + +#ifndef USE_ACCUM_NORMAL +/** + * Computes normal from density field at given point. + * + * \note Doesn't do normalization! + */ static void vnormal(PROCESS *process, const float point[3], float r_no[3]) { - const float delta = 0.2f * process->delta; - const float f = process->function(process, point[0], point[1], point[2]); + const float delta = process->delta; + const float f = metaball(process, point[0], point[1], point[2]); - r_no[0] = process->function(process, point[0] + delta, point[1], point[2]) - f; - r_no[1] = process->function(process, point[0], point[1] + delta, point[2]) - f; - r_no[2] = process->function(process, point[0], point[1], point[2] + delta) - f; + r_no[0] = metaball(process, point[0] + delta, point[1], point[2]) - f; + r_no[1] = metaball(process, point[0], point[1] + delta, point[2]) - f; + r_no[2] = metaball(process, point[0], point[1], point[2] + delta) - f; -#if 1 - normalize_v3(r_no); -#else +#if 0 f = normalize_v3(r_no); - + if (0) { float tvec[3]; - + delta *= 2.0f; - + f = process->function(process, point[0], point[1], point[2]); - + tvec[0] = process->function(process, point[0] + delta, point[1], point[2]) - f; tvec[1] = process->function(process, point[0], point[1] + delta, point[2]) - f; tvec[2] = process->function(process, point[0], point[1], point[2] + delta) - f; - + if (normalize_v3(tvec) != 0.0f) { add_v3_v3(r_no, tvec); normalize_v3(r_no); @@ -941,355 +880,242 @@ static void vnormal(PROCESS *process, const float point[3], float r_no[3]) } #endif } +#endif /* USE_ACCUM_NORMAL */ - -static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2, MetaBall *mb) +/** + * \return the id of vertex between two corners. + * + * If it wasn't previously computed, does #converge() and adds vertex to process. + */ +static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2) { - VERTEX v; + float v[3], no[3]; int vid = getedge(process->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k); - if (vid != -1) { - return vid; /* previously computed */ - } + if (vid != -1) return vid; /* previously computed */ - converge(process, c1->co, c2->co, c1->value, c2->value, v.co, mb, 1); /* position */ - vnormal(process, v.co, v.no); + converge(process, c1, c2, v); /* position */ + +#ifdef USE_ACCUM_NORMAL + zero_v3(no); +#else + vnormal(process, v, no); +#endif + + addtovertices(process, v, no); /* save vertex */ + vid = (int)process->curvertex - 1; + setedge(process, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid); - addtovertices(&process->vertices, v); /* save vertex */ - vid = process->vertices.count - 1; - setedge(process, process->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid); - return vid; } - -/* converge: from two points of differing sign, converge to zero crossing */ -/* watch it: p1 and p2 are used to calculate */ -static void converge(PROCESS *process, const float p1[3], const float p2[3], float v1, float v2, - float p[3], MetaBall *mb, int f) +/** + * Given two corners, computes approximation of surface intersection point between them. + * In case of small threshold, do bisection. + */ +static void converge(PROCESS *process, const CORNER *c1, const CORNER *c2, float r_p[3]) { - int i = 0; - float pos[3], neg[3]; - float positive = 0.0f, negative = 0.0f; - float dvec[3]; - - if (v1 < 0) { - copy_v3_v3(pos, p2); - copy_v3_v3(neg, p1); - positive = v2; - negative = v1; + float tmp, dens; + unsigned int i; + float c1_value, c1_co[3]; + float c2_value, c2_co[3]; + + if (c1->value < c2->value) { + c1_value = c2->value; + copy_v3_v3(c1_co, c2->co); + c2_value = c1->value; + copy_v3_v3(c2_co, c1->co); } else { - copy_v3_v3(pos, p1); - copy_v3_v3(neg, p2); - positive = v1; - negative = v2; + c1_value = c1->value; + copy_v3_v3(c1_co, c1->co); + c2_value = c2->value; + copy_v3_v3(c2_co, c2->co); } - sub_v3_v3v3(dvec, pos, neg); -/* Approximation by linear interpolation is faster then binary subdivision, - * but it results sometimes (mb->thresh < 0.2) into the strange results */ - if ((mb->thresh > 0.2f) && (f == 1)) { - if ((dvec[1] == 0.0f) && (dvec[2] == 0.0f)) { - p[0] = neg[0] - negative * dvec[0] / (positive - negative); - p[1] = neg[1]; - p[2] = neg[2]; - return; - } - if ((dvec[0] == 0.0f) && (dvec[2] == 0.0f)) { - p[0] = neg[0]; - p[1] = neg[1] - negative * dvec[1] / (positive - negative); - p[2] = neg[2]; - return; - } - if ((dvec[0] == 0.0f) && (dvec[1] == 0.0f)) { - p[0] = neg[0]; - p[1] = neg[1]; - p[2] = neg[2] - negative * dvec[2] / (positive - negative); - return; - } - } + for (i = 0; i < process->converge_res; i++) { + interp_v3_v3v3(r_p, c1_co, c2_co, 0.5f); + dens = metaball(process, r_p[0], r_p[1], r_p[2]); - if ((dvec[1] == 0.0f) && (dvec[2] == 0.0f)) { - p[1] = neg[1]; - p[2] = neg[2]; - while (1) { - if (i++ == RES) return; - p[0] = 0.5f * (pos[0] + neg[0]); - if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[0] = p[0]; - else neg[0] = p[0]; + if (dens > 0.0f) { + c1_value = dens; + copy_v3_v3(c1_co, r_p); } - } - - if ((dvec[0] == 0.0f) && (dvec[2] == 0.0f)) { - p[0] = neg[0]; - p[2] = neg[2]; - while (1) { - if (i++ == RES) return; - p[1] = 0.5f * (pos[1] + neg[1]); - if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[1] = p[1]; - else neg[1] = p[1]; + else { + c2_value = dens; + copy_v3_v3(c2_co, r_p); } } - if ((dvec[0] == 0.0f) && (dvec[1] == 0.0f)) { - p[0] = neg[0]; - p[1] = neg[1]; - while (1) { - if (i++ == RES) return; - p[2] = 0.5f * (pos[2] + neg[2]); - if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[2] = p[2]; - else neg[2] = p[2]; - } - } + tmp = -c1_value / (c2_value - c1_value); + interp_v3_v3v3(r_p, c1_co, c2_co, tmp); +} - /* This is necessary to find start point */ - while (1) { - mid_v3_v3v3(&p[0], pos, neg); +/** + * Adds cube at given lattice position to cube stack of process. + */ +static void add_cube(PROCESS *process, int i, int j, int k) +{ + CUBES *ncube; + int n; - if (i++ == RES) { - return; - } + /* test if cube has been found before */ + if (setcenter(process, process->centers, i, j, k) == 0) { + /* push cube on stack: */ + ncube = BLI_memarena_alloc(process->pgn_elements, sizeof(CUBES)); + ncube->next = process->cubes; + process->cubes = ncube; - if ((process->function(process, p[0], p[1], p[2])) > 0.0f) { - copy_v3_v3(pos, &p[0]); - } - else { - copy_v3_v3(neg, &p[0]); - } + ncube->cube.i = i; + ncube->cube.j = j; + ncube->cube.k = k; + + /* set corners of initial cube: */ + for (n = 0; n < 8; n++) + ncube->cube.corners[n] = setcorner(process, i + MB_BIT(n, 2), j + MB_BIT(n, 1), k + MB_BIT(n, 0)); } } -/* ************************************** */ -static void add_cube(PROCESS *process, int i, int j, int k, int count) +static void next_lattice(int r[3], const float pos[3], const float size) { - CUBES *ncube; - int n; - int a, b, c; - - /* hmmm, not only one, but eight cube will be added on the stack - * ... */ - for (a = i - 1; a < i + count; a++) - for (b = j - 1; b < j + count; b++) - for (c = k - 1; c < k + count; c++) { - /* test if cube has been found before */ - if (setcenter(process, process->centers, a, b, c) == 0) { - /* push cube on stack: */ - ncube = (CUBES *) new_pgn_element(process, sizeof(CUBES)); - ncube->next = process->cubes; - process->cubes = ncube; - - ncube->cube.i = a; - ncube->cube.j = b; - ncube->cube.k = c; - - /* set corners of initial cube: */ - for (n = 0; n < 8; n++) - ncube->cube.corners[n] = setcorner(process, a + MB_BIT(n, 2), b + MB_BIT(n, 1), c + MB_BIT(n, 0)); - } - } + r[0] = (int)ceil((pos[0] / size) + 0.5f); + r[1] = (int)ceil((pos[1] / size) + 0.5f); + r[2] = (int)ceil((pos[2] / size) + 0.5f); } - - -static void find_first_points(PROCESS *process, MetaBall *mb, int a) +static void prev_lattice(int r[3], const float pos[3], const float size) { - MetaElem *ml; - float f; - - ml = process->mainb[a]; - f = 1.0f - (mb->thresh / ml->s); - - /* Skip, when Stiffness of MetaElement is too small ... MetaElement can't be - * visible alone ... but still can influence others MetaElements :-) */ - if (f > 0.0f) { - float IN[3] = {0.0f}, OUT[3] = {0.0f}, in[3] = {0.0f}, out[3]; - int i, j, k, c_i, c_j, c_k; - int index[3] = {1, 0, -1}; - float in_v /*, out_v*/; - float workp[3]; - float dvec[3]; - float tmp_v, workp_v, max_len_sq, nx, ny, nz, max_dim; - - calc_mballco(ml, in); - in_v = process->function(process, in[0], in[1], in[2]); - - for (i = 0; i < 3; i++) { - switch (ml->type) { - case MB_BALL: - OUT[0] = out[0] = IN[0] + index[i] * ml->rad; - break; - case MB_TUBE: - case MB_PLANE: - case MB_ELIPSOID: - case MB_CUBE: - OUT[0] = out[0] = IN[0] + index[i] * (ml->expx + ml->rad); - break; - } + next_lattice(r, pos, size); + r[0]--; r[1]--; r[2]--; +} +static void closest_latice(int r[3], const float pos[3], const float size) +{ + r[0] = (int)floorf(pos[0] / size + 1.0f); + r[1] = (int)floorf(pos[1] / size + 1.0f); + r[2] = (int)floorf(pos[2] / size + 1.0f); +} - for (j = 0; j < 3; j++) { - switch (ml->type) { - case MB_BALL: - OUT[1] = out[1] = IN[1] + index[j] * ml->rad; - break; - case MB_TUBE: - case MB_PLANE: - case MB_ELIPSOID: - case MB_CUBE: - OUT[1] = out[1] = IN[1] + index[j] * (ml->expy + ml->rad); - break; +/** + * Find at most 26 cubes to start polygonization from. + */ +static void find_first_points(PROCESS *process, const unsigned int em) +{ + const MetaElem *ml; + int center[3], lbn[3], rtf[3], it[3], dir[3], add[3]; + float tmp[3], a, b; + + ml = process->mainb[em]; + + mid_v3_v3v3(tmp, ml->bb->vec[0], ml->bb->vec[6]); + closest_latice(center, tmp, process->size); + prev_lattice(lbn, ml->bb->vec[0], process->size); + next_lattice(rtf, ml->bb->vec[6], process->size); + + for (dir[0] = -1; dir[0] <= 1; dir[0]++) { + for (dir[1] = -1; dir[1] <= 1; dir[1]++) { + for (dir[2] = -1; dir[2] <= 1; dir[2]++) { + if (dir[0] == 0 && dir[1] == 0 && dir[2] == 0) { + continue; } - - for (k = 0; k < 3; k++) { - out[0] = OUT[0]; - out[1] = OUT[1]; - switch (ml->type) { - case MB_BALL: - case MB_TUBE: - case MB_PLANE: - out[2] = IN[2] + index[k] * ml->rad; - break; - case MB_ELIPSOID: - case MB_CUBE: - out[2] = IN[2] + index[k] * (ml->expz + ml->rad); - break; - } - - calc_mballco(ml, out); - - /*out_v = process->function(out[0], out[1], out[2]);*/ /*UNUSED*/ - - /* find "first points" on Implicit Surface of MetaElemnt ml */ - copy_v3_v3(workp, in); - workp_v = in_v; - max_len_sq = len_squared_v3v3(out, in); - - nx = fabsf((out[0] - in[0]) / process->size); - ny = fabsf((out[1] - in[1]) / process->size); - nz = fabsf((out[2] - in[2]) / process->size); - - max_dim = max_fff(nx, ny, nz); - if (max_dim != 0.0f) { - float len_sq = 0.0f; - - dvec[0] = (out[0] - in[0]) / max_dim; - dvec[1] = (out[1] - in[1]) / max_dim; - dvec[2] = (out[2] - in[2]) / max_dim; - - while (len_sq <= max_len_sq) { - add_v3_v3(workp, dvec); - - /* compute value of implicite function */ - tmp_v = process->function(process, workp[0], workp[1], workp[2]); - /* add cube to the stack, when value of implicite function crosses zero value */ - if ((tmp_v < 0.0f && workp_v >= 0.0f) || (tmp_v > 0.0f && workp_v <= 0.0f)) { - - /* indexes of CUBE, which includes "first point" */ - c_i = (int)floor(workp[0] / process->size); - c_j = (int)floor(workp[1] / process->size); - c_k = (int)floor(workp[2] / process->size); - - /* add CUBE (with indexes c_i, c_j, c_k) to the stack, - * this cube includes found point of Implicit Surface */ - if ((ml->flag & MB_NEGATIVE) == 0) { - add_cube(process, c_i, c_j, c_k, 1); - } - else { - add_cube(process, c_i, c_j, c_k, 2); - } - } - len_sq = len_squared_v3v3(workp, in); - workp_v = tmp_v; - } + copy_v3_v3_int(it, center); + + b = setcorner(process, it[0], it[1], it[2])->value; + do { + it[0] += dir[0]; + it[1] += dir[1]; + it[2] += dir[2]; + a = b; + b = setcorner(process, it[0], it[1], it[2])->value; + + if (a * b < 0.0f) { + add[0] = it[0] - dir[0]; + add[1] = it[1] - dir[1]; + add[2] = it[2] - dir[2]; + DO_MIN(it, add); + add_cube(process, add[0], add[1], add[2]); + break; } - } + } while ((it[0] > lbn[0]) && (it[1] > lbn[1]) && (it[2] > lbn[2]) && + (it[0] < rtf[0]) && (it[1] < rtf[1]) && (it[2] < rtf[2])); } } } } -static void polygonize(PROCESS *process, MetaBall *mb) +/** + * The main polygonization proc. + * Allocates memory, makes cubetable, + * finds starting surface points + * and processes cubes on the stack until none left. + */ +static void polygonize(PROCESS *process) { CUBE c; - int a; - - process->vertices.count = process->vertices.max = 0; - process->vertices.ptr = NULL; + unsigned int i; - /* allocate hash tables and build cube polygon table: */ process->centers = MEM_callocN(HASHSIZE * sizeof(CENTERLIST *), "mbproc->centers"); process->corners = MEM_callocN(HASHSIZE * sizeof(CORNER *), "mbproc->corners"); process->edges = MEM_callocN(2 * HASHSIZE * sizeof(EDGELIST *), "mbproc->edges"); - makecubetable(); + process->bvh_queue = MEM_callocN(sizeof(MetaballBVHNode *) * process->bvh_queue_size, "Metaball BVH Queue"); - for (a = 0; a < process->totelem; a++) { + makecubetable(); - /* try to find 8 points on the surface for each MetaElem */ - find_first_points(process, mb, a); + for (i = 0; i < process->totelem; i++) { + find_first_points(process, i); } - /* polygonize all MetaElems of current MetaBall */ - while (process->cubes != NULL) { /* process active cubes till none left */ + while (process->cubes != NULL) { c = process->cubes->cube; - - /* polygonize the cube directly: */ - docube(process, &c, mb); - - /* pop current cube from stack */ process->cubes = process->cubes->next; - - /* test six face directions, maybe add to stack: */ - testface(process, c.i - 1, c.j, c.k, &c, 2, LBN, LBF, LTN, LTF); - testface(process, c.i + 1, c.j, c.k, &c, 2, RBN, RBF, RTN, RTF); - testface(process, c.i, c.j - 1, c.k, &c, 1, LBN, LBF, RBN, RBF); - testface(process, c.i, c.j + 1, c.k, &c, 1, LTN, LTF, RTN, RTF); - testface(process, c.i, c.j, c.k - 1, &c, 0, LBN, LTN, RBN, RTN); - testface(process, c.i, c.j, c.k + 1, &c, 0, LBF, LTF, RBF, RTF); + + docube(process, &c); } } -static float init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob) /* return totsize */ +/** + * Iterates over ALL objects in the scene and all of its sets, including + * making all duplis(not only metas). Copies metas to mainb array. + * Computes bounding boxes for building BVH. */ +static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob) { Scene *sce_iter = scene; Base *base; Object *bob; MetaBall *mb; - MetaElem *ml; - float size, totsize, obinv[4][4], obmat[4][4], vec[3]; - //float max = 0.0f; - int a, obnr, zero_size = 0; + const MetaElem *ml; + float obinv[4][4], obmat[4][4]; + unsigned int i; + int obnr, zero_size = 0; char obname[MAX_ID_NAME]; SceneBaseIter iter; copy_m4_m4(obmat, ob->obmat); /* to cope with duplicators from BKE_scene_base_iter_next */ invert_m4_m4(obinv, ob->obmat); - a = 0; - + BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); - + /* make main array */ BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL); while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &bob)) { - if (bob->type == OB_MBALL) { zero_size = 0; ml = NULL; if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) { mb = ob->data; - + if (mb->editelems) ml = mb->editelems->first; else ml = mb->elems.first; } else { char name[MAX_ID_NAME]; int nr; - + BLI_split_name_num(name, &nr, bob->id.name + 2, '.'); if (STREQ(obname, name)) { mb = bob->data; - + if (mb->editelems) ml = mb->editelems->first; else ml = mb->elems.first; } @@ -1312,562 +1138,124 @@ static float init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *sce } if (zero_size) { - unsigned int ml_count = 0; while (ml) { - ml_count++; ml = ml->next; } - process->totelem -= ml_count; } else { while (ml) { if (!(ml->flag & MB_HIDE)) { - int i; - float temp1[4][4], temp2[4][4], temp3[4][4]; - float (*mat)[4] = NULL, (*imat)[4] = NULL; - float max_x, max_y, max_z, min_x, min_y, min_z; + float pos[4][4], rot[4][4]; float expx, expy, expz; + float tempmin[3], tempmax[3]; - max_x = max_y = max_z = -3.4e38; - min_x = min_y = min_z = 3.4e38; - - /* too big stiffness seems only ugly due to linear interpolation - * no need to have possibility for too big stiffness */ - if (ml->s > 10.0f) ml->s = 10.0f; - - /* Rotation of MetaElem is stored in quat */ - quat_to_mat4(temp3, ml->quat); - - /* Translation of MetaElem */ - unit_m4(temp2); - temp2[3][0] = ml->x; - temp2[3][1] = ml->y; - temp2[3][2] = ml->z; - - mul_m4_m4m4(temp1, temp2, temp3); + MetaElem *new_ml; /* make a copy because of duplicates */ - process->mainb[a] = new_pgn_element(process, sizeof(MetaElem)); - *(process->mainb[a]) = *ml; - process->mainb[a]->bb = new_pgn_element(process, sizeof(BoundBox)); + new_ml = BLI_memarena_alloc(process->pgn_elements, sizeof(MetaElem)); + *(new_ml) = *ml; + new_ml->bb = BLI_memarena_alloc(process->pgn_elements, sizeof(BoundBox)); + new_ml->mat = BLI_memarena_alloc(process->pgn_elements, 4 * 4 * sizeof(float)); + new_ml->imat = BLI_memarena_alloc(process->pgn_elements, 4 * 4 * sizeof(float)); - mat = new_pgn_element(process, 4 * 4 * sizeof(float)); - imat = new_pgn_element(process, 4 * 4 * sizeof(float)); - - /* mat is the matrix to transform from mball into the basis-mball */ - invert_m4_m4(obinv, obmat); - mul_m4_m4m4(temp2, obinv, bob->obmat); - /* MetaBall transformation */ - mul_m4_m4m4(mat, temp2, temp1); - - invert_m4_m4(imat, mat); + /* too big stiffness seems only ugly due to linear interpolation + * no need to have possibility for too big stiffness */ + if (ml->s > 10.0f) new_ml->s = 10.0f; + else new_ml->s = ml->s; - process->mainb[a]->rad2 = ml->rad * ml->rad; + /* if metaball is negative, set stiffness negative */ + if (new_ml->flag & MB_NEGATIVE) new_ml->s = -new_ml->s; - process->mainb[a]->mat = (float *) mat; - process->mainb[a]->imat = (float *) imat; + /* Translation of MetaElem */ + unit_m4(pos); + pos[3][0] = ml->x; + pos[3][1] = ml->y; + pos[3][2] = ml->z; - if (!MB_TYPE_SIZE_SQUARED(ml->type)) { - expx = ml->expx; - expy = ml->expy; - expz = ml->expz; - } - else { - expx = ml->expx * ml->expx; - expy = ml->expy * ml->expy; - expz = ml->expz * ml->expz; + /* Rotation of MetaElem is stored in quat */ + quat_to_mat4(rot, ml->quat); + + /* basis object space -> world -> ml object space -> position -> rotation -> ml local space */ + mul_m4_series((float(*)[4])new_ml->mat, obinv, bob->obmat, pos, rot); + /* ml local space -> basis object space */ + invert_m4_m4((float(*)[4])new_ml->imat, (float(*)[4])new_ml->mat); + + /* rad2 is inverse of squared radius */ + new_ml->rad2 = 1 / (ml->rad * ml->rad); + + /* initial dimensions = radius */ + expx = ml->rad; + expy = ml->rad; + expz = ml->rad; + + switch (ml->type) { + case MB_BALL: + break; + case MB_CUBE: /* cube is "expanded" by expz, expy and expx */ + expz += ml->expz; + /* fall through */ + case MB_PLANE: /* plane is "expanded" by expy and expx */ + expy += ml->expy; + /* fall through */ + case MB_TUBE: /* tube is "expanded" by expx */ + expx += ml->expx; + break; + case MB_ELIPSOID: /* ellipsoid is "stretched" by exp* */ + expx *= ml->expx; + expy *= ml->expy; + expz *= ml->expz; + break; } /* untransformed Bounding Box of MetaElem */ /* TODO, its possible the elem type has been changed and the exp* values can use a fallback */ - copy_v3_fl3(process->mainb[a]->bb->vec[0], -expx, -expy, -expz); /* 0 */ - copy_v3_fl3(process->mainb[a]->bb->vec[1], +expx, -expy, -expz); /* 1 */ - copy_v3_fl3(process->mainb[a]->bb->vec[2], +expx, +expy, -expz); /* 2 */ - copy_v3_fl3(process->mainb[a]->bb->vec[3], -expx, +expy, -expz); /* 3 */ - copy_v3_fl3(process->mainb[a]->bb->vec[4], -expx, -expy, +expz); /* 4 */ - copy_v3_fl3(process->mainb[a]->bb->vec[5], +expx, -expy, +expz); /* 5 */ - copy_v3_fl3(process->mainb[a]->bb->vec[6], +expx, +expy, +expz); /* 6 */ - copy_v3_fl3(process->mainb[a]->bb->vec[7], -expx, +expy, +expz); /* 7 */ + copy_v3_fl3(new_ml->bb->vec[0], -expx, -expy, -expz); /* 0 */ + copy_v3_fl3(new_ml->bb->vec[1], +expx, -expy, -expz); /* 1 */ + copy_v3_fl3(new_ml->bb->vec[2], +expx, +expy, -expz); /* 2 */ + copy_v3_fl3(new_ml->bb->vec[3], -expx, +expy, -expz); /* 3 */ + copy_v3_fl3(new_ml->bb->vec[4], -expx, -expy, +expz); /* 4 */ + copy_v3_fl3(new_ml->bb->vec[5], +expx, -expy, +expz); /* 5 */ + copy_v3_fl3(new_ml->bb->vec[6], +expx, +expy, +expz); /* 6 */ + copy_v3_fl3(new_ml->bb->vec[7], -expx, +expy, +expz); /* 7 */ /* transformation of Metalem bb */ for (i = 0; i < 8; i++) - mul_m4_v3((float (*)[4])mat, process->mainb[a]->bb->vec[i]); + mul_m4_v3((float(*)[4])new_ml->mat, new_ml->bb->vec[i]); /* find max and min of transformed bb */ + INIT_MINMAX(tempmin, tempmax); for (i = 0; i < 8; i++) { - /* find maximums */ - if (process->mainb[a]->bb->vec[i][0] > max_x) max_x = process->mainb[a]->bb->vec[i][0]; - if (process->mainb[a]->bb->vec[i][1] > max_y) max_y = process->mainb[a]->bb->vec[i][1]; - if (process->mainb[a]->bb->vec[i][2] > max_z) max_z = process->mainb[a]->bb->vec[i][2]; - /* find minimums */ - if (process->mainb[a]->bb->vec[i][0] < min_x) min_x = process->mainb[a]->bb->vec[i][0]; - if (process->mainb[a]->bb->vec[i][1] < min_y) min_y = process->mainb[a]->bb->vec[i][1]; - if (process->mainb[a]->bb->vec[i][2] < min_z) min_z = process->mainb[a]->bb->vec[i][2]; + DO_MINMAX(new_ml->bb->vec[i], tempmin, tempmax); } - - /* create "new" bb, only point 0 and 6, which are - * necessary for octal tree filling */ - process->mainb[a]->bb->vec[0][0] = min_x - ml->rad; - process->mainb[a]->bb->vec[0][1] = min_y - ml->rad; - process->mainb[a]->bb->vec[0][2] = min_z - ml->rad; - - process->mainb[a]->bb->vec[6][0] = max_x + ml->rad; - process->mainb[a]->bb->vec[6][1] = max_y + ml->rad; - process->mainb[a]->bb->vec[6][2] = max_z + ml->rad; - - a++; - } - ml = ml->next; - } - } - } - } - - - /* totsize (= 'manhattan' radius) */ - totsize = 0.0; - for (a = 0; a < process->totelem; a++) { - - vec[0] = process->mainb[a]->x + process->mainb[a]->rad + process->mainb[a]->expx; - vec[1] = process->mainb[a]->y + process->mainb[a]->rad + process->mainb[a]->expy; - vec[2] = process->mainb[a]->z + process->mainb[a]->rad + process->mainb[a]->expz; - - calc_mballco(process->mainb[a], vec); - - size = fabsf(vec[0]); - if (size > totsize) totsize = size; - size = fabsf(vec[1]); - if (size > totsize) totsize = size; - size = fabsf(vec[2]); - if (size > totsize) totsize = size; - - vec[0] = process->mainb[a]->x - process->mainb[a]->rad; - vec[1] = process->mainb[a]->y - process->mainb[a]->rad; - vec[2] = process->mainb[a]->z - process->mainb[a]->rad; - - calc_mballco(process->mainb[a], vec); - - size = fabsf(vec[0]); - if (size > totsize) totsize = size; - size = fabsf(vec[1]); - if (size > totsize) totsize = size; - size = fabsf(vec[2]); - if (size > totsize) totsize = size; - } - - for (a = 0; a < process->totelem; a++) { - process->thresh += densfunc(process->mainb[a], 2.0f * totsize, 2.0f * totsize, 2.0f * totsize); - } - - return totsize; -} - -/* if MetaElem lies in node, then node includes MetaElem pointer (ml_p) - * pointing at MetaElem (ml) - */ -static void fill_metaball_octal_node(octal_node *node, MetaElem *ml, short i) -{ - ml_pointer *ml_p; - - ml_p = MEM_mallocN(sizeof(ml_pointer), "ml_pointer"); - ml_p->ml = ml; - BLI_addtail(&(node->nodes[i]->elems), ml_p); - node->count++; - - if ((ml->flag & MB_NEGATIVE) == 0) { - node->nodes[i]->pos++; - } - else { - node->nodes[i]->neg++; - } -} -/* Node is subdivided as is illustrated on the following figure: - * - * +------+------+ - * / / /| - * +------+------+ | - * / / /| + - * +------+------+ |/| - * | | | + | - * | | |/| + - * +------+------+ |/ - * | | | + - * | | |/ - * +------+------+ - * - */ -static void subdivide_metaball_octal_node(octal_node *node, float size_x, float size_y, float size_z, short depth) -{ - MetaElem *ml; - ml_pointer *ml_p; - float x, y, z; - int a, i; - - /* create new nodes */ - for (a = 0; a < 8; a++) { - node->nodes[a] = MEM_mallocN(sizeof(octal_node), "octal_node"); - for (i = 0; i < 8; i++) - node->nodes[a]->nodes[i] = NULL; - node->nodes[a]->parent = node; - BLI_listbase_clear(&node->nodes[a]->elems); - node->nodes[a]->count = 0; - node->nodes[a]->neg = 0; - node->nodes[a]->pos = 0; - } + /* set only point 0 and 6 - AABB of Metaelem */ + copy_v3_v3(new_ml->bb->vec[0], tempmin); + copy_v3_v3(new_ml->bb->vec[6], tempmax); - size_x /= 2; - size_y /= 2; - size_z /= 2; - - /* center of node */ - node->x = x = node->x_min + size_x; - node->y = y = node->y_min + size_y; - node->z = z = node->z_min + size_z; - - /* setting up of border points of new nodes */ - node->nodes[0]->x_min = node->x_min; - node->nodes[0]->y_min = node->y_min; - node->nodes[0]->z_min = node->z_min; - node->nodes[0]->x = node->nodes[0]->x_min + size_x / 2; - node->nodes[0]->y = node->nodes[0]->y_min + size_y / 2; - node->nodes[0]->z = node->nodes[0]->z_min + size_z / 2; - - node->nodes[1]->x_min = x; - node->nodes[1]->y_min = node->y_min; - node->nodes[1]->z_min = node->z_min; - node->nodes[1]->x = node->nodes[1]->x_min + size_x / 2; - node->nodes[1]->y = node->nodes[1]->y_min + size_y / 2; - node->nodes[1]->z = node->nodes[1]->z_min + size_z / 2; - - node->nodes[2]->x_min = x; - node->nodes[2]->y_min = y; - node->nodes[2]->z_min = node->z_min; - node->nodes[2]->x = node->nodes[2]->x_min + size_x / 2; - node->nodes[2]->y = node->nodes[2]->y_min + size_y / 2; - node->nodes[2]->z = node->nodes[2]->z_min + size_z / 2; - - node->nodes[3]->x_min = node->x_min; - node->nodes[3]->y_min = y; - node->nodes[3]->z_min = node->z_min; - node->nodes[3]->x = node->nodes[3]->x_min + size_x / 2; - node->nodes[3]->y = node->nodes[3]->y_min + size_y / 2; - node->nodes[3]->z = node->nodes[3]->z_min + size_z / 2; - - node->nodes[4]->x_min = node->x_min; - node->nodes[4]->y_min = node->y_min; - node->nodes[4]->z_min = z; - node->nodes[4]->x = node->nodes[4]->x_min + size_x / 2; - node->nodes[4]->y = node->nodes[4]->y_min + size_y / 2; - node->nodes[4]->z = node->nodes[4]->z_min + size_z / 2; - - node->nodes[5]->x_min = x; - node->nodes[5]->y_min = node->y_min; - node->nodes[5]->z_min = z; - node->nodes[5]->x = node->nodes[5]->x_min + size_x / 2; - node->nodes[5]->y = node->nodes[5]->y_min + size_y / 2; - node->nodes[5]->z = node->nodes[5]->z_min + size_z / 2; - - node->nodes[6]->x_min = x; - node->nodes[6]->y_min = y; - node->nodes[6]->z_min = z; - node->nodes[6]->x = node->nodes[6]->x_min + size_x / 2; - node->nodes[6]->y = node->nodes[6]->y_min + size_y / 2; - node->nodes[6]->z = node->nodes[6]->z_min + size_z / 2; - - node->nodes[7]->x_min = node->x_min; - node->nodes[7]->y_min = y; - node->nodes[7]->z_min = z; - node->nodes[7]->x = node->nodes[7]->x_min + size_x / 2; - node->nodes[7]->y = node->nodes[7]->y_min + size_y / 2; - node->nodes[7]->z = node->nodes[7]->z_min + size_z / 2; - - ml_p = node->elems.first; - - /* setting up references of MetaElems for new nodes */ - while (ml_p) { - ml = ml_p->ml; - if (ml->bb->vec[0][2] < z) { - if (ml->bb->vec[0][1] < y) { - /* vec[0][0] lies in first octant */ - if (ml->bb->vec[0][0] < x) { - /* ml belongs to the (0)1st node */ - fill_metaball_octal_node(node, ml, 0); - - /* ml belongs to the (3)4th node */ - if (ml->bb->vec[6][1] >= y) { - fill_metaball_octal_node(node, ml, 3); - - /* ml belongs to the (7)8th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 7); - } - } - - /* ml belongs to the (1)2nd node */ - if (ml->bb->vec[6][0] >= x) { - fill_metaball_octal_node(node, ml, 1); - - /* ml belongs to the (5)6th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 5); - } - } + /* add new_ml to mainb[] */ + if (process->totelem == process->mem) { + MetaElem **newelem; + process->mem = process->mem * 2 + 10; + newelem = MEM_mallocN(sizeof(MetaElem *) * process->mem, "metaballs"); - /* ml belongs to the (2)3th node */ - if ((ml->bb->vec[6][0] >= x) && (ml->bb->vec[6][1] >= y)) { - fill_metaball_octal_node(node, ml, 2); - - /* ml belong to the (6)7th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 6); + memcpy(newelem, process->mainb, sizeof(MetaElem *) * process->totelem); + if (process->mainb) MEM_freeN(process->mainb); + process->mainb = newelem; } - - } - - /* ml belongs to the (4)5th node too */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 4); - } - - - - } - /* vec[0][0] is in the (1)second octant */ - else { - /* ml belong to the (1)2nd node */ - fill_metaball_octal_node(node, ml, 1); - - /* ml belongs to the (2)3th node */ - if (ml->bb->vec[6][1] >= y) { - fill_metaball_octal_node(node, ml, 2); - - /* ml belongs to the (6)7th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 6); - } - - } - - /* ml belongs to the (5)6th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 5); - } - } - } - else { - /* vec[0][0] is in the (3)4th octant */ - if (ml->bb->vec[0][0] < x) { - /* ml belongs to the (3)4nd node */ - fill_metaball_octal_node(node, ml, 3); - - /* ml belongs to the (7)8th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 7); - } - - - /* ml belongs to the (2)3th node */ - if (ml->bb->vec[6][0] >= x) { - fill_metaball_octal_node(node, ml, 2); - - /* ml belongs to the (6)7th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 6); - } - } - } - - } - - /* vec[0][0] is in the (2)3th octant */ - if ((ml->bb->vec[0][0] >= x) && (ml->bb->vec[0][1] >= y)) { - /* ml belongs to the (2)3th node */ - fill_metaball_octal_node(node, ml, 2); - - /* ml belongs to the (6)7th node */ - if (ml->bb->vec[6][2] >= z) { - fill_metaball_octal_node(node, ml, 6); - } - } - } - else { - if (ml->bb->vec[0][1] < y) { - /* vec[0][0] lies in (4)5th octant */ - if (ml->bb->vec[0][0] < x) { - /* ml belongs to the (4)5th node */ - fill_metaball_octal_node(node, ml, 4); - - if (ml->bb->vec[6][0] >= x) { - fill_metaball_octal_node(node, ml, 5); - } - - if (ml->bb->vec[6][1] >= y) { - fill_metaball_octal_node(node, ml, 7); - } - - if ((ml->bb->vec[6][0] >= x) && (ml->bb->vec[6][1] >= y)) { - fill_metaball_octal_node(node, ml, 6); - } - } - /* vec[0][0] lies in (5)6th octant */ - else { - fill_metaball_octal_node(node, ml, 5); - - if (ml->bb->vec[6][1] >= y) { - fill_metaball_octal_node(node, ml, 6); - } - } - } - else { - /* vec[0][0] lies in (7)8th octant */ - if (ml->bb->vec[0][0] < x) { - fill_metaball_octal_node(node, ml, 7); - - if (ml->bb->vec[6][0] >= x) { - fill_metaball_octal_node(node, ml, 6); + process->mainb[process->totelem++] = new_ml; } + ml = ml->next; } - } - - /* vec[0][0] lies in (6)7th octant */ - if ((ml->bb->vec[0][0] >= x) && (ml->bb->vec[0][1] >= y)) { - fill_metaball_octal_node(node, ml, 6); - } - } - ml_p = ml_p->next; - } - - /* free references of MetaElems for curent node (it is not needed anymore) */ - BLI_freelistN(&node->elems); - - depth--; - - if (depth > 0) { - for (a = 0; a < 8; a++) { - if (node->nodes[a]->count > 0) /* if node is not empty, then it is subdivided */ - subdivide_metaball_octal_node(node->nodes[a], size_x, size_y, size_z, depth); - } - } -} - -/* free all octal nodes recursively */ -static void free_metaball_octal_node(octal_node *node) -{ - int a; - for (a = 0; a < 8; a++) { - if (node->nodes[a] != NULL) free_metaball_octal_node(node->nodes[a]); - } - BLI_freelistN(&node->elems); - MEM_freeN(node); -} - -/* If scene include more than one MetaElem, then octree is used */ -static void init_metaball_octal_tree(PROCESS *process, int depth) -{ - struct octal_node *node; - ml_pointer *ml_p; - float size[3]; - int a; - - process->metaball_tree = MEM_mallocN(sizeof(octal_tree), "metaball_octal_tree"); - process->metaball_tree->first = node = MEM_mallocN(sizeof(octal_node), "metaball_octal_node"); - /* maximal depth of octree */ - process->metaball_tree->depth = depth; - - process->metaball_tree->neg = node->neg = 0; - process->metaball_tree->pos = node->pos = 0; - - BLI_listbase_clear(&node->elems); - node->count = 0; - - for (a = 0; a < 8; a++) - node->nodes[a] = NULL; - - node->x_min = node->y_min = node->z_min = FLT_MAX; - node->x_max = node->y_max = node->z_max = -FLT_MAX; - - /* size of octal tree scene */ - for (a = 0; a < process->totelem; a++) { - if (process->mainb[a]->bb->vec[0][0] < node->x_min) node->x_min = process->mainb[a]->bb->vec[0][0]; - if (process->mainb[a]->bb->vec[0][1] < node->y_min) node->y_min = process->mainb[a]->bb->vec[0][1]; - if (process->mainb[a]->bb->vec[0][2] < node->z_min) node->z_min = process->mainb[a]->bb->vec[0][2]; - - if (process->mainb[a]->bb->vec[6][0] > node->x_max) node->x_max = process->mainb[a]->bb->vec[6][0]; - if (process->mainb[a]->bb->vec[6][1] > node->y_max) node->y_max = process->mainb[a]->bb->vec[6][1]; - if (process->mainb[a]->bb->vec[6][2] > node->z_max) node->z_max = process->mainb[a]->bb->vec[6][2]; - - ml_p = MEM_mallocN(sizeof(ml_pointer), "ml_pointer"); - ml_p->ml = process->mainb[a]; - BLI_addtail(&node->elems, ml_p); - - if ((process->mainb[a]->flag & MB_NEGATIVE) == 0) { - /* number of positive MetaElem in scene */ - process->metaball_tree->pos++; - } - else { - /* number of negative MetaElem in scene */ - process->metaball_tree->neg++; } } - /* size of first node */ - size[0] = node->x_max - node->x_min; - size[1] = node->y_max - node->y_min; - size[2] = node->z_max - node->z_min; - - /* first node is subdivided recursively */ - subdivide_metaball_octal_node(node, size[0], size[1], size[2], process->metaball_tree->depth); -} - -static void mball_count(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *basis) -{ - Scene *sce_iter = scene; - Base *base; - Object *ob, *bob = basis; - MetaElem *ml = NULL; - int basisnr, obnr; - char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; - SceneBaseIter iter; - - BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.'); - process->totelem = 0; - - BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL); - while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) { - if (ob->type == OB_MBALL) { - if (ob == bob) { - MetaBall *mb = ob->data; - - /* if bob object is in edit mode, then dynamic list of all MetaElems - * is stored in editelems */ - if (mb->editelems) ml = mb->editelems->first; - /* if bob object is in object mode */ - else ml = mb->elems.first; - } - else { - BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); - - /* object ob has to be in same "group" ... it means, that it has to have - * same base of its name */ - if (STREQ(obname, basisname)) { - MetaBall *mb = ob->data; - - /* if object is in edit mode, then dynamic list of all MetaElems - * is stored in editelems */ - if (mb->editelems) ml = mb->editelems->first; - /* if bob object is in object mode */ - else ml = mb->elems.first; - } - } - - for ( ; ml; ml = ml->next) { - if (!(ml->flag & MB_HIDE)) { - process->totelem++; - } - } - } + /* compute AABB of all Metaelems */ + if (process->totelem > 0) { + copy_v3_v3(process->allbb.min, process->mainb[0]->bb->vec[0]); + copy_v3_v3(process->allbb.max, process->mainb[0]->bb->vec[6]); + for (i = 1; i < process->totelem; i++) + make_box_union(process->mainb[i]->bb, &process->allbb, &process->allbb); } } @@ -1875,102 +1263,66 @@ void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob, { MetaBall *mb; DispList *dl; - int a, nr_cubes; - float *co, *no, totsize, width; + unsigned int a; PROCESS process = {0}; mb = ob->data; - mball_count(eval_ctx, &process, scene, ob); - - if (process.totelem == 0) return; - if ((eval_ctx->mode != DAG_EVAL_RENDER) && (mb->flag == MB_UPDATE_NEVER)) return; - if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_FAST) return; - process.thresh = mb->thresh; - /* total number of MetaElems (totelem) is precomputed in find_basis_mball() function */ - process.mainb = MEM_mallocN(sizeof(void *) * process.totelem, "mainb"); - - /* initialize all mainb (MetaElems) */ - totsize = init_meta(eval_ctx, &process, scene, ob); - - /* if scene includes more than one MetaElem, then octal tree optimization is used */ - if ((process.totelem > 1) && (process.totelem <= 64)) init_metaball_octal_tree(&process, 1); - if ((process.totelem > 64) && (process.totelem <= 128)) init_metaball_octal_tree(&process, 2); - if ((process.totelem > 128) && (process.totelem <= 512)) init_metaball_octal_tree(&process, 3); - if ((process.totelem > 512) && (process.totelem <= 1024)) init_metaball_octal_tree(&process, 4); - if (process.totelem > 1024) init_metaball_octal_tree(&process, 5); - - /* don't polygonize metaballs with too high resolution (base mball to small) - * note: Eps was 0.0001f but this was giving problems for blood animation for durian, using 0.00001f */ - if (process.metaball_tree) { - if (ob->size[0] <= 0.00001f * (process.metaball_tree->first->x_max - process.metaball_tree->first->x_min) || - ob->size[1] <= 0.00001f * (process.metaball_tree->first->y_max - process.metaball_tree->first->y_min) || - ob->size[2] <= 0.00001f * (process.metaball_tree->first->z_max - process.metaball_tree->first->z_min)) - { - new_pgn_element(&process, -1); /* free values created by init_meta */ - - MEM_freeN(process.mainb); - - /* free tree */ - free_metaball_octal_node(process.metaball_tree->first); - MEM_freeN(process.metaball_tree); + if (process.thresh < 0.001f) process.converge_res = 16; + else if (process.thresh < 0.01f) process.converge_res = 8; + else if (process.thresh < 0.1f) process.converge_res = 4; + else process.converge_res = 2; - return; - } - } + if ((eval_ctx->mode != DAG_EVAL_RENDER) && (mb->flag == MB_UPDATE_NEVER)) return; + if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_FAST) return; - /* width is size per polygonize cube */ if (eval_ctx->mode == DAG_EVAL_RENDER) { - width = mb->rendersize; + process.size = mb->rendersize; } else { - width = mb->wiresize; + process.size = mb->wiresize; if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_HALFRES) { - width *= 2; + process.size *= 2.0f; } } - /* nr_cubes is just for safety, minimum is totsize */ - nr_cubes = (int)(0.5f + totsize / width); - - /* init process */ - process.function = metaball; - process.size = width; - process.bounds = nr_cubes; - process.cubes = NULL; - process.delta = width / (float)(RES * RES); - - polygonize(&process, mb); - - MEM_freeN(process.mainb); - - /* free octal tree */ - if (process.totelem > 1) { - free_metaball_octal_node(process.metaball_tree->first); - MEM_freeN(process.metaball_tree); - process.metaball_tree = NULL; - } - if (process.curindex) { - VERTEX *ptr = process.vertices.ptr; + process.delta = process.size * 0.001f; - dl = MEM_callocN(sizeof(DispList), "mbaldisp"); - BLI_addtail(dispbase, dl); - dl->type = DL_INDEX4; - dl->nr = process.vertices.count; - dl->parts = process.curindex; + process.pgn_elements = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "Metaball memarena"); - dl->index = process.indices; - process.indices = NULL; + /* initialize all mainb (MetaElems) */ + init_meta(eval_ctx, &process, scene, ob); - a = process.vertices.count; - dl->verts = co = MEM_mallocN(sizeof(float[3]) * a, "mballverts"); - dl->nors = no = MEM_mallocN(sizeof(float[3]) * a, "mballnors"); + if (process.totelem > 0) { + build_bvh_spatial(&process, &process.metaball_bvh, 0, process.totelem, &process.allbb); - for (a = 0; a < process.vertices.count; ptr++, a++, no += 3, co += 3) { - copy_v3_v3(co, ptr->co); - copy_v3_v3(no, ptr->no); + /* don't polygonize metaballs with too high resolution (base mball to small) + * note: Eps was 0.0001f but this was giving problems for blood animation for durian, using 0.00001f */ + if (ob->size[0] > 0.00001f * (process.allbb.max[0] - process.allbb.min[0]) || + ob->size[1] > 0.00001f * (process.allbb.max[1] - process.allbb.min[1]) || + ob->size[2] > 0.00001f * (process.allbb.max[2] - process.allbb.min[2])) + { + polygonize(&process); + + /* add resulting surface to displist */ + if (process.curindex) { + dl = MEM_callocN(sizeof(DispList), "mballdisp"); + BLI_addtail(dispbase, dl); + dl->type = DL_INDEX4; + dl->nr = (int)process.curvertex; + dl->parts = (int)process.curindex; + + dl->index = (int *)process.indices; + + for (a = 0; a < process.curvertex; a++) { + normalize_v3(process.no[a]); + } + + dl->verts = (float *)process.co; + dl->nors = (float *)process.no; + } } } diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index f1f73563dec..4f019c0a913 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -60,7 +60,7 @@ #include "BKE_global.h" #include "BKE_library.h" #include "BKE_main.h" -#include "BKE_mball.h" +#include "BKE_mball_tessellate.h" #include "BKE_node.h" #include "BKE_report.h" -- cgit v1.2.3 From 4b685e1b90c555a222d524b16a482913865683aa Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 7 Apr 2015 13:50:11 +0500 Subject: Fix T44268: Particles: too many virtual parents + non-100 display% = crash Issue was caused by mismatched logic in counting child/parent particles in job initialization and actual job execution. Confusion here came from mixed usage of psys->renderdata and G.is_rendering. We need to get rid of G.is_rendering and use eval_ctx if it's really needed, but we also might just use psys->renderdata check since it's expected psys to have this structure anyway. --- source/blender/blenkernel/intern/particle.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 8d3f92182d4..fbd55928534 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -286,7 +286,7 @@ bool psys_check_enabled(Object *ob, ParticleSystem *psys) return 0; psmd = psys_get_modifier(ob, psys); - if (psys->renderdata || G.is_rendering) { + if (psys->renderdata) { if (!(psmd->modifier.mode & eModifierMode_Render)) return 0; } @@ -1955,7 +1955,7 @@ void psys_find_parents(ParticleSimulationData *sim) int from = PART_FROM_FACE; totparent = (int)(totchild * part->parents * 0.3f); - if ((sim->psys->renderdata || G.is_rendering) && part->child_nbr && part->ren_child_nbr) + if (sim->psys->renderdata && part->child_nbr && part->ren_child_nbr) totparent *= (float)part->child_nbr / (float)part->ren_child_nbr; /* hard limit, workaround for it being ignored above */ @@ -2009,7 +2009,7 @@ static bool psys_thread_context_init_path(ParticleThreadContext *ctx, ParticleSi if (totchild && part->childtype == PART_CHILD_FACES) { totparent = (int)(totchild * part->parents * 0.3f); - if ((psys->renderdata || G.is_rendering) && part->child_nbr && part->ren_child_nbr) + if (psys->renderdata && part->child_nbr && part->ren_child_nbr) totparent *= (float)part->child_nbr / (float)part->ren_child_nbr; /* part->parents could still be 0 so we can't test with totparent */ @@ -2288,6 +2288,7 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp if (i >= ctx->totparent) { pa = &psys->particles[cpa->parent]; /* this is now threadsafe, virtual parents are calculated before rest of children */ + BLI_assert(cpa->parent < psys->totchildcache); par = cache[cpa->parent]; } } @@ -2335,6 +2336,7 @@ static void exec_child_path_cache(TaskPool *UNUSED(pool), void *taskdata, int UN cpa = psys->child + task->begin; for (i = task->begin; i < task->end; ++i, ++cpa) { + BLI_assert(i < psys->totchildcache); psys_thread_create_path(task, cpa, cache[i], i); } } -- cgit v1.2.3 From 20a780e3e88948a0f0a4e552359c8ff915a369a8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 7 Apr 2015 19:54:46 +1000 Subject: Fix T44258: Can't select similar regions --- source/blender/bmesh/tools/bmesh_region_match.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c index 0c0bb892f7b..e9686ec5a54 100644 --- a/source/blender/bmesh/tools/bmesh_region_match.c +++ b/source/blender/bmesh/tools/bmesh_region_match.c @@ -615,7 +615,7 @@ static unsigned int bm_uuidwalk_init_from_edge( /* turning an array into LinkNode's seems odd, * but this is just for initialization, * elsewhere using LinkNode's makes more sense */ - for (i = 0; i < f_arr_len; i++) { + for (i = 0; i < f_arr_len; ) { LinkNode *faces_pass = NULL; const int f_len = f_arr[i]->len; -- cgit v1.2.3 From 34818a44b282f44e22205507dabee1e37c6312ab Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 7 Apr 2015 12:15:02 +0200 Subject: Make image strips also follow the project directory storage options. --- source/blender/blenkernel/intern/sequencer.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 8c803f86979..4cea8aa0b85 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1581,13 +1581,19 @@ static bool seq_proxy_get_fname(Editing *ed, Sequence *seq, int cfra, int render sanim = BLI_findlink(&seq->anims, view_id); - if (sanim && sanim->anim && ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) { + if (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) { char fname[FILE_MAXFILE]; if (ed->proxy_dir[0] == 0) BLI_strncpy(dir, "//BL_proxy", sizeof(dir)); else BLI_strncpy(dir, ed->proxy_dir, sizeof(dir)); - IMB_anim_get_fname(sanim->anim, fname, FILE_MAXFILE); + + if (sanim && sanim->anim) { + IMB_anim_get_fname(sanim->anim, fname, FILE_MAXFILE); + } + else if (seq->type == SEQ_TYPE_IMAGE) { + fname[0] = 0; + } BLI_path_append(dir, sizeof(dir), fname); BLI_path_abs(name, G.main->name); } -- cgit v1.2.3 From d60ff6c112b1c5d3819676109b0080a316850eb0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 7 Apr 2015 20:26:42 +1000 Subject: Fix for own last commit resolved bug but wasn't correct --- source/blender/bmesh/tools/bmesh_region_match.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c index e9686ec5a54..4322a288471 100644 --- a/source/blender/bmesh/tools/bmesh_region_match.c +++ b/source/blender/bmesh/tools/bmesh_region_match.c @@ -617,13 +617,14 @@ static unsigned int bm_uuidwalk_init_from_edge( * elsewhere using LinkNode's makes more sense */ for (i = 0; i < f_arr_len; ) { LinkNode *faces_pass = NULL; + const unsigned int i_init = i; const int f_len = f_arr[i]->len; do { BLI_linklist_prepend_pool(&faces_pass, f_arr[i++], uuidwalk->link_pool); } while (i < f_arr_len && (f_len == f_arr[i]->len)); - bm_uuidwalk_pass_add(uuidwalk, faces_pass, i); + bm_uuidwalk_pass_add(uuidwalk, faces_pass, i - i_init); BLI_linklist_free_pool(faces_pass, NULL, uuidwalk->link_pool); fstep_num += 1; } -- cgit v1.2.3 From cc78664d50c6ae82d139552283ede467b0cf28cc Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 7 Apr 2015 14:08:30 +0200 Subject: Revert Sticky Keys (and everything related to that) Our current keymap doesn't give us enough room to make such changes in the event system. To fix small issues caused by this, we would need to do drastic changes in Blender's keymaps and internal handling. It was worth a try, but it didn't work. I can write down a more descriptive statement in a few days, but for now I need a break of this stuff. --- release/scripts/presets/keyconfig/3dsmax.py | 56 ++++----- release/scripts/presets/keyconfig/maya.py | 60 ++++----- release/scripts/startup/bl_ui/space_userpref.py | 13 +- source/blender/editors/armature/armature_ops.c | 2 +- source/blender/editors/curve/curve_ops.c | 2 +- source/blender/editors/gpencil/gpencil_paint.c | 2 +- .../editors/interface/interface_eyedropper.c | 4 - .../blender/editors/interface/interface_handlers.c | 67 +++++------ source/blender/editors/interface/interface_panel.c | 2 +- .../blender/editors/interface/interface_regions.c | 4 +- source/blender/editors/interface/resources.c | 7 +- source/blender/editors/mesh/editmesh_extrude.c | 4 - source/blender/editors/mesh/mesh_ops.c | 2 +- source/blender/editors/object/object_ops.c | 2 +- source/blender/editors/space_console/console_ops.c | 7 +- source/blender/editors/space_file/space_file.c | 16 +-- source/blender/editors/space_graph/graph_ops.c | 2 +- .../editors/space_node/node_relationships.c | 13 +- .../blender/editors/space_outliner/outliner_ops.c | 8 +- source/blender/editors/space_text/text_ops.c | 12 +- source/blender/editors/space_view3d/view3d_ops.c | 4 +- source/blender/editors/transform/transform.c | 8 +- source/blender/makesdna/DNA_userdef_types.h | 7 +- source/blender/makesdna/DNA_windowmanager_types.h | 3 +- source/blender/makesrna/intern/rna_userdef.c | 8 +- source/blender/makesrna/intern/rna_wm.c | 2 - source/blender/windowmanager/WM_types.h | 17 ++- .../blender/windowmanager/intern/wm_event_system.c | 134 ++++++++++++--------- source/blender/windowmanager/intern/wm_keymap.c | 4 - source/blender/windowmanager/intern/wm_operators.c | 2 +- source/blender/windowmanager/intern/wm_window.c | 76 +----------- 31 files changed, 215 insertions(+), 335 deletions(-) diff --git a/release/scripts/presets/keyconfig/3dsmax.py b/release/scripts/presets/keyconfig/3dsmax.py index 319728df4cc..7694e338d68 100644 --- a/release/scripts/presets/keyconfig/3dsmax.py +++ b/release/scripts/presets/keyconfig/3dsmax.py @@ -139,16 +139,16 @@ kmi = km.keymap_items.new('marker.camera_bind', 'B', 'PRESS', ctrl=True) km = kc.keymaps.new('Outliner', space_type='OUTLINER', region_type='WINDOW', modal=False) kmi = km.keymap_items.new('outliner.item_rename', 'LEFTMOUSE', 'DOUBLE_CLICK') -kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'PRESS') +kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'CLICK') kmi.properties.extend = False kmi.properties.recursive = False -kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'PRESS', shift=True) +kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'CLICK', shift=True) kmi.properties.extend = True kmi.properties.recursive = False -kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'PRESS', ctrl=True) +kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'CLICK', ctrl=True) kmi.properties.extend = False kmi.properties.recursive = True -kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'PRESS', shift=True, ctrl=True) +kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'CLICK', shift=True, ctrl=True) kmi.properties.extend = True kmi.properties.recursive = True kmi = km.keymap_items.new('outliner.select_border', 'B', 'PRESS') @@ -236,7 +236,7 @@ kmi = km.keymap_items.new('pose.paste', 'V', 'PRESS', ctrl=True) kmi.properties.flipped = False kmi = km.keymap_items.new('pose.paste', 'V', 'PRESS', shift=True, ctrl=True) kmi.properties.flipped = True -kmi = km.keymap_items.new('pose.select_all', 'LEFTMOUSE', 'PRESS') +kmi = km.keymap_items.new('pose.select_all', 'LEFTMOUSE', 'CLICK') kmi.properties.action = 'TOGGLE' kmi = km.keymap_items.new('pose.select_all', 'I', 'PRESS', ctrl=True) kmi.properties.action = 'INVERT' @@ -586,56 +586,56 @@ kmi = km.keymap_items.new('wm.context_toggle_enum', 'Z', 'PRESS', alt=True) kmi.properties.data_path = 'space_data.viewport_shade' kmi.properties.value_1 = 'SOLID' kmi.properties.value_2 = 'TEXTURED' -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS') +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK') kmi.properties.extend = False kmi.properties.deselect = False kmi.properties.toggle = False kmi.properties.center = False kmi.properties.enumerate = False kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', ctrl=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', ctrl=True) kmi.properties.extend = False kmi.properties.deselect = False kmi.properties.toggle = True kmi.properties.center = False kmi.properties.enumerate = False kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True) kmi.properties.extend = False kmi.properties.deselect = False kmi.properties.toggle = False kmi.properties.center = True kmi.properties.enumerate = False kmi.properties.object = True -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', alt=True) kmi.properties.extend = False kmi.properties.deselect = False kmi.properties.toggle = False kmi.properties.center = False kmi.properties.enumerate = True kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True, ctrl=True) kmi.properties.extend = True kmi.properties.deselect = False kmi.properties.toggle = True kmi.properties.center = True kmi.properties.enumerate = False kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', ctrl=True, alt=True) kmi.properties.extend = False kmi.properties.deselect = False kmi.properties.toggle = False kmi.properties.center = True kmi.properties.enumerate = True kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True, alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True, alt=True) kmi.properties.extend = False kmi.properties.deselect = False kmi.properties.toggle = True kmi.properties.center = False kmi.properties.enumerate = True kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True, ctrl=True, alt=True) kmi.properties.extend = False kmi.properties.deselect = False kmi.properties.toggle = True @@ -971,7 +971,7 @@ kmi = km.keymap_items.new('graph.delete', 'X', 'PRESS') kmi = km.keymap_items.new('graph.delete', 'DEL', 'PRESS') kmi = km.keymap_items.new('graph.duplicate_move', 'D', 'PRESS', shift=True) kmi = km.keymap_items.new('graph.keyframe_insert', 'I', 'PRESS') -kmi = km.keymap_items.new('graph.click_insert', 'ACTIONMOUSE', 'PRESS', ctrl=True) +kmi = km.keymap_items.new('graph.click_insert', 'ACTIONMOUSE', 'CLICK', ctrl=True) kmi = km.keymap_items.new('graph.copy', 'C', 'PRESS', ctrl=True) kmi = km.keymap_items.new('graph.paste', 'V', 'PRESS', ctrl=True) kmi = km.keymap_items.new('graph.previewrange_set', 'P', 'PRESS', ctrl=True, alt=True) @@ -1130,18 +1130,18 @@ km = kc.keymaps.new('File Browser Main', space_type='FILE_BROWSER', region_type= kmi = km.keymap_items.new('file.execute', 'LEFTMOUSE', 'DOUBLE_CLICK') kmi.properties.need_active = True -kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'PRESS') -kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'PRESS', shift=True) +kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'CLICK') +kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'CLICK', shift=True) kmi.properties.extend = True -kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'PRESS', alt=True) +kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'CLICK', alt=True) kmi.properties.extend = True kmi.properties.fill = True -kmi = km.keymap_items.new('file.select', 'RIGHTMOUSE', 'PRESS') +kmi = km.keymap_items.new('file.select', 'RIGHTMOUSE', 'CLICK') kmi.properties.open = False -kmi = km.keymap_items.new('file.select', 'RIGHTMOUSE', 'PRESS', shift=True) +kmi = km.keymap_items.new('file.select', 'RIGHTMOUSE', 'CLICK', shift=True) kmi.properties.extend = True kmi.properties.open = False -kmi = km.keymap_items.new('file.select', 'RIGHTMOUSE', 'PRESS', alt=True) +kmi = km.keymap_items.new('file.select', 'RIGHTMOUSE', 'CLICK', alt=True) kmi.properties.extend = True kmi.properties.fill = True kmi.properties.open = False @@ -2156,9 +2156,9 @@ kmi = km.keymap_items.new('mesh.separate', 'P', 'PRESS') kmi = km.keymap_items.new('mesh.split', 'Y', 'PRESS') kmi = km.keymap_items.new('mesh.vert_connect', 'J', 'PRESS') kmi = km.keymap_items.new('transform.vert_slide', 'V', 'PRESS', shift=True) -kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'PRESS', ctrl=True) +kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'CLICK', ctrl=True) kmi.properties.rotate_source = True -kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'PRESS', shift=True, ctrl=True) +kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'CLICK', shift=True, ctrl=True) kmi.properties.rotate_source = False kmi = km.keymap_items.new('wm.call_menu', 'X', 'PRESS') kmi.properties.name = 'VIEW3D_MT_edit_mesh_delete' @@ -2223,8 +2223,8 @@ km = kc.keymaps.new('Curve', space_type='EMPTY', region_type='WINDOW', modal=Fal kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True) kmi.properties.name = 'INFO_MT_edit_curve_add' kmi = km.keymap_items.new('curve.handle_type_set', 'V', 'PRESS') -kmi = km.keymap_items.new('curve.vertex_add', 'LEFTMOUSE', 'PRESS', ctrl=True) -kmi = km.keymap_items.new('curve.select_all', 'LEFTMOUSE', 'PRESS') +kmi = km.keymap_items.new('curve.vertex_add', 'LEFTMOUSE', 'CLICK', ctrl=True) +kmi = km.keymap_items.new('curve.select_all', 'LEFTMOUSE', 'CLICK') kmi.properties.action = 'TOGGLE' kmi = km.keymap_items.new('curve.select_all', 'I', 'PRESS', ctrl=True) kmi.properties.action = 'INVERT' @@ -2293,7 +2293,7 @@ kmi = km.keymap_items.new('armature.switch_direction', 'F', 'PRESS', alt=True) kmi = km.keymap_items.new('armature.bone_primitive_add', 'A', 'PRESS', shift=True) kmi = km.keymap_items.new('armature.parent_set', 'P', 'PRESS', ctrl=True) kmi = km.keymap_items.new('armature.parent_clear', 'P', 'PRESS', alt=True) -kmi = km.keymap_items.new('armature.select_all', 'LEFTMOUSE', 'PRESS') +kmi = km.keymap_items.new('armature.select_all', 'LEFTMOUSE', 'CLICK') kmi.properties.action = 'TOGGLE' kmi = km.keymap_items.new('armature.select_all', 'I', 'PRESS', ctrl=True) kmi.properties.action = 'INVERT' @@ -2316,7 +2316,7 @@ kmi = km.keymap_items.new('armature.delete', 'DEL', 'PRESS') kmi = km.keymap_items.new('armature.duplicate_move', 'D', 'PRESS', shift=True) kmi = km.keymap_items.new('armature.extrude_move', 'E', 'PRESS') kmi = km.keymap_items.new('armature.extrude_forked', 'E', 'PRESS', shift=True) -kmi = km.keymap_items.new('armature.click_extrude', 'LEFTMOUSE', 'PRESS', ctrl=True) +kmi = km.keymap_items.new('armature.click_extrude', 'LEFTMOUSE', 'CLICK', ctrl=True) kmi = km.keymap_items.new('armature.fill', 'F', 'PRESS', ctrl=True) kmi = km.keymap_items.new('armature.merge', 'M', 'PRESS', alt=True) kmi = km.keymap_items.new('armature.separate', 'P', 'PRESS', ctrl=True, alt=True) @@ -2348,7 +2348,7 @@ kmi.properties.unselected = True kmi = km.keymap_items.new('mball.delete_metaelems', 'X', 'PRESS') kmi = km.keymap_items.new('mball.delete_metaelems', 'DEL', 'PRESS') kmi = km.keymap_items.new('mball.duplicate_metaelems', 'D', 'PRESS', shift=True) -kmi = km.keymap_items.new('mball.select_all', 'LEFTMOUSE', 'PRESS') +kmi = km.keymap_items.new('mball.select_all', 'LEFTMOUSE', 'CLICK') kmi.properties.action = 'TOGGLE' kmi = km.keymap_items.new('mball.select_all', 'I', 'PRESS', ctrl=True) kmi.properties.action = 'INVERT' @@ -2366,7 +2366,7 @@ kmi.properties.value_2 = 'CONNECTED' # Map Lattice km = kc.keymaps.new('Lattice', space_type='EMPTY', region_type='WINDOW', modal=False) -kmi = km.keymap_items.new('lattice.select_all', 'LEFTMOUSE', 'PRESS') +kmi = km.keymap_items.new('lattice.select_all', 'LEFTMOUSE', 'CLICK') kmi.properties.action = 'TOGGLE' kmi = km.keymap_items.new('lattice.select_all', 'I', 'PRESS', ctrl=True) kmi.properties.action = 'INVERT' diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py index f9bb020d856..28799d1cf67 100644 --- a/release/scripts/presets/keyconfig/maya.py +++ b/release/scripts/presets/keyconfig/maya.py @@ -227,9 +227,9 @@ kmi = km.keymap_items.new('time.view_all', 'A', 'PRESS') km = kc.keymaps.new('Outliner', space_type='OUTLINER', region_type='WINDOW', modal=False) kmi = km.keymap_items.new('outliner.item_rename', 'LEFTMOUSE', 'DOUBLE_CLICK') -kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'PRESS') +kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'CLICK') kmi.properties.extend = False -kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'PRESS', shift=True) +kmi = km.keymap_items.new('outliner.item_activate', 'LEFTMOUSE', 'CLICK', shift=True) kmi.properties.extend = True kmi = km.keymap_items.new('outliner.select_border', 'EVT_TWEAK_S', 'ANY', any=True) kmi = km.keymap_items.new('outliner.item_openclose', 'RET', 'PRESS') @@ -656,7 +656,7 @@ kmi = km.keymap_items.new('mesh.edge_face_add', 'F', 'PRESS', alt=True) kmi = km.keymap_items.new('mesh.duplicate_move', 'D', 'PRESS', ctrl=True) kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True) kmi.properties.name = 'INFO_MT_mesh_add' -kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'MIDDLEMOUSE', 'PRESS', ctrl=True) +kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'MIDDLEMOUSE', 'CLICK', ctrl=True) kmi = km.keymap_items.new('wm.call_menu', 'BACK_SPACE', 'PRESS') kmi.properties.name = 'VIEW3D_MT_edit_mesh_delete' kmi = km.keymap_items.new('wm.call_menu', 'DEL', 'PRESS') @@ -727,7 +727,7 @@ km = kc.keymaps.new('Curve', space_type='EMPTY', region_type='WINDOW', modal=Fal kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True) kmi.properties.name = 'INFO_MT_edit_curve_add' kmi = km.keymap_items.new('curve.handle_type_set', 'RIGHTMOUSE', 'PRESS') -kmi = km.keymap_items.new('curve.vertex_add', 'MIDDLEMOUSE', 'PRESS', ctrl=True) +kmi = km.keymap_items.new('curve.vertex_add', 'MIDDLEMOUSE', 'CLICK', ctrl=True) kmi = km.keymap_items.new('curve.select_all', 'A', 'PRESS', ctrl=True) kmi.properties.action = 'TOGGLE' kmi = km.keymap_items.new('curve.select_all', 'I', 'PRESS', ctrl=True) @@ -817,7 +817,7 @@ kmi = km.keymap_items.new('armature.delete', 'DEL', 'PRESS') kmi = km.keymap_items.new('armature.duplicate_move', 'D', 'PRESS', ctrl=True) kmi = km.keymap_items.new('armature.extrude_move', 'X', 'PRESS', alt=True) kmi = km.keymap_items.new('armature.extrude_forked', 'X', 'PRESS', shift=True, alt=True) -kmi = km.keymap_items.new('armature.click_extrude', 'MIDDLEMOUSE', 'PRESS', ctrl=True) +kmi = km.keymap_items.new('armature.click_extrude', 'MIDDLEMOUSE', 'CLICK', ctrl=True) kmi = km.keymap_items.new('armature.fill', 'F', 'PRESS', alt=True) kmi = km.keymap_items.new('armature.merge', 'M', 'PRESS', alt=True) kmi = km.keymap_items.new('armature.separate', 'P', 'PRESS', ctrl=True, alt=True) @@ -1003,56 +1003,56 @@ kmi = km.keymap_items.new('wm.context_toggle_enum', 'FIVE', 'PRESS') kmi.properties.data_path = 'space_data.viewport_shade' kmi.properties.value_1 = 'TEXTURED' kmi.properties.value_2 = 'SOLID' -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS') +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK') kmi.properties.extend = False kmi.properties.toggle = False kmi.properties.deselect = False kmi.properties.center = False kmi.properties.object = False kmi.properties.enumerate = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True) kmi.properties.extend = False kmi.properties.toggle = True kmi.properties.deselect = False kmi.properties.center = False kmi.properties.object = False kmi.properties.enumerate = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', ctrl=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', ctrl=True) kmi.properties.center = False kmi.properties.extend = False kmi.properties.toggle = False kmi.properties.deselect = True kmi.properties.object = False kmi.properties.enumerate = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', alt=True) kmi.properties.enumerate = True kmi.properties.extend = False kmi.properties.toggle = False kmi.properties.deselect = False kmi.properties.center = False kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True, ctrl=True) kmi.properties.extend = True kmi.properties.center = True kmi.properties.toggle = False kmi.properties.deselect = False kmi.properties.object = False kmi.properties.enumerate = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', ctrl=True, alt=True) kmi.properties.center = True kmi.properties.enumerate = True kmi.properties.extend = False kmi.properties.toggle = False kmi.properties.deselect = False kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True, alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True, alt=True) kmi.properties.extend = True kmi.properties.enumerate = True kmi.properties.toggle = False kmi.properties.deselect = False kmi.properties.center = False kmi.properties.object = False -kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True) +kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK', shift=True, ctrl=True, alt=True) kmi.properties.extend = True kmi.properties.center = True kmi.properties.enumerate = True @@ -1106,7 +1106,7 @@ km = kc.keymaps.new('Animation Channels', space_type='EMPTY', region_type='WINDO kmi = km.keymap_items.new('anim.channels_click', 'LEFTMOUSE', 'PRESS') kmi.properties.extend = False -kmi = km.keymap_items.new('anim.channels_click', 'LEFTMOUSE', 'PRESS', shift=True) +kmi = km.keymap_items.new('anim.channels_click', 'LEFTMOUSE', 'CLICK', shift=True) kmi.properties.extend = True kmi = km.keymap_items.new('anim.channels_click', 'LEFTMOUSE', 'PRESS', shift=True, ctrl=True) kmi.properties.children_only = True @@ -1144,9 +1144,9 @@ km = kc.keymaps.new('UV Editor', space_type='EMPTY', region_type='WINDOW', modal kmi = km.keymap_items.new('wm.context_toggle', 'Q', 'PRESS') kmi.properties.data_path = 'tool_settings.use_uv_sculpt' kmi = km.keymap_items.new('uv.mark_seam', 'E', 'PRESS', ctrl=True) -kmi = km.keymap_items.new('uv.select', 'SELECTMOUSE', 'PRESS') +kmi = km.keymap_items.new('uv.select', 'SELECTMOUSE', 'CLICK') kmi.properties.extend = False -kmi = km.keymap_items.new('uv.select', 'SELECTMOUSE', 'PRESS', shift=True) +kmi = km.keymap_items.new('uv.select', 'SELECTMOUSE', 'CLICK', shift=True) kmi.properties.extend = True kmi = km.keymap_items.new('uv.select_loop', 'LEFTMOUSE', 'PRESS', ctrl=True, alt=True) kmi.properties.extend = False @@ -1314,7 +1314,7 @@ kmi = km.keymap_items.new('wm.context_toggle', 'H', 'PRESS', ctrl=True) kmi.properties.data_path = 'space_data.show_handles' kmi = km.keymap_items.new('graph.cursor_set', 'LEFTMOUSE', 'PRESS', key_modifier='K') kmi.properties.value = 1.1754943508222875e-38 -kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'PRESS') +kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'CLICK') kmi.properties.extend = False kmi.properties.column = False kmi.properties.curves = False @@ -1322,11 +1322,11 @@ kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'PRESS', alt=True) kmi.properties.extend = False kmi.properties.column = True kmi.properties.curves = False -kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'PRESS', shift=True) +kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'CLICK', shift=True) kmi.properties.extend = True kmi.properties.column = False kmi.properties.curves = False -kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'PRESS', shift=True, alt=True) +kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'CLICK', shift=True, alt=True) kmi.properties.extend = True kmi.properties.column = True kmi.properties.curves = False @@ -1334,7 +1334,7 @@ kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'PRESS', ctrl=True kmi.properties.extend = False kmi.properties.column = False kmi.properties.curves = True -kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True) +kmi = km.keymap_items.new('graph.clickselect', 'SELECTMOUSE', 'CLICK', shift=True, ctrl=True, alt=True) kmi.properties.extend = True kmi.properties.column = False kmi.properties.curves = True @@ -1366,7 +1366,7 @@ kmi = km.keymap_items.new('graph.delete', 'BACK_SPACE', 'PRESS') kmi = km.keymap_items.new('graph.delete', 'DEL', 'PRESS') kmi = km.keymap_items.new('graph.duplicate_move', 'D', 'PRESS', ctrl=True) kmi = km.keymap_items.new('graph.keyframe_insert', 'I', 'PRESS') -kmi = km.keymap_items.new('graph.click_insert', 'LEFTMOUSE', 'PRESS', ctrl=True) +kmi = km.keymap_items.new('graph.click_insert', 'LEFTMOUSE', 'CLICK', ctrl=True) kmi = km.keymap_items.new('graph.copy', 'C', 'PRESS', ctrl=True) kmi = km.keymap_items.new('graph.paste', 'V', 'PRESS', ctrl=True) kmi = km.keymap_items.new('graph.previewrange_set', 'P', 'PRESS', ctrl=True, alt=True) @@ -1511,11 +1511,11 @@ km = kc.keymaps.new('File Browser Main', space_type='FILE_BROWSER', region_type= kmi = km.keymap_items.new('file.execute', 'LEFTMOUSE', 'DOUBLE_CLICK') kmi.properties.need_active = True -kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'PRESS') +kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'CLICK') kmi.properties.extend = False -kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'PRESS', shift=True) +kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'CLICK', shift=True) kmi.properties.extend = True -kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'PRESS', alt=True) +kmi = km.keymap_items.new('file.select', 'LEFTMOUSE', 'CLICK', alt=True) kmi.properties.extend = True kmi.properties.fill = True kmi = km.keymap_items.new('file.select_all_toggle', 'A', 'PRESS', ctrl=True) @@ -1541,13 +1541,13 @@ kmi.properties.increment = -100 # Map Dopesheet km = kc.keymaps.new('Dopesheet', space_type='DOPESHEET_EDITOR', region_type='WINDOW', modal=False) -kmi = km.keymap_items.new('action.clickselect', 'LEFTMOUSE', 'PRESS') +kmi = km.keymap_items.new('action.clickselect', 'LEFTMOUSE', 'CLICK') kmi.properties.extend = False kmi.properties.column = False kmi = km.keymap_items.new('action.clickselect', 'LEFTMOUSE', 'PRESS', alt=True) kmi.properties.extend = False kmi.properties.column = True -kmi = km.keymap_items.new('action.clickselect', 'LEFTMOUSE', 'PRESS', shift=True) +kmi = km.keymap_items.new('action.clickselect', 'LEFTMOUSE', 'CLICK', shift=True) kmi.properties.extend = True kmi.properties.column = False kmi = km.keymap_items.new('action.clickselect', 'LEFTMOUSE', 'PRESS', shift=True, alt=True) @@ -1618,7 +1618,7 @@ kmi = km.keymap_items.new('nla.tracks_delete', 'DEL', 'PRESS') # Map NLA Editor km = kc.keymaps.new('NLA Editor', space_type='NLA_EDITOR', region_type='WINDOW', modal=False) -kmi = km.keymap_items.new('nla.click_select', 'SELECTMOUSE', 'PRESS') +kmi = km.keymap_items.new('nla.click_select', 'SELECTMOUSE', 'CLICK') kmi.properties.extend = False kmi = km.keymap_items.new('nla.click_select', 'SELECTMOUSE', 'PRESS', shift=True) kmi.properties.extend = True @@ -1740,12 +1740,12 @@ kmi = km.keymap_items.new('sequencer.cut_multicam', 'NINE', 'PRESS') kmi.properties.camera = 9 kmi = km.keymap_items.new('sequencer.cut_multicam', 'ZERO', 'PRESS') kmi.properties.camera = 10 -kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'PRESS') +kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'CLICK') kmi.properties.extend = False kmi.properties.linked_handle = False kmi.properties.left_right = 'NONE' kmi.properties.linked_time = False -kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'PRESS', shift=True) +kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'CLICK', shift=True) kmi.properties.extend = True kmi.properties.linked_handle = False kmi.properties.left_right = 'NONE' @@ -1755,7 +1755,7 @@ kmi.properties.extend = False kmi.properties.linked_handle = True kmi.properties.left_right = 'NONE' kmi.properties.linked_time = False -kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'PRESS', shift=True, alt=True) +kmi = km.keymap_items.new('sequencer.select', 'SELECTMOUSE', 'CLICK', shift=True, alt=True) kmi.properties.extend = True kmi.properties.linked_handle = True kmi.properties.left_right = 'NONE' diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 04020d0a1bb..3b17e40c294 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -1055,15 +1055,6 @@ class USERPREF_PT_input(Panel): subrow.menu("USERPREF_MT_interaction_presets", text=bpy.types.USERPREF_MT_interaction_presets.bl_label) subrow.operator("wm.interaction_preset_add", text="", icon='ZOOMIN') subrow.operator("wm.interaction_preset_add", text="", icon='ZOOMOUT').remove_active = True - - sub.separator() - - sub = col.column() - sub.label(text="Double Click:") - sub.prop(inputs, "double_click_time", text="Speed") - sub.label(text="Sticky Keys:") - sub.prop(inputs, "click_timeout") - sub.separator() sub.label(text="Mouse:") @@ -1077,6 +1068,10 @@ class USERPREF_PT_input(Panel): sub.label(text="Select With:") sub.row().prop(inputs, "select_mouse", expand=True) + sub = col.column() + sub.label(text="Double Click:") + sub.prop(inputs, "mouse_double_click_time", text="Speed") + sub.separator() sub.prop(inputs, "use_emulate_numpad") diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index 3f00068c3d2..61c9dfb24fa 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -271,7 +271,7 @@ void ED_keymap_armature(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "ARMATURE_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_extrude_move", EKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_extrude_forked", EKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "ARMATURE_OT_click_extrude", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "ARMATURE_OT_click_extrude", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_fill", FKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_merge", MKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_split", YKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c index 561c349edec..4bcb16d31ef 100644 --- a/source/blender/editors/curve/curve_ops.c +++ b/source/blender/editors/curve/curve_ops.c @@ -230,7 +230,7 @@ void ED_keymap_curve(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "CURVE_OT_handle_type_set", VKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "CURVE_OT_vertex_add", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "CURVE_OT_vertex_add", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); kmi = WM_keymap_add_item(keymap, "CURVE_OT_select_all", AKEY, KM_PRESS, 0, 0); RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE); diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 3a564cc6ddb..2795c820fa7 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1931,7 +1931,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* stroke could be smoothed, send notifier to refresh screen */ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); } - else if (event->val == KM_RELEASE) { + else { /* printf("\t\tGP - end of stroke + op\n"); */ p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index 96f9b87611f..f5847a9d701 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -277,10 +277,6 @@ static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event) eyedropper_cancel(C, op); return OPERATOR_CANCELLED; case LEFTMOUSE: - /* two release events are sent on KM_CLICK, so ignore second one */ - if (event->click_type == KM_CLICK) { - break; - } if (event->val == KM_RELEASE) { if (eye->accum_tot == 0) { eyedropper_color_sample(C, eye, event->x, event->y); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 163502b4230..bc35fde633c 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1180,7 +1180,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void switch (event->type) { case LEFTMOUSE: { - if (event->val == KM_RELEASE) { + if (event->val != KM_PRESS) { done = true; } break; @@ -2721,7 +2721,8 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle if (data->searchbox) inbox = ui_searchbox_inside(data->searchbox, event->x, event->y); - if (event->val == KM_PRESS) { + /* for double click: we do a press again for when you first click on button (selects all text, no cursor pos) */ + if (event->val == KM_PRESS || event->val == KM_DBL_CLICK) { float mx, my; mx = event->x; @@ -2746,7 +2747,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle } /* only select a word in button if there was no selection before */ - if ((event->click_type == KM_DBL_CLICK) && (had_selection == false)) { + if (event->val == KM_DBL_CLICK && had_selection == false) { ui_textedit_move(but, data, STRCUR_DIR_PREV, false, STRCUR_JUMP_DELIM); ui_textedit_move(but, data, STRCUR_DIR_NEXT, true, STRCUR_JUMP_DELIM); retval = WM_UI_HANDLER_BREAK; @@ -3170,7 +3171,7 @@ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, cons } } else if (data->state == BUTTON_STATE_WAIT_RELEASE) { - if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + if (event->type == LEFTMOUSE && event->val != KM_PRESS) { if (!(but->flag & UI_SELECT)) data->cancel = true; button_activate_state(C, but, BUTTON_STATE_EXIT); @@ -3738,7 +3739,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton button_activate_state(C, but, BUTTON_STATE_EXIT); } } - else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { if (data->dragchange) { #ifdef USE_DRAG_MULTINUM /* if we started multibutton but didnt drag, then edit */ @@ -4035,7 +4036,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton button_activate_state(C, but, BUTTON_STATE_EXIT); } } - else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { if (data->dragchange) { #ifdef USE_DRAG_MULTINUM /* if we started multibutton but didnt drag, then edit */ @@ -4180,7 +4181,7 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut button_activate_state(C, but, BUTTON_STATE_EXIT); } } - else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->type == MOUSEMOVE) { @@ -4228,7 +4229,7 @@ static int ui_do_but_GRIP(bContext *C, uiBlock *block, uiBut *but, uiHandleButto button_activate_state(C, but, BUTTON_STATE_EXIT); } } - else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->type == MOUSEMOVE) { @@ -4252,7 +4253,7 @@ static int ui_do_but_LISTROW(bContext *C, uiBut *but, uiHandleButtonData *data, * editing field for editing list item names */ if ((ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS && event->ctrl) || - (event->type == LEFTMOUSE && event->click_type == KM_DBL_CLICK)) + (event->type == LEFTMOUSE && event->val == KM_DBL_CLICK)) { uiBut *labelbut = ui_but_list_row_text_activate(C, but, data, event, BUTTON_ACTIVATE_TEXT_EDITING); if (labelbut) { @@ -4604,7 +4605,7 @@ static int ui_do_but_UNITVEC(bContext *C, uiBlock *block, uiBut *but, uiHandleBu ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_EXIT); } @@ -4925,7 +4926,7 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_EXIT); } @@ -5198,7 +5199,7 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle } } } - else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_EXIT); } return WM_UI_HANDLER_BREAK; @@ -5283,7 +5284,7 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_EXIT); } @@ -5522,7 +5523,7 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { if (data->dragsel != -1) { CurveMapping *cumap = (CurveMapping *)but->poin; CurveMap *cuma = cumap->cm + cumap->cur; @@ -5618,7 +5619,7 @@ static int ui_do_but_HISTOGRAM(bContext *C, uiBlock *block, uiBut *but, uiHandle ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_EXIT); } return WM_UI_HANDLER_BREAK; @@ -5691,7 +5692,7 @@ static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleB ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_EXIT); } return WM_UI_HANDLER_BREAK; @@ -5716,7 +5717,7 @@ static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, con } else if (data->state == BUTTON_STATE_WAIT_RELEASE) { - if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + if (event->type == LEFTMOUSE && event->val != KM_PRESS) { if (!(but->flag & UI_SELECT)) data->cancel = true; button_activate_state(C, but, BUTTON_STATE_EXIT); @@ -5799,7 +5800,7 @@ static int ui_do_but_TRACKPREVIEW(bContext *C, uiBlock *block, uiBut *but, uiHan ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_EXIT); } return WM_UI_HANDLER_BREAK; @@ -8315,7 +8316,7 @@ static int ui_handle_menu_event( #ifdef USE_DRAG_POPUP if (menu->is_grab) { - if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + if (event->type == LEFTMOUSE) { menu->is_grab = false; retval = WM_UI_HANDLER_BREAK; } @@ -8600,7 +8601,7 @@ static int ui_handle_menu_event( uiSafetyRct *saferct = block->saferct.first; if (ELEM(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) && - (event->val == KM_PRESS || event->click_type == KM_DBL_CLICK)) + ELEM(event->val, KM_PRESS, KM_DBL_CLICK)) { if ((is_parent_menu == false) && (U.uiflag & USER_MENUOPENAUTO) == 0) { /* for root menus, allow clicking to close */ @@ -8977,11 +8978,6 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle switch (event->type) { case MOUSEMOVE: - /* verify we have a real mousemove */ - if (event->x == event->prevx && event->y == event->prevy) { - break; - } - if (!is_click_style) { float len_sq = len_squared_v2v2(event_xy, block->pie_data.pie_center_init); @@ -9008,9 +9004,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle case LEFTMOUSE: if (is_click_style) { - /* the click_type test sends a second event on KM_CLICK that - * may destroy nested pies even before they are drawn */ - if ((block->pie_data.flags & UI_PIE_INVALID_DIR) && (event->click_type != KM_CLICK)) { + if (block->pie_data.flags & UI_PIE_INVALID_DIR) { menu->menuretval = UI_RETURN_CANCEL; } else { @@ -9051,7 +9045,9 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle case YKEY: case ZKEY: { - if ((event->val == KM_PRESS) && !IS_EVENT_MOD(event, shift, ctrl, oskey)) { + if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) && + !IS_EVENT_MOD(event, shift, ctrl, oskey)) + { for (but = block->buttons.first; but; but = but->next) { if (but->menu_key == event->type) { ui_but_pie_button_activate(C, but, menu); @@ -9158,9 +9154,8 @@ static int ui_handle_menus_recursive( if (block->flag & UI_BLOCK_RADIAL) retval = ui_pie_handler(C, event, menu); - else if ((event->type == LEFTMOUSE) || (event->click_type != KM_DBL_CLICK)) { + else if (event->type == LEFTMOUSE || event->val != KM_DBL_CLICK) retval = ui_handle_menu_event(C, event, menu, level, is_parent_inside, is_parent_menu, is_floating); - } } } @@ -9196,16 +9191,10 @@ static int ui_region_handler(bContext *C, const wmEvent *event, void *UNUSED(use retval = ui_handle_list_event(C, event, ar); if (retval == WM_UI_HANDLER_CONTINUE) { - if (but) { + if (but) retval = ui_handle_button_event(C, event, but); - } - else { + else retval = ui_handle_button_over(C, event, ar); - - /* let's make sure we are really not hovering a button by adding a mousemove! - * XXX some WM_event_add_mousemove calls may become unnecessary with this and can be removed */ - WM_event_add_mousemove(C); - } } /* re-enable tooltips */ diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 7d6d5c3a6d7..d165e2719c5 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -1865,7 +1865,7 @@ static int ui_handler_panel(bContext *C, const wmEvent *event, void *userdata) uiHandlePanelData *data = panel->activedata; /* verify if we can stop */ - if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + if (event->type == LEFTMOUSE && event->val != KM_PRESS) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); int align = panel_aligned(sa, ar); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 0fbd0c40510..7cb9dca78bf 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -2749,8 +2749,8 @@ uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, co pie->block_radial->puphash = ui_popup_menu_hash(title); pie->block_radial->flag |= UI_BLOCK_RADIAL; - /* if pie is spawned by a left click or on release, it is always assumed to be click style */ - if ((event->type == LEFTMOUSE) || (event->val == KM_RELEASE)) { + /* if pie is spawned by a left click, it is always assumed to be click style */ + if (event->type == LEFTMOUSE) { pie->block_radial->pie_data.flags |= UI_PIE_CLICK_STYLE; pie->block_radial->pie_data.event = EVENT_NONE; win->lock_pie_event = EVENT_NONE; diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index b7545199f56..15e742c930a 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -2602,12 +2602,7 @@ void init_userdef_do_versions(void) cp[3] = 255; } } - - if (U.versionfile < 274 || (U.versionfile == 274 && U.subversionfile < 3)) { - if (U.click_timeout == 0) - U.click_timeout = 250; - } - + if (U.pixelsize == 0.0f) U.pixelsize = 1.0f; diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 5cdd45061e1..5c7efcc40da 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -511,10 +511,6 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w bool done = false; bool use_proj; - if (ELEM(event->click_type, KM_CLICK, KM_HOLD)) { - return OPERATOR_CANCELLED; - } - em_setup_viewcontext(C, &vc); ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 79eec57712f..126d1cb0ad9 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -407,7 +407,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) /* Vertex Slide */ WM_keymap_add_item(keymap, "TRANSFORM_OT_vert_slide", VKEY, KM_PRESS, KM_SHIFT, 0); /* use KM_CLICK because same key is used for tweaks */ - kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_RELEASE, KM_CTRL, 0); + kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "rotate_source", true); kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_PRESS, KM_SHIFT | KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "rotate_source", false); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index cf717cc48ca..422f0c12e51 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -295,7 +295,7 @@ void ED_keymap_object(wmKeyConfig *keyconf) keymap = WM_keymap_find(keyconf, "Object Non-modal", 0, 0); /* Note: this keymap works disregarding mode */ - kmi = WM_keymap_add_item(keymap, "OBJECT_OT_mode_set", TABKEY, KM_CLICK, 0, 0); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_mode_set", TABKEY, KM_PRESS, 0, 0); RNA_enum_set(kmi->ptr, "mode", OB_MODE_EDIT); RNA_boolean_set(kmi->ptr, "toggle", true); diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index b3149c1bbf4..92731c2f135 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -1140,11 +1140,8 @@ static int console_modal_select(bContext *C, wmOperator *op, const wmEvent *even case LEFTMOUSE: case MIDDLEMOUSE: case RIGHTMOUSE: - if (event->val == KM_RELEASE) { - console_cursor_set_exit(C, op); - return OPERATOR_FINISHED; - } - break; + console_cursor_set_exit(C, op); + return OPERATOR_FINISHED; case MOUSEMOVE: console_modal_select_apply(C, op, event); break; diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 557a495cb8f..782b318b8a2 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -444,27 +444,27 @@ static void file_keymap(struct wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "need_active", true); /* left mouse selects and opens */ - WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_PRESS, 0, 0); - kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, 0, 0); + kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", true); - kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0); + kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_CTRL | KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", true); RNA_boolean_set(kmi->ptr, "fill", true); /* right mouse selects without opening */ - kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_PRESS, 0, 0); + kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_CLICK, 0, 0); RNA_boolean_set(kmi->ptr, "open", false); - kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_PRESS, KM_SHIFT, 0); + kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_CLICK, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", true); RNA_boolean_set(kmi->ptr, "open", false); - kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_PRESS, KM_ALT, 0); + kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_CLICK, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "extend", true); RNA_boolean_set(kmi->ptr, "fill", true); RNA_boolean_set(kmi->ptr, "open", false); /* front and back mouse folder navigation */ - WM_keymap_add_item(keymap, "FILE_OT_previous", BUTTON4MOUSE, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "FILE_OT_next", BUTTON5MOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "FILE_OT_previous", BUTTON4MOUSE, KM_CLICK, 0, 0); + WM_keymap_add_item(keymap, "FILE_OT_next", BUTTON5MOUSE, KM_CLICK, 0, 0); WM_keymap_add_item(keymap, "FILE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "FILE_OT_refresh", PADPERIOD, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index e266a5089c8..33e8b522335 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -574,7 +574,7 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* insertkey */ WM_keymap_add_item(keymap, "GRAPH_OT_keyframe_insert", IKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "GRAPH_OT_click_insert", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_click_insert", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); /* copy/paste */ WM_keymap_add_item(keymap, "GRAPH_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index f72def8377f..c8951a1172e 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -633,14 +633,11 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) case RIGHTMOUSE: case MIDDLEMOUSE: { - if (event->val != KM_NOTHING) { - node_link_exit(C, op, true); - - ED_area_headerprint(CTX_wm_area(C), NULL); - ED_region_tag_redraw(ar); - return OPERATOR_FINISHED; - } - break; + node_link_exit(C, op, true); + + ED_area_headerprint(CTX_wm_area(C), NULL); + ED_region_tag_redraw(ar); + return OPERATOR_FINISHED; } } diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index 93116dbe22c..f5869575cc6 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -91,19 +91,19 @@ void outliner_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "OUTLINER_OT_item_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0); - kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_PRESS, 0, 0); + kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, 0, 0); RNA_boolean_set(kmi->ptr, "recursive", false); RNA_boolean_set(kmi->ptr, "extend", false); - kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); + kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "recursive", false); RNA_boolean_set(kmi->ptr, "extend", true); - kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); + kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "recursive", true); RNA_boolean_set(kmi->ptr, "extend", false); - kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0); + kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, KM_CTRL | KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "recursive", true); RNA_boolean_set(kmi->ptr, "extend", true); diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 9d517b20f01..ad8050a50e8 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -2163,11 +2163,6 @@ static int text_scroll_modal(bContext *C, wmOperator *op, const wmEvent *event) case LEFTMOUSE: case RIGHTMOUSE: case MIDDLEMOUSE: - /* don't exit on dummy events */ - if (event->val == KM_NOTHING) { - return OPERATOR_RUNNING_MODAL; - } - if (ELEM(tsc->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) { txt_screen_skip(st, ar, st->viewlines * (tsc->zone == SCROLLHANDLE_MIN_OUTSIDE ? 1 : -1)); @@ -2672,11 +2667,8 @@ static int text_set_selection_modal(bContext *C, wmOperator *op, const wmEvent * case LEFTMOUSE: case MIDDLEMOUSE: case RIGHTMOUSE: - if (event->val != KM_NOTHING) { - text_cursor_set_exit(C, op); - return OPERATOR_FINISHED; - } - break; + text_cursor_set_exit(C, op); + return OPERATOR_FINISHED; case TIMER: case MOUSEMOVE: text_cursor_set_apply(C, op, event); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 6ba3a2850cc..6a2c948aa8d 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -237,7 +237,7 @@ void view3d_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "VIEW3D_OT_navigate", FKEY, KM_PRESS, KM_SHIFT, 0); /* value is set to KM_NOTHING to avoid conflicts with click type (see T44251) */ - WM_keymap_verify_item(keymap, "VIEW3D_OT_smoothview", TIMER1, KM_NOTHING, KM_ANY, 0); + WM_keymap_verify_item(keymap, "VIEW3D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEPAN, 0, 0, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEROTATE, 0, 0, 0); @@ -387,7 +387,7 @@ void view3d_keymap(wmKeyConfig *keyconf) /* drawtype */ - kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", ZKEY, KM_CLICK, 0, 0); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", ZKEY, KM_PRESS, 0, 0); RNA_string_set(kmi->ptr, "data_path", "space_data.viewport_shade"); RNA_string_set(kmi->ptr, "value_1", "SOLID"); RNA_string_set(kmi->ptr, "value_2", "WIREFRAME"); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 161b8ca232d..44063335dbe 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -866,10 +866,10 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) keymap = WM_modalkeymap_add(keyconf, "Transform Modal Map", modal_items); /* items for modal map */ - WM_modalkeymap_add_item(keymap, ESCKEY, KM_RELEASE, KM_ANY, 0, TFM_MODAL_CANCEL); - WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, TFM_MODAL_CONFIRM); - WM_modalkeymap_add_item(keymap, RETKEY, KM_RELEASE, KM_ANY, 0, TFM_MODAL_CONFIRM); - WM_modalkeymap_add_item(keymap, PADENTER, KM_RELEASE, KM_ANY, 0, TFM_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_CANCEL); + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM); WM_modalkeymap_add_item(keymap, GKEY, KM_PRESS, 0, 0, TFM_MODAL_TRANSLATE); WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, TFM_MODAL_ROTATE); diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 348e895e0a9..afa1f03a8ca 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -447,9 +447,7 @@ typedef struct UserDef { short versions; short dbl_click_time; - short click_timeout; - short pad3; - + short gameflags; short wheellinescroll; int uiflag, uiflag2; @@ -467,8 +465,7 @@ typedef struct UserDef { char pad2[2]; short transopts; short menuthreshold1, menuthreshold2; - int pad4; - + struct ListBase themes; struct ListBase uifonts; struct ListBase uistyles; diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index dca2faf0d54..6eb2f2487b0 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -253,8 +253,7 @@ typedef struct wmKeyMapItem { /* event */ short type; /* event code itself */ - short val; /* NOTE: other than event->val this can be the value itself - * (KM_ANY, KM_PRESS, etc) AND the clicktype (KM_DBL_CLICK, KM_HOLD, etc) */ + short val; /* KM_ANY, KM_PRESS, KM_NOTHING etc */ short shift, ctrl, alt, oskey; /* oskey is apple or windowskey, value denotes order of pressed */ short keymodifier; /* rawkey modifier */ diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 23412a549fa..ef52fe2a084 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -4324,16 +4324,12 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_FLY_HELICOPTER); RNA_def_property_ui_text(prop, "Helicopter Mode", "Device up/down directly controls your Z position"); - prop = RNA_def_property(srna, "double_click_time", PROP_INT, PROP_NONE); + + prop = RNA_def_property(srna, "mouse_double_click_time", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "dbl_click_time"); RNA_def_property_range(prop, 1, 1000); RNA_def_property_ui_text(prop, "Double Click Timeout", "Time/delay (in ms) for a double click"); - prop = RNA_def_property(srna, "click_timeout", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "click_timeout"); - RNA_def_property_range(prop, 0, 10000); - RNA_def_property_ui_text(prop, "Click Timeout", "Time (in ms) to determine if a key is clicked or held"); - prop = RNA_def_property(srna, "use_mouse_emulate_3_button", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_TWOBUTTONMOUSE); RNA_def_property_ui_text(prop, "Emulate 3 Button Mouse", diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 28881b0b40c..a423a069517 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -49,7 +49,6 @@ static EnumPropertyItem event_keymouse_value_items[] = { {KM_PRESS, "PRESS", 0, "Press", ""}, {KM_RELEASE, "RELEASE", 0, "Release", ""}, {KM_CLICK, "CLICK", 0, "Click", ""}, - {KM_HOLD, "HOLD", 0, "Hold", ""}, {KM_DBL_CLICK, "DOUBLE_CLICK", 0, "Double Click", ""}, {0, NULL, 0, NULL, NULL} }; @@ -381,7 +380,6 @@ EnumPropertyItem event_value_items[] = { {KM_PRESS, "PRESS", 0, "Press", ""}, {KM_RELEASE, "RELEASE", 0, "Release", ""}, {KM_CLICK, "CLICK", 0, "Click", ""}, - {KM_HOLD, "HOLD", 0, "Hold", ""}, {KM_DBL_CLICK, "DOUBLE_CLICK", 0, "Double Click", ""}, {EVT_GESTURE_N, "NORTH", 0, "North", ""}, {EVT_GESTURE_NE, "NORTH_EAST", 0, "North-East", ""}, diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 366d3218176..e716cd6b779 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -180,11 +180,9 @@ enum { #define KM_NOTHING 0 #define KM_PRESS 1 #define KM_RELEASE 2 +#define KM_CLICK 3 +#define KM_DBL_CLICK 4 -/* clicktype */ -#define KM_CLICK 3 /* clicked key (click_time <= U.click_timeout) */ -#define KM_DBL_CLICK 4 /* double click - keep at 4 to avoid breakage with older key configs */ -#define KM_HOLD 5 /* held key (click_time > U.click_timeout) */ /* ************** UI Handler ***************** */ @@ -429,9 +427,7 @@ typedef struct wmEvent { short type; /* event code itself (short, is also in keymap) */ short val; /* press, release, scrollvalue */ - short click_type; /* click, hold or double click */ int x, y; /* mouse pointer position, screen coord */ - double click_time; /* the time since keypress started */ int mval[2]; /* region mouse position, name convention pre 2.5 :) */ char utf8_buf[6]; /* from, ghost if utf8 is enabled for the platform, * BLI_str_utf8_size() must _always_ be valid, check @@ -439,19 +435,20 @@ typedef struct wmEvent { char ascii; /* from ghost, fallback if utf8 isn't set */ char pad; - bool is_key_pressed; /* is a (non-modifier) key is pressed? (keyboard, mouse, NDOF, ...) */ - - /* previous state, used for clicktype */ + /* previous state, used for double click and the 'click' */ short prevtype; short prevval; int prevx, prevy; - double prevclick_time; + double prevclicktime; int prevclickx, prevclicky; /* modifier states */ short shift, ctrl, alt, oskey; /* oskey is apple or windowskey, value denotes order of pressed */ short keymodifier; /* rawkey modifier */ + /* set in case a KM_PRESS went by unhandled */ + short check_click; + /* keymap item, set by handler (weak?) */ const char *keymap_idname; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 8c013eb7cd4..d8ca80a62cb 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -404,7 +404,7 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve * to make the DBL_CLICK conversion work, we just don't send this to UI, except mouse clicks */ if (((handler->flag & WM_HANDLER_ACCEPT_DBL_CLICK) == 0) && (event->type != LEFTMOUSE) && - (event->click_type == KM_DBL_CLICK)) + (event->val == KM_DBL_CLICK)) { return WM_HANDLER_CONTINUE; } @@ -1442,7 +1442,6 @@ int WM_userdef_event_map(int kmitype) } -/* XXX rename to something more descriptive like wm_event_is_keymapitem_matching and use bool */ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) { int kmitype = WM_userdef_event_map(kmi->type); @@ -1459,13 +1458,10 @@ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) if (kmitype != KM_ANY) if (winevent->type != kmitype) return 0; - - /* KM_ANY excludes KM_HOLD since it's time based and not a real input - filter it out */ - if (kmi->val == KM_ANY && winevent->click_type == KM_HOLD) return 0; - + if (kmi->val != KM_ANY) - if (!ELEM(kmi->val, winevent->val, winevent->click_type)) return 0; - + if (winevent->val != kmi->val) return 0; + /* modifiers also check bits, so it allows modifier order */ if (kmi->shift != KM_ANY) if (winevent->shift != kmi->shift && !(winevent->shift & kmi->shift)) return 0; @@ -1512,9 +1508,8 @@ static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *eve /* modal keymap checking returns handled events fine, but all hardcoded modal * handling typically swallows all events (OPERATOR_RUNNING_MODAL). * This bypass just disables support for double clicks in hardcoded modal handlers */ - if (event->click_type == KM_DBL_CLICK) { + if (event->val == KM_DBL_CLICK) { event->val = KM_PRESS; - event->click_type = 0; *dbl_click_disabled = true; } } @@ -1546,9 +1541,9 @@ static void wm_event_modalmap_end(wmEvent *event, bool dbl_click_disabled) event->val = event->prevval; event->prevval = 0; } - else if (dbl_click_disabled) { - event->click_type = KM_DBL_CLICK; - } + else if (dbl_click_disabled) + event->val = KM_DBL_CLICK; + } /* Warning: this function removes a modal handler, when finished */ @@ -2026,21 +2021,47 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) /* test for CLICK events */ if (wm_action_not_handled(action)) { wmWindow *win = CTX_wm_window(C); - - /* XXX check if those double click hacks can be removed/improved since click_type was introduced */ + + /* eventstate stores if previous event was a KM_PRESS, in case that + * wasn't handled, the KM_RELEASE will become a KM_CLICK */ + + if (win && event->val == KM_PRESS) { + win->eventstate->check_click = true; + } + if (win && win->eventstate->prevtype == event->type) { - if (event->click_type == KM_DBL_CLICK) { + + if ((event->val == KM_RELEASE) && + (win->eventstate->prevval == KM_PRESS) && + (win->eventstate->check_click == true)) + { + event->val = KM_CLICK; + + if (G.debug & (G_DEBUG_HANDLERS)) { + printf("%s: handling CLICK\n", __func__); + } + + action |= wm_handlers_do_intern(C, event, handlers); + + event->val = KM_RELEASE; + } + else if (event->val == KM_DBL_CLICK) { event->val = KM_PRESS; - event->click_type = 0; action |= wm_handlers_do_intern(C, event, handlers); /* revert value if not handled */ if (wm_action_not_handled(action)) { - event->click_type = KM_DBL_CLICK; + event->val = KM_DBL_CLICK; } } } } + else { + wmWindow *win = CTX_wm_window(C); + + if (win) + win->eventstate->check_click = 0; + } } return action; @@ -2984,50 +3005,22 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi return NULL; } -/** - * Clicktype test - * - * We have 3 different click_types: #KM_CLICK, #KM_HOLD# and #KM_DBL_CLICK. - * - * Time is used to determine, what to send. It works as follows: - * - #KM_RELEASE && time since first #KM_PRESS < U.click_timeout --> send #KM_CLICK - * - #KM_PRESS && time since first #KM_PRESS > U.click_timeout --> send #KM_HOLD - * - #KM_PRESS after a #KM_RELEASE && time since previous #KM_PRESS < U.dbl_click_time --> send #KM_DBL_CLICK - * - * \note: only #KM_DBL_CLICK is handled here, rest in #wm_window_event_clicktype_init (wm_window.c) - */ -static void wm_event_clicktype_init(wmWindow *win, wmEvent *event, wmEvent *event_state) +static bool wm_event_is_double_click(wmEvent *event, wmEvent *event_state) { - short click_type = 0; - - if ((event->val == KM_PRESS) && - (event_state->prevval != KM_PRESS || event->prevtype != win->eventstate->prevtype)) - { - event_state->prevclick_time = event->click_time; - event_state->prevclickx = event->x; - event_state->prevclicky = event->y; - } - - /* double click */ - if (event->type == event_state->prevtype && - event_state->prevval == KM_RELEASE && - event->val == KM_PRESS) + if ((event->type == event_state->prevtype) && + (event_state->prevval == KM_RELEASE) && + (event->val == KM_PRESS)) { if ((ISMOUSE(event->type) == false) || ((ABS(event->x - event_state->prevclickx)) <= 2 && (ABS(event->y - event_state->prevclicky)) <= 2)) { - if ((PIL_check_seconds_timer() - event_state->prevclick_time) * 1000 < U.dbl_click_time) { - click_type = KM_DBL_CLICK; - if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) { - printf("%s Send double click event\n", __func__); - } + if ((PIL_check_seconds_timer() - event_state->prevclicktime) * 1000 < U.dbl_click_time) { + return true; } } } - if (click_type != event->click_type) { - event_state->click_type = event->click_type = click_type; - } + return false; } static void wm_event_add_mousemove(wmWindow *win, const wmEvent *event) @@ -3159,9 +3152,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U evt->val = event.val; evt->type = event.type; - /* click_type */ - wm_event_clicktype_init(win, &event, evt); - if (win->active == 0) { int cx, cy; @@ -3172,6 +3162,18 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event.y = evt->y = cy; } + /* double click test */ + if (wm_event_is_double_click(&event, evt)) { + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) + printf("%s Send double click\n", __func__); + event.val = KM_DBL_CLICK; + } + if (event.val == KM_PRESS) { + evt->prevclicktime = PIL_check_seconds_timer(); + evt->prevclickx = event.x; + evt->prevclicky = event.y; + } + /* add to other window if event is there (not to both!) */ owin = wm_event_cursor_other_windows(wm, win, &event); if (owin) { @@ -3210,10 +3212,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U /* copy to event state */ evt->val = event.val; evt->type = event.type; - - /* clicktype */ - wm_event_clicktype_init(win, &event, evt); - + /* exclude arrow keys, esc, etc from text input */ if (type == GHOST_kEventKeyUp) { event.ascii = '\0'; @@ -3279,6 +3278,14 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event.keymodifier = evt->keymodifier = 0; break; } + + /* double click test */ + /* if previous event was same type, and previous was release, and now it presses... */ + if (wm_event_is_double_click(&event, evt)) { + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) + printf("%s Send double click\n", __func__); + evt->val = event.val = KM_DBL_CLICK; + } /* this case happens on holding a key pressed, it should not generate * press events events with the same key as modifier */ @@ -3299,6 +3306,13 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U G.is_break = true; } + /* double click test - only for press */ + if (event.val == KM_PRESS) { + evt->prevclicktime = PIL_check_seconds_timer(); + evt->prevclickx = event.x; + evt->prevclicky = event.y; + } + wm_event_add(win, &event); break; diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 0a89ca113c4..82e46c1b333 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -1192,15 +1192,11 @@ int WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2) return 0; if (k1->val != KM_ANY && k2->val != KM_ANY) { - -#if 0 /* thanks to clicktype those shouldn't be needed anymore */ /* take click, press, release conflict into account */ if (k1->val == KM_CLICK && ELEM(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0) return 0; if (k2->val == KM_CLICK && ELEM(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0) return 0; -#endif - if (k1->val != k2->val) return 0; } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 499adf5704d..2e48c840c2c 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -5149,7 +5149,7 @@ void wm_window_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "WM_OT_debug_menu", DKEY, KM_PRESS, KM_ALT | KM_CTRL, 0); /* menus that can be accessed anywhere in blender */ - WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_CLICK, 0, 0); + WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_PRESS, 0, 0); WM_keymap_add_menu(keymap, "USERPREF_MT_ndof_settings", NDOF_BUTTON_MENU, KM_PRESS, 0, 0); /* Space switching */ diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 61bddb144ae..d69cf3326b7 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1106,76 +1106,6 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr return 1; } -/** - * #KM_DBL_CLICK is set in wm_event_clicktype_init (wm_event_system.c) - * Normally, this should be there too, but for #KM_CLICK/#KM_HOLD, we need a - * time precision of a few milliseconds, which we can't get from there - */ -static void wm_window_event_clicktype_init(const bContext *C) -{ - wmWindowManager *wm = CTX_wm_manager(C); - - if (wm->winactive) { - wmWindow *win = wm->winactive; - wmEvent *event = win->eventstate; - short click_type = event->click_type; - - BLI_assert(event != NULL); - - if ((event->type == EVENT_NONE) || - ((event->val == KM_NOTHING) && (event->is_key_pressed == false))) - { - /* nothing needs to be done here */ - return; - } - - /* we always want click_type of last clicked button (to enable - * use with modifier keys) - unnecessary for mouse though */ - if (!ISMOUSE(event->type) && - event->val == KM_PRESS && - event->type != event->keymodifier) - { - event->is_key_pressed = false; - } - else if (event->val == KM_PRESS && !event->is_key_pressed) { - event->is_key_pressed = true; - event->click_time = PIL_check_seconds_timer(); - } - else if (event->val == KM_RELEASE && event->is_key_pressed) { - event->is_key_pressed = false; - } - else if (event->is_key_pressed == false) { - return; - } - - /* the actual test */ - if ((PIL_check_seconds_timer() - event->click_time) * 1000 <= U.click_timeout) { - /* for any reason some X11 systems send two release events triggering two KM_CLICK - * events - making the rules more strict by checking for prevval resolves this */ - if (event->val == KM_RELEASE && event->prevval != KM_RELEASE) { - click_type = KM_CLICK; - if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) { - printf("%s Send click event\n", __func__); - } - } - } - else if (event->is_key_pressed) { - click_type = KM_HOLD; - if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) { - printf("%s Send hold event\n", __func__); - } - - /* the event we send in this case is a "dummy" event - don't send value */ - event->val = KM_NOTHING; - } - - /* send event with new click_type */ - if (event->click_type != click_type) { - event->click_type = click_type; - wm_event_add(win, event); - } - } -} /* This timer system only gives maximum 1 timer event per redraw cycle, * to prevent queues to get overloaded. @@ -1235,11 +1165,7 @@ void wm_window_process_events(const bContext *C) if (hasevent) GHOST_DispatchEvents(g_system); - - /* not nice to have this here, but it's the only place - * that can call it with the needed time precision */ - wm_window_event_clicktype_init(C); - + hasevent |= wm_window_timer(C); /* no event, we sleep 5 milliseconds */ -- cgit v1.2.3 From f9f3c29a3a5b558e09c36076521bdafc91e7e326 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 7 Apr 2015 16:08:46 +0200 Subject: Fix crash when changing proxy storage type for editing (was own stupidity casting from Scene to Editing in RNA) Move versioning for proxy storage to multiview version check (not really correct but it was orphaned before and it doesn't hurt either). --- source/blender/blenloader/intern/versioning_270.c | 34 ++++++++--------------- source/blender/makesrna/intern/rna_sequencer.c | 4 +-- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 70c7cc9e878..1b91d3d869e 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -708,28 +708,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } FOREACH_NODETREE_END } - if (!DNA_struct_elem_find(fd->filesdna, "Sequence", "char", "storage")) { - Scene *scene; - Sequence *seq; - -#define SEQ_USE_PROXY_CUSTOM_DIR (1 << 19) -#define SEQ_USE_PROXY_CUSTOM_FILE (1 << 21) - - for (scene = main->scene.first; scene; scene = scene->id.next) { - SEQ_BEGIN (scene->ed, seq) { - if (seq->strip && seq->strip->proxy) { - if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) - seq->strip->proxy->storage = SEQ_STORAGE_PROXY_CUSTOM_DIR; - if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) - seq->strip->proxy->storage = SEQ_STORAGE_PROXY_CUSTOM_FILE; - } - } - SEQ_END - } -#undef SEQ_USE_PROXY_CUSTOM_DIR -#undef SEQ_USE_PROXY_CUSTOM_FILE - } - if (!MAIN_VERSION_ATLEAST(main, 274, 4)) { SceneRenderView *srv; wmWindowManager *wm; @@ -753,6 +731,18 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) SEQ_BEGIN (scene->ed, seq) { seq->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo Display 3d Format"); + +#define SEQ_USE_PROXY_CUSTOM_DIR (1 << 19) +#define SEQ_USE_PROXY_CUSTOM_FILE (1 << 21) + if (seq->strip && seq->strip->proxy && !seq->strip->proxy->storage) { + if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) + seq->strip->proxy->storage = SEQ_STORAGE_PROXY_CUSTOM_DIR; + if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) + seq->strip->proxy->storage = SEQ_STORAGE_PROXY_CUSTOM_FILE; + } +#undef SEQ_USE_PROXY_CUSTOM_DIR +#undef SEQ_USE_PROXY_CUSTOM_FILE + } SEQ_END } diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index ee4ec1cb659..052744a9864 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -135,9 +135,9 @@ static void rna_SequenceEditor_sequences_all_begin(CollectionPropertyIterator *i rna_iterator_listbase_begin(iter, &ed->seqbase, NULL); } -static void rna_SequenceEditor_update_cache(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) +static void rna_SequenceEditor_update_cache(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) { - Editing *ed = (Editing *) ptr->id.data; + Editing *ed = scene->ed; BKE_sequencer_free_imbuf(scene, &ed->seqbase, false); } -- cgit v1.2.3 From e36b0cb8f32fc4302499c87e5c2b4c1ecc7a6543 Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Tue, 7 Apr 2015 18:32:25 +0200 Subject: BGE: New API method getDisplayDimensions This patch adds a new API function to get the actual display dimensions in pixels. Reviewers: dfelinto, sybren, lordloki, moguri Reviewed By: lordloki, moguri Differential Revision: https://developer.blender.org/D648 --- doc/python_api/rst/bge.render.rst | 6 ++++++ source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp | 5 +++++ source/gameengine/BlenderRoutines/KX_BlenderCanvas.h | 2 ++ source/gameengine/GamePlayer/common/GPC_Canvas.h | 2 ++ source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp | 12 ++++++++++++ source/gameengine/GamePlayer/ghost/GPG_Canvas.h | 2 ++ source/gameengine/Ketsji/KX_PythonInit.cpp | 16 ++++++++++++++++ source/gameengine/Rasterizer/RAS_ICanvas.h | 2 ++ 8 files changed, 47 insertions(+) diff --git a/doc/python_api/rst/bge.render.rst b/doc/python_api/rst/bge.render.rst index 651693b7a8a..1748ae14fc8 100644 --- a/doc/python_api/rst/bge.render.rst +++ b/doc/python_api/rst/bge.render.rst @@ -123,6 +123,12 @@ Functions :rtype: bool +.. function:: getDisplayDimensions() + + Get the actual display dimensions, in pixels, of the physical display (e.g., the monitor). + + :type dimension: list [width,heigh] + .. function:: makeScreenshot(filename) Writes an image file with the current displayed frame. diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp index 3a31806fad4..e37818678d6 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp @@ -97,6 +97,11 @@ bool KX_BlenderCanvas::GetSwapInterval(int &intervalOut) return wm_window_get_swap_interval(m_win, &intervalOut); } +void KX_BlenderCanvas::GetDisplayDimensions(int &width, int &height) +{ + wm_get_screensize(&width, &height); +} + void KX_BlenderCanvas::ResizeWindow(int width, int height) { // Not implemented for the embedded player diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h index c150af21230..817a667d783 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h @@ -87,6 +87,8 @@ public: int &intervalOut ); + void GetDisplayDimensions(int &width, int &height); + void ResizeWindow( int width, diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.h b/source/gameengine/GamePlayer/common/GPC_Canvas.h index acbea477e38..34cc9759a08 100644 --- a/source/gameengine/GamePlayer/common/GPC_Canvas.h +++ b/source/gameengine/GamePlayer/common/GPC_Canvas.h @@ -71,6 +71,8 @@ public: virtual void ResizeWindow(int width, int height) {} + virtual void GetDisplayDimensions(int &width, int &height) {} + /** * \section Methods inherited from abstract base class RAS_ICanvas. */ diff --git a/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp b/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp index 556f85804ea..09eb1691dae 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp @@ -121,6 +121,18 @@ bool GPG_Canvas::GetSwapInterval(int& intervalOut) return false; } +void GPG_Canvas::GetDisplayDimensions(int &width, int &height) + { + unsigned int uiwidth; + unsigned int uiheight; + + GHOST_ISystem *system = GHOST_ISystem::getSystem(); + system->getMainDisplayDimensions(uiwidth, uiheight); + + width = uiwidth; + height = uiheight; +} + void GPG_Canvas::ResizeWindow(int width, int height) { if (m_window->getState() == GHOST_kWindowStateFullScreen) diff --git a/source/gameengine/GamePlayer/ghost/GPG_Canvas.h b/source/gameengine/GamePlayer/ghost/GPG_Canvas.h index 337c2cedf55..18afbf6cd9e 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Canvas.h +++ b/source/gameengine/GamePlayer/ghost/GPG_Canvas.h @@ -63,6 +63,8 @@ public: virtual float GetMouseNormalizedX(int x); virtual float GetMouseNormalizedY(int y); + virtual void GetDisplayDimensions(int &width, int &height); + virtual void ResizeWindow(int width, int height); virtual void SetFullScreen(bool enable); virtual bool GetFullScreen(); diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 18b25d340dd..420e0be8c5d 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -1403,6 +1403,20 @@ static PyObject *gPyClearDebugList(PyObject *) Py_RETURN_NONE; } +static PyObject *gPyGetDisplayDimensions(PyObject *) +{ + PyObject *list = PyList_New(0); + int width; + int height; + + gp_Canvas->GetDisplayDimensions(width, height); + + PyList_Append(list, PyLong_FromLong(width)); + PyList_Append(list, PyLong_FromLong(height)); + + return list; +} + PyDoc_STRVAR(Rasterizer_module_documentation, "This is the Python API for the game engine of Rasterizer" ); @@ -1446,6 +1460,8 @@ static struct PyMethodDef rasterizer_methods[] = { {"setWindowSize", (PyCFunction) gPySetWindowSize, METH_VARARGS, ""}, {"setFullScreen", (PyCFunction) gPySetFullScreen, METH_O, ""}, {"getFullScreen", (PyCFunction) gPyGetFullScreen, METH_NOARGS, ""}, + {"getDisplayDimensions", (PyCFunction) gPyGetDisplayDimensions, METH_NOARGS, + "Get the actual dimensions, in pixels, of the physical display (e.g., the monitor)."}, {"setMipmapping", (PyCFunction) gPySetMipmapping, METH_VARARGS, ""}, {"getMipmapping", (PyCFunction) gPyGetMipmapping, METH_NOARGS, ""}, {"setVsync", (PyCFunction) gPySetVsync, METH_VARARGS, ""}, diff --git a/source/gameengine/Rasterizer/RAS_ICanvas.h b/source/gameengine/Rasterizer/RAS_ICanvas.h index d90cbea286e..471c2c97fa1 100644 --- a/source/gameengine/Rasterizer/RAS_ICanvas.h +++ b/source/gameengine/Rasterizer/RAS_ICanvas.h @@ -237,6 +237,8 @@ public: const char* filename )=0; + virtual void GetDisplayDimensions(int &width, int &height) = 0; + virtual void ResizeWindow( -- cgit v1.2.3 From 858f54f16ed3b8109fde1655fc8f224a0058b69c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 7 Apr 2015 22:41:08 +0500 Subject: Cycles: Cleanup, indentation --- intern/cycles/kernel/geom/geom_triangle_intersect.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index b29fc2b4e9d..d867a193beb 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -60,7 +60,7 @@ ccl_device_inline ccl_device_noinline #endif void triangle_intersect_precalc(float3 dir, - IsectPrecalc *isect_precalc) + IsectPrecalc *isect_precalc) { /* Calculate dimension where the ray direction is maximal. */ int kz = util_max_axis(make_float3(fabsf(dir.x), -- cgit v1.2.3 From 662c2cd9105c43f2c21c511a68d45cef719ef9c9 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Tue, 7 Apr 2015 15:42:44 -0300 Subject: Multiview: update Set Stereo 3D menu when the selected stereo mode changes --- source/blender/windowmanager/intern/wm_operators.c | 1 + source/blender/windowmanager/intern/wm_stereo.c | 8 ++++++++ source/blender/windowmanager/wm.h | 1 + 3 files changed, 10 insertions(+) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 2e48c840c2c..f97e79d882d 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -4855,6 +4855,7 @@ static void WM_OT_stereo3d_set(wmOperatorType *ot) ot->invoke = wm_stereo3d_set_invoke; ot->poll = WM_operator_winactive; ot->ui = wm_stereo3d_set_draw; + ot->check = wm_stereo3d_set_check; ot->cancel = wm_stereo3d_set_cancel; prop = RNA_def_enum(ot->srna, "display_mode", stereo3d_display_items, S3D_DISPLAY_ANAGLYPH, "Display Mode", ""); diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 5d7b11272c6..44d0e81e93c 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -519,6 +519,14 @@ void wm_stereo3d_set_draw(bContext *C, wmOperator *op) } } +bool wm_stereo3d_set_check(bContext *UNUSED(C), wmOperator *UNUSED(op)) +{ + /* the check function guarantees that the menu is updated to show the + * sub-options when an enum change (e.g., it shows the anaglyph options + * when anaglyph is on, and the interlace options when this is on */ + return true; +} + void wm_stereo3d_set_cancel(bContext *C, wmOperator *op) { Stereo3dData *s3dd = op->customdata; diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h index bc777b74b51..2f06ddab1e8 100644 --- a/source/blender/windowmanager/wm.h +++ b/source/blender/windowmanager/wm.h @@ -81,6 +81,7 @@ void wm_method_draw_stereo3d(const bContext *C, wmWindow *win); int wm_stereo3d_set_exec(bContext *C, wmOperator *op); int wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *event); void wm_stereo3d_set_draw(bContext *C, wmOperator *op); +bool wm_stereo3d_set_check(bContext *C, wmOperator *op); void wm_stereo3d_set_cancel(bContext *C, wmOperator *op); /* init operator properties */ -- cgit v1.2.3 From c1e5d966c60876453dc7b66e0c23065088e8b94b Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 7 Apr 2015 16:45:29 +0200 Subject: Proportional editing support for the action editor. There are a few things here which are not so nice: * Position of proportional edit circle is not centered on data (difficult to predict positions here since those are completely custom, will probably be positioned at center of area later instead) * Result is flushed to curve handles only at the end of the transform, so if people have the graph editor open they will see handles lagging behind. --- release/scripts/startup/bl_ui/space_dopesheet.py | 6 + source/blender/editors/space_action/action_ops.c | 6 +- source/blender/editors/transform/transform.c | 15 +- .../editors/transform/transform_constraints.c | 2 +- .../editors/transform/transform_conversions.c | 233 ++++++++++++++++----- .../blender/editors/transform/transform_generics.c | 2 +- 6 files changed, 211 insertions(+), 53 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index bb08a7c392e..843cf41b07c 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -105,6 +105,7 @@ class DOPESHEET_HT_header(Header): layout = self.layout st = context.space_data + toolsettings = context.tool_settings row = layout.row(align=True) row.template_header() @@ -133,6 +134,11 @@ class DOPESHEET_HT_header(Header): # filters which will work here and are useful (especially for character animation) dopesheet_filter(layout, context, genericFiltersOnly=True) + row = layout.row(align=True) + row.prop(toolsettings, "proportional_edit", icon_only=True) + if toolsettings.proportional_edit != 'DISABLED': + row.prop(toolsettings, "proportional_edit_falloff", icon_only=True) + # Grease Pencil mode doesn't need snapping, as it's frame-aligned only if st.mode != 'GPENCIL': layout.prop(st, "auto_snap", text="") diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 9ad0931a957..0f21446cc3d 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -202,7 +202,6 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) WM_keymap_add_item(keymap, "ACTION_OT_keyframe_type", RKEY, KM_PRESS, 0, 0); /* destructive */ - WM_keymap_add_item(keymap, "ACTION_OT_clean", OKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ACTION_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "ACTION_OT_delete", XKEY, KM_PRESS, 0, 0); @@ -241,6 +240,11 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* transform system */ transform_keymap_for_space(keyconf, keymap, SPACE_ACTION); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", OKEY, KM_PRESS, 0, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.proportional_edit"); + RNA_string_set(kmi->ptr, "value_1", "DISABLED"); + RNA_string_set(kmi->ptr, "value_2", "ENABLED"); + /* special markers hotkeys for anim editors: see note in definition of this function */ ED_marker_keymap_animedit_conflictfree(keymap); } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 44063335dbe..17f1d6112b2 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2095,6 +2095,12 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t); } + else if (t->spacetype == SPACE_ACTION) { + unit_m3(t->spacemtx); + t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); + //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); + t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t); + } else unit_m3(t->spacemtx); @@ -7518,6 +7524,7 @@ static void initTimeTranslate(TransInfo *t) static void headerTimeTranslate(TransInfo *t, char str[MAX_INFO_LEN]) { char tvec[NUM_STR_REP_LEN * 3]; + int ofs = 0; /* if numeric input is active, use results from that, otherwise apply snapping to result */ if (hasNumInput(&t->num)) { @@ -7553,7 +7560,11 @@ static void headerTimeTranslate(TransInfo *t, char str[MAX_INFO_LEN]) BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val); } - BLI_snprintf(str, MAX_INFO_LEN, IFACE_("DeltaX: %s"), &tvec[0]); + ofs += BLI_snprintf(str, MAX_INFO_LEN, IFACE_("DeltaX: %s"), &tvec[0]); + + if (t->flag & T_PROP_EDIT_ALL) { + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); + } } static void applyTimeTranslateValue(TransInfo *t, float UNUSED(sval)) @@ -7590,7 +7601,7 @@ static void applyTimeTranslateValue(TransInfo *t, float UNUSED(sval)) } val = BKE_nla_tweakedit_remap(adt, td->ival, NLATIME_CONVERT_MAP); - val += deltax; + val += deltax * td->factor; *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP); } else { diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index bcd66f56c53..03d626fe179 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -765,7 +765,7 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) } glScalef(1.0f / aspx, 1.0f / aspy, 1.0f); } - else if (t->spacetype == SPACE_IPO) { + else if (ELEM(t->spacetype, SPACE_IPO, SPACE_ACTION)) { /* only scale y */ rcti *mask = &t->ar->v2d.mask; rctf *datamask = &t->ar->v2d.cur; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 6124dab343f..23648c242f7 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3328,10 +3328,10 @@ static void posttrans_action_clean(bAnimContext *ac, bAction *act) /* ----------------------------- */ /* fully select selected beztriples, but only include if it's on the right side of cfra */ -static int count_fcurve_keys(FCurve *fcu, char side, float cfra) +static int count_fcurve_keys(FCurve *fcu, char side, float cfra, bool propedit) { BezTriple *bezt; - int i, count = 0; + int i, count = 0, count_all = 0; if (ELEM(NULL, fcu, fcu->bezt)) return count; @@ -3341,20 +3341,22 @@ static int count_fcurve_keys(FCurve *fcu, char side, float cfra) if (bezt->f2 & SELECT) { /* no need to adjust the handle selection since they are assumed * selected (like graph editor with SIPO_NOHANDLES) */ - if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) { - count += 1; - } + if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) + count++; } + count_all++; } - return count; + if (propedit && count > 0) + return count_all; + else return count; } /* fully select selected beztriples, but only include if it's on the right side of cfra */ -static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra) +static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra, bool propedit) { bGPDframe *gpf; - int count = 0; + int count = 0, count_all = 0; if (gpl == NULL) return count; @@ -3365,16 +3367,20 @@ static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra) if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) count++; } + count_all++; } - return count; + if (propedit && count > 0) + return count_all; + else + return count; } /* fully select selected beztriples, but only include if it's on the right side of cfra */ -static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra) +static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, bool propedit) { MaskLayerShape *masklayer_shape; - int count = 0; + int count = 0, count_all = 0; if (masklay == NULL) return count; @@ -3385,9 +3391,13 @@ static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra) if (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra)) count++; } + count_all++; } - return count; + if (propedit && count > 0) + return count_all; + else + return count; } @@ -3398,6 +3408,8 @@ static void TimeToTransData(TransData *td, float *time, AnimData *adt) td->val = time; td->ival = *(time); + td->center[0] = td->ival; + /* store the AnimData where this keyframe exists as a keyframe of the * active action as td->extra. */ @@ -3411,7 +3423,7 @@ static void TimeToTransData(TransData *td, float *time, AnimData *adt) * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data * on the named side are used. */ -static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra) +static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra, bool propedit) { BezTriple *bezt; TransData2D *td2d = *td2dv; @@ -3422,11 +3434,14 @@ static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FC for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { /* only add selected keyframes (for now, proportional edit is not enabled) */ - if (bezt->f2 & SELECT) { /* note this MUST match count_fcurve_keys(), so can't use BEZSELECTED() macro */ + if (propedit || (bezt->f2 & SELECT)) { /* note this MUST match count_fcurve_keys(), so can't use BEZSELECTED() macro */ /* only add if on the right 'side' of the current frame */ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) { TimeToTransData(td, bezt->vec[1], adt); + if (bezt->f2 & SELECT) + td->flag |= TD_SELECTED; + /*set flags to move handles as necessary*/ td->flag |= TD_MOVEHANDLE1 | TD_MOVEHANDLE2; td2d->h1 = bezt->vec[0]; @@ -3477,19 +3492,21 @@ void flushTransIntFrameActionData(TransInfo *t) * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data * on the named side are used. */ -static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra) +static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra, bool propedit) { bGPDframe *gpf; int count = 0; /* check for select frames on right side of current frame */ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - if (gpf->flag & GP_FRAME_SELECT) { + if (propedit || (gpf->flag & GP_FRAME_SELECT)) { if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) { /* memory is calloc'ed, so that should zero everything nicely for us */ td->val = &tfd->val; td->ival = (float)gpf->framenum; + td->center[0] = td->ival; + tfd->val = (float)gpf->framenum; tfd->sdata = &gpf->framenum; @@ -3505,19 +3522,21 @@ static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, } /* refer to comment above #GPLayerToTransData, this is the same but for masks */ -static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra) +static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra, bool propedit) { MaskLayerShape *masklay_shape; int count = 0; /* check for select frames on right side of current frame */ for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { - if (masklay_shape->flag & MASK_SHAPE_SELECT) { + if (propedit || (masklay_shape->flag & MASK_SHAPE_SELECT)) { if (FrameOnMouseSide(side, (float)masklay_shape->frame, cfra)) { /* memory is calloc'ed, so that should zero everything nicely for us */ td->val = &tfd->val; td->ival = (float)masklay_shape->frame; + td->center[0] = td->ival; + tfd->val = (float)masklay_shape->frame; tfd->sdata = &masklay_shape->frame; @@ -3539,15 +3558,16 @@ static void createTransActionData(bContext *C, TransInfo *t) TransData *td = NULL; TransData2D *td2d = NULL; tGPFtransdata *tfd = NULL; - + bAnimContext ac; ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; - + const bool propedit = (t->flag & T_PROP_EDIT) != 0; + int count = 0; float cfra; - + /* determine what type of data we are operating on */ if (ANIM_animdata_get_context(C, &ac) == 0) return; @@ -3575,7 +3595,7 @@ static void createTransActionData(bContext *C, TransInfo *t) /* loop 1: fully select ipo-keys and count how many BezTriples are selected */ for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(&ac, ale); - + int adt_count = 0; /* convert current-frame to action-time (slightly less accurate, especially under * higher scaling ratios, but is faster than converting all points) */ @@ -3585,13 +3605,18 @@ static void createTransActionData(bContext *C, TransInfo *t) cfra = (float)CFRA; if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) - count += count_fcurve_keys(ale->key_data, t->frame_side, cfra); + adt_count = count_fcurve_keys(ale->key_data, t->frame_side, cfra, propedit); else if (ale->type == ANIMTYPE_GPLAYER) - count += count_gplayer_frames(ale->data, t->frame_side, cfra); + adt_count = count_gplayer_frames(ale->data, t->frame_side, cfra, propedit); else if (ale->type == ANIMTYPE_MASKLAYER) - count += count_masklayer_frames(ale->data, t->frame_side, cfra); + adt_count = count_masklayer_frames(ale->data, t->frame_side, cfra, propedit); else BLI_assert(0); + + if (adt_count > 0) { + count += adt_count; + ale->tag = true; + } } /* stop if trying to build list if nothing selected */ @@ -3628,11 +3653,22 @@ static void createTransActionData(bContext *C, TransInfo *t) /* loop 2: build transdata array */ for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt; + + if (propedit && !ale->tag) + continue; + + adt = ANIM_nla_mapping_get(&ac, ale); + if (adt) + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); + else + cfra = (float)CFRA; + if (ale->type == ANIMTYPE_GPLAYER) { bGPDlayer *gpl = (bGPDlayer *)ale->data; int i; - i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra); + i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, propedit); td += i; tfd += i; } @@ -3640,7 +3676,7 @@ static void createTransActionData(bContext *C, TransInfo *t) MaskLayer *masklay = (MaskLayer *)ale->data; int i; - i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra); + i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, propedit); td += i; tfd += i; } @@ -3648,15 +3684,7 @@ static void createTransActionData(bContext *C, TransInfo *t) AnimData *adt = ANIM_nla_mapping_get(&ac, ale); FCurve *fcu = (FCurve *)ale->key_data; - /* convert current-frame to action-time (slightly less accurate, especially under - * higher scaling ratios, but is faster than converting all points) - */ - if (adt) - cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); - else - cfra = (float)CFRA; - - td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra); + td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, propedit); } } @@ -3685,6 +3713,107 @@ static void createTransActionData(bContext *C, TransInfo *t) *((float *)(t->customData) + 1) = max; } + /* calculate distances for proportional editing */ + if (propedit) { + td = t->data; + + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt; + + /* F-Curve may not have any keyframes */ + if (!ale->tag) + continue; + + adt = ANIM_nla_mapping_get(&ac, ale); + if (adt) + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); + else + cfra = (float)CFRA; + + if (ale->type == ANIMTYPE_GPLAYER) { + bGPDlayer *gpl = (bGPDlayer *)ale->data; + bGPDframe *gpf; + + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { + if (gpf->flag & GP_FRAME_SELECT) { + td->dist = td->rdist = 0.0f; + } + else { + bGPDframe *gpf_iter; + float min = FLT_MAX; + for (gpf_iter = gpl->frames.first; gpf_iter; gpf_iter = gpf->next) { + if (gpf_iter->flag & GP_FRAME_SELECT) { + if (FrameOnMouseSide(t->frame_side, (float)gpf_iter->framenum, cfra)) { + float val = fabs(gpf->framenum - gpf_iter->framenum); + if (val < min) + min = val; + } + } + } + td->dist = td->rdist = min; + } + td++; + } + } + else if (ale->type == ANIMTYPE_MASKLAYER) { + MaskLayer *masklay = (MaskLayer *)ale->data; + MaskLayerShape *masklay_shape; + + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { + if (FrameOnMouseSide(t->frame_side, (float)masklay_shape->frame, cfra)) { + if (masklay_shape->flag & MASK_SHAPE_SELECT) { + td->dist = td->rdist = 0.0f; + } + else { + MaskLayerShape *masklay_iter; + float min = FLT_MAX; + for (masklay_iter = masklay->splines_shapes.first; masklay_iter; masklay_iter = masklay_iter->next) { + if (masklay_iter->flag & MASK_SHAPE_SELECT) { + if (FrameOnMouseSide(t->frame_side, (float)masklay_iter->frame, cfra)) { + float val = fabs(masklay_shape->frame - masklay_iter->frame); + if (val < min) + min = val; + } + } + } + td->dist = td->rdist = min; + } + td++; + } + } + } + else { + FCurve *fcu = (FCurve *)ale->key_data; + BezTriple *bezt; + int i; + + for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { + if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { + if (bezt->f2 & SELECT) { + td->dist = td->rdist = 0.0f; + } + else { + BezTriple *bezt_iter; + int j; + float min = FLT_MAX; + for (j = 0, bezt_iter = fcu->bezt; j < fcu->totvert; j++, bezt_iter++) { + if (bezt_iter->f2 & SELECT) { + if (FrameOnMouseSide(t->frame_side, (float)bezt_iter->vec[1][0], cfra)) { + float val = fabs(bezt->vec[1][0] - bezt_iter->vec[1][0]); + if (val < min) + min = val; + } + } + } + td->dist = td->rdist = min; + } + td++; + } + } + } + } + } + /* cleanup temp list */ ANIM_animdata_freelist(&anim_data); } @@ -3787,7 +3916,7 @@ static bool graph_edit_use_local_center(TransInfo *t) } -static void graph_key_shortest_dist(FCurve *fcu, TransData *td_start, TransData *td, bool use_handle) +static void graph_key_shortest_dist(TransInfo *t, FCurve *fcu, TransData *td_start, TransData *td, int cfra, bool use_handle) { int j = 0; TransData *td_iter = td_start; @@ -3795,15 +3924,17 @@ static void graph_key_shortest_dist(FCurve *fcu, TransData *td_start, TransData td->dist = FLT_MAX; for (; j < fcu->totvert; j++) { BezTriple *bezt = fcu->bezt + j; - const bool sel2 = (bezt->f2 & SELECT) != 0; - const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2; - const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; + if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { + const bool sel2 = (bezt->f2 & SELECT) != 0; + const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2; + const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; - if (sel1 || sel2 || sel3) { - td->dist = td->rdist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0])); - } + if (sel1 || sel2 || sel3) { + td->dist = td->rdist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0])); + } - td_iter += 3; + td_iter += 3; + } } } @@ -4091,7 +4222,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) td->dist = td->rdist = 0.0f; } else { - graph_key_shortest_dist(fcu, td_start, td, use_handle); + graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle); } td++; @@ -4099,7 +4230,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) td->dist = td->rdist = 0.0f; } else { - graph_key_shortest_dist(fcu, td_start, td, use_handle); + graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle); } td++; @@ -4107,7 +4238,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) td->dist = td->rdist = 0.0f; } else { - graph_key_shortest_dist(fcu, td_start, td, use_handle); + graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle); } td++; } @@ -7725,6 +7856,12 @@ void createTransData(bContext *C, TransInfo *t) else if (t->spacetype == SPACE_ACTION) { t->flag |= T_POINTS | T_2D_EDIT; createTransActionData(C, t); + + if (t->data && (t->flag & T_PROP_EDIT)) { + sort_trans_data(t); // makes selected become first in array + //set_prop_dist(t, false); /* don't do that, distance has been set in createTransActionData already */ + sort_trans_data_dist(t); + } } else if (t->spacetype == SPACE_NLA) { t->flag |= T_POINTS | T_2D_EDIT; @@ -7741,7 +7878,7 @@ void createTransData(bContext *C, TransInfo *t) if (t->data && (t->flag & T_PROP_EDIT)) { sort_trans_data(t); // makes selected become first in array - //set_prop_dist(t, false); /* don't do that, distance has been set in createTransGraphEditData already */ + set_prop_dist(t, false); /* don't do that, distance has been set in createTransGraphEditData already */ sort_trans_data_dist(t); } } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 0571fc399a6..27a072c301b 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1320,7 +1320,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve /* use settings from scene only if modal */ if (t->flag & T_MODAL) { if ((t->options & CTX_NO_PET) == 0) { - if (t->spacetype == SPACE_IPO) { + if (ELEM(t->spacetype, SPACE_IPO, SPACE_ACTION)) { t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional); } else if (t->obedit) { -- cgit v1.2.3 From 4c2306d21a2a1aea37261c5a6c92b6c2bff55e9f Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Tue, 7 Apr 2015 16:37:16 -0300 Subject: Multiview: compositor was not updating when multiview was off --- source/blender/editors/space_node/node_edit.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 80ecab09442..360087d77c7 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -239,9 +239,14 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog // XXX BIF_store_spare(); /* 1 is do_previews */ - for (srv = scene->r.views.first; srv; srv = srv->next) { - if (BKE_scene_multiview_is_render_view_active(&scene->r, srv) == false) continue; - ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings, srv->name); + if ((cj->scene->r.scemode & R_MULTIVIEW) == 0) { + ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings, ""); + } + else { + for (srv = scene->r.views.first; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(&scene->r, srv) == false) continue; + ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings, srv->name); + } } ntree->test_break = NULL; -- cgit v1.2.3 From cc9c049ff7695ba5fa6a48d468bf3d18602d330e Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Tue, 7 Apr 2015 16:56:26 -0300 Subject: Multiview: compositor - avoid trashing image viewer views/buffers when multiview is off I found this while investigating why the backdrop shows 'blank' while I update a node influence factor. This problem still persist, but maybe it was there before multiview. In release it is not noticeable, but in my debug build is quite evident. --- source/blender/blenkernel/intern/image.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index f852d886ae9..bd0daf36147 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2357,11 +2357,16 @@ Image *BKE_image_verify_viewer(int type, const char *name) static void image_viewer_create_views(const RenderData *rd, Image *ima) { - SceneRenderView *srv; - for (srv = rd->views.first; srv; srv = srv->next) { - if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) - continue; - image_add_view(ima, srv->name, ""); + if ((rd->scemode & R_MULTIVIEW) == 0) { + image_add_view(ima, "", ""); + } + else { + SceneRenderView *srv; + for (srv = rd->views.first; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) + continue; + image_add_view(ima, srv->name, ""); + } } } -- cgit v1.2.3 From 09a746b857452705a152b3e9acadc39d884de8c3 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 8 Apr 2015 01:13:16 +0500 Subject: Cycles: Cleanup, typos --- intern/cycles/kernel/geom/geom_triangle_intersect.h | 8 ++++---- intern/cycles/render/graph.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index d867a193beb..a0e36058bf8 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -77,10 +77,10 @@ void triangle_intersect_precalc(float3 dir, } /* Calculate the shear constants. */ - float inf_dir_z = 1.0f / IDX(dir, kz); - isect_precalc->Sx = IDX(dir, kx) * inf_dir_z; - isect_precalc->Sy = IDX(dir, ky) * inf_dir_z; - isect_precalc->Sz = inf_dir_z; + float inv_dir_z = 1.0f / IDX(dir, kz); + isect_precalc->Sx = IDX(dir, kx) * inv_dir_z; + isect_precalc->Sy = IDX(dir, ky) * inv_dir_z; + isect_precalc->Sz = inv_dir_z; /* Store the dimensions. */ isect_precalc->kx = kx; diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 4767bbb4806..b63a7c1bc68 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -892,7 +892,7 @@ void ShaderGraph::dump_graph(const char *filename) input, output->name, input->name); fprintf(fd, - "\"\%p\":\"OUT_%p\":e -> \"%p\":\"IN_%p\":w [label=\"\"]\n", + "\"%p\":\"OUT_%p\":e -> \"%p\":\"IN_%p\":w [label=\"\"]\n", output->parent, output, input->parent, -- cgit v1.2.3 From c89637be306b0c6bc23c40e9f764ac53159e1214 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 8 Apr 2015 06:28:05 +1000 Subject: BGE: use tuple for returning display size --- source/gameengine/Ketsji/KX_PythonInit.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 420e0be8c5d..f7048f10783 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -51,6 +51,8 @@ # include extern "C" { + # include "BLI_utildefines.h" + # include "python_utildefines.h" # include "bpy_internal_import.h" /* from the blender python api, but we want to import text too! */ # include "py_capi_utils.h" # include "mathutils.h" // 'mathutils' module copied here so the blenderlayer can use. @@ -1405,16 +1407,17 @@ static PyObject *gPyClearDebugList(PyObject *) static PyObject *gPyGetDisplayDimensions(PyObject *) { - PyObject *list = PyList_New(0); - int width; - int height; + PyObject *result; + int width, height; gp_Canvas->GetDisplayDimensions(width, height); - PyList_Append(list, PyLong_FromLong(width)); - PyList_Append(list, PyLong_FromLong(height)); + result = PyTuple_New(2); + PyTuple_SET_ITEMS(result, + PyLong_FromLong(width), + PyLong_FromLong(height)); - return list; + return result; } PyDoc_STRVAR(Rasterizer_module_documentation, -- cgit v1.2.3 From 796c3c774820edf70572a6717ceb6c188a267577 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 8 Apr 2015 06:50:38 +1000 Subject: Fix T44290: Clear users & fake-user conflict The purpose of clearing users in this case is not to save the data, so keeping fake-user doesn't make sense. --- source/blender/editors/interface/interface_templates.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index c4158fe2a17..c36d25b8030 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -273,8 +273,11 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) RNA_property_pointer_set(&template->ptr, template->prop, idptr); RNA_property_update(C, &template->ptr, template->prop); - if (id && CTX_wm_window(C)->eventstate->shift) /* useful hidden functionality, */ + if (id && CTX_wm_window(C)->eventstate->shift) { + /* only way to force-remove data (on save) */ + id->flag &= ~LIB_FAKEUSER; id->us = 0; + } break; case UI_ID_FAKE_USER: -- cgit v1.2.3 From 7e52d810f3a1b6ba8732eb7ccab11ecf9cfbb09f Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 8 Apr 2015 00:28:03 +0200 Subject: Muliview: Minor UI-tweaks * Don't grey multiview options in file browser and in Node Editor Properties out if multi-view is disabled, hide them completely (I think greying out single buttons is fine, but in case of entire blocks we should just hide to save space) * Move multiview settings in Node Editor Properties above alpha settings to prevent the alpha buttons from appearing above multiview settings if multiview is enabled and Stereo 3D format is chosen (making them appear below is much nicer) --- source/blender/editors/space_image/image_buttons.c | 54 +++++++++------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index a02f64d68d8..ee298a27b25 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -896,6 +896,14 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char BKE_image_release_ibuf(ima, ibuf, NULL); } + if ((scene->r.scemode & R_MULTIVIEW) != 0) { + uiItemR(layout, &imaptr, "use_multiview", 0, NULL, ICON_NONE); + + if (RNA_boolean_get(&imaptr, "use_multiview")) { + uiTemplateImageViews(layout, &imaptr); + } + } + if (has_alpha) { col = uiLayoutColumn(layout, false); uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE); @@ -904,24 +912,11 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char uiItemR(row, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE); } - if ((scene->r.scemode & R_MULTIVIEW) != 0) { - uiItemS(layout); - - col = uiLayoutColumn(layout, false); - uiItemR(col, &imaptr, "use_multiview", 0, NULL, ICON_NONE); - - col = uiLayoutColumn(layout, false); - uiLayoutSetActive(col, RNA_boolean_get(&imaptr, "use_multiview")); - uiTemplateImageViews(col, &imaptr); - } - if (ima->source == IMA_SRC_MOVIE) { col = uiLayoutColumn(layout, false); uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE); } - uiItemS(layout); - split = uiLayoutSplit(layout, 0.0f, false); col = uiLayoutColumn(split, false); @@ -1155,28 +1150,25 @@ void uiTemplateImageViews(uiLayout *layout, PointerRNA *imaptr) void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA *ptr) { ImageFormatData *imf = imfptr->data; - uiLayout *col; - if (ptr) { - uiItemR(layout, ptr, "use_multiview", 0, NULL, ICON_NONE); - col = uiLayoutColumn(layout, false); - uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_multiview")); - } - else { - col = uiLayoutColumn(layout, false); - } + if (ptr == NULL) + return; - if (imf->imtype != R_IMF_IMTYPE_MULTILAYER) { - PropertyRNA *prop; - PointerRNA stereo3d_format_ptr; + uiItemR(layout, ptr, "use_multiview", 0, NULL, ICON_NONE); - prop = RNA_struct_find_property(imfptr, "stereo_3d_format"); - stereo3d_format_ptr = RNA_property_pointer_get(imfptr, prop); + if (RNA_boolean_get(ptr, "use_multiview")) { + if (imf->imtype != R_IMF_IMTYPE_MULTILAYER) { + PropertyRNA *prop; + PointerRNA stereo3d_format_ptr; - uiTemplateViewsFormat(col, imfptr, &stereo3d_format_ptr); - } - else { - uiTemplateViewsFormat(col, imfptr, NULL); + prop = RNA_struct_find_property(imfptr, "stereo_3d_format"); + stereo3d_format_ptr = RNA_property_pointer_get(imfptr, prop); + + uiTemplateViewsFormat(layout, imfptr, &stereo3d_format_ptr); + } + else { + uiTemplateViewsFormat(layout, imfptr, NULL); + } } } -- cgit v1.2.3 From a57b898d1760ade693983d1fd080399ab5e3367f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 8 Apr 2015 09:45:41 +1000 Subject: BLF: Fix clamping drawing into byte buffer --- source/blender/blenfont/intern/blf_font.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 087c7c7345e..1391e18748c 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -375,8 +375,8 @@ void blf_font_buffer(FontBLF *font, const char *str) if (buf_info->cbuf) { int yb = yb_start; - for (y = 0; y < height_clip; y++) { - for (x = 0; x < width_clip; x++) { + for (y = ((chy >= 0) ? 0 : -chy); y < height_clip; y++) { + for (x = ((chx >= 0) ? 0 : -chx); x < width_clip; x++) { a = *(g->bitmap + x + (yb * g->pitch)) / 255.0f; if (a > 0.0f) { -- cgit v1.2.3 From a2ea4ce70da8562ec2671070eccf46b5bee1f66c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 8 Apr 2015 07:35:53 +1000 Subject: Cleanup: IMB/thumb naming --- source/blender/imbuf/IMB_thumbs.h | 6 ++---- source/blender/imbuf/intern/thumbs.c | 2 +- source/blender/imbuf/intern/thumbs_blend.c | 4 ++-- source/blender/windowmanager/intern/wm_files.c | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h index 9fc075e4e8b..bea531c1442 100644 --- a/source/blender/imbuf/IMB_thumbs.h +++ b/source/blender/imbuf/IMB_thumbs.h @@ -60,8 +60,6 @@ typedef enum ThumbSource { /* don't generate thumbs for images bigger then this (100mb) */ #define THUMB_SIZE_MAX (100 * 1024 * 1024) -// IB_metadata - /* create thumbnail for file and returns new imbuf for thumbnail */ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, ImBuf *ibuf); @@ -78,8 +76,8 @@ ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source); void IMB_thumb_makedirs(void); /* special function for loading a thumbnail embedded into a blend file */ -ImBuf *IMB_loadblend_thumb(const char *path); -void IMB_overlayblend_thumb(unsigned int *thumb, int width, int height, float aspect); +ImBuf *IMB_thumb_load_blend(const char *path); +void IMB_thumb_overlay_blend(unsigned int *thumb, int width, int height, float aspect); #ifdef __cplusplus } diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 21f440a8232..e88cbef206a 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -335,7 +335,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im /* only load if we didnt give an image */ if (img == NULL) { if (THB_SOURCE_BLEND == source) { - img = IMB_loadblend_thumb(path); + img = IMB_thumb_load_blend(path); } else { img = IMB_loadiffname(path, IB_rect | IB_metadata | IB_thumbnail, NULL); diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c index aee465c49cc..d7b9089c437 100644 --- a/source/blender/imbuf/intern/thumbs_blend.c +++ b/source/blender/imbuf/intern/thumbs_blend.c @@ -121,7 +121,7 @@ static ImBuf *loadblend_thumb(gzFile gzfile) return NULL; } -ImBuf *IMB_loadblend_thumb(const char *path) +ImBuf *IMB_thumb_load_blend(const char *path) { gzFile gzfile; /* not necessarily a gzip */ @@ -143,7 +143,7 @@ ImBuf *IMB_loadblend_thumb(const char *path) /* add a fake passepartout overlay to a byte buffer, use for blend file thumbnails */ #define MARGIN 2 -void IMB_overlayblend_thumb(unsigned int *thumb, int width, int height, float aspect) +void IMB_thumb_overlay_blend(unsigned int *thumb, int width, int height, float aspect) { unsigned char *px = (unsigned char *)thumb; int margin_l = MARGIN; diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index f3e9c416e7b..fdad108d44d 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -860,7 +860,7 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt) IMB_scaleImBuf(ibuf, BLEN_THUMB_SIZE, BLEN_THUMB_SIZE); /* add pretty overlay */ - IMB_overlayblend_thumb(ibuf->rect, ibuf->x, ibuf->y, aspect); + IMB_thumb_overlay_blend(ibuf->rect, ibuf->x, ibuf->y, aspect); /* first write into thumb buffer */ thumb = MEM_mallocN(((2 + (BLEN_THUMB_SIZE * BLEN_THUMB_SIZE))) * sizeof(int), "write_file thumb"); -- cgit v1.2.3 From c56c493cf403b63ec46b90023cdc8137275a310f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 8 Apr 2015 10:29:37 +1000 Subject: BLF: use regular unsigned int's So GL isnt needed to include BLF types. --- source/blender/blenfont/intern/blf_internal_types.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index da756d65483..1404b9de250 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -48,7 +48,7 @@ typedef struct GlyphCacheBLF { struct GlyphBLF *glyph_ascii_table[256]; /* texture array, to draw the glyphs. */ - GLuint *textures; + unsigned int *textures; /* size of the array. */ unsigned int ntex; @@ -103,7 +103,7 @@ typedef struct GlyphBLF { int advance_i; /* texture id where this glyph is store. */ - GLuint tex; + unsigned int tex; /* position inside the texture where this glyph is store. */ int xoff; -- cgit v1.2.3 From 8c539b0ab521d442d88c70243c04cbb9e40fe412 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 8 Apr 2015 10:10:17 +1000 Subject: Font preview for file browser D1002 by @plasmasolutions, with own refactoring. Note, needed to do a bad-level call here (IMB -> BLF) Also can't use the BLF API directly because its not thread-safe. So keep the function isolated (blf_thumbs.c). --- source/blender/blenfont/BLF_api.h | 6 ++ source/blender/blenfont/CMakeLists.txt | 1 + source/blender/blenfont/intern/blf_thumbs.c | 104 ++++++++++++++++++++++++++ source/blender/editors/space_file/file_draw.c | 17 +++-- source/blender/editors/space_file/filelist.c | 7 +- source/blender/imbuf/CMakeLists.txt | 1 + source/blender/imbuf/IMB_thumbs.h | 8 +- source/blender/imbuf/intern/thumbs.c | 19 +++-- source/blender/imbuf/intern/thumbs_font.c | 73 ++++++++++++++++++ 9 files changed, 222 insertions(+), 14 deletions(-) create mode 100644 source/blender/blenfont/intern/blf_thumbs.c create mode 100644 source/blender/imbuf/intern/thumbs_font.c diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index 206345582b2..09734bd9754 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -186,6 +186,12 @@ char **BLF_dir_get(int *ndir) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); /* Free the data return by BLF_dir_get. */ void BLF_dir_free(char **dirs, int count) ATTR_NONNULL(); +/* blf_thumbs.c */ +void BLF_thumb_preview( + const char *filename, const char **draw_str, const unsigned char draw_str_lines, + const float font_color[4], const int font_size, + unsigned char *buf, int w, int h, int channels) ATTR_NONNULL(); + #ifdef DEBUG void BLF_state_print(int fontid); #endif diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt index 392a9ede100..2f10c3580e0 100644 --- a/source/blender/blenfont/CMakeLists.txt +++ b/source/blender/blenfont/CMakeLists.txt @@ -47,6 +47,7 @@ set(SRC intern/blf_font.c intern/blf_glyph.c intern/blf_lang.c + intern/blf_thumbs.c intern/blf_translation.c intern/blf_util.c diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c new file mode 100644 index 00000000000..afda6a382f9 --- /dev/null +++ b/source/blender/blenfont/intern/blf_thumbs.c @@ -0,0 +1,104 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Thomas Beck + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenfont/intern/blf_thumbs.c + * \ingroup blf + * + * Utility function to generate font preview images. + * + * Isolate since this needs to be called by #ImBuf code (bad level call). + */ + +#include +#include +#include + +#include + +#include FT_FREETYPE_H + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_rect.h" +#include "BLI_threads.h" + +#include "blf_internal.h" +#include "blf_internal_types.h" + +#include "BLF_api.h" + +#include "BLI_strict_flags.h" + +/** + * This function is used for generating thumbnail previews. + * + * \note called from a thread, so it bypasses the normal BLF_* api (which isn't thread-safe). + */ +void BLF_thumb_preview( + const char *filename, + const char **draw_str, const unsigned char draw_str_lines, + const float font_color[4], const int font_size, + unsigned char *buf, int w, int h, int channels) +{ + const unsigned int dpi = 72; + const int font_size_min = 6; + int font_size_curr; + /* shrink 1/th each line */ + int font_shrink = 4; + + FontBLF* font; + int i; + + /* Create a new blender font obj and fill it with default values */ + font = blf_font_new("thumb_font", filename); + if (!font) { + printf("Info: Can't load font '%s', no preview possible\n", filename); + return; + } + + /* Would be done via the BLF API, but we're not using a fontid here */ + font->buf_info.cbuf = buf; + font->buf_info.ch = channels; + font->buf_info.w = w; + font->buf_info.h = h; + + /* Always create the image with a white font, + * the caller can theme how it likes */ + memcpy(font->buf_info.col, font_color, sizeof(font->buf_info.col)); + font->pos[1] = (float)h; + + font_size_curr = font_size; + + for (i = 0; i < draw_str_lines; i++) { + blf_font_size(font, (unsigned int)MAX2(font_size_min, font_size_curr), dpi); + + /* decrease font size each time */ + font_size_curr -= (font_size_curr / font_shrink); + font_shrink += 1; + + font->pos[1] -= font->glyph_cache->ascender * 1.1f; + + blf_font_buffer(font, draw_str[i]); + } + + blf_font_free(font); +} diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 98c7ddeff77..a6f3a73841e 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -323,7 +323,7 @@ void file_calc_previews(const bContext *C, ARegion *ar) UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height); } -static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int sy, ImBuf *imb, FileLayout *layout, bool dropshadow, bool drag) +static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int sy, ImBuf *imb, FileLayout *layout, bool is_icon, bool drag) { uiBut *but; float fx, fy; @@ -332,6 +332,7 @@ static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int float scaledx, scaledy; float scale; int ex, ey; + bool use_dropshadow = !is_icon && (file->flags & FILE_TYPE_IMAGE); BLI_assert(imb != NULL); @@ -367,17 +368,23 @@ static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* shadow */ - if (dropshadow) + if (use_dropshadow) { UI_draw_box_shadow(220, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey)); + } glEnable(GL_BLEND); /* the image */ - glColor4f(1.0, 1.0, 1.0, 1.0); + if (!is_icon && file->flags & FILE_TYPE_FTFONT) { + UI_ThemeColor(TH_TEXT); + } + else { + glColor4f(1.0, 1.0, 1.0, 1.0); + } glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect, scale, scale); /* border */ - if (dropshadow) { + if (use_dropshadow) { glColor4f(0.0f, 0.0f, 0.0f, 0.4f); fdrawbox((float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey)); } @@ -549,7 +556,7 @@ void file_draw_list(const bContext *C, ARegion *ar) is_icon = 1; } - file_draw_preview(block, file, sx, sy, imb, layout, !is_icon && (file->flags & FILE_TYPE_IMAGE), do_drag); + file_draw_preview(block, file, sx, sy, imb, layout, is_icon, do_drag); } else { file_draw_icon(block, file->path, sx, sy - (UI_UNIT_Y / 6), get_file_icon(file), ICON_DEFAULT_WIDTH_SCALE, ICON_DEFAULT_HEIGHT_SCALE, do_drag); diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 66acd7d05e3..5214b611fb9 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -1348,6 +1348,9 @@ static void thumbnails_startjob(void *tjv, short *stop, short *do_update, float limg->flags |= FILE_TYPE_MOVIE_ICON; } } + else if (limg->flags & FILE_TYPE_FTFONT) { + limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_FONT); + } *do_update = true; PIL_sleep_ms(10); limg = limg->next; @@ -1363,7 +1366,7 @@ static void thumbnails_update(void *tjv) while (limg) { if (!limg->done && limg->img) { tj->filelist->filelist[limg->index].image = IMB_dupImBuf(limg->img); - /* update flag for movie files where thumbnail can't be created */ + /* update flag for movie and font files where thumbnail can't be created */ if (limg->flags & FILE_TYPE_MOVIE_ICON) { tj->filelist->filelist[limg->index].flags &= ~FILE_TYPE_MOVIE; tj->filelist->filelist[limg->index].flags |= FILE_TYPE_MOVIE_ICON; @@ -1408,7 +1411,7 @@ void thumbnails_start(FileList *filelist, const bContext *C) continue; } if (!filelist->filelist[idx].image) { - if (filelist->filelist[idx].flags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | + if (filelist->filelist[idx].flags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { FileImage *limg = MEM_callocN(sizeof(*limg), __func__); diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt index eadedbd5e00..bdd8230a6ff 100644 --- a/source/blender/imbuf/CMakeLists.txt +++ b/source/blender/imbuf/CMakeLists.txt @@ -66,6 +66,7 @@ set(SRC intern/targa.c intern/thumbs.c intern/thumbs_blend.c + intern/thumbs_font.c intern/util.c intern/writeimage.c diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h index bea531c1442..404052f2e8e 100644 --- a/source/blender/imbuf/IMB_thumbs.h +++ b/source/blender/imbuf/IMB_thumbs.h @@ -54,7 +54,8 @@ typedef enum ThumbSize { typedef enum ThumbSource { THB_SOURCE_IMAGE, THB_SOURCE_MOVIE, - THB_SOURCE_BLEND + THB_SOURCE_BLEND, + THB_SOURCE_FONT, } ThumbSource; /* don't generate thumbs for images bigger then this (100mb) */ @@ -79,6 +80,11 @@ void IMB_thumb_makedirs(void); ImBuf *IMB_thumb_load_blend(const char *path); void IMB_thumb_overlay_blend(unsigned int *thumb, int width, int height, float aspect); +/* special function for previewing fonts */ +ImBuf *IMB_thumb_load_font( + const char *filename, + unsigned int x, unsigned int y); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index e88cbef206a..78f47b7bc34 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -330,15 +330,22 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im if (!img) return NULL; } else { - if (THB_SOURCE_IMAGE == source || THB_SOURCE_BLEND == source) { + if (ELEM(source, THB_SOURCE_IMAGE, THB_SOURCE_BLEND, THB_SOURCE_FONT)) { /* only load if we didnt give an image */ if (img == NULL) { - if (THB_SOURCE_BLEND == source) { - img = IMB_thumb_load_blend(path); - } - else { - img = IMB_loadiffname(path, IB_rect | IB_metadata | IB_thumbnail, NULL); + switch (source) { + case THB_SOURCE_IMAGE: + img = IMB_loadiffname(path, IB_rect | IB_metadata, NULL); + break; + case THB_SOURCE_BLEND: + img = IMB_thumb_load_blend(path); + break; + case THB_SOURCE_FONT: + img = IMB_thumb_load_font(path, tsize, tsize); + break; + default: + BLI_assert(0); /* This should never happen */ } } diff --git a/source/blender/imbuf/intern/thumbs_font.c b/source/blender/imbuf/intern/thumbs_font.c new file mode 100644 index 00000000000..c8982318d80 --- /dev/null +++ b/source/blender/imbuf/intern/thumbs_font.c @@ -0,0 +1,73 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Thomas Beck. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/imbuf/intern/thumbs_font.c + * \ingroup imbuf + */ + +#include "BLI_utildefines.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#include "IMB_thumbs.h" + + +/* XXX, bad level call */ +#include "../../blenfont/BLF_api.h" + + +struct ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y) +{ + const int font_size = y / 4; + const char *thumb_str[] = { + "AaBbCc", + + "The quick", + "brown fox", + "jumps over", + "the lazy dog", + }; + + struct ImBuf *ibuf; + float font_color[4]; + + /* create a white image (theme color is used for drawing) */ + font_color[0] = font_color[1] = font_color[2] = 1.0f; + + /* fill with zero alpha */ + font_color[3] = 0.0f; + + ibuf = IMB_allocImBuf(x, y, 32, IB_rect | IB_metadata); + IMB_rectfill(ibuf, font_color); + + /* draw with full alpha */ + font_color[3] = 1.0f; + + BLF_thumb_preview( + filename, thumb_str, ARRAY_SIZE(thumb_str), + font_color, font_size, + (unsigned char *)ibuf->rect, ibuf->x, ibuf->y, ibuf->channels); + + return ibuf; +} + -- cgit v1.2.3 From ccfb9a96c346eb8df95775b34ae5388fa5fcacb1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 8 Apr 2015 11:50:57 +1000 Subject: CMake: resolve linking error on Linux Since multiview, matrixGlyph failed to link --- build_files/cmake/macros.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index e23d2c6a07c..8b2f3f18215 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -516,11 +516,11 @@ macro(SETUP_BLENDER_SORTED_LIBS) bf_ikplugin bf_modifiers bf_bmesh + bf_gpu bf_blenkernel bf_physics bf_nodes bf_rna - bf_gpu bf_blenloader bf_imbuf bf_blenlib -- cgit v1.2.3 From 808ea6271a0107cc3df52fb0ef18ccec191f6f15 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 8 Apr 2015 12:23:38 +1000 Subject: Cleanup: confusing if statements & alignment --- intern/ghost/intern/GHOST_SystemWin32.cpp | 4 ++-- source/blender/blenkernel/intern/sequencer.c | 19 ++++++---------- .../blender/blenloader/intern/versioning_legacy.c | 24 +++++++------------- .../operations/COM_GlareGhostOperation.cpp | 2 +- .../blender/editors/interface/interface_widgets.c | 8 +++---- .../editors/space_sequencer/sequencer_scopes.c | 26 +++++++++++----------- source/blender/render/intern/source/pipeline.c | 6 ++--- 7 files changed, 38 insertions(+), 51 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 038e6a03c7d..46ed8bbe1fc 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -714,8 +714,8 @@ GHOST_EventWheel *GHOST_SystemWin32::processWheelEvent(GHOST_WindowWin32 *window // zDelta /= WHEEL_DELTA; // temporary fix below: microsoft now has added more precision, making the above division not work - if (zDelta <= 0) zDelta = -1; else zDelta = 1; - + zDelta = (zDelta <= 0) ? -1 : 1; + // short xPos = (short) LOWORD(lParam); // horizontal position of pointer // short yPos = (short) HIWORD(lParam); // vertical position of pointer return new GHOST_EventWheel(getSystem()->getMilliSeconds(), window, zDelta); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 4cea8aa0b85..2fde98cce74 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1161,30 +1161,25 @@ static void make_black_ibuf(ImBuf *ibuf) } } -static void multibuf(ImBuf *ibuf, float fmul) +static void multibuf(ImBuf *ibuf, const float fmul) { char *rt; float *rt_float; - int a, mul, icol; + int a; - mul = (int)(256.0f * fmul); rt = (char *)ibuf->rect; rt_float = ibuf->rect_float; if (rt) { + const int imul = (int)(256.0f * fmul); a = ibuf->x * ibuf->y; while (a--) { + rt[0] = min_ii((imul * rt[0]) >> 8, 255); + rt[1] = min_ii((imul * rt[1]) >> 8, 255); + rt[2] = min_ii((imul * rt[2]) >> 8, 255); + rt[3] = min_ii((imul * rt[3]) >> 8, 255); - icol = (mul * rt[0]) >> 8; - if (icol > 254) rt[0] = 255; else rt[0] = icol; - icol = (mul * rt[1]) >> 8; - if (icol > 254) rt[1] = 255; else rt[1] = icol; - icol = (mul * rt[2]) >> 8; - if (icol > 254) rt[2] = 255; else rt[2] = icol; - icol = (mul * rt[3]) >> 8; - if (icol > 254) rt[3] = 255; else rt[3] = icol; - rt += 4; } } diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 5dae6fbc464..94ad348bfcf 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -795,22 +795,14 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) nr = me->totface; tface = me->tface; while (nr--) { - cp = (char *)&tface->col[0]; - if (cp[1] > 126) cp[1] = 255; else cp[1] *= 2; - if (cp[2] > 126) cp[2] = 255; else cp[2] *= 2; - if (cp[3] > 126) cp[3] = 255; else cp[3] *= 2; - cp = (char *)&tface->col[1]; - if (cp[1] > 126) cp[1] = 255; else cp[1] *= 2; - if (cp[2] > 126) cp[2] = 255; else cp[2] *= 2; - if (cp[3] > 126) cp[3] = 255; else cp[3] *= 2; - cp = (char *)&tface->col[2]; - if (cp[1] > 126) cp[1] = 255; else cp[1] *= 2; - if (cp[2] > 126) cp[2] = 255; else cp[2] *= 2; - if (cp[3] > 126) cp[3] = 255; else cp[3] *= 2; - cp = (char *)&tface->col[3]; - if (cp[1] > 126) cp[1] = 255; else cp[1] *= 2; - if (cp[2] > 126) cp[2] = 255; else cp[2] *= 2; - if (cp[3] > 126) cp[3] = 255; else cp[3] *= 2; + int j; + for (j = 0; j < 4; j++) { + int k; + cp = ((char *)&tface->col[j]) + 1; + for (k = 0; k < 3; k++) { + cp[k] = (cp[k] > 126) ? 255 : cp[k] * 2; + } + } tface++; } diff --git a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp index 69b5bd7d6bf..eea6588a9a6 100644 --- a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp @@ -65,7 +65,7 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No if (isBreaked()) breaked = true; if (!breaked) FastGaussianBlurOperation::IIR_gauss(tbuf2, s2, 2, 3); - if (settings->iter & 1) ofs = 0.5f; else ofs = 0.f; + ofs = (settings->iter & 1) ? 0.5f : 0.0f; for (x = 0; x < (settings->iter * 4); x++) { y = x & 3; cm[x][0] = cm[x][1] = cm[x][2] = 1; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 1cf78e68315..51a98231c8b 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -602,10 +602,10 @@ static void round_box_shade_col4_r(unsigned char r_col[4], const char col1[4], c const int faci = FTOCHAR(fac); const int facm = 255 - faci; - r_col[0] = (faci * col1[0] + facm * col2[0]) >> 8; - r_col[1] = (faci * col1[1] + facm * col2[1]) >> 8; - r_col[2] = (faci * col1[2] + facm * col2[2]) >> 8; - r_col[3] = (faci * col1[3] + facm * col2[3]) >> 8; + r_col[0] = (faci * col1[0] + facm * col2[0]) / 256; + r_col[1] = (faci * col1[1] + facm * col2[1]) / 256; + r_col[2] = (faci * col1[2] + facm * col2[2]) / 256; + r_col[3] = (faci * col1[3] + facm * col2[3]) / 256; } static void widget_verts_to_triangle_strip(uiWidgetBase *wtb, const int totvert, float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]) diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index b4bcfb4eb07..404671cac84 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -648,13 +648,13 @@ static ImBuf *make_vectorscope_view_from_ibuf_byte(ImBuf *ibuf) wtable[x] = (unsigned char) (pow(((float) x + 1) / 256, scope_gamma) * 255); } - for (x = 0; x <= 255; x++) { - vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1); - vectorscope_put_cross(255, x, 0, tgt, w, h, 1); - vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1); - vectorscope_put_cross(0, 255, x, tgt, w, h, 1); - vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1); - vectorscope_put_cross(x, 0, 255, tgt, w, h, 1); + for (x = 0; x < 256; x++) { + vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1); + vectorscope_put_cross(255, x, 0, tgt, w, h, 1); + vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1); + vectorscope_put_cross(0, 255, x, tgt, w, h, 1); + vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1); + vectorscope_put_cross(x, 0, 255, tgt, w, h, 1); } for (y = 0; y < ibuf->y; y++) { @@ -695,12 +695,12 @@ static ImBuf *make_vectorscope_view_from_ibuf_float(ImBuf *ibuf) } for (x = 0; x <= 255; x++) { - vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1); - vectorscope_put_cross(255, x, 0, tgt, w, h, 1); - vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1); - vectorscope_put_cross(0, 255, x, tgt, w, h, 1); - vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1); - vectorscope_put_cross(x, 0, 255, tgt, w, h, 1); + vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1); + vectorscope_put_cross(255, x, 0, tgt, w, h, 1); + vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1); + vectorscope_put_cross(0, 255, x, tgt, w, h, 1); + vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1); + vectorscope_put_cross(x, 0, 255, tgt, w, h, 1); } for (y = 0; y < ibuf->y; y++) { diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 4a767184c44..05bee6f165a 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2249,9 +2249,9 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) for (x = 0; x < re->rectx; x++, rf += 4, col += 4) { /* clamping to 1.0 is needed for correct AA */ - if (col[0] < 0.0f) col[0] = 0.0f; else if (col[0] > 1.0f) col[0] = 1.0f; - if (col[1] < 0.0f) col[1] = 0.0f; else if (col[1] > 1.0f) col[1] = 1.0f; - if (col[2] < 0.0f) col[2] = 0.0f; else if (col[2] > 1.0f) col[2] = 1.0f; + CLAMP(col[0], 0.0, 1.0f); + CLAMP(col[1], 0.0, 1.0f); + CLAMP(col[2], 0.0, 1.0f); add_filt_fmask_coord(filt, col, rf, re->rectx, re->recty, x, y); } -- cgit v1.2.3 From 1492db09d196fa60b063eea2847738d79069c7e0 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 8 Apr 2015 14:17:36 +1200 Subject: Partial fixes for issues raised in T44219 * The breakdowner tool will no longer operate directly on properties of type "enum", as this doesn't make sense most of the time. This is still not much use though when custom properties (ints) are used to drive some underlying enum property though (as in blenrig) * The breakdowner no longer tries to perform any blending if the start and end values are the same, to avoid float precision issues. --- source/blender/editors/armature/pose_slide.c | 36 ++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index 09c8b4c370c..a863dae045c 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -201,6 +201,12 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, float *val) /* next/end */ eVal = evaluate_fcurve(fcu, (float)pso->nextFrame); + /* if both values are equal, don't do anything */ + if (IS_EQ(sVal, eVal)) { + (*val) = sVal; + return; + } + /* calculate the relative weights of the endpoints */ if (pso->mode == POSESLIDE_BREAKDOWN) { /* get weights from the percentage control */ @@ -234,7 +240,7 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, float *val) * - perform this weighting a number of times given by the percentage... */ int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */ - + while (iters-- > 0) { (*val) = (-((sVal * w2) + (eVal * w1)) + ((*val) * 6.0f) ) / 5.0f; } @@ -247,7 +253,7 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, float *val) * - perform this weighting a number of times given by the percentage... */ int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */ - + while (iters-- > 0) { (*val) = ( ((sVal * w2) + (eVal * w1)) + ((*val) * 5.0f) ) / 6.0f; } @@ -320,6 +326,7 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl) if (prop) { switch (RNA_property_type(prop)) { + /* continuous values that can be smoothly interpolated... */ case PROP_FLOAT: { float tval = RNA_property_float_get(&ptr, prop); @@ -327,8 +334,6 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl) RNA_property_float_set(&ptr, prop, tval); break; } - case PROP_BOOLEAN: - case PROP_ENUM: case PROP_INT: { float tval = (float)RNA_property_int_get(&ptr, prop); @@ -336,6 +341,23 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl) RNA_property_int_set(&ptr, prop, (int)tval); break; } + + /* values which can only take discrete values */ + case PROP_BOOLEAN: + { + float tval = (float)RNA_property_boolean_get(&ptr, prop); + pose_slide_apply_val(pso, fcu, &tval); + RNA_property_boolean_set(&ptr, prop, (int)tval); // XXX: do we need threshold clamping here? + break; + } + case PROP_ENUM: + { + /* don't handle this case - these don't usually represent interchangeable + * set of values which should be interpolated between + */ + break; + } + default: /* cannot handle */ //printf("Cannot Pose Slide non-numerical property\n"); @@ -404,11 +426,11 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl) } else if (pso->mode == POSESLIDE_PUSH) { float quat_diff[4], quat_orig[4]; - + /* calculate the delta transform from the previous to the current */ /* TODO: investigate ways to favour one transform more? */ sub_qt_qtqt(quat_diff, pchan->quat, quat_prev); - + /* make a copy of the original rotation */ copy_qt_qt(quat_orig, pchan->quat); @@ -418,7 +440,7 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl) else { float quat_interp[4], quat_orig[4]; int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */ - + /* perform this blending several times until a satisfactory result is reached */ while (iters-- > 0) { /* calculate the interpolation between the endpoints */ -- cgit v1.2.3 From 441f68e2b08c7b55e69128ebf715e4bae2ac29d5 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 8 Apr 2015 14:27:17 +1200 Subject: Partial fix for T44219 Prevent crashes from out of bounds array access if an invalid rotation mode is passed to the euler rotation blenlib calculations. --- source/blender/blenlib/intern/math_rotation.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 7706e8e8e49..1f0d68b09b2 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -1323,12 +1323,21 @@ static const RotOrderInfo rotOrders[] = { * NOTE: since we start at 1 for the values, but arrays index from 0, * there is -1 factor involved in this process... */ -#define GET_ROTATIONORDER_INFO(order) (assert(order >= 0 && order <= 6), (order < 1) ? &rotOrders[0] : &rotOrders[(order) - 1]) +static const RotOrderInfo *get_rotation_order_info(const short order) +{ + assert(order >= 0 && order <= 6); + if (order < 1) + return &rotOrders[0]; + else if (order < 6) + return &rotOrders[order - 1]; + else + return &rotOrders[5]; +} /* Construct quaternion from Euler angles (in radians). */ void eulO_to_quat(float q[4], const float e[3], const short order) { - const RotOrderInfo *R = GET_ROTATIONORDER_INFO(order); + const RotOrderInfo *R = get_rotation_order_info(order); short i = R->axis[0], j = R->axis[1], k = R->axis[2]; double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss; double a[3]; @@ -1373,7 +1382,7 @@ void quat_to_eulO(float e[3], short const order, const float q[4]) /* Construct 3x3 matrix from Euler angles (in radians). */ void eulO_to_mat3(float M[3][3], const float e[3], const short order) { - const RotOrderInfo *R = GET_ROTATIONORDER_INFO(order); + const RotOrderInfo *R = get_rotation_order_info(order); short i = R->axis[0], j = R->axis[1], k = R->axis[2]; double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss; @@ -1414,7 +1423,7 @@ void eulO_to_mat3(float M[3][3], const float e[3], const short order) /* returns two euler calculation methods, so we can pick the best */ static void mat3_to_eulo2(float M[3][3], float eul1[3], float eul2[3], const short order) { - const RotOrderInfo *R = GET_ROTATIONORDER_INFO(order); + const RotOrderInfo *R = get_rotation_order_info(order); short i = R->axis[0], j = R->axis[1], k = R->axis[2]; float mat[3][3]; float cy; @@ -1550,7 +1559,7 @@ void rotate_eulO(float beul[3], const short order, char axis, float ang) /* the matrix is written to as 3 axis vectors */ void eulO_to_gimbal_axis(float gmat[3][3], const float eul[3], const short order) { - const RotOrderInfo *R = GET_ROTATIONORDER_INFO(order); + const RotOrderInfo *R = get_rotation_order_info(order); float mat[3][3]; float teul[3]; -- cgit v1.2.3 From f5648f6db9f4549d9e3220f89361e5f76e5b2b2a Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Wed, 8 Apr 2015 06:44:39 +0200 Subject: BGE : Fix T36285 Wrong viewport scale. Fix of T36285, I just invalidate projection matrix when a camera switch to viewport mode, because we need to rewrite the projection matrix in RenderFrame. It worked with old blender version because when you use viewport render one camera is added in the camera list and initialize its projection matrix for the first time. But when we used several cameras + viewport for splitscreen we had issues. Reviewers: dfelinto, hg1, ben2610, lordloki, moguri Reviewed By: moguri Projects: #game_rendering, #game_engine Differential Revision: https://developer.blender.org/D1202 --- source/gameengine/Ketsji/KX_Camera.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index ce2fe5f5ad8..4dbaddcaa47 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -463,6 +463,7 @@ bool KX_Camera::GetFrustumCulling() const void KX_Camera::EnableViewport(bool viewport) { + InvalidateProjectionMatrix(false); // We need to reset projection matrix m_camdata.m_viewport = viewport; } -- cgit v1.2.3 From 796b17b8439eb883c892dbc3896a2d8a62af2b43 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Wed, 8 Apr 2015 01:59:24 -0300 Subject: Multiview: Fullscreen modes (sidebyside/topbottom) were not working * WM_window_is_fullscreen() is not the correct test. * Also, we no longer change window to fullscreen automatically. --- source/blender/windowmanager/intern/wm_stereo.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 44d0e81e93c..9e9a9739cc0 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -365,8 +365,9 @@ bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check) if ((skip_stereo3d_check == false) && (ED_screen_stereo3d_required(screen) == false)) return false; - if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) - return WM_window_is_fullscreen(win); + if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) { + return (GHOST_GetWindowState(win->ghostwin) == GHOST_kWindowStateFullScreen); + } return true; } @@ -457,7 +458,7 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) { if (!is_fullscreen) { - wm_window_fullscreen_toggle_exec(C, op); + BKE_reportf(op->reports, RPT_INFO, "Stereo 3D Mode requires the window to be fullscreen"); } } -- cgit v1.2.3 From 45e23661488d2bd585cfcc4561868361e98f906b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 8 Apr 2015 15:07:11 +1000 Subject: Cleanup: remove unused defines --- intern/ghost/GHOST_Types.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index eccbaadb71d..752a45c7473 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -126,12 +126,8 @@ typedef enum { GHOST_kWindowStateMinimized, GHOST_kWindowStateFullScreen, GHOST_kWindowStateEmbedded, - GHOST_kWindowState8Normal = 8, - GHOST_kWindowState8Maximized, - GHOST_kWindowState8Minimized, - GHOST_kWindowState8FullScreen, - GHOST_kWindowStateModified, - GHOST_kWindowStateUnModified + // GHOST_kWindowStateModified, + // GHOST_kWindowStateUnModified, } GHOST_TWindowState; -- cgit v1.2.3 From 60ecc6b3b38ccedd282da7c635578504a11707b4 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Wed, 8 Apr 2015 03:10:39 -0300 Subject: Multiview: Expose current drawn eye to API (viewport only) --- source/blender/makesrna/intern/rna_space.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 8e573e08815..0419802dcc7 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -118,6 +118,11 @@ static EnumPropertyItem multiview_camera_items[] = { #undef V3D_S3D_CAMERA_S3D #undef V3D_S3D_CAMERA_VIEWS +static EnumPropertyItem stereo3d_eye_items[] = { + {STEREO_LEFT_ID, "LEFT_EYE", ICON_NONE, "Left Eye"}, + {STEREO_RIGHT_ID, "RIGHT_EYE", ICON_NONE, "Right Eye"}, + {0, NULL, 0, NULL, NULL} +}; static EnumPropertyItem pivot_items_full[] = { {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center", @@ -2563,6 +2568,13 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* Stereo Settings */ + prop = RNA_def_property(srna, "stereo_3d_eye", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "multiview_eye"); + RNA_def_property_enum_items(prop, stereo3d_eye_items); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_SpaceView3D_stereo3d_camera_itemf"); + RNA_def_property_ui_text(prop, "Stereo Eye", "Current stereo eye being drawn"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop = RNA_def_property(srna, "stereo_3d_camera", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "stereo3d_camera"); RNA_def_property_enum_items(prop, stereo3d_camera_items); -- cgit v1.2.3 From ab2a8832dda571237bf775c2276a68e89f7f82eb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 8 Apr 2015 16:13:00 +1000 Subject: Use IS_EQF for floats --- source/blender/editors/armature/pose_slide.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index a863dae045c..ffb7b3e4a1a 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -202,7 +202,7 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, float *val) eVal = evaluate_fcurve(fcu, (float)pso->nextFrame); /* if both values are equal, don't do anything */ - if (IS_EQ(sVal, eVal)) { + if (IS_EQF(sVal, eVal)) { (*val) = sVal; return; } -- cgit v1.2.3 From a18e5d6a67b9fe56f6ca9840d346e173a6b4301a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 8 Apr 2015 16:26:58 +1000 Subject: warning: unused --- source/blender/makesrna/intern/rna_space.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 0419802dcc7..ca3ea9bda81 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -118,11 +118,13 @@ static EnumPropertyItem multiview_camera_items[] = { #undef V3D_S3D_CAMERA_S3D #undef V3D_S3D_CAMERA_VIEWS +#ifndef RNA_RUNTIME static EnumPropertyItem stereo3d_eye_items[] = { {STEREO_LEFT_ID, "LEFT_EYE", ICON_NONE, "Left Eye"}, {STEREO_RIGHT_ID, "RIGHT_EYE", ICON_NONE, "Right Eye"}, {0, NULL, 0, NULL, NULL} }; +#endif static EnumPropertyItem pivot_items_full[] = { {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center", -- cgit v1.2.3 From d6d4d5e094eae31b33c844c3d4f9602e6377de4b Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 8 Apr 2015 11:53:14 +0200 Subject: Fix multiview issue: play animation crashes We need to avoid passing a NULL string here, and also we need to pass the correct suffix we used to pass view string directly which is probably not what we want. --- source/blender/makesrna/intern/rna_scene_api.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 0d70b6f3ba8..02364d9b3a9 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -121,8 +121,14 @@ static void rna_Scene_update_tagged(Scene *scene) static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, int preview, const char *view, char *name) { + const char *suffix = BKE_scene_multiview_view_suffix_get(rd, view); + + /* avoid NULL pointer */ + if (!suffix) + suffix = ""; + if (BKE_imtype_is_movie(rd->im_format.imtype)) { - BKE_movie_filepath_get(name, rd, preview != 0, view); + BKE_movie_filepath_get(name, rd, preview != 0, suffix); } else { BKE_image_path_from_imformat( -- cgit v1.2.3 From bb19c7c3f76efc7e2d8b444da479b495bba0ff5a Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 8 Apr 2015 12:02:23 +0200 Subject: Forgot this last commit. --- source/blender/makesrna/intern/rna_scene_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 02364d9b3a9..9d63dfe0f55 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -133,7 +133,7 @@ static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, int previe else { BKE_image_path_from_imformat( name, rd->pic, G.main->name, (frame == INT_MIN) ? rd->cfra : frame, - &rd->im_format, (rd->scemode & R_EXTENSION) != 0, true, view); + &rd->im_format, (rd->scemode & R_EXTENSION) != 0, true, suffix); } } -- cgit v1.2.3 From 7621ff7e554486182efc07327d6bfd2277c5bf03 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 8 Apr 2015 15:35:01 +0500 Subject: Cycles: Code cleanup, indentation. Was wrong in the multiview commit --- intern/cycles/blender/blender_session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 17bab0ab525..bdacea0cd7e 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -632,7 +632,7 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::Re } else { /* copy combined pass */ - BL::RenderPass b_combined_pass(b_rlay.passes.find_by_type(BL::RenderPass::type_COMBINED, b_rview_name.c_str())); + BL::RenderPass b_combined_pass(b_rlay.passes.find_by_type(BL::RenderPass::type_COMBINED, b_rview_name.c_str())); if(buffers->get_pass_rect(PASS_COMBINED, exposure, rtile.sample, 4, &pixels[0])) b_combined_pass.rect(&pixels[0]); } -- cgit v1.2.3 From 235f1feaf4f28f0d3bf3b608ba447b9b0ef5aedc Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 8 Apr 2015 12:49:39 +0200 Subject: Fix opengl render preview in image editor broken During multiview, invalidation of the display imbuf of the preview image was eaten by code eating elves. --- source/blender/editors/render/render_opengl.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index b59fd10870e..9548b4bca68 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -493,6 +493,8 @@ static void screen_opengl_render_apply(OGLRender *oglrender) RenderResult *rr; RenderView *rv; int view_id; + ImBuf *ibuf; + void *lock; rr = RE_AcquireResultRead(oglrender->re); for (rv = rr->views.first, view_id = 0; rv; rv = rv->next, view_id++) { @@ -503,6 +505,12 @@ static void screen_opengl_render_apply(OGLRender *oglrender) RE_ReleaseResult(oglrender->re); + ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); + if (ibuf) { + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + } + BKE_image_release_ibuf(oglrender->ima, ibuf, lock); + if (oglrender->write_still) { screen_opengl_render_write(oglrender); } -- cgit v1.2.3 From 40984f6c8650cca2784c9be7371e86e8e91bbf37 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 8 Apr 2015 13:00:46 +0200 Subject: Fix annoying warning in GHOST when ASSERT_ABORT is off --- intern/ghost/intern/GHOST_Debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h index 9292235a9c7..c99f3dfac95 100644 --- a/intern/ghost/intern/GHOST_Debug.h +++ b/intern/ghost/intern/GHOST_Debug.h @@ -80,7 +80,7 @@ } \ } (void)0 #else // GHOST_DEBUG -# define GHOST_ASSERT(x, info) +# define GHOST_ASSERT(x, info) (void)(x) #endif // GHOST_DEBUG #endif // __GHOST_DEBUG_H__ -- cgit v1.2.3 From c5c60099c536d2d5276c79eff9c6bda0e9d6dd60 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 8 Apr 2015 14:31:11 +0200 Subject: Proportional editing in action editor: display circle in center of region. It's -really- hard getting the center of selection here in the y axis, I feel this is the best compromise. --- .../editors/transform/transform_conversions.c | 29 ++++++++++++++++------ 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 23648c242f7..e11da84954b 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -58,6 +58,7 @@ #include "BLI_linklist_stack.h" #include "BLI_string.h" #include "BLI_bitmap.h" +#include "BLI_rect.h" #include "BKE_DerivedMesh.h" #include "BKE_action.h" @@ -3402,13 +3403,14 @@ static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, boo /* This function assigns the information to transdata */ -static void TimeToTransData(TransData *td, float *time, AnimData *adt) +static void TimeToTransData(TransData *td, float *time, AnimData *adt, float ypos) { /* memory is calloc'ed, so that should zero everything nicely for us */ td->val = time; td->ival = *(time); td->center[0] = td->ival; + td->center[1] = ypos; /* store the AnimData where this keyframe exists as a keyframe of the * active action as td->extra. @@ -3423,7 +3425,7 @@ static void TimeToTransData(TransData *td, float *time, AnimData *adt) * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data * on the named side are used. */ -static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra, bool propedit) +static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra, bool propedit, float ypos) { BezTriple *bezt; TransData2D *td2d = *td2dv; @@ -3437,7 +3439,7 @@ static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FC if (propedit || (bezt->f2 & SELECT)) { /* note this MUST match count_fcurve_keys(), so can't use BEZSELECTED() macro */ /* only add if on the right 'side' of the current frame */ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) { - TimeToTransData(td, bezt->vec[1], adt); + TimeToTransData(td, bezt->vec[1], adt, ypos); if (bezt->f2 & SELECT) td->flag |= TD_SELECTED; @@ -3492,7 +3494,7 @@ void flushTransIntFrameActionData(TransInfo *t) * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data * on the named side are used. */ -static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra, bool propedit) +static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra, bool propedit, float ypos) { bGPDframe *gpf; int count = 0; @@ -3506,6 +3508,7 @@ static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, td->ival = (float)gpf->framenum; td->center[0] = td->ival; + td->center[1] = ypos; tfd->val = (float)gpf->framenum; tfd->sdata = &gpf->framenum; @@ -3522,7 +3525,7 @@ static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, } /* refer to comment above #GPLayerToTransData, this is the same but for masks */ -static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra, bool propedit) +static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra, bool propedit, float ypos) { MaskLayerShape *masklay_shape; int count = 0; @@ -3536,6 +3539,7 @@ static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *ma td->ival = (float)masklay_shape->frame; td->center[0] = td->ival; + td->center[1] = ypos; tfd->val = (float)masklay_shape->frame; tfd->sdata = &masklay_shape->frame; @@ -3559,6 +3563,14 @@ static void createTransActionData(bContext *C, TransInfo *t) TransData2D *td2d = NULL; tGPFtransdata *tfd = NULL; + rcti *mask = &t->ar->v2d.mask; + rctf *datamask = &t->ar->v2d.cur; + + float xsize = BLI_rctf_size_x(datamask); + float ysize = BLI_rctf_size_y(datamask); + float xmask = BLI_rcti_size_x(mask); + float ymask = BLI_rcti_size_y(mask); + bAnimContext ac; ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; @@ -3567,6 +3579,7 @@ static void createTransActionData(bContext *C, TransInfo *t) int count = 0; float cfra; + float ypos = 1.0f / ((ysize / xsize) * (xmask / ymask)) * BLI_rctf_cent_y(&t->ar->v2d.cur); /* determine what type of data we are operating on */ if (ANIM_animdata_get_context(C, &ac) == 0) @@ -3668,7 +3681,7 @@ static void createTransActionData(bContext *C, TransInfo *t) bGPDlayer *gpl = (bGPDlayer *)ale->data; int i; - i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, propedit); + i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, propedit, ypos); td += i; tfd += i; } @@ -3676,7 +3689,7 @@ static void createTransActionData(bContext *C, TransInfo *t) MaskLayer *masklay = (MaskLayer *)ale->data; int i; - i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, propedit); + i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, propedit, ypos); td += i; tfd += i; } @@ -3684,7 +3697,7 @@ static void createTransActionData(bContext *C, TransInfo *t) AnimData *adt = ANIM_nla_mapping_get(&ac, ale); FCurve *fcu = (FCurve *)ale->key_data; - td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, propedit); + td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, propedit, ypos); } } -- cgit v1.2.3 From 3b440dbf66afd33ad8ab6f8444a425ca59c6a5c3 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 8 Apr 2015 14:29:33 +0200 Subject: FileBrowser previews: Get rid of ugly, stupid and confusing 'FILE_TYPE_ICON_MOVIE' hack. Was only handling failures in video thumbnails, was confusing (giving two different types for video files, *sigh*), and... useless, since thumbnail code already handles smartly failures in preview generation! --- source/blender/editors/space_file/filelist.c | 25 ++++++++++--------------- source/blender/makesdna/DNA_space_types.h | 2 +- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 5214b611fb9..d5092ef46d7 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -654,7 +654,7 @@ ImBuf *filelist_geticon(struct FileList *filelist, const int index) if (file->flags & FILE_TYPE_BLENDER) { ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE]; } - else if ((file->flags & FILE_TYPE_MOVIE) || (file->flags & FILE_TYPE_MOVIE_ICON)) { + else if (file->flags & FILE_TYPE_MOVIE) { ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE]; } else if (file->flags & FILE_TYPE_SOUND) { @@ -1334,23 +1334,23 @@ static void thumbnails_startjob(void *tjv, short *stop, short *do_update, float tj->do_update = do_update; while ((*stop == 0) && (limg)) { + ThumbSource source = 0; + + BLI_assert(limg->flags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | + FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)); if (limg->flags & FILE_TYPE_IMAGE) { - limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_IMAGE); + source = THB_SOURCE_IMAGE; } else if (limg->flags & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { - limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_BLEND); + source = THB_SOURCE_BLEND; } else if (limg->flags & FILE_TYPE_MOVIE) { - limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_MOVIE); - if (!limg->img) { - /* remember that file can't be loaded via IMB_open_anim */ - limg->flags &= ~FILE_TYPE_MOVIE; - limg->flags |= FILE_TYPE_MOVIE_ICON; - } + source = THB_SOURCE_MOVIE; } else if (limg->flags & FILE_TYPE_FTFONT) { - limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_FONT); + source = THB_SOURCE_FONT; } + limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, source); *do_update = true; PIL_sleep_ms(10); limg = limg->next; @@ -1366,11 +1366,6 @@ static void thumbnails_update(void *tjv) while (limg) { if (!limg->done && limg->img) { tj->filelist->filelist[limg->index].image = IMB_dupImBuf(limg->img); - /* update flag for movie and font files where thumbnail can't be created */ - if (limg->flags & FILE_TYPE_MOVIE_ICON) { - tj->filelist->filelist[limg->index].flags &= ~FILE_TYPE_MOVIE; - tj->filelist->filelist[limg->index].flags |= FILE_TYPE_MOVIE_ICON; - } limg->done = true; IMB_freeImBuf(limg->img); limg->img = NULL; diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index c2f49ea92b5..29b78c158fd 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -712,7 +712,7 @@ typedef enum eFileSel_File_Types { FILE_TYPE_FTFONT = (1 << 7), FILE_TYPE_SOUND = (1 << 8), FILE_TYPE_TEXT = (1 << 9), - FILE_TYPE_MOVIE_ICON = (1 << 10), /* movie file that preview can't load */ + /* 1 << 10 was FILE_TYPE_MOVIE_ICON, got rid of this so free slot for future type... */ FILE_TYPE_FOLDER = (1 << 11), /* represents folders for filtering */ FILE_TYPE_BTX = (1 << 12), FILE_TYPE_COLLADA = (1 << 13), -- cgit v1.2.3 From d249db9755182bd705c4ea331ccfffef8cf7e270 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 8 Apr 2015 14:35:46 +0200 Subject: Action editor proportional editing: Fix crash when extending instead of translating --- .../blender/editors/transform/transform_conversions.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index e11da84954b..1af214b8c77 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3339,13 +3339,14 @@ static int count_fcurve_keys(FCurve *fcu, char side, float cfra, bool propedit) /* only include points that occur on the right side of cfra */ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { - if (bezt->f2 & SELECT) { + if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) { /* no need to adjust the handle selection since they are assumed * selected (like graph editor with SIPO_NOHANDLES) */ - if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) + if (bezt->f2 & SELECT) count++; + + count_all++; } - count_all++; } if (propedit && count > 0) @@ -3364,11 +3365,11 @@ static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra, bool prop /* only include points that occur on the right side of cfra */ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - if (gpf->flag & GP_FRAME_SELECT) { - if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) + if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) { + if (gpf->flag & GP_FRAME_SELECT) count++; + count_all++; } - count_all++; } if (propedit && count > 0) @@ -3388,11 +3389,11 @@ static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, boo /* only include points that occur on the right side of cfra */ for (masklayer_shape = masklay->splines_shapes.first; masklayer_shape; masklayer_shape = masklayer_shape->next) { - if (masklayer_shape->flag & MASK_SHAPE_SELECT) { - if (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra)) + if (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra)) { + if (masklayer_shape->flag & MASK_SHAPE_SELECT) count++; + count_all++; } - count_all++; } if (propedit && count > 0) -- cgit v1.2.3 From 01b1eb445ceb7200d9ac4d00eb624d92713024c7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 8 Apr 2015 22:49:07 +1000 Subject: Math Lib: add project_plane_v3_v3v3 Useful for projecting one vector onto another (as a plane). This is a rather common operation, doing inline isn't always obvious whats happening. --- source/blender/blenlib/BLI_math_vector.h | 2 ++ source/blender/blenlib/intern/math_vector.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index de712cbaa12..9c8a9f54379 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -271,6 +271,8 @@ void angle_poly_v3(float *angles, const float *verts[3], int len); void project_v2_v2v2(float c[2], const float v1[2], const float v2[2]); void project_v3_v3v3(float r[3], const float p[3], const float n[3]); +void project_plane_v3_v3v3(float c[3], const float v[3], const float v_plane[3]); +void project_plane_v2_v2v2(float c[2], const float v[2], const float v_plane[2]); void project_v3_plane(float v[3], const float n[3], const float p[3]); void reflect_v3_v3v3(float r[3], const float v[3], const float n[3]); void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3]); diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 814180bba24..e9909cef29d 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -572,6 +572,27 @@ void project_v3_v3v3(float c[3], const float v1[3], const float v2[3]) c[2] = mul * v2[2]; } +/** + * In this case plane is a 3D vector only (no 4th component). + * + * Projecting will make \a c a copy of \a v orthogonal to \a v_plane. + * + * \note If \a v is exactly perpendicular to \a v_plane, \a c will just be a copy of \a v. + */ +void project_plane_v3_v3v3(float c[3], const float v[3], const float v_plane[3]) +{ + float delta[3]; + project_v3_v3v3(delta, v, v_plane); + sub_v3_v3v3(c, v, delta); +} + +void project_plane_v2_v2v2(float c[2], const float v[2], const float v_plane[2]) +{ + float delta[2]; + project_v2_v2v2(delta, v, v_plane); + sub_v2_v2v2(c, v, delta); +} + /* project a vector on a plane defined by normal and a plane point p */ void project_v3_plane(float v[3], const float n[3], const float p[3]) { -- cgit v1.2.3 From 2c91f9dc1129c4d11a0100dc1925ac244e550cf6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 8 Apr 2015 22:58:31 +1000 Subject: Transform: use relative motion for vertex slide Vertex slide was using absolute mouse position unlike all other kinds of transform. also remove need for allocated 2d projections. --- source/blender/editors/transform/transform.c | 138 +++++++++++++++------------ source/blender/editors/transform/transform.h | 5 +- 2 files changed, 82 insertions(+), 61 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 17f1d6112b2..0d5e496ee07 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -6449,10 +6449,20 @@ static void calcVertSlideCustomPoints(struct TransInfo *t) { VertSlideData *sld = t->customData; TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index]; - const float *co_orig = sv->co_orig_2d; - const float *co_curr = sv->co_link_orig_2d[sv->co_link_curr]; - const int mval_start[2] = {co_orig[0], co_orig[1]}; - const int mval_end[2] = {co_curr[0], co_curr[1]}; + + const float *co_orig_3d = sv->co_orig_3d; + const float *co_curr_3d = sv->co_link_orig_3d[sv->co_link_curr]; + + float co_curr_2d[2], co_orig_2d[2]; + + int mval_ofs[2], mval_start[2], mval_end[2]; + + ED_view3d_project_float_v2_m4(t->ar, co_orig_3d, co_orig_2d, sld->proj_mat); + ED_view3d_project_float_v2_m4(t->ar, co_curr_3d, co_curr_2d, sld->proj_mat); + + ARRAY_SET_ITEMS(mval_ofs, t->imval[0] - co_orig_2d[0], t->imval[1] - co_orig_2d[1]); + ARRAY_SET_ITEMS(mval_start, co_orig_2d[0] + mval_ofs[0], co_orig_2d[1] + mval_ofs[1]); + ARRAY_SET_ITEMS(mval_end, co_curr_2d[0] + mval_ofs[0], co_curr_2d[1] + mval_ofs[1]); if (sld->flipped_vtx && sld->is_proportional == false) { setCustomPoints(t, &t->mouse, mval_start, mval_end); @@ -6460,6 +6470,11 @@ static void calcVertSlideCustomPoints(struct TransInfo *t) else { setCustomPoints(t, &t->mouse, mval_end, mval_start); } + + /* setCustomPoints isn't normally changing as the mouse moves, + * in this case apply mouse input immediatly so we don't refresh + * with the value from the previous points */ + applyMouseInput(t, &t->mouse, t->mval, t->values); } /** @@ -6477,28 +6492,35 @@ static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2]) int i; for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) { - dist_sq = len_squared_v2v2(mval_fl, sv->co_orig_2d); + float co_2d[2]; + + ED_view3d_project_float_v2_m4(t->ar, sv->co_orig_3d, co_2d, sld->proj_mat); + + dist_sq = len_squared_v2v2(mval_fl, co_2d); if (dist_sq < dist_min_sq) { dist_min_sq = dist_sq; sld->curr_sv_index = i; } } } + /** * Run while moving the mouse to slide along the edge matching the mouse direction */ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2]) { VertSlideData *sld = t->customData; - float mval_fl[2] = {UNPACK2(mval)}; + float imval_fl[2] = {UNPACK2(t->imval)}; + float mval_fl[2] = {UNPACK2(mval)}; - float dir[2]; + float dir[3]; TransDataVertSlideVert *sv; int i; - /* first get the direction of the original vertex */ - sub_v2_v2v2(dir, sld->sv[sld->curr_sv_index].co_orig_2d, mval_fl); - normalize_v2(dir); + /* first get the direction of the original mouse position */ + sub_v2_v2v2(dir, imval_fl, mval_fl); + ED_view3d_win_to_delta(t->ar, dir, dir, t->zfac); + normalize_v3(dir); for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) { if (sv->co_link_tot > 1) { @@ -6507,11 +6529,14 @@ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2] int j; for (j = 0; j < sv->co_link_tot; j++) { - float tdir[2]; + float tdir[3]; float dir_dot; - sub_v2_v2v2(tdir, sv->co_orig_2d, sv->co_link_orig_2d[j]); - normalize_v2(tdir); - dir_dot = dot_v2v2(dir, tdir); + + sub_v3_v3v3(tdir, sv->co_orig_3d, sv->co_link_orig_3d[j]); + project_plane_v3_v3v3(tdir, tdir, t->viewinv[2]); + + normalize_v3(tdir); + dir_dot = dot_v3v3(dir, tdir); if (dir_dot > dir_dot_best) { dir_dot_best = dir_dot; co_link_curr_best = j; @@ -6535,32 +6560,14 @@ static bool createVertSlideVerts(TransInfo *t) BMVert *v; TransDataVertSlideVert *sv_array; VertSlideData *sld = MEM_callocN(sizeof(*sld), "sld"); -// View3D *v3d = NULL; - RegionView3D *rv3d = NULL; - ARegion *ar = t->ar; - float projectMat[4][4]; int j; - if (t->spacetype == SPACE_VIEW3D) { - /* background mode support */ -// v3d = t->sa ? t->sa->spacedata.first : NULL; - rv3d = ar ? ar->regiondata : NULL; - } - slide_origdata_init_flag(t, &sld->orig_data); sld->is_proportional = true; sld->curr_sv_index = 0; sld->flipped_vtx = false; - if (!rv3d) { - /* ok, let's try to survive this */ - unit_m4(projectMat); - } - else { - ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat); - } - j = 0; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { bool ok = false; @@ -6604,7 +6611,6 @@ static bool createVertSlideVerts(TransInfo *t) } sv_array[j].co_link_orig_3d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_3d) * k, __func__); - sv_array[j].co_link_orig_2d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_2d) * k, __func__); sv_array[j].co_link_tot = k; k = 0; @@ -6612,31 +6618,9 @@ static bool createVertSlideVerts(TransInfo *t) if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { BMVert *v_other = BM_edge_other_vert(e, v); copy_v3_v3(sv_array[j].co_link_orig_3d[k], v_other->co); - if (ar) { - ED_view3d_project_float_v2_m4(ar, - sv_array[j].co_link_orig_3d[k], - sv_array[j].co_link_orig_2d[k], - projectMat); - } - else { - copy_v2_v2(sv_array[j].co_link_orig_2d[k], - sv_array[j].co_link_orig_3d[k]); - } k++; } } - - if (ar) { - ED_view3d_project_float_v2_m4(ar, - sv_array[j].co_orig_3d, - sv_array[j].co_orig_2d, - projectMat); - } - else { - copy_v2_v2(sv_array[j].co_orig_2d, - sv_array[j].co_orig_3d); - } - j++; } } @@ -6654,7 +6638,19 @@ static bool createVertSlideVerts(TransInfo *t) t->customData = sld; - if (rv3d) { + /* most likely will be set below */ + unit_m4(sld->proj_mat); + + if (t->spacetype == SPACE_VIEW3D) { + /* view vars */ + RegionView3D *rv3d = NULL; + ARegion *ar = t->ar; + + rv3d = ar ? ar->regiondata : NULL; + if (rv3d) { + ED_view3d_ob_project_mat_get(rv3d, t->obedit, sld->proj_mat); + } + calcVertSlideMouseActiveVert(t, t->mval); calcVertSlideMouseActiveEdges(t, t->mval); } @@ -6694,7 +6690,6 @@ void freeVertSlideVerts(TransInfo *t) TransDataVertSlideVert *sv = sld->sv; int i = 0; for (i = 0; i < sld->totsv; i++, sv++) { - MEM_freeN(sv->co_link_orig_2d); MEM_freeN(sv->co_link_orig_3d); } } @@ -6874,11 +6869,36 @@ static void drawVertSlide(const struct bContext *C, TransInfo *t) curr_sv->co_orig_3d); bglEnd(); + glDisable(GL_BLEND); + + /* direction from active vertex! */ + if ((t->mval[0] != t->imval[0]) || + (t->mval[1] != t->imval[1])) + { + float zfac = ED_view3d_calc_zfac(t->ar->regiondata, curr_sv->co_orig_3d, NULL); + float mval_ofs[2]; + float co_dest_3d[3]; + + mval_ofs[0] = t->mval[0] - t->imval[0]; + mval_ofs[1] = t->mval[1] - t->imval[1]; + + ED_view3d_win_to_delta(t->ar, mval_ofs, co_dest_3d, zfac); + add_v3_v3(co_dest_3d, curr_sv->co_orig_3d); + + glLineWidth(1); + setlinestyle(1); + + cpack(0xffffff); + glBegin(GL_LINES); + glVertex3fv(curr_sv->co_orig_3d); + glVertex3fv(co_dest_3d); + + glEnd(); + } + glPopMatrix(); glPopAttrib(); - glDisable(GL_BLEND); - if (v3d && v3d->zbuf) glEnable(GL_DEPTH_TEST); } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 97cc6dd9dd1..1971c88ae2e 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -266,9 +266,7 @@ typedef struct TransDataVertSlideVert { float co_orig_3d[3]; /* end generic */ - float co_orig_2d[2]; float (*co_link_orig_3d)[3]; - float (*co_link_orig_2d)[2]; int co_link_tot; int co_link_curr; } TransDataVertSlideVert; @@ -287,6 +285,9 @@ typedef struct VertSlideData { bool flipped_vtx; int curr_sv_index; + + /* result of ED_view3d_ob_project_mat_get */ + float proj_mat[4][4]; } VertSlideData; typedef struct BoneInitData { -- cgit v1.2.3 From bf11e362c5418ec40dc0437d329efceb225eb5ef Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 8 Apr 2015 18:44:31 +0500 Subject: Fix T44046: Cycles speed regression in 2.74 (CPU only) Issue was caused by MSVC not being able to optimize some code out in the same way as GCC/Clang does, so now that parts of code are explicitly unfolded in order to help compilers out. This makes speed loss much less drastic on my laptop. That's probably as good as we can do with MSVC without investing infinite amount of time looking trying to workaround the optimizer. --- .../cycles/kernel/geom/geom_triangle_intersect.h | 56 ++++++++++------------ 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index a0e36058bf8..3990bae5478 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -110,14 +110,12 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg, const float Sz = isect_precalc->Sz; /* Calculate vertices relative to ray origin. */ - float3 tri[3]; - tri[0] = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0)); - tri[1] = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1)); - tri[2] = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2)); - - const float3 A = tri[0] - P; - const float3 B = tri[1] - P; - const float3 C = tri[2] - P; + const float4 tri_a = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0), + tri_b = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1), + tri_c = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2); + const float3 A = make_float3(tri_a.x - P.x, tri_a.y - P.y, tri_a.z - P.z); + const float3 B = make_float3(tri_b.x - P.x, tri_b.y - P.y, tri_b.z - P.z); + const float3 C = make_float3(tri_c.x - P.x, tri_c.y - P.y, tri_c.z - P.z); const float A_kx = IDX(A, kx), A_ky = IDX(A, ky), A_kz = IDX(A, kz); const float B_kx = IDX(B, kx), B_ky = IDX(B, ky), B_kz = IDX(B, kz); @@ -205,14 +203,12 @@ ccl_device_inline void triangle_intersect_subsurface( const float Sz = isect_precalc->Sz; /* Calculate vertices relative to ray origin. */ - float3 tri[3]; - tri[0] = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0)); - tri[1] = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1)); - tri[2] = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2)); - - const float3 A = tri[0] - P; - const float3 B = tri[1] - P; - const float3 C = tri[2] - P; + const float4 tri_a = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0), + tri_b = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1), + tri_c = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2); + const float3 A = make_float3(tri_a.x - P.x, tri_a.y - P.y, tri_a.z - P.z); + const float3 B = make_float3(tri_b.x - P.x, tri_b.y - P.y, tri_b.z - P.z); + const float3 C = make_float3(tri_c.x - P.x, tri_c.y - P.y, tri_c.z - P.z); const float A_kx = IDX(A, kx), A_ky = IDX(A, ky), A_kz = IDX(A, kz); const float B_kx = IDX(B, kx), B_ky = IDX(B, ky), B_kz = IDX(B, kz); @@ -322,14 +318,12 @@ ccl_device_inline float3 triangle_refine(KernelGlobals *kg, P = P + D*t; - float3 tri[3]; - tri[0] = float4_to_float3(kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0)); - tri[1] = float4_to_float3(kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1)); - tri[2] = float4_to_float3(kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2)); - - float3 edge1 = tri[0] - tri[2]; - float3 edge2 = tri[1] - tri[2]; - float3 tvec = P - tri[2]; + const float4 tri_a = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0), + tri_b = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1), + tri_c = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2); + float3 edge1 = make_float3(tri_a.x - tri_c.x, tri_a.y - tri_c.y, tri_a.z - tri_c.z); + float3 edge2 = make_float3(tri_b.x - tri_c.x, tri_b.y - tri_c.y, tri_b.z - tri_c.z); + float3 tvec = make_float3(P.x - tri_c.x, P.y - tri_c.y, P.z - tri_c.z); float3 qvec = cross(tvec, edge1); float3 pvec = cross(D, edge2); float rt = dot(edge2, qvec) / dot(edge1, pvec); @@ -381,14 +375,12 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg, P = P + D*t; - float3 tri[3]; - tri[0] = float4_to_float3(kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0)); - tri[1] = float4_to_float3(kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1)); - tri[2] = float4_to_float3(kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2)); - - float3 edge1 = tri[0] - tri[2]; - float3 edge2 = tri[1] - tri[2]; - float3 tvec = P - tri[2]; + const float4 tri_a = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0), + tri_b = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1), + tri_c = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2); + float3 edge1 = make_float3(tri_a.x - tri_c.x, tri_a.y - tri_c.y, tri_a.z - tri_c.z); + float3 edge2 = make_float3(tri_b.x - tri_c.x, tri_b.y - tri_c.y, tri_b.z - tri_c.z); + float3 tvec = make_float3(P.x - tri_c.x, P.y - tri_c.y, P.z - tri_c.z); float3 qvec = cross(tvec, edge1); float3 pvec = cross(D, edge2); float rt = dot(edge2, qvec) / dot(edge1, pvec); -- cgit v1.2.3 From 7fcb0bf71e5ebb911a22ac628b74f26cf77f16ce Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 8 Apr 2015 16:30:26 +0200 Subject: Attempt GLSL compile fix in opensuse linux basically, we passed a vec3 as a float. --- source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c index b9c94fc3aee..8dda7b0859b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c @@ -51,8 +51,8 @@ static void node_shader_init_anisotropic(bNodeTree *UNUSED(ntree), bNode *node) static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - if (!in[3].link) - in[3].link = GPU_builtin(GPU_VIEW_NORMAL); + if (!in[4].link) + in[4].link = GPU_builtin(GPU_VIEW_NORMAL); return GPU_stack_link(mat, "node_bsdf_anisotropic", in, out); } -- cgit v1.2.3 From 62f863b78a79474ef31362179800be7ff79f7510 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 8 Apr 2015 16:48:15 +0200 Subject: Fix memory leak in bump GLSL node --- source/blender/nodes/shader/nodes/node_shader_bump.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.c index de152ee45d1..3146454f26d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bump.c +++ b/source/blender/nodes/shader/nodes/node_shader_bump.c @@ -47,7 +47,10 @@ static bNodeSocketTemplate sh_node_bump_out[] = { static int gpu_shader_bump(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - return GPU_stack_link(mat, "node_bump", in, out, GPU_builtin(GPU_VIEW_NORMAL)); + if (!in[3].link) + in[3].link = GPU_builtin(GPU_VIEW_NORMAL); + + return GPU_stack_link(mat, "node_bump", in, out); } /* node type definition */ -- cgit v1.2.3 From 2d054667001602cd9b15046190e09167d7951d89 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 8 Apr 2015 20:03:35 +0500 Subject: Fix T44213: Bevel object from different scene won't update generated bezier curve geometry The issue was caused by bevel object being automatically added to the scene graph by dag_get_node() and had no incoming relations, even form the scene. This confused scene update flush logic. Now there'll be a scene relation added to such nodes, so they're always reachable from the root node. --- source/blender/blenkernel/intern/depsgraph.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 911415621d1..869404ae4a6 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -960,6 +960,10 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask) /* also flush custom data mask */ ((Object *)node->ob)->customdata_mask = node->customdata_mask; + + if (node->parent == NULL) { + dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation"); + } } } /* now set relations equal, so that when only one parent changes, the correct recalcs are found */ -- cgit v1.2.3 From c523e82e3176fe8663f7513ae727265311835908 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 8 Apr 2015 20:17:44 +0500 Subject: Particles: Fix for missing particles in render if they're disabled for viewport The issue was introduced in rB4b685e1 and it appears some crazy area still accesses particles for render after deleting it's render data, which broke viewport/render behavior. This commit restores previous G.is_rendering logic and adds corresponding checks to cache construction, so counting is all consistent. Goes to the TODO list to either replace G.is_rendering with eval_ctx or to make it so psys->renderdata always exists during render sync. --- source/blender/blenkernel/intern/particle.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index fbd55928534..6c354c59d7a 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -286,7 +286,7 @@ bool psys_check_enabled(Object *ob, ParticleSystem *psys) return 0; psmd = psys_get_modifier(ob, psys); - if (psys->renderdata) { + if (psys->renderdata || G.is_rendering) { if (!(psmd->modifier.mode & eModifierMode_Render)) return 0; } @@ -1955,7 +1955,7 @@ void psys_find_parents(ParticleSimulationData *sim) int from = PART_FROM_FACE; totparent = (int)(totchild * part->parents * 0.3f); - if (sim->psys->renderdata && part->child_nbr && part->ren_child_nbr) + if ((sim->psys->renderdata || G.is_rendering) && part->child_nbr && part->ren_child_nbr) totparent *= (float)part->child_nbr / (float)part->ren_child_nbr; /* hard limit, workaround for it being ignored above */ @@ -2000,7 +2000,7 @@ static bool psys_thread_context_init_path(ParticleThreadContext *ctx, ParticleSi if (psys_in_edit_mode(scene, psys)) { ParticleEditSettings *pset = &scene->toolsettings->particle; - if (psys->renderdata == 0 && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0) + if ((psys->renderdata == 0 && G.is_rendering == 0) && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0) totchild = 0; segments = 1 << pset->draw_step; @@ -2009,14 +2009,14 @@ static bool psys_thread_context_init_path(ParticleThreadContext *ctx, ParticleSi if (totchild && part->childtype == PART_CHILD_FACES) { totparent = (int)(totchild * part->parents * 0.3f); - if (psys->renderdata && part->child_nbr && part->ren_child_nbr) + if ((psys->renderdata || G.is_rendering) && part->child_nbr && part->ren_child_nbr) totparent *= (float)part->child_nbr / (float)part->ren_child_nbr; /* part->parents could still be 0 so we can't test with totparent */ between = 1; } - if (psys->renderdata) + if (psys->renderdata || G.is_rendering) segments = 1 << part->ren_step; else { totchild = (int)((float)totchild * (float)part->disp / 100.0f); @@ -2470,7 +2470,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra) float prev_tangent[3] = {0.0f, 0.0f, 0.0f}, hairmat[4][4]; float rotmat[3][3]; int k; - int segments = (int)pow(2.0, (double)(psys->renderdata ? part->ren_step : part->draw_step)); + int segments = (int)pow(2.0, (double)((psys->renderdata || G.is_rendering) ? part->ren_step : part->draw_step)); int totpart = psys->totpart; float length, vec[3]; float *vg_effector = NULL; -- cgit v1.2.3 From 0a304337e184c97eabf7e451714bde14a32c0a12 Mon Sep 17 00:00:00 2001 From: Tamito Kajiyama Date: Thu, 9 Apr 2015 00:24:26 +0900 Subject: Freestyle: Fix for AndBP1D and OrBP1D not working due to typos. Problem report by Folkert de Vries (flokkievids) through personal communications. Thanks! --- release/scripts/freestyle/modules/freestyle/predicates.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release/scripts/freestyle/modules/freestyle/predicates.py b/release/scripts/freestyle/modules/freestyle/predicates.py index 54656e450d9..2439cb0cf97 100644 --- a/release/scripts/freestyle/modules/freestyle/predicates.py +++ b/release/scripts/freestyle/modules/freestyle/predicates.py @@ -564,7 +564,7 @@ class AndBP1D(BinaryPredicate1D): def __init__(self, *predicates): BinaryPredicate1D.__init__(self) self._predicates = predicates - if len(self.predicates) < 2: + if len(predicates) < 2: raise ValueError("Expected two or more BinaryPredicate1D, got ", len(predictates)) def __call__(self, i1, i2): @@ -575,7 +575,7 @@ class OrBP1D(BinaryPredicate1D): def __init__(self, *predicates): BinaryPredicate1D.__init__(self) self._predicates = predicates - if len(self.predicates) < 2: + if len(predicates) < 2: raise ValueError("Expected two or more BinaryPredicate1D, got ", len(predictates)) def __call__(self, i1, i2): -- cgit v1.2.3 From 5d212fb8121912cd583eadb55ea19c9bbab7b5e9 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Wed, 8 Apr 2015 16:17:16 -0300 Subject: Fix T44310: Other render slots cleared after each render --- source/blender/editors/space_image/space_image.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 1023f9641b3..32584a3a2df 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -157,6 +157,7 @@ static SpaceLink *image_new(const bContext *UNUSED(C)) simage->iuser.fie_ima = 2; simage->iuser.frames = 100; simage->iuser.flag = IMA_SHOW_STEREO; + simage->iuser.passtype = SCE_PASS_COMBINED; scopes_new(&simage->scopes); simage->sample_line_hist.height = 100; -- cgit v1.2.3 From 114d1b23d298a9a5ddb6201046ec8b9e74661b7e Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 8 Apr 2015 21:54:52 +0200 Subject: Fix T44113: Some System Folders do not contain go back arrow. On windows empty dirs are completely empty - no par or current entries are listed either, in those cases artificially add those. Furthermore, stat on UNC paths do not support current/parent 'shortcuts' (i.e. things like '\\SERVER\foo\bar\..' do not work), so we have to hack around that mess... This should ensure us we always do have valid parrent entry... --- source/blender/blenlib/intern/BLI_filelist.c | 34 ++++++++++++++++++++++++++++ source/blender/editors/space_file/filelist.c | 1 - 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/source/blender/blenlib/intern/BLI_filelist.c b/source/blender/blenlib/intern/BLI_filelist.c index 81813ce1f62..b934b51375b 100644 --- a/source/blender/blenlib/intern/BLI_filelist.c +++ b/source/blender/blenlib/intern/BLI_filelist.c @@ -112,10 +112,40 @@ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) if ((dir = opendir(dirname)) != NULL) { const struct dirent *fname; + bool has_current = false, has_parent = false; + while ((fname = readdir(dir)) != NULL) { struct dirlink * const dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); if (dlink != NULL) { dlink->name = BLI_strdup(fname->d_name); + if (FILENAME_IS_PARENT(dlink->name)) { + has_parent = true; + } + else if (FILENAME_IS_CURRENT(dlink->name)) { + has_current = true; + } + BLI_addhead(&dirbase, dlink); + newnum++; + } + } + + if (!has_parent) { + char pardir[FILE_MAXDIR]; + + BLI_strncpy(pardir, dirname, sizeof(pardir)); + if (BLI_parent_dir(pardir) && (BLI_access(pardir, R_OK) == 0)) { + struct dirlink * const dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); + if (dlink != NULL) { + dlink->name = BLI_strdup(FILENAME_PARENT); + BLI_addhead(&dirbase, dlink); + newnum++; + } + } + } + if (!has_current) { + struct dirlink * const dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); + if (dlink != NULL) { + dlink->name = BLI_strdup(FILENAME_CURRENT); BLI_addhead(&dirbase, dlink); newnum++; } @@ -148,6 +178,10 @@ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) if (BLI_stat(fullname, &file->s) != -1) { file->type = file->s.st_mode; } + else if (FILENAME_IS_CURRPAR(file->relname)) { + /* Hack around for UNC paths on windows - does not support stat on '\\SERVER\foo\..', sigh... */ + file->type |= S_IFDIR; + } file->flags = 0; dir_ctx->nrfiles++; file++; diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index d5092ef46d7..87e6183f4f8 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -900,7 +900,6 @@ static void filelist_setfiletypes(struct FileList *filelist) file = filelist->filelist; for (num = 0; num < filelist->numfiles; num++, file++) { - file->type = file->s.st_mode; /* restore the mess below */ #ifndef __APPLE__ /* Don't check extensions for directories, allow in OSX cause bundles have extensions*/ if (file->type & S_IFDIR) { -- cgit v1.2.3 From aa24704749861e8f1691347ced0f28522cb0e61e Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 8 Apr 2015 21:57:49 +0200 Subject: Fix T44235: UNC Path Fails in open. Here again, stat on '\\MYSERVER\foo\..' does not work... Anyway, we can handle this in a much much simpler way using BLI_access and BLI_parent_dir... --- source/blender/blenlib/intern/path_util.c | 33 ++++++++++--------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 72739018399..58b01f7e140 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -57,6 +57,8 @@ # include # include "BLI_winstuff.h" # include "MEM_guardedalloc.h" +#else +# include "unistd.h" #endif /* WIN32 */ /* local */ @@ -743,7 +745,7 @@ bool BLI_parent_dir(char *path) BLI_cleanup_dir(NULL, tmp); /* does all the work of normalizing the path for us */ if (!BLI_testextensie(tmp, parent_dir)) { - BLI_strncpy(path, tmp, sizeof(tmp)); + strcpy(path, tmp); /* We assume pardir is always shorter... */ return true; } else { @@ -1109,33 +1111,18 @@ void BLI_char_switch(char *string, char from, char to) */ void BLI_make_exist(char *dir) { - int a; - char par_path[PATH_MAX + 3]; - - BLI_char_switch(dir, ALTSEP, SEP); + bool valid_path = true; - a = strlen(dir); + /* Loop as long as cur path is not a dir, and we can get a parent path. */ + while ((BLI_access(dir, R_OK) != 0) && (valid_path = BLI_parent_dir(dir))); - for (BLI_join_dirfile(par_path, sizeof(par_path), dir, FILENAME_PARENT); - !(BLI_is_dir(dir) && BLI_exists(par_path)); - BLI_join_dirfile(par_path, sizeof(par_path), dir, FILENAME_PARENT)) - { - a--; - while (dir[a] != SEP) { - a--; - if (a <= 0) break; - } - if (a >= 0) { - dir[a + 1] = '\0'; - } - else { + /* If we could not find an existing dir, use default root... */ + if (!valid_path || !dir[0]) { #ifdef WIN32 - get_default_root(dir); + get_default_root(dir); #else - strcpy(dir, "/"); + strcpy(dir, "/"); #endif - break; - } } } -- cgit v1.2.3 From 12661de0875110abb63db3ac27f71bf7d926a380 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 9 Apr 2015 13:00:31 +1000 Subject: Remove invalid assert --- source/blender/blenlib/intern/edgehash.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c index fd7ad4db44b..edf70a1f188 100644 --- a/source/blender/blenlib/intern/edgehash.c +++ b/source/blender/blenlib/intern/edgehash.c @@ -232,7 +232,6 @@ BLI_INLINE void edgehash_insert_ex_keyonly(EdgeHash *eh, unsigned int v0, unsign EdgeEntry *e = BLI_mempool_alloc(eh->epool); BLI_assert((eh->flag & EDGEHASH_FLAG_ALLOW_DUPES) || (BLI_edgehash_haskey(eh, v0, v1) == 0)); - IS_EDGEHASH_ASSERT(eh); /* this helps to track down errors with bad edge data */ BLI_assert(v0 < v1); -- cgit v1.2.3 From 1b72ad0c3d57e4c19a90f27106e4ffd435c0e04e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 9 Apr 2015 13:55:46 +1000 Subject: GHOST: don't instantiate assert arg When debugging is disabled, function calls in an assert should never run. --- intern/ghost/intern/GHOST_Debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h index c99f3dfac95..db49627b378 100644 --- a/intern/ghost/intern/GHOST_Debug.h +++ b/intern/ghost/intern/GHOST_Debug.h @@ -80,7 +80,7 @@ } \ } (void)0 #else // GHOST_DEBUG -# define GHOST_ASSERT(x, info) (void)(x) +# define GHOST_ASSERT(x, info) ((void)0) #endif // GHOST_DEBUG #endif // __GHOST_DEBUG_H__ -- cgit v1.2.3 From 0b598651154ddaaff4ae721e1627b1f99de67d94 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 9 Apr 2015 17:09:10 +1000 Subject: Fix missing NULL check --- source/blender/blenkernel/intern/sequencer.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 2fde98cce74..f5e75e17b16 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1505,9 +1505,15 @@ static void seq_open_anim_file(Scene *scene, Sequence *seq, bool openfile) seq->streamindex, seq->strip->colorspace_settings.name); } - seq_anim_add_suffix(scene, sanim->anim, i); - - if (sanim->anim == NULL) { + if (sanim->anim) { +#if 0 + seq_anim_add_suffix(scene, sanim->anim, i); +#else + /* we already have the suffix */ + IMB_suffix_anim(sanim->anim, suffix); +#endif + } + else { if (openfile) { sanim->anim = openanim( name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), -- cgit v1.2.3 From 5467260ce9af14d8bd4d88758e1925c88dafa8c8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 9 Apr 2015 17:19:50 +1000 Subject: Cleanup: redundant NULL checks --- source/blender/editors/space_action/action_data.c | 2 +- .../blender/render/intern/source/render_result.c | 23 ++++------------------ 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index a7358172ef5..440201bd93e 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -646,7 +646,7 @@ static NlaTrack *nla_tweak_track_get(AnimData *adt) printf("%s: Active strip (%p, %s) not in NLA track found (%p, %s)\n", __func__, adt->actstrip, (adt->actstrip) ? adt->actstrip->name : "", - nlt, (nlt) ? nlt->name : ""); + nlt, nlt->name); } } } diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 90f6eab0cc1..9ae394fa675 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -1512,10 +1512,7 @@ void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBu /* TSK! Since sequence render doesn't free the *rr render result, the old rect32 * can hang around when sequence render has rendered a 32 bits one before */ - if (rv->rect32) { - MEM_freeN(rv->rect32); - rv->rect32 = NULL; - } + MEM_SAFE_FREE(rv->rect32); } else if (ibuf->rect) { if (!rv->rect32) @@ -1524,24 +1521,12 @@ void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBu memcpy(rv->rect32, ibuf->rect, 4 * rr->rectx * rr->recty); /* Same things as above, old rectf can hang around from previous render. */ - if (rv->rectf) { - MEM_freeN(rv->rectf); - rv->rectf = NULL; - } + MEM_SAFE_FREE(rv->rectf); } /* clean up non-view buffers */ - if (rr) { - if (rr->rectf) { - MEM_freeN(rr->rectf); - rr->rectf = NULL; - } - - if (rr->rect32) { - MEM_freeN(rr->rect32); - rr->rect32 = NULL; - } - } + MEM_SAFE_FREE(rr->rect32); + MEM_SAFE_FREE(rr->rectf); } void render_result_rect_fill_zero(RenderResult *rr, const int view_id) -- cgit v1.2.3 From 089fc24c76a513347ce1f10a6a5d20707685d060 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 9 Apr 2015 17:21:17 +1000 Subject: Fix for passing -1 to close() --- source/blender/blenkernel/intern/image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index bd0daf36147..80828533a31 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -4533,8 +4533,8 @@ static void image_update_views_format(Image *ima, ImageUser *iuser) } else { iv = iv->prev; + close(file); } - close(file); } /* all good */ -- cgit v1.2.3 From 55ee436618bc99fbf88fc60db222593d84a1bb6f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 9 Apr 2015 17:23:51 +1000 Subject: Fix missing NULL checks --- source/blender/blenkernel/intern/sequencer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index f5e75e17b16..2b44ba9ce68 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -868,9 +868,9 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r seq_multiview_name(scene, i, prefix, ext, str, FILE_MAX); anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex, seq->strip->colorspace_settings.name); - seq_anim_add_suffix(scene, anim, i); if (anim) { + seq_anim_add_suffix(scene, anim, i); sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); BLI_addtail(&seq->anims, sanim); sanim->anim = anim; @@ -5065,9 +5065,9 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad seq_multiview_name(scene, i, prefix, ext, str, FILE_MAX); anim_arr[j] = openanim(str, IB_rect, 0, colorspace); - seq_anim_add_suffix(scene, anim_arr[j], i); if (anim_arr[j]) { + seq_anim_add_suffix(scene, anim_arr[j], i); j++; } } -- cgit v1.2.3 From bdad2c0595948add04cbb30a3118ddb1f2056ca7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 9 Apr 2015 17:30:26 +1000 Subject: Fix uninitialized var use reading view prefix --- source/blender/blenkernel/intern/sequencer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 2b44ba9ce68..339432c2b77 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1782,6 +1782,9 @@ static bool seq_proxy_multiview_context_invalid(Sequence *seq, Scene *scene, con BLI_path_abs(path, G.main->name); BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext); } + else { + prefix[0] = '\0'; + } if (prefix[0] == '\0') return view_id != 0; @@ -2739,6 +2742,9 @@ static ImBuf *seq_render_image_strip(const SeqRenderData *context, Sequence *seq goto monoview_image; } } + else { + prefix[0] = '\0'; + } totviews = BKE_scene_multiview_num_views_get(&context->scene->r); ibufs_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Sequence Image Views Imbufs"); -- cgit v1.2.3 From cc6e0b7394e2abb6fd32722851d30299ca75fa67 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 9 Apr 2015 19:09:03 +1000 Subject: UI: Extend preset menu - allow for preset menu to change operator defaults. - allow preset menu to select own kinds of file extensions. --- release/scripts/modules/bpy_types.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index c7ec7e1e54a..94d371447d6 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -715,7 +715,7 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta): __slots__ = () def path_menu(self, searchpaths, operator, - props_default={}, filter_ext=None): + props_default=None, filter_ext=None): layout = self.layout # hard coded to set the operators 'filepath' to the filename. @@ -745,8 +745,9 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta): text=bpy.path.display_name(f), translate=False) - for attr, value in props_default.items(): - setattr(props, attr, value) + if props_default is not None: + for attr, value in props_default.items(): + setattr(props, attr, value) props.filepath = filepath if operator == "script.execute_preset": @@ -754,14 +755,20 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta): def draw_preset(self, context): """ - Define these on the subclass - - preset_operator - - preset_subdir + Define these on the subclass: + - preset_operator (string) + - preset_subdir (string) + + Optionally: + - preset_extensions (set of strings) + - preset_operator_defaults (dict of keyword args) """ import bpy + ext = getattr(self, "preset_extensions", {".py", ".xml"}) + ext = getattr(self, "preset_operator_defaults", None) self.path_menu(bpy.utils.preset_paths(self.preset_subdir), self.preset_operator, - filter_ext=lambda ext: ext.lower() in {".py", ".xml"}) + filter_ext=lambda ext: ext.lower() in ext) @classmethod def draw_collapsible(cls, context, layout): -- cgit v1.2.3 From 8732c1a8b763a30d4077ab3f6617f1043a95fb63 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 9 Apr 2015 19:45:06 +1000 Subject: WM: allow 'save as' to path set by operator Invoke assumed the filepath was never set. Scripts couldn't invoke save-as at a custom location. --- source/blender/windowmanager/intern/wm_operators.c | 70 ++++++++++++---------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index f97e79d882d..c97b8e588e8 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2877,30 +2877,45 @@ static void wm_filepath_default(char *filepath) static void save_set_compress(wmOperator *op) { - if (!RNA_struct_property_is_set(op->ptr, "compress")) { - if (G.save_over) /* keep flag for existing file */ - RNA_boolean_set(op->ptr, "compress", (G.fileflags & G_FILE_COMPRESS) != 0); - else /* use userdef for new file */ - RNA_boolean_set(op->ptr, "compress", (U.flag & USER_FILECOMPRESS) != 0); + PropertyRNA *prop; + + prop = RNA_struct_find_property(op->ptr, "compress"); + if (!RNA_property_is_set(op->ptr, prop)) { + if (G.save_over) { /* keep flag for existing file */ + RNA_property_boolean_set(op->ptr, prop, (G.fileflags & G_FILE_COMPRESS) != 0); + } + else { /* use userdef for new file */ + RNA_property_boolean_set(op->ptr, prop, (U.flag & USER_FILECOMPRESS) != 0); + } } } -static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static void save_set_filepath(wmOperator *op) { + PropertyRNA *prop; char name[FILE_MAX]; - save_set_compress(op); - - /* if not saved before, get the name of the most recently used .blend file */ - if (G.main->name[0] == 0 && G.recent_files.first) { - struct RecentFile *recent = G.recent_files.first; - BLI_strncpy(name, recent->filepath, FILE_MAX); + prop = RNA_struct_find_property(op->ptr, "filepath"); + if (!RNA_property_is_set(op->ptr, prop)) { + /* if not saved before, get the name of the most recently used .blend file */ + if (G.main->name[0] == 0 && G.recent_files.first) { + struct RecentFile *recent = G.recent_files.first; + BLI_strncpy(name, recent->filepath, FILE_MAX); + } + else { + BLI_strncpy(name, G.main->name, FILE_MAX); + } + + wm_filepath_default(name); + RNA_property_string_set(op->ptr, prop, name); } - else - BLI_strncpy(name, G.main->name, FILE_MAX); - - wm_filepath_default(name); - RNA_string_set(op->ptr, "filepath", name); +} + +static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + + save_set_compress(op); + save_set_filepath(op); WM_event_add_fileselect(C, op); @@ -2999,7 +3014,6 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot) static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - char name[FILE_MAX]; int ret; /* cancel if no active window */ @@ -3007,18 +3021,7 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U return OPERATOR_CANCELLED; save_set_compress(op); - - /* if not saved before, get the name of the most recently used .blend file */ - if (G.main->name[0] == 0 && G.recent_files.first) { - struct RecentFile *recent = G.recent_files.first; - BLI_strncpy(name, recent->filepath, FILE_MAX); - } - else - BLI_strncpy(name, G.main->name, FILE_MAX); - - wm_filepath_default(name); - - RNA_string_set(op->ptr, "filepath", name); + save_set_filepath(op); /* if we're saving for the first time and prefer relative paths - any existing paths will be absolute, * enable the option to remap paths to avoid confusion [#37240] */ @@ -3030,8 +3033,11 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U } if (G.save_over) { - if (BLI_exists(name)) { - ret = WM_operator_confirm_message_ex(C, op, IFACE_("Save Over?"), ICON_QUESTION, name); + char path[FILE_MAX]; + + RNA_string_get(op->ptr, "filepath", path); + if (BLI_exists(path)) { + ret = WM_operator_confirm_message_ex(C, op, IFACE_("Save Over?"), ICON_QUESTION, path); } else { ret = wm_save_as_mainfile_exec(C, op); -- cgit v1.2.3 From d75bfdfafcfeb7fa02496be70f57e6fc15d0c397 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 9 Apr 2015 12:18:51 +0200 Subject: Fix T44308 painting in 2D editor offset by one pixel. Not sure why this was so in the first place but changing it seems OK. --- source/blender/editors/sculpt_paint/paint_image_2d.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index 9d39eea7b96..eff604658d9 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -996,8 +996,8 @@ static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos) static void paint_2d_convert_brushco(ImBuf *ibufb, const float pos[2], int ipos[2]) { - ipos[0] = (int)floorf((pos[0] - ibufb->x / 2) + 1.0f); - ipos[1] = (int)floorf((pos[1] - ibufb->y / 2) + 1.0f); + ipos[0] = (int)floorf((pos[0] - ibufb->x / 2)); + ipos[1] = (int)floorf((pos[1] - ibufb->y / 2)); } static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsigned short *texmaskb, const float lastpos[2], const float pos[2]) -- cgit v1.2.3 From 9749b2cb81add7c4fe59ec2ca828cc34369e02b3 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 9 Apr 2015 15:32:53 +0500 Subject: Fix partial image update during rendering Was broken since 5d212fb. --- source/blender/editors/render/render_internal.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index f76f7cad1ae..2e447be3f21 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -893,6 +893,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even rj->write_still = is_write_still && !is_animation; rj->iuser.scene = scene; rj->iuser.ok = 1; + rj->iuser.passtype = SCE_PASS_COMBINED; rj->reports = op->reports; rj->orig_layer = 0; rj->last_layer = 0; -- cgit v1.2.3 From 8a1c444c937cd1326d9e1b1d3302a1617b3c79f8 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 9 Apr 2015 12:48:49 +0200 Subject: Disable proportional editing when duplicating keyframes --- source/blender/editors/space_action/action_ops.c | 1 + source/blender/editors/space_graph/graph_ops.c | 1 + 2 files changed, 2 insertions(+) diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 0f21446cc3d..752863f86e0 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -106,6 +106,7 @@ void ED_operatormacros_action(void) WM_operatortype_macro_define(ot, "ACTION_OT_duplicate"); otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_transform"); RNA_enum_set(otmacro->ptr, "mode", TFM_TIME_DUPLICATE); + RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF); } /* ************************** registration - keymaps **********************************/ diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 33e8b522335..4b55a16b767 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -440,6 +440,7 @@ void ED_operatormacros_graph(void) WM_operatortype_macro_define(ot, "GRAPH_OT_duplicate"); otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_transform"); RNA_enum_set(otmacro->ptr, "mode", TFM_TIME_DUPLICATE); + RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF); } -- cgit v1.2.3 From d687428122acba3071f3eba1d60b4e8b3fce2f7b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 9 Apr 2015 21:23:03 +1000 Subject: Error in own last commit --- release/scripts/modules/bpy_types.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 94d371447d6..9b0352b7887 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -764,11 +764,12 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta): - preset_operator_defaults (dict of keyword args) """ import bpy - ext = getattr(self, "preset_extensions", {".py", ".xml"}) - ext = getattr(self, "preset_operator_defaults", None) + ext_valid = getattr(self, "preset_extensions", {".py", ".xml"}) + props_default = getattr(self, "preset_operator_defaults", None) self.path_menu(bpy.utils.preset_paths(self.preset_subdir), self.preset_operator, - filter_ext=lambda ext: ext.lower() in ext) + props_default=props_default, + filter_ext=lambda ext: ext.lower() in ext_valid) @classmethod def draw_collapsible(cls, context, layout): -- cgit v1.2.3 From 5197aa04c6bd0197b82c0266eb291ac185c4eeea Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 9 Apr 2015 16:12:20 +0200 Subject: Fix part of T44320 selecting islands can fail. Issue here is simple and has been fixed in other places such as texpainting: Basically if face has different winding, do not calculate it as adjucent to the other face, even if UV is identical. This allows us to stack islands of symmetrical closed meshes on top of one another and still be able to select the two identical island halfs (provided the normals are correct of course). --- source/blender/blenkernel/intern/mesh_mapping.c | 19 ++++++- source/blender/editors/mesh/editmesh_utils.c | 67 ++++++++++++++++--------- 2 files changed, 61 insertions(+), 25 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index 8d9fbe46f19..974e8118b15 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -30,7 +30,9 @@ #include "MEM_guardedalloc.h" #include "DNA_meshdata_types.h" +#include "DNA_vec_types.h" +#include "BLI_buffer.h" #include "BLI_utildefines.h" #include "BLI_bitmap.h" #include "BLI_math.h" @@ -62,6 +64,8 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, int i, totuv, nverts; totuv = 0; + bool *winding; + BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, 32); /* generate UvMapVert array */ mp = mpoly; @@ -72,7 +76,9 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, if (totuv == 0) return NULL; + winding = MEM_callocN(sizeof(*winding) * totpoly, "winding"); vmap = (UvVertMap *)MEM_callocN(sizeof(*vmap), "UvVertMap"); + if (!vmap) return NULL; @@ -87,6 +93,8 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, mp = mpoly; for (a = 0; a < totpoly; a++, mp++) { if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) { + float (*tf_uv)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, mp->totloop); + nverts = mp->totloop; for (i = 0; i < nverts; i++) { @@ -95,8 +103,12 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, buf->separate = 0; buf->next = vmap->vert[mloop[mp->loopstart + i].v]; vmap->vert[mloop[mp->loopstart + i].v] = buf; + + copy_v2_v2(tf_uv[i], mloopuv[mpoly[a].loopstart + i].uv); buf++; } + + winding[a] = cross_poly_v2((const float (*)[2])tf_uv, (unsigned int)nverts) > 0; } } @@ -123,7 +135,9 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, sub_v2_v2v2(uvdiff, uv2, uv); - if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1]) { + if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1] && + winding[iterv->f] == winding[v->f]) + { if (lastv) lastv->next = next; else vlist = next; iterv->next = newvlist; @@ -141,6 +155,9 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, vmap->vert[a] = newvlist; } + MEM_freeN(winding); + BLI_buffer_free(&tf_uv_buf); + return vmap; } diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 86cd75eed7a..1875689415a 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -37,6 +37,7 @@ #include "BLI_math.h" #include "BLI_alloca.h" +#include "BLI_buffer.h" #include "BLI_listbase.h" #include "BKE_DerivedMesh.h" @@ -625,11 +626,14 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2 /* MTexPoly *tf; */ /* UNUSED */ MLoopUV *luv; unsigned int a; - int totverts, i, totuv; + int totverts, i, totuv, totfaces; const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + bool *winding; + BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE); + totfaces = bm->totface; totverts = bm->totvert; totuv = 0; @@ -650,17 +654,18 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2 vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totverts, "UvMapVert_pt"); buf = vmap->buf = (UvMapVert *)MEM_callocN(sizeof(*vmap->buf) * totuv, "UvMapVert"); + winding = MEM_callocN(sizeof(*winding) * totfaces, "winding"); if (!vmap->vert || !vmap->buf) { BKE_mesh_uv_vert_map_free(vmap); return NULL; } - a = 0; - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, a) { if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) { - i = 0; - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + float (*tf_uv)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa->len); + + BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i) { buf->tfindex = i; buf->f = a; buf->separate = 0; @@ -668,17 +673,18 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2 buf->next = vmap->vert[BM_elem_index_get(l->v)]; vmap->vert[BM_elem_index_get(l->v)] = buf; + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + copy_v2_v2(tf_uv[i], luv->uv); + buf++; - i++; } - } - a++; + winding[a] = cross_poly_v2((const float (*)[2])tf_uv, efa->len) > 0; + } } /* sort individual uvs for each vert */ - a = 0; - BM_ITER_MESH (ev, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, a) { UvMapVert *newvlist = NULL, *vlist = vmap->vert[a]; UvMapVert *iterv, *v, *lastv, *next; float *uv, *uv2, uvdiff[2]; @@ -710,7 +716,9 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2 sub_v2_v2v2(uvdiff, uv2, uv); - if (fabsf(uvdiff[0]) < limit[0] && fabsf(uvdiff[1]) < limit[1]) { + if (fabsf(uvdiff[0]) < limit[0] && fabsf(uvdiff[1]) < limit[1] && + winding[iterv->f] == winding[v->f]) + { if (lastv) lastv->next = next; else vlist = next; iterv->next = newvlist; @@ -727,9 +735,11 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2 } vmap->vert[a] = newvlist; - a++; } + MEM_freeN(winding); + BLI_buffer_free(&tf_uv_buf); + return vmap; } @@ -755,9 +765,11 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo UvElement *islandbuf; /* island number for faces */ int *island_number; + bool *winding; + BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); MLoopUV *luv; - int totverts, i, totuv, j, nislands = 0, islandbufsize = 0; + int totverts, totfaces, i, totuv, j, nislands = 0, islandbufsize = 0; unsigned int *map; BMFace **stack; @@ -767,13 +779,12 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE); + totfaces = bm->totface; totverts = bm->totvert; totuv = 0; - island_number = MEM_mallocN(sizeof(*stack) * bm->totface, "uv_island_number_face"); - if (!island_number) { - return NULL; - } + island_number = MEM_mallocN(sizeof(*stack) * totfaces, "uv_island_number_face"); + winding = MEM_callocN(sizeof(*winding) * totfaces, "winding"); /* generate UvElement array */ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { @@ -801,10 +812,11 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo return NULL; } - j = 0; - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - island_number[j++] = INVALID_ISLAND; + BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, j) { + island_number[j] = INVALID_ISLAND; if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + float (*tf_uv)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa->len); + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { buf->l = l; buf->separate = 0; @@ -814,14 +826,18 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo buf->next = element_map->vert[BM_elem_index_get(l->v)]; element_map->vert[BM_elem_index_get(l->v)] = buf; + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + copy_v2_v2(tf_uv[i], luv->uv); + buf++; } + + winding[j] = cross_poly_v2((const float (*)[2])tf_uv, efa->len) > 0; } } /* sort individual uvs for each vert */ - i = 0; - BM_ITER_MESH (ev, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, i) { UvElement *newvlist = NULL, *vlist = element_map->vert[i]; UvElement *iterv, *v, *lastv, *next; float *uv, *uv2, uvdiff[2]; @@ -848,7 +864,8 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo sub_v2_v2v2(uvdiff, uv2, uv); - if (fabsf(uvdiff[0]) < STD_UV_CONNECT_LIMIT && fabsf(uvdiff[1]) < STD_UV_CONNECT_LIMIT) { + if (fabsf(uvdiff[0]) < STD_UV_CONNECT_LIMIT && fabsf(uvdiff[1]) < STD_UV_CONNECT_LIMIT && + winding[BM_elem_index_get(iterv->l->f)] == winding[BM_elem_index_get(v->l->f)]) { if (lastv) lastv->next = next; else vlist = next; iterv->next = newvlist; @@ -865,7 +882,6 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo } element_map->vert[i] = newvlist; - i++; } if (do_islands) { @@ -958,7 +974,10 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo MEM_freeN(stack); MEM_freeN(map); } + MEM_freeN(island_number); + MEM_freeN(winding); + BLI_buffer_free(&tf_uv_buf); return element_map; } -- cgit v1.2.3 From 4cadbb03a8e4f6c6e59b3d2e3b48c6376e9b385b Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 9 Apr 2015 16:17:51 +0200 Subject: Seriously... Fix building! --- source/blender/blenkernel/intern/mesh_mapping.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index 974e8118b15..ebdbd3aac8a 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -63,10 +63,11 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, unsigned int a; int i, totuv, nverts; - totuv = 0; bool *winding; BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, 32); + totuv = 0; + /* generate UvMapVert array */ mp = mpoly; for (a = 0; a < totpoly; a++, mp++) -- cgit v1.2.3 From b30a2fe3f4e0414483c8408a080fd56bc1ca5958 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 9 Apr 2015 16:32:45 +0200 Subject: Fix T44322: Crash when trying to render spotlight halos. Trying to access rl's from full samples in non-full-OSA context (with uninitialized sample index even :P ). Caused by rBd5f1b9c2, probably a copy/paste typo or so. --- source/blender/render/intern/source/rendercore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 99611a9c5a8..a634bd9780c 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -413,7 +413,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) } else { fac= ((float)R.osa-totsamp)/(float)R.osa; - pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); pass += od * 4; pass[0]+= fac*col[0]; pass[1]+= fac*col[1]; -- cgit v1.2.3 From ae5f2c202504ad23fe7d2147c0bfd8290d6dad07 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 9 Apr 2015 18:01:52 +0200 Subject: Fix regression after multiview, basically we appended the wrong frames to movie file. We have to resort to use crappy workarounds with preview arguments again since preview range is only for OpenGL preview. --- source/blender/editors/render/render_opengl.c | 2 +- source/blender/render/extern/include/RE_pipeline.h | 2 +- source/blender/render/intern/source/pipeline.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 9548b4bca68..ded2489e1e5 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -795,7 +795,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) if (is_movie) { ok = RE_WriteRenderViewsMovie(oglrender->reports, rr, scene, &scene->r, oglrender->mh, oglrender->sizex, - oglrender->sizey, oglrender->movie_ctx_arr, oglrender->totvideos); + oglrender->sizey, oglrender->movie_ctx_arr, oglrender->totvideos, PRVRANGEON != 0); if (ok) { printf("Append frame %d", scene->r.cfra); BKE_reportf(op->reports, RPT_INFO, "Appended frame: %d", scene->r.cfra); diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 2a07246eaba..482677c7585 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -264,7 +264,7 @@ void RE_TileProcessor(struct Render *re); bool RE_WriteRenderViewsImage(struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, struct Object *camera, const bool stamp, char *name); bool RE_WriteRenderViewsMovie(struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, struct RenderData *rd, struct bMovieHandle *mh, const size_t width, const size_t height, void **movie_ctx_arr, - const size_t totvideos); + const size_t totvideos, bool preview); /* only RE_NewRender() needed, main Blender render calls */ void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene, diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 05bee6f165a..cd7940e52c8 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -3233,7 +3233,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen } bool RE_WriteRenderViewsMovie(ReportList *reports, RenderResult *rr, Scene *scene, RenderData *rd, bMovieHandle *mh, - const size_t width, const size_t height, void **movie_ctx_arr, const size_t totvideos) + const size_t width, const size_t height, void **movie_ctx_arr, const size_t totvideos, bool preview) { bool is_mono; bool ok = true; @@ -3261,7 +3261,7 @@ bool RE_WriteRenderViewsMovie(ReportList *reports, RenderResult *rr, Scene *scen IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, &scene->display_settings, &scene->r.im_format); - ok &= mh->append_movie(movie_ctx_arr[view_id], rd, scene->r.sfra, scene->r.cfra, + ok &= mh->append_movie(movie_ctx_arr[view_id], rd, preview ? scene->r.psfra : scene->r.sfra, scene->r.cfra, (int *) ibuf->rect, ibuf->x, ibuf->y, suffix, reports); if (do_free) { @@ -3301,7 +3301,7 @@ bool RE_WriteRenderViewsMovie(ReportList *reports, RenderResult *rr, Scene *scen ibuf_arr[2] = IMB_stereo3d_ImBuf(&scene->r.im_format, ibuf_arr[0], ibuf_arr[1]); - ok = mh->append_movie(movie_ctx_arr[0], rd, scene->r.sfra, scene->r.cfra, (int *) ibuf_arr[2]->rect, + ok = mh->append_movie(movie_ctx_arr[0], rd, preview ? scene->r.psfra : scene->r.sfra, scene->r.cfra, (int *) ibuf_arr[2]->rect, ibuf_arr[2]->x, ibuf_arr[2]->y, "", reports); for (i = 0; i < 2; i++) { @@ -3331,7 +3331,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie /* write movie or image */ if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { - RE_WriteRenderViewsMovie(re->reports, &rres, scene, &re->r, mh, re->rectx, re->recty, re->movie_ctx_arr, totvideos); + RE_WriteRenderViewsMovie(re->reports, &rres, scene, &re->r, mh, re->rectx, re->recty, re->movie_ctx_arr, totvideos, false); } else { if (name_override) -- cgit v1.2.3 From cca4405437363bd1cb3d8ee9a77691fd8225d76f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 9 Apr 2015 21:21:48 +0500 Subject: Cycles: Fix wrong render result in certain configuration of render layer's surface/hair There were some synchronization missing in cases when only one of those settings was disabled. Also added a render test for such configurations now. --- intern/cycles/blender/blender_mesh.cpp | 14 ++++++++++---- intern/cycles/render/mesh.cpp | 2 +- intern/cycles/render/mesh.h | 9 +++++++-- tests/python/CMakeLists.txt | 6 ++++++ 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index deae36f0130..d88ebb854d2 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -621,7 +621,13 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri } /* test if we need to sync */ - bool use_mesh_geometry = render_layer.use_surfaces || render_layer.use_hair; + int requested_geometry_flags = Mesh::GEOMETRY_NONE; + if(render_layer.use_surfaces) { + requested_geometry_flags |= Mesh::GEOMETRY_TRIANGLES; + } + if(render_layer.use_hair) { + requested_geometry_flags |= Mesh::GEOMETRY_CURVES; + } Mesh *mesh; if(!mesh_map.sync(&mesh, key)) { @@ -630,7 +636,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri /* test if shaders changed, these can be object level so mesh * does not get tagged for recalc */ else if(mesh->used_shaders != used_shaders); - else if(use_mesh_geometry != mesh->geometry_synced); + else if(requested_geometry_flags != mesh->geometry_flags); else { /* even if not tagged for recalc, we may need to sync anyway * because the shader needs different mesh attributes */ @@ -664,7 +670,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri mesh->used_shaders = used_shaders; mesh->name = ustring(b_ob_data.name().c_str()); - if(use_mesh_geometry) { + if(requested_geometry_flags != Mesh::GEOMETRY_NONE) { /* mesh objects does have special handle in the dependency graph, * they're ensured to have properly updated. * @@ -697,8 +703,8 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri /* free derived mesh */ b_data.meshes.remove(b_mesh); } - mesh->geometry_synced = true; } + mesh->geometry_flags = requested_geometry_flags; /* displacement method */ if(cmesh.data) { diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 1d453164aa8..b31e09c6ef9 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -135,7 +135,7 @@ void Mesh::clear() transform_applied = false; transform_negative_scaled = false; transform_normal = transform_identity(); - geometry_synced = false; + geometry_flags = GEOMETRY_NONE; } int Mesh::split_vertex(int vertex) diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index 62e775e5bc9..6eaafea8729 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -71,8 +71,13 @@ public: ustring name; /* Mesh Data */ - bool geometry_synced; /* used to distinguish meshes with no verts - and meshed for which geometry is not created */ + enum GeometryFlags { + GEOMETRY_NONE = 0, + GEOMETRY_TRIANGLES = (1 << 0), + GEOMETRY_CURVES = (1 << 1), + }; + int geometry_flags; /* used to distinguish meshes with no verts + and meshed for which geometry is not created */ vector verts; vector triangles; diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index fd47bba4182..81438d357e4 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -395,6 +395,12 @@ if(WITH_CYCLES) -testdir "${TEST_SRC_DIR}/cycles/ctests/reports" -idiff "${OPENIMAGEIO_IDIFF}" ) + add_test(cycles_render_test + ${CMAKE_CURRENT_LIST_DIR}/cycles_render_tests.py + -blender "${TEST_BLENDER_EXE_BARE}" + -testdir "${TEST_SRC_DIR}/cycles/ctests/render" + -idiff "${OPENIMAGEIO_IDIFF}" + ) add_test(cycles_shaders_test ${CMAKE_CURRENT_LIST_DIR}/cycles_render_tests.py -blender "${TEST_BLENDER_EXE_BARE}" -- cgit v1.2.3 From 851ea206d05b4d91423bc754ab2cc4bb0d1f6f38 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 9 Apr 2015 18:29:58 +0200 Subject: Separate proportional editing options for graph and action editor. --- release/scripts/startup/bl_ui/space_dopesheet.py | 8 +++++--- release/scripts/startup/bl_ui/space_graph.py | 9 ++++++--- source/blender/editors/space_action/action_ops.c | 6 ++---- source/blender/editors/space_graph/graph_ops.c | 6 ++---- source/blender/editors/transform/transform.c | 6 +++++- source/blender/editors/transform/transform_generics.c | 7 +++++-- source/blender/makesdna/DNA_scene_types.h | 5 ++++- source/blender/makesrna/intern/rna_scene.c | 12 ++++++++++++ 8 files changed, 41 insertions(+), 18 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 843cf41b07c..799431118fb 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -135,9 +135,11 @@ class DOPESHEET_HT_header(Header): dopesheet_filter(layout, context, genericFiltersOnly=True) row = layout.row(align=True) - row.prop(toolsettings, "proportional_edit", icon_only=True) - if toolsettings.proportional_edit != 'DISABLED': - row.prop(toolsettings, "proportional_edit_falloff", icon_only=True) + row.prop(toolsettings, "use_proportional_action", + text="", icon_only=True) + if toolsettings.use_proportional_action: + row.prop(toolsettings, "proportional_edit_falloff", + text="", icon_only=True) # Grease Pencil mode doesn't need snapping, as it's frame-aligned only if st.mode != 'GPENCIL': diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index 4c3f4bb695e..485bd271060 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -48,9 +48,12 @@ class GRAPH_HT_header(Header): row.prop(st, "use_auto_normalization", text="Auto") row = layout.row(align=True) - row.prop(toolsettings, "proportional_edit", icon_only=True) - if toolsettings.proportional_edit != 'DISABLED': - row.prop(toolsettings, "proportional_edit_falloff", icon_only=True) + + row.prop(toolsettings, "use_proportional_ipo", + text="", icon_only=True) + if toolsettings.use_proportional_ipo: + row.prop(toolsettings, "proportional_edit_falloff", + text="", icon_only=True) layout.prop(st, "auto_snap", text="") layout.prop(st, "pivot_point", icon_only=True) diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 752863f86e0..0ecd8b31d37 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -241,10 +241,8 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* transform system */ transform_keymap_for_space(keyconf, keymap, SPACE_ACTION); - kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", OKEY, KM_PRESS, 0, 0); - RNA_string_set(kmi->ptr, "data_path", "tool_settings.proportional_edit"); - RNA_string_set(kmi->ptr, "value_1", "DISABLED"); - RNA_string_set(kmi->ptr, "value_2", "ENABLED"); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", OKEY, KM_PRESS, 0, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_proportional_action"); /* special markers hotkeys for anim editors: see note in definition of this function */ ED_marker_keymap_animedit_conflictfree(keymap); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 4b55a16b767..5ca7d156a1e 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -608,10 +608,8 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* transform system */ transform_keymap_for_space(keyconf, keymap, SPACE_IPO); - kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", OKEY, KM_PRESS, 0, 0); - RNA_string_set(kmi->ptr, "data_path", "tool_settings.proportional_edit"); - RNA_string_set(kmi->ptr, "value_1", "DISABLED"); - RNA_string_set(kmi->ptr, "value_2", "ENABLED"); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", OKEY, KM_PRESS, 0, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_proportional_ipo"); /* pivot point settings */ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 0d5e496ee07..ddd2df80d1a 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1938,7 +1938,11 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) if ((prop = RNA_struct_find_property(op->ptr, "proportional")) && !RNA_property_is_set(op->ptr, prop)) { - if (t->obedit) + if (t->spacetype == SPACE_IPO) + ts->proportional_ipo = proportional; + else if (t->spacetype == SPACE_ACTION) + ts->proportional_action = proportional; + else if (t->obedit) ts->proportional = proportional; else if (t->options & CTX_MASK) ts->proportional_mask = (proportional != PROP_EDIT_OFF); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 27a072c301b..b27f7c5ae12 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1320,8 +1320,11 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve /* use settings from scene only if modal */ if (t->flag & T_MODAL) { if ((t->options & CTX_NO_PET) == 0) { - if (ELEM(t->spacetype, SPACE_IPO, SPACE_ACTION)) { - t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional); + if (t->spacetype == SPACE_IPO) { + t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_ipo); + } + else if (t->spacetype == SPACE_ACTION) { + t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_action); } else if (t->obedit) { t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 250bfe85ec2..ed63aefa4df 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1269,7 +1269,10 @@ typedef struct ToolSettings { short snap_flag, snap_target; short proportional, prop_mode; char proportional_objects; /* proportional edit, object mode */ - char proportional_mask; /* proportional edit, object mode */ + char proportional_mask; /* proportional edit, mask editing */ + char proportional_action; /* proportional edit, action editor */ + char proportional_ipo; /* proportional edit, graph editor */ + char pad4[6]; char auto_normalize; /*auto normalizing mode in wpaint*/ char multipaint; /* paint multiple bones in wpaint */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 3bcac9c6696..696f1b996d4 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2168,6 +2168,18 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + prop = RNA_def_property(srna, "use_proportional_action", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "proportional_action", 0); + RNA_def_property_ui_text(prop, "Proportional Editing Actions", "Proportional editing in action editor"); + RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + + prop = RNA_def_property(srna, "use_proportional_ipo", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "proportional_ipo", 0); + RNA_def_property_ui_text(prop, "Proportional Editing Ipo Curves", "Proportional editing in ipo editor"); + RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + prop = RNA_def_property(srna, "proportional_edit_falloff", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "prop_mode"); RNA_def_property_enum_items(prop, proportional_falloff_items); -- cgit v1.2.3 From 7ea4163e1e5a33d38573371c8b19969b051d5ea2 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 9 Apr 2015 22:23:59 +0500 Subject: Cycles: Fix BVH counter on mesh updates --- intern/cycles/render/mesh.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index b31e09c6ef9..6cf75a287e5 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -1215,7 +1215,9 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen &progress, i, num_bvh)); - i++; + if(!mesh->transform_applied) { + i++; + } } } -- cgit v1.2.3 From 866532360c75298c88dc51724e878255295b98df Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 9 Apr 2015 20:20:33 +0200 Subject: Fix T31546 fragment program gets created every frame That was really crappy indeed. Now we have a separate API for low level OpenGL programs, plus a nice interface for GPU, also removes some GL calls from main code as a plus :) The source for the programs is also moved to nice external .glsl files (not sure which extension convention GPU assemply uses) --- SConstruct | 3 + source/blender/editors/space_view3d/drawvolume.c | 101 +++--------------- source/blender/gpu/CMakeLists.txt | 5 + source/blender/gpu/GPU_extensions.h | 25 ++++- source/blender/gpu/SConscript | 2 + source/blender/gpu/intern/gpu_extensions.c | 115 ++++++++++++++++++++- .../gpu/shaders/gpu_program_smoke_color_frag.glsl | 32 ++++++ .../gpu/shaders/gpu_program_smoke_frag.glsl | 27 +++++ 8 files changed, 215 insertions(+), 95 deletions(-) create mode 100644 source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl create mode 100644 source/blender/gpu/shaders/gpu_program_smoke_frag.glsl diff --git a/SConstruct b/SConstruct index 7cdc4b35206..6cf3874b366 100644 --- a/SConstruct +++ b/SConstruct @@ -758,6 +758,9 @@ if B.targets != ['cudakernels']: data_to_c_simple("release/datafiles/preview_cycles.blend") # --- glsl --- + data_to_c_simple("source/blender/gpu/shaders/gpu_program_smoke_frag.glsl") + data_to_c_simple("source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl") + data_to_c_simple("source/blender/gpu/shaders/gpu_shader_simple_frag.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_simple_vert.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_material.glsl") diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index 92883f28836..c0d8d139ddd 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -135,76 +135,8 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, unsigned char *spec_data; float *spec_pixels; GPUTexture *tex_spec; - - /* Fragment program to calculate the view3d of smoke */ - /* using 4 textures, density, shadow, flame and flame spectrum */ - const char *shader_basic = - "!!ARBfp1.0\n" - "PARAM dx = program.local[0];\n" - "PARAM darkness = program.local[1];\n" - "PARAM render = program.local[2];\n" - "PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n" - "TEMP temp, shadow, flame, spec, value;\n" - "TEX temp, fragment.texcoord[0], texture[0], 3D;\n" - "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n" - "TEX flame, fragment.texcoord[0], texture[2], 3D;\n" - "TEX spec, flame.r, texture[3], 1D;\n" - /* calculate shading factor from density */ - "MUL value.r, temp.a, darkness.a;\n" - "MUL value.r, value.r, dx.r;\n" - "MUL value.r, value.r, f.r;\n" - "EX2 temp, -value.r;\n" - /* alpha */ - "SUB temp.a, 1.0, temp.r;\n" - /* shade colors */ - "MUL temp.r, temp.r, shadow.r;\n" - "MUL temp.g, temp.g, shadow.r;\n" - "MUL temp.b, temp.b, shadow.r;\n" - "MUL temp.r, temp.r, darkness.r;\n" - "MUL temp.g, temp.g, darkness.g;\n" - "MUL temp.b, temp.b, darkness.b;\n" - /* for now this just replace smoke shading if rendering fire */ - "CMP result.color, render.r, temp, spec;\n" - "END\n"; - - /* color shader */ - const char *shader_color = - "!!ARBfp1.0\n" - "PARAM dx = program.local[0];\n" - "PARAM darkness = program.local[1];\n" - "PARAM render = program.local[2];\n" - "PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041};\n" - "TEMP temp, shadow, flame, spec, value;\n" - "TEX temp, fragment.texcoord[0], texture[0], 3D;\n" - "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n" - "TEX flame, fragment.texcoord[0], texture[2], 3D;\n" - "TEX spec, flame.r, texture[3], 1D;\n" - /* unpremultiply volume texture */ - "RCP value.r, temp.a;\n" - "MUL temp.r, temp.r, value.r;\n" - "MUL temp.g, temp.g, value.r;\n" - "MUL temp.b, temp.b, value.r;\n" - /* calculate shading factor from density */ - "MUL value.r, temp.a, darkness.a;\n" - "MUL value.r, value.r, dx.r;\n" - "MUL value.r, value.r, f.r;\n" - "EX2 value.r, -value.r;\n" - /* alpha */ - "SUB temp.a, 1.0, value.r;\n" - /* shade colors */ - "MUL temp.r, temp.r, shadow.r;\n" - "MUL temp.g, temp.g, shadow.r;\n" - "MUL temp.b, temp.b, shadow.r;\n" - "MUL temp.r, temp.r, value.r;\n" - "MUL temp.g, temp.g, value.r;\n" - "MUL temp.b, temp.b, value.r;\n" - /* for now this just replace smoke shading if rendering fire */ - "CMP result.color, render.r, temp, spec;\n" - "END\n"; - - GLuint prog; - - + GPUProgram *smoke_program; + int progtype = (sds->active_fields & SM_ACTIVE_COLORS) ? GPU_PROGRAM_SMOKE_COLORED : GPU_PROGRAM_SMOKE; float size[3]; if (!tex) { @@ -349,24 +281,17 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, // printf("i: %d\n", i); // printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]); - if (GL_TRUE == glewIsSupported("GL_ARB_fragment_program")) { - glEnable(GL_FRAGMENT_PROGRAM_ARB); - glGenProgramsARB(1, &prog); - - glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog); - /* set shader */ - if (sds->active_fields & SM_ACTIVE_COLORS) - glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_color), shader_color); - else - glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_basic), shader_basic); + smoke_program = GPU_shader_get_builtin_program(progtype); + if (smoke_program) { + GPU_program_bind(smoke_program); /* cell spacing */ - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0); + GPU_program_parameter_4f(smoke_program, 0, dx, dx, dx, 1.0); /* custom parameter for smoke style (higher = thicker) */ if (sds->active_fields & SM_ACTIVE_COLORS) - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1.0, 1.0, 1.0, 10.0); + GPU_program_parameter_4f(smoke_program, 1, 1.0, 1.0, 1.0, 10.0); else - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0); + GPU_program_parameter_4f(smoke_program, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0); } else printf("Your gfx card does not support 3D View smoke drawing.\n"); @@ -446,7 +371,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, else glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, 1.0, 0.0, 0.0, 0.0); + GPU_program_parameter_4f(smoke_program, 2, 1.0, 0.0, 0.0, 0.0); glBegin(GL_POLYGON); glColor3f(1.0, 1.0, 1.0); for (i = 0; i < numpoints; i++) { @@ -466,7 +391,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, -1.0, 0.0, 0.0, 0.0); + GPU_program_parameter_4f(smoke_program, 2, -1.0, 0.0, 0.0, 0.0); glBegin(GL_POLYGON); glColor3f(1.0, 1.0, 1.0); for (i = 0; i < numpoints; i++) { @@ -499,10 +424,8 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, free(spec_data); free(spec_pixels); - if (GLEW_ARB_fragment_program) { - glDisable(GL_FRAGMENT_PROGRAM_ARB); - glDeleteProgramsARB(1, &prog); - } + if (smoke_program) + GPU_program_unbind(smoke_program); MEM_freeN(points); diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 97b0e7e1e0e..23a2b77d1e7 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -57,6 +57,9 @@ set(SRC intern/gpu_compositing.c intern/gpu_debug.c + shaders/gpu_program_smoke_frag.glsl + shaders/gpu_program_smoke_color_frag.glsl + shaders/gpu_shader_fx_lib.glsl shaders/gpu_shader_fx_ssao_frag.glsl shaders/gpu_shader_fx_dof_frag.glsl @@ -89,6 +92,8 @@ set(SRC intern/gpu_private.h ) +data_to_c_simple(shaders/gpu_program_smoke_frag.glsl SRC) +data_to_c_simple(shaders/gpu_program_smoke_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_material.glsl SRC) data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_vert.glsl SRC) diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index de0af815bf4..27a4396e5d8 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -52,6 +52,9 @@ typedef struct GPUOffScreen GPUOffScreen; struct GPUShader; typedef struct GPUShader GPUShader; +struct GPUProgram; +typedef struct GPUProgram GPUProgram; + /* GPU extensions support */ void GPU_extensions_disable(void); @@ -181,6 +184,18 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels); int GPU_offscreen_width(const GPUOffScreen *ofs); int GPU_offscreen_height(const GPUOffScreen *ofs); +/* Builtin/Non-generated shaders */ +typedef enum GPUProgramType { + GPU_PROGRAM_TYPE_FRAGMENT = 0 +} GPUProgramType; + + +GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code); +void GPU_program_free(GPUProgram *program); +void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w); +void GPU_program_bind(GPUProgram *); +void GPU_program_unbind(GPUProgram *); + /* GPU Shader * - only for fragment shaders now * - must call texture bind before setting a texture as uniform! */ @@ -205,11 +220,17 @@ int GPU_shader_get_attribute(GPUShader *shader, const char *name); /* Builtin/Non-generated shaders */ typedef enum GPUBuiltinShader { - GPU_SHADER_VSM_STORE = (1<<0), - GPU_SHADER_SEP_GAUSSIAN_BLUR = (1<<1), + GPU_SHADER_VSM_STORE = 0, + GPU_SHADER_SEP_GAUSSIAN_BLUR = 1, } GPUBuiltinShader; +typedef enum GPUBuiltinProgram { + GPU_PROGRAM_SMOKE = 0, + GPU_PROGRAM_SMOKE_COLORED = 1, +} GPUBuiltinProgram; + GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader); +GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program); GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp); void GPU_shader_free_builtin_shaders(void); diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript index 8d0ef394a06..ff5fb42c021 100644 --- a/source/blender/gpu/SConscript +++ b/source/blender/gpu/SConscript @@ -63,6 +63,8 @@ if env['WITH_BF_DDS']: # generated data files import os sources.extend(( + os.path.join(env['DATA_SOURCES'], "gpu_program_smoke_frag.glsl.c"), + os.path.join(env['DATA_SOURCES'], "gpu_program_smoke_color_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_vert.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_ssao_frag.glsl.c"), diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 363e19908e5..e8595ecc67c 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -77,6 +77,8 @@ */ /* Non-generated shaders */ +extern char datatoc_gpu_program_smoke_frag_glsl[]; +extern char datatoc_gpu_program_smoke_color_frag_glsl[]; extern char datatoc_gpu_shader_vsm_store_vert_glsl[]; extern char datatoc_gpu_shader_vsm_store_frag_glsl[]; extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[]; @@ -94,6 +96,8 @@ extern char datatoc_gpu_shader_fx_lib_glsl[]; typedef struct GPUShaders { GPUShader *vsm_store; GPUShader *sep_gaussian_blur; + GPUProgram *smoke; + GPUProgram *smoke_colored; /* cache for shader fx. Those can exist in combinations so store them here */ GPUShader *fx_shaders[MAX_FX_SHADERS * 2]; } GPUShaders; @@ -1430,7 +1434,13 @@ struct GPUShader { int uniforms; /* required uniforms */ }; -static void shader_print_errors(const char *task, char *log, const char **code, int totcode) +struct GPUProgram { + GPUProgramType type; + GLuint prog; +}; + + +static void shader_print_errors(const char *task, const char *log, const char **code, int totcode) { int i; int line = 1; @@ -1504,6 +1514,70 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH]) return; } +void GPU_program_bind(GPUProgram *program) +{ + glEnable(program->type); + glBindProgramARB(program->type, program->prog); +} + +void GPU_program_unbind(GPUProgram *program) +{ + glDisable(program->type); + glBindProgramARB(program->type, 0); +} + + +GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code) +{ + GPUProgram *program; + GLint error_pos, is_native; + + if (!(GLEW_ARB_fragment_program && type == GPU_PROGRAM_TYPE_FRAGMENT)) + return NULL; + + program = MEM_callocN(sizeof(GPUProgram), "GPUProgram"); + + switch (type) { + case GPU_PROGRAM_TYPE_FRAGMENT: + program->type = GL_FRAGMENT_PROGRAM_ARB; + break; + } + + /* create the object and set its code string */ + glGenProgramsARB(1, &program->prog); + glBindProgramARB(program->type, program->prog); + + glProgramStringARB(program->type, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(code), code); + + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos); + glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &is_native); + if ((error_pos == -1) && (is_native == 1)) { + return program; + } + else { + /* glGetError is set before that, clear it */ + while (glGetError() != GL_NO_ERROR) + ; + shader_print_errors("compile", (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB), &code, 1); + MEM_freeN(program); + } + + return NULL; +} + +void GPU_program_free(GPUProgram *program) +{ + glDeleteProgramsARB(1, &program->prog); + MEM_freeN(program); +} + +void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w) +{ + glProgramLocalParameter4fARB(program->type, location, x, y, z, w); +} + + + GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines, int input, int output, int number) { GLint status; @@ -1824,6 +1898,29 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) return retval; } +GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program) +{ + GPUProgram *retval = NULL; + + switch (program) { + case GPU_PROGRAM_SMOKE: + if (!GG.shaders.smoke) + GG.shaders.smoke = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_frag_glsl); + retval = GG.shaders.smoke; + break; + case GPU_PROGRAM_SMOKE_COLORED: + if (!GG.shaders.smoke_colored) + GG.shaders.smoke_colored = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_color_frag_glsl); + retval = GG.shaders.smoke_colored; + break; + } + + if (retval == NULL) + printf("Unable to create a GPUProgram for builtin program: %d\n", program); + + return retval; +} + #define MAX_DEFINES 100 GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp) @@ -1905,18 +2002,28 @@ void GPU_shader_free_builtin_shaders(void) int i; if (GG.shaders.vsm_store) { - MEM_freeN(GG.shaders.vsm_store); + GPU_shader_free(GG.shaders.vsm_store); GG.shaders.vsm_store = NULL; } if (GG.shaders.sep_gaussian_blur) { - MEM_freeN(GG.shaders.sep_gaussian_blur); + GPU_shader_free(GG.shaders.sep_gaussian_blur); GG.shaders.sep_gaussian_blur = NULL; } + if (GG.shaders.smoke) { + GPU_program_free(GG.shaders.smoke); + GG.shaders.smoke = NULL; + } + + if (GG.shaders.smoke_colored) { + GPU_program_free(GG.shaders.smoke_colored); + GG.shaders.smoke_colored = NULL; + } + for (i = 0; i < 2 * MAX_FX_SHADERS; i++) { if (GG.shaders.fx_shaders[i]) { - MEM_freeN(GG.shaders.fx_shaders[i]); + GPU_shader_free(GG.shaders.fx_shaders[i]); GG.shaders.fx_shaders[i] = NULL; } } diff --git a/source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl b/source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl new file mode 100644 index 00000000000..a94c823f408 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl @@ -0,0 +1,32 @@ +!!ARBfp1.0 +PARAM dx = program.local[0]; +PARAM darkness = program.local[1]; +PARAM render = program.local[2]; +PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041}; +TEMP temp, shadow, flame, spec, value; +TEX temp, fragment.texcoord[0], texture[0], 3D; +TEX shadow, fragment.texcoord[0], texture[1], 3D; +TEX flame, fragment.texcoord[0], texture[2], 3D; +TEX spec, flame.r, texture[3], 1D; +# unpremultiply volume texture +RCP value.r, temp.a; +MUL temp.r, temp.r, value.r; +MUL temp.g, temp.g, value.r; +MUL temp.b, temp.b, value.r; +# calculate shading factor from density +MUL value.r, temp.a, darkness.a; +MUL value.r, value.r, dx.r; +MUL value.r, value.r, f.r; +EX2 value.r, -value.r; +# alpha +SUB temp.a, 1.0, value.r; +# shade colors +MUL temp.r, temp.r, shadow.r; +MUL temp.g, temp.g, shadow.r; +MUL temp.b, temp.b, shadow.r; +MUL temp.r, temp.r, value.r; +MUL temp.g, temp.g, value.r; +MUL temp.b, temp.b, value.r; +# for now this just replace smoke shading if rendering fire +CMP result.color, render.r, temp, spec; +END diff --git a/source/blender/gpu/shaders/gpu_program_smoke_frag.glsl b/source/blender/gpu/shaders/gpu_program_smoke_frag.glsl new file mode 100644 index 00000000000..04b171d24bd --- /dev/null +++ b/source/blender/gpu/shaders/gpu_program_smoke_frag.glsl @@ -0,0 +1,27 @@ +!!ARBfp1.0 +PARAM dx = program.local[0]; +PARAM darkness = program.local[1]; +PARAM render = program.local[2]; +PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01}; +TEMP temp, shadow, flame, spec, value; +TEX temp, fragment.texcoord[0], texture[0], 3D; +TEX shadow, fragment.texcoord[0], texture[1], 3D; +TEX flame, fragment.texcoord[0], texture[2], 3D; +TEX spec, flame.r, texture[3], 1D; +# calculate shading factor from density +MUL value.r, temp.a, darkness.a; +MUL value.r, value.r, dx.r; +MUL value.r, value.r, f.r; +EX2 temp, -value.r; +# alpha +SUB temp.a, 1.0, temp.r; +# shade colors +MUL temp.r, temp.r, shadow.r; +MUL temp.g, temp.g, shadow.r; +MUL temp.b, temp.b, shadow.r; +MUL temp.r, temp.r, darkness.r; +MUL temp.g, temp.g, darkness.g; +MUL temp.b, temp.b, darkness.b; +# for now this just replace smoke shading if rendering fire +CMP result.color, render.r, temp, spec; +END -- cgit v1.2.3 From 33028d17a006dc9fd8f806fe40a97c14b3b69fd8 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 9 Apr 2015 15:20:45 -0300 Subject: =?UTF-8?q?Multiview:=20fix=20crashes=20with=20pageflip=20mode=20-?= =?UTF-8?q?=20by=20C=C3=A9dric=20Paille=20(cedricp)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/blender/windowmanager/intern/wm_stereo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 9e9a9739cc0..240e35b2e3d 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -79,6 +79,8 @@ static void wm_method_draw_stereo3d_pageflip(wmWindow *win) wm_triple_draw_textures(win, drawdata->triple, 1.0f); } + + glDrawBuffer(GL_BACK); } static GLuint left_interlace_mask[32]; -- cgit v1.2.3 From 52f511269b98efa804ce7fcc99039ef22190cf29 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 9 Apr 2015 20:43:59 -0300 Subject: Multiview: remove option to preview the selected stereo 3d mode and error when quadbuffer not supported This was causing glitches when switching from/to fullscreen modes (e.g., side by side to anaglyph). As for the quadbuffer errors this is part of a more complete solution to be committed later. --- source/blender/windowmanager/intern/wm_stereo.c | 55 +++++++++++++++---------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 240e35b2e3d..38f1cf68ac8 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -352,6 +352,13 @@ void wm_method_draw_stereo3d(const bContext *UNUSED(C), wmWindow *win) } } +static bool wm_stereo3d_quadbuffer_supported() +{ + int gl_stereo = 0; + glGetBooleanv(GL_STEREO, (GLboolean *)&gl_stereo); + return gl_stereo != 0; +} + static bool wm_stereo3d_is_fullscreen_required(eStereoDisplayMode stereo_display) { return ELEM(stereo_display, @@ -364,11 +371,14 @@ bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check) { bScreen *screen = win->screen; - if ((skip_stereo3d_check == false) && (ED_screen_stereo3d_required(screen) == false)) + if ((skip_stereo3d_check == false) && (ED_screen_stereo3d_required(screen) == false)) { return false; + } if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) { - return (GHOST_GetWindowState(win->ghostwin) == GHOST_kWindowStateFullScreen); + if (GHOST_GetWindowState(win->ghostwin) != GHOST_kWindowStateFullScreen) { + return false; + } } return true; @@ -379,10 +389,10 @@ typedef struct Stereo3dData { Stereo3dFormat stereo3d_format; } Stereo3dData; -static bool wm_stereo3d_set_properties(bContext *C, wmOperator *op) +static bool wm_stereo3d_set_properties(bContext *UNUSED(C), wmOperator *op) { - wmWindow *win = CTX_wm_window(C); - Stereo3dFormat *s3d = win->stereo3d_format; + Stereo3dData *s3dd = op->customdata; + Stereo3dFormat *s3d = &s3dd->stereo3d_format; PropertyRNA *prop; bool is_set = false; @@ -441,12 +451,24 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); const bool is_fullscreen = WM_window_is_fullscreen(win); + char display_mode = win->stereo3d_format->display_mode; if (G.background) return OPERATOR_CANCELLED; - /* pagelfip requires a new window to be created with the proper OS flags */ + if (op->customdata) { + Stereo3dData *s3dd = op->customdata; + *win->stereo3d_format = s3dd->stereo3d_format; + } + + /* pageflip requires a new window to be created with the proper OS flags */ if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { + if (wm_stereo3d_quadbuffer_supported() == false) { + BKE_reportf(op->reports, RPT_ERROR, + "Quadbuffer not supported by the system"); + win->stereo3d_format->display_mode = display_mode; + return OPERATOR_CANCELLED; + } if (wm_window_duplicate_exec(C, op) == OPERATOR_FINISHED) { wm_window_close(C, wm, win); win = wm->windows.last; @@ -454,6 +476,7 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) else { BKE_reportf(op->reports, RPT_ERROR, "Fail to create a window compatible with time sequential (page-flip) display method"); + win->stereo3d_format->display_mode = display_mode; return OPERATOR_CANCELLED; } } @@ -482,21 +505,19 @@ int wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(ev return WM_operator_props_dialog_popup(C, op, 250, 100); } -void wm_stereo3d_set_draw(bContext *C, wmOperator *op) +void wm_stereo3d_set_draw(bContext *UNUSED(C), wmOperator *op) { - wmWindow *win = CTX_wm_window(C); - Stereo3dFormat *stereo3d_format; + Stereo3dData *s3dd = op->customdata; PointerRNA stereo3d_format_ptr; uiLayout *layout = op->layout; uiLayout *col; - stereo3d_format = win->stereo3d_format; - RNA_pointer_create(NULL, &RNA_Stereo3dDisplay, stereo3d_format, &stereo3d_format_ptr); + RNA_pointer_create(NULL, &RNA_Stereo3dDisplay, &s3dd->stereo3d_format, &stereo3d_format_ptr); col = uiLayoutColumn(layout, false); uiItemR(col, &stereo3d_format_ptr, "display_mode", 0, NULL, ICON_NONE); - switch (stereo3d_format->display_mode) { + switch (s3dd->stereo3d_format.display_mode) { case S3D_DISPLAY_ANAGLYPH: { uiItemR(col, &stereo3d_format_ptr, "anaglyph_type", 0, NULL, ICON_NONE); @@ -530,16 +551,8 @@ bool wm_stereo3d_set_check(bContext *UNUSED(C), wmOperator *UNUSED(op)) return true; } -void wm_stereo3d_set_cancel(bContext *C, wmOperator *op) +void wm_stereo3d_set_cancel(bContext *UNUSED(C), wmOperator *op) { - Stereo3dData *s3dd = op->customdata; - wmWindow *win = CTX_wm_window(C); - - /* roll back to the original */ - if (win) { - *win->stereo3d_format = s3dd->stereo3d_format; - } - MEM_freeN(op->customdata); op->customdata = NULL; } -- cgit v1.2.3 From f2452bc9ab9797293c4b51fa022f6a6de82d52e3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 10 Apr 2015 11:38:30 +1000 Subject: Test: blacklist loading addons /w known problems The test now runs without warnings --- tests/python/bl_load_addons.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tests/python/bl_load_addons.py b/tests/python/bl_load_addons.py index 227edf4164d..85b2f1270f5 100644 --- a/tests/python/bl_load_addons.py +++ b/tests/python/bl_load_addons.py @@ -34,11 +34,28 @@ import imp BLACKLIST_DIRS = ( os.path.join(bpy.utils.resource_path('USER'), "scripts"), ) + tuple(addon_utils.paths()[1:]) +BLACKLIST_ADDONS = set() + +def _init_addon_blacklist(): + + # in case we built without cycles + if not bpy.app.build_options.cycles: + BLACKLIST_ADDONS.add("cycles") + + # in case we built without freestyle + if not bpy.app.build_options.freestyle: + BLACKLIST_ADDONS.add("render_freestyle_svg") + + # netrender has known problems re-registering + BLACKLIST_ADDONS.add("netrender") def addon_modules_sorted(): modules = addon_utils.modules({}) - modules[:] = [mod for mod in modules if not mod.__file__.startswith(BLACKLIST_DIRS)] + modules[:] = [ + mod for mod in modules + if not (mod.__file__.startswith(BLACKLIST_DIRS)) + if not (mod.__name__ in BLACKLIST_ADDONS)] modules.sort(key=lambda mod: mod.__name__) return modules @@ -64,7 +81,7 @@ def test_load_addons(): mod_name = mod.__name__ print("\tenabling:", mod_name) addon_utils.enable(mod_name, default_set=True) - if mod_name not in addons: + if (mod_name not in addons) and (mod_name not in BLACKLIST_ADDONS): addons_fail.append(mod_name) if addons_fail: @@ -106,6 +123,9 @@ def reload_addons(do_reload=True, do_reverse=True): def main(): + + _init_addon_blacklist() + # first load addons, print a list of all addons that fail test_load_addons() -- cgit v1.2.3 From 31d354dfa34306dfa94671e3c6fb11666e6bb48b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 10 Apr 2015 13:41:57 +1000 Subject: rename _ipo -> _fcurve --- release/scripts/startup/bl_ui/space_graph.py | 2 +- source/blender/editors/space_graph/graph_ops.c | 2 +- source/blender/editors/transform/transform.c | 2 +- source/blender/editors/transform/transform_generics.c | 2 +- source/blender/makesdna/DNA_scene_types.h | 2 +- source/blender/makesrna/intern/rna_scene.c | 6 +++--- source/blender/windowmanager/intern/wm_stereo.c | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index 485bd271060..c00e0a1f9d9 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -49,7 +49,7 @@ class GRAPH_HT_header(Header): row = layout.row(align=True) - row.prop(toolsettings, "use_proportional_ipo", + row.prop(toolsettings, "use_proportional_fcurve", text="", icon_only=True) if toolsettings.use_proportional_ipo: row.prop(toolsettings, "proportional_edit_falloff", diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 5ca7d156a1e..7032c98ada7 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -609,7 +609,7 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) transform_keymap_for_space(keyconf, keymap, SPACE_IPO); kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", OKEY, KM_PRESS, 0, 0); - RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_proportional_ipo"); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_proportional_fcurve"); /* pivot point settings */ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index ddd2df80d1a..be33dfd5e20 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1939,7 +1939,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) !RNA_property_is_set(op->ptr, prop)) { if (t->spacetype == SPACE_IPO) - ts->proportional_ipo = proportional; + ts->proportional_fcurve = proportional; else if (t->spacetype == SPACE_ACTION) ts->proportional_action = proportional; else if (t->obedit) diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index b27f7c5ae12..243b54b04d5 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1321,7 +1321,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve if (t->flag & T_MODAL) { if ((t->options & CTX_NO_PET) == 0) { if (t->spacetype == SPACE_IPO) { - t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_ipo); + t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_fcurve); } else if (t->spacetype == SPACE_ACTION) { t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_action); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index ed63aefa4df..2f54dfa8116 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1271,7 +1271,7 @@ typedef struct ToolSettings { char proportional_objects; /* proportional edit, object mode */ char proportional_mask; /* proportional edit, mask editing */ char proportional_action; /* proportional edit, action editor */ - char proportional_ipo; /* proportional edit, graph editor */ + char proportional_fcurve; /* proportional edit, graph editor */ char pad4[6]; char auto_normalize; /*auto normalizing mode in wpaint*/ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 696f1b996d4..f93cdc5715d 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2174,9 +2174,9 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - prop = RNA_def_property(srna, "use_proportional_ipo", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "proportional_ipo", 0); - RNA_def_property_ui_text(prop, "Proportional Editing Ipo Curves", "Proportional editing in ipo editor"); + prop = RNA_def_property(srna, "use_proportional_fcurve", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "proportional_fcurve", 0); + RNA_def_property_ui_text(prop, "Proportional Editing FCurves", "Proportional editing in FCurve editor"); RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 38f1cf68ac8..c619b2ed727 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -352,7 +352,7 @@ void wm_method_draw_stereo3d(const bContext *UNUSED(C), wmWindow *win) } } -static bool wm_stereo3d_quadbuffer_supported() +static bool wm_stereo3d_quadbuffer_supported(void) { int gl_stereo = 0; glGetBooleanv(GL_STEREO, (GLboolean *)&gl_stereo); -- cgit v1.2.3 From 40334b4920d6f43a6926eef32dda94555f84ead4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 10 Apr 2015 13:44:26 +1000 Subject: missed last commit --- release/scripts/startup/bl_ui/space_graph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index c00e0a1f9d9..c838016b0dc 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -51,7 +51,7 @@ class GRAPH_HT_header(Header): row.prop(toolsettings, "use_proportional_fcurve", text="", icon_only=True) - if toolsettings.use_proportional_ipo: + if toolsettings.use_proportional_fcurve: row.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True) -- cgit v1.2.3 From 11a48b7227022df8154bec6583ad06ea9396725c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 10 Apr 2015 15:49:07 +1000 Subject: Python API docs, don't hard-code sphinx themes also set the theme to classic (as it was for 2.73) --- doc/python_api/sphinx_doc_gen.py | 38 ++++++-------------------------------- 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 344e6769524..fab66d56a79 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -138,19 +138,9 @@ def handle_args(): parser.add_argument("-T", "--sphinx-theme", dest="sphinx_theme", type=str, - default='default', - help= - # see SPHINX_THEMES below - "Sphinx theme (default='default')\n" - "Available themes\n" - "----------------\n" - "(Blender Foundation) blender-org\n" # naiad - "(Sphinx) agogo, basic, epub, haiku, nature, " - "scrolls, sphinxdoc, traditional\n", -# choices=['naiad', 'blender-org'] + # bf -# ['agogo', 'basic', 'epub', -# 'haiku', 'nature', 'scrolls', -# 'sphinxdoc', 'traditional'], # sphinx + default="classic", + help="Sphinx theme (default='classic'), " + "see: http://sphinx-doc.org/theming.html", required=False) parser.add_argument("-N", "--sphinx-named-output", @@ -419,23 +409,7 @@ BLENDER_ZIP_FILENAME = "%s.zip" % REFERENCE_NAME # -------------------------------SPHINX----------------------------------------- -SPHINX_THEMES = {'bf': ['blender-org'], # , 'naiad', - 'sphinx': ['agogo', - 'basic', - 'default', - 'epub', - 'haiku', - 'nature', - 'scrolls', - 'sphinxdoc', - 'traditional']} - -available_themes = SPHINX_THEMES['bf'] + SPHINX_THEMES['sphinx'] -if ARGS.sphinx_theme not in available_themes: - print("Please choose a theme among: %s" % ', '.join(available_themes)) - sys.exit() - -if ARGS.sphinx_theme in SPHINX_THEMES['bf']: +if ARGS.sphinx_theme == "blender-org": SPHINX_THEME_DIR = os.path.join(ARGS.output_dir, ARGS.sphinx_theme) SPHINX_THEME_SVN_DIR = os.path.join(SCRIPT_DIR, ARGS.sphinx_theme) @@ -1572,7 +1546,7 @@ def write_sphinx_conf_py(basepath): if ARGS.sphinx_theme != 'default': fw("html_theme = '%s'\n" % ARGS.sphinx_theme) - if ARGS.sphinx_theme in SPHINX_THEMES['bf']: + if ARGS.sphinx_theme == "blender-org": fw("html_theme_path = ['../']\n") # copied with the theme, exclude else we get an error [#28873] fw("html_favicon = 'favicon.ico'\n") # in /static/ @@ -1987,7 +1961,7 @@ def main(): copy_function=shutil.copy) # eventually, copy the theme dir - if ARGS.sphinx_theme in SPHINX_THEMES['bf']: + if ARGS.sphinx_theme == "blender-org": if os.path.exists(SPHINX_THEME_DIR): shutil.rmtree(SPHINX_THEME_DIR, True) shutil.copytree(SPHINX_THEME_SVN_DIR, -- cgit v1.2.3 From 253d15ea16a90af1c2ac28d933b73fe7576e0315 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 10 Apr 2015 11:52:54 +0200 Subject: Move clean operator from action/ipo editors to the delete menu, now that O key is bound to proportional editing. --- release/scripts/startup/bl_ui/space_dopesheet.py | 13 +++++++++++++ release/scripts/startup/bl_ui/space_graph.py | 13 +++++++++++++ source/blender/editors/space_action/action_ops.c | 4 ++-- source/blender/editors/space_graph/graph_ops.c | 6 +++--- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 799431118fb..e9818f612c2 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -403,5 +403,18 @@ class DOPESHEET_MT_gpencil_frame(Menu): #layout.operator("action.copy") #layout.operator("action.paste") + +class DOPESHEET_MT_delete(Menu): + bl_label = "Delete" + + def draw(self, context): + layout = self.layout + + layout.operator("action.delete") + + layout.separator() + + layout.operator("action.clean") + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index c838016b0dc..4503a0f4c68 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -280,5 +280,18 @@ class GRAPH_MT_key_transform(Menu): layout.operator("transform.rotate", text="Rotate") layout.operator("transform.resize", text="Scale") +class GRAPH_MT_delete(Menu): + bl_label = "Delete" + + def draw(self, context): + layout = self.layout + + layout.operator("graph.delete") + + layout.separator() + + layout.operator("graph.clean") + + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 0ecd8b31d37..47a120007a5 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -205,8 +205,8 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* destructive */ WM_keymap_add_item(keymap, "ACTION_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "ACTION_OT_delete", XKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "ACTION_OT_delete", DELKEY, KM_PRESS, 0, 0); + WM_keymap_add_menu(keymap, "DOPESHEET_MT_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_menu(keymap, "DOPESHEET_MT_delete", DELKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ACTION_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "ACTION_OT_keyframe_insert", IKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 7032c98ada7..5c3fdce4282 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -568,9 +568,9 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) WM_keymap_add_item(keymap, "GRAPH_OT_bake", CKEY, KM_PRESS, KM_ALT, 0); - WM_keymap_add_item(keymap, "GRAPH_OT_delete", XKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "GRAPH_OT_delete", DELKEY, KM_PRESS, 0, 0); - + WM_keymap_add_menu(keymap, "GRAPH_MT_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_menu(keymap, "GRAPH_MT_delete", DELKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); /* insertkey */ -- cgit v1.2.3 From 1e71270f77a4e1c7c84b871e5378c659d61edb3e Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 10 Apr 2015 12:32:19 +0200 Subject: Fix T44329: Blender Crash when rendering in 3DView. This commit fixes two different issues actually: * When view name is unknown/irrelevant, you should pass a NULL str pointer to `RE_RenderLayerGetPass()`, not an empty string! * `render_result_rescale()` would unconditionnaly free re->result (at the end), even if it did not replaced it at all, leading to freed memory access later. This is only a partial fix though, "CacheBuffer" (i.e. saving tiles in EXR files) shall not be used in 3DView rendering, and yet it is here... --- source/blender/render/intern/source/pipeline.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index cd7940e52c8..db3499b4180 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -202,7 +202,7 @@ float *RE_RenderLayerGetPass(volatile RenderLayer *rl, int passtype, const char if (viewname == NULL) break; - else if (strcmp(rpass->view, viewname) == 0) + else if (STREQ(rpass->view, viewname)) break; } } @@ -776,7 +776,7 @@ static void render_result_rescale(Render *re) if (src_rectf == NULL) { RenderLayer *rl = render_get_active_layer(re, re->result); if (rl != NULL) { - src_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, ""); + src_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, NULL); } } @@ -795,7 +795,7 @@ static void render_result_rescale(Render *re) RenderLayer *rl; rl = render_get_active_layer(re, re->result); if (rl != NULL) { - dst_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, ""); + dst_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, NULL); } } @@ -812,9 +812,8 @@ static void render_result_rescale(Render *re) } } } + render_result_free(result); } - - render_result_free(result); } void RE_ChangeResolution(Render *re, int winx, int winy, rcti *disprect) -- cgit v1.2.3 From 2f5dd83759d2db8480706c3a472bdf0f7db4f725 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 10 Apr 2015 15:36:56 +0500 Subject: Cycles: Add some statistics logging Covers number of entities in the scene (objects, meshes etc), also reports sizes of textures being allocated. --- intern/cycles/device/device_cpu.cpp | 2 ++ intern/cycles/device/device_cuda.cpp | 1 + intern/cycles/device/device_multi.cpp | 3 +++ intern/cycles/device/device_network.cpp | 2 ++ intern/cycles/device/device_opencl.cpp | 2 ++ intern/cycles/render/light.cpp | 2 ++ intern/cycles/render/mesh.cpp | 2 ++ intern/cycles/render/object.cpp | 3 +++ intern/cycles/render/osl.cpp | 2 ++ intern/cycles/render/particles.cpp | 4 ++++ intern/cycles/render/svm.cpp | 3 +++ intern/cycles/render/tables.cpp | 3 +++ 12 files changed, 29 insertions(+) diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 148e52e2c86..63735df88ab 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -38,6 +38,7 @@ #include "util_debug.h" #include "util_foreach.h" #include "util_function.h" +#include "util_logging.h" #include "util_opengl.h" #include "util_progress.h" #include "util_system.h" @@ -115,6 +116,7 @@ public: void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool /*periodic*/) { + VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes."; kernel_tex_copy(&kernel_globals, name, mem.data_pointer, mem.data_width, mem.data_height, mem.data_depth, interpolation); mem.device_pointer = mem.data_pointer; mem.device_size = mem.memory_size(); diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 5afeb896ac8..9d3b16b1e1b 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -419,6 +419,7 @@ public: void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic) { /* todo: support 3D textures, only CPU for now */ + VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes."; /* determine format */ CUarray_format_enum format; diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp index 9aac86daa1d..8da489a0ab5 100644 --- a/intern/cycles/device/device_multi.cpp +++ b/intern/cycles/device/device_multi.cpp @@ -25,6 +25,7 @@ #include "util_foreach.h" #include "util_list.h" +#include "util_logging.h" #include "util_map.h" #include "util_time.h" @@ -170,6 +171,8 @@ public: void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic) { + VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes."; + foreach(SubDevice& sub, devices) { mem.device_pointer = 0; sub.device->tex_alloc(name, mem, interpolation, periodic); diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp index 20df2434a4a..90cd6a76d63 100644 --- a/intern/cycles/device/device_network.cpp +++ b/intern/cycles/device/device_network.cpp @@ -164,6 +164,8 @@ public: void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic) { + VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes."; + thread_scoped_lock lock(rpc_lock); mem.device_pointer = ++mem_counter; diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index a77a6aaceb2..1147cbd69b4 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -28,6 +28,7 @@ #include "buffers.h" #include "util_foreach.h" +#include "util_logging.h" #include "util_map.h" #include "util_math.h" #include "util_md5.h" @@ -859,6 +860,7 @@ public: InterpolationType /*interpolation*/, bool /*periodic*/) { + VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes."; mem_alloc(mem, MEM_READ_ONLY); mem_copy_to(mem); assert(mem_map.find(name) == mem_map.end()); diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 08ee8eddc07..91e45aea17a 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -662,6 +662,8 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { + VLOG(1) << "Total " << scene->lights.size() << " lights."; + if(!need_update) return; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 6cf75a287e5..74ea3c94593 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -1150,6 +1150,8 @@ void MeshManager::device_update_flags(Device * /*device*/, void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { + VLOG(1) << "Total " << scene->meshes.size() << " meshes."; + if(!need_update) return; diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index a1d0439c0d7..6650b42d39c 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -23,6 +23,7 @@ #include "scene.h" #include "util_foreach.h" +#include "util_logging.h" #include "util_map.h" #include "util_progress.h" #include "util_vector.h" @@ -377,6 +378,8 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { + VLOG(1) << "Total " << scene->objects.size() << " objects."; + if(!need_update) return; diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 679d54d1d1e..cd6c6eb3706 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -75,6 +75,8 @@ void OSLShaderManager::reset(Scene * /*scene*/) void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { + VLOG(1) << "Total " << scene->shaders.size() << " shaders."; + if(!need_update) return; diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp index f6a89d7a10c..8f9e8c6d639 100644 --- a/intern/cycles/render/particles.cpp +++ b/intern/cycles/render/particles.cpp @@ -19,6 +19,7 @@ #include "scene.h" #include "util_foreach.h" +#include "util_logging.h" #include "util_map.h" #include "util_progress.h" #include "util_vector.h" @@ -92,6 +93,9 @@ void ParticleSystemManager::device_update_particles(Device *device, DeviceScene void ParticleSystemManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { + VLOG(1) << "Total " << scene->particle_systems.size() + << " particle systems."; + if(!need_update) return; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index f5264debd8b..6f7cffa320f 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -24,6 +24,7 @@ #include "svm.h" #include "util_debug.h" +#include "util_logging.h" #include "util_foreach.h" #include "util_progress.h" @@ -45,6 +46,8 @@ void SVMShaderManager::reset(Scene * /*scene*/) void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { + VLOG(1) << "Total " << scene->shaders.size() << " shaders."; + if(!need_update) return; diff --git a/intern/cycles/render/tables.cpp b/intern/cycles/render/tables.cpp index faf7ea3409b..ad3f4866072 100644 --- a/intern/cycles/render/tables.cpp +++ b/intern/cycles/render/tables.cpp @@ -19,6 +19,7 @@ #include "tables.h" #include "util_debug.h" +#include "util_logging.h" CCL_NAMESPACE_BEGIN @@ -36,6 +37,8 @@ LookupTables::~LookupTables() void LookupTables::device_update(Device *device, DeviceScene *dscene) { + VLOG(1) << "Total " << lookup_tables.size() << " lookup tables."; + if(!need_update) return; -- cgit v1.2.3 From 237c53fbf101012b545a46a2a72f77b76727a579 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 10 Apr 2015 12:44:54 +0200 Subject: Only selected keys will get cleaned by the action and graph clean operators --- source/blender/editors/animation/keyframes_general.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 2d869d272bd..02e16ff3446 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -199,13 +199,17 @@ void clean_fcurve(FCurve *fcu, float thresh) /* now insert first keyframe, as it should be ok */ bezt = old_bezts; insert_vert_fcurve(fcu, bezt->vec[1][0], bezt->vec[1][1], 0); + if (!(bezt->f2 & SELECT)) { + lastb = fcu->bezt; + lastb->f1 = lastb->f2 = lastb->f3 = 0; + } /* Loop through BezTriples, comparing them. Skip any that do * not fit the criteria for "ok" points. */ for (i = 1; i < totCount; i++) { float prev[2], cur[2], next[2]; - + /* get BezTriples and their values */ if (i < (totCount - 1)) { beztn = (old_bezts + (i + 1)); @@ -217,10 +221,17 @@ void clean_fcurve(FCurve *fcu, float thresh) } lastb = (fcu->bezt + (fcu->totvert - 1)); bezt = (old_bezts + i); - + /* get references for quicker access */ prev[0] = lastb->vec[1][0]; prev[1] = lastb->vec[1][1]; cur[0] = bezt->vec[1][0]; cur[1] = bezt->vec[1][1]; + + if (!(bezt->f2 & SELECT)) { + insert_vert_fcurve(fcu, cur[0], cur[1], 0); + lastb = (fcu->bezt + (fcu->totvert - 1)); + lastb->f1 = lastb->f2 = lastb->f3 = 0; + continue; + } /* check if current bezt occurs at same time as last ok */ if (IS_EQT(cur[0], prev[0], thresh)) { @@ -228,7 +239,7 @@ void clean_fcurve(FCurve *fcu, float thresh) * if there is a considerable distance between the points, and also if the * current is further away than the next one is to the previous. */ - if (beztn && (IS_EQT(cur[0], next[0], thresh)) && + if (beztn && (IS_EQT(cur[0], next[0], thresh)) && (IS_EQT(next[1], prev[1], thresh) == 0)) { /* only add if current is further away from previous */ -- cgit v1.2.3 From e073562f80121ced07db38716e996c32b0c01a45 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 10 Apr 2015 15:52:40 +0500 Subject: Cycles: Make transform from viewplane a generic utility function --- intern/cycles/render/camera.cpp | 11 ----------- intern/cycles/render/camera.h | 1 - intern/cycles/util/util_transform.cpp | 16 ++++++++++++++-- intern/cycles/util/util_transform.h | 3 +++ 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 80101a81bfd..9e3a17bf792 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -409,15 +409,4 @@ BoundBox Camera::viewplane_bounds_get() return bounds; } -Transform Camera::transform_from_viewplane(BoundBox2D &viewplane) -{ - return - transform_scale(1.0f / (viewplane.right - viewplane.left), - 1.0f / (viewplane.top - viewplane.bottom), - 1.0f) * - transform_translate(-viewplane.left, - -viewplane.bottom, - 0.0f); -} - CCL_NAMESPACE_END diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index e1faee3543d..31240f6813e 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -125,7 +125,6 @@ public: BoundBox viewplane_bounds_get(); float3 transform_raster_to_world(float raster_x, float raster_y); - Transform transform_from_viewplane(BoundBox2D &viewplane); }; CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp index 0a1c09ae3d5..acaca69464c 100644 --- a/intern/cycles/util/util_transform.cpp +++ b/intern/cycles/util/util_transform.cpp @@ -46,9 +46,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "util_math.h" #include "util_transform.h" +#include "util_boundbox.h" +#include "util_math.h" + CCL_NAMESPACE_BEGIN /* Transform Inverse */ @@ -271,5 +273,15 @@ void transform_motion_decompose(DecompMotionTransform *decomp, const MotionTrans decomp->post_y = post.y; } -CCL_NAMESPACE_END +Transform transform_from_viewplane(BoundBox2D& viewplane) +{ + return + transform_scale(1.0f / (viewplane.right - viewplane.left), + 1.0f / (viewplane.top - viewplane.bottom), + 1.0f) * + transform_translate(-viewplane.left, + -viewplane.bottom, + 0.0f); +} +CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index ac97fa53084..1829ad29df3 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -449,6 +449,8 @@ ccl_device void transform_motion_interpolate(Transform *tfm, const DecompMotionT #ifndef __KERNEL_GPU__ +class BoundBox2D; + ccl_device_inline bool operator==(const MotionTransform& A, const MotionTransform& B) { return (A.pre == B.pre && A.post == B.post); @@ -456,6 +458,7 @@ ccl_device_inline bool operator==(const MotionTransform& A, const MotionTransfor float4 transform_to_quat(const Transform& tfm); void transform_motion_decompose(DecompMotionTransform *decomp, const MotionTransform *motion, const Transform *mid); +Transform transform_from_viewplane(BoundBox2D& viewplane); #endif -- cgit v1.2.3 From 711a5c79d8c4105dc0ccf771b79d66c79ee3c570 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 10 Apr 2015 13:05:17 +0200 Subject: Don't use vertex colors in textured mesh display during texpaint. Wasn't that irritating? --- source/blender/editors/space_view3d/drawmesh.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index 755c633531d..b1f8d112765 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -588,15 +588,19 @@ static DMDrawOption draw_tface__set_draw(MTFace *tface, const bool UNUSED(has_mc return DM_DRAW_OPTION_NORMAL; } -static void update_tface_color_layer(DerivedMesh *dm) +static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol) { MTFace *tface = DM_get_tessface_data_layer(dm, CD_MTFACE); MFace *mface = dm->getTessFaceArray(dm); MCol *finalCol; int i, j; - MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL); - if (!mcol) - mcol = dm->getTessFaceDataArray(dm, CD_MCOL); + MCol *mcol = NULL; + + if (use_mcol) { + mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL); + if (!mcol) + mcol = dm->getTessFaceDataArray(dm, CD_MCOL); + } if (CustomData_has_layer(&dm->faceData, CD_TEXTURE_MCOL)) { finalCol = CustomData_get_layer(&dm->faceData, CD_TEXTURE_MCOL); @@ -937,7 +941,7 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d else { drawTFace_userData userData; - update_tface_color_layer(dm); + update_tface_color_layer(dm, !(ob->mode & OB_MODE_TEXTURE_PAINT)); userData.mf = DM_get_tessface_data_layer(dm, CD_MFACE); userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE); -- cgit v1.2.3 From 085fa2e3d7c002396c031fa907c7bd6e6f8b3541 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 10 Apr 2015 13:16:05 +0200 Subject: Fix T44329: Second part: prevent 'cachebuffer' and 'fullOSA' in preview renders. --- source/blender/editors/render/render_internal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 2e447be3f21..fbfe8d93a22 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -1230,10 +1230,10 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda if ((update_flag & (PR_UPDATE_RENDERSIZE | PR_UPDATE_DATABASE)) || rstats->convertdone == 0) { RenderData rdata; - /* no osa, blur, seq, layers, etc for preview render */ + /* no osa, blur, seq, layers, savebuffer etc for preview render */ rdata = rp->scene->r; rdata.mode &= ~(R_OSA | R_MBLUR | R_BORDER | R_PANORAMA); - rdata.scemode &= ~(R_DOSEQ | R_DOCOMP | R_FREE_IMAGE); + rdata.scemode &= ~(R_DOSEQ | R_DOCOMP | R_FREE_IMAGE | R_EXR_TILE_FILE | R_FULL_SAMPLE); rdata.scemode |= R_VIEWPORT_PREVIEW; /* we do use layers, but only active */ -- cgit v1.2.3 From aac0df956f22f7989e88958cbd3723b2bdee3d27 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 10 Apr 2015 16:25:12 +0500 Subject: Cycles: Cleanup, make more clear what camera utility functions are private/public --- intern/cycles/render/camera.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 31240f6813e..00387bcb7b1 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -123,7 +123,11 @@ public: bool motion_modified(const Camera& cam); void tag_update(); + /* Public utility functions. */ BoundBox viewplane_bounds_get(); + +private: + /* Private utility functions. */ float3 transform_raster_to_world(float raster_x, float raster_y); }; -- cgit v1.2.3 From b0906bcc5e1b5ce7049e0b72fcfc0d0916c20563 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 10 Apr 2015 21:49:07 +1000 Subject: Cleanup: remove win32 workaround --- source/blender/blenlib/intern/BLI_filelist.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/source/blender/blenlib/intern/BLI_filelist.c b/source/blender/blenlib/intern/BLI_filelist.c index b934b51375b..e9ed785efc7 100644 --- a/source/blender/blenlib/intern/BLI_filelist.c +++ b/source/blender/blenlib/intern/BLI_filelist.c @@ -218,19 +218,16 @@ static void bli_adddirstrings(struct BuildDirCtx *dir_ctx) const char *types[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"}; /* symbolic display, indexed by mode field value */ int num; -#ifdef WIN32 - __int64 st_size; -#else off_t st_size; - int mode; -#endif - struct direntry *file; struct tm *tm; time_t zero = 0; - for (num = 0, file = dir_ctx->files; num < dir_ctx->nrfiles; num++, file++) { +#ifndef WIN32 + int mode; +#endif + for (num = 0, file = dir_ctx->files; num < dir_ctx->nrfiles; num++, file++) { /* Mode */ #ifdef WIN32 -- cgit v1.2.3 From ec710775cfb314abdd501873aa9f5e790b1c06b6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 10 Apr 2015 22:01:10 +1000 Subject: Use off_t for filesize (was int) Resolves finding >2gig files. Also enable strict flags. --- source/blender/blenkernel/intern/bpath.c | 52 +++++++++++++++++--------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index bb3731218ed..2b3261fa4a7 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -80,6 +80,8 @@ #include "BKE_bpath.h" /* own include */ +#include "BLI_strict_flags.h" + static bool checkMissingFiles_visit_cb(void *userdata, char *UNUSED(path_dst), const char *path_src) { ReportList *reports = (ReportList *)userdata; @@ -204,18 +206,19 @@ void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *re * \returns found: 1/0. */ #define MAX_RECUR 16 -static int findFileRecursive(char *filename_new, - const char *dirname, - const char *filename, - int *filesize, - int *recur_depth) +static bool missing_files_find__recursive( + char *filename_new, + const char *dirname, + const char *filename, + off_t *r_filesize, + int *r_recur_depth) { /* file searching stuff */ DIR *dir; struct dirent *de; BLI_stat_t status; char path[FILE_MAX]; - int size; + off_t size; bool found = false; dir = opendir(dirname); @@ -223,8 +226,8 @@ static int findFileRecursive(char *filename_new, if (dir == NULL) return found; - if (*filesize == -1) - *filesize = 0; /* dir opened fine */ + if (*r_filesize == -1) + *r_filesize = 0; /* dir opened fine */ while ((de = readdir(dir)) != NULL) { @@ -240,18 +243,18 @@ static int findFileRecursive(char *filename_new, if (STREQLEN(filename, de->d_name, FILE_MAX)) { /* name matches */ /* open the file to read its size */ size = status.st_size; - if ((size > 0) && (size > *filesize)) { /* find the biggest file */ - *filesize = size; + if ((size > 0) && (size > *r_filesize)) { /* find the biggest file */ + *r_filesize = size; BLI_strncpy(filename_new, path, FILE_MAX); found = true; } } } else if (S_ISDIR(status.st_mode)) { /* is subdir */ - if (*recur_depth <= MAX_RECUR) { - (*recur_depth)++; - found |= findFileRecursive(filename_new, path, filename, filesize, recur_depth); - (*recur_depth)--; + if (*r_recur_depth <= MAX_RECUR) { + (*r_recur_depth)++; + found |= missing_files_find__recursive(filename_new, path, filename, r_filesize, r_recur_depth); + (*r_recur_depth)--; } } } @@ -266,14 +269,14 @@ typedef struct BPathFind_Data { bool find_all; } BPathFind_Data; -static bool findMissingFiles_visit_cb(void *userdata, char *path_dst, const char *path_src) +static bool missing_files_find__visit_cb(void *userdata, char *path_dst, const char *path_src) { BPathFind_Data *data = (BPathFind_Data *)userdata; char filename_new[FILE_MAX]; - int filesize = -1; + off_t filesize = -1; int recur_depth = 0; - int found; + bool found; if (data->find_all == false) { if (BLI_exists(path_src)) { @@ -283,9 +286,10 @@ static bool findMissingFiles_visit_cb(void *userdata, char *path_dst, const char filename_new[0] = '\0'; - found = findFileRecursive(filename_new, - data->searchdir, BLI_path_basename(path_src), - &filesize, &recur_depth); + found = missing_files_find__recursive( + filename_new, + data->searchdir, BLI_path_basename(path_src), + &filesize, &recur_depth); if (filesize == -1) { /* could not open dir */ BKE_reportf(data->reports, RPT_WARNING, @@ -322,7 +326,7 @@ void BKE_bpath_missing_files_find(Main *bmain, const char *searchpath, ReportLis data.searchdir = searchpath; data.find_all = find_all; - BKE_bpath_traverse_main(bmain, findMissingFiles_visit_cb, BKE_BPATH_TRAVERSE_ABS, (void *)&data); + BKE_bpath_traverse_main(bmain, missing_files_find__visit_cb, BKE_BPATH_TRAVERSE_ABS, (void *)&data); } /* Run a visitor on a string, replacing the contents of the string as needed. */ @@ -589,12 +593,12 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int } else if ((seq->type == SEQ_TYPE_IMAGE) && se) { /* might want an option not to loop over all strips */ - int len = MEM_allocN_len(se) / sizeof(*se); - int i; + unsigned int len = (unsigned int)MEM_allocN_len(se) / sizeof(*se); + unsigned int i; if (flag & BKE_BPATH_TRAVERSE_SKIP_MULTIFILE) { /* only operate on one path */ - len = MIN2(1, len); + len = MIN2(1u, len); } for (i = 0; i < len; i++, se++) { -- cgit v1.2.3 From a36c43fc8cabdaee69df69e9b0d2ee37fd7a8b12 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 10 Apr 2015 14:46:17 +0200 Subject: Thumbnails: some reorganization, decouple actual path of file to preview from 'ref' one. (Partial) backport from asset-experiments branch. Reorganization: previously we could recompute name/path of thumb file two or three times, now added lower-level internal functions that take those as parameters, so in most case they are computed only once. Very minor optimization, but simple too. Also, path of file to preview is now decoupled from path used to generate its URI (and hence thumbnail path). In asset-experiments branch this is needed because we also handle datablock previews in/as thumbnails (file_path is .blend path, URI is .blend path + datablock 'path'). Here this will be needed for same kind of reason - once translated, font thumbnails need to be re-generated when we change current language... --- source/blender/imbuf/IMB_thumbs.h | 4 +- source/blender/imbuf/intern/thumbs.c | 132 +++++++++++++++++++++-------------- 2 files changed, 80 insertions(+), 56 deletions(-) diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h index 404052f2e8e..c3350ecdc21 100644 --- a/source/blender/imbuf/IMB_thumbs.h +++ b/source/blender/imbuf/IMB_thumbs.h @@ -81,9 +81,7 @@ ImBuf *IMB_thumb_load_blend(const char *path); void IMB_thumb_overlay_blend(unsigned int *thumb, int width, int height, float aspect); /* special function for previewing fonts */ -ImBuf *IMB_thumb_load_font( - const char *filename, - unsigned int x, unsigned int y); +ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y); #ifdef __cplusplus } diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 78f47b7bc34..59b8f279f98 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -239,30 +239,45 @@ static int uri_from_filename(const char *path, char *uri) return 1; } -static void thumbname_from_uri(const char *uri, char *thumb, const int thumb_len) +static bool thumbpathname_from_uri( + const char *uri, char *r_path, const int path_len, char *r_name, int name_len, ThumbSize size) { - char hexdigest[33]; - unsigned char digest[16]; + char name_buff[40]; + + if (r_path && !r_name) { + r_name = name_buff; + name_len = sizeof(name_buff); + } + + if (r_name) { + char hexdigest[33]; + unsigned char digest[16]; + BLI_hash_md5_buffer(uri, strlen(uri), digest); + hexdigest[0] = '\0'; + BLI_snprintf(r_name, name_len, "%s.png", BLI_hash_md5_to_hexdigest(digest, hexdigest)); +// printf("%s: '%s' --> '%s'\n", __func__, uri, r_name); + } + + if (r_path) { + char tmppath[FILE_MAX]; - BLI_hash_md5_buffer(uri, strlen(uri), digest); - hexdigest[0] = '\0'; - BLI_snprintf(thumb, thumb_len, "%s.png", BLI_hash_md5_to_hexdigest(digest, hexdigest)); + if (get_thumb_dir(tmppath, size)) { + BLI_snprintf(r_path, path_len, "%s%s", tmppath, r_name); +// printf("%s: '%s' --> '%s'\n", __func__, uri, r_path); + return true; + } + } + return false; +} - // printf("%s: '%s' --> '%s'\n", __func__, uri, thumb); +static void thumbname_from_uri(const char *uri, char *thumb, const int thumb_len) +{ + thumbpathname_from_uri(uri, NULL, 0, thumb, thumb_len, THB_FAIL); } -static int thumbpath_from_uri(const char *uri, char *path, const int path_len, ThumbSize size) +static bool thumbpath_from_uri(const char *uri, char *path, const int path_len, ThumbSize size) { - char tmppath[FILE_MAX]; - int rv = 0; - - if (get_thumb_dir(tmppath, size)) { - char thumb[40]; - thumbname_from_uri(uri, thumb, sizeof(thumb)); - BLI_snprintf(path, path_len, "%s%s", tmppath, thumb); - rv = 1; - } - return rv; + return thumbpathname_from_uri(uri, path, path_len, NULL, 0, size); } void IMB_thumb_makedirs(void) @@ -277,9 +292,9 @@ void IMB_thumb_makedirs(void) } /* create thumbnail for file and returns new imbuf for thumbnail */ -ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, ImBuf *img) +static ImBuf *thumb_create_ex( + const char *file_path, const char *uri, const char *thumb, ThumbSize size, ThumbSource source, ImBuf *img) { - char uri[URI_MAX] = ""; char desc[URI_MAX + 22]; char tpath[FILE_MAX]; char tdir[FILE_MAX]; @@ -287,7 +302,6 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im char mtime[40] = "0"; /* in case we can't stat the file */ char cwidth[40] = "0"; /* in case images have no data */ char cheight[40] = "0"; - char thumb[40]; short tsize = 128; short ex, ey; float scaledx, scaledy; @@ -309,20 +323,18 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im /* exception, skip images over 100mb */ if (source == THB_SOURCE_IMAGE) { - const size_t file_size = BLI_file_size(path); + const size_t file_size = BLI_file_size(file_path); if (file_size != -1 && file_size > THUMB_SIZE_MAX) { - // printf("file too big: %d, skipping %s\n", (int)size, path); + // printf("file too big: %d, skipping %s\n", (int)size, file_path); return NULL; } } - uri_from_filename(path, uri); - thumbname_from_uri(uri, thumb, sizeof(thumb)); if (get_thumb_dir(tdir, size)) { BLI_snprintf(tpath, FILE_MAX, "%s%s", tdir, thumb); - thumb[8] = '\0'; /* shorten for tempname, not needed anymore */ +// thumb[8] = '\0'; /* shorten for tempname, not needed anymore */ BLI_snprintf(temp, FILE_MAX, "%sblender_%d_%s.png", tdir, abs(getpid()), thumb); - if (BLI_path_ncmp(path, tdir, sizeof(tdir)) == 0) { + if (BLI_path_ncmp(file_path, tdir, sizeof(tdir)) == 0) { return NULL; } if (size == THB_FAIL) { @@ -331,18 +343,17 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im } else { if (ELEM(source, THB_SOURCE_IMAGE, THB_SOURCE_BLEND, THB_SOURCE_FONT)) { - /* only load if we didnt give an image */ if (img == NULL) { switch (source) { case THB_SOURCE_IMAGE: - img = IMB_loadiffname(path, IB_rect | IB_metadata, NULL); + img = IMB_loadiffname(file_path, IB_rect | IB_metadata, NULL); break; case THB_SOURCE_BLEND: - img = IMB_thumb_load_blend(path); + img = IMB_thumb_load_blend(file_path); break; case THB_SOURCE_FONT: - img = IMB_thumb_load_font(path, tsize, tsize); + img = IMB_thumb_load_font(file_path, tsize, tsize); break; default: BLI_assert(0); /* This should never happen */ @@ -350,7 +361,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im } if (img != NULL) { - if (BLI_stat(path, &info) != -1) { + if (BLI_stat(file_path, &info) != -1) { BLI_snprintf(mtime, sizeof(mtime), "%ld", (long int)info.st_mtime); } BLI_snprintf(cwidth, sizeof(cwidth), "%d", img->x); @@ -359,11 +370,11 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im } else if (THB_SOURCE_MOVIE == source) { struct anim *anim = NULL; - anim = IMB_open_anim(path, IB_rect | IB_metadata, 0, NULL); + anim = IMB_open_anim(file_path, IB_rect | IB_metadata, 0, NULL); if (anim != NULL) { img = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); if (img == NULL) { - printf("not an anim; %s\n", path); + printf("not an anim; %s\n", file_path); } else { IMB_freeImBuf(img); @@ -371,7 +382,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im } IMB_free_anim(anim); } - if (BLI_stat(path, &info) != -1) { + if (BLI_stat(file_path, &info) != -1) { BLI_snprintf(mtime, sizeof(mtime), "%ld", (long int)info.st_mtime); } } @@ -387,7 +398,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im } ex = (short)scaledx; ey = (short)scaledy; - + /* save some time by only scaling byte buf */ if (img->rect_float) { if (img->rect == NULL) { @@ -404,7 +415,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im IMB_metadata_change_field(img, "Software", "Blender"); IMB_metadata_change_field(img, "Thumb::URI", uri); IMB_metadata_change_field(img, "Thumb::MTime", mtime); - if (THB_SOURCE_IMAGE == source) { + if (ELEM(source, THB_SOURCE_IMAGE, THB_SOURCE_BLEND, THB_SOURCE_FONT)) { IMB_metadata_change_field(img, "Thumb::Image::Width", cwidth); IMB_metadata_change_field(img, "Thumb::Image::Height", cheight); } @@ -419,12 +430,21 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im BLI_rename(temp, tpath); } - - return img; } return img; } +ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, ImBuf *img) +{ + char uri[URI_MAX] = ""; + char thumb_name[40]; + + uri_from_filename(path, uri); + thumbname_from_uri(uri, thumb_name, sizeof(thumb_name)); + + return thumb_create_ex(path, uri, thumb_name, size, source, img); +} + /* read thumbnail for file and returns new imbuf for thumbnail */ ImBuf *IMB_thumb_read(const char *path, ThumbSize size) { @@ -465,23 +485,29 @@ void IMB_thumb_delete(const char *path, ThumbSize size) /* create the thumb if necessary and manage failed and old thumbs */ ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source) { - char thumb[FILE_MAX]; + char thumb_path[FILE_MAX]; + char thumb_name[40]; char uri[URI_MAX]; + const char *file_path; + char path_buff[FILE_MAX]; BLI_stat_t st; ImBuf *img = NULL; - - if (BLI_stat(path, &st) == -1) { + + file_path = path; + UNUSED_VARS(path_buff); + + if (BLI_stat(file_path, &st) == -1) { return NULL; } if (!uri_from_filename(path, uri)) { return NULL; } - if (thumbpath_from_uri(uri, thumb, sizeof(thumb), THB_FAIL)) { + if (thumbpath_from_uri(uri, thumb_path, sizeof(thumb_path), THB_FAIL)) { /* failure thumb exists, don't try recreating */ - if (BLI_exists(thumb)) { + if (BLI_exists(thumb_path)) { /* clear out of date fail case */ - if (BLI_file_older(thumb, path)) { - BLI_delete(thumb, false, false); + if (BLI_file_older(thumb_path, file_path)) { + BLI_delete(thumb_path, false, false); } else { return NULL; @@ -489,12 +515,12 @@ ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source) } } - if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) { - if (BLI_path_ncmp(path, thumb, sizeof(thumb)) == 0) { + if (thumbpathname_from_uri(uri, thumb_path, sizeof(thumb_path), thumb_name, sizeof(thumb_name), size)) { + if (BLI_path_ncmp(path, thumb_path, sizeof(thumb_path)) == 0) { img = IMB_loadiffname(path, IB_rect, NULL); } else { - img = IMB_loadiffname(thumb, IB_rect | IB_metadata, NULL); + img = IMB_loadiffname(thumb_path, IB_rect | IB_metadata, NULL); if (img) { char mtime[40]; if (!IMB_metadata_get_field(img, "Thumb::MTime", mtime, 40)) { @@ -511,10 +537,10 @@ ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source) IMB_thumb_delete(path, THB_NORMAL); IMB_thumb_delete(path, THB_LARGE); IMB_thumb_delete(path, THB_FAIL); - img = IMB_thumb_create(path, size, source, NULL); + img = thumb_create_ex(file_path, uri, thumb_name, size, source, NULL); if (!img) { /* thumb creation failed, write fail thumb */ - img = IMB_thumb_create(path, THB_FAIL, source, NULL); + img = thumb_create_ex(file_path, uri, thumb_name, THB_FAIL, source, NULL); if (img) { /* we don't need failed thumb anymore */ IMB_freeImBuf(img); @@ -525,10 +551,10 @@ ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source) } } else { - img = IMB_thumb_create(path, size, source, NULL); + img = thumb_create_ex(file_path, uri, thumb_name, size, source, NULL); if (!img) { /* thumb creation failed, write fail thumb */ - img = IMB_thumb_create(path, THB_FAIL, source, NULL); + img = thumb_create_ex(file_path, uri, thumb_name, THB_FAIL, source, NULL); if (img) { /* we don't need failed thumb anymore */ IMB_freeImBuf(img); -- cgit v1.2.3 From 8a99dc232469a987ca2631b3ab5dd8e0da948054 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 10 Apr 2015 15:28:47 +0200 Subject: BLF translation: fix BLF_lang_get(), add UI-agnostic BLF_translate/_do helpers. BLF_lang_get() shall return 'default' Blender locale (en_US) when translations are completely disabled! Also, add BLF_translate() and BLF_translate_do() to allow translating some strings outside of label/tip context, but still only when i18n global flag is enabled. --- source/blender/blenfont/BLF_translation.h | 2 ++ source/blender/blenfont/intern/blf_lang.c | 13 ++++++++----- source/blender/blenfont/intern/blf_translation.c | 24 ++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/source/blender/blenfont/BLF_translation.h b/source/blender/blenfont/BLF_translation.h index 49bfdbfe877..c9b0c253ed4 100644 --- a/source/blender/blenfont/BLF_translation.h +++ b/source/blender/blenfont/BLF_translation.h @@ -79,9 +79,11 @@ bool BLF_is_default_context(const char *msgctxt); const char *BLF_pgettext(const char *msgctxt, const char *msgid); /* translation */ +bool BLF_translate(void); bool BLF_translate_iface(void); bool BLF_translate_tooltips(void); bool BLF_translate_new_dataname(void); +const char *BLF_translate_do(const char *msgctxt, const char *msgid); const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid); const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid); const char *BLF_translate_do_new_dataname(const char *msgctxt, const char *msgid); diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c index 99e1aa5d3e3..4683081a1ed 100644 --- a/source/blender/blenfont/intern/blf_lang.c +++ b/source/blender/blenfont/intern/blf_lang.c @@ -284,12 +284,15 @@ void BLF_lang_set(const char *str) const char *BLF_lang_get(void) { #ifdef WITH_INTERNATIONAL - const char *locale = LOCALE(ULANGUAGE); - if (locale[0] == '\0') { - /* Default locale, we have to find which one we are actually using! */ - locale = bl_locale_get(); + if (BLF_translate()) { + const char *locale = LOCALE(ULANGUAGE); + if (locale[0] == '\0') { + /* Default locale, we have to find which one we are actually using! */ + locale = bl_locale_get(); + } + return locale; } - return locale; + return "en_US"; /* Kind of default locale in Blender when no translation enabled. */ #else return ""; #endif diff --git a/source/blender/blenfont/intern/blf_translation.c b/source/blender/blenfont/intern/blf_translation.c index 2a4a152f0eb..25464864657 100644 --- a/source/blender/blenfont/intern/blf_translation.c +++ b/source/blender/blenfont/intern/blf_translation.c @@ -164,6 +164,15 @@ const char *BLF_pgettext(const char *msgctxt, const char *msgid) #endif } +bool BLF_translate(void) +{ +#ifdef WITH_INTERNATIONAL + return (U.transopts & USER_DOTRANSLATE) != 0; +#else + return false; +#endif +} + bool BLF_translate_iface(void) { #ifdef WITH_INTERNATIONAL @@ -191,6 +200,21 @@ bool BLF_translate_new_dataname(void) #endif } +const char *BLF_translate_do(const char *msgctxt, const char *msgid) +{ +#ifdef WITH_INTERNATIONAL + if (BLF_translate()) { + return BLF_pgettext(msgctxt, msgid); + } + else { + return msgid; + } +#else + (void)msgctxt; + return msgid; +#endif +} + const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL -- cgit v1.2.3 From f75bbe27e23d2f79490aac82666ded1b1574083c Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 10 Apr 2015 15:31:38 +0200 Subject: Thumbnails: Add translations to font preview. Not much to say, this is pretty straightforward. We just have to add current locale to thumbnails 'signature', so that previews get re-generated when we change locale... Tested with Japanese and French. Btw, I do not really understand why using BLF in ImBuf is badlevel... :/ --- source/blender/blenfont/intern/blf_thumbs.c | 3 ++- source/blender/imbuf/IMB_thumbs.h | 1 + source/blender/imbuf/intern/thumbs.c | 10 +++++++--- source/blender/imbuf/intern/thumbs_font.c | 15 ++++++++++----- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c index afda6a382f9..3c400d0b8e4 100644 --- a/source/blender/blenfont/intern/blf_thumbs.c +++ b/source/blender/blenfont/intern/blf_thumbs.c @@ -45,6 +45,7 @@ #include "blf_internal_types.h" #include "BLF_api.h" +#include "BLF_translation.h" #include "BLI_strict_flags.h" @@ -97,7 +98,7 @@ void BLF_thumb_preview( font->pos[1] -= font->glyph_cache->ascender * 1.1f; - blf_font_buffer(font, draw_str[i]); + blf_font_buffer(font, BLF_translate_do(BLF_I18NCONTEXT_DEFAULT, draw_str[i])); } blf_font_free(font); diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h index c3350ecdc21..f977a633c57 100644 --- a/source/blender/imbuf/IMB_thumbs.h +++ b/source/blender/imbuf/IMB_thumbs.h @@ -82,6 +82,7 @@ void IMB_thumb_overlay_blend(unsigned int *thumb, int width, int height, float /* special function for previewing fonts */ ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y); +const char *IMB_thumb_load_font_get_language(void); #ifdef __cplusplus } diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 59b8f279f98..2318553eecc 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -483,18 +483,22 @@ void IMB_thumb_delete(const char *path, ThumbSize size) /* create the thumb if necessary and manage failed and old thumbs */ -ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source) +ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source) { char thumb_path[FILE_MAX]; char thumb_name[40]; char uri[URI_MAX]; const char *file_path; + const char *path; char path_buff[FILE_MAX]; BLI_stat_t st; ImBuf *img = NULL; - file_path = path; - UNUSED_VARS(path_buff); + path = file_path = org_path; + if (source == THB_SOURCE_FONT) { + BLI_snprintf(path_buff, sizeof(path_buff), "%s.%s", org_path, IMB_thumb_load_font_get_language()); + path = path_buff; + } if (BLI_stat(file_path, &st) == -1) { return NULL; diff --git a/source/blender/imbuf/intern/thumbs_font.c b/source/blender/imbuf/intern/thumbs_font.c index c8982318d80..7c94742a187 100644 --- a/source/blender/imbuf/intern/thumbs_font.c +++ b/source/blender/imbuf/intern/thumbs_font.c @@ -34,18 +34,19 @@ /* XXX, bad level call */ #include "../../blenfont/BLF_api.h" +#include "../../blenfont/BLF_translation.h" /* 'N_' macro and BLF_lang_get()... */ struct ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y) { const int font_size = y / 4; const char *thumb_str[] = { - "AaBbCc", + N_("AaBbCc"), - "The quick", - "brown fox", - "jumps over", - "the lazy dog", + N_("The quick"), + N_("brown fox"), + N_("jumps over"), + N_("the lazy dog"), }; struct ImBuf *ibuf; @@ -71,3 +72,7 @@ struct ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned return ibuf; } +const char *IMB_thumb_load_font_get_language(void) +{ + return BLF_lang_get(); +} -- cgit v1.2.3 From 02a5cf75a21ba0aeb394b3ff0b9882f950187adc Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Fri, 10 Apr 2015 11:03:47 -0300 Subject: Fix for debug-only crash when setting "Any" keymap input type Another one of those assert crashes when passing values != than 1 and 0 (in this case the value is -1) Notes from reviewer: -------------------- These should really be enums. since valid values are KM_ANY, KM_MOD_FIRST, KM_MOD_SECOND. But can see at some point this was changed from an enum so... I guess this is the only way. Reviewers: campbellbarton Differential Revision: https://developer.blender.org/D1227 --- source/blender/makesrna/intern/rna_wm.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index a423a069517..f01e1d02028 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -790,6 +790,29 @@ static void rna_KeyMapItem_any_set(PointerRNA *ptr, int value) } } +static int rna_KeyMapItem_shift_get(PointerRNA *ptr) +{ + wmKeyMapItem *kmi = (wmKeyMapItem *)ptr->data; + return kmi->shift != 0; +} + +static int rna_KeyMapItem_ctrl_get(PointerRNA *ptr) +{ + wmKeyMapItem *kmi = (wmKeyMapItem *)ptr->data; + return kmi->ctrl != 0; +} + +static int rna_KeyMapItem_alt_get(PointerRNA *ptr) +{ + wmKeyMapItem *kmi = (wmKeyMapItem *)ptr->data; + return kmi->alt != 0; +} + +static int rna_KeyMapItem_oskey_get(PointerRNA *ptr) +{ + wmKeyMapItem *kmi = (wmKeyMapItem *)ptr->data; + return kmi->oskey != 0; +} static PointerRNA rna_WindowManager_active_keyconfig_get(PointerRNA *ptr) { @@ -2073,6 +2096,7 @@ static void rna_def_keyconfig(BlenderRNA *brna) prop = RNA_def_property(srna, "shift", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "shift", 0); + RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_shift_get", NULL); /* RNA_def_property_enum_sdna(prop, NULL, "shift"); */ /* RNA_def_property_enum_items(prop, keymap_modifiers_items); */ RNA_def_property_ui_text(prop, "Shift", "Shift key pressed"); @@ -2080,6 +2104,7 @@ static void rna_def_keyconfig(BlenderRNA *brna) prop = RNA_def_property(srna, "ctrl", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ctrl", 0); + RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_ctrl_get", NULL); /* RNA_def_property_enum_sdna(prop, NULL, "ctrl"); */ /* RNA_def_property_enum_items(prop, keymap_modifiers_items); */ RNA_def_property_ui_text(prop, "Ctrl", "Control key pressed"); @@ -2087,6 +2112,7 @@ static void rna_def_keyconfig(BlenderRNA *brna) prop = RNA_def_property(srna, "alt", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "alt", 0); + RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_alt_get", NULL); /* RNA_def_property_enum_sdna(prop, NULL, "alt"); */ /* RNA_def_property_enum_items(prop, keymap_modifiers_items); */ RNA_def_property_ui_text(prop, "Alt", "Alt key pressed"); @@ -2094,6 +2120,7 @@ static void rna_def_keyconfig(BlenderRNA *brna) prop = RNA_def_property(srna, "oskey", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "oskey", 0); + RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_oskey_get", NULL); /* RNA_def_property_enum_sdna(prop, NULL, "oskey"); */ /* RNA_def_property_enum_items(prop, keymap_modifiers_items); */ RNA_def_property_ui_text(prop, "OS Key", "Operating system key pressed"); -- cgit v1.2.3 From d850fd8244d3aee72ad8a1aadda98dd2a6bcb1eb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 11 Apr 2015 00:42:35 +1000 Subject: Disable strict flags for msvc --- source/blender/blenkernel/intern/bpath.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 2b3261fa4a7..357e248c323 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -80,7 +80,9 @@ #include "BKE_bpath.h" /* own include */ -#include "BLI_strict_flags.h" +#ifndef _MSC_VER +# include "BLI_strict_flags.h" +#endif static bool checkMissingFiles_visit_cb(void *userdata, char *UNUSED(path_dst), const char *path_src) { -- cgit v1.2.3 From 35812e65f42681e7ade107ad1c703532e2cf1e17 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 10 Apr 2015 22:35:10 +0500 Subject: Cycles: Fix compilation error on windows after recent logging changes --- intern/cycles/device/device_cpu.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 63735df88ab..013f656e31c 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -19,6 +19,15 @@ /* So ImathMath is included before our kernel_cpu_compat. */ #ifdef WITH_OSL +# if defined(_MSC_VER) +/* Prevent OSL from polluting the context with weird macros from windows.h. + * TODO(sergey): Ideally it's only enough to have class/struct declarations in + * the header and skip header include here. + */ +# define NOGDI +# define NOMINMAX +# define WIN32_LEAN_AND_MEAN +# endif # include #endif -- cgit v1.2.3 From 465a5d29c0333f5bd5847f3febdd12f4b2746d0b Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Fri, 10 Apr 2015 20:20:52 +0200 Subject: BGE : Fix T43800: getScreenVect()/getScreenPosition()/modelview_matrix returns incorrect results The getScreenVect(), getScreenPosition() and modelview_matrixmethod returns an incorrect results if called after the camera has been translated on the same frame. The model view matrix will be update only once per frame with Cam->SetModelviewMatrix in KX_KetsjiEngine::RenderFrame. Using GetWorldToCamera as model view matrix to get an actual view matrix even if the camera is moved. Reviewers: sergey, dfelinto, brita_, sybren, hg1, campbellbarton Reviewed By: hg1, campbellbarton Projects: #game_engine Differential Revision: https://developer.blender.org/D1170 --- source/gameengine/Ketsji/KX_Camera.cpp | 6 +++--- source/gameengine/Ketsji/KX_Camera.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index 4dbaddcaa47..4456345e1d9 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -886,7 +886,7 @@ int KX_Camera::pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_D PyObject *KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_Camera* self = static_cast(self_v); - return PyObjectFrom(self->GetModelviewMatrix()); + return PyObjectFrom(self->GetWorldToCamera()); } PyObject *KX_Camera::pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -995,7 +995,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition, GLdouble modelmatrix[16]; GLdouble projmatrix[16]; - MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix(); + MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera(); MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); m_modelmatrix.getValue(modelmatrix); @@ -1038,7 +1038,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenVect, GLdouble modelmatrix[16]; GLdouble projmatrix[16]; - MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix(); + MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera(); MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); m_modelmatrix.getValue(modelmatrix); diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index 454c4a54ec1..eeb836c44b8 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -192,7 +192,7 @@ public: void InvalidateProjectionMatrix(bool valid = false); /** Gets the modelview matrix that is used by the rasterizer. - * \warning If the Camera is a dynamic object then this method may return garbage. Use GetCameraToWorld() instead. + * \warning If the Camera is a dynamic object then this method may return garbage. Use GetWorldToCamera() instead. */ const MT_Matrix4x4& GetModelviewMatrix() const; -- cgit v1.2.3 From 7447a0173cc841a1e9bd3f655c3230382c1e7cb7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 11 Apr 2015 19:41:31 +1000 Subject: Remove splash link to support gooseberry Was included only for initial campaign. --- source/blender/windowmanager/intern/wm_operators.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index c97b8e588e8..2b09c5cc9f8 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1997,8 +1997,10 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar split = uiLayoutSplit(layout, 0.0f, false); col = uiLayoutColumn(split, false); uiItemL(col, IFACE_("Links"), ICON_NONE); +#if 0 uiItemStringO(col, IFACE_("Support an Open Animation Movie"), ICON_URL, "WM_OT_url_open", "url", "https://cloud.blender.org/join"); +#endif uiItemStringO(col, IFACE_("Donations"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/foundation/donation-payment/"); uiItemStringO(col, IFACE_("Credits"), ICON_URL, "WM_OT_url_open", "url", -- cgit v1.2.3 From ccf44c400c896761c87836a06be24216c366c87b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 11 Apr 2015 23:36:37 +1000 Subject: BMesh: simplify hashing for dyntopo Was using pointer hashing when the keys are in fact uint's. Since they're well distributed from the rangetree, no need to do bit-shifting tricks. just use int as hash. Gives ~8% speedup in own tests. --- source/blender/blenlib/BLI_ghash.h | 1 + source/blender/blenlib/intern/BLI_ghash.c | 5 +++++ source/blender/bmesh/intern/bmesh_log.c | 16 ++++++++++------ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index a00ddeefb2b..f287cf71f53 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -148,6 +148,7 @@ bool BLI_ghashutil_strcmp(const void *a, const void *b); unsigned int BLI_ghashutil_uinthash(unsigned int key); unsigned int BLI_ghashutil_inthash_p(const void *ptr); unsigned int BLI_ghashutil_inthash_p_murmur(const void *ptr); +unsigned int BLI_ghashutil_inthash_p_simple(const void *ptr); bool BLI_ghashutil_intcmp(const void *a, const void *b); diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index dae7af6a927..484fe70104e 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -1091,6 +1091,11 @@ unsigned int BLI_ghashutil_inthash_p_murmur(const void *ptr) return BLI_hash_mm2((const unsigned char *)&key, sizeof(key), 0); } +unsigned int BLI_ghashutil_inthash_p_simple(const void *ptr) +{ + return GET_UINT_FROM_POINTER(ptr); +} + bool BLI_ghashutil_intcmp(const void *a, const void *b) { return (a != b); diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index c53b7f939c9..25ddb9ea79e 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -126,6 +126,10 @@ typedef struct { /************************* Get/set element IDs ************************/ +/* bypass actual hashing, the keys don't overlap */ +#define logkey_hash BLI_ghashutil_inthash_p_simple +#define logkey_cmp BLI_ghashutil_intcmp + /* Get the vertex's unique ID from the log */ static unsigned int bm_log_vert_id_get(BMLog *log, BMVert *v) { @@ -386,12 +390,12 @@ static BMLogEntry *bm_log_entry_create(void) { BMLogEntry *entry = MEM_callocN(sizeof(BMLogEntry), __func__); - entry->deleted_verts = BLI_ghash_ptr_new(__func__); - entry->deleted_faces = BLI_ghash_ptr_new(__func__); - entry->added_verts = BLI_ghash_ptr_new(__func__); - entry->added_faces = BLI_ghash_ptr_new(__func__); - entry->modified_verts = BLI_ghash_ptr_new(__func__); - entry->modified_faces = BLI_ghash_ptr_new(__func__); + entry->deleted_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); + entry->deleted_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); + entry->added_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); + entry->added_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); + entry->modified_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); + entry->modified_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); entry->pool_verts = BLI_mempool_create(sizeof(BMLogVert), 0, 64, BLI_MEMPOOL_NOP); entry->pool_faces = BLI_mempool_create(sizeof(BMLogFace), 0, 64, BLI_MEMPOOL_NOP); -- cgit v1.2.3 From a6421e12915db17d311cd716f34395b3c56859bc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 11 Apr 2015 23:41:10 +1000 Subject: BMesh: intersect was using ptr hash for int keys --- source/blender/bmesh/tools/bmesh_intersect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c index 064dbd7405b..6c0fa4a37c0 100644 --- a/source/blender/bmesh/tools/bmesh_intersect.c +++ b/source/blender/bmesh/tools/bmesh_intersect.c @@ -804,7 +804,7 @@ bool BM_mesh_intersect( s.edgetri_cache = BLI_ghash_new(BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, __func__); s.edge_verts = BLI_ghash_ptr_new(__func__); - s.face_edges = BLI_ghash_ptr_new(__func__); + s.face_edges = BLI_ghash_int_new(__func__); s.wire_edges = BLI_gset_ptr_new(__func__); s.vert_dissolve = NULL; -- cgit v1.2.3 From b329016b29c3189e23bafebbe984008dae0d60a2 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 11 Apr 2015 16:07:45 +0200 Subject: BGE: FIX T43537: ImageMirror does not work in BlenderPlayer with quad buffer In quad-buffer stereo mode, the GE render pass ends with the right eye on the right buffer, but we need to draw on the left buffer to capture the render. Reviewed By: agoose77, HG1 --- source/gameengine/VideoTexture/ImageRender.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 9feb6141cc4..6a898ff50c2 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -272,6 +272,12 @@ void ImageRender::Render() // restore the stereo mode now that the matrix is computed m_rasterizer->SetStereoMode(stereomode); + if (stereomode == RAS_IRasterizer::RAS_STEREO_QUADBUFFERED) { + // In QUAD buffer stereo mode, the GE render pass ends with the right eye on the right buffer + // but we need to draw on the left buffer to capture the render + // TODO: implement an explicit function in rasterizer to restore the left buffer. + m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_LEFTEYE); + } m_scene->CalculateVisibleMeshes(m_rasterizer,m_camera); m_scene->RenderBuckets(camtrans, m_rasterizer); -- cgit v1.2.3 From 87b6d3c7960461249e80c4c8c304cfc968c6586c Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Sat, 11 Apr 2015 16:16:46 +0200 Subject: BGE: Add keyword arguments to createConstraint API Added keyword arguments to createConstraint. Changed initial values for the pivod XYZ form 1 to 0.0. Changed initial values for the axis Z form 1 to 0.0. Delete the parsing for 4 parameters, because parsing only the X pivot is not necessary, also it was not working correctly (int instead of float). Reviewers: brita_, sybren, lordloki, campbellbarton, moguri Reviewed By: lordloki, campbellbarton Subscribers: campbellbarton Differential Revision: https://developer.blender.org/D705 --- doc/python_api/rst/bge.constraints.rst | 32 ++++---- .../gameengine/Ketsji/KX_PyConstraintBinding.cpp | 89 +++++++--------------- 2 files changed, 45 insertions(+), 76 deletions(-) diff --git a/doc/python_api/rst/bge.constraints.rst b/doc/python_api/rst/bge.constraints.rst index 018be96fd14..636a66273e8 100644 --- a/doc/python_api/rst/bge.constraints.rst +++ b/doc/python_api/rst/bge.constraints.rst @@ -11,14 +11,14 @@ Physics Constraints (bge.constraints) .. literalinclude:: ../examples/bge.constraints.py :lines: 6- -.. function:: createConstraint(physicsid, physicsid2, constrainttype, [pivotX, pivotY, pivotZ, [axisX, axisY, axisZ, [flag]]]]) +.. function:: createConstraint(physicsid_1, physicsid_2, constraint_type, pivot_X, pivot_y, pivot_z, axis_x, axis_y, axis_z, flag) Creates a constraint. - :arg physicsid: the physics id of the first object in constraint + :arg physicsid_1: the physics id of the first object in constraint :type physicsid: int - :arg physicsid2: the physics id of the second object in constraint + :arg physicsid_2: the physics id of the second object in constraint :type physicsid2: int :arg constrainttype: the type of the constraint. The constraint types are: @@ -32,26 +32,26 @@ Physics Constraints (bge.constraints) :type constrainttype: int - :arg pivotX: pivot X position - :type pivotX: float + :arg pivot_X: pivot X position + :type pivot_X: float (optional) - :arg pivotY: pivot Y position - :type pivotY: float + :arg pivot_Y: pivot Y position + :type pivot_Y: float (optional) - :arg pivotZ: pivot Z position - :type pivotZ: float + :arg pivot_Z: pivot Z position + :type pivot_Z: float (optional) - :arg axisX: X axis - :type axisX: float + :arg axis_X: X axis angle in degrees + :type axis_X: float (optional) - :arg axisY: Y axis - :type axisY: float + :arg axis_Y: Y axis angle in degrees + :type axis_Y: float (optional) - :arg axisZ: Z axis - :type axisZ: float + :arg axis_Z: Z axis angle in degrees + :type axis_Z: float (optional) :arg flag: 128 to disable collision between linked bodies - :type flag: int + :type flag: int (optional) .. attribute:: error diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 94f5064261f..77453916e44 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -496,78 +496,47 @@ static PyObject *gPyCreateConstraint(PyObject *self, { /* FIXME - physicsid is a long being cast to a pointer, should at least use PyCapsule */ unsigned long long physicsid = 0, physicsid2 = 0; - int constrainttype=0, extrainfo=0; + int constrainttype = 0; int len = PyTuple_Size(args); - int success = 1; int flag = 0; + float pivotX = 0.0f, pivotY = 0.0f, pivotZ = 0.0f, axisX = 0.0f, axisY = 0.0f, axisZ = 0.0f; - float pivotX=1,pivotY=1,pivotZ=1,axisX=0,axisY=0,axisZ=1; - if (len == 3) - { - success = PyArg_ParseTuple(args, "KKi", &physicsid, &physicsid2, &constrainttype); - } - else if (len == 6) - { - success = PyArg_ParseTuple(args, "KKifff", &physicsid, &physicsid2, &constrainttype, - &pivotX, &pivotY, &pivotZ); - } - else if (len == 9) - { - success = PyArg_ParseTuple(args, "KKiffffff", &physicsid, &physicsid2, &constrainttype, - &pivotX, &pivotY, &pivotZ, &axisX, &axisY, &axisZ); - } - else if (len == 10) - { - success = PyArg_ParseTuple(args, "KKiffffffi", &physicsid, &physicsid2, &constrainttype, - &pivotX, &pivotY, &pivotZ, &axisX, &axisY, &axisZ, &flag); - } + static const char *kwlist[] = {"physicsid_1", "physicsid_2", "constraint_type", "pivot_x", "pivot_y", "pivot_z", + "axis_X", "axis_y", "axis_z", "flag", NULL}; - /* XXX extrainfo seems to be nothing implemented. right now it works as a pivot with [X,0,0] */ - else if (len == 4) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "KKi|ffffffi:createConstraint", (char **)kwlist, + &physicsid, &physicsid2, &constrainttype, + &pivotX, &pivotY, &pivotZ, &axisX, &axisY, &axisZ, &flag)) { - success = PyArg_ParseTuple(args,"KKii", &physicsid, &physicsid2, &constrainttype, &extrainfo); - pivotX=extrainfo; + return NULL; } - if (success) - { - if (PHY_GetActiveEnvironment()) - { - - PHY_IPhysicsController* physctrl = (PHY_IPhysicsController*) physicsid; - PHY_IPhysicsController* physctrl2 = (PHY_IPhysicsController*) physicsid2; - if (physctrl) //TODO:check for existence of this pointer! - { - int constraintid =0; - - //convert from euler angle into axis - float radsPerDeg = 6.283185307179586232f / 360.f; + if (PHY_GetActiveEnvironment()) { + PHY_IPhysicsController *physctrl = (PHY_IPhysicsController*)physicsid; + PHY_IPhysicsController *physctrl2 = (PHY_IPhysicsController*)physicsid2; + if (physctrl) { //TODO:check for existence of this pointer! + //convert from euler angle into axis + const float deg2rad = 0.017453292f; - //we need to pass a full constraint frame, not just axis - //localConstraintFrameBasis - MT_Matrix3x3 localCFrame(MT_Vector3(radsPerDeg*axisX,radsPerDeg*axisY,radsPerDeg*axisZ)); - MT_Vector3 axis0 = localCFrame.getColumn(0); - MT_Vector3 axis1 = localCFrame.getColumn(1); - MT_Vector3 axis2 = localCFrame.getColumn(2); + //we need to pass a full constraint frame, not just axis + //localConstraintFrameBasis + MT_Matrix3x3 localCFrame(MT_Vector3(deg2rad*axisX, deg2rad*axisY, deg2rad*axisZ)); + MT_Vector3 axis0 = localCFrame.getColumn(0); + MT_Vector3 axis1 = localCFrame.getColumn(1); + MT_Vector3 axis2 = localCFrame.getColumn(2); - constraintid = PHY_GetActiveEnvironment()->CreateConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype, - pivotX,pivotY,pivotZ, - (float)axis0.x(),(float)axis0.y(),(float)axis0.z(), - (float)axis1.x(),(float)axis1.y(),(float)axis1.z(), - (float)axis2.x(),(float)axis2.y(),(float)axis2.z(),flag); + int constraintid = PHY_GetActiveEnvironment()->CreateConstraint( + physctrl, physctrl2, (enum PHY_ConstraintType)constrainttype, pivotX, pivotY, pivotZ, + (float)axis0.x(), (float)axis0.y(), (float)axis0.z(), + (float)axis1.x(), (float)axis1.y(), (float)axis1.z(), + (float)axis2.x(), (float)axis2.y(), (float)axis2.z(), flag); - KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment()); + KX_ConstraintWrapper *wrap = new KX_ConstraintWrapper( + (enum PHY_ConstraintType)constrainttype, constraintid, PHY_GetActiveEnvironment()); - return wrap->NewProxy(true); - } - - + return wrap->NewProxy(true); } } - else { - return NULL; - } - Py_RETURN_NONE; } @@ -680,7 +649,7 @@ static struct PyMethodDef physicsconstraints_methods[] = { {"createConstraint",(PyCFunction) gPyCreateConstraint, - METH_VARARGS, (const char *)gPyCreateConstraint__doc__}, + METH_VARARGS|METH_KEYWORDS, (const char *)gPyCreateConstraint__doc__}, {"getVehicleConstraint",(PyCFunction) gPyGetVehicleConstraint, METH_VARARGS, (const char *)gPyGetVehicleConstraint__doc__}, -- cgit v1.2.3 From 17b4f57bf0ec8beb956198654589d49e261b7f97 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 12 Apr 2015 11:12:16 +1000 Subject: Missed this last commit (dyntopo hashing) --- source/blender/bmesh/intern/bmesh_log.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index 25ddb9ea79e..8596fcbf83e 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -480,10 +480,11 @@ static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash) BMLog *BM_log_create(BMesh *bm) { BMLog *log = MEM_callocN(sizeof(*log), __func__); + const unsigned int reserve_num = (unsigned int)(bm->totvert + bm->totface); log->unused_ids = range_tree_uint_alloc(0, (unsigned)-1); - log->id_to_elem = BLI_ghash_ptr_new_ex(__func__, (unsigned int)(bm->totvert + bm->totface)); - log->elem_to_id = BLI_ghash_ptr_new_ex(__func__, (unsigned int)(bm->totvert + bm->totface)); + log->id_to_elem = BLI_ghash_new_ex(logkey_hash, logkey_cmp, __func__, reserve_num); + log->elem_to_id = BLI_ghash_ptr_new_ex(__func__, reserve_num); /* Assign IDs to all existing vertices and faces */ bm_log_assign_ids(bm, log); -- cgit v1.2.3 From f50fed6a6dfc24a52327f9085122e0a530fcc2ae Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Sun, 12 Apr 2015 08:03:46 +0200 Subject: Reset view after ctrl-clicking a Panel Using ctrl+LMB to collapse all panels except of the clicked one resulted in an empty area if done from a view that is scrolled down to some degree. Resetting the view makes this much better, although it still doesn't work that well if the area is really small, but I don't think it's worth over-complicating things here. "Feature-Request" by @maxon ;) --- source/blender/editors/interface/interface_panel.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index d165e2719c5..5aee8e18ba0 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -1187,9 +1187,13 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in ED_region_tag_redraw(ar); } else { /* collapse */ - if (ctrl) + if (ctrl) { panels_collapse_all(sa, ar, block->panel); + /* reset the view - we don't want to display a view without content */ + UI_view2d_offset(&ar->v2d, 0.0f, 1.0f); + } + if (block->panel->flag & PNL_CLOSED) { block->panel->flag &= ~PNL_CLOSED; /* snap back up so full panel aligns with screen edge */ -- cgit v1.2.3 From 6d2c3a245622fa836ae603666789970a2f83b1c1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 12 Apr 2015 15:01:38 +1000 Subject: BMesh: avoid ghash realloc's making log entry --- source/blender/bmesh/intern/bmesh_log.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index 8596fcbf83e..d2397faa7d1 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -993,6 +993,15 @@ void BM_log_all_added(BMesh *bm, BMLog *log) BMVert *v; BMFace *f; + /* avoid unnecessary resizing on initialization */ + if (BLI_ghash_size(log->current_entry->added_verts) == 0) { + BLI_ghash_reserve(log->current_entry->added_verts, (unsigned int)bm->totvert); + } + + if (BLI_ghash_size(log->current_entry->added_faces) == 0) { + BLI_ghash_reserve(log->current_entry->added_faces, (unsigned int)bm->totface); + } + /* Log all vertices as newly created */ BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) { BM_log_vert_added(log, v, cd_vert_mask_offset); -- cgit v1.2.3 From 690b90f1e2cb949a3cdfb02678be844c4808f2cb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 12 Apr 2015 15:21:40 +1000 Subject: BMesh: minor optimization counting adjacent data add BM_***_count_is_over(), _count_is_equal() Useful if we only want to know if the count is a smaller value. --- source/blender/blenkernel/intern/pbvh_bmesh.c | 52 ++++++++++++------- source/blender/bmesh/intern/bmesh_core.c | 2 +- source/blender/bmesh/intern/bmesh_mods.c | 5 +- source/blender/bmesh/intern/bmesh_private.h | 1 + source/blender/bmesh/intern/bmesh_queries.c | 41 ++++++++++++++- source/blender/bmesh/intern/bmesh_queries.h | 10 ++++ source/blender/bmesh/intern/bmesh_structure.c | 59 ++++++++++++++++++++-- source/blender/bmesh/intern/bmesh_structure.h | 2 + source/blender/bmesh/tools/bmesh_beautify.c | 6 +-- source/blender/bmesh/tools/bmesh_bevel.c | 2 +- source/blender/editors/mesh/editmesh_rip.c | 6 +-- source/blender/editors/mesh/editmesh_select.c | 4 +- source/blender/editors/sculpt_paint/paint_stroke.c | 2 +- source/blender/python/bmesh/bmesh_py_utils.c | 4 +- 14 files changed, 158 insertions(+), 38 deletions(-) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 01bca44d3b6..92fdfa9e2a4 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -369,6 +369,7 @@ static BMFace *pbvh_bmesh_face_create( } /* Return the number of faces in 'node' that use vertex 'v' */ +#if 0 static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v) { BMIter bm_iter; @@ -376,12 +377,33 @@ static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v) int count = 0; BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) { - PBVHNode *f_node; + PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, f); + if (f_node == node) { + count++; + } + } - f_node = pbvh_bmesh_node_lookup(bvh, f); + return count; +} +#endif + +#define pbvh_bmesh_node_vert_use_count_is_equal(bvh, node, v, n) \ + (pbvh_bmesh_node_vert_use_count_ex(bvh, node, v, (n) + 1) == n) - if (f_node == node) +static int pbvh_bmesh_node_vert_use_count_ex(PBVH *bvh, PBVHNode *node, BMVert *v, const int count_max) +{ + BMIter bm_iter; + BMFace *f; + int count = 0; + + BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) { + PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, f); + if (f_node == node) { count++; + if (count == count_max) { + break; + } + } } return count; @@ -484,13 +506,13 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { v = l_iter->v; - if (pbvh_bmesh_node_vert_use_count(bvh, f_node, v) == 1) { + if (pbvh_bmesh_node_vert_use_count_is_equal(bvh, f_node, v, 1)) { if (BLI_gset_haskey(f_node->bm_unique_verts, v)) { /* Find a different node that uses 'v' */ PBVHNode *new_node; new_node = pbvh_bmesh_vert_other_node_find(bvh, v); - BLI_assert(new_node || BM_vert_face_count(v) == 1); + BLI_assert(new_node || BM_vert_face_count_is_equal(v, 1)); if (new_node) { pbvh_bmesh_vert_ownership_transfer(bvh, new_node, v); @@ -810,13 +832,11 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh, BM_face_kill(bvh->bm, f_adj); /* Ensure new vertex is in the node */ - if (!BLI_gset_haskey(bvh->nodes[ni].bm_unique_verts, v_new) && - !BLI_gset_haskey(bvh->nodes[ni].bm_other_verts, v_new)) - { - BLI_gset_insert(bvh->nodes[ni].bm_other_verts, v_new); + if (!BLI_gset_haskey(bvh->nodes[ni].bm_unique_verts, v_new)) { + BLI_gset_add(bvh->nodes[ni].bm_other_verts, v_new); } - if (BM_vert_edge_count(v_opp) >= 9) { + if (BM_vert_edge_count_is_over(v_opp, 8)) { BMIter bm_iter; BMEdge *e2; @@ -945,10 +965,8 @@ static void pbvh_bmesh_collapse_edge( pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f); /* Ensure that v_conn is in the new face's node */ - if (!BLI_gset_haskey(n->bm_unique_verts, v_conn) && - !BLI_gset_haskey(n->bm_other_verts, v_conn)) - { - BLI_gset_insert(n->bm_other_verts, v_conn); + if (!BLI_gset_haskey(n->bm_unique_verts, v_conn)) { + BLI_gset_add(n->bm_other_verts, v_conn); } } @@ -973,7 +991,7 @@ static void pbvh_bmesh_collapse_edge( /* Check if any of the face's vertices are now unused, if so * remove them from the PBVH */ for (j = 0; j < 3; j++) { - if (v_tri[j] != v_del && BM_vert_face_count(v_tri[j]) == 1) { + if (v_tri[j] != v_del && BM_vert_face_count_is_equal(v_tri[j], 1)) { BLI_gset_insert(deleted_verts, v_tri[j]); pbvh_bmesh_vert_remove(bvh, v_tri[j]); } @@ -1010,7 +1028,7 @@ static void pbvh_bmesh_collapse_edge( } /* Delete v_del */ - BLI_assert(BM_vert_face_count(v_del) == 0); + BLI_assert(!BM_vert_face_check(v_del)); BLI_gset_insert(deleted_verts, v_del); BM_log_vert_removed(bvh->bm_log, v_del, eq_ctx->cd_vert_mask_offset); BM_vert_kill(bvh->bm, v_del); @@ -1641,7 +1659,7 @@ static void pbvh_bmesh_verify(PBVH *bvh) GSET_ITER (gs_iter, n->bm_other_verts) { BMVert *v = BLI_gsetIterator_getKey(&gs_iter); - BLI_assert(BM_vert_face_count(v) > 0); + BLI_assert(!BM_vert_face_check(v)); BLI_assert(BLI_gset_haskey(verts_all, v)); } } diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 9e0807710fc..ad35f6e0472 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1111,7 +1111,7 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del) if (!d1 && !d2 && !BM_ELEM_API_FLAG_TEST(l_iter->e, _FLAG_JF)) { /* don't remove an edge it makes up the side of another face * else this will remove the face as well - campbell */ - if (BM_edge_face_count(l_iter->e) <= 2) { + if (!BM_edge_face_count_is_over(l_iter->e, 3)) { if (do_del) { BLI_array_append(deledges, l_iter->e); } diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 7b3f64dc5cd..85e9ec3aa24 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -72,7 +72,8 @@ */ bool BM_vert_dissolve(BMesh *bm, BMVert *v) { - const int len = BM_vert_edge_count(v); + /* logic for 3 or more is identical */ + const int len = BM_vert_edge_count_ex(v, 3); if (len == 1) { BM_vert_kill(bm, v); /* will kill edges too */ @@ -97,7 +98,7 @@ bool BM_vert_dissolve(BMesh *bm, BMVert *v) return false; } } - else if (len == 2 && BM_vert_face_count(v) == 1) { + else if (len == 2 && BM_vert_face_count_is_equal(v, 1)) { /* boundary vertex on a face */ return (BM_vert_collapse_edge(bm, v->e, v, true, true) != NULL); } diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h index 102a677943b..814015a2a74 100644 --- a/source/blender/bmesh/intern/bmesh_private.h +++ b/source/blender/bmesh/intern/bmesh_private.h @@ -54,6 +54,7 @@ int bmesh_elem_check(void *element, const char htype); #endif int bmesh_radial_length(const BMLoop *l); +int bmesh_disk_count_ex(const BMVert *v, const int count_max); int bmesh_disk_count(const BMVert *v); /** diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 7c557cb1343..392f8b0bba2 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -750,6 +750,11 @@ int BM_vert_edge_count(const BMVert *v) return bmesh_disk_count(v); } +int BM_vert_edge_count_ex(const BMVert *v, const int count_max) +{ + return bmesh_disk_count_ex(v, count_max); +} + int BM_vert_edge_count_nonwire(const BMVert *v) { int count = 0; @@ -770,13 +775,30 @@ int BM_edge_face_count(const BMEdge *e) int count = 0; if (e->l) { - BMLoop *l_iter; - BMLoop *l_first; + BMLoop *l_iter, *l_first; l_iter = l_first = e->l; + do { + count++; + } while ((l_iter = l_iter->radial_next) != l_first); + } + return count; +} + +int BM_edge_face_count_ex(const BMEdge *e, const int count_max) +{ + int count = 0; + + if (e->l) { + BMLoop *l_iter, *l_first; + + l_iter = l_first = e->l; do { count++; + if (count == count_max) { + break; + } } while ((l_iter = l_iter->radial_next) != l_first); } @@ -792,6 +814,21 @@ int BM_vert_face_count(const BMVert *v) return bmesh_disk_facevert_count(v); } +int BM_vert_face_count_ex(const BMVert *v, int count_max) +{ + return bmesh_disk_facevert_count_ex(v, count_max); +} + +/** + * Return true if the vertex is connected to _any_ faces. + * + * same as ``BM_vert_face_count(v) != 0`` or ``BM_vert_find_first_loop(v) == NULL`` + */ +bool BM_vert_face_check(BMVert *v) +{ + return v->e && (bmesh_disk_faceedge_find_first(v->e, v) != NULL); +} + /** * Tests whether or not the vertex is part of a wire edge. * (ie: has no faces attached to it) diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 4ee5588ba0b..6d25d9fbfec 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -65,12 +65,22 @@ BMFace *BM_vert_pair_share_face_by_angle( const bool allow_adjacent) ATTR_NONNULL(); int BM_vert_edge_count_nonwire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +#define BM_vert_edge_count_is_equal(v, n) (BM_vert_edge_count_ex(v, (n) + 1) == n) +#define BM_vert_edge_count_is_over(v, n) (BM_vert_edge_count_ex(v, (n) + 1) == (n) + 1) +int BM_vert_edge_count_ex(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int BM_vert_edge_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +#define BM_edge_face_count_is_equal(e, n) (BM_edge_face_count_ex(e, (n) + 1) == n) +#define BM_edge_face_count_is_over(e, n) (BM_edge_face_count_ex(e, (n) + 1) == (n) + 1) +int BM_edge_face_count_ex(const BMEdge *e, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int BM_edge_face_count(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +#define BM_vert_face_count_is_equal(v, n) (BM_vert_face_count_ex(v, (n) + 1) == n) +#define BM_vert_face_count_is_over(v, n) (BM_vert_face_count_ex(v, (n) + 1) == (n) + 1) +int BM_vert_face_count_ex(const BMVert *v, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int BM_vert_face_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool BM_vert_is_edge_pair(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_vert_face_check(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool BM_vert_is_wire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c index 3e8002c0192..cf56c3b4b83 100644 --- a/source/blender/bmesh/intern/bmesh_structure.c +++ b/source/blender/bmesh/intern/bmesh_structure.c @@ -206,6 +206,22 @@ int bmesh_disk_count(const BMVert *v) return count; } +int bmesh_disk_count_ex(const BMVert *v, const int count_max) +{ + int count = 0; + if (v->e) { + BMEdge *e_first, *e_iter; + e_iter = e_first = v->e; + do { + count++; + if (count == count_max) { + break; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + } + return count; +} + bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) { BMEdge *e_iter; @@ -236,9 +252,9 @@ bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) int bmesh_disk_facevert_count(const BMVert *v) { /* is there an edge on this vert at all */ + int count = 0; if (v->e) { BMEdge *e_first, *e_iter; - int count = 0; /* first, loop around edge */ e_first = e_iter = v->e; @@ -247,11 +263,29 @@ int bmesh_disk_facevert_count(const BMVert *v) count += bmesh_radial_facevert_count(e_iter->l, v); } } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - return count; } - else { - return 0; + return count; +} + +int bmesh_disk_facevert_count_ex(const BMVert *v, const int count_max) +{ + /* is there an edge on this vert at all */ + int count = 0; + if (v->e) { + BMEdge *e_first, *e_iter; + + /* first, loop around edge */ + e_first = e_iter = v->e; + do { + if (e_iter->l) { + count += bmesh_radial_facevert_count_ex(e_iter->l, v, count_max - count); + if (count == count_max) { + break; + } + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); } + return count; } /** @@ -456,6 +490,23 @@ int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) return count; } +int bmesh_radial_facevert_count_ex(const BMLoop *l, const BMVert *v, const int count_max) +{ + const BMLoop *l_iter; + int count = 0; + l_iter = l; + do { + if (l_iter->v == v) { + count++; + if (count == count_max) { + break; + } + } + } while ((l_iter = l_iter->radial_next) != l); + + return count; +} + /** * \brief RADIAL CHECK FACE VERT * diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h index 29868194bbf..4a6247d7165 100644 --- a/source/blender/bmesh/intern/bmesh_structure.h +++ b/source/blender/bmesh/intern/bmesh_structure.h @@ -49,6 +49,7 @@ BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v) A BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int bmesh_disk_facevert_count_ex(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int bmesh_disk_facevert_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); @@ -60,6 +61,7 @@ void bmesh_radial_loop_remove(BMLoop *l, BMEdge *e) ATTR_NONNULL(1); * bmesh_radial_loop_next(BMLoop *l) / prev. * just use member access l->radial_next, l->radial_prev now */ +int bmesh_radial_facevert_count_ex(const BMLoop *l, const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool bmesh_radial_facevert_check(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c index 990a2108bd7..b64c3aab5d7 100644 --- a/source/blender/bmesh/tools/bmesh_beautify.c +++ b/source/blender/bmesh/tools/bmesh_beautify.c @@ -333,7 +333,7 @@ static void bm_edge_update_beauty_cost(BMEdge *e, Heap *eheap, HeapNode **eheap_ BLI_assert(e->l->f->len == 3 && e->l->radial_next->f->len == 3); - BLI_assert(BM_edge_face_count(e) == 2); + BLI_assert(BM_edge_face_count_is_equal(e, 2)); for (i = 0; i < 4; i++) { bm_edge_update_beauty_cost_single( @@ -389,11 +389,11 @@ void BM_mesh_beautify_fill( i = BM_elem_index_get(e); eheap_table[i] = NULL; - BLI_assert(BM_edge_face_count(e) == 2); + BLI_assert(BM_edge_face_count_is_equal(e, 2)); e = BM_edge_rotate(bm, e, false, BM_EDGEROT_CHECK_EXISTS); - BLI_assert(e == NULL || BM_edge_face_count(e) == 2); + BLI_assert(e == NULL || BM_edge_face_count_is_equal(e, 2)); if (LIKELY(e)) { GSet *e_state_set = edge_state_arr[i]; diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 3c7a86a332f..a2a0f974a79 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -2778,7 +2778,7 @@ static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv) copy_mesh_vert(vm, 1, 0, ns - k, 0, 0, k); } - if (BM_vert_face_count(bv->v) == 0) { + if (BM_vert_face_check(bv->v) == false) { e_eg = bv->edges[0].e; BLI_assert(e_eg != NULL); for (k = 0; k < ns; k++) { diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index ead243d6de8..45e16ceff7b 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -587,8 +587,8 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve /* if we are ripping a single vertex from 3 faces, * then measure the distance to the face corner as well as the edge */ - if (BM_vert_face_count(v) == 3 && - BM_vert_edge_count(v) == 3) + if (BM_vert_face_count_is_equal(v, 3) && + BM_vert_edge_count_is_equal(v, 3)) { BMEdge *e_all[3]; BMLoop *l_all[3]; @@ -735,7 +735,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve * but both allocate fill */ /* rip two adjacent edges */ - if (BM_edge_is_boundary(e2) || BM_vert_face_count(v) == 2) { + if (BM_edge_is_boundary(e2) || BM_vert_face_count_is_equal(v, 2)) { /* Don't run the edge split operator in this case */ BMVert *v_rip; diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index c020243c8ff..0c3f69e4996 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2042,7 +2042,7 @@ bool EDBM_select_interior_faces(BMEditMesh *em) ok = true; BM_ITER_ELEM (eed, &eiter, efa, BM_EDGES_OF_FACE) { - if (BM_edge_face_count(eed) < 3) { + if (!BM_edge_face_count_is_over(eed, 2)) { ok = false; break; } @@ -2938,7 +2938,7 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op) if ((use_wire && BM_edge_is_wire(e)) || (use_boundary && BM_edge_is_boundary(e)) || (use_non_contiguous && (BM_edge_is_manifold(e) && !BM_edge_is_contiguous(e))) || - (use_multi_face && (BM_edge_face_count(e) > 2))) + (use_multi_face && (BM_edge_face_count_is_over(e, 2)))) { /* check we never select perfect edge (in test above) */ BLI_assert(!(BM_edge_is_manifold(e) && BM_edge_is_contiguous(e))); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 0db2259b307..5588d1e589e 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -68,7 +68,7 @@ #include #include -// #define DEBUG_TIME +#define DEBUG_TIME #ifdef DEBUG_TIME # include "PIL_time_utildefines.h" diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index 2e32a571e3c..0dd6ee7d51a 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -84,7 +84,7 @@ static PyObject *bpy_bm_utils_vert_collapse_edge(PyObject *UNUSED(self), PyObjec return NULL; } - if (BM_vert_edge_count(py_vert->v) > 2) { + if (BM_vert_edge_count_is_over(py_vert->v, 2)) { PyErr_SetString(PyExc_ValueError, "vert_collapse_edge(vert, edge): vert has more than 2 connected edges"); return NULL; @@ -150,7 +150,7 @@ static PyObject *bpy_bm_utils_vert_collapse_faces(PyObject *UNUSED(self), PyObje return NULL; } - if (BM_vert_edge_count(py_vert->v) > 2) { + if (BM_vert_edge_count_is_over(py_vert->v, 2)) { PyErr_SetString(PyExc_ValueError, "vert_collapse_faces(vert, edge): vert has more than 2 connected edges"); return NULL; -- cgit v1.2.3 From 542a0c41d2c0a77de2d139bac8bc95c029ebf11c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 12 Apr 2015 19:14:28 +1000 Subject: Dyntopo: redundant length check subdividing edges --- source/blender/blenkernel/intern/pbvh_bmesh.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 92fdfa9e2a4..26d3a1e14ba 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -862,8 +862,14 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh, BLI_mempool_free(eq_ctx->pool, pair); pair = NULL; + /* At the moment edges never get shorter (subdiv will make new edges) + * unlike collapse where edges can become longer. */ +#if 0 if (len_squared_v3v3(v1->co, v2->co) <= eq_ctx->q->limit_len_squared) continue; +#else + BLI_assert(len_squared_v3v3(v1->co, v2->co) > eq_ctx->q->limit_len_squared); +#endif /* Check that the edge still exists */ if (!(e = BM_edge_exists(v1, v2))) { -- cgit v1.2.3 From c950b8f2892b985c4fa3e70cea572adda9608491 Mon Sep 17 00:00:00 2001 From: Ines Almeida Date: Sun, 12 Apr 2015 11:38:18 +0100 Subject: making add>lamp its own menu so it can be extended by addons --- release/scripts/startup/bl_ui/space_view3d.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index a23ad4209d5..32b8af140f4 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1043,6 +1043,17 @@ class INFO_MT_armature_add(Menu): layout.operator("object.armature_add", text="Single Bone", icon='BONE_DATA') +class INFO_MT_lamp_add(Menu): + bl_idname = "INFO_MT_lamp_add" + bl_label = "Lamp" + + def draw(self, context): + layout = self.layout + + layout.operator_context = 'INVOKE_REGION_WIN' + layout.operator_enum("object.lamp_add", "type") + + class INFO_MT_add(Menu): bl_label = "Add" @@ -1075,7 +1086,7 @@ class INFO_MT_add(Menu): layout.separator() layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA') - layout.operator_menu_enum("object.lamp_add", "type", text="Lamp", icon='OUTLINER_OB_LAMP') + layout.menu("INFO_MT_lamp_add", icon='OUTLINER_OB_LAMP') layout.separator() layout.operator_menu_enum("object.effector_add", "type", text="Force Field", icon='OUTLINER_OB_EMPTY') -- cgit v1.2.3 From 55b7a8c027717c93c74d1a81d66ded9f850ba372 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 12 Apr 2015 19:58:17 -0400 Subject: ndof: fix Linux device detect regression --- intern/ghost/intern/GHOST_NDOFManagerX11.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp index de44b36c73e..75e476c287f 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp @@ -43,7 +43,7 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys) #define MAX_LINE_LENGTH 100 /* look for USB devices with Logitech or 3Dconnexion's vendor ID */ - FILE *command_output = popen("lsusb | grep '046d:\|256f:'", "r"); + FILE *command_output = popen("lsusb | grep '046d:\\|256f:'", "r"); if (command_output) { char line[MAX_LINE_LENGTH] = {0}; while (fgets(line, MAX_LINE_LENGTH, command_output)) { -- cgit v1.2.3 From e688ba0304907d7e8d77a3d9dcb27d06dabc8a62 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 13 Apr 2015 13:45:14 +1000 Subject: GHash: use unsigned int for ghash_size --- source/blender/blenlib/BLI_ghash.h | 4 ++-- source/blender/blenlib/intern/BLI_ghash.c | 8 ++++---- source/blender/bmesh/tools/bmesh_intersect.c | 4 ++-- source/blender/bmesh/tools/bmesh_region_match.c | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index f287cf71f53..a5c397f32f0 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -86,7 +86,7 @@ void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP va const unsigned int nentries_reserve); void *BLI_ghash_popkey(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) ATTR_WARN_UNUSED_RESULT; bool BLI_ghash_haskey(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT; -int BLI_ghash_size(GHash *gh) ATTR_WARN_UNUSED_RESULT; +unsigned int BLI_ghash_size(GHash *gh) ATTR_WARN_UNUSED_RESULT; void BLI_ghash_flag_set(GHash *gh, unsigned int flag); void BLI_ghash_flag_clear(GHash *gh, unsigned int flag); @@ -220,7 +220,7 @@ GSet *BLI_gset_new_ex(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; GSet *BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; GSet *BLI_gset_copy(GSet *gs, GSetKeyCopyFP keycopyfp) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; -int BLI_gset_size(GSet *gs) ATTR_WARN_UNUSED_RESULT; +unsigned int BLI_gset_size(GSet *gs) ATTR_WARN_UNUSED_RESULT; void BLI_gset_flag_set(GSet *gs, unsigned int flag); void BLI_gset_flag_clear(GSet *gs, unsigned int flag); void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp); diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 484fe70104e..950d164bdbe 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -664,9 +664,9 @@ void BLI_ghash_reserve(GHash *gh, const unsigned int nentries_reserve) /** * \return size of the GHash. */ -int BLI_ghash_size(GHash *gh) +unsigned int BLI_ghash_size(GHash *gh) { - return (int)gh->nentries; + return gh->nentries; } /** @@ -1243,9 +1243,9 @@ GSet *BLI_gset_copy(GSet *gs, GHashKeyCopyFP keycopyfp) return (GSet *)ghash_copy((GHash *)gs, keycopyfp, NULL); } -int BLI_gset_size(GSet *gs) +unsigned int BLI_gset_size(GSet *gs) { - return (int)((GHash *)gs)->nentries; + return ((GHash *)gs)->nentries; } /** diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c index 6c0fa4a37c0..ceb6ded5a43 100644 --- a/source/blender/bmesh/tools/bmesh_intersect.c +++ b/source/blender/bmesh/tools/bmesh_intersect.c @@ -1040,8 +1040,8 @@ bool BM_mesh_intersect( } } - splice_ls = MEM_mallocN((unsigned int)BLI_gset_size(s.wire_edges) * sizeof(*splice_ls), __func__); - STACK_INIT(splice_ls, (unsigned int)BLI_gset_size(s.wire_edges)); + splice_ls = MEM_mallocN(BLI_gset_size(s.wire_edges) * sizeof(*splice_ls), __func__); + STACK_INIT(splice_ls, BLI_gset_size(s.wire_edges)); for (node = s.vert_dissolve; node; node = node->next) { BMEdge *e_pair[2]; diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c index 4322a288471..484eea73bbe 100644 --- a/source/blender/bmesh/tools/bmesh_region_match.c +++ b/source/blender/bmesh/tools/bmesh_region_match.c @@ -419,8 +419,8 @@ static void bm_uuidwalk_rehash( UUID_Int *uuid_store; unsigned int i; - unsigned int rehash_store_len_new = (unsigned int)MAX2(BLI_ghash_size(uuidwalk->verts_uuid), - BLI_ghash_size(uuidwalk->faces_uuid)); + unsigned int rehash_store_len_new = MAX2(BLI_ghash_size(uuidwalk->verts_uuid), + BLI_ghash_size(uuidwalk->faces_uuid)); bm_uuidwalk_rehash_reserve(uuidwalk, rehash_store_len_new); uuid_store = uuidwalk->cache.rehash_store; @@ -862,7 +862,7 @@ static BMFace **bm_mesh_region_match_pair( break; } - found = ((unsigned int)BLI_ghash_size(w_dst->faces_uuid) == faces_src_region_len); + found = (BLI_ghash_size(w_dst->faces_uuid) == faces_src_region_len); if (found) { break; } @@ -875,7 +875,7 @@ static BMFace **bm_mesh_region_match_pair( if (found) { GHashIterator gh_iter; - const unsigned int faces_result_len = (unsigned int)BLI_ghash_size(w_dst->faces_uuid); + const unsigned int faces_result_len = BLI_ghash_size(w_dst->faces_uuid); unsigned int i; faces_result = MEM_mallocN(sizeof(*faces_result) * (faces_result_len + 1), __func__); -- cgit v1.2.3 From 9b359c1592057ae9296b4f0a4b543b1b783a232c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 13 Apr 2015 14:35:16 +1000 Subject: Py API: default arg for location_3d_to_region_2d This function could return None for points behind the view, note this in the doc-string and add an optional fallback argument. --- release/scripts/modules/bpy_extras/view3d_utils.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/release/scripts/modules/bpy_extras/view3d_utils.py b/release/scripts/modules/bpy_extras/view3d_utils.py index ec4a395f1e1..b8f9bc730f7 100644 --- a/release/scripts/modules/bpy_extras/view3d_utils.py +++ b/release/scripts/modules/bpy_extras/view3d_utils.py @@ -160,7 +160,7 @@ def region_2d_to_location_3d(region, rv3d, coord, depth_location): )[0] -def location_3d_to_region_2d(region, rv3d, coord): +def location_3d_to_region_2d(region, rv3d, coord, default=None): """ Return the *region* relative 2d location of a 3d position. @@ -170,8 +170,10 @@ def location_3d_to_region_2d(region, rv3d, coord): :type rv3d: :class:`bpy.types.RegionView3D` :arg coord: 3d worldspace location. :type coord: 3d vector + :arg default: Return this value if ``coord`` + is behind the origin of a perspective view. :return: 2d location - :rtype: :class:`mathutils.Vector` + :rtype: :class:`mathutils.Vector` or ``default`` argument. """ from mathutils import Vector @@ -184,4 +186,4 @@ def location_3d_to_region_2d(region, rv3d, coord): height_half + height_half * (prj.y / prj.w), )) else: - return None + return default -- cgit v1.2.3 From 919de1e4c91d69938cfb8eed1deed26c867fcdcf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 13 Apr 2015 15:42:00 +1000 Subject: BMesh: diagram for dyntopo edge subdiv --- source/blender/blenkernel/intern/pbvh_bmesh.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 26d3a1e14ba..7daea181599 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -810,6 +810,32 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh, if (ni != node_index && i == 0) pbvh_bmesh_vert_ownership_transfer(bvh, &bvh->nodes[ni], v_new); + /** + * The 2 new faces created and assigned to ``f_new`` have their + * verts & edges shuffled around. + * + * - faces wind anticlockwise in this example. + * - original edge is (v1, v2) + * - oroginal face is (v1, v2, v3) + * + *
+		 *         + v3(v_opp)
+		 *        /|\
+		 *       / | \
+		 *      /  |  \
+		 *   e4/   |   \e3
+		 *    /    |e5  \
+		 *   /     |     \
+		 *  /  e1  |  e2  \
+		 * +-------+-------+
+		 * v1      v4(v_new) v2
+		 *  (first) (second)
+		 *
+		 * - f_new (first):  v_tri=(v1, v4, v3), e_tri=(e1, e5, e4)
+		 * - f_new (second): v_tri=(v4, v2, v3), e_tri=(e2, e3, e5)
+		 * 
+ */ + /* Create two new faces */ v_tri[0] = v1; v_tri[1] = v_new; -- cgit v1.2.3 From dd0cba00764eca60e29254c6836e980af57772ce Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 13 Apr 2015 15:43:57 +1000 Subject: error in last commit --- source/blender/blenkernel/intern/pbvh_bmesh.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 7daea181599..fb4ad70e985 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -815,25 +815,25 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh, * verts & edges shuffled around. * * - faces wind anticlockwise in this example. - * - original edge is (v1, v2) - * - oroginal face is (v1, v2, v3) + * - original edge is ``(v1, v2)`` + * - oroginal face is ``(v1, v2, v3)`` * *
 		 *         + v3(v_opp)
 		 *        /|\
 		 *       / | \
 		 *      /  |  \
-		 *   e4/   |   \e3
+		 *   e4/   |   \ e3
 		 *    /    |e5  \
 		 *   /     |     \
 		 *  /  e1  |  e2  \
 		 * +-------+-------+
 		 * v1      v4(v_new) v2
 		 *  (first) (second)
-		 *
-		 * - f_new (first):  v_tri=(v1, v4, v3), e_tri=(e1, e5, e4)
-		 * - f_new (second): v_tri=(v4, v2, v3), e_tri=(e2, e3, e5)
 		 * 
+ * + * - f_new (first): ``v_tri=(v1, v4, v3), e_tri=(e1, e5, e4)`` + * - f_new (second): ``v_tri=(v4, v2, v3), e_tri=(e2, e3, e5)`` */ /* Create two new faces */ -- cgit v1.2.3 From f684dfc43216a3e9286202bd07b05064bb37f9ee Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 13 Apr 2015 15:54:37 +1000 Subject: Fix T44364: Remove shape key crashes Blender --- source/blender/blenkernel/intern/DerivedMesh.c | 3 ++- source/blender/modifiers/intern/MOD_cloth.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 87a00c20d46..1ece9d82cc2 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1011,8 +1011,9 @@ static float (*get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *fr ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ob), clmd->sim_parms->shapekey_rest); - if (kb->data) + if (kb && kb->data) { return kb->data; + } } return NULL; diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index d76427cd6ee..392112e4b4a 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -98,7 +98,7 @@ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, if (derivedData == NULL && clmd->sim_parms->shapekey_rest) { KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ob), clmd->sim_parms->shapekey_rest); - if (kb->data != NULL) { + if (kb && kb->data != NULL) { float (*layerorco)[3]; if (!(layerorco = DM_get_vert_data_layer(dm, CD_CLOTH_ORCO))) { DM_add_vert_layer(dm, CD_CLOTH_ORCO, CD_CALLOC, NULL); -- cgit v1.2.3 From 4fb33d82e251e340d4ffee8efda62cfeb5c03135 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 13 Apr 2015 10:51:04 +0200 Subject: Fix T44361: array modifier "fit curve" mode not working properly 'tot_length / step_length' gives the number of 'segments', not the number of copies - we have to add 1 here. --- source/blender/modifiers/intern/MOD_array.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 409d862addb..8ebee0dc1b4 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -501,7 +501,7 @@ static DerivedMesh *arrayModifier_doArray( if (dist > eps) { /* this gives length = first copy start to last copy end * add a tiny offset for floating point rounding errors */ - count = (length + eps) / dist; + count = (length + eps) / dist + 1; } else { /* if the offset has no translation, just make one copy */ -- cgit v1.2.3 From 6fbf05f326911d10e6227837f8b5de1d86f950b2 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Mon, 13 Apr 2015 10:59:47 +0200 Subject: Make python gotchas more clear (regarding handling of stale data) --- doc/python_api/rst/info_gotcha.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/python_api/rst/info_gotcha.rst b/doc/python_api/rst/info_gotcha.rst index 35f9c1bda9f..aad23112b42 100644 --- a/doc/python_api/rst/info_gotcha.rst +++ b/doc/python_api/rst/info_gotcha.rst @@ -86,9 +86,15 @@ Consider the calculations that might go into working out the object's final tran To avoid expensive recalculations every time a property is modified, Blender defers making the actual calculations until they are needed. However, while the script runs you may want to access the updated values. +In this case you need to call :class:`bpy.types.Scene.update` after modifying values, for example: + +.. code-block:: python + + bpy.context.object.location = 1, 2, 3 + bpy.context.scene.update() -This can be done by calling :class:`bpy.types.Scene.update` after modifying values which recalculates all data that is tagged to be updated. +Now all dependent data (child objects, modifiers, drivers... etc) has been recalculated and is available to the script. Can I redraw during the script? ------------------------------- -- cgit v1.2.3 From 176ed5bfe280ef2151f93c0940d54498aaf00d71 Mon Sep 17 00:00:00 2001 From: Mai Lavelle Date: Mon, 13 Apr 2015 14:14:43 +0500 Subject: Fix hair random rotation limited to 180 degrees The issue was caused by phase being limited from 0 to 1, which gave only 0..M_PI distribution which is not good enough for good randomness. Now the phase is being randomized across full 0..2*M_PI range. --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/intern/particle.c | 2 +- source/blender/blenkernel/intern/particle_system.c | 2 +- source/blender/blenloader/intern/versioning_270.c | 8 ++++++++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 86576f9a11b..f5e7643085a 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 274 -#define BLENDER_SUBVERSION 4 +#define BLENDER_SUBVERSION 5 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 5 diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 6c354c59d7a..0e200c73918 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -4100,7 +4100,7 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa float q_phase[4]; float phasefac = psys->part->phasefac; if (psys->part->randphasefac != 0.0f) - phasefac += psys->part->randphasefac * psys_frand(psys, (pa - psys->particles) + 20); + phasefac += psys->part->randphasefac * psys_frand(psys, (pa - psys->particles) + 20) * 2.0f; axis_angle_to_quat(q_phase, vec, phasefac * (float)M_PI); mul_qt_v3(q_phase, side); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 5a263e24fc4..0439e56c294 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -928,7 +928,7 @@ void psys_get_birth_coords(ParticleSimulationData *sim, ParticleData *pa, Partic /* rotation phase */ phasefac = part->phasefac; if (part->randphasefac != 0.0f) - phasefac += part->randphasefac * psys_frand(psys, p + 20); + phasefac += part->randphasefac * psys_frand(psys, p + 20) * 2.0f; axis_angle_to_quat( q_phase,x_vec, phasefac*(float)M_PI); /* combine base rotation & phase */ diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 1b91d3d869e..49e81b1cfff 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -799,4 +799,12 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } + + if (!MAIN_VERSION_ATLEAST(main, 274, 5)) { + /* Particle random phase range doubled. */ + ParticleSettings *part; + for (part = main->particle.first; part; part = part->id.next) { + part->randphasefac *= 0.5f; + } + } } -- cgit v1.2.3 From 890e533c7695927212a6164c0ca86ff7a314bf5f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 13 Apr 2015 19:27:10 +1000 Subject: Fix adding to paint-curves from the first point - add_index now works when selecting the first point. - sliding now selects the correct handle. --- source/blender/blenkernel/BKE_paint.h | 1 + source/blender/blenkernel/intern/paint.c | 5 +++ source/blender/editors/sculpt_paint/paint_curve.c | 44 ++++++++++++++++++----- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 4d713449b17..53c2a82fb8e 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -120,6 +120,7 @@ void BKE_paint_brush_set(struct Paint *paint, struct Brush *br); struct Palette *BKE_paint_palette(struct Paint *paint); void BKE_paint_palette_set(struct Paint *p, struct Palette *palette); void BKE_paint_curve_set(struct Brush *br, struct PaintCurve *pc); +void BKE_paint_curve_clamp_endpoint_add_index(struct PaintCurve *pc, const int add_index); void BKE_paint_data_warning(struct ReportList *reports, bool uvs, bool mat, bool tex, bool stencil); bool BKE_paint_proj_mesh_data_check(struct Scene *scene, struct Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil); diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index a5b608703d1..b45e6b81ec8 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -313,6 +313,11 @@ void BKE_paint_curve_set(Brush *br, PaintCurve *pc) } } +void BKE_paint_curve_clamp_endpoint_add_index(PaintCurve *pc, const int add_index) +{ + pc->add_index = (add_index || pc->tot_points == 1) ? (add_index + 1) : 0; +} + /* remove colour from palette. Must be certain color is inside the palette! */ void BKE_palette_color_remove(Palette *palette, PaletteColor *color) { diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c index 439c2a639bd..8c754d7adf3 100644 --- a/source/blender/editors/sculpt_paint/paint_curve.c +++ b/source/blender/editors/sculpt_paint/paint_curve.c @@ -222,6 +222,28 @@ static int paintcurve_point_co_index(char sel) return i; } +static char paintcurve_point_side_index(const BezTriple *bezt, const bool is_first, const char fallback) +{ + /* when matching, guess based on endpoint side */ + if (BEZSELECTED(bezt)) { + if ((bezt->f1 & SELECT) == (bezt->f3 & SELECT)) { + return is_first ? SEL_F1 : SEL_F3; + } + else if (bezt->f1 & SELECT) { + return SEL_F1; + } + else if (bezt->f3 & SELECT) { + return SEL_F3; + } + else { + return fallback; + } + } + else { + return 0; + } +} + /******************* Operators *********************************/ static int paintcurve_new_exec(bContext *C, wmOperator *UNUSED(op)) @@ -295,10 +317,17 @@ static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2]) for (i = 0; i < pc->tot_points; i++) { pcp[i].bez.f1 = pcp[i].bez.f2 = pcp[i].bez.f3 = 0; } - pcp[add_index].bez.f3 = SELECT; - pcp[add_index].bez.h2 = HD_ALIGN; - pc->add_index = add_index + 1; + BKE_paint_curve_clamp_endpoint_add_index(pc, add_index); + + if (pc->add_index != 0) { + pcp[add_index].bez.f3 = SELECT; + pcp[add_index].bez.h2 = HD_ALIGN; + } + else { + pcp[add_index].bez.f1 = SELECT; + pcp[add_index].bez.h1 = HD_ALIGN; + } WM_paint_cursor_tag_redraw(window, ar); } @@ -384,7 +413,7 @@ static int paintcurve_delete_point_exec(bContext *C, wmOperator *op) points_new[j] = pc->points[i]; if ((i + 1) == pc->add_index) { - pc->add_index = j + 1; + BKE_paint_curve_clamp_endpoint_add_index(pc, j); } j++; } @@ -469,7 +498,7 @@ static bool paintcurve_point_select(bContext *C, wmOperator *op, const int loc[2 pcp = paintcurve_point_get_closest(pc, loc_fl, false, PAINT_CURVE_SELECT_THRESHOLD, &selflag); if (pcp) { - pc->add_index = (pcp - pc->points) + 1; + BKE_paint_curve_clamp_endpoint_add_index(pc, pcp - pc->points); if (selflag == SEL_F2) { if (extend) @@ -599,9 +628,8 @@ static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *e pcp = NULL; /* just find first selected point */ for (i = 0; i < pc->tot_points; i++) { - if (pc->points[i].bez.f1 || pc->points[i].bez.f2 || pc->points[i].bez.f3) { + if ((select = paintcurve_point_side_index(&pc->points[i].bez, i == 0, SEL_F3))) { pcp = &pc->points[i]; - select = SEL_F3; break; } } @@ -631,7 +659,7 @@ static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *e /* only select the active point */ PAINT_CURVE_POINT_SELECT(pcp, psd->select); - pc->add_index = (pcp - pc->points) + 1; + BKE_paint_curve_clamp_endpoint_add_index(pc, pcp - pc->points); WM_event_add_modal_handler(C, op); WM_paint_cursor_tag_redraw(window, ar); -- cgit v1.2.3 From 97ae0f22cd5709e4a1af532d594012426c2b364e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 13 Apr 2015 14:37:12 +0500 Subject: Depsgraph debug: Remove hardcoded array of BLENDER_MAX_THREADS elements Allocate statistics array dynamically, so increasing max number of threads does not increase sloppyness of the memory usage. For the further cleanups: we can try alloca-ing this array, but it's also not really safe because we can have quite huge number of threads in the future. Plus statistics will allocate memory for each individual entry, so using alloca is not going to give anything beneficial here. --- source/blender/blenkernel/intern/scene.c | 15 ++++++++++----- source/blender/blenlib/BLI_task.h | 3 +++ source/blender/blenlib/intern/task.c | 10 ++++++++++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 443671f5a61..60b05cea21b 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1373,13 +1373,13 @@ typedef struct ThreadedObjectUpdateState { Scene *scene_parent; double base_time; - /* Execution statistics */ - ListBase statistics[BLENDER_MAX_THREADS]; - bool has_updated_objects; - #ifdef MBALL_SINGLETHREAD_HACK bool has_mballs; #endif + + /* Execution statistics */ + bool has_updated_objects; + ListBase *statistics; } ThreadedObjectUpdateState; static void scene_update_object_add_task(void *node, void *user_data); @@ -1448,6 +1448,8 @@ static void scene_update_object_func(TaskPool *pool, void *taskdata, int threadi if (add_to_stats) { StatisicsEntry *entry; + BLI_assert(threadid < BLI_pool_get_num_threads(pool)); + entry = MEM_mallocN(sizeof(StatisicsEntry), "update thread statistics"); entry->object = object; entry->start_time = start_time; @@ -1576,7 +1578,9 @@ static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene /* Those are only needed when blender is run with --debug argument. */ if (G.debug & G_DEBUG_DEPSGRAPH) { - memset(state.statistics, 0, sizeof(state.statistics)); + const int tot_thread = BLI_task_scheduler_num_threads(task_scheduler); + state.statistics = MEM_callocN(tot_thread * sizeof(*state.statistics), + "scene update objects stats"); state.has_updated_objects = false; state.base_time = PIL_check_seconds_timer(); } @@ -1593,6 +1597,7 @@ static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene if (G.debug & G_DEBUG_DEPSGRAPH) { print_threads_statistics(&state); + MEM_freeN(state.statistics); } /* We do single thread pass to update all the objects which are in cyclic dependency. diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h index 2eaec024ce2..780b0bfbbd6 100644 --- a/source/blender/blenlib/BLI_task.h +++ b/source/blender/blenlib/BLI_task.h @@ -88,6 +88,9 @@ void BLI_task_pool_cancel(TaskPool *pool); /* stop all worker threads */ void BLI_task_pool_stop(TaskPool *pool); +/* get number of threads allowed to be used by this pool */ +int BLI_pool_get_num_threads(TaskPool *pool); + /* set number of threads allowed to be used by this pool */ void BLI_pool_set_num_threads(TaskPool *pool, int num_threads); diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c index d187a8d1968..f442a6219a5 100644 --- a/source/blender/blenlib/intern/task.c +++ b/source/blender/blenlib/intern/task.c @@ -417,6 +417,16 @@ void BLI_task_pool_work_and_wait(TaskPool *pool) BLI_mutex_unlock(&pool->num_mutex); } +int BLI_pool_get_num_threads(TaskPool *pool) +{ + if (pool->num_threads != 0) { + return pool->num_threads; + } + else { + return BLI_task_scheduler_num_threads(pool->scheduler); + } +} + void BLI_pool_set_num_threads(TaskPool *pool, int num_threads) { /* NOTE: Don't try to modify threads while tasks are running! */ -- cgit v1.2.3 From 8a97d462961d3f4be96303ab5eb59c0e5a00ba7c Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 13 Apr 2015 12:21:21 +0200 Subject: Windows: Only print backtrace on debug builds, since on release builds there is only some useless output from a python library and fftw. --- source/blender/blenlib/intern/system.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c index b6b0f14a4e2..18703a83621 100644 --- a/source/blender/blenlib/intern/system.c +++ b/source/blender/blenlib/intern/system.c @@ -99,8 +99,7 @@ void BLI_system_backtrace(FILE *fp) /* Windows */ #elif defined(_MSC_VER) - (void)fp; -#if defined WIN32 +#ifndef NDEBUG #define MAXSYMBOL 256 #define SIZE 100 unsigned short i; @@ -127,11 +126,12 @@ void BLI_system_backtrace(FILE *fp) MEM_freeN(symbolinfo); #undef MAXSYMBOL #undef SIZE -#endif - +#else + fprintf(fp, "Not supported on release builds\n"); +#endif /* NDEBUG */ +#else /* _MSC_VER */ /* ------------------ */ /* non msvc/osx/linux */ -#else (void)fp; #endif -- cgit v1.2.3 From efe90384b79f0859a56bb4bbc668d7be0707ac6a Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 13 Apr 2015 12:28:12 +0200 Subject: Be a bit more specific in the message. --- source/blender/blenlib/intern/system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c index 18703a83621..5d1bdd6d978 100644 --- a/source/blender/blenlib/intern/system.c +++ b/source/blender/blenlib/intern/system.c @@ -127,7 +127,7 @@ void BLI_system_backtrace(FILE *fp) #undef MAXSYMBOL #undef SIZE #else - fprintf(fp, "Not supported on release builds\n"); + fprintf(fp, "Crash backtrace not supported on release builds\n"); #endif /* NDEBUG */ #else /* _MSC_VER */ /* ------------------ */ -- cgit v1.2.3 From fdc653e8ce77a188138dc707207139c3d1e6b166 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 13 Apr 2015 14:45:56 +0500 Subject: Nodes: Remove hardcoded BLENDER_MAX_THREADS number of threads Use actual available number of threads now, which will make it easier to increase max number of threads, without having some sloppy memory usage and without doing some redundant checks on thread data which was never used. --- source/blender/nodes/intern/node_exec.c | 3 ++- source/blender/nodes/intern/node_exec.h | 1 + source/blender/nodes/shader/node_shader_tree.c | 5 +++-- source/blender/nodes/texture/node_texture_tree.c | 7 ++++--- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c index 2347564c696..07826686634 100644 --- a/source/blender/nodes/intern/node_exec.c +++ b/source/blender/nodes/intern/node_exec.c @@ -29,6 +29,7 @@ * \ingroup nodes */ +#include /* for abort() */ #include "DNA_node_types.h" @@ -262,7 +263,7 @@ bNodeThreadStack *ntreeGetThreadStack(bNodeTreeExec *exec, int thread) { ListBase *lb = &exec->threadstack[thread]; bNodeThreadStack *nts; - + BLI_assert(thread < exec->tot_thread); for (nts = lb->first; nts; nts = nts->next) { if (!nts->used) { nts->used = true; diff --git a/source/blender/nodes/intern/node_exec.h b/source/blender/nodes/intern/node_exec.h index a0023d02295..8bb8c77a88c 100644 --- a/source/blender/nodes/intern/node_exec.h +++ b/source/blender/nodes/intern/node_exec.h @@ -65,6 +65,7 @@ typedef struct bNodeTreeExec { int stacksize; struct bNodeStack *stack; /* socket data stack */ /* only used by material and texture trees to keep one stack for each thread */ + int tot_thread; ListBase *threadstack; /* one instance of the stack for each thread */ } bNodeTreeExec; diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index f18ee1d649f..57cc1eab929 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -234,7 +234,8 @@ bNodeTreeExec *ntreeShaderBeginExecTree_internal(bNodeExecContext *context, bNod exec = ntree_exec_begin(context, ntree, parent_key); /* allocate the thread stack listbase array */ - exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array"); + exec->tot_thread = BLI_system_thread_count(); + exec->threadstack = MEM_callocN(exec->tot_thread * sizeof(ListBase), "thread stack array"); for (node = exec->nodetree->nodes.first; node; node = node->next) node->need_exec = 1; @@ -271,7 +272,7 @@ void ntreeShaderEndExecTree_internal(bNodeTreeExec *exec) int a; if (exec->threadstack) { - for (a = 0; a < BLENDER_MAX_THREADS; a++) { + for (a = 0; a < exec->tot_thread; a++) { for (nts = exec->threadstack[a].first; nts; nts = nts->next) if (nts->stack) MEM_freeN(nts->stack); BLI_freelistN(&exec->threadstack[a]); diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index 79923c5f7d5..93ce469c150 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -232,7 +232,8 @@ bNodeTreeExec *ntreeTexBeginExecTree_internal(bNodeExecContext *context, bNodeTr exec = ntree_exec_begin(context, ntree, parent_key); /* allocate the thread stack listbase array */ - exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array"); + exec->tot_thread = BLI_system_thread_count(); + exec->threadstack = MEM_callocN(exec->tot_thread * sizeof(ListBase), "thread stack array"); for (node = exec->nodetree->nodes.first; node; node = node->next) node->need_exec = 1; @@ -270,7 +271,7 @@ static void tex_free_delegates(bNodeTreeExec *exec) bNodeStack *ns; int th, a; - for (th = 0; th < BLENDER_MAX_THREADS; th++) + for (th = 0; th < exec->tot_thread; th++) for (nts = exec->threadstack[th].first; nts; nts = nts->next) for (ns = nts->stack, a = 0; a < exec->stacksize; a++, ns++) if (ns->data && !ns->is_copy) @@ -285,7 +286,7 @@ void ntreeTexEndExecTree_internal(bNodeTreeExec *exec) if (exec->threadstack) { tex_free_delegates(exec); - for (a = 0; a < BLENDER_MAX_THREADS; a++) { + for (a = 0; a < exec->tot_thread; a++) { for (nts = exec->threadstack[a].first; nts; nts = nts->next) if (nts->stack) MEM_freeN(nts->stack); BLI_freelistN(&exec->threadstack[a]); -- cgit v1.2.3 From 8c616e86b5dccead43e78dc2f8a86978a6aec4e2 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 13 Apr 2015 12:43:56 +0200 Subject: Calculate auto normalization maximum from keyframes within range if preview is on --- source/blender/editors/animation/anim_draw.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index c0ac42f3a5d..ed294d7208f 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -37,6 +37,7 @@ #include "BLI_math.h" #include "BLI_timecode.h" +#include "BLI_utildefines.h" #include "BKE_context.h" #include "BKE_global.h" @@ -266,7 +267,7 @@ short ANIM_get_normalization_flags(bAnimContext *ac) return 0; } -static float normalzation_factor_get(FCurve *fcu, short flag) +static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag) { float factor = 1.0f; @@ -292,10 +293,21 @@ static float normalzation_factor_get(FCurve *fcu, short flag) return 1.0f; } - for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { - max_coord = max_ff(max_coord, fabsf(bezt->vec[0][1])); - max_coord = max_ff(max_coord, fabsf(bezt->vec[1][1])); - max_coord = max_ff(max_coord, fabsf(bezt->vec[2][1])); + if (PRVRANGEON) { + for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { + if (IN_RANGE_INCL(bezt->vec[1][0], scene->r.psfra, scene->r.pefra)) { + max_coord = max_ff(max_coord, fabsf(bezt->vec[0][1])); + max_coord = max_ff(max_coord, fabsf(bezt->vec[1][1])); + max_coord = max_ff(max_coord, fabsf(bezt->vec[2][1])); + } + } + } + else { + for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { + max_coord = max_ff(max_coord, fabsf(bezt->vec[0][1])); + max_coord = max_ff(max_coord, fabsf(bezt->vec[1][1])); + max_coord = max_ff(max_coord, fabsf(bezt->vec[2][1])); + } } if (max_coord > FLT_EPSILON) { @@ -310,7 +322,7 @@ static float normalzation_factor_get(FCurve *fcu, short flag) float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag) { if (flag & ANIM_UNITCONV_NORMALIZE) { - return normalzation_factor_get(fcu, flag); + return normalization_factor_get(scene, fcu, flag); } /* sanity checks */ -- cgit v1.2.3 From a50955ee0f6c45c613ae9d1e66b1d3cd48e6ff2c Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Mon, 13 Apr 2015 13:22:40 +0200 Subject: Minor edits of python class documentation (regarding ID tagging) --- source/blender/makesrna/intern/rna_ID.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 8632467281a..34ef4cceebd 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -566,7 +566,7 @@ static void rna_def_ID(BlenderRNA *brna) prop = RNA_def_property(srna, "tag", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LIB_DOIT); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); - RNA_def_property_ui_text(prop, "Tag", "Tools can use this to tag data (initial state is undefined)"); + RNA_def_property_ui_text(prop, "Tag", "Tools can use this to tag data for their own purposes (initial state is undefined)."); prop = RNA_def_property(srna, "is_updated", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LIB_ID_RECALC); @@ -608,7 +608,7 @@ static void rna_def_ID(BlenderRNA *brna) func = RNA_def_function(srna, "update_tag", "rna_ID_update_tag"); RNA_def_function_flag(func, FUNC_USE_REPORTS); - RNA_def_function_ui_description(func, "Tag the ID to update its display data"); + RNA_def_function_ui_description(func, "Tag the ID to update its display data, e.g. when calling :class:`bpy.types.Scene.update`"); RNA_def_enum_flag(func, "refresh", update_flag_items, 0, "", "Type of updates to perform"); } -- cgit v1.2.3 From d2da8aa27aad3e97365e6cae80d3c516073529c9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 13 Apr 2015 20:40:52 +1000 Subject: BMesh: resolve skinny face artifacts /w dyntopo Dyntopo can currently create skinny faces, especially when the faces are much larger then the resolution. To get the old behavior, set debug value to 1234 --- source/blender/blenkernel/intern/pbvh_bmesh.c | 75 +++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index fb4ad70e985..f7edd34c70a 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -41,6 +41,12 @@ #include +/* Avoid skinny faces */ +#define USE_EDGEQUEUE_EVEN_SUBDIV +#ifdef USE_EDGEQUEUE_EVEN_SUBDIV +# include "BKE_global.h" +#endif + // #define USE_VERIFY #ifdef USE_VERIFY @@ -570,6 +576,9 @@ typedef struct { const float *center; float radius_squared; float limit_len_squared; +#ifdef USE_EDGEQUEUE_EVEN_SUBDIV + float limit_len; +#endif } EdgeQueue; typedef struct { @@ -633,6 +642,57 @@ static void long_edge_queue_edge_add(EdgeQueueContext *eq_ctx, edge_queue_insert(eq_ctx, e, -len_sq); } +#ifdef USE_EDGEQUEUE_EVEN_SUBDIV +static void long_edge_queue_edge_add_recursive( + EdgeQueueContext *eq_ctx, + BMLoop *l_edge, BMLoop *l_end, + const float len_sq, float limit_len) +{ + BLI_assert(len_sq > SQUARE(limit_len)); + edge_queue_insert(eq_ctx, l_edge->e, -len_sq); + + /* temp support previous behavior! */ + if (UNLIKELY(G.debug_value == 1234)) { + return; + } + + if ((l_edge->radial_next != l_edge)) { + /* how much longer we need to be to consider for subdividing + * (avoids subdividing faces which are only *slightly* skinny) */ +#define EVEN_EDGELEN_THRESHOLD 1.2f + /* how much the limit increases per recursion + * (avoids performing subdvisions too far away) */ +#define EVEN_GENERATION_SCALE 1.6f + + const float len_sq_cmp = len_sq * EVEN_EDGELEN_THRESHOLD; + float limit_len_sq; + BMLoop *l_iter; + + limit_len *= EVEN_GENERATION_SCALE; + limit_len_sq = SQUARE(limit_len); + + l_iter = l_edge; + do { + float len_sq_other; + BMLoop *l_adjacent[2] = {l_iter->next, l_iter->prev}; + int i; + for (i = 0; i < ARRAY_SIZE(l_adjacent); i++) { + len_sq_other = BM_edge_calc_length_squared(l_adjacent[i]->e); + if (len_sq_other > max_ff(len_sq_cmp, limit_len_sq)) { +// edge_queue_insert(eq_ctx, l_adjacent[i]->e, -len_sq_other); + long_edge_queue_edge_add_recursive( + eq_ctx, l_adjacent[i]->radial_next, l_adjacent[i], + len_sq_other, limit_len); + } + } + } while ((l_iter = l_iter->radial_next) != l_end); + +#undef EVEN_EDGELEN_THRESHOLD +#undef EVEN_GENERATION_SCALE + } +} +#endif /* USE_EDGEQUEUE_EVEN_SUBDIV */ + static void short_edge_queue_edge_add(EdgeQueueContext *eq_ctx, BMEdge *e) { @@ -651,7 +711,16 @@ static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, /* Check each edge of the face */ l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { +#ifdef USE_EDGEQUEUE_EVEN_SUBDIV + const float len_sq = BM_edge_calc_length_squared(l_iter->e); + if (len_sq > eq_ctx->q->limit_len_squared) { + long_edge_queue_edge_add_recursive( + eq_ctx, l_iter->radial_next, l_iter, + len_sq, eq_ctx->q->limit_len_squared); + } +#else long_edge_queue_edge_add(eq_ctx, l_iter->e); +#endif } while ((l_iter = l_iter->next) != l_first); } } @@ -690,6 +759,9 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx, eq_ctx->q->center = center; eq_ctx->q->radius_squared = radius * radius; eq_ctx->q->limit_len_squared = bvh->bm_max_edge_len * bvh->bm_max_edge_len; +#ifdef USE_EDGEQUEUE_EVEN_SUBDIV + eq_ctx->q->limit_len = bvh->bm_max_edge_len; +#endif for (n = 0; n < bvh->totnode; n++) { PBVHNode *node = &bvh->nodes[n]; @@ -730,6 +802,9 @@ static void short_edge_queue_create(EdgeQueueContext *eq_ctx, eq_ctx->q->center = center; eq_ctx->q->radius_squared = radius * radius; eq_ctx->q->limit_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len; +#ifdef USE_EDGEQUEUE_EVEN_SUBDIV + eq_ctx->q->limit_len = bvh->bm_min_edge_len; +#endif for (n = 0; n < bvh->totnode; n++) { PBVHNode *node = &bvh->nodes[n]; -- cgit v1.2.3 From d1f9fcaabcc64f224467523bb1258c59ebfb8209 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 13 Apr 2015 22:08:51 +1000 Subject: Cleanup: style --- intern/cycles/render/camera.cpp | 2 +- intern/ghost/GHOST_C-api.h | 10 +++++----- source/blender/blenfont/intern/blf_thumbs.c | 2 +- source/blender/editors/mesh/editmesh_utils.c | 3 ++- source/blender/makesrna/intern/rna_ID.c | 8 ++++++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 9e3a17bf792..65953a41be8 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -400,7 +400,7 @@ BoundBox Camera::viewplane_bounds_get() bounds.grow(transform_raster_to_world((float)width, (float)height)); bounds.grow(transform_raster_to_world((float)width, 0.0f)); if(type == CAMERA_PERSPECTIVE) { - /* Center point has the most distancei in local Z axis, + /* Center point has the most distance in local Z axis, * use it to construct bounding box/ */ bounds.grow(transform_raster_to_world(0.5f*width, 0.5f*height)); diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 5f01a13b64e..8a80a51a77b 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -660,7 +660,7 @@ extern GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle, /** * Swaps front and back buffers of a window. * \param windowhandle The handle to the window - * \return An intean success indicator. + * \return A success indicator. */ extern GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle); @@ -688,7 +688,7 @@ extern GHOST_TUns16 GHOST_GetNumOfAASamples(GHOST_WindowHandle windowhandle); /** * Activates the drawing context of this window. * \param windowhandle The handle to the window - * \return An intean success indicator. + * \return A success indicator. */ extern GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle); @@ -752,7 +752,7 @@ extern void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle, * Returns whether this rectangle is empty. * Empty rectangles are rectangles that have width==0 and/or height==0. * \param rectanglehandle The handle to the rectangle - * \return intean value (true == empty rectangle) + * \return Success value (true == empty rectangle) */ extern GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehandle); @@ -760,7 +760,7 @@ extern GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehand * Returns whether this rectangle is valid. * Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. Thus, empty rectangles are valid. * \param rectanglehandle The handle to the rectangle - * \return intean value (true == valid rectangle) + * \return Success value (true == valid rectangle) */ extern GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehandle); @@ -798,7 +798,7 @@ extern void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle, * \param rectanglehandle The handle to the rectangle * \param x x-coordinate of point to test. * \param y y-coordinate of point to test. - * \return intean value (true if point is inside). + * \return Success value (true if point is inside). */ extern GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle, GHOST_TInt32 x, diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c index 3c400d0b8e4..7c0a43e09ee 100644 --- a/source/blender/blenfont/intern/blf_thumbs.c +++ b/source/blender/blenfont/intern/blf_thumbs.c @@ -66,7 +66,7 @@ void BLF_thumb_preview( /* shrink 1/th each line */ int font_shrink = 4; - FontBLF* font; + FontBLF *font; int i; /* Create a new blender font obj and fill it with default values */ diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 1875689415a..4706f0467fd 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -865,7 +865,8 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo sub_v2_v2v2(uvdiff, uv2, uv); if (fabsf(uvdiff[0]) < STD_UV_CONNECT_LIMIT && fabsf(uvdiff[1]) < STD_UV_CONNECT_LIMIT && - winding[BM_elem_index_get(iterv->l->f)] == winding[BM_elem_index_get(v->l->f)]) { + winding[BM_elem_index_get(iterv->l->f)] == winding[BM_elem_index_get(v->l->f)]) + { if (lastv) lastv->next = next; else vlist = next; iterv->next = newvlist; diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 34ef4cceebd..db25786c599 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -566,7 +566,9 @@ static void rna_def_ID(BlenderRNA *brna) prop = RNA_def_property(srna, "tag", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LIB_DOIT); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); - RNA_def_property_ui_text(prop, "Tag", "Tools can use this to tag data for their own purposes (initial state is undefined)."); + RNA_def_property_ui_text(prop, "Tag", + "Tools can use this to tag data for their own purposes " + "(initial state is undefined)"); prop = RNA_def_property(srna, "is_updated", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LIB_ID_RECALC); @@ -608,7 +610,9 @@ static void rna_def_ID(BlenderRNA *brna) func = RNA_def_function(srna, "update_tag", "rna_ID_update_tag"); RNA_def_function_flag(func, FUNC_USE_REPORTS); - RNA_def_function_ui_description(func, "Tag the ID to update its display data, e.g. when calling :class:`bpy.types.Scene.update`"); + RNA_def_function_ui_description(func, + "Tag the ID to update its display data, " + "e.g. when calling :class:`bpy.types.Scene.update`"); RNA_def_enum_flag(func, "refresh", update_flag_items, 0, "", "Type of updates to perform"); } -- cgit v1.2.3 From 364b6b29ff2ea19a31fdfc8e08b75ce0d46df40b Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 13 Apr 2015 14:30:17 +0200 Subject: New operator for action and graph editor that centers around current scene frame, bound to numberpad zero. --- release/scripts/startup/bl_ui/space_dopesheet.py | 1 + release/scripts/startup/bl_ui/space_graph.py | 1 + source/blender/editors/include/UI_view2d.h | 2 +- source/blender/editors/interface/view2d_ops.c | 15 +++++++++++++ source/blender/editors/space_action/action_edit.c | 25 +++++++++++++++++++++- .../blender/editors/space_action/action_intern.h | 1 + source/blender/editors/space_action/action_ops.c | 5 ++++- source/blender/editors/space_graph/graph_edit.c | 23 ++++++++++++++++++++ source/blender/editors/space_graph/graph_intern.h | 1 + source/blender/editors/space_graph/graph_ops.c | 4 +++- 10 files changed, 74 insertions(+), 4 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index e9818f612c2..13c37182ae4 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -203,6 +203,7 @@ class DOPESHEET_MT_view(Menu): layout.separator() layout.operator("action.view_all") layout.operator("action.view_selected") + layout.operator("action.view_frame") layout.separator() layout.operator("screen.area_dupli") diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index 4503a0f4c68..27928ae3be1 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -125,6 +125,7 @@ class GRAPH_MT_view(Menu): layout.separator() layout.operator("graph.view_all") layout.operator("graph.view_selected") + layout.operator("graph.view_frame") layout.separator() layout.operator("screen.area_dupli") diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 4d7446a7a81..430093b641b 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -233,7 +233,7 @@ void ED_keymap_view2d(struct wmKeyConfig *keyconf); void UI_view2d_smooth_view(struct bContext *C, struct ARegion *ar, const struct rctf *cur, const int smooth_viewtx); - +void UI_view2d_center_frame(struct bContext *C, int smooth_viewtx); #define UI_MARKER_MARGIN_Y (42 * UI_DPI_FAC) #endif /* __UI_VIEW2D_H__ */ diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 88140d897ae..5730c967880 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -1462,6 +1462,21 @@ void UI_view2d_smooth_view(bContext *C, ARegion *ar, } } +void UI_view2d_center_frame(struct bContext *C, int smooth_viewtx) +{ + ARegion *ar = CTX_wm_region(C); + Scene *scene = CTX_data_scene(C); + float w = BLI_rctf_size_x(&ar->v2d.cur); + rctf newrct; + + newrct.xmax = scene->r.cfra + (w / 2); + newrct.xmin = scene->r.cfra - (w / 2); + newrct.ymax = ar->v2d.cur.ymax; + newrct.ymin = ar->v2d.cur.ymin; + + UI_view2d_smooth_view(C, ar, &newrct, smooth_viewtx); +} + /* only meant for timer usage */ static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 4b8ddacb418..d83137d4cb0 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -425,7 +425,15 @@ static int actkeys_viewsel_exec(bContext *C, wmOperator *UNUSED(op)) /* only selected */ return actkeys_viewall(C, true); } - + +static int actkeys_view_frame_exec(bContext *C, wmOperator *op) +{ + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + UI_view2d_center_frame(C, smooth_viewtx); + + return OPERATOR_FINISHED; +} + void ACTION_OT_view_all(wmOperatorType *ot) { /* identifiers */ @@ -456,6 +464,21 @@ void ACTION_OT_view_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +void ACTION_OT_view_frame(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "View Frame"; + ot->idname = "ACTION_OT_view_frame"; + ot->description = "Reset viewable area to show range around current frame"; + + /* api callbacks */ + ot->exec = actkeys_view_frame_exec; + ot->poll = ED_operator_action_active; /* XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier... */ + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + /* ************************************************************************** */ /* GENERAL STUFF */ diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index 9f9b15c3c26..17f1f404225 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -77,6 +77,7 @@ enum eActKeys_ColumnSelect_Mode { void ACTION_OT_previewrange_set(struct wmOperatorType *ot); void ACTION_OT_view_all(struct wmOperatorType *ot); void ACTION_OT_view_selected(struct wmOperatorType *ot); +void ACTION_OT_view_frame(struct wmOperatorType *ot); void ACTION_OT_copy(struct wmOperatorType *ot); void ACTION_OT_paste(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 47a120007a5..59b147c6f6c 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -91,7 +91,8 @@ void action_operatortypes(void) WM_operatortype_append(ACTION_OT_previewrange_set); WM_operatortype_append(ACTION_OT_view_all); WM_operatortype_append(ACTION_OT_view_selected); - + WM_operatortype_append(ACTION_OT_view_frame); + WM_operatortype_append(ACTION_OT_markers_make_local); } @@ -228,6 +229,8 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) WM_keymap_add_item(keymap, "ACTION_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ACTION_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ACTION_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "ACTION_OT_view_frame", PAD0, KM_PRESS, 0, 0); + /* animation module */ /* channels list diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index a26bfddf65a..0dba9ccfbae 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -256,6 +256,14 @@ static int graphkeys_view_selected_exec(bContext *C, wmOperator *op) return graphkeys_viewall(C, true, include_handles, smooth_viewtx); } +static int graphkeys_view_frame_exec(bContext *C, wmOperator *op) +{ + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + UI_view2d_center_frame(C, smooth_viewtx); + return OPERATOR_FINISHED; +} + + void GRAPH_OT_view_all(wmOperatorType *ot) { /* identifiers */ @@ -294,6 +302,21 @@ void GRAPH_OT_view_selected(wmOperatorType *ot) "Include handles of keyframes when calculating extents"); } +void GRAPH_OT_view_frame(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "View Frame"; + ot->idname = "GRAPH_OT_view_frame"; + ot->description = "Reset viewable area to show range around current frame"; + + /* api callbacks */ + ot->exec = graphkeys_view_frame_exec; + ot->poll = ED_operator_graphedit_active; /* XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier... */ + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + /* ******************** Create Ghost-Curves Operator *********************** */ /* This operator samples the data of the selected F-Curves to F-Points, storing them * as 'ghost curves' in the active Graph Editor diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index e2fab188fc8..a478a86a5e2 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -91,6 +91,7 @@ void get_graph_keyframe_extents(struct bAnimContext *ac, float *xmin, float *xma void GRAPH_OT_previewrange_set(struct wmOperatorType *ot); void GRAPH_OT_view_all(struct wmOperatorType *ot); void GRAPH_OT_view_selected(struct wmOperatorType *ot); +void GRAPH_OT_view_frame(struct wmOperatorType *ot); void GRAPH_OT_click_insert(struct wmOperatorType *ot); void GRAPH_OT_keyframe_insert(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 5c3fdce4282..3d1fa2cc008 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -380,6 +380,7 @@ void graphedit_operatortypes(void) WM_operatortype_append(GRAPH_OT_view_all); WM_operatortype_append(GRAPH_OT_view_selected); WM_operatortype_append(GRAPH_OT_properties); + WM_operatortype_append(GRAPH_OT_view_frame); WM_operatortype_append(GRAPH_OT_ghost_curves_create); WM_operatortype_append(GRAPH_OT_ghost_curves_clear); @@ -594,7 +595,8 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) WM_keymap_add_item(keymap, "GRAPH_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "GRAPH_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "GRAPH_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); - + WM_keymap_add_item(keymap, "GRAPH_OT_view_frame", PAD0, KM_PRESS, 0, 0); + /* F-Modifiers */ kmi = WM_keymap_add_item(keymap, "GRAPH_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "only_active", false); -- cgit v1.2.3 From 41350a91b52fa391bdd9e37b1c7b171b3a6b9021 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 13 Apr 2015 22:39:27 +1000 Subject: Workaround T44351: Scopes make editmesh lag Scopes are very heavy to calculate and editmesh uv's can cause the image view to redraw. Best just disable scopes in this case. --- release/scripts/startup/bl_ui/space_image.py | 2 +- source/blender/editors/space_image/image_edit.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index a1101bb3efb..9a1b9dbc74f 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -1060,7 +1060,7 @@ class ImageScopesPanel: if sima.mode in {'PAINT'}: return False ob = context.active_object - if ob and ob.mode in {'TEXTURE_PAINT'}: + if ob and ob.mode in {'TEXTURE_PAINT', 'EDIT'}: return False return True diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 8e2c6b97a5b..19fa068a693 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -299,7 +299,7 @@ void ED_space_image_scopes_update(const struct bContext *C, struct SpaceImage *s /* scope update can be expensive, don't update during paint modes */ if (sima->mode == SI_MODE_PAINT) return; - if (ob && ((ob->mode & OB_MODE_TEXTURE_PAINT) != 0)) + if (ob && ((ob->mode & (OB_MODE_TEXTURE_PAINT | OB_MODE_EDIT)) != 0)) return; scopes_update(&sima->scopes, ibuf, use_view_settings ? &scene->view_settings : NULL, &scene->display_settings); -- cgit v1.2.3 From 17a9b05b9d2ec986223159b7ec92cddd236690a5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 13 Apr 2015 23:10:43 +1000 Subject: Fix T44350: View3D layer out of sync /w scene --- source/blender/blenkernel/intern/blender.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 8106f27253b..305bf1ed796 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -293,6 +293,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath if (wm_scene_is_visible(wm, bfd->curscene) == false) { curscene = bfd->curscene; curscreen->scene = curscene; + BKE_screen_view3d_scene_sync(curscreen); } } } -- cgit v1.2.3 From 8ad37b0d224fcf3eb09dd2b7def8bdcc386af1a1 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 13 Apr 2015 15:41:57 +0200 Subject: Fix T44359: `mesh_normals_loop_custom_set()` would not behave correctly with zero-normals. Zero-normals here are used as a shortcut to say 'use auto-computed values'. So we have to do so in pre-process steps! --- source/blender/blenkernel/intern/mesh_evaluate.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index ceb9b016ff2..bbc175fefcd 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -1349,6 +1349,10 @@ static void mesh_normals_loop_custom_set( const int nidx = lidx; float *nor = custom_loopnors[nidx]; + if (is_zero_v3(nor)) { + nor = lnors[nidx]; + } + if (!org_nor) { org_nor = nor; } @@ -1408,6 +1412,10 @@ static void mesh_normals_loop_custom_set( const int nidx = use_vertices ? (int)mloops[lidx].v : lidx; float *nor = custom_loopnors[nidx]; + if (is_zero_v3(nor)) { + nor = lnors[nidx]; + } + nbr_nors++; add_v3_v3(avg_nor, nor); BLI_SMALLSTACK_PUSH(clnors_data, (short *)r_clnors_data[lidx]); -- cgit v1.2.3 From 198ca57ae48fb6860fd82c04e5f1f0a41a5612da Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 13 Apr 2015 15:57:46 +0200 Subject: Graph editor: Normalization feature now uses the full range of the data instead of just one semiaxis for the maximum size. --- source/blender/editors/animation/anim_draw.c | 53 +++++++++++++++++----- source/blender/editors/include/ED_anim_api.h | 2 +- source/blender/editors/space_graph/graph_draw.c | 29 +++++++----- source/blender/editors/space_graph/graph_edit.c | 35 ++++++++------ source/blender/editors/space_graph/graph_select.c | 20 ++++---- .../editors/transform/transform_conversions.c | 34 +++++++------- source/blender/makesdna/DNA_anim_types.h | 2 +- 7 files changed, 110 insertions(+), 65 deletions(-) diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index ed294d7208f..6d0086ca459 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -267,19 +267,26 @@ short ANIM_get_normalization_flags(bAnimContext *ac) return 0; } -static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag) +static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, float *r_offset) { - float factor = 1.0f; + float factor = 1.0f, offset = 0.0f; if (flag & ANIM_UNITCONV_RESTORE) { + if (r_offset) + *r_offset = fcu->prev_offset; + return 1.0f / fcu->prev_norm_factor; } if (flag & ANIM_UNITCONV_NORMALIZE_FREEZE) { + if (r_offset) + *r_offset = fcu->prev_offset; return fcu->prev_norm_factor; } if (G.moving & G_TRANSFORM_FCURVES) { + if (r_offset) + *r_offset = fcu->prev_offset; return fcu->prev_norm_factor; } @@ -288,6 +295,8 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag) BezTriple *bezt; int i; float max_coord = -FLT_MAX; + float min_coord = FLT_MAX; + float range; if (fcu->totvert < 1) { return 1.0f; @@ -296,35 +305,55 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag) if (PRVRANGEON) { for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { if (IN_RANGE_INCL(bezt->vec[1][0], scene->r.psfra, scene->r.pefra)) { - max_coord = max_ff(max_coord, fabsf(bezt->vec[0][1])); - max_coord = max_ff(max_coord, fabsf(bezt->vec[1][1])); - max_coord = max_ff(max_coord, fabsf(bezt->vec[2][1])); + max_coord = max_ff(max_coord, bezt->vec[0][1]); + max_coord = max_ff(max_coord, bezt->vec[1][1]); + max_coord = max_ff(max_coord, bezt->vec[2][1]); + + min_coord = min_ff(min_coord, bezt->vec[0][1]); + min_coord = min_ff(min_coord, bezt->vec[1][1]); + min_coord = min_ff(min_coord, bezt->vec[2][1]); } } } else { for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { - max_coord = max_ff(max_coord, fabsf(bezt->vec[0][1])); - max_coord = max_ff(max_coord, fabsf(bezt->vec[1][1])); - max_coord = max_ff(max_coord, fabsf(bezt->vec[2][1])); + max_coord = max_ff(max_coord, bezt->vec[0][1]); + max_coord = max_ff(max_coord, bezt->vec[1][1]); + max_coord = max_ff(max_coord, bezt->vec[2][1]); + + min_coord = min_ff(min_coord, bezt->vec[0][1]); + min_coord = min_ff(min_coord, bezt->vec[1][1]); + min_coord = min_ff(min_coord, bezt->vec[2][1]); } } - if (max_coord > FLT_EPSILON) { - factor = 1.0f / max_coord; + range = max_coord - min_coord; + + if (range > FLT_EPSILON) { + factor = 1.0f / range; } + offset = -min_coord - range / 2.0f; } + + if (r_offset) { + *r_offset = offset; + } + fcu->prev_norm_factor = factor; + fcu->prev_offset = offset; return factor; } /* Get unit conversion factor for given ID + F-Curve */ -float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag) +float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag, float *r_offset) { if (flag & ANIM_UNITCONV_NORMALIZE) { - return normalization_factor_get(scene, fcu, flag); + return normalization_factor_get(scene, fcu, flag, r_offset); } + if (r_offset) + *r_offset = 0.0f; + /* sanity checks */ if (id && fcu && fcu->rna_path) { PointerRNA ptr, id_ptr; diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 9dea66adc7c..73f28986375 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -617,7 +617,7 @@ typedef enum eAnimUnitConv_Flags { short ANIM_get_normalization_flags(bAnimContext *ac); /* Get unit conversion factor for given ID + F-Curve */ -float ANIM_unit_mapping_get_factor(struct Scene *scene, struct ID *id, struct FCurve *fcu, short flag); +float ANIM_unit_mapping_get_factor(struct Scene *scene, struct ID *id, struct FCurve *fcu, short flag, float *r_offset); /* ------------- Utility macros ----------------------- */ diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index 0313ce4b1d4..87e7cab4d15 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -481,7 +481,7 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d ChannelDriver *driver; float samplefreq; float stime, etime; - float unitFac; + float unitFac, offset; float dx, dy; short mapping_flag = ANIM_get_normalization_flags(ac); int i, n; @@ -498,7 +498,7 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d fcu->driver = NULL; /* compute unit correction factor */ - unitFac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag); + unitFac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset); /* Note about sampling frequency: * Ideally, this is chosen such that we have 1-2 pixels = 1 segment @@ -550,7 +550,7 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d n = (etime - stime) / samplefreq + 0.5f; for (i = 0; i <= n; i++) { float ctime = stime + i * samplefreq; - glVertex2f(ctime, evaluate_fcurve(fcu, ctime) * unitFac); + glVertex2f(ctime, (evaluate_fcurve(fcu, ctime) + offset) * unitFac); } glEnd(); @@ -566,13 +566,14 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie FPoint *fpt = prevfpt + 1; float fac, v[2]; int b = fcu->totvert - 1; - float unit_scale; + float unit_scale, offset; short mapping_flag = ANIM_get_normalization_flags(ac); /* apply unit mapping */ glPushMatrix(); - unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag); + unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset); glScalef(1.0f, unit_scale, 1.0f); + glTranslatef(0.0f, offset, 0.0f); glBegin(GL_LINE_STRIP); @@ -665,14 +666,15 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 float fac = 0.0f; int b = fcu->totvert - 1; int resol; - float unit_scale; + float unit_scale, offset; short mapping_flag = ANIM_get_normalization_flags(ac); /* apply unit mapping */ glPushMatrix(); - unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag); + unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset); glScalef(1.0f, unit_scale, 1.0f); - + glTranslatef(0.0f, offset, 0.0f); + glBegin(GL_LINE_STRIP); /* extrapolate to left? */ @@ -826,7 +828,8 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) ChannelDriver *driver = fcu->driver; View2D *v2d = &ac->ar->v2d; short mapping_flag = ANIM_get_normalization_flags(ac); - float unitfac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag); + float offset; + float unitfac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset); /* for now, only show when debugging driver... */ //if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0) @@ -850,10 +853,10 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) glBegin(GL_LINES); { t = v2d->cur.xmin; - glVertex2f(t, t * unitfac); + glVertex2f(t, (t + offset) * unitfac); t = v2d->cur.xmax; - glVertex2f(t, t * unitfac); + glVertex2f(t, (t + offset) * unitfac); } glEnd(); @@ -1067,10 +1070,12 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid } else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) { short mapping_flag = ANIM_get_normalization_flags(ac); - float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag); + float offset; + float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); glPushMatrix(); glScalef(1.0f, unit_scale, 1.0f); + glTranslatef(0.0f, offset, 0.0f); if (fcu->bezt) { bool do_handles = draw_fcurve_handles_check(sipo, fcu); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 0dba9ccfbae..80503a7897c 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -109,7 +109,7 @@ void get_graph_keyframe_extents(bAnimContext *ac, float *xmin, float *xmax, floa AnimData *adt = ANIM_nla_mapping_get(ac, ale); FCurve *fcu = (FCurve *)ale->key_data; float txmin, txmax, tymin, tymax; - float unitFac; + float unitFac, offset; /* get range */ if (calc_fcurve_bounds(fcu, &txmin, &txmax, &tymin, &tymax, do_sel_only, include_handles)) { @@ -122,7 +122,9 @@ void get_graph_keyframe_extents(bAnimContext *ac, float *xmin, float *xmax, floa } /* apply unit corrections */ - unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag); + unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); + tymin += offset; + tymax += offset; tymin *= unitFac; tymax *= unitFac; @@ -350,7 +352,7 @@ static void create_ghost_curves(bAnimContext *ac, int start, int end) AnimData *adt = ANIM_nla_mapping_get(ac, ale); ChannelDriver *driver = fcu->driver; FPoint *fpt; - float unitFac; + float unitFac, offset; int cfra; SpaceIpo *sipo = (SpaceIpo *) ac->sl; short mapping_flag = ANIM_get_normalization_flags(ac); @@ -359,7 +361,7 @@ static void create_ghost_curves(bAnimContext *ac, int start, int end) fcu->driver = NULL; /* calculate unit-mapping factor */ - unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag); + unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); /* create samples, but store them in a new curve * - we cannot use fcurve_store_samples() as that will only overwrite the original curve @@ -372,7 +374,7 @@ static void create_ghost_curves(bAnimContext *ac, int start, int end) float cfrae = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP); fpt->vec[0] = cfrae; - fpt->vec[1] = fcurve_samplingcb_evalcurve(fcu, NULL, cfrae) * unitFac; + fpt->vec[1] = (fcurve_samplingcb_evalcurve(fcu, NULL, cfrae) + offset) * unitFac; } /* set color of ghost curve @@ -610,7 +612,7 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op) ListBase anim_data; short mapping_flag = ANIM_get_normalization_flags(&ac); - + float scale, offset; /* get frame and value from props */ frame = RNA_float_get(op->ptr, "frame"); val = RNA_float_get(op->ptr, "value"); @@ -620,8 +622,10 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op) frame = BKE_nla_tweakedit_remap(adt, frame, NLATIME_CONVERT_UNMAP); /* apply inverse unit-mapping to value to get correct value for F-Curves */ - val *= ANIM_unit_mapping_get_factor(ac.scene, ale->id, fcu, mapping_flag | ANIM_UNITCONV_RESTORE); - + scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, fcu, mapping_flag | ANIM_UNITCONV_RESTORE, &offset); + + val = val * scale - offset; + /* insert keyframe on the specified frame + value */ insert_vert_fcurve(fcu, frame, val, 0); @@ -1905,7 +1909,8 @@ static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op)) AnimData *adt = ANIM_nla_mapping_get(&ac, ale); short mapping_flag = ANIM_get_normalization_flags(&ac); KeyframeEditData current_ked; - float unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS); + float offset; + float unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset); memset(¤t_ked, 0, sizeof(current_ked)); @@ -1919,7 +1924,7 @@ static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op)) ked.f1 += current_ked.f1; ked.i1 += current_ked.i1; - ked.f2 += current_ked.f2 * unit_scale; + ked.f2 += (current_ked.f2 + offset) * unit_scale; ked.i2 += current_ked.i2; } @@ -2012,9 +2017,10 @@ static void snap_graph_keys(bAnimContext *ac, short mode) /* normalise cursor value (for normalised F-Curves display) */ if (mode == GRAPHKEYS_SNAP_VALUE) { short mapping_flag = ANIM_get_normalization_flags(ac); - float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag); + float offset; + float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag, &offset); - ked.f1 = cursor_value / unit_scale; + ked.f1 = (cursor_value / unit_scale) - offset; } /* perform snapping */ @@ -2139,9 +2145,10 @@ static void mirror_graph_keys(bAnimContext *ac, short mode) /* apply unit corrections */ if (mode == GRAPHKEYS_MIRROR_VALUE) { short mapping_flag = ANIM_get_normalization_flags(ac); - float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS); + float offset; + float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset); - ked.f1 = cursor_value * unit_scale; + ked.f1 = (cursor_value + offset) * unit_scale; } /* perform actual mirroring */ diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 28107337084..4cf8a1de7ab 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -272,7 +272,8 @@ static void borderselect_graphkeys( for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); FCurve *fcu = (FCurve *)ale->key_data; - float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag); + float offset; + float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); /* apply NLA mapping to all the keyframes, since it's easier than trying to * guess when a callback might use something different @@ -282,8 +283,8 @@ static void borderselect_graphkeys( scaled_rectf.xmin = rectf.xmin; scaled_rectf.xmax = rectf.xmax; - scaled_rectf.ymin = rectf.ymin / unit_scale; - scaled_rectf.ymax = rectf.ymax / unit_scale; + scaled_rectf.ymin = rectf.ymin / unit_scale - offset; + scaled_rectf.ymax = rectf.ymax / unit_scale - offset; /* set horizontal range (if applicable) * NOTE: these values are only used for x-range and y-range but not region @@ -1119,7 +1120,7 @@ static bool fcurve_handle_sel_check(SpaceIpo *sipo, BezTriple *bezt) // TODO: should we return if we hit something? static void nearest_fcurve_vert_store( ListBase *matches, View2D *v2d, FCurve *fcu, eAnim_ChannelType ctype, - BezTriple *bezt, FPoint *fpt, short hpoint, const int mval[2], float unit_scale) + BezTriple *bezt, FPoint *fpt, short hpoint, const int mval[2], float unit_scale, float offset) { /* Keyframes or Samples? */ if (bezt) { @@ -1131,7 +1132,7 @@ static void nearest_fcurve_vert_store( * 'vec' matrix */ if (UI_view2d_view_to_region_clip(v2d, - bezt->vec[hpoint + 1][0], bezt->vec[hpoint + 1][1] * unit_scale, + bezt->vec[hpoint + 1][0], (bezt->vec[hpoint + 1][1] + offset) * unit_scale, &screen_co[0], &screen_co[1]) && /* check if distance from mouse cursor to vert in screen space is within tolerance */ ((dist = len_v2v2_int(mval, screen_co)) <= GVERTSEL_TOL)) @@ -1193,7 +1194,8 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L for (ale = anim_data.first; ale; ale = ale->next) { FCurve *fcu = (FCurve *)ale->key_data; AnimData *adt = ANIM_nla_mapping_get(ac, ale); - float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag); + float offset; + float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); /* apply NLA mapping to all the keyframes */ if (adt) @@ -1205,18 +1207,18 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L for (i = 0; i < fcu->totvert; i++, prevbezt = bezt1, bezt1++) { /* keyframe */ - nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_KEY, mval, unit_scale); + nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_KEY, mval, unit_scale, offset); /* handles - only do them if they're visible */ if (fcurve_handle_sel_check(sipo, bezt1) && (fcu->totvert > 1)) { /* first handle only visible if previous segment had handles */ if ((!prevbezt && (bezt1->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) { - nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_LEFT, mval, unit_scale); + nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_LEFT, mval, unit_scale, offset); } /* second handle only visible if this segment is bezier */ if (bezt1->ipo == BEZT_IPO_BEZ) { - nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_RIGHT, mval, unit_scale); + nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_RIGHT, mval, unit_scale, offset); } } } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 1af214b8c77..f21685551a8 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3836,6 +3836,7 @@ static void createTransActionData(bContext *C, TransInfo *t) typedef struct TransDataGraph { float unit_scale; + float offset; } TransDataGraph; /* Helper function for createTransGraphEditData, which is responsible for associating @@ -3844,7 +3845,7 @@ typedef struct TransDataGraph { static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph *tdg, AnimData *adt, BezTriple *bezt, int bi, bool selected, bool ishandle, bool intvals, - float mtx[3][3], float smtx[3][3], float unit_scale) + float mtx[3][3], float smtx[3][3], float unit_scale, float offset) { float *loc = bezt->vec[bi]; const float *cent = bezt->vec[1]; @@ -3858,26 +3859,26 @@ static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph * if (adt) { td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], NLATIME_CONVERT_MAP); - td2d->loc[1] = loc[1] * unit_scale; + td2d->loc[1] = (loc[1] + offset) * unit_scale; td2d->loc[2] = 0.0f; td2d->loc2d = loc; td->loc = td2d->loc; td->center[0] = BKE_nla_tweakedit_remap(adt, cent[0], NLATIME_CONVERT_MAP); - td->center[1] = cent[1] * unit_scale; + td->center[1] = (cent[1] + offset) * unit_scale; td->center[2] = 0.0f; copy_v3_v3(td->iloc, td->loc); } else { td2d->loc[0] = loc[0]; - td2d->loc[1] = loc[1] * unit_scale; + td2d->loc[1] = (loc[1] + offset) * unit_scale; td2d->loc[2] = 0.0f; td2d->loc2d = loc; td->loc = td2d->loc; copy_v3_v3(td->center, cent); - td->center[1] *= unit_scale; + td->center[1] = (td->center[1] + offset) * unit_scale; copy_v3_v3(td->iloc, td->loc); } @@ -3917,6 +3918,7 @@ static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph * copy_m3_m3(td->smtx, smtx); tdg->unit_scale = unit_scale; + tdg->offset = offset; } static bool graph_edit_is_translation_mode(TransInfo *t) @@ -4104,7 +4106,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) AnimData *adt = ANIM_nla_mapping_get(&ac, ale); FCurve *fcu = (FCurve *)ale->key_data; bool intvals = (fcu->flag & FCURVE_INT_VALUES) != 0; - float unit_scale; + float unit_scale, offset; float cfra; /* F-Curve may not have any keyframes */ @@ -4119,7 +4121,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) else cfra = (float)CFRA; - unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, anim_map_flag); + unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, anim_map_flag, &offset); /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { @@ -4135,11 +4137,11 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) bool is_sel = (sel2 || sel1 || sel3); /* we always select all handles for proportional editing if central handle is selected */ initTransDataCurveHandles(td, bezt); - bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, is_sel, true, intvals, mtx, smtx, unit_scale); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, is_sel, true, intvals, mtx, smtx, unit_scale, offset); initTransDataCurveHandles(td, bezt); - bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, is_sel, false, intvals, mtx, smtx, unit_scale); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, is_sel, false, intvals, mtx, smtx, unit_scale, offset); initTransDataCurveHandles(td, bezt); - bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, is_sel, true, intvals, mtx, smtx, unit_scale); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, is_sel, true, intvals, mtx, smtx, unit_scale, offset); } else { /* only include handles if selected, irrespective of the interpolation modes. @@ -4148,7 +4150,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) if (!is_translation_mode || !(sel2)) { if (sel1) { hdata = initTransDataCurveHandles(td, bezt); - bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, sel1, true, intvals, mtx, smtx, unit_scale); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, sel1, true, intvals, mtx, smtx, unit_scale, offset); } else { /* h1 = 0; */ /* UNUSED */ @@ -4157,7 +4159,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) if (sel3) { if (hdata == NULL) hdata = initTransDataCurveHandles(td, bezt); - bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, sel3, true, intvals, mtx, smtx, unit_scale); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, sel3, true, intvals, mtx, smtx, unit_scale, offset); } else { /* h2 = 0; */ /* UNUSED */ @@ -4178,7 +4180,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) hdata = initTransDataCurveHandles(td, bezt); } - bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, sel2, false, intvals, mtx, smtx, unit_scale); + bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, sel2, false, intvals, mtx, smtx, unit_scale, offset); } /* special hack (must be done after initTransDataCurveHandles(), as that stores handle settings to restore...): @@ -4543,16 +4545,16 @@ void flushTransGraphData(TransInfo *t) if (td->flag & TD_INTVALUES) td2d->loc2d[1] = floorf(td2d->loc[1] + 0.5f); else - td2d->loc2d[1] = td2d->loc[1] * inv_unit_scale; + td2d->loc2d[1] = td2d->loc[1] * inv_unit_scale - tdg->offset; if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) { td2d->h1[0] = td2d->ih1[0] + td->loc[0] - td->iloc[0]; - td2d->h1[1] = td2d->ih1[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale; + td2d->h1[1] = td2d->ih1[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale - tdg->offset; } if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) { td2d->h2[0] = td2d->ih2[0] + td->loc[0] - td->iloc[0]; - td2d->h2[1] = td2d->ih2[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale; + td2d->h2[1] = td2d->ih2[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale - tdg->offset; } } } diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index 9e6b71fcbac..693e0fc1293 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -459,7 +459,7 @@ typedef struct FCurve { int color_mode; /* coloring method to use (eFCurve_Coloring) */ float color[3]; /* the last-color this curve took */ - float prev_norm_factor, pad; + float prev_norm_factor, prev_offset; } FCurve; -- cgit v1.2.3 From 4ce437fff0374af7b38e1cf2b3ded4279da7f2e2 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 13 Apr 2015 19:16:40 +0500 Subject: Revert "Fix hair random rotation limited to 180 degrees" This reverts commit 176ed5bfe280ef2151f93c0940d54498aaf00d71. --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/intern/particle.c | 2 +- source/blender/blenkernel/intern/particle_system.c | 2 +- source/blender/blenloader/intern/versioning_270.c | 8 -------- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index f5e7643085a..86576f9a11b 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 274 -#define BLENDER_SUBVERSION 5 +#define BLENDER_SUBVERSION 4 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 5 diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 0e200c73918..6c354c59d7a 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -4100,7 +4100,7 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa float q_phase[4]; float phasefac = psys->part->phasefac; if (psys->part->randphasefac != 0.0f) - phasefac += psys->part->randphasefac * psys_frand(psys, (pa - psys->particles) + 20) * 2.0f; + phasefac += psys->part->randphasefac * psys_frand(psys, (pa - psys->particles) + 20); axis_angle_to_quat(q_phase, vec, phasefac * (float)M_PI); mul_qt_v3(q_phase, side); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 0439e56c294..5a263e24fc4 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -928,7 +928,7 @@ void psys_get_birth_coords(ParticleSimulationData *sim, ParticleData *pa, Partic /* rotation phase */ phasefac = part->phasefac; if (part->randphasefac != 0.0f) - phasefac += part->randphasefac * psys_frand(psys, p + 20) * 2.0f; + phasefac += part->randphasefac * psys_frand(psys, p + 20); axis_angle_to_quat( q_phase,x_vec, phasefac*(float)M_PI); /* combine base rotation & phase */ diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 49e81b1cfff..1b91d3d869e 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -799,12 +799,4 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } - - if (!MAIN_VERSION_ATLEAST(main, 274, 5)) { - /* Particle random phase range doubled. */ - ParticleSettings *part; - for (part = main->particle.first; part; part = part->id.next) { - part->randphasefac *= 0.5f; - } - } } -- cgit v1.2.3 From f27e0b7c5e9d9ac1d80fc6b86d29ea96e971708d Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 13 Apr 2015 16:09:45 +0200 Subject: After user feedback: * Allow ctrl click to do negative stroke in line strokes * Use alt for angle constraints. --- source/blender/editors/sculpt_paint/paint_stroke.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 5588d1e589e..f5a65be880e 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -673,7 +673,7 @@ PaintStroke *paint_stroke_new(bContext *C, if (stroke->stroke_mode == BRUSH_STROKE_INVERT) { - if (br->flag & (BRUSH_CURVE | BRUSH_LINE)) { + if (br->flag & (BRUSH_CURVE)) { RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL); } } @@ -1129,7 +1129,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_FINISHED; } else if (br->flag & BRUSH_LINE) { - if (event->ctrl) + if (event->alt) stroke->constrain_line = true; else stroke->constrain_line = false; -- cgit v1.2.3 From cae23bab6b5fdb0da96244c1ecc8c1586c9961f3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 14 Apr 2015 00:59:28 +1000 Subject: Fix for crash with non-camera as a camera --- source/blender/blenkernel/intern/camera.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index fec6542ac47..d62628baa9e 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -931,6 +931,8 @@ float BKE_camera_multiview_shift_x(RenderData *rd, Object *camera, const char *v const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0; Camera *data = camera->data; + BLI_assert(camera->type == OB_CAMERA); + if (!is_multiview) { return data->shiftx; } @@ -944,7 +946,9 @@ float BKE_camera_multiview_shift_x(RenderData *rd, Object *camera, const char *v void BKE_camera_multiview_params(RenderData *rd, CameraParams *params, Object *camera, const char *viewname) { - params->shiftx = BKE_camera_multiview_shift_x(rd, camera, viewname); + if (camera->type == OB_CAMERA) { + params->shiftx = BKE_camera_multiview_shift_x(rd, camera, viewname); + } } void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings) -- cgit v1.2.3 From aed97c9efb3c7c035031bf70edd07f2d81e4e3e2 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 13 Apr 2015 18:37:15 +0200 Subject: Fix bug with autonormalization and transform (after own range commit). Transforming the center after transforming a handle would continuously flush an extra offset to the handles. Also use normalization range of -1.0 to 1.0 instead of -0.5 to 0.5 (not really important, just for better comparisons) --- source/blender/editors/animation/anim_draw.c | 2 +- source/blender/editors/transform/transform_conversions.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 6d0086ca459..54d371d8f50 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -330,7 +330,7 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo range = max_coord - min_coord; if (range > FLT_EPSILON) { - factor = 1.0f / range; + factor = 2.0f / range; } offset = -min_coord - range / 2.0f; } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index f21685551a8..5750ba40afe 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -4549,12 +4549,12 @@ void flushTransGraphData(TransInfo *t) if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) { td2d->h1[0] = td2d->ih1[0] + td->loc[0] - td->iloc[0]; - td2d->h1[1] = td2d->ih1[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale - tdg->offset; + td2d->h1[1] = td2d->ih1[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale; } if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) { td2d->h2[0] = td2d->ih2[0] + td->loc[0] - td->iloc[0]; - td2d->h2[1] = td2d->ih2[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale - tdg->offset; + td2d->h2[1] = td2d->ih2[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale; } } } -- cgit v1.2.3 From 86fe894f8624fe64c5acde94de0e5d14e8803a55 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 13 Apr 2015 20:27:32 +0200 Subject: Moar precision for Color Stop position slider in Color Ramps Normal dragging now uses a precision of 0.01 instead of 0.1, shift+dragging now uses 0.001. (0.1 steps can still be done using ctrl) Requested by @venomgfx --- source/blender/editors/interface/interface_templates.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index c36d25b8030..c3a9d17d255 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1561,6 +1561,7 @@ static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand row = uiLayoutRow(split, false); uiItemR(row, &ptr, "position", 0, IFACE_("Pos"), ICON_NONE); bt = block->buttons.last; + bt->a1 = 1.0f; /* gives a bit more precision for modifying position */ UI_but_func_set(bt, colorband_update_cb, bt, coba); row = uiLayoutRow(layout, false); @@ -1578,6 +1579,7 @@ static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand row = uiLayoutRow(subsplit, false); uiItemR(row, &ptr, "position", UI_ITEM_R_SLIDER, IFACE_("Pos"), ICON_NONE); bt = block->buttons.last; + bt->a1 = 1.0f; /* gives a bit more precision for modifying position */ UI_but_func_set(bt, colorband_update_cb, bt, coba); row = uiLayoutRow(split, false); -- cgit v1.2.3 From 057c7c6fabdb6106079fe4af90721c79c5c59142 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 13 Apr 2015 21:00:06 +0200 Subject: Cleanup: do not use _reportf() when not doing any string formating! Also usual minor i18n messages stuff... --- release/scripts/modules/bl_i18n_utils/settings.py | 3 +++ source/blender/makesrna/intern/rna_color.c | 2 +- source/blender/makesrna/intern/rna_nodetree.c | 2 +- source/blender/makesrna/intern/rna_scene.c | 2 +- source/blender/windowmanager/intern/wm_stereo.c | 9 ++++----- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py index 920a56a628b..c1d9b926924 100644 --- a/release/scripts/modules/bl_i18n_utils/settings.py +++ b/release/scripts/modules/bl_i18n_utils/settings.py @@ -324,6 +324,7 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = { "y", # Sub-strings. "available with", + "brown fox", "can't save image while rendering", "expected a timeline/animation area to be active", "expected a view3d region", @@ -332,6 +333,8 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = { "image file not found", "image path can't be written to", "in memory to enable editing!", + "jumps over", + "the lazy dog", "unable to load movie clip", "unable to load text", "unable to open the file", diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 0c871317d04..8ea67a34fbb 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -673,7 +673,7 @@ static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene) static float rna_CurveMap_evaluateF(struct CurveMap *cuma, ReportList *reports, float value) { if (!cuma->table) { - BKE_reportf(reports, RPT_ERROR, "CurveMap table not initialized, call initialize() on CurveMapping owner of the CurveMap"); + BKE_report(reports, RPT_ERROR, "CurveMap table not initialized, call initialize() on CurveMapping owner of the CurveMap"); return 0.0f; } return curvemap_evaluateF(cuma, value); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 075b139c6c4..da77b9ee6ea 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1578,7 +1578,7 @@ static bNodeSocket *rna_Node_outputs_new(ID *id, bNode *node, ReportList *report sock = nodeAddSocket(ntree, node, SOCK_OUT, type, identifier, name); if (sock == NULL) { - BKE_reportf(reports, RPT_ERROR, "Unable to create socket"); + BKE_report(reports, RPT_ERROR, "Unable to create socket"); } else { ntreeUpdateTree(G.main, ntree); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index f93cdc5715d..ee77bccc340 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1907,7 +1907,7 @@ static void rna_FreestyleSettings_module_remove( if (module->script) BKE_reportf(reports, RPT_ERROR, "Style module '%s' could not be removed", module->script->id.name + 2); else - BKE_reportf(reports, RPT_ERROR, "Style module could not be removed"); + BKE_report(reports, RPT_ERROR, "Style module could not be removed"); return; } diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index c619b2ed727..328223645bc 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -464,8 +464,7 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) /* pageflip requires a new window to be created with the proper OS flags */ if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { if (wm_stereo3d_quadbuffer_supported() == false) { - BKE_reportf(op->reports, RPT_ERROR, - "Quadbuffer not supported by the system"); + BKE_report(op->reports, RPT_ERROR, "Quad-buffer not supported by the system"); win->stereo3d_format->display_mode = display_mode; return OPERATOR_CANCELLED; } @@ -474,8 +473,8 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) win = wm->windows.last; } else { - BKE_reportf(op->reports, RPT_ERROR, - "Fail to create a window compatible with time sequential (page-flip) display method"); + BKE_report(op->reports, RPT_ERROR, + "Fail to create a window compatible with time sequential (page-flip) display method"); win->stereo3d_format->display_mode = display_mode; return OPERATOR_CANCELLED; } @@ -483,7 +482,7 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) { if (!is_fullscreen) { - BKE_reportf(op->reports, RPT_INFO, "Stereo 3D Mode requires the window to be fullscreen"); + BKE_report(op->reports, RPT_INFO, "Stereo 3D Mode requires the window to be fullscreen"); } } -- cgit v1.2.3 From 27ded012d68751c3705b4a49d3d59259a2ef8d5c Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 13 Apr 2015 16:56:43 -0400 Subject: cleanup: style to match my earlier commit in temp_viewport_fx_merge branch https://developer.blender.org/rBc3f3b958dc0b plus more no functional changes --- .../blender/editors/interface/interface_widgets.c | 63 +++++++++------------- source/blender/editors/space_view3d/drawobject.c | 23 ++++---- source/blender/editors/space_view3d/view3d_draw.c | 22 ++++---- 3 files changed, 47 insertions(+), 61 deletions(-) diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 51a98231c8b..b3c3d7f53a9 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -70,7 +70,7 @@ * - return: array of [size][2][x,y] points, the edges of the roundbox, + UV coords * * - draw black box with alpha 0 on exact button boundbox - * - for ever AA step: + * - for every AA step: * - draw the inner part for a round filled box, with color blend codes or texture coords * - draw outline in outline color * - draw outer part, bottom half, extruded 1 pixel to bottom, for emboss shadow @@ -547,12 +547,12 @@ static void widget_menu_trias(uiWidgetTrias *tria, const rcti *rect) { float centx, centy, size; int a; - + /* center position and size */ centx = rect->xmax - 0.32f * BLI_rcti_size_y(rect); centy = rect->ymin + 0.50f * BLI_rcti_size_y(rect); - size = 0.4f * (float)BLI_rcti_size_y(rect); - + size = 0.4f * BLI_rcti_size_y(rect); + for (a = 0; a < 6; a++) { tria->vec[a][0] = size * menu_tria_vert[a][0] + centx; tria->vec[a][1] = size * menu_tria_vert[a][1] + centy; @@ -585,7 +585,6 @@ static void widget_check_trias(uiWidgetTrias *tria, const rcti *rect) /* prepares shade colors */ static void shadecolors4(char coltop[4], char coldown[4], const char *color, short shadetop, short shadedown) { - coltop[0] = CLAMPIS(color[0] + shadetop, 0, 255); coltop[1] = CLAMPIS(color[1] + shadetop, 0, 255); coltop[2] = CLAMPIS(color[2] + shadetop, 0, 255); @@ -781,6 +780,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) wcol->item[1], wcol->item[2], (unsigned char)((float)wcol->item[3] / WIDGET_AA_JITTER)}; + /* for each AA step */ for (j = 0; j < WIDGET_AA_JITTER; j++) { glTranslatef(jit[j][0], jit[j][1], 0.0f); @@ -799,7 +799,6 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) } glDisable(GL_BLEND); - } /* *********************** text/icon ************************************** */ @@ -1215,7 +1214,6 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs); if (but->strwidth < 10) break; } - } @@ -1382,7 +1380,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b t = 0; } - glColor3f(0.20, 0.6, 0.9); + glColor3f(0.2, 0.6, 0.9); tx = rect->xmin + t + 2; ty = rect->ymin + 2; @@ -2188,7 +2186,6 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir static void ui_hsv_cursor(float x, float y) { - glPushMatrix(); glTranslatef(x, y, 0.0f); @@ -2203,7 +2200,6 @@ static void ui_hsv_cursor(float x, float y) glDisable(GL_LINE_SMOOTH); glPopMatrix(); - } void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rect, @@ -2278,12 +2274,12 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti * * Useful for color correction tools where you're only interested in hue. */ if (but->flag & UI_BUT_COLOR_LOCK) { if (U.color_picker_type == USER_CP_CIRCLE_HSV) - hsv[2] = 1.f; + hsv[2] = 1.0f; else hsv[2] = 0.5f; } - ui_color_picker_to_rgb(0.f, 0.f, hsv[2], colcent, colcent + 1, colcent + 2); + ui_color_picker_to_rgb(0.0f, 0.0f, hsv[2], colcent, colcent + 1, colcent + 2); glShadeModel(GL_SMOOTH); @@ -2329,7 +2325,7 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti * void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha) { /* allows for 4 steps (red->yellow) */ - const float color_step = (1.0 / 48.0); + const float color_step = 1.0f / 48.0f; int a; float h = hsv[0], s = hsv[1], v = hsv[2]; float dx, dy, sx1, sx2, sy; @@ -2359,26 +2355,26 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons hsv_to_rgb(0.0, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]); break; case UI_GRAD_H: - hsv_to_rgb(0.0, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]); + hsv_to_rgb(0.0, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]); copy_v3_v3(col1[1], col1[0]); copy_v3_v3(col1[2], col1[0]); copy_v3_v3(col1[3], col1[0]); break; case UI_GRAD_S: - hsv_to_rgb(1.0, 0.0, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(1.0, 0.0, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]); copy_v3_v3(col1[0], col1[1]); copy_v3_v3(col1[2], col1[1]); copy_v3_v3(col1[3], col1[1]); break; case UI_GRAD_V: - hsv_to_rgb(1.0, 1.0, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(1.0, 1.0, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]); copy_v3_v3(col1[0], col1[2]); copy_v3_v3(col1[1], col1[2]); copy_v3_v3(col1[3], col1[2]); break; default: assert(!"invalid 'type' argument"); - hsv_to_rgb(1.0, 1.0, 1.0, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(1.0, 1.0, 1.0, &col1[2][0], &col1[2][1], &col1[2][2]); copy_v3_v3(col1[0], col1[2]); copy_v3_v3(col1[1], col1[2]); copy_v3_v3(col1[3], col1[2]); @@ -2417,23 +2413,21 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons hsv_to_rgb(dx_next, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]); break; case UI_GRAD_H: - { /* annoying but without this the color shifts - could be solved some other way * - campbell */ - hsv_to_rgb(dx_next, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]); + hsv_to_rgb(dx_next, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]); copy_v3_v3(col1[1], col1[0]); copy_v3_v3(col1[2], col1[0]); copy_v3_v3(col1[3], col1[0]); break; - } case UI_GRAD_S: - hsv_to_rgb(h, dx, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(h, dx, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]); copy_v3_v3(col1[0], col1[1]); copy_v3_v3(col1[2], col1[1]); copy_v3_v3(col1[3], col1[1]); break; case UI_GRAD_V: - hsv_to_rgb(h, 1.0, dx, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(h, 1.0, dx, &col1[2][0], &col1[2][1], &col1[2][2]); copy_v3_v3(col1[0], col1[2]); copy_v3_v3(col1[1], col1[2]); copy_v3_v3(col1[3], col1[2]); @@ -2462,9 +2456,8 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons } glEnd(); } - + glShadeModel(GL_FLAT); - } bool ui_but_is_colorpicker_display_space(uiBut *but) @@ -2507,11 +2500,10 @@ void ui_hsvcube_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float *x y = (hsv[2] - but->softmin) / (but->softmax - but->softmin); break; } - + /* cursor */ *xp = rect->xmin + x * BLI_rcti_size_x(rect); *yp = rect->ymin + y * BLI_rcti_size_y(rect); - } static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect) @@ -2592,9 +2584,8 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect) x = rect->xmin + 0.5f * BLI_rcti_size_x(rect); y = rect->ymin + v * BLI_rcti_size_y(rect); CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f); - + ui_hsv_cursor(x, y); - } @@ -2679,7 +2670,8 @@ bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol) BKE_curve_forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], &coord_array[0][0], resol, sizeof(float[2])); BKE_curve_forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], &coord_array[0][1], resol, sizeof(float[2])); - return 1; + /* TODO: why return anything if always true? */ + return true; } #define LINK_RESOL 24 @@ -2688,9 +2680,10 @@ void ui_draw_link_bezier(const rcti *rect) float coord_array[LINK_RESOL + 1][2]; if (ui_link_bezier_points(rect, coord_array, LINK_RESOL)) { +#if 0 /* unused */ /* we can reuse the dist variable here to increment the GL curve eval amount*/ - // const float dist = 1.0f / (float)LINK_RESOL; // UNUSED - + const float dist = 1.0f / (float)LINK_RESOL; +#endif glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); @@ -2701,7 +2694,6 @@ void ui_draw_link_bezier(const rcti *rect) glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - } } @@ -2965,7 +2957,6 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s rect->xmax -= toffs; rect->xmin += toffs; } - } /* I think 3 is sufficient border to indicate keyed status */ @@ -3080,7 +3071,6 @@ static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roun round_box_edges(&wtb, roundboxalign, rect, rad); widgetbase_draw(&wtb, wcol); - } @@ -3276,7 +3266,6 @@ static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), round_box_edges(&wtb, roundboxalign, rect, rad); widgetbase_draw(&wtb, wcol); - } static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign) @@ -3317,7 +3306,6 @@ static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int round_box_edges(&wtb, roundboxalign, rect, rad); widgetbase_draw(&wtb, wcol); - } static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign) @@ -3361,7 +3349,6 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType * wtb.outline = 1; wtb.inner = 0; widgetbase_draw(&wtb, &wt->wcol); - } static uiWidgetType *widget_type(uiWidgetTypeEnum type) @@ -3928,7 +3915,6 @@ static void draw_disk_shaded( glVertex2f(c * radius_ext, s * radius_ext); } glEnd(); - } void ui_draw_pie_center(uiBlock *block) @@ -4017,7 +4003,6 @@ void ui_draw_search_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect) wt->draw(&wt->wcol, rect, block->flag, UI_CNR_ALL); else wt->draw(&wt->wcol, rect, 0, UI_CNR_ALL); - } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index f0b78649307..8dcf1d388ea 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -403,13 +403,13 @@ static const float cosval[CIRCLE_RESOL] = { static void draw_xyz_wire(const float c[3], float size, int axis) { - float v1[3] = {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f}; + float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3] = {0.0f, 0.0f, 0.0f}; float dim = size * 0.1f; float dx[3], dy[3], dz[3]; - dx[0] = dim; dx[1] = 0.f; dx[2] = 0.f; - dy[0] = 0.f; dy[1] = dim; dy[2] = 0.f; - dz[0] = 0.f; dz[1] = 0.f; dz[2] = dim; + dx[0] = dim; dx[1] = 0.0f; dx[2] = 0.0f; + dy[0] = 0.0f; dy[1] = dim; dy[2] = 0.0f; + dz[0] = 0.0f; dz[1] = 0.0f; dz[2] = dim; switch (axis) { case 0: /* x axis */ @@ -425,7 +425,7 @@ static void draw_xyz_wire(const float c[3], float size, int axis) glVertex3fv(v2); /* top left to bottom right */ - mul_v3_fl(dy, 2.f); + mul_v3_fl(dy, 2.0f); add_v3_v3(v1, dy); sub_v3_v3(v2, dy); @@ -448,7 +448,7 @@ static void draw_xyz_wire(const float c[3], float size, int axis) glVertex3fv(v2); /* top left to center */ - mul_v3_fl(dy, 2.f); + mul_v3_fl(dy, 2.0f); add_v3_v3(v1, dy); copy_v3_v3(v2, c); @@ -466,12 +466,12 @@ static void draw_xyz_wire(const float c[3], float size, int axis) glVertex3fv(v1); - mul_v3_fl(dx, 2.f); + mul_v3_fl(dx, 2.0f); add_v3_v3(v1, dx); glVertex3fv(v1); - mul_v3_fl(dz, 2.f); + mul_v3_fl(dz, 2.0f); sub_v3_v3(v1, dx); sub_v3_v3(v1, dz); @@ -484,7 +484,6 @@ static void draw_xyz_wire(const float c[3], float size, int axis) glEnd(); break; } - } void drawaxes(float size, char drawtype) @@ -1619,7 +1618,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D glColor3ubv(ob_wire_col); } - glLineWidth(2.f); + glLineWidth(2.0f); glDisable(GL_LIGHTING); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); @@ -1627,7 +1626,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_LIGHTING); - glLineWidth(1.f); + glLineWidth(1.0f); } if ((dflag & DRAW_CONSTCOLOR) == 0) { @@ -5240,7 +5239,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv BLI_assert(0); break; } - CLAMP(intensity, 0.f, 1.f); + CLAMP(intensity, 0.0f, 1.0f); weight_to_rgb(ma_col, intensity); } } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 195dffe74a0..fd6288b1601 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -657,7 +657,7 @@ static void draw_rotation_guide(RegionView3D *rv3d) glEnable(GL_POINT_SMOOTH); glDepthMask(0); /* don't overwrite zbuf */ - if (rv3d->rot_angle != 0.f) { + if (rv3d->rot_angle != 0.0f) { /* -- draw rotation axis -- */ float scaled_axis[3]; const float scale = rv3d->dist; @@ -665,19 +665,21 @@ static void draw_rotation_guide(RegionView3D *rv3d) glBegin(GL_LINE_STRIP); - color[3] = 0.f; /* more transparent toward the ends */ + color[3] = 0.0f; /* more transparent toward the ends */ glColor4fv(color); add_v3_v3v3(end, o, scaled_axis); glVertex3fv(end); - // color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */ - // ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 +#if 0 + color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */ + /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */ +#endif color[3] = 0.5f; /* more opaque toward the center */ glColor4fv(color); glVertex3fv(o); - color[3] = 0.f; + color[3] = 0.0f; glColor4fv(color); sub_v3_v3v3(end, o, scaled_axis); glVertex3fv(end); @@ -688,14 +690,14 @@ static void draw_rotation_guide(RegionView3D *rv3d) #define ROT_AXIS_DETAIL 13 const float s = 0.05f * scale; - const float step = 2.f * (float)(M_PI / ROT_AXIS_DETAIL); + const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL); float angle; int i; float q[4]; /* rotate ring so it's perpendicular to axis */ const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f; if (!upright) { - const float up[3] = {0.f, 0.f, 1.f}; + const float up[3] = {0.0f, 0.0f, 1.0f}; float vis_angle, vis_axis[3]; cross_v3_v3v3(vis_axis, up, rv3d->rot_axis); @@ -706,7 +708,7 @@ static void draw_rotation_guide(RegionView3D *rv3d) color[3] = 0.25f; /* somewhat faint */ glColor4fv(color); glBegin(GL_LINE_LOOP); - for (i = 0, angle = 0.f; i < ROT_AXIS_DETAIL; ++i, angle += step) { + for (i = 0, angle = 0.0f; i < ROT_AXIS_DETAIL; ++i, angle += step) { float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f}; if (!upright) { @@ -732,12 +734,12 @@ static void draw_rotation_guide(RegionView3D *rv3d) glVertex3fv(o); glEnd(); - /* find screen coordinates for rotation center, then draw pretty icon */ #if 0 + /* find screen coordinates for rotation center, then draw pretty icon */ mul_m4_v3(rv3d->persinv, rot_center); UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN); -#endif /* ^^ just playing around, does not work */ +#endif glDisable(GL_BLEND); glDisable(GL_POINT_SMOOTH); -- cgit v1.2.3 From 54c18d4849ccf1a97ba85ed30416d3639f4909ea Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 13 Apr 2015 23:58:50 +0200 Subject: Fix T44362 no easy way to repeatedly duplicate keyframes in action editors. Reporter used a hacky work-around by placing cursor at end of keyframe range and doing ctrl-C ctrl-V repeatedly. This was working on 2.73 but not anymore since the old selection is not kept. Much better is to have duplication operator be repeatable. This commit takes care of that. --- source/blender/editors/space_action/action_edit.c | 8 -------- source/blender/editors/space_graph/graph_edit.c | 8 -------- source/blender/editors/transform/transform.c | 16 +++++++++------- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index d83137d4cb0..debe3cb9730 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -792,13 +792,6 @@ static int actkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } - -static int actkeys_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) -{ - actkeys_duplicate_exec(C, op); - - return OPERATOR_FINISHED; -} void ACTION_OT_duplicate(wmOperatorType *ot) { @@ -808,7 +801,6 @@ void ACTION_OT_duplicate(wmOperatorType *ot) ot->description = "Make a copy of all selected keyframes"; /* api callbacks */ - ot->invoke = actkeys_duplicate_invoke; ot->exec = actkeys_duplicate_exec; ot->poll = ED_operator_action_active; diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 80503a7897c..d450335d16a 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -883,13 +883,6 @@ static int graphkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static int graphkeys_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) -{ - graphkeys_duplicate_exec(C, op); - - return OPERATOR_FINISHED; -} - void GRAPH_OT_duplicate(wmOperatorType *ot) { /* identifiers */ @@ -898,7 +891,6 @@ void GRAPH_OT_duplicate(wmOperatorType *ot) ot->description = "Make a copy of all selected keyframes"; /* api callbacks */ - ot->invoke = graphkeys_duplicate_invoke; ot->exec = graphkeys_duplicate_exec; ot->poll = graphop_editable_keyframes_poll; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index be33dfd5e20..f8e529aa4bf 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -7591,7 +7591,7 @@ static void headerTimeTranslate(TransInfo *t, char str[MAX_INFO_LEN]) } } -static void applyTimeTranslateValue(TransInfo *t, float UNUSED(sval)) +static void applyTimeTranslateValue(TransInfo *t) { TransData *td = t->data; TransData2D *td2d = t->data2d; @@ -7649,15 +7649,17 @@ static void applyTimeTranslateValue(TransInfo *t, float UNUSED(sval)) static void applyTimeTranslate(TransInfo *t, const int mval[2]) { View2D *v2d = (View2D *)t->view; - float cval[2], sval[2]; char str[MAX_INFO_LEN]; /* calculate translation amount from mouse movement - in 'time-grid space' */ - UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]); - UI_view2d_region_to_view(v2d, t->imval[0], t->imval[0], &sval[0], &sval[1]); + if (t->flag & T_MODAL) { + float cval[2], sval[2]; + UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]); + UI_view2d_region_to_view(v2d, t->imval[0], t->imval[0], &sval[0], &sval[1]); - /* we only need to calculate effect for time (applyTimeTranslate only needs that) */ - t->values[0] = cval[0] - sval[0]; + /* we only need to calculate effect for time (applyTimeTranslate only needs that) */ + t->values[0] = cval[0] - sval[0]; + } /* handle numeric-input stuff */ t->vec[0] = t->values[0]; @@ -7665,7 +7667,7 @@ static void applyTimeTranslate(TransInfo *t, const int mval[2]) t->values[0] = t->vec[0]; headerTimeTranslate(t, str); - applyTimeTranslateValue(t, sval[0]); + applyTimeTranslateValue(t); recalcData(t); -- cgit v1.2.3 From 2bceb3ae1859e67e4f6b487e999f0f81d7615fb3 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Mon, 13 Apr 2015 19:56:56 -0300 Subject: Fix for *harmless* T44342 Error when saving multilayer EXR This was introduced with multiview, and it was an oversight on my end. There is no error, we simply was never returning True --- source/blender/render/intern/source/render_result.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 9ae394fa675..303494d2beb 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -1025,7 +1025,7 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil RenderPass *rpass; RenderView *rview; void *exrhandle = IMB_exr_get_handle(); - bool success = false; + bool success; int a, nr; const char *chan_view = NULL; int compress = (imf ? imf->exr_codec : 0); @@ -1111,6 +1111,7 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil if (IMB_exr_begin_write(exrhandle, filename, width, height, compress)) { IMB_exr_write_channels(exrhandle); + success = true; } else { /* TODO, get the error from openexr's exception */ -- cgit v1.2.3 From af2f4724d57ac11d45e22db97fa797676c44d091 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 14 Apr 2015 10:29:11 +1000 Subject: Cleanup: don't use single sets for comparisons --- release/scripts/startup/bl_ui/properties_constraint.py | 2 +- release/scripts/startup/bl_ui/properties_data_mesh.py | 6 +++--- release/scripts/startup/bl_ui/properties_freestyle.py | 2 +- .../scripts/startup/bl_ui/properties_grease_pencil_common.py | 2 +- release/scripts/startup/bl_ui/properties_mask_common.py | 2 +- release/scripts/startup/bl_ui/properties_material.py | 2 +- release/scripts/startup/bl_ui/properties_particle.py | 4 ++-- .../scripts/startup/bl_ui/properties_physics_dynamicpaint.py | 2 +- release/scripts/startup/bl_ui/properties_render_layer.py | 2 +- release/scripts/startup/bl_ui/properties_scene.py | 2 +- release/scripts/startup/bl_ui/properties_texture.py | 2 +- release/scripts/startup/bl_ui/space_clip.py | 10 +++++----- release/scripts/startup/bl_ui/space_filebrowser.py | 2 +- release/scripts/startup/bl_ui/space_image.py | 2 +- release/scripts/startup/bl_ui/space_node.py | 2 +- release/scripts/startup/bl_ui/space_sequencer.py | 2 +- release/scripts/startup/bl_ui/space_view3d.py | 2 +- release/scripts/startup/bl_ui/space_view3d_toolbar.py | 6 +++--- tests/python/bl_rst_completeness.py | 2 +- 19 files changed, 28 insertions(+), 28 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py index 9aa67223fc4..483da82e6a3 100644 --- a/release/scripts/startup/bl_ui/properties_constraint.py +++ b/release/scripts/startup/bl_ui/properties_constraint.py @@ -894,7 +894,7 @@ class OBJECT_PT_constraints(ConstraintButtonsPanel, Panel): obj = context.object - if obj.type == 'ARMATURE' and obj.mode in {'POSE'}: + if obj.type == 'ARMATURE' and obj.mode == 'POSE': box = layout.box() box.alert = True # XXX: this should apply to the box background box.label(icon='INFO', text="Constraints for active bone do not live here") diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index 058f6283619..e2b0121cdbe 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -70,7 +70,7 @@ class MESH_UL_vgroups(UIList): layout.prop(vgroup, "name", text="", emboss=False, icon_value=icon) icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED' layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False) - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label(text="", icon_value=icon) @@ -94,7 +94,7 @@ class MESH_UL_shape_keys(UIList): else: row.label(text="") row.prop(key_block, "mute", text="", emboss=False) - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label(text="", icon_value=icon) @@ -106,7 +106,7 @@ class MESH_UL_uvmaps_vcols(UIList): layout.prop(item, "name", text="", emboss=False, icon_value=icon) icon = 'RESTRICT_RENDER_OFF' if item.active_render else 'RESTRICT_RENDER_ON' layout.prop(item, "active_render", text="", icon=icon, emboss=False) - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label(text="", icon_value=icon) diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py index 2d91c998007..adc706569b1 100644 --- a/release/scripts/startup/bl_ui/properties_freestyle.py +++ b/release/scripts/startup/bl_ui/properties_freestyle.py @@ -95,7 +95,7 @@ class RENDERLAYER_UL_linesets(UIList): if self.layout_type in {'DEFAULT', 'COMPACT'}: layout.prop(lineset, "name", text="", emboss=False, icon_value=icon) layout.prop(lineset, "show_render", text="", index=index) - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label("", icon_value=icon) diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index 5b5a7648d83..50886231347 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -321,7 +321,7 @@ class GPENCIL_UL_layer(UIList): row = layout.row(align=True) row.prop(gpl, "lock", text="", emboss=False) row.prop(gpl, "hide", text="", emboss=False) - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label(text="", icon_value=icon) diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py index cb4a0f5bb85..9d94d5efa2e 100644 --- a/release/scripts/startup/bl_ui/properties_mask_common.py +++ b/release/scripts/startup/bl_ui/properties_mask_common.py @@ -36,7 +36,7 @@ class MASK_UL_layers(UIList): row.prop(mask, "hide", text="", emboss=False) row.prop(mask, "hide_select", text="", emboss=False) row.prop(mask, "hide_render", text="", emboss=False) - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label(text="", icon_value=icon) diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py index 20143b81d14..cea0c9aef95 100644 --- a/release/scripts/startup/bl_ui/properties_material.py +++ b/release/scripts/startup/bl_ui/properties_material.py @@ -87,7 +87,7 @@ class MATERIAL_UL_matslots(UIList): layout.label(text=iface_("Node %s") % manode.name, translate=False, icon_value=layout.icon(manode)) elif ma.use_nodes: layout.label(text="Node ") - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label(text="", icon_value=icon) diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index 29be9ac2158..e294f5487a6 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -118,7 +118,7 @@ class PARTICLE_UL_particle_systems(bpy.types.UIList): layout.prop(md, "show_render", emboss=False, icon_only=True, icon='RESTRICT_RENDER_OFF' if md.show_render else 'RESTRICT_RENDER_ON') layout.prop(md, "show_viewport", emboss=False, icon_only=True, icon='RESTRICT_VIEW_OFF' if md.show_viewport else 'RESTRICT_VIEW_ON') - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label(text="", icon_value=icon) @@ -1243,7 +1243,7 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel): split = layout.split() split.active = part.kink != 'NO' - if part.kink in {'SPIRAL'}: + if part.kink == 'SPIRAL': col = split.column() sub = col.column(align=True) sub.prop(part, "kink_amplitude", text="Radius") diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py index 01dcf837546..269ffa6d371 100644 --- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py +++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py @@ -40,7 +40,7 @@ class PHYSICS_UL_dynapaint_surfaces(UIList): row.prop(surf, "show_preview", text="", emboss=False, icon='RESTRICT_VIEW_OFF' if surf.show_preview else 'RESTRICT_VIEW_ON') row.prop(surf, "is_active", text="") - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' row = layout.row(align=True) row.label(text="", icon_value=icon) diff --git a/release/scripts/startup/bl_ui/properties_render_layer.py b/release/scripts/startup/bl_ui/properties_render_layer.py index 18c75ccb20c..b23892df408 100644 --- a/release/scripts/startup/bl_ui/properties_render_layer.py +++ b/release/scripts/startup/bl_ui/properties_render_layer.py @@ -40,7 +40,7 @@ class RENDERLAYER_UL_renderlayers(UIList): if self.layout_type in {'DEFAULT', 'COMPACT'}: layout.prop(layer, "name", text="", icon_value=icon, emboss=False) layout.prop(layer, "use", text="", index=index) - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label("", icon_value=icon) diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py index facf54d358a..b4c4ed6ceae 100644 --- a/release/scripts/startup/bl_ui/properties_scene.py +++ b/release/scripts/startup/bl_ui/properties_scene.py @@ -35,7 +35,7 @@ class SCENE_UL_keying_set_paths(UIList): if self.layout_type in {'DEFAULT', 'COMPACT'}: # Do not make this one editable in uiList for now... layout.label(text=kspath.data_path, translate=False, icon_value=icon) - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label(text="", icon_value=icon) diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py index a48e06249fb..98a52444a5a 100644 --- a/release/scripts/startup/bl_ui/properties_texture.py +++ b/release/scripts/startup/bl_ui/properties_texture.py @@ -72,7 +72,7 @@ class TEXTURE_UL_texslots(UIList): layout.label(text="", icon_value=icon) if tex and isinstance(item, bpy.types.MaterialTextureSlot): layout.prop(ma, "use_textures", text="", index=index) - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label(text="", icon_value=icon) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index a7a352f303b..24b17b70493 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -37,7 +37,7 @@ class CLIP_UL_tracking_objects(UIList): layout.prop(tobj, "name", text="", emboss=False, icon='CAMERA_DATA' if tobj.is_camera else 'OBJECT_DATA') - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label(text="", icon='CAMERA_DATA' if tobj.is_camera @@ -147,7 +147,7 @@ class CLIP_HT_header(Header): sc = context.space_data - if sc.mode in {'TRACKING'}: + if sc.mode == 'TRACKING': self._draw_tracking(context) else: self._draw_masking(context) @@ -716,7 +716,7 @@ class CLIP_PT_tracking_camera(Panel): if CLIP_PT_clip_view_panel.poll(context): sc = context.space_data - return sc.mode in {'TRACKING'} and sc.clip + return sc.mode == 'TRACKING' and sc.clip return False @@ -756,7 +756,7 @@ class CLIP_PT_tracking_lens(Panel): if CLIP_PT_clip_view_panel.poll(context): sc = context.space_data - return sc.mode in {'TRACKING'} and sc.clip + return sc.mode == 'TRACKING' and sc.clip return False @@ -893,7 +893,7 @@ class CLIP_PT_stabilization(CLIP_PT_reconstruction_panel, Panel): if CLIP_PT_clip_view_panel.poll(context): sc = context.space_data - return sc.mode in {'TRACKING'} and sc.clip + return sc.mode == 'TRACKING' and sc.clip return False diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py index cf7669e74a4..44dfe2a688e 100644 --- a/release/scripts/startup/bl_ui/space_filebrowser.py +++ b/release/scripts/startup/bl_ui/space_filebrowser.py @@ -104,7 +104,7 @@ class FILEBROWSER_UL_dir(bpy.types.UIList): else: row.prop(direntry, "name", text="", emboss=False, icon=icon) - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.prop(direntry, "path", text="") diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 9a1b9dbc74f..e4542163086 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -1057,7 +1057,7 @@ class ImageScopesPanel: if not (sima and sima.image): return False # scopes are not updated in paint modes, hide - if sima.mode in {'PAINT'}: + if sima.mode == 'PAINT': return False ob = context.active_object if ob and ob.mode in {'TEXTURE_PAINT', 'EDIT'}: diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index 31bfed21c4a..18890aadc93 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -441,7 +441,7 @@ class NODE_UL_interface_sockets(bpy.types.UIList): if socket.is_output: row.template_node_socket(color) - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.template_node_socket(color) diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index e19cf8239d7..4bb65ff7869 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -473,7 +473,7 @@ class SEQUENCER_PT_edit(SequencerButtonsPanel, Panel): split.label(text="Type:") split.prop(strip, "type", text="") - if strip.type not in {'SOUND'}: + if strip.type != 'SOUND': split = layout.split(percentage=0.3) split.label(text="Blend:") split.prop(strip, "blend_type", text="") diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 32b8af140f4..4d8230e2f4d 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -158,7 +158,7 @@ class VIEW3D_MT_editor_menus(Menu): if edit_object: layout.menu("VIEW3D_MT_edit_%s" % edit_object.type.lower()) elif obj: - if mode_string not in {'PAINT_TEXTURE'}: + if mode_string != 'PAINT_TEXTURE': layout.menu("VIEW3D_MT_%s" % mode_string.lower()) if mode_string in {'SCULPT', 'PAINT_VERTEX', 'PAINT_WEIGHT', 'PAINT_TEXTURE'}: layout.menu("VIEW3D_MT_brush") diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index f01ea793e4f..d5f64a7dd0a 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -100,7 +100,7 @@ class VIEW3D_PT_tools_object(View3DPanel, Panel): row.operator("object.shade_smooth", text="Smooth") row.operator("object.shade_flat", text="Flat") - if obj_type in {'MESH'}: + if obj_type == 'MESH': col = layout.column(align=True) col.label(text="Data Transfer:") row = col.row(align=True) @@ -1075,7 +1075,7 @@ class TEXTURE_UL_texpaintslots(UIList): if (not mat.use_nodes) and context.scene.render.engine in {'BLENDER_RENDER', 'BLENDER_GAME'}: mtex_index = mat.texture_paint_slots[index].index layout.prop(mat, "use_textures", text="", index=mtex_index) - elif self.layout_type in {'GRID'}: + elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label(text="") @@ -1858,7 +1858,7 @@ class VIEW3D_PT_tools_history(View3DPanel, Panel): row = col.row(align=True) row.operator("ed.undo") row.operator("ed.redo") - if obj is None or obj.mode not in {'SCULPT'}: + if obj is None or obj.mode != 'SCULPT': # Sculpt mode does not generate an undo menu it seems... col.operator("ed.undo_history") diff --git a/tests/python/bl_rst_completeness.py b/tests/python/bl_rst_completeness.py index d0ba2c552cf..d8dfac66d13 100644 --- a/tests/python/bl_rst_completeness.py +++ b/tests/python/bl_rst_completeness.py @@ -62,7 +62,7 @@ def is_directive_pydata(filepath, directive): return True elif directive.type in {"module", "note", "warning", "code-block", "hlist", "seealso"}: return False - elif directive.type in {"literalinclude"}: # TODO + elif directive.type == "literalinclude": # TODO return False else: print(directive_to_str(filepath, directive), end=" ") -- cgit v1.2.3 From c448196bb4c99b13cdaaf0e197a9f44a46b3bc18 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 14 Apr 2015 10:30:14 +1000 Subject: Cleanup: warnings --- source/blender/blenkernel/intern/bpath.c | 2 +- source/blender/blenloader/intern/versioning_270.c | 4 ++-- source/blender/compositor/intern/COM_ExecutionGroup.cpp | 2 +- source/blender/editors/space_view3d/view3d_view.c | 2 +- source/blender/editors/transform/transform_conversions.c | 4 ++-- source/blender/modifiers/intern/MOD_correctivesmooth.c | 8 ++++---- source/blender/physics/intern/BPH_mass_spring.cpp | 2 +- source/blender/render/intern/source/pipeline.c | 6 +++--- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 357e248c323..7c2b0a8a840 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -595,7 +595,7 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int } else if ((seq->type == SEQ_TYPE_IMAGE) && se) { /* might want an option not to loop over all strips */ - unsigned int len = (unsigned int)MEM_allocN_len(se) / sizeof(*se); + unsigned int len = (unsigned int)MEM_allocN_len(se) / (unsigned int)sizeof(*se); unsigned int i; if (flag & BKE_BPATH_TRAVERSE_SKIP_MULTIFILE) { diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 1b91d3d869e..c8862870b92 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -776,8 +776,8 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } for (cam = main->camera.first; cam; cam = cam->id.next) { - cam->stereo.interocular_distance = 0.065; - cam->stereo.convergence_distance = 30.f * 0.065; + cam->stereo.interocular_distance = 0.065f; + cam->stereo.convergence_distance = 30.0f * 0.065f; } for (ima = main->image.first; ima; ima = ima->id.next) { diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp index ca4f5c38f36..39ffa42e03c 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp @@ -402,7 +402,7 @@ void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memo this->m_bTree->progress(this->m_bTree->prh, progress); char buf[128]; - BLI_snprintf(buf, sizeof(buf), "Compositing | Tile %d-%d", + BLI_snprintf(buf, sizeof(buf), "Compositing | Tile %u-%u", this->m_chunksFinished, this->m_numberOfChunks); this->m_bTree->stats_draw(this->m_bTree->sdh, buf); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 2de391c5163..529e5fcf756 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1289,7 +1289,7 @@ static bool view3d_localview_init( } if (rv3d->persp == RV3D_ORTHO) { - if (size < 0.0001) { + if (size < 0.0001f) { ok_dist = false; } } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 5750ba40afe..a5f247d7172 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3758,7 +3758,7 @@ static void createTransActionData(bContext *C, TransInfo *t) for (gpf_iter = gpl->frames.first; gpf_iter; gpf_iter = gpf->next) { if (gpf_iter->flag & GP_FRAME_SELECT) { if (FrameOnMouseSide(t->frame_side, (float)gpf_iter->framenum, cfra)) { - float val = fabs(gpf->framenum - gpf_iter->framenum); + float val = fabsf(gpf->framenum - gpf_iter->framenum); if (val < min) min = val; } @@ -3784,7 +3784,7 @@ static void createTransActionData(bContext *C, TransInfo *t) for (masklay_iter = masklay->splines_shapes.first; masklay_iter; masklay_iter = masklay_iter->next) { if (masklay_iter->flag & MASK_SHAPE_SELECT) { if (FrameOnMouseSide(t->frame_side, (float)masklay_iter->frame, cfra)) { - float val = fabs(masklay_shape->frame - masklay_iter->frame); + float val = fabsf(masklay_shape->frame - masklay_iter->frame); if (val < min) min = val; } diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index 82c1d6f2ec8..295f303974d 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -607,7 +607,7 @@ static void correctivesmooth_modifier_do( /* If the number of verts has changed, the bind is invalid, so we do nothing */ if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) { if (csmd->bind_coords_num != numVerts) { - modifier_setError(md, "Bind vertex count mismatch: %d to %d", csmd->bind_coords_num, numVerts); + modifier_setError(md, "Bind vertex count mismatch: %u to %u", csmd->bind_coords_num, numVerts); goto error; } } @@ -618,10 +618,10 @@ static void correctivesmooth_modifier_do( goto error; } else { - int me_numVerts = (em) ? em->bm->totvert : ((Mesh *)ob->data)->totvert; + unsigned int me_numVerts = (unsigned int)((em) ? em->bm->totvert : ((Mesh *)ob->data)->totvert); - if ((unsigned int)me_numVerts != numVerts) { - modifier_setError(md, "Original vertex count mismatch: %d to %d", me_numVerts, numVerts); + if (me_numVerts != numVerts) { + modifier_setError(md, "Original vertex count mismatch: %u to %u", me_numVerts, numVerts); goto error; } } diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp index e0ca945eaf7..9f6050527ef 100644 --- a/source/blender/physics/intern/BPH_mass_spring.cpp +++ b/source/blender/physics/intern/BPH_mass_spring.cpp @@ -140,7 +140,7 @@ static bool collision_response(ClothModifierData *clmd, CollisionModifierData *c float v1[3], v2_old[3], v2_new[3], v_rel_old[3], v_rel_new[3]; float epsilon2 = BLI_bvhtree_getepsilon(collmd->bvhtree); - float margin_distance = collpair->distance - epsilon2; + float margin_distance = (float)collpair->distance - epsilon2; float mag_v_rel; zero_v3(r_impulse); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index db3499b4180..24e66cbf3cb 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2248,9 +2248,9 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) for (x = 0; x < re->rectx; x++, rf += 4, col += 4) { /* clamping to 1.0 is needed for correct AA */ - CLAMP(col[0], 0.0, 1.0f); - CLAMP(col[1], 0.0, 1.0f); - CLAMP(col[2], 0.0, 1.0f); + CLAMP(col[0], 0.0f, 1.0f); + CLAMP(col[1], 0.0f, 1.0f); + CLAMP(col[2], 0.0f, 1.0f); add_filt_fmask_coord(filt, col, rf, re->rectx, re->recty, x, y); } -- cgit v1.2.3 From 6fb0563aee04fa94517745d6c2bcf093669fbf3e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 14 Apr 2015 15:24:32 +1000 Subject: BMesh: optimize BM_face_exists Avoid flagging/clearing flags, just walk over the face until a mismatch is found. --- source/blender/bmesh/intern/bmesh_queries.c | 114 +++++++++++----------------- 1 file changed, 44 insertions(+), 70 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 392f8b0bba2..4d3dd580ab3 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -1637,85 +1637,59 @@ BMEdge *BM_edge_find_double(BMEdge *e) */ bool BM_face_exists(BMVert **varr, int len, BMFace **r_existface) { - BMVert *v_search = varr[0]; /* we can search any of the verts in the array */ - BMIter liter; - BMLoop *l_search; - - -#if 0 - BM_ITER_ELEM (f, &viter, v_search, BM_FACES_OF_VERT) { - if (f->len == len) { - if (BM_verts_in_face(varr, len, f)) { - if (r_existface) { - *r_existface = f; - } - return true; - } - } - } - - if (r_existface) { - *r_existface = NULL; - } - return false; - -#else - - /* faster to do the flagging once, and inline */ - bool is_init = false; - bool is_found = false; - int i; - - - BM_ITER_ELEM (l_search, &liter, v_search, BM_LOOPS_OF_VERT) { - if (l_search->f->len == len) { - if (is_init == false) { - is_init = true; - for (i = 0; i < len; i++) { - BLI_assert(!BM_ELEM_API_FLAG_TEST(varr[i], _FLAG_OVERLAP)); - BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP); - } - } - - is_found = true; - - { - BMLoop *l_iter; + if (varr[0]->e) { + BMEdge *e_iter, *e_first; + e_iter = e_first = varr[0]->e; - /* skip ourselves */ - l_iter = l_search->next; + /* would normally use BM_LOOPS_OF_VERT, but this runs so often, + * its faster to iterate on the data directly */ + do { + if (e_iter->l) { + BMLoop *l_iter_radial, *l_first_radial; + l_iter_radial = l_first_radial = e_iter->l; do { - if (!BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) { - is_found = false; - break; + if ((l_iter_radial->v == varr[0]) && + (l_iter_radial->f->len == len)) + { + /* the fist 2 verts match, now check the remaining (len - 2) faces do too + * winding isn't known, so check in both directions */ + int i_walk = 2; + + if (l_iter_radial->next->v == varr[1]) { + BMLoop *l_walk = l_iter_radial->next->next; + do { + if (l_walk->v != varr[i_walk]) { + break; + } + } while ((l_walk = l_walk->next), ++i_walk != len); + } + else if (l_iter_radial->prev->v == varr[1]) { + BMLoop *l_walk = l_iter_radial->prev->prev; + do { + if (l_walk->v != varr[i_walk]) { + break; + } + } while ((l_walk = l_walk->prev), ++i_walk != len); + } + + if (i_walk == len) { + if (r_existface) { + *r_existface = l_iter_radial->f; + } + return true; + } } - } while ((l_iter = l_iter->next) != l_search); - } + } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial); - if (is_found) { - if (r_existface) { - *r_existface = l_search->f; - } - break; } - } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, varr[0])) != e_first); } - if (is_found == false) { - if (r_existface) { - *r_existface = NULL; - } - } - - if (is_init == true) { - for (i = 0; i < len; i++) { - BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP); - } + if (r_existface) { + *r_existface = NULL; } - - return is_found; -#endif + return false; } -- cgit v1.2.3 From d841b75c5f1e6de60bc57804204b73f2c3de4530 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 14 Apr 2015 15:27:27 +1000 Subject: BMesh: avoid redundant face-exists check (dyntopo) --- source/blender/blenkernel/intern/pbvh_bmesh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index f7edd34c70a..ce26df4ee3a 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -358,7 +358,7 @@ static BMFace *pbvh_bmesh_face_create( /* ensure we never add existing face */ BLI_assert(BM_face_exists(v_tri, 3, NULL) == false); - f = BM_face_create(bvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NOP); + f = BM_face_create(bvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NO_DOUBLE); f->head.hflag = f_example->head.hflag; BLI_gset_insert(node->bm_faces, f); -- cgit v1.2.3 From 097801e701cec7ae1e388d201ca3426153616097 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 12 Apr 2015 20:42:34 +1200 Subject: NLA: Shift-Tab toggles tweakmode AND makes that track solo To help make it more convenient to edit stashed actions, Shift-Tab (i.e. holding down the Shift key, which "tabbing" into tweakmode as usual to edit the action referenced by the active NLA strip) now flags the NLA Track that the strip occupies as being "solo" too. This allows you to use the NLA to select a stashed action, then Shift-Tab to start editing it without any other actions in the NLA stack interfering. Like the "Next/Previous Layer" tools in the Action Editor, this is designed to help with checking on stashed actions. --- release/scripts/startup/bl_ui/space_nla.py | 2 + source/blender/blenkernel/BKE_nla.h | 2 + source/blender/blenkernel/intern/nla.c | 34 +++++++++++++++++ source/blender/editors/space_action/action_data.c | 34 +---------------- source/blender/editors/space_nla/nla_channels.c | 4 +- source/blender/editors/space_nla/nla_edit.c | 46 ++++++++++++++++++++--- source/blender/editors/space_nla/nla_intern.h | 2 +- source/blender/editors/space_nla/nla_ops.c | 11 ++++++ 8 files changed, 96 insertions(+), 39 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py index ae432c44bf6..c083907f017 100644 --- a/release/scripts/startup/bl_ui/space_nla.py +++ b/release/scripts/startup/bl_ui/space_nla.py @@ -168,8 +168,10 @@ class NLA_MT_edit(Menu): layout.separator() # TODO: names of these tools for 'tweak-mode' need changing? if scene.is_nla_tweakmode: + layout.operator("nla.tweakmode_exit", text="Stop Editing Stashed Action").isolate_action = True layout.operator("nla.tweakmode_exit", text="Stop Tweaking Strip Actions") else: + layout.operator("nla.tweakmode_enter", text="Start Editing Stashed Action").isolate_action = True layout.operator("nla.tweakmode_enter", text="Start Tweaking Strip Actions") diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index c3fc29e811f..3bf8bba47f5 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -76,6 +76,8 @@ void BKE_nlameta_flush_transforms(struct NlaStrip *mstrip); struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks); void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt); +struct NlaTrack *BKE_nlatrack_find_tweaked(struct AnimData *adt); + void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt); bool BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index c87f378d5ae..eaa4460ce70 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -926,6 +926,40 @@ NlaTrack *BKE_nlatrack_find_active(ListBase *tracks) return NULL; } +/* Get the NLA Track that the active action/action strip comes from, + * since this info is not stored in AnimData. It also isn't as simple + * as just using the active track, since multiple tracks may have been + * entered at the same time. + */ +// TODO: Store this info in AnimData... Old files would still need to use this function for version patching though +NlaTrack *BKE_nlatrack_find_tweaked(AnimData *adt) +{ + NlaTrack *nlt; + + /* sanity check */ + if (adt == NULL) + return NULL; + + /* Since the track itself gets disabled, we want the first disabled... */ + for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { + if (nlt->flag & (NLATRACK_ACTIVE | NLATRACK_DISABLED)) { + /* For good measure, make sure that strip actually exists there */ + if (BLI_findindex(&nlt->strips, adt->actstrip) != -1) { + return nlt; + } + else if (G.debug & G_DEBUG) { + printf("%s: Active strip (%p, %s) not in NLA track found (%p, %s)\n", + __func__, + adt->actstrip, (adt->actstrip) ? adt->actstrip->name : "", + nlt, nlt->name); + } + } + } + + /* Not found! */ + return NULL; +} + /* Toggle the 'solo' setting for the given NLA-track, making sure that it is the only one * that has this status in its AnimData block. */ diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index 440201bd93e..11ccaee4146 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -625,36 +625,6 @@ void ACTION_OT_unlink(wmOperatorType *ot) /* ************************************************************************** */ /* ACTION BROWSING */ -/* Get the NLA Track that the active action comes from, since this is not stored in AnimData */ -/* TODO: Move this to blenkernel/nla.c */ -static NlaTrack *nla_tweak_track_get(AnimData *adt) -{ - NlaTrack *nlt; - - /* sanity check */ - if (adt == NULL) - return NULL; - - /* Since the track itself gets disabled, we want the first disabled... */ - for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { - if (nlt->flag & (NLATRACK_ACTIVE | NLATRACK_DISABLED)) { - /* For good measure, make sure that strip actually exists there */ - if (BLI_findindex(&nlt->strips, adt->actstrip) != -1) { - return nlt; - } - else if (G.debug & G_DEBUG) { - printf("%s: Active strip (%p, %s) not in NLA track found (%p, %s)\n", - __func__, - adt->actstrip, (adt->actstrip) ? adt->actstrip->name : "", - nlt, nlt->name); - } - } - } - - /* Not found! */ - return NULL; -} - /* Try to find NLA Strip to use for action layer up/down tool */ static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime) { @@ -774,7 +744,7 @@ static int action_layer_next_exec(bContext *C, wmOperator *op) float ctime = BKE_scene_frame_get(scene); /* Get active track */ - act_track = nla_tweak_track_get(adt); + act_track = BKE_nlatrack_find_tweaked(adt); if (act_track == NULL) { BKE_report(op->reports, RPT_ERROR, "Could not find current NLA Track"); @@ -891,7 +861,7 @@ static int action_layer_prev_exec(bContext *C, wmOperator *op) } /* Get active track */ - act_track = nla_tweak_track_get(adt); + act_track = BKE_nlatrack_find_tweaked(adt); /* If there is no active track, that means we are using the active action... */ if (act_track) { diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 4ed4a3f9514..32a8e660f66 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -291,10 +291,12 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe * the case of users trying to use this to change actions * - in tweakmode, clicking here gets us out of tweakmode, as changing selection * while in tweakmode is really evil! + * - we disable "solo" flags too, to make it easier to work with stashed actions + * with less trouble */ if (nlaedit_is_tweakmode_on(ac)) { /* exit tweakmode immediately */ - nlaedit_disable_tweakmode(ac); + nlaedit_disable_tweakmode(ac, true); /* changes to NLA-Action occurred */ notifierFlags |= ND_NLA_ACTCHANGE; diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 9ae96292f52..19e6f5a8100 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -111,6 +111,8 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op) ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; + + const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action"); bool ok = false; /* get editor data */ @@ -133,6 +135,15 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op) /* try entering tweakmode if valid */ ok |= BKE_nla_tweakmode_enter(adt); + + /* mark the active track as being "solo"? */ + if (do_solo && adt->actstrip) { + NlaTrack *nlt = BKE_nlatrack_find_tweaked(adt); + + if (nlt && !(nlt->flag & NLATRACK_SOLO)) { + BKE_nlatrack_solo_toggle(adt, nlt); + } + } } /* free temp data */ @@ -159,6 +170,8 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op) void NLA_OT_tweakmode_enter(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Enter Tweak Mode"; ot->idname = "NLA_OT_tweakmode_enter"; @@ -170,16 +183,22 @@ void NLA_OT_tweakmode_enter(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_boolean(ot->srna, "isolate_action", 0, "Isolate Action", + "Enable 'solo' on the NLA Track containing the active strip, " + "to edit it without seeing the effects of the NLA stack"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ------------- */ /* NLA Editor internal API function for exiting tweakmode */ -bool nlaedit_disable_tweakmode(bAnimContext *ac) +bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; - int filter; + int filter; /* get a list of the AnimData blocks being shown in the NLA */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA); @@ -195,7 +214,14 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac) for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ale->data; - /* to be sure, just exit tweakmode... */ + /* clear solo flags */ + if ((do_solo) & (adt->flag & ADT_NLA_SOLO_TRACK) && + (adt->flag & ADT_NLA_EDIT_ON)) + { + BKE_nlatrack_solo_toggle(adt, NULL); + } + + /* to be sure that we're doing everything right, just exit tweakmode... */ BKE_nla_tweakmode_exit(adt); } @@ -218,9 +244,11 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac) } /* exit tweakmode operator callback */ -static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *UNUSED(op)) +static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *op) { bAnimContext ac; + + const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action"); bool ok = false; /* get editor data */ @@ -228,7 +256,7 @@ static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; /* perform operation */ - ok = nlaedit_disable_tweakmode(&ac); + ok = nlaedit_disable_tweakmode(&ac, do_solo); /* success? */ if (ok) @@ -239,6 +267,8 @@ static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *UNUSED(op)) void NLA_OT_tweakmode_exit(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Exit Tweak Mode"; ot->idname = "NLA_OT_tweakmode_exit"; @@ -250,6 +280,12 @@ void NLA_OT_tweakmode_exit(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_boolean(ot->srna, "isolate_action", 0, "Isolate Action", + "Disable 'solo' on any of the NLA Tracks after exiting tweak mode " + "to get things back to normal"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 70fdb2d478d..344580c0d15 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -83,7 +83,7 @@ enum eNlaEdit_Snap_Mode { /* --- */ -bool nlaedit_disable_tweakmode(bAnimContext *ac); +bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo); void NLA_OT_tweakmode_enter(wmOperatorType *ot); void NLA_OT_tweakmode_exit(wmOperatorType *ot); diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 43bc4b9df0f..98da10470f8 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -306,6 +306,7 @@ static void nla_keymap_main(wmKeyConfig *keyconf, wmKeyMap *keymap) void nla_keymap(wmKeyConfig *keyconf) { wmKeyMap *keymap; + wmKeyMapItem *kmi; /* keymap for all regions ------------------------------------------- */ keymap = WM_keymap_find(keyconf, "NLA Generic", SPACE_NLA, 0); @@ -320,6 +321,16 @@ void nla_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "NLA_OT_tweakmode_enter", TABKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NLA_OT_tweakmode_exit", TABKEY, KM_PRESS, 0, 0); + /* tweakmode for stashed actions + * - similar to normal tweakmode, except we mark the tracks as being "solo" + * too so that the action can be edited in isolation + */ + kmi = WM_keymap_add_item(keymap, "NLA_OT_tweakmode_enter", TABKEY, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "isolate_action", true); + + kmi = WM_keymap_add_item(keymap, "NLA_OT_tweakmode_exit", TABKEY, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "isolate_action", true); + /* find (i.e. a shortcut for setting the name filter) */ WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0); -- cgit v1.2.3 From 5361339ba0590abe2220a65efa53ca48b2813974 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 14 Apr 2015 16:48:34 +1200 Subject: Temporary fix for NLA strips not getting drawn in tweakmode with multiple strips selected When entering tweakmode on multiple strips (from different AnimData blocks) simultaneously, only the track containing the last selected strip would be shown. All the other tracks with strips being tweaked would not appear at all. --- source/blender/editors/animation/anim_filter.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index ee662c46fd0..25f2b0b43af 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1301,8 +1301,22 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop * - active track should still get shown though (even though it has disabled flag set) */ // FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel - if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED) && !(nlt->flag & NLATRACK_ACTIVE)) - continue; + if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED)) { + /* NOTE: The tweaking track may not be active, if strips from different AnimData blocks + * entered tweakmode at the same time. Since this loop works both ways, we can't + * just stop on the first disabled track we encounter... + */ + if (nlt->flag & NLATRACK_ACTIVE) { + /* OK = "the" active track */ + } + else if (BLI_findindex(&nlt->strips, adt->actstrip) != -1) { + /* OK = this is the one containing the active strip */ + } + else { + /* Not OK - neither of the previous two were met, so it must be one of the "later" ones */ + continue; + } + } /* only work with this channel and its subchannels if it is editable */ if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) { -- cgit v1.2.3 From c95f38b92aa2981a771c4a4c010270547becec26 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 14 Apr 2015 16:51:20 +1200 Subject: Fix for another NLA drawing bug uncovered by the previous commit With multiple strips in tweakmode, only the one tagged as being "active" would get drawn in the correct colours, while all the others would just get drawn as a selected strip instead. --- source/blender/editors/space_nla/nla_draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 5d9a77c8576..52156a2394e 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -186,7 +186,7 @@ static void nla_strip_get_color_inside(AnimData *adt, NlaStrip *strip, float col } else { /* Action Clip (default/normal type of strip) */ - if ((strip->flag & NLASTRIP_FLAG_ACTIVE) && (adt && (adt->flag & ADT_NLA_EDIT_ON))) { + if (adt && (adt->flag & ADT_NLA_EDIT_ON) && (adt->actstrip == strip)) { /* active strip should be drawn green when it is acting as the tweaking strip. * however, this case should be skipped for when not in EditMode... */ -- cgit v1.2.3 From bb1bc7ecda28cc3c70992f8383151e4055a227e0 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 14 Apr 2015 17:10:04 +1200 Subject: NLA: Store track that the strip being tweaked comes from There should be no functional changes visible from this change, but this commit should make it easier to code tools which need to check on tweeakmode status, by making it easier to figure out which NLA Track contains the strip which owned the action being edited. (The strip is already saved, so this commit just adds the track alongside it). For now there is no version patch for this. The worst that happens is that an extra refresh is needed in the NLA editor to get these to show up. --- source/blender/blenkernel/intern/nla.c | 12 +++++++++--- source/blender/blenloader/intern/readfile.c | 3 ++- source/blender/editors/animation/anim_filter.c | 18 ++---------------- source/blender/makesdna/DNA_anim_types.h | 2 ++ 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index eaa4460ce70..650efea2e96 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -535,9 +535,14 @@ float BKE_nla_tweakedit_remap(AnimData *adt, float cframe, short mode) /* if the active-strip info has been stored already, access this, otherwise look this up * and store for (very probable) future usage */ + if (adt->act_track == NULL) { + if (adt->actstrip) + adt->act_track = BKE_nlatrack_find_tweaked(adt); + else + adt->act_track = BKE_nlatrack_find_active(&adt->nla_tracks); + } if (adt->actstrip == NULL) { - NlaTrack *nlt = BKE_nlatrack_find_active(&adt->nla_tracks); - adt->actstrip = BKE_nlastrip_find_active(nlt); + adt->actstrip = BKE_nlastrip_find_active(adt->act_track); } strip = adt->actstrip; @@ -931,7 +936,6 @@ NlaTrack *BKE_nlatrack_find_active(ListBase *tracks) * as just using the active track, since multiple tracks may have been * entered at the same time. */ -// TODO: Store this info in AnimData... Old files would still need to use this function for version patching though NlaTrack *BKE_nlatrack_find_tweaked(AnimData *adt) { NlaTrack *nlt; @@ -1796,6 +1800,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt) */ adt->tmpact = adt->action; adt->action = activeStrip->act; + adt->act_track = activeTrack; adt->actstrip = activeStrip; id_us_plus(&activeStrip->act->id); adt->flag |= ADT_NLA_EDIT_ON; @@ -1855,6 +1860,7 @@ void BKE_nla_tweakmode_exit(AnimData *adt) if (adt->action) adt->action->id.us--; adt->action = adt->tmpact; adt->tmpact = NULL; + adt->act_track = NULL; adt->actstrip = NULL; adt->flag &= ~ADT_NLA_EDIT_ON; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9a269cad756..9dd5245dcbf 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2431,12 +2431,13 @@ static void direct_link_animdata(FileData *fd, AnimData *adt) link_list(fd, &adt->nla_tracks); direct_link_nladata(fd, &adt->nla_tracks); - /* relink active strip - even though strictly speaking this should only be used + /* relink active track/strip - even though strictly speaking this should only be used * if we're in 'tweaking mode', we need to be able to have this loaded back for * undo, but also since users may not exit tweakmode before saving (#24535) */ // TODO: it's not really nice that anyone should be able to save the file in this // state, but it's going to be too hard to enforce this single case... + adt->act_track = newdataadr(fd, adt->act_track); adt->actstrip = newdataadr(fd, adt->actstrip); } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 25f2b0b43af..f575326083a 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1301,22 +1301,8 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop * - active track should still get shown though (even though it has disabled flag set) */ // FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel - if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED)) { - /* NOTE: The tweaking track may not be active, if strips from different AnimData blocks - * entered tweakmode at the same time. Since this loop works both ways, we can't - * just stop on the first disabled track we encounter... - */ - if (nlt->flag & NLATRACK_ACTIVE) { - /* OK = "the" active track */ - } - else if (BLI_findindex(&nlt->strips, adt->actstrip) != -1) { - /* OK = this is the one containing the active strip */ - } - else { - /* Not OK - neither of the previous two were met, so it must be one of the "later" ones */ - continue; - } - } + if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED) && (adt->act_track != nlt)) + continue; /* only work with this channel and its subchannels if it is editable */ if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) { diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index 693e0fc1293..68f80cb27d8 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -853,6 +853,8 @@ typedef struct AnimData { /* nla-tracks */ ListBase nla_tracks; + /* active NLA-track (only set/used during tweaking, so no need to worry about dangling pointers) */ + NlaTrack *act_track; /* active NLA-strip (only set/used during tweaking, so no need to worry about dangling pointers) */ NlaStrip *actstrip; -- cgit v1.2.3 From 1e488802dc866c919a421a1c33d2b1c459096459 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 14 Apr 2015 18:27:05 +1200 Subject: NLA: The "filter by name" functionality now works with NLA strips too --- release/scripts/startup/bl_ui/space_dopesheet.py | 5 +++++ source/blender/editors/animation/anim_filter.c | 24 ++++++++++++++++++++++++ source/blender/makesrna/intern/rna_action.c | 13 +++++++++++++ 3 files changed, 42 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 13c37182ae4..0b7502b585b 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -51,6 +51,11 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False): row.prop(dopesheet, "show_only_matching_fcurves", text="") if dopesheet.show_only_matching_fcurves: row.prop(dopesheet, "filter_fcurve_name", text="") + else: + row = layout.row(align=True) + row.prop(dopesheet, "use_filter_text", text="") + if dopesheet.use_filter_text: + row.prop(dopesheet, "filter_text", text="") if not genericFiltersOnly: row = layout.row(align=True) diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index f575326083a..8c598d4bb13 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1310,6 +1310,30 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop if (ANIMCHANNEL_SELOK(SEL_NLT(nlt))) { /* only include if this track is active */ if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) { + /* name based filtering... */ + if (((ads) && (ads->filterflag & ADS_FILTER_BY_FCU_NAME)) && (owner_id)) { + bool track_ok = false, strip_ok = false; + + /* check if the name of the track, or the strips it has are ok... */ + track_ok = BLI_strcasestr(nlt->name, ads->searchstr); + + if (track_ok == false) { + NlaStrip *strip; + for (strip = nlt->strips.first; strip; strip = strip->next) { + if (BLI_strcasestr(strip->name, ads->searchstr)) { + strip_ok = true; + break; + } + } + } + + /* skip if both fail this test... */ + if (!track_ok && !strip_ok) { + continue; + } + } + + /* add the track now that it has passed all our tests */ ANIMCHANNEL_NEW_CHANNEL(nlt, ANIMTYPE_NLATRACK, owner_id); } } diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 3fed505b9d6..0cf2c8800c1 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -331,6 +331,19 @@ static void rna_def_dopesheet(BlenderRNA *brna) RNA_def_property_ui_text(prop, "F-Curve Name Filter", "F-Curve live filtering string"); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + /* NLA Name Search Settings (Shared with FCurve setting, but with different labels) */ + prop = RNA_def_property(srna, "use_filter_text", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_BY_FCU_NAME); + RNA_def_property_ui_text(prop, "Only Matching Channels", + "Only include channels with names containing search text"); + RNA_def_property_ui_icon(prop, ICON_VIEWZOOM, 0); + RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + + prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "searchstr"); + RNA_def_property_ui_text(prop, "Name Filter", "Live filtering string"); + RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + /* NLA Specific Settings */ prop = RNA_def_property(srna, "show_missing_nla", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NLA_NOACT); -- cgit v1.2.3 From 34d4ad326cdaf9cf90ac6efbea52ba9d62eac594 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 14 Apr 2015 18:50:15 +1200 Subject: Animation Editors: Name filter now updates as you type, making it a true "live search" --- source/blender/makesrna/intern/rna_action.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 0cf2c8800c1..29e699a57b2 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -329,6 +329,7 @@ static void rna_def_dopesheet(BlenderRNA *brna) prop = RNA_def_property(srna, "filter_fcurve_name", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "searchstr"); RNA_def_property_ui_text(prop, "F-Curve Name Filter", "F-Curve live filtering string"); + RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); /* NLA Name Search Settings (Shared with FCurve setting, but with different labels) */ @@ -342,6 +343,7 @@ static void rna_def_dopesheet(BlenderRNA *brna) prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "searchstr"); RNA_def_property_ui_text(prop, "Name Filter", "Live filtering string"); + RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); /* NLA Specific Settings */ -- cgit v1.2.3 From 8486ee39bd689f8659cf90cc6942560225de7527 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 14 Apr 2015 16:02:38 +1000 Subject: PBVH: use realloc/recalloc --- source/blender/blenkernel/intern/pbvh.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 5e07437d426..c9e632b7295 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -232,16 +232,11 @@ static int partition_indices_material(PBVH *bvh, int lo, int hi) void pbvh_grow_nodes(PBVH *bvh, int totnode) { - if (totnode > bvh->node_mem_count) { - PBVHNode *prev = bvh->nodes; - bvh->node_mem_count *= 1.33; + if (UNLIKELY(totnode > bvh->node_mem_count)) { + bvh->node_mem_count = bvh->node_mem_count + (bvh->node_mem_count / 3); if (bvh->node_mem_count < totnode) bvh->node_mem_count = totnode; - bvh->nodes = MEM_mallocN(sizeof(PBVHNode) * bvh->node_mem_count, - "bvh nodes"); - memcpy(bvh->nodes, prev, bvh->totnode * sizeof(PBVHNode)); - memset(bvh->nodes + bvh->totnode, 0, (bvh->node_mem_count - bvh->totnode) * sizeof(PBVHNode)); - MEM_freeN(prev); + bvh->nodes = MEM_recallocN(bvh->nodes, sizeof(PBVHNode) * bvh->node_mem_count); } bvh->totnode = totnode; @@ -699,16 +694,16 @@ static void pbvh_iter_end(PBVHIter *iter) static void pbvh_stack_push(PBVHIter *iter, PBVHNode *node, int revisiting) { - if (iter->stacksize == iter->stackspace) { - PBVHStack *newstack; - + if (UNLIKELY(iter->stacksize == iter->stackspace)) { iter->stackspace *= 2; - newstack = MEM_callocN(sizeof(PBVHStack) * iter->stackspace, "PBVHStack"); - memcpy(newstack, iter->stack, sizeof(PBVHStack) * iter->stacksize); - if (iter->stackspace > STACK_FIXED_DEPTH) - MEM_freeN(iter->stack); - iter->stack = newstack; + if (iter->stackspace != STACK_FIXED_DEPTH) { + iter->stack = MEM_reallocN(iter->stack, sizeof(PBVHStack) * iter->stackspace); + } + else { + iter->stack = MEM_mallocN(sizeof(PBVHStack) * iter->stackspace, "PBVHStack"); + memcpy(iter->stack, iter->stackfixed, sizeof(PBVHStack) * iter->stacksize); + } } iter->stack[iter->stacksize].node = node; @@ -800,7 +795,7 @@ void BKE_pbvh_search_gather(PBVH *bvh, while ((node = pbvh_iter_next(&iter))) { if (node->flag & PBVH_Leaf) { - if (tot == space) { + if (UNLIKELY(tot == space)) { /* resize array if needed */ space = (tot == 0) ? 32 : space * 2; array = MEM_recallocN_id(array, sizeof(PBVHNode *) * space, __func__); -- cgit v1.2.3 From 825b015e9218810ae2011df6cf4b67920ad9295d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 14 Apr 2015 13:24:17 +0500 Subject: Fix T44348: Blender crashes when selecting bone from inactive scene in outliner Pose is not guaranteed to be existing in object, so can't be used for selection flag clear. Use bones themselves for that. --- source/blender/editors/space_outliner/outliner_select.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 6050b66fdb7..e52c68b57e9 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -554,10 +554,12 @@ static eOLDrawState tree_element_active_bone( Object *ob = OBACT; if (ob) { if (set != OL_SETSEL_EXTEND) { - bPoseChannel *pchannel; /* single select forces all other bones to get unselected */ - for (pchannel = ob->pose->chanbase.first; pchannel; pchannel = pchannel->next) - pchannel->bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL); + Bone *bone; + for (bone = arm->bonebase.first; bone != NULL; bone = bone->next) { + bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL); + do_outliner_bone_select_recursive(arm, bone, false); + } } } -- cgit v1.2.3 From d36429b9307db13628701831cf84d2f3fb147ab0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 14 Apr 2015 18:24:40 +1000 Subject: initialize members in-order --- source/blender/blenlib/intern/BLI_heap.c | 2 +- source/blender/bmesh/intern/bmesh_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c index 66dfa87b7b9..c0f338a1918 100644 --- a/source/blender/blenlib/intern/BLI_heap.c +++ b/source/blender/blenlib/intern/BLI_heap.c @@ -183,8 +183,8 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr) node = (HeapNode *)BLI_memarena_alloc(heap->arena, sizeof(*node)); } - node->value = value; node->ptr = ptr; + node->value = value; node->index = heap->size; heap->tree[node->index] = node; diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index ad35f6e0472..dc5e5a5a13c 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -213,8 +213,8 @@ static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, BM_elem_index_set(l, -1); /* set_ok_invalid */ #endif - l->head.hflag = 0; l->head.htype = BM_LOOP; + l->head.hflag = 0; l->head.api_flag = 0; l->v = v; -- cgit v1.2.3 From 7daa921359a182e00a6bba5b654ace41f26033a2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 14 Apr 2015 18:32:10 +1000 Subject: BMesh: avoid customdata copy for new dyntopo verts --- source/blender/blenkernel/intern/pbvh_bmesh.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index ce26df4ee3a..b6e5fcfb405 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -331,11 +331,15 @@ static BMVert *pbvh_bmesh_vert_create( const BMVert *example, const int cd_vert_mask_offset) { - BMVert *v = BM_vert_create(bvh->bm, co, example, BM_CREATE_NOP); PBVHNode *node = &bvh->nodes[node_index]; + BMVert *v; BLI_assert((bvh->totnode == 1 || node_index) && node_index <= bvh->totnode); + /* avoid initializing customdata because its quite involved */ + v = BM_vert_create(bvh->bm, co, example, BM_CREATE_SKIP_CD); + CustomData_bmesh_set_default(&bvh->bm->vdata, &v->head.data); + BLI_gset_insert(node->bm_unique_verts, v); BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, node_index); @@ -1167,14 +1171,14 @@ static bool pbvh_bmesh_collapse_short_edges( continue; } - if (len_squared_v3v3(v1->co, v2->co) >= min_len_squared) - continue; - /* Check that the edge still exists */ if (!(e = BM_edge_exists(v1, v2))) { continue; } + if (len_squared_v3v3(v1->co, v2->co) >= min_len_squared) + continue; + /* Check that the edge's vertices are still in the PBVH. It's * possible that an edge collapse has deleted adjacent faces * and the node has been split, thus leaving wire edges and -- cgit v1.2.3 From 68eeeea57e0e9408c096f2555054cfbdda9ae7ae Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 14 Apr 2015 18:39:40 +1000 Subject: Dyntopo queue added the same edges multiple times Use tagging to avoid re-evaluating the same edges while sculpting. While gives only minor speedup, it allows for changes to the queue without additional redundant checks. --- source/blender/blenkernel/intern/pbvh_bmesh.c | 108 ++++++++++++++++++++------ 1 file changed, 84 insertions(+), 24 deletions(-) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index b6e5fcfb405..86c430d1785 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -47,6 +47,9 @@ # include "BKE_global.h" #endif +/* don't add edges into the queue multiple times */ +#define USE_EDGEQUEUE_TAG + // #define USE_VERIFY #ifdef USE_VERIFY @@ -594,6 +597,13 @@ typedef struct { int cd_face_node_offset; } EdgeQueueContext; +/* only tag'd edges are in the queue */ +#ifdef USE_EDGEQUEUE_TAG +# define EDGE_QUEUE_TEST(e) (BM_elem_flag_test((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG)) +# define EDGE_QUEUE_ENABLE(e) BM_elem_flag_enable((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG) +# define EDGE_QUEUE_DISABLE(e) BM_elem_flag_disable((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG) +#endif + static bool edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f) { BMVert *v_tri[3]; @@ -635,15 +645,25 @@ static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e, pair[0] = e->v1; pair[1] = e->v2; BLI_heap_insert(eq_ctx->q->heap, priority, pair); +#ifdef USE_EDGEQUEUE_TAG + BLI_assert(EDGE_QUEUE_TEST(e) == false); + EDGE_QUEUE_ENABLE(e); +#endif } } static void long_edge_queue_edge_add(EdgeQueueContext *eq_ctx, BMEdge *e) { - const float len_sq = BM_edge_calc_length_squared(e); - if (len_sq > eq_ctx->q->limit_len_squared) - edge_queue_insert(eq_ctx, e, -len_sq); +#ifdef USE_EDGEQUEUE_TAG + if (EDGE_QUEUE_TEST(e) == false) +#endif + { + const float len_sq = BM_edge_calc_length_squared(e); + if (len_sq > eq_ctx->q->limit_len_squared) { + edge_queue_insert(eq_ctx, e, -len_sq); + } + } } #ifdef USE_EDGEQUEUE_EVEN_SUBDIV @@ -681,12 +701,17 @@ static void long_edge_queue_edge_add_recursive( BMLoop *l_adjacent[2] = {l_iter->next, l_iter->prev}; int i; for (i = 0; i < ARRAY_SIZE(l_adjacent); i++) { - len_sq_other = BM_edge_calc_length_squared(l_adjacent[i]->e); - if (len_sq_other > max_ff(len_sq_cmp, limit_len_sq)) { -// edge_queue_insert(eq_ctx, l_adjacent[i]->e, -len_sq_other); - long_edge_queue_edge_add_recursive( - eq_ctx, l_adjacent[i]->radial_next, l_adjacent[i], - len_sq_other, limit_len); +#ifdef USE_EDGEQUEUE_TAG + if (EDGE_QUEUE_TEST(l_adjacent[i]->e) == false) +#endif + { + len_sq_other = BM_edge_calc_length_squared(l_adjacent[i]->e); + if (len_sq_other > max_ff(len_sq_cmp, limit_len_sq)) { +// edge_queue_insert(eq_ctx, l_adjacent[i]->e, -len_sq_other); + long_edge_queue_edge_add_recursive( + eq_ctx, l_adjacent[i]->radial_next, l_adjacent[i], + len_sq_other, limit_len); + } } } } while ((l_iter = l_iter->radial_next) != l_end); @@ -700,9 +725,15 @@ static void long_edge_queue_edge_add_recursive( static void short_edge_queue_edge_add(EdgeQueueContext *eq_ctx, BMEdge *e) { - const float len_sq = BM_edge_calc_length_squared(e); - if (len_sq < eq_ctx->q->limit_len_squared) - edge_queue_insert(eq_ctx, e, len_sq); +#ifdef USE_EDGEQUEUE_TAG + if (EDGE_QUEUE_TEST(e) == false) +#endif + { + const float len_sq = BM_edge_calc_length_squared(e); + if (len_sq < eq_ctx->q->limit_len_squared) { + edge_queue_insert(eq_ctx, e, len_sq); + } + } } static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, @@ -715,16 +746,21 @@ static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, /* Check each edge of the face */ l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { +#ifdef USE_EDGEQUEUE_TAG + if (EDGE_QUEUE_TEST(l_iter->e) == false) +#endif + { #ifdef USE_EDGEQUEUE_EVEN_SUBDIV - const float len_sq = BM_edge_calc_length_squared(l_iter->e); - if (len_sq > eq_ctx->q->limit_len_squared) { - long_edge_queue_edge_add_recursive( - eq_ctx, l_iter->radial_next, l_iter, - len_sq, eq_ctx->q->limit_len_squared); - } + const float len_sq = BM_edge_calc_length_squared(l_iter->e); + if (len_sq > eq_ctx->q->limit_len_squared) { + long_edge_queue_edge_add_recursive( + eq_ctx, l_iter->radial_next, l_iter, + len_sq, eq_ctx->q->limit_len_squared); + } #else - long_edge_queue_edge_add(eq_ctx, l_iter->e); + long_edge_queue_edge_add(eq_ctx, l_iter->e); #endif + } } while ((l_iter = l_iter->next) != l_first); } } @@ -959,6 +995,12 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh, { bool any_subdivided = false; +#if defined(USE_EDGEQUEUE_TAG) && !defined(NDEBUG) +# define USE_EDGEQUEUE_TAG_VALIDATE + int heap_tot = 0, heap_overlap = 0; +#endif + + while (!BLI_heap_is_empty(eq_ctx->q->heap)) { BMVert **pair = BLI_heap_popmin(eq_ctx->q->heap); BMVert *v1 = pair[0], *v2 = pair[1]; @@ -967,6 +1009,21 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh, BLI_mempool_free(eq_ctx->pool, pair); pair = NULL; +#ifdef USE_EDGEQUEUE_TAG_VALIDATE + heap_tot += 1; +#endif + + /* Check that the edge still exists */ + if (!(e = BM_edge_exists(v1, v2))) { +#ifdef USE_EDGEQUEUE_TAG_VALIDATE + heap_overlap += 1; +#endif + continue; + } +#ifdef USE_EDGEQUEUE_TAG + EDGE_QUEUE_DISABLE(e); +#endif + /* At the moment edges never get shorter (subdiv will make new edges) * unlike collapse where edges can become longer. */ #if 0 @@ -976,11 +1033,6 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh, BLI_assert(len_squared_v3v3(v1->co, v2->co) > eq_ctx->q->limit_len_squared); #endif - /* Check that the edge still exists */ - if (!(e = BM_edge_exists(v1, v2))) { - continue; - } - /* Check that the edge's vertices are still in the PBVH. It's * possible that an edge collapse has deleted adjacent faces * and the node has been split, thus leaving wire edges and @@ -996,6 +1048,11 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh, pbvh_bmesh_split_edge(eq_ctx, bvh, e, edge_loops); } +#ifdef USE_EDGEQUEUE_TAG_VALIDATE + // printf("%d %d\n", heap_total, heap_overlap); + BLI_assert(heap_overlap == 0); +#undef USE_EDGEQUEUE_TAG_VALIDATE +#endif return any_subdivided; } @@ -1175,6 +1232,9 @@ static bool pbvh_bmesh_collapse_short_edges( if (!(e = BM_edge_exists(v1, v2))) { continue; } +#ifdef USE_EDGEQUEUE_TAG + EDGE_QUEUE_DISABLE(e); +#endif if (len_squared_v3v3(v1->co, v2->co) >= min_len_squared) continue; -- cgit v1.2.3 From ed40d5eaa79972486f743de04e11fb64f4af0049 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 14 Apr 2015 12:11:24 +0200 Subject: Add flag that prevents editing of markers. Can be located in marker menu. When active, all editing operators for markers will not fire up. --- release/scripts/startup/bl_ui/space_time.py | 4 ++++ source/blender/editors/animation/anim_markers.c | 32 +++++++++++++++++++++---- source/blender/makesdna/DNA_scene_types.h | 3 ++- source/blender/makesrna/intern/rna_scene.c | 4 ++++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py index 819c2af4200..2a3bcfc01ba 100644 --- a/release/scripts/startup/bl_ui/space_time.py +++ b/release/scripts/startup/bl_ui/space_time.py @@ -254,6 +254,10 @@ def marker_menu_generic(layout): layout.operator("screen.marker_jump", text="Jump to Next Marker").next = True layout.operator("screen.marker_jump", text="Jump to Previous Marker").next = False + layout.separator() + ts = bpy.context.tool_settings + layout.prop(ts, "marker_lock") + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 68660740ac7..ac6a0aede17 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -499,6 +499,23 @@ static int ed_markers_poll_selected_markers(bContext *C) return ED_markers_get_first_selected(markers) != NULL; } +static int ed_markers_poll_selected_no_locked_markers(bContext *C) +{ + ListBase *markers = ED_context_get_markers(C); + ToolSettings *ts = CTX_data_tool_settings(C); + + if (ts->marker_lock) + return 0; + + /* first things first: markers can only exist in timeline views */ + if (ED_operator_animview_active(C) == 0) + return 0; + + /* check if some marker is selected */ + return ED_markers_get_first_selected(markers) != NULL; +} + + /* special poll() which checks if there are any markers at all first */ static int ed_markers_poll_markers_exist(bContext *C) { @@ -941,7 +958,7 @@ static void MARKER_OT_move(wmOperatorType *ot) ot->exec = ed_marker_move_exec; ot->invoke = ed_marker_move_invoke_wrapper; ot->modal = ed_marker_move_modal; - ot->poll = ed_markers_poll_selected_markers; + ot->poll = ed_markers_poll_selected_no_locked_markers; ot->cancel = ed_marker_move_cancel; /* flags */ @@ -1034,7 +1051,7 @@ static void MARKER_OT_duplicate(wmOperatorType *ot) ot->exec = ed_marker_duplicate_exec; ot->invoke = ed_marker_duplicate_invoke_wrapper; ot->modal = ed_marker_move_modal; - ot->poll = ed_markers_poll_selected_markers; + ot->poll = ed_markers_poll_selected_no_locked_markers; ot->cancel = ed_marker_move_cancel; /* flags */ @@ -1364,7 +1381,7 @@ static void MARKER_OT_delete(wmOperatorType *ot) /* api callbacks */ ot->invoke = ed_marker_delete_invoke_wrapper; ot->exec = ed_marker_delete_exec; - ot->poll = ed_markers_poll_selected_markers; + ot->poll = ed_markers_poll_selected_no_locked_markers; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1412,7 +1429,7 @@ static void MARKER_OT_rename(wmOperatorType *ot) /* api callbacks */ ot->invoke = ed_marker_rename_invoke_wrapper; ot->exec = ed_marker_rename_exec; - ot->poll = ed_markers_poll_selected_markers; + ot->poll = ed_markers_poll_selected_no_locked_markers; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1440,6 +1457,11 @@ static int ed_marker_make_links_scene_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + if (scene_to->toolsettings->marker_lock) { + BKE_report(op->reports, RPT_ERROR, "Target scene has locked markers"); + return OPERATOR_CANCELLED; + } + /* copy markers */ for (marker = markers->first; marker; marker = marker->next) { if (marker->flag & SELECT) { @@ -1521,7 +1543,7 @@ static void MARKER_OT_camera_bind(wmOperatorType *ot) /* api callbacks */ ot->exec = ed_marker_camera_bind_exec; ot->invoke = ed_markers_opwrap_invoke; - ot->poll = ed_markers_poll_selected_markers; + ot->poll = ed_markers_poll_selected_no_locked_markers; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 2f54dfa8116..e03d77d4ec5 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1272,7 +1272,8 @@ typedef struct ToolSettings { char proportional_mask; /* proportional edit, mask editing */ char proportional_action; /* proportional edit, action editor */ char proportional_fcurve; /* proportional edit, graph editor */ - char pad4[6]; + char marker_lock; /* lock marker editing */ + char pad4[5]; char auto_normalize; /*auto normalizing mode in wpaint*/ char multipaint; /* paint multiple bones in wpaint */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index ee77bccc340..a17a746945c 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2180,6 +2180,10 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + prop = RNA_def_property(srna, "marker_lock", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "marker_lock", 0); + RNA_def_property_ui_text(prop, "Lock Markers", "Prevent marker editing"); + prop = RNA_def_property(srna, "proportional_edit_falloff", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "prop_mode"); RNA_def_property_enum_items(prop, proportional_falloff_items); -- cgit v1.2.3 From 04daaee0fd0153783653df185286e34dd8684e6f Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 14 Apr 2015 12:31:23 +0200 Subject: Fix T44385 SSAO inverted with new Intel drivers. Intel has decided to fix this for newer devices and drivers only, so we can't really avoid keeping a list of buggy drivers here. --- source/blender/gpu/intern/gpu_extensions.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index e8595ecc67c..0d735d11902 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -263,7 +263,8 @@ void gpu_extensions_init(void) GG.dfdyfactors[0] = 1.0; GG.dfdyfactors[1] = -1.0; } - else if (GG.device == GPU_DEVICE_INTEL && GG.os == GPU_OS_WIN) { + else if (GG.device == GPU_DEVICE_INTEL && GG.os == GPU_OS_WIN && + (strstr(version, "4.0.0 - Build 9.18.10.3165"))) { GG.dfdyfactors[0] = -1.0; GG.dfdyfactors[1] = 1.0; } -- cgit v1.2.3 From f1e1ec2d8d43034ae36a5143ee57ce58756f115c Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 15 Apr 2015 01:18:45 +1200 Subject: Action Editor: Make the warning on unlinking actions a bit less intrusive venomgfx was complaining that having it do the popup everytime was too intrusive, so demoting it to just showing the warning in the header. --- source/blender/editors/space_action/action_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index 11ccaee4146..6e3e456f67d 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -543,7 +543,7 @@ void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act, * trying to get rid of stuff that's actually unwanted! */ if (act->id.us == 1) { - BKE_reportf(reports, RPT_ERROR, + BKE_reportf(reports, RPT_WARNING, "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain", act->id.name + 2); } -- cgit v1.2.3 From f1355d0b45cf8c0d170c9ad0fdf7f36ef8ac1585 Mon Sep 17 00:00:00 2001 From: Mai Lavelle Date: Tue, 14 Apr 2015 19:00:17 +0500 Subject: Second round of hair random rotation limited to 180 degrees This time roll back to originally discussed in the code review page approach with simply bumping UI range for the property. It's still not totally free from forward compatibility breaking (which is already broken comparing to previous release) but at least it'll keep files working inbetween of git blender versions in cases random factor was not set above 2.0. Differential Revision: https://developer.blender.org/D1214 --- source/blender/makesrna/intern/rna_particle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 029563ad9c3..c0ce8f21870 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -2720,7 +2720,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "phase_factor_random", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "randphasefac"); - RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_range(prop, 0.0f, 2.0f); RNA_def_property_ui_text(prop, "Random Phase", "Randomize rotation around the chosen orientation axis"); RNA_def_property_update(prop, 0, "rna_Particle_reset"); -- cgit v1.2.3 From 66e2fc39ce2fbb02eda44775fbaf758d7ddf5834 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Tue, 14 Apr 2015 11:19:23 -0300 Subject: Fix T44343 Compositor image node cannot properly load multilayer EXRs --- source/blender/compositor/operations/COM_ImageOperation.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp index c140b7afbd7..c55366ab370 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.cpp +++ b/source/blender/compositor/operations/COM_ImageOperation.cpp @@ -70,8 +70,12 @@ ImBuf *BaseImageOperation::getImBuf() ImBuf *ibuf; ImageUser iuser = *this->m_imageUser; + if (this->m_image == NULL) + return NULL; + /* local changes to the original ImageUser */ - iuser.multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName); + if (BKE_image_is_multilayer(this->m_image) == false) + iuser.multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName); ibuf = BKE_image_acquire_ibuf(this->m_image, &iuser, NULL); if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) { -- cgit v1.2.3 From 2d33057c753117e14e407ed913e2ec04171740bf Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Tue, 14 Apr 2015 12:19:07 -0300 Subject: Multiview: compositor openexr multiview images fully working This is from my original missing-bits/TODO list. Basically multiview openexr was only working when multiview was on. --- source/blender/compositor/nodes/COM_ImageNode.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp index 93ab6dd765a..fdd75033aea 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cpp +++ b/source/blender/compositor/nodes/COM_ImageNode.cpp @@ -97,8 +97,7 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo socket = this->getOutputSocket(index); bNodeSocket *bnodeSocket = socket->getbNodeSocket(); RenderPass *rpass = (RenderPass *)BLI_findstring(&rl->passes, bnodeSocket->identifier, offsetof(RenderPass, internal_name)); - - int view = (rpass ? rpass->view_id : 0); + int view = 0; /* Passes in the file can differ from passes stored in sockets (#36755). * Look up the correct file pass using the socket identifier instead. @@ -118,6 +117,7 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo /* heuristic to match image name with scene names * check if the view name exists in the image */ view = BLI_findstringindex(&image->rr->views, context.getViewName(), offsetof(RenderView, name)); + if (view == -1) view = 0; } else { view = view_image - 1; -- cgit v1.2.3 From 9b9978656d80d0343f21d9032278a57322b44b4b Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 14 Apr 2015 17:15:28 +0200 Subject: Fix T44389: Tooltips swapped in Logic Editor --- source/blender/makesrna/intern/rna_sensor.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c index 5d7bb6d2d94..69dd0925a42 100644 --- a/source/blender/makesrna/intern/rna_sensor.c +++ b/source/blender/makesrna/intern/rna_sensor.c @@ -402,8 +402,8 @@ static void rna_def_mouse_sensor(BlenderRNA *brna) }; static const EnumPropertyItem prop_mouse_type_items[] = { - {SENS_COLLISION_PROPERTY, "PROPERTY", ICON_LOGIC, "Property", "Use a material for ray intersections"}, - {SENS_COLLISION_MATERIAL, "MATERIAL", ICON_MATERIAL_DATA, "Material", "Use a property for ray intersections"}, + {SENS_COLLISION_PROPERTY, "PROPERTY", ICON_LOGIC, "Property", "Use a property for ray intersections"}, + {SENS_COLLISION_MATERIAL, "MATERIAL", ICON_MATERIAL_DATA, "Material", "Use a material for ray intersections"}, {0, NULL, 0, NULL, NULL} }; @@ -736,8 +736,8 @@ static void rna_def_ray_sensor(BlenderRNA *brna) }; static const EnumPropertyItem prop_ray_type_items[] = { - {SENS_COLLISION_PROPERTY, "PROPERTY", ICON_LOGIC, "Property", "Use a material for ray intersections"}, - {SENS_COLLISION_MATERIAL, "MATERIAL", ICON_MATERIAL_DATA, "Material", "Use a property for ray intersections"}, + {SENS_COLLISION_PROPERTY, "PROPERTY", ICON_LOGIC, "Property", "Use a property for ray intersections"}, + {SENS_COLLISION_MATERIAL, "MATERIAL", ICON_MATERIAL_DATA, "Material", "Use a material for ray intersections"}, {0, NULL, 0, NULL, NULL} }; -- cgit v1.2.3 From b216f7abd6ba4311918ee84bf051fac3d96faf5f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 15 Apr 2015 14:51:17 +1000 Subject: RNA: use lock_ prefix for booleans --- release/scripts/startup/bl_ui/space_time.py | 2 +- source/blender/editors/animation/anim_markers.c | 4 ++-- source/blender/makesdna/DNA_scene_types.h | 2 +- source/blender/makesrna/intern/rna_scene.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py index 2a3bcfc01ba..c4c4097315c 100644 --- a/release/scripts/startup/bl_ui/space_time.py +++ b/release/scripts/startup/bl_ui/space_time.py @@ -256,7 +256,7 @@ def marker_menu_generic(layout): layout.separator() ts = bpy.context.tool_settings - layout.prop(ts, "marker_lock") + layout.prop(ts, "lock_markers") if __name__ == "__main__": # only for live edit. diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index ac6a0aede17..aa06740ed0e 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -504,7 +504,7 @@ static int ed_markers_poll_selected_no_locked_markers(bContext *C) ListBase *markers = ED_context_get_markers(C); ToolSettings *ts = CTX_data_tool_settings(C); - if (ts->marker_lock) + if (ts->lock_markers) return 0; /* first things first: markers can only exist in timeline views */ @@ -1457,7 +1457,7 @@ static int ed_marker_make_links_scene_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (scene_to->toolsettings->marker_lock) { + if (scene_to->toolsettings->lock_markers) { BKE_report(op->reports, RPT_ERROR, "Target scene has locked markers"); return OPERATOR_CANCELLED; } diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index e03d77d4ec5..ca2edb5eb90 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1272,7 +1272,7 @@ typedef struct ToolSettings { char proportional_mask; /* proportional edit, mask editing */ char proportional_action; /* proportional edit, action editor */ char proportional_fcurve; /* proportional edit, graph editor */ - char marker_lock; /* lock marker editing */ + char lock_markers; /* lock marker editing */ char pad4[5]; char auto_normalize; /*auto normalizing mode in wpaint*/ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index a17a746945c..a47a777ee7c 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2180,8 +2180,8 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - prop = RNA_def_property(srna, "marker_lock", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "marker_lock", 0); + prop = RNA_def_property(srna, "lock_markers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "lock_markers", 0); RNA_def_property_ui_text(prop, "Lock Markers", "Prevent marker editing"); prop = RNA_def_property(srna, "proportional_edit_falloff", PROP_ENUM, PROP_NONE); -- cgit v1.2.3 From 356ceded279b190bfca801afe25323efadd40571 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 15 Apr 2015 15:22:37 +1000 Subject: Sculpt: change behavior of crease brush Pinch would give a flat result on either side of the stroke, because points were dragged towards a single point. Now pinch is projected on the sculpt plane, which gives a tighter crease. The reverse is true too - blob brush which shares the code is also more curved. --- source/blender/editors/sculpt_paint/sculpt.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 6ca368ea4f7..411ccefe5c0 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1699,6 +1699,16 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod float brush_alpha; int n; + /* vars for handling projection when calculating the pinch vector. + * Use surface normal for 'v_proj',s o the vertices are pinched towards a line instead of a single point. + * Without this we get a 'flat' surface surrounding the pinch */ + const float *pinch_proj = ss->cache->sculpt_normal_symm; + const float pinch_proj_len_sq = len_squared_v3(pinch_proj); + const bool do_pinch_proj = (pinch_proj_len_sq > FLT_EPSILON); + /* simplifies projection calc below */ + const float pinch_proj_len_sq_inv_neg = do_pinch_proj ? -1.0f / pinch_proj_len_sq : 0.0f; + + /* offset with as much as possible factored in already */ mul_v3_v3fl(offset, ss->cache->sculpt_normal_symm, ss->cache->radius); mul_v3_v3(offset, ss->cache->scale); @@ -1739,6 +1749,15 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod sub_v3_v3v3(val1, test.location, vd.co); mul_v3_fl(val1, fade * flippedbstrength); + if (do_pinch_proj) { +#if 0 + project_plane_v3_v3v3(val1, val1, v_proj); +#else + /* inline the projection, cache `-1.0 / dot_v3_v3(v_proj, v_proj)` */ + madd_v3_v3fl(val1, pinch_proj, dot_v3v3(val1, pinch_proj) * pinch_proj_len_sq_inv_neg); +#endif + } + /* then we draw */ mul_v3_v3fl(val2, offset, fade); -- cgit v1.2.3 From 9a711f98a7f55a2534f1f6fe3756914d8f7f8861 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 15 Apr 2015 15:34:06 +1000 Subject: typo in last commit --- source/blender/editors/sculpt_paint/sculpt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 411ccefe5c0..b14fbc40049 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -328,7 +328,7 @@ static int sculpt_stroke_dynamic_topology(const SculptSession *ss, * dynamic-topology */ !(brush->flag & BRUSH_ANCHORED) && !(brush->flag & BRUSH_DRAG_DOT) && - + (!ELEM(brush->sculpt_tool, /* These brushes, as currently coded, cannot * support dynamic topology */ @@ -1700,7 +1700,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod int n; /* vars for handling projection when calculating the pinch vector. - * Use surface normal for 'v_proj',s o the vertices are pinched towards a line instead of a single point. + * Use surface normal for 'pinch_proj', so the vertices are pinched towards a line instead of a single point. * Without this we get a 'flat' surface surrounding the pinch */ const float *pinch_proj = ss->cache->sculpt_normal_symm; const float pinch_proj_len_sq = len_squared_v3(pinch_proj); -- cgit v1.2.3 From 730684f976d69c6ad6d58428315f2c1f996f7a85 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 15 Apr 2015 16:14:27 +1000 Subject: BMesh: avoid ghash lookups splitting the pbvh This isn't a bottleneck but may as well avoid the extra ghash overhead. --- source/blender/blenkernel/intern/pbvh_bmesh.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 86c430d1785..630f3ab2b07 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -116,7 +116,7 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index, const int cd_ver } /* Recursively split the node if it exceeds the leaf_limit */ -static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index) +static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_index) { GSet *empty, *other; GSetIterator gs_iter; @@ -138,7 +138,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index) BB_reset(&cb); GSET_ITER (gs_iter, n->bm_faces) { const BMFace *f = BLI_gsetIterator_getKey(&gs_iter); - const BBC *bbc = BLI_ghash_lookup(prim_bbc, f); + const BBC *bbc = &bbc_array[BM_elem_index_get(f)]; BB_expand(&cb, bbc->bcentroid); } @@ -166,7 +166,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index) /* Partition the parent node's faces between the two children */ GSET_ITER (gs_iter, n->bm_faces) { BMFace *f = BLI_gsetIterator_getKey(&gs_iter); - const BBC *bbc = BLI_ghash_lookup(prim_bbc, f); + const BBC *bbc = &bbc_array[BM_elem_index_get(f)]; if (bbc->bcentroid[axis] < mid) BLI_gset_insert(c1->bm_faces, f); @@ -230,8 +230,8 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index) /* Recurse */ c1 = c2 = NULL; - pbvh_bmesh_node_split(bvh, prim_bbc, children); - pbvh_bmesh_node_split(bvh, prim_bbc, children + 1); + pbvh_bmesh_node_split(bvh, bbc_array, children); + pbvh_bmesh_node_split(bvh, bbc_array, children + 1); /* Array maybe reallocated, update current node pointer */ n = &bvh->nodes[node_index]; @@ -246,7 +246,6 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index) /* Recursively split the node if it exceeds the leaf_limit */ static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index) { - GHash *prim_bbc; GSet *bm_faces; int bm_faces_size; GSetIterator gs_iter; @@ -261,8 +260,7 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index) } /* For each BMFace, store the AABB and AABB centroid */ - prim_bbc = BLI_ghash_ptr_new_ex("prim_bbc", bm_faces_size); - bbc_array = MEM_callocN(sizeof(BBC) * bm_faces_size, "BBC"); + bbc_array = MEM_mallocN(sizeof(BBC) * bm_faces_size, "BBC"); GSET_ITER_INDEX (gs_iter, bm_faces, i) { BMFace *f = BLI_gsetIterator_getKey(&gs_iter); @@ -277,12 +275,14 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index) } while ((l_iter = l_iter->next) != l_first); BBC_update_centroid(bbc); - BLI_ghash_insert(prim_bbc, f, bbc); + /* so we can do direct lookups on 'bbc_array' */ + BM_elem_index_set(f, i); /* set_dirty! */ } + /* likely this is already dirty */ + bvh->bm->elem_index_dirty |= BM_FACE; - pbvh_bmesh_node_split(bvh, prim_bbc, node_index); + pbvh_bmesh_node_split(bvh, bbc_array, node_index); - BLI_ghash_free(prim_bbc, NULL, NULL); MEM_freeN(bbc_array); return true; -- cgit v1.2.3 From 255fb79ff30cdea8065e28ae16ea24eb0f536f96 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 15 Apr 2015 11:11:22 +0200 Subject: Fix T44395: String untranslated in open file window. --- source/blender/windowmanager/intern/wm_operators.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 2b09c5cc9f8..19a6b86db90 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2454,18 +2454,18 @@ static void wm_open_mainfile_ui(bContext *UNUSED(C), wmOperator *op) struct FileRuntime *file_info = (struct FileRuntime *)&op->customdata; uiLayout *layout = op->layout; uiLayout *col = op->layout; - const char *autoexec_text = NULL; + const char *autoexec_text; uiItemR(layout, op->ptr, "load_ui", 0, NULL, ICON_NONE); col = uiLayoutColumn(layout, false); if (file_info->is_untrusted) { - autoexec_text = "Trusted Source [Untrusted Path]"; + autoexec_text = IFACE_("Trusted Source [Untrusted Path]"); uiLayoutSetActive(col, false); uiLayoutSetEnabled(col, false); } else { - autoexec_text = "Trusted Source"; + autoexec_text = IFACE_("Trusted Source"); } uiItemR(col, op->ptr, "use_scripts", 0, autoexec_text, ICON_NONE); -- cgit v1.2.3 From 240c5704e479ede0635beca1c2be07d1cd028c8c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 15 Apr 2015 20:46:33 +1000 Subject: BMesh: Missed normal from example /w skip-cd flag We may still want to use the normal as a reference but skip customdata. --- source/blender/bmesh/intern/bmesh_core.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index dc5e5a5a13c..7b54fcbffde 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -88,7 +88,7 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], else { zero_v3(v->co); } - zero_v3(v->no); + /* 'v->no' set below */ v->e = NULL; /* --- done --- */ @@ -107,6 +107,7 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], if (v_example) { int *keyi; + /* handles 'v->no' too */ BM_elem_attrs_copy(bm, bm, v_example, v); /* exception: don't copy the original shapekey index */ @@ -117,6 +118,15 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], } else { CustomData_bmesh_set_default(&bm->vdata, &v->head.data); + zero_v3(v->no); + } + } + else { + if (v_example) { + copy_v3_v3(v->no, v_example->no); + } + else { + zero_v3(v->no); } } @@ -362,7 +372,8 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) f->l_first = NULL; #endif f->len = 0; - zero_v3(f->no); + /* caller must initialize */ + // zero_v3(f->no); f->mat_nr = 0; /* --- done --- */ @@ -443,6 +454,15 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, } else { CustomData_bmesh_set_default(&bm->pdata, &f->head.data); + zero_v3(f->no); + } + } + else { + if (f_example) { + copy_v3_v3(f->no, f_example->no); + } + else { + zero_v3(f->no); } } -- cgit v1.2.3 From b9ea6fbb301f264110b5b0ab0ace021079434e69 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 15 Apr 2015 20:52:51 +1000 Subject: BMesh: dyntopo used lopsided normals Normals from subdivided edges were only taken from the edges first vertex. Interpolate between the two to give more even results. --- source/blender/blenkernel/intern/pbvh_bmesh.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 630f3ab2b07..ce405e88481 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -330,8 +330,7 @@ static PBVHNode *pbvh_bmesh_node_lookup(PBVH *bvh, void *key) static BMVert *pbvh_bmesh_vert_create( PBVH *bvh, int node_index, - const float co[3], - const BMVert *example, + const float co[3], const float no[3], const int cd_vert_mask_offset) { PBVHNode *node = &bvh->nodes[node_index]; @@ -340,9 +339,12 @@ static BMVert *pbvh_bmesh_vert_create( BLI_assert((bvh->totnode == 1 || node_index) && node_index <= bvh->totnode); /* avoid initializing customdata because its quite involved */ - v = BM_vert_create(bvh->bm, co, example, BM_CREATE_SKIP_CD); + v = BM_vert_create(bvh->bm, co, NULL, BM_CREATE_SKIP_CD); CustomData_bmesh_set_default(&bvh->bm->vdata, &v->head.data); + /* This value is logged below */ + copy_v3_v3(v->no, no); + BLI_gset_insert(node->bm_unique_verts, v); BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, node_index); @@ -879,17 +881,19 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh, BMEdge *e, BLI_Buffer *edge_loops) { BMVert *v_new; - float mid[3]; + float co_mid[3], no_mid[3]; int i, node_index; /* Get all faces adjacent to the edge */ pbvh_bmesh_edge_loops(edge_loops, e); /* Create a new vertex in current node at the edge's midpoint */ - mid_v3_v3v3(mid, e->v1->co, e->v2->co); + mid_v3_v3v3(co_mid, e->v1->co, e->v2->co); + mid_v3_v3v3(no_mid, e->v1->no, e->v2->no); + normalize_v3(no_mid); node_index = BM_ELEM_CD_GET_INT(e->v1, eq_ctx->cd_vert_node_offset); - v_new = pbvh_bmesh_vert_create(bvh, node_index, mid, e->v1, eq_ctx->cd_vert_mask_offset); + v_new = pbvh_bmesh_vert_create(bvh, node_index, co_mid, no_mid, eq_ctx->cd_vert_mask_offset); /* update paint mask */ if (eq_ctx->cd_vert_mask_offset != -1) { -- cgit v1.2.3 From 7730391d7425a8581cf16b3a6510acc56108071c Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Wed, 15 Apr 2015 21:45:43 +1000 Subject: BGE: subclass with more than 1 argument, D1237 In the BGE you can't create a subclass with more than 1 argument like : "player = Player(owner, 10)" I have modified the py_base_new to check only the first argument of args tuple. Now we can do : class Player(types.KX_GameObject): def __init__(self, gameobj, life): print("create new player :", self, ", life :", life) player = Player(own, 50) --- source/gameengine/Expressions/PyObjectPlus.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index a65d61bc98b..d475152f83e 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -148,10 +148,15 @@ PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the ent PyObject *PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyTypeObject *base_type; - PyObjectPlus_Proxy *base = NULL; - if (!PyArg_ParseTuple(args, "O:Base PyObjectPlus", &base)) + /* one or more args is needed */ + if (!PyTuple_GET_SIZE(args)) { + PyErr_SetString(PyExc_TypeError, + "Expected at least one argument"); return NULL; + } + + PyObjectPlus_Proxy *base = (PyObjectPlus_Proxy *)PyTuple_GET_ITEM(args, 0); /* the 'base' PyObject may be subclassed (multiple times even) * we need to find the first C++ defined class to check 'type' -- cgit v1.2.3 From f660085e2f0d1f000f8243f480376492540bfe99 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 16 Apr 2015 00:59:43 +1000 Subject: Increase max brush size from 200 to 500 --- source/blender/makesdna/DNA_brush_types.h | 2 +- source/blender/makesrna/intern/rna_sculpt_paint.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 6d6d33a6f1b..a711f2ae100 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -295,7 +295,7 @@ typedef enum BlurKernelType { KERNEL_BOX } BlurKernelType; -#define MAX_BRUSH_PIXEL_RADIUS 200 +#define MAX_BRUSH_PIXEL_RADIUS 500 #endif diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index b98652de759..a975ea3d7e4 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -875,7 +875,7 @@ static void rna_def_particle_edit(BlenderRNA *brna) prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL); RNA_def_property_range(prop, 1, SHRT_MAX); - RNA_def_property_ui_range(prop, 1, 100, 10, 3); + RNA_def_property_ui_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS, 10, 3); RNA_def_property_ui_text(prop, "Radius", "Radius of the brush in pixels"); prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_FACTOR); -- cgit v1.2.3 From 34c1319d06f691aa8cabcc34a52d406ce99b682e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 16 Apr 2015 01:07:54 +1000 Subject: Cleanup: use const for event->tablet_data --- source/blender/editors/gpencil/gpencil_paint.c | 2 +- source/blender/windowmanager/WM_types.h | 2 +- source/blender/windowmanager/intern/wm_event_system.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 2795c820fa7..778f98d212e 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1608,7 +1608,7 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event) /* handle pressure sensitivity (which is supplied by tablets) */ if (event->tablet_data) { - wmTabletData *wmtab = event->tablet_data; + const wmTabletData *wmtab = event->tablet_data; tablet = (wmtab->Active != EVT_TABLET_NONE); p->pressure = wmtab->Pressure; diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index e716cd6b779..ecc7a827bee 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -453,7 +453,7 @@ typedef struct wmEvent { const char *keymap_idname; /* tablet info, only use when the tablet is active */ - struct wmTabletData *tablet_data; + const struct wmTabletData *tablet_data; /* custom data */ short custom; /* custom data type, stylus, 6dof, see wm_event_types.h */ diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index d8ca80a62cb..2280782f7bd 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -123,7 +123,7 @@ void wm_event_free(wmEvent *event) } if (event->tablet_data) { - MEM_freeN(event->tablet_data); + MEM_freeN((void *)event->tablet_data); } MEM_freeN(event); @@ -3504,7 +3504,7 @@ float WM_event_tablet_data(const wmEvent *event, int *pen_flip, float tilt[2]) zero_v2(tilt); if (event->tablet_data) { - wmTabletData *wmtab = event->tablet_data; + const wmTabletData *wmtab = event->tablet_data; erasor = (wmtab->Active == EVT_TABLET_ERASER); if (wmtab->Active != EVT_TABLET_NONE) { -- cgit v1.2.3 From 99299da4b5ca1f9e9c347db120dc93df58e8d0a6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 16 Apr 2015 01:12:22 +1000 Subject: Cleanup: warnings, ws --- source/blender/blenkernel/BKE_sequencer.h | 2 +- source/blender/bmesh/intern/bmesh_operator_api.h | 3 --- source/blender/collada/AnimationExporter.h | 4 ++-- source/blender/makesdna/DNA_object_force.h | 2 +- source/gameengine/Ketsji/KX_PyConstraintBinding.cpp | 1 - 5 files changed, 4 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 4a45489933c..f73548373ef 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -296,7 +296,7 @@ int BKE_sequence_effect_get_supports_mask(int seq_type); * Sequencer editing functions * ********************************************************************** */ - + /* for transform but also could use elsewhere */ int BKE_sequence_tx_get_final_left(struct Sequence *seq, bool metaclip); int BKE_sequence_tx_get_final_right(struct Sequence *seq, bool metaclip); diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index d966d882c67..33a956b652f 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -483,9 +483,6 @@ bool BMO_iter_map_value_bool(BMOIter *iter); ele; \ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_step(iter)) -/******************* Inlined Functions********************/ -typedef void (*opexec)(BMesh *bm, BMOperator *op); - extern const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES]; int BMO_opcode_from_opname(const char *opname); diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h index 6f675ed6a39..4736361ad13 100644 --- a/source/blender/collada/AnimationExporter.h +++ b/source/blender/collada/AnimationExporter.h @@ -103,7 +103,7 @@ protected: const ExportSettings *export_settings; void dae_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma = NULL); - + void export_object_constraint_animation(Object *ob); void export_morph_animation(Object *ob); @@ -154,7 +154,7 @@ protected: std::string create_xyz_source(float *v, int tot, const std::string& anim_id); std::string create_4x4_source(std::vector &frames, Object * ob_arm, Bone *bone, const std::string& anim_id); - + std::string create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents); std::string fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name); diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index 5cc56d861a3..c9c1f618e86 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -297,7 +297,7 @@ typedef struct SoftBody { char namedVG_Softgoal[64]; /* MAX_VGROUP_NAME */ /* starting to fix old bug .. nastiness that VG are indexes * rather find them by name tag to find it -> jow20090613 */ - + short fuzzyness; /* */ /* springs */ diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 77453916e44..065251f5676 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -497,7 +497,6 @@ static PyObject *gPyCreateConstraint(PyObject *self, /* FIXME - physicsid is a long being cast to a pointer, should at least use PyCapsule */ unsigned long long physicsid = 0, physicsid2 = 0; int constrainttype = 0; - int len = PyTuple_Size(args); int flag = 0; float pivotX = 0.0f, pivotY = 0.0f, pivotZ = 0.0f, axisX = 0.0f, axisY = 0.0f, axisZ = 0.0f; -- cgit v1.2.3 From 7f4b6a345e59bd4b05c8cab08d0c618eea9f827d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 16 Apr 2015 01:45:30 +1000 Subject: Fix crash loading file without scene in bg mode --- source/blender/blenkernel/intern/blender.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 305bf1ed796..4b2c6ef5e0e 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -263,7 +263,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath /* but use new Scene pointer */ curscene = bfd->curscene; - track_undo_scene = (mode == LOAD_UNDO && curscreen && bfd->main->wm.first); + track_undo_scene = (mode == LOAD_UNDO && curscreen && curscene && bfd->main->wm.first); if (curscene == NULL) curscene = bfd->main->scene.first; /* empty file, we add a scene to make Blender work */ -- cgit v1.2.3 From 6675fd6b52554cf4ed63d5a740dfe60525cf1f3a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 16 Apr 2015 04:14:01 +1000 Subject: dyntopo: don't allocate tessfaces while sculpting Tessellation data isn't used for drawing or sculpting. This frees up some memory ~approx 10% in own tests. Also slight spee-up since it avoids calculating it in the first place. --- source/blender/blenkernel/BKE_pbvh.h | 1 + source/blender/blenkernel/intern/DerivedMesh.c | 4 ++-- source/blender/blenkernel/intern/cdderivedmesh.c | 8 ++++---- source/blender/blenkernel/intern/paint.c | 17 +++++++++-------- source/blender/blenkernel/intern/pbvh.c | 11 +++++++++++ source/blender/blenkernel/intern/subsurf_ccg.c | 2 +- source/blender/editors/space_view3d/drawobject.c | 13 +++++++------ 7 files changed, 35 insertions(+), 21 deletions(-) diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 9276a6e14e9..035c8aa9515 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -121,6 +121,7 @@ typedef enum { } PBVHType; PBVHType BKE_pbvh_type(const PBVH *bvh); +bool BKE_pbvh_has_faces(const PBVH *bvh); /* Get the PBVH root's bounding box */ void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3]); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 1ece9d82cc2..38ae0461c84 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1939,7 +1939,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos DM_calc_loop_normals(finaldm, do_loop_normals, loop_normals_split_angle); } - { + if (sculpt_dyntopo == false) { DM_ensure_tessface(finaldm); /* without this, drawing ngon tri's faces will show ugly tessellated face @@ -2348,7 +2348,7 @@ static CustomDataMask object_get_datamask(const Scene *scene, Object *ob) if (ob == actob) { /* check if we need tfaces & mcols due to face select or texture paint */ - if (BKE_paint_select_face_test(ob) || (ob->mode & OB_MODE_TEXTURE_PAINT)) { + if ((ob->mode & OB_MODE_TEXTURE_PAINT) || BKE_paint_select_face_test(ob)) { mask |= CD_MASK_MTFACE | CD_MASK_MCOL; } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index bd5ee4b9851..e4a5dbb9d24 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -470,7 +470,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, int a; if (cddm->pbvh && cddm->pbvh_draw) { - if (dm->numTessFaceData) { + if (BKE_pbvh_has_faces(cddm->pbvh)) { float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL); BKE_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors, @@ -527,7 +527,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, * (the same as it'll display without UV maps in textured view) */ if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) { - if (dm->numTessFaceData) { + if (BKE_pbvh_has_faces(cddm->pbvh)) { GPU_set_tpage(NULL, false, false); BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false); } @@ -912,7 +912,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, * works fine for matcap */ if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) { - if (dm->numTessFaceData) { + if (BKE_pbvh_has_faces(cddm->pbvh)) { setMaterial(1, &gattribs); BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false); } @@ -1246,7 +1246,7 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, * works fine for matcap */ if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) { - if (dm->numTessFaceData) { + if (BKE_pbvh_has_faces(cddm->pbvh)) { setMaterial(userData, 1, &gattribs); BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false); } diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index b45e6b81ec8..fd5d14b6cfc 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -566,13 +566,9 @@ void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, cons void BKE_sculptsession_free_deformMats(SculptSession *ss) { - if (ss->orig_cos) MEM_freeN(ss->orig_cos); - if (ss->deform_cos) MEM_freeN(ss->deform_cos); - if (ss->deform_imats) MEM_freeN(ss->deform_imats); - - ss->orig_cos = NULL; - ss->deform_cos = NULL; - ss->deform_imats = NULL; + MEM_SAFE_FREE(ss->orig_cos); + MEM_SAFE_FREE(ss->deform_cos); + MEM_SAFE_FREE(ss->deform_imats); } /* Write out the sculpt dynamic-topology BMesh to the Mesh */ @@ -772,7 +768,12 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, } /* BMESH ONLY --- at some point we should move sculpt code to use polygons only - but for now it needs tessfaces */ - BKE_mesh_tessface_ensure(me); + if (ss->bm) { + BKE_mesh_tessface_clear(me); + } + else { + BKE_mesh_tessface_ensure(me); + } if (!mmd) ss->kb = BKE_keyblock_from_object(ob); else ss->kb = NULL; diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index c9e632b7295..e12d685fb67 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -943,6 +943,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes, int n; if (bvh->type == PBVH_BMESH) { + BLI_assert(face_nors == NULL); pbvh_bmesh_normals_update(nodes, totnode); return; } @@ -1280,6 +1281,16 @@ PBVHType BKE_pbvh_type(const PBVH *bvh) return bvh->type; } +bool BKE_pbvh_has_faces(const PBVH *bvh) +{ + if (bvh->type == PBVH_BMESH) { + return (bvh->bm->totface != 0); + } + else { + return (bvh->totprim != 0); + } +} + void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3]) { if (bvh->totnode) { diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 9519c7b25a1..a4e0eaaa324 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1762,7 +1762,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) ccgdm_pbvh_update(ccgdm); if (ccgdm->pbvh && ccgdm->multires.mmd && !fast) { - if (dm->numTessFaceData) { + if (BKE_pbvh_has_faces(ccgdm->pbvh)) { BKE_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL, setMaterial, false); glShadeModel(GL_FLAT); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 8dcf1d388ea..10db8c38de3 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -3912,7 +3912,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D #endif Mesh *me = ob->data; eWireDrawMode draw_wire = OBDRAW_WIRE_OFF; - int /* totvert,*/ totedge, totface; + bool /* no_verts,*/ no_edges, no_faces; DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask); const bool is_obact = (ob == OBACT); int draw_flags = (is_obact && BKE_paint_select_face_test(ob)) ? DRAW_FACE_SELECT : 0; @@ -3935,8 +3935,9 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D draw_wire = OBDRAW_WIRE_ON_DEPTH; /* draw wire after solid using zoffset and depth buffer adjusment */ } - totedge = dm->getNumEdges(dm); - totface = dm->getNumTessFaces(dm); + /* check polys instead of tessfaces because of dyntopo where tessfaces don't exist */ + no_edges = (dm->getNumEdges(dm) == 0); + no_faces = (dm->getNumPolys(dm) == 0); /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */ glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); @@ -3945,14 +3946,14 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0) draw_bounding_volume(ob, ob->boundtype); } - else if ((totface == 0 && totedge == 0) || + else if ((no_faces && no_edges) || ((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob))) { glPointSize(1.5); dm->drawVerts(dm); glPointSize(1.0); } - else if (dt == OB_WIRE || totface == 0) { + else if ((dt == OB_WIRE) || no_faces) { draw_wire = OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff */ } else if (((is_obact && ob->mode & OB_MODE_TEXTURE_PAINT)) || @@ -4146,7 +4147,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */ } - dm->drawEdges(dm, (dt == OB_WIRE || totface == 0), (ob->dtx & OB_DRAW_ALL_EDGES) != 0); + dm->drawEdges(dm, ((dt == OB_WIRE) || no_faces), (ob->dtx & OB_DRAW_ALL_EDGES) != 0); if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) { glDepthMask(1); -- cgit v1.2.3 From f57b904807c7efb3f799e46ce7d903d00301a0ac Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 16 Apr 2015 11:59:48 +1000 Subject: Dyntopo: blend vertex normals when collapsing --- source/blender/blenkernel/intern/pbvh_bmesh.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index ce405e88481..116c1827f85 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -1197,6 +1197,8 @@ static void pbvh_bmesh_collapse_edge( if (!BLI_gset_haskey(deleted_verts, v_conn)) { BM_log_vert_before_modified(bvh->bm_log, v_conn, eq_ctx->cd_vert_mask_offset); mid_v3_v3v3(v_conn->co, v_conn->co, v_del->co); + add_v3_v3(v_conn->no, v_del->no); + normalize_v3(v_conn->no); } /* Delete v_del */ -- cgit v1.2.3 From b88421aa6204f51e23dbff3ee48a5d2c360b0536 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 16 Apr 2015 12:24:59 +1000 Subject: Dyntopo: avoid redundant loop collapsing edges --- source/blender/blenkernel/intern/pbvh_bmesh.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 116c1827f85..d54c598e988 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -1160,18 +1160,6 @@ static void pbvh_bmesh_collapse_edge( v_tri[1] = l_iter->v; e_tri[1] = l_iter->e; l_iter = l_iter->next; v_tri[2] = l_iter->v; e_tri[2] = l_iter->e; - /* Check if any of the face's vertices are now unused, if so - * remove them from the PBVH */ - for (j = 0; j < 3; j++) { - if (v_tri[j] != v_del && BM_vert_face_count_is_equal(v_tri[j], 1)) { - BLI_gset_insert(deleted_verts, v_tri[j]); - pbvh_bmesh_vert_remove(bvh, v_tri[j]); - } - else { - v_tri[j] = NULL; - } - } - /* Remove the face */ pbvh_bmesh_face_remove(bvh, f_del); BM_face_kill(bvh->bm, f_del); @@ -1183,9 +1171,13 @@ static void pbvh_bmesh_collapse_edge( BM_edge_kill(bvh->bm, e_tri[j]); } - /* Delete unused vertices */ + /* Check if any of the face's vertices are now unused, if so + * remove them from the PBVH */ for (j = 0; j < 3; j++) { - if (v_tri[j]) { + if ((v_tri[j] != v_del) && (v_tri[j]->e == NULL)) { + BLI_gset_insert(deleted_verts, v_tri[j]); + pbvh_bmesh_vert_remove(bvh, v_tri[j]); + BM_log_vert_removed(bvh->bm_log, v_tri[j], eq_ctx->cd_vert_mask_offset); BM_vert_kill(bvh->bm, v_tri[j]); } -- cgit v1.2.3 From b466a82fa5b3490a13880a92ce00d01057ae21b3 Mon Sep 17 00:00:00 2001 From: Tamito Kajiyama Date: Thu, 16 Apr 2015 09:13:40 +0900 Subject: Partial fix for T44404: freestyle crashes blender. Logical predicates AndUP1D and OrUP1D were instantiated even with an empty list of unary 1D predicates, causing an exception in the constructors of the logical predicate classes. This is a regression made in b408d8af31c9fba5898e353c97f95f7ce8dc19c1. --- release/scripts/freestyle/modules/parameter_editor.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/release/scripts/freestyle/modules/parameter_editor.py b/release/scripts/freestyle/modules/parameter_editor.py index d4765847450..3c11c33a39d 100644 --- a/release/scripts/freestyle/modules/parameter_editor.py +++ b/release/scripts/freestyle/modules/parameter_editor.py @@ -960,11 +960,11 @@ def process(layer_name, lineset_name): if lineset.select_external_contour: upred = ExternalContourUP1D() edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_external_contour else upred) - if lineset.edge_type_combination == 'OR': - upred = OrUP1D(*edge_type_criteria) - else: - upred = AndUP1D(*edge_type_criteria) - if upred is not None: + if edge_type_criteria: + if lineset.edge_type_combination == 'OR': + upred = OrUP1D(*edge_type_criteria) + else: + upred = AndUP1D(*edge_type_criteria) if lineset.edge_type_negation == 'EXCLUSIVE': upred = NotUP1D(upred) selection_criteria.append(upred) @@ -989,8 +989,9 @@ def process(layer_name, lineset_name): upred = WithinImageBoundaryUP1D(*ContextFunctions.get_border()) selection_criteria.append(upred) # select feature edges - upred = AndUP1D(*selection_criteria) - if upred is None: + if selection_criteria: + upred = AndUP1D(*selection_criteria) + else: upred = TrueUP1D() Operators.select(upred) # join feature edges to form chains -- cgit v1.2.3 From 8c98b1649d1cee38faff338414d35c87ee0f8c2a Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Thu, 16 Apr 2015 06:31:25 +0200 Subject: BGE: Fix for T42341 Sensor.frequency is badly named "Frequency" parameter is renamed to "Skip" in the LogicBricks sensors as it represents skipped frames between pulses. Naming something (frequency) the exact opposite of what it represents (period) was the worst choice. Also, a new BGE python attribute 'skippedTicks' was introduced. 'frequency' attribute is maintained but deprecated. Internally, freq variable is used yet at DNA_Sensor to maintain compability and to avoid do_versions. Thanks to Sybren for the investigation. {F162440} Reviewers: campbellbarton, sybren, moguri, hg1 Reviewed By: sybren, hg1 Differential Revision: https://developer.blender.org/D1229 --- .../rst/bge_types/bge.types.SCA_ISensor.rst | 10 +++++-- source/blender/editors/space_logic/logic_window.c | 2 +- source/blender/makesdna/DNA_sensor_types.h | 2 +- source/blender/makesrna/intern/rna_sensor.c | 6 ++-- source/gameengine/Converter/KX_ConvertSensors.cpp | 8 ++--- source/gameengine/GameLogic/SCA_ISensor.cpp | 34 ++++++++++++++++++---- source/gameengine/GameLogic/SCA_ISensor.h | 8 +++-- source/gameengine/GameLogic/SCA_RandomSensor.cpp | 2 +- 8 files changed, 52 insertions(+), 20 deletions(-) diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_ISensor.rst b/doc/python_api/rst/bge_types/bge.types.SCA_ISensor.rst index 9efd2e2d63a..af444fb9e65 100644 --- a/doc/python_api/rst/bge_types/bge.types.SCA_ISensor.rst +++ b/doc/python_api/rst/bge_types/bge.types.SCA_ISensor.rst @@ -23,8 +23,14 @@ base class --- :class:`SCA_ILogicBrick` .. attribute:: frequency - The frequency for pulse mode sensors. - + The frequency for pulse mode sensors. (Deprecated: use SCA_ISensor.skippedTicks) + + :type: integer + + .. attribute:: skippedTicks + + Number of logic ticks skipped between 2 active pulses + :type: integer .. attribute:: level diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index 7204144ce85..d4fa911f025 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -903,7 +903,7 @@ static void draw_sensor_internal_header(uiLayout *layout, PointerRNA *ptr) sub = uiLayoutRow(row, false); uiLayoutSetActive(sub, (RNA_boolean_get(ptr, "use_pulse_true_level") || RNA_boolean_get(ptr, "use_pulse_false_level"))); - uiItemR(sub, ptr, "frequency", 0, IFACE_("Freq"), ICON_NONE); + uiItemR(sub, ptr, "skipped_ticks", 0, IFACE_("Skip"), ICON_NONE); row = uiLayoutRow(split, true); uiItemR(row, ptr, "use_level", UI_ITEM_R_TOGGLE, NULL, ICON_NONE); diff --git a/source/blender/makesdna/DNA_sensor_types.h b/source/blender/makesdna/DNA_sensor_types.h index 8d59a13768b..d886dcf2807 100644 --- a/source/blender/makesdna/DNA_sensor_types.h +++ b/source/blender/makesdna/DNA_sensor_types.h @@ -164,7 +164,7 @@ typedef struct bSensor { struct bSensor *next, *prev; /* pulse and freq are the bool toggle and frame count for pulse mode */ short type, otype, flag, pulse; - short freq, totlinks, pad1, pad2; + short freq, totlinks, pad1, pad2; /* freq makes reference to skipped ticks between 2 active pulses */ char name[64]; /* MAX_NAME */ void *data; diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c index 69dd0925a42..3cc94039d59 100644 --- a/source/blender/makesrna/intern/rna_sensor.c +++ b/source/blender/makesrna/intern/rna_sensor.c @@ -325,9 +325,11 @@ static void rna_def_sensor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Pulse False Level", "Activate FALSE level triggering (pulse mode)"); RNA_def_property_update(prop, NC_LOGIC, NULL); - prop = RNA_def_property(srna, "frequency", PROP_INT, PROP_NONE); + prop = RNA_def_property(srna, "skipped_ticks", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "freq"); - RNA_def_property_ui_text(prop, "Frequency", "Delay between repeated pulses(in logic tics, 0=no delay)"); + RNA_def_property_ui_text(prop, "Skip", + "Number of logic ticks skipped between 2 active pulses " + "(0 = pulse every logic tick, 1 = skip 1 logic tick between pulses, etc.)"); RNA_def_property_range(prop, 0, 10000); RNA_def_property_update(prop, NC_LOGIC, NULL); diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index 0d706fcd924..b781e4d1cc8 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -105,7 +105,7 @@ void BL_ConvertSensors(struct Object* blenderobject, bSensor* sens = (bSensor*)blenderobject->sensors.first; bool pos_pulsemode = false; bool neg_pulsemode = false; - int frequency = 0; + int skipped_ticks = 0; bool invert = false; bool level = false; bool tap = false; @@ -120,13 +120,13 @@ void BL_ConvertSensors(struct Object* blenderobject, while (sens) { SCA_ISensor* gamesensor=NULL; - /* All sensors have a pulse toggle, frequency, and invert field. */ + /* All sensors have a pulse toggle, skipped ticks parameter, and invert field. */ /* These are extracted here, and set when the sensor is added to the */ /* list. */ pos_pulsemode = (sens->pulse & SENS_PULSE_REPEAT)!=0; neg_pulsemode = (sens->pulse & SENS_NEG_PULSE_MODE)!=0; - frequency = sens->freq; + skipped_ticks = sens->freq; invert = !(sens->invert == 0); level = !(sens->level == 0); tap = !(sens->tap == 0); @@ -602,7 +602,7 @@ void BL_ConvertSensors(struct Object* blenderobject, /* Conversion succeeded, so we can set the generic props here. */ gamesensor->SetPulseMode(pos_pulsemode, neg_pulsemode, - frequency); + skipped_ticks); gamesensor->SetInvert(invert); gamesensor->SetLevel(level); gamesensor->SetTap(tap); diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index 1cb17af8325..66dd69f93c4 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -67,7 +67,7 @@ SCA_ISensor::SCA_ISensor(SCA_IObject* gameobj, m_neg_ticks = 0; m_pos_pulsemode = false; m_neg_pulsemode = false; - m_pulse_frequency = 0; + m_skipped_ticks = 0; m_state = false; m_prev_state = false; @@ -102,11 +102,11 @@ bool SCA_ISensor::IsPositiveTrigger() void SCA_ISensor::SetPulseMode(bool posmode, bool negmode, - int freq) + int skippedticks) { m_pos_pulsemode = posmode; m_neg_pulsemode = negmode; - m_pulse_frequency = freq; + m_skipped_ticks = skippedticks; } void SCA_ISensor::SetInvert(bool inv) @@ -263,7 +263,7 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr) * not set :( */ if (m_pos_pulsemode) { m_pos_ticks++; - if (m_pos_ticks > m_pulse_frequency) { + if (m_pos_ticks > m_skipped_ticks) { if ( m_state ) { ActivateControllers(logicmgr); @@ -276,7 +276,7 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr) if (m_neg_pulsemode && !m_tap) { m_neg_ticks++; - if (m_neg_ticks > m_pulse_frequency) { + if (m_neg_ticks > m_skipped_ticks) { if (!m_state ) { ActivateControllers(logicmgr); @@ -367,7 +367,7 @@ PyMethodDef SCA_ISensor::Methods[] = { PyAttributeDef SCA_ISensor::Attributes[] = { KX_PYATTRIBUTE_BOOL_RW("usePosPulseMode",SCA_ISensor,m_pos_pulsemode), KX_PYATTRIBUTE_BOOL_RW("useNegPulseMode",SCA_ISensor,m_neg_pulsemode), - KX_PYATTRIBUTE_INT_RW("frequency",0,100000,true,SCA_ISensor,m_pulse_frequency), + KX_PYATTRIBUTE_INT_RW("skippedTicks",0,100000,true,SCA_ISensor,m_skipped_ticks), KX_PYATTRIBUTE_BOOL_RW("invert",SCA_ISensor,m_invert), KX_PYATTRIBUTE_BOOL_RW_CHECK("level",SCA_ISensor,m_level,pyattr_check_level), KX_PYATTRIBUTE_BOOL_RW_CHECK("tap",SCA_ISensor,m_tap,pyattr_check_tap), @@ -376,6 +376,7 @@ PyAttributeDef SCA_ISensor::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("status", SCA_ISensor, pyattr_get_status), KX_PYATTRIBUTE_RO_FUNCTION("pos_ticks", SCA_ISensor, pyattr_get_posTicks), KX_PYATTRIBUTE_RO_FUNCTION("neg_ticks", SCA_ISensor, pyattr_get_negTicks), + KX_PYATTRIBUTE_RW_FUNCTION("frequency", SCA_ISensor, pyattr_get_frequency, pyattr_set_frequency), { NULL } //Sentinel }; @@ -444,6 +445,27 @@ int SCA_ISensor::pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrde self->m_level = false; return 0; } + +PyObject *SCA_ISensor::pyattr_get_frequency(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_ISensor *self = static_cast(self_v); + ShowDeprecationWarning("SCA_ISensor.frequency", "SCA_ISensor.skippedTicks"); + return PyLong_FromLong(self->m_skipped_ticks); +} + +int SCA_ISensor::pyattr_set_frequency(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + SCA_ISensor *self = static_cast(self_v); + ShowDeprecationWarning("SCA_ISensor.frequency", "SCA_ISensor.skippedTicks"); + if (PyLong_Check(value)) { + self->m_skipped_ticks = PyLong_AsLong(value); + return PY_SET_ATTR_SUCCESS; + } + else { + PyErr_SetString(PyExc_TypeError, "sensor.frequency = int: Sensor, expected an integer"); + return PY_SET_ATTR_FAIL; + } +} #endif // WITH_PYTHON /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index 7bbba7aaafe..1e82f3ab11f 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -57,8 +57,8 @@ protected: /** Pulse negative pulses? */ bool m_neg_pulsemode; - /** Repeat frequency in pulse mode. */ - int m_pulse_frequency; + /** Number of skipped ticks between two active pulses. */ + int m_skipped_ticks; /** Number of ticks since the last positive pulse. */ int m_pos_ticks; @@ -125,7 +125,7 @@ public: */ void SetPulseMode(bool posmode, bool negmode, - int freq); + int skippedticks); /** Set inversion of pulses on or off. */ void SetInvert(bool inv); @@ -201,6 +201,8 @@ public: static PyObject* pyattr_get_status(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_posTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_negTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_frequency(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_frequency(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index 4e93556453a..2fe4d18a7fc 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -107,7 +107,7 @@ bool SCA_RandomSensor::Evaluate() bool evaluateResult = false; - if (++m_interval > m_pulse_frequency) { + if (++m_interval > m_skipped_ticks) { bool drawResult = false; m_interval = 0; if (m_iteration > 31) { -- cgit v1.2.3 From c5a126ee70595aa187e7503d8872c689c42b5262 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 16 Apr 2015 16:07:46 +1000 Subject: Docs: BLI_rand non-obvious behavior --- source/blender/blenlib/intern/rand.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c index a03b236b5c6..66c568a7ff3 100644 --- a/source/blender/blenlib/intern/rand.c +++ b/source/blender/blenlib/intern/rand.c @@ -68,6 +68,9 @@ RNG *BLI_rng_new(unsigned int seed) return rng; } +/** + * A version of #BLI_rng_new that hashes the seed. + */ RNG *BLI_rng_new_srandom(unsigned int seed) { RNG *rng = MEM_mallocN(sizeof(*rng), "rng"); @@ -87,6 +90,9 @@ void BLI_rng_seed(RNG *rng, unsigned int seed) rng->X = (((uint64_t) seed) << 16) | LOWSEED; } +/** + * Use a hash table to create better seed. + */ void BLI_rng_srandom(RNG *rng, unsigned int seed) { BLI_rng_seed(rng, seed + hash[seed & 255]); @@ -113,11 +119,17 @@ unsigned int BLI_rng_get_uint(RNG *rng) return (unsigned int) (rng->X >> 17); } +/** + * \return Random value (0..1), but never 1.0. + */ double BLI_rng_get_double(RNG *rng) { return (double) BLI_rng_get_int(rng) / 0x80000000; } +/** + * \return Random value (0..1), but never 1.0. + */ float BLI_rng_get_float(RNG *rng) { return (float) BLI_rng_get_int(rng) / 0x80000000; @@ -172,7 +184,7 @@ void BLI_rng_get_tri_sample_float_v2( void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsigned int elem_tot) { - const size_t elem_size = (unsigned int)elem_size_i; + const size_t elem_size = (size_t)elem_size_i; unsigned int i = elem_tot; void *temp; @@ -196,6 +208,11 @@ void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsig free(temp); } +/** + * Simulate getting \a n random values. + * + * \note Useful when threaded code needs consistent values, independent of task division. + */ void BLI_rng_skip(RNG *rng, int n) { while (n--) { @@ -208,7 +225,6 @@ void BLI_rng_skip(RNG *rng, int n) /* initialize with some non-zero seed */ static RNG theBLI_rng = {611330372042337130}; -/* using hash table to create better seed */ void BLI_srandom(unsigned int seed) { BLI_rng_srandom(&theBLI_rng, seed); -- cgit v1.2.3 From 59db8d74b9f6faaed4ffdeed508ba0b769d09a50 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 16 Apr 2015 16:41:12 +1000 Subject: RNA: avoid past tense in property names --- release/scripts/startup/bl_ui/properties_physics_common.py | 2 +- source/blender/editors/space_logic/logic_window.c | 2 +- source/blender/makesrna/intern/rna_object_force.c | 2 +- source/blender/makesrna/intern/rna_sensor.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py index bb0f0cfc796..82eecf0fb5a 100644 --- a/release/scripts/startup/bl_ui/properties_physics_common.py +++ b/release/scripts/startup/bl_ui/properties_physics_common.py @@ -191,7 +191,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype): col.operator("ptcache.bake", text="Bake").bake = True sub = col.row() - sub.enabled = (cache.frames_skipped or cache.is_outdated) and enabled + sub.enabled = (cache.is_frame_skip or cache.is_outdated) and enabled sub.operator("ptcache.bake", text="Calculate To Frame").bake = False sub = col.column() diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index d4fa911f025..e78100f3ceb 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -903,7 +903,7 @@ static void draw_sensor_internal_header(uiLayout *layout, PointerRNA *ptr) sub = uiLayoutRow(row, false); uiLayoutSetActive(sub, (RNA_boolean_get(ptr, "use_pulse_true_level") || RNA_boolean_get(ptr, "use_pulse_false_level"))); - uiItemR(sub, ptr, "skipped_ticks", 0, IFACE_("Skip"), ICON_NONE); + uiItemR(sub, ptr, "tick_skip", 0, IFACE_("Skip"), ICON_NONE); row = uiLayoutRow(split, true); uiItemR(row, ptr, "use_level", UI_ITEM_R_TOGGLE, NULL, ICON_NONE); diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 4cc098fb4a6..75becb341b9 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -845,7 +845,7 @@ static void rna_def_pointcache(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Cache is outdated", ""); - prop = RNA_def_property(srna, "frames_skipped", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "is_frame_skip", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_FRAMES_SKIPPED); RNA_def_property_clear_flag(prop, PROP_EDITABLE); diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c index 3cc94039d59..cbc02858f78 100644 --- a/source/blender/makesrna/intern/rna_sensor.c +++ b/source/blender/makesrna/intern/rna_sensor.c @@ -325,7 +325,7 @@ static void rna_def_sensor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Pulse False Level", "Activate FALSE level triggering (pulse mode)"); RNA_def_property_update(prop, NC_LOGIC, NULL); - prop = RNA_def_property(srna, "skipped_ticks", PROP_INT, PROP_NONE); + prop = RNA_def_property(srna, "tick_skip", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "freq"); RNA_def_property_ui_text(prop, "Skip", "Number of logic ticks skipped between 2 active pulses " -- cgit v1.2.3 From eced87b2d6414f103911ab1daf0a28181f783cba Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 16 Apr 2015 12:37:03 +0200 Subject: Fix T44406: the Hebrew font causes trouble. Looks like the droidsans hebrew font we used back in the days had some kerning bug or so... Updated with latest version from Debian Testing repo, works nice now. --- release/datafiles/fonts/droidsans.ttf.gz | Bin 2644887 -> 2451240 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/release/datafiles/fonts/droidsans.ttf.gz b/release/datafiles/fonts/droidsans.ttf.gz index c76cf67992c..a73566ce57c 100644 Binary files a/release/datafiles/fonts/droidsans.ttf.gz and b/release/datafiles/fonts/droidsans.ttf.gz differ -- cgit v1.2.3 From 69b33b6ed3f41de3d2d6e25e67e33ad695e2e3c4 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 16 Apr 2015 13:01:57 +0200 Subject: Draw smoke domain in transparent pass. Should composite smoke domains correctly in scene - with known limitations of blending between transparent objects. --- source/blender/editors/space_view3d/drawobject.c | 34 ++++++++++++++++++------ source/blender/editors/space_view3d/drawvolume.c | 5 +--- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 10db8c38de3..ecc2499a63f 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -7501,7 +7501,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short const bool render_override = (v3d->flag2 & V3D_RENDER_OVERRIDE) != 0; const bool is_picking = (G.f & G_PICKSEL) != 0; const bool has_particles = (ob->particlesystem.first != NULL); - bool particle_skip_object = false; /* Draw particles but not their emitter object. */ + bool skip_object = false; /* Draw particles but not their emitter object. */ + SmokeModifierData *smd = NULL; if (ob != scene->obedit) { if (ob->restrictflag & OB_RESTRICT_VIEW) @@ -7525,17 +7526,37 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (ob->mode == OB_MODE_OBJECT) { ParticleSystem *psys; - particle_skip_object = render_override; + skip_object = render_override; for (psys = ob->particlesystem.first; psys; psys = psys->next) { /* Once we have found a psys which renders its emitter object, we are done. */ if (psys->part->draw & PART_DRAW_EMITTER) { - particle_skip_object = false; + skip_object = false; break; } } } } + if ((md = modifiers_findByType(ob, eModifierType_Smoke)) && (modifier_isEnabled(scene, md, eModifierMode_Realtime))) { + smd = (SmokeModifierData *)md; + + if (smd->domain) { + if (!v3d->transp && (dflag & DRAW_PICKING) == 0) { + if (!v3d->xray && !(ob->dtx & OB_DRAWXRAY)) { + /* object has already been drawn so skip drawing it */ + ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag); + return; + } + else if (v3d->xray) { + /* object has already been drawn so skip drawing it */ + ED_view3d_after_add(&v3d->afterdraw_xraytransp, base, dflag); + return; + } + } + } + } + + /* xray delay? */ if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { /* don't do xray in particle mode, need the z-buffer */ @@ -7639,7 +7660,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } } - if (!particle_skip_object) { + if (!skip_object) { /* draw outline for selected objects, mesh does itself */ if ((v3d->flag & V3D_SELECT_OUTLINE) && !render_override && ob->type != OB_MESH) { if (dt > OB_WIRE && (ob->mode & OB_MODE_EDIT) == 0 && (dflag & DRAW_SCENESET) == 0) { @@ -7858,9 +7879,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } /* draw code for smoke */ - if ((md = modifiers_findByType(ob, eModifierType_Smoke)) && (modifier_isEnabled(scene, md, eModifierMode_Realtime))) { - SmokeModifierData *smd = (SmokeModifierData *)md; - + if (smd) { #if 0 /* draw collision objects */ if ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll) { @@ -7920,7 +7939,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* don't show smoke before simulation starts, this could be made an option in the future */ if (smd->domain->fluid && CFRA >= smd->domain->point_cache[0]->startframe) { - /* get view vector */ copy_v3_v3(viewnormal, rv3d->viewinv[2]); invert_m4_m4(ob->imat, ob->obmat); diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index c0d8d139ddd..50ccde6da01 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -253,8 +253,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend); glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth); - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); + glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); /* find cube vertex that is closest to the viewer */ @@ -437,8 +436,6 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, if (gl_depth) { glEnable(GL_DEPTH_TEST); } - - glDepthMask(GL_TRUE); } #ifdef SMOKE_DEBUG_VELOCITY -- cgit v1.2.3 From 6603a10331be5186bdec8063a6eeb913a71f3c47 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 16 Apr 2015 22:26:20 +1000 Subject: Cleanup: remove redundant initializers --- source/blender/python/bmesh/bmesh_py_types.c | 22 +++++++++++----------- .../python/bmesh/bmesh_py_types_customdata.c | 12 ++++++------ .../blender/python/bmesh/bmesh_py_types_meshdata.c | 8 ++++---- .../blender/python/bmesh/bmesh_py_types_select.c | 4 ++-- source/blender/python/intern/bpy_interface.c | 2 +- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 20ee872b3be..0edca96404f 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -3251,17 +3251,17 @@ static PyObject *bpy_bmloop_repr(BPy_BMLoop *self) /* Types * ===== */ -PyTypeObject BPy_BMesh_Type = {{{0}}}; -PyTypeObject BPy_BMVert_Type = {{{0}}}; -PyTypeObject BPy_BMEdge_Type = {{{0}}}; -PyTypeObject BPy_BMFace_Type = {{{0}}}; -PyTypeObject BPy_BMLoop_Type = {{{0}}}; -PyTypeObject BPy_BMElemSeq_Type = {{{0}}}; -PyTypeObject BPy_BMVertSeq_Type = {{{0}}}; -PyTypeObject BPy_BMEdgeSeq_Type = {{{0}}}; -PyTypeObject BPy_BMFaceSeq_Type = {{{0}}}; -PyTypeObject BPy_BMLoopSeq_Type = {{{0}}}; -PyTypeObject BPy_BMIter_Type = {{{0}}}; +PyTypeObject BPy_BMesh_Type; +PyTypeObject BPy_BMVert_Type; +PyTypeObject BPy_BMEdge_Type; +PyTypeObject BPy_BMFace_Type; +PyTypeObject BPy_BMLoop_Type; +PyTypeObject BPy_BMElemSeq_Type; +PyTypeObject BPy_BMVertSeq_Type; +PyTypeObject BPy_BMEdgeSeq_Type; +PyTypeObject BPy_BMFaceSeq_Type; +PyTypeObject BPy_BMLoopSeq_Type; +PyTypeObject BPy_BMIter_Type; diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c index bfcd91ac72d..7b6e062896f 100644 --- a/source/blender/python/bmesh/bmesh_py_types_customdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c @@ -787,12 +787,12 @@ PyDoc_STRVAR(bpy_bmlayeritem_type_doc, ); -PyTypeObject BPy_BMLayerAccessVert_Type = {{{0}}}; /* bm.verts.layers */ -PyTypeObject BPy_BMLayerAccessEdge_Type = {{{0}}}; /* bm.edges.layers */ -PyTypeObject BPy_BMLayerAccessFace_Type = {{{0}}}; /* bm.faces.layers */ -PyTypeObject BPy_BMLayerAccessLoop_Type = {{{0}}}; /* bm.loops.layers */ -PyTypeObject BPy_BMLayerCollection_Type = {{{0}}}; /* bm.loops.layers.uv */ -PyTypeObject BPy_BMLayerItem_Type = {{{0}}}; /* bm.loops.layers.uv["UVMap"] */ +PyTypeObject BPy_BMLayerAccessVert_Type; /* bm.verts.layers */ +PyTypeObject BPy_BMLayerAccessEdge_Type; /* bm.edges.layers */ +PyTypeObject BPy_BMLayerAccessFace_Type; /* bm.faces.layers */ +PyTypeObject BPy_BMLayerAccessLoop_Type; /* bm.loops.layers */ +PyTypeObject BPy_BMLayerCollection_Type; /* bm.loops.layers.uv */ +PyTypeObject BPy_BMLayerItem_Type; /* bm.loops.layers.uv["UVMap"] */ PyObject *BPy_BMLayerAccess_CreatePyObject(BMesh *bm, const char htype) diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c index 94f38ffdec7..92c11a03433 100644 --- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c @@ -99,7 +99,7 @@ static PyGetSetDef bpy_bmtexpoly_getseters[] = { {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; -static PyTypeObject BPy_BMTexPoly_Type = {{{0}}}; /* bm.loops.layers.uv.active */ +static PyTypeObject BPy_BMTexPoly_Type; /* bm.loops.layers.uv.active */ static void bm_init_types_bmtexpoly(void) { @@ -212,7 +212,7 @@ static PyGetSetDef bpy_bmloopuv_getseters[] = { {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; -PyTypeObject BPy_BMLoopUV_Type = {{{0}}}; /* bm.loops.layers.uv.active */ +PyTypeObject BPy_BMLoopUV_Type; /* bm.loops.layers.uv.active */ static void bm_init_types_bmloopuv(void) { @@ -321,7 +321,7 @@ static PyGetSetDef bpy_bmvertskin_getseters[] = { {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; -static PyTypeObject BPy_BMVertSkin_Type = {{{0}}}; /* bm.loops.layers.uv.active */ +static PyTypeObject BPy_BMVertSkin_Type; /* bm.loops.layers.uv.active */ static void bm_init_types_bmvertskin(void) { @@ -750,7 +750,7 @@ static struct PyMethodDef bpy_bmdeformvert_methods[] = { {NULL, NULL, 0, NULL} }; -PyTypeObject BPy_BMDeformVert_Type = {{{0}}}; /* bm.loops.layers.uv.active */ +PyTypeObject BPy_BMDeformVert_Type; /* bm.loops.layers.uv.active */ static void bm_init_types_bmdvert(void) { diff --git a/source/blender/python/bmesh/bmesh_py_types_select.c b/source/blender/python/bmesh/bmesh_py_types_select.c index 7b792e9f08e..a2dceb2a877 100644 --- a/source/blender/python/bmesh/bmesh_py_types_select.c +++ b/source/blender/python/bmesh/bmesh_py_types_select.c @@ -342,8 +342,8 @@ static PyObject *bpy_bmeditseliter_next(BPy_BMEditSelIter *self) } } -PyTypeObject BPy_BMEditSelSeq_Type = {{{0}}}; -PyTypeObject BPy_BMEditSelIter_Type = {{{0}}}; +PyTypeObject BPy_BMEditSelSeq_Type; +PyTypeObject BPy_BMEditSelIter_Type; PyObject *BPy_BMEditSel_CreatePyObject(BMesh *bm) diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 690ea115fcd..ca61ba99f9f 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -836,7 +836,7 @@ static void bpy_module_delay_init(PyObject *bpy_proxy) static void dealloc_obj_dealloc(PyObject *self); -static PyTypeObject dealloc_obj_Type = {{{0}}}; +static PyTypeObject dealloc_obj_Type; /* use our own dealloc so we can free a property if we use one */ static void dealloc_obj_dealloc(PyObject *self) -- cgit v1.2.3 From 0b691563eaff385d23c4199c85dc47a188420284 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 17 Apr 2015 01:07:05 +1200 Subject: Fix T44408: "Rest Length" property in the Stretch To constraint was getting clipped when using Metric Units Increased the upper bound for the "Rest Length" property to cope with metric units, especially when large (i.e. > 2 m) distances are involved. It may be necessary to increase this again in the future, if even larger distances get used (though it then starts getting a bit difficulty to justify such setups). --- source/blender/makesrna/intern/rna_constraint.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 2cff8cfb376..abc489bb9b0 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -1357,7 +1357,8 @@ static void rna_def_constraint_stretch_to(BlenderRNA *brna) prop = RNA_def_property(srna, "rest_length", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "orglength"); - RNA_def_property_range(prop, 0.0, 100.f); + RNA_def_property_range(prop, 0.0, 1000.f); + RNA_def_property_ui_range(prop, 0, 100.0f, 10, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_ui_text(prop, "Original Length", "Length at rest position"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); -- cgit v1.2.3 From 6589d07c8faa6f2705530ed0dfc6ec30a77c72f2 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 17 Apr 2015 01:10:27 +1200 Subject: Action Editor: Preemptive fix for null-pointer dereference A few weeks ago, I got a random crash while testing som edge cases (IIRC, it was trying to assign an action with no active object), which I haven't been able to reproduce since then. This commit though adds some extra sanity checks here, as a user may try to assign an action to an animdata block which did not have an action already. --- source/blender/makesrna/intern/rna_space.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index ca3ea9bda81..8e3c4e5e877 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -1225,7 +1225,9 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *UNUSED(bmain), Scene *s /* set action */ if (adt) { /* fix id-count of action we're replacing */ - id_us_min(&adt->action->id); + if (adt->action) { + id_us_min(&adt->action->id); + } /* assign new action, and adjust the usercounts accordingly */ adt->action = saction->action; -- cgit v1.2.3 From a7cae2987d078da8a3cb9a293fbcdf3b6ab43ddb Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 16 Apr 2015 18:34:53 +0200 Subject: OpenGL does not like line thickness less than 1.0. Check here is not completely correct either, we should check against GL_ALIASED_LINE_WIDTH_RANGE and GL_SMOOTH_LINE_WIDTH_RANGE --- source/blender/editors/gpencil/drawgpencil.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index d4d601b1e8d..08926926861 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -121,7 +121,7 @@ static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickn /* draw stroke curve */ if (G.debug & G_DEBUG) setlinestyle(2); - glLineWidth(oldpressure * thickness); + glLineWidth(max_ff(oldpressure * thickness, 1.0)); glBegin(GL_LINE_STRIP); for (i = 0, pt = points; i < totpoints && pt; i++, pt++) { @@ -130,7 +130,7 @@ static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickn */ if (fabsf(pt->pressure - oldpressure) > 0.2f) { glEnd(); - glLineWidth(pt->pressure * thickness); + glLineWidth(max_ff(pt->pressure * thickness, 1.0f)); glBegin(GL_LINE_STRIP); /* need to roll-back one point to ensure that there are no gaps in the stroke */ @@ -415,7 +415,7 @@ static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness int i; /* draw stroke curve */ - glLineWidth(curpressure * thickness); + glLineWidth(max_ff(curpressure * thickness, 1.0f)); glBegin(GL_LINE_STRIP); for (i = 0, pt = points; i < totpoints && pt; i++, pt++) { /* if there was a significant pressure change, stop the curve, change the thickness of the stroke, @@ -425,7 +425,7 @@ static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) { glEnd(); curpressure = pt->pressure; - glLineWidth(curpressure * thickness); + glLineWidth(max_ff(curpressure * thickness, 1.0f)); glBegin(GL_LINE_STRIP); /* need to roll-back one point to ensure that there are no gaps in the stroke */ -- cgit v1.2.3 From bbae0664a3df0ec3b3dcc199ab3a52a998bc5290 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Thu, 16 Apr 2015 19:02:00 +0200 Subject: Added Support for Custom Vertex Normals to Collada exporter --- source/blender/collada/GeometryExporter.cpp | 38 ++++++++++++++++++++--------- source/blender/collada/GeometryExporter.h | 19 ++++++++++++--- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index 28cee05ec4b..1353d988137 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -82,6 +82,9 @@ void GeometryExporter::operator()(Object *ob) this->export_settings->apply_modifiers, this->export_settings->triangulate); + Mesh *mesh = (Mesh *) ob->data; + me->flag = mesh->flag; + std::string geom_id = get_geometry_id(ob, use_instantiation); std::vector nor; std::vector norind; @@ -563,6 +566,11 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me) } } +bool operator<(const Normal &a, const Normal &b) +{ + /* only needed to sort normal vectors and find() them later in a map.*/ + return a.x < b.x || (a.x == b.x && (a.y < b.y || (a.y == b.y && a.z < b.z))); +} //creates for normals void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::vector& nor) @@ -596,11 +604,18 @@ void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::v void GeometryExporter::create_normals(std::vector &normals, std::vector &polygons_normals, Mesh *me) { - std::map shared_normal_indices; + std::map shared_normal_indices; int last_normal_index = -1; MVert *verts = me->mvert; MLoop *mloops = me->mloop; + float(*lnors)[3]; + + BKE_mesh_calc_normals_split(me); + if (CustomData_has_layer(&me->ldata, CD_NORMAL)) { + lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL); + } + for (int poly_index = 0; poly_index < me->totpoly; poly_index++) { MPoly *mpoly = &me->mpoly[poly_index]; @@ -615,25 +630,24 @@ void GeometryExporter::create_normals(std::vector &normals, std::vector< last_normal_index++; } - MLoop *mloop = mloops + mpoly->loopstart; BCPolygonNormalsIndices poly_indices; for (int loop_index = 0; loop_index < mpoly->totloop; loop_index++) { - unsigned int vertex_index = mloop[loop_index].v; + unsigned int loop_idx = mpoly->loopstart + loop_index; if (mpoly->flag & ME_SMOOTH) { - if (shared_normal_indices.find(vertex_index) != shared_normal_indices.end()) - poly_indices.add_index (shared_normal_indices[vertex_index]); - else { - float vector[3]; - normal_short_to_float_v3(vector, verts[vertex_index].no); + float normalized[3]; + normalize_v3_v3(normalized, lnors[loop_idx]); + Normal n = { normalized[0], normalized[1], normalized[2] }; - Normal n = { vector[0], vector[1], vector[2] }; - normals.push_back(n); + if (shared_normal_indices.find(n) != shared_normal_indices.end()) { + poly_indices.add_index(shared_normal_indices[n]); + } + else { last_normal_index++; - poly_indices.add_index(last_normal_index); - shared_normal_indices[vertex_index] = last_normal_index; + shared_normal_indices[n] = last_normal_index; + normals.push_back(n); } } else { diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h index 4d54e79d796..69d1067e6f4 100644 --- a/source/blender/collada/GeometryExporter.h +++ b/source/blender/collada/GeometryExporter.h @@ -48,6 +48,20 @@ extern Object *bc_get_highest_selected_ancestor_or_self(Object *ob); +class Normal +{ + public: + float x; + float y; + float z; + + friend bool operator< (const Normal &, const Normal &); + +}; + +bool operator< (const Normal &, const Normal &); + + // TODO: optimize UV sets by making indexed list with duplicates removed class GeometryExporter : COLLADASW::LibraryGeometries { @@ -56,10 +70,7 @@ class GeometryExporter : COLLADASW::LibraryGeometries unsigned int v1, v2, v3, v4; }; - struct Normal - { - float x, y, z; - }; + Normal n; Scene *mScene; -- cgit v1.2.3 From afc2f415ab6997168b838102ab29ba15b306b80e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 17 Apr 2015 03:10:57 +1000 Subject: Cleanup: use const for sculpt code --- source/blender/blenkernel/BKE_brush.h | 32 +++++++++++++++------------- source/blender/blenkernel/intern/brush.c | 25 +++++++++++----------- source/blender/editors/sculpt_paint/sculpt.c | 20 ++++++++++------- 3 files changed, 42 insertions(+), 35 deletions(-) diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index f8cd51b331d..023303fe602 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -79,34 +79,36 @@ struct ImBuf *BKE_brush_gen_radial_control_imbuf(struct Brush *br, bool secondar /* unified strength size and color */ -float *BKE_brush_color_get(const struct Scene *scene, struct Brush *brush); -float *BKE_brush_secondary_color_get(const struct Scene *scene, struct Brush *brush); +const float *BKE_brush_color_get(const struct Scene *scene, const struct Brush *brush); +const float *BKE_brush_secondary_color_get(const struct Scene *scene, const struct Brush *brush); void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float color[3]); -int BKE_brush_size_get(const struct Scene *scene, struct Brush *brush); +int BKE_brush_size_get(const struct Scene *scene, const struct Brush *brush); void BKE_brush_size_set(struct Scene *scene, struct Brush *brush, int value); -float BKE_brush_unprojected_radius_get(const struct Scene *scene, struct Brush *brush); +float BKE_brush_unprojected_radius_get(const struct Scene *scene, const struct Brush *brush); void BKE_brush_unprojected_radius_set(struct Scene *scene, struct Brush *brush, float value); -float BKE_brush_alpha_get(const struct Scene *scene, struct Brush *brush); +float BKE_brush_alpha_get(const struct Scene *scene, const struct Brush *brush); void BKE_brush_alpha_set(Scene *scene, struct Brush *brush, float alpha); -float BKE_brush_weight_get(const Scene *scene, struct Brush *brush); +float BKE_brush_weight_get(const Scene *scene, const struct Brush *brush); void BKE_brush_weight_set(const Scene *scene, struct Brush *brush, float value); -int BKE_brush_use_locked_size(const struct Scene *scene, struct Brush *brush); -int BKE_brush_use_alpha_pressure(const struct Scene *scene, struct Brush *brush); -int BKE_brush_use_size_pressure(const struct Scene *scene, struct Brush *brush); +int BKE_brush_use_locked_size(const struct Scene *scene, const struct Brush *brush); +int BKE_brush_use_alpha_pressure(const struct Scene *scene, const struct Brush *brush); +int BKE_brush_use_size_pressure(const struct Scene *scene, const struct Brush *brush); /* scale unprojected radius to reflect a change in the brush's 2D size */ -void BKE_brush_scale_unprojected_radius(float *unprojected_radius, - int new_brush_size, - int old_brush_size); +void BKE_brush_scale_unprojected_radius( + float *unprojected_radius, + int new_brush_size, + int old_brush_size); /* scale brush size to reflect a change in the brush's unprojected radius */ -void BKE_brush_scale_size(int *BKE_brush_size_get, - float new_unprojected_radius, - float old_unprojected_radius); +void BKE_brush_scale_size( + int *r_brush_size, + float new_unprojected_radius, + float old_unprojected_radius); /* debugging only */ void BKE_brush_debug_print_state(struct Brush *br); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 661bf6e7d76..307f97f1344 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -782,13 +782,13 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br, * inconsistency. */ -float *BKE_brush_color_get(const struct Scene *scene, struct Brush *brush) +const float *BKE_brush_color_get(const struct Scene *scene, const struct Brush *brush) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->rgb : brush->rgb; } -float *BKE_brush_secondary_color_get(const struct Scene *scene, struct Brush *brush) +const float *BKE_brush_secondary_color_get(const struct Scene *scene, const struct Brush *brush) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->secondary_rgb : brush->secondary_rgb; @@ -819,7 +819,7 @@ void BKE_brush_size_set(Scene *scene, Brush *brush, int size) brush->size = size; } -int BKE_brush_size_get(const Scene *scene, Brush *brush) +int BKE_brush_size_get(const Scene *scene, const Brush *brush) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; int size = (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size; @@ -827,7 +827,7 @@ int BKE_brush_size_get(const Scene *scene, Brush *brush) return (int)((float)size * U.pixelsize); } -int BKE_brush_use_locked_size(const Scene *scene, Brush *brush) +int BKE_brush_use_locked_size(const Scene *scene, const Brush *brush) { const short us_flag = scene->toolsettings->unified_paint_settings.flag; @@ -836,7 +836,7 @@ int BKE_brush_use_locked_size(const Scene *scene, Brush *brush) (brush->flag & BRUSH_LOCK_SIZE); } -int BKE_brush_use_size_pressure(const Scene *scene, Brush *brush) +int BKE_brush_use_size_pressure(const Scene *scene, const Brush *brush) { const short us_flag = scene->toolsettings->unified_paint_settings.flag; @@ -845,7 +845,7 @@ int BKE_brush_use_size_pressure(const Scene *scene, Brush *brush) (brush->flag & BRUSH_SIZE_PRESSURE); } -int BKE_brush_use_alpha_pressure(const Scene *scene, Brush *brush) +int BKE_brush_use_alpha_pressure(const Scene *scene, const Brush *brush) { const short us_flag = scene->toolsettings->unified_paint_settings.flag; @@ -864,7 +864,7 @@ void BKE_brush_unprojected_radius_set(Scene *scene, Brush *brush, float unprojec brush->unprojected_radius = unprojected_radius; } -float BKE_brush_unprojected_radius_get(const Scene *scene, Brush *brush) +float BKE_brush_unprojected_radius_get(const Scene *scene, const Brush *brush) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; @@ -883,14 +883,14 @@ void BKE_brush_alpha_set(Scene *scene, Brush *brush, float alpha) brush->alpha = alpha; } -float BKE_brush_alpha_get(const Scene *scene, Brush *brush) +float BKE_brush_alpha_get(const Scene *scene, const Brush *brush) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; return (ups->flag & UNIFIED_PAINT_ALPHA) ? ups->alpha : brush->alpha; } -float BKE_brush_weight_get(const Scene *scene, Brush *brush) +float BKE_brush_weight_get(const Scene *scene, const Brush *brush) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; @@ -920,9 +920,10 @@ void BKE_brush_scale_unprojected_radius(float *unprojected_radius, } /* scale brush size to reflect a change in the brush's unprojected radius */ -void BKE_brush_scale_size(int *r_brush_size, - float new_unprojected_radius, - float old_unprojected_radius) +void BKE_brush_scale_size( + int *r_brush_size, + float new_unprojected_radius, + float old_unprojected_radius) { float scale = new_unprojected_radius; /* avoid division by zero */ diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index b14fbc40049..165de4ca791 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -705,10 +705,10 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache) /* Return modified brush strength. Includes the direction of the brush, positive * values pull vertices, negative values push. Uses tablet pressure and a * special multiplier found experimentally to scale the strength factor. */ -static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather, UnifiedPaintSettings *ups) +static float brush_strength(const Sculpt *sd, const StrokeCache *cache, const float feather, const UnifiedPaintSettings *ups) { const Scene *scene = cache->vc->scene; - Brush *brush = BKE_paint_brush(&sd->paint); + const Brush *brush = BKE_paint_brush((Paint *)&sd->paint); /* Primary strength input; square it to make lower values more sensitive */ const float root_alpha = BKE_brush_alpha_get(scene, brush); @@ -2450,20 +2450,24 @@ static void calc_sculpt_plane(Sculpt *sd, Object *ob, PBVHNode **nodes, int totn } /* Projects a point onto a plane along the plane's normal */ -static void point_plane_project(float intr[3], float co[3], float plane_normal[3], float plane_center[3]) +static void point_plane_project( + float intr[3], + const float co[3], const float plane_normal[3], const float plane_center[3]) { sub_v3_v3v3(intr, co, plane_center); mul_v3_v3fl(intr, plane_normal, dot_v3v3(plane_normal, intr)); sub_v3_v3v3(intr, co, intr); } -static int plane_trim(StrokeCache *cache, Brush *brush, float val[3]) +static int plane_trim(const StrokeCache *cache, const Brush *brush, const float val[3]) { return (!(brush->flag & BRUSH_PLANE_TRIM) || ((dot_v3v3(val, val) <= cache->radius_squared * cache->plane_trim_squared))); } -static int plane_point_side_flip(float co[3], float plane_normal[3], float plane_center[3], int flip) +static bool plane_point_side_flip( + const float co[3], const float plane_normal[3], const float plane_center[3], + const bool flip) { float delta[3]; float d; @@ -2476,7 +2480,7 @@ static int plane_point_side_flip(float co[3], float plane_normal[3], float plane return d <= 0.0f; } -static int plane_point_side(float co[3], float plane_normal[3], float plane_center[3]) +static int plane_point_side(const float co[3], const float plane_normal[3], const float plane_center[3]) { float delta[3]; @@ -2577,7 +2581,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) float temp[3]; - int flip; + bool flip; calc_sculpt_plane(sd, ob, nodes, totnode, an, fc); @@ -2655,7 +2659,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t float scale[4][4]; float tmat[4][4]; - int flip; + bool flip; calc_sculpt_plane(sd, ob, nodes, totnode, sn, fc); -- cgit v1.2.3 From 4cd37541b0e44315716d898cd84ee99d89634964 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Fri, 17 Apr 2015 02:02:30 +0200 Subject: BGE: Fix for T44374 Crash when collision sensor deactivated Don't allocate memory for sensor logic brick if it is deactivated --- source/gameengine/Converter/KX_ConvertSensors.cpp | 972 +++++++++++----------- 1 file changed, 486 insertions(+), 486 deletions(-) diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index b781e4d1cc8..854ae5b28dc 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -119,542 +119,542 @@ void BL_ConvertSensors(struct Object* blenderobject, sens = (bSensor*)blenderobject->sensors.first; while (sens) { - SCA_ISensor* gamesensor=NULL; - /* All sensors have a pulse toggle, skipped ticks parameter, and invert field. */ - /* These are extracted here, and set when the sensor is added to the */ - /* list. */ - pos_pulsemode = (sens->pulse & SENS_PULSE_REPEAT)!=0; - neg_pulsemode = (sens->pulse & SENS_NEG_PULSE_MODE)!=0; - - skipped_ticks = sens->freq; - invert = !(sens->invert == 0); - level = !(sens->level == 0); - tap = !(sens->tap == 0); - - switch (sens->type) - { - case SENS_ALWAYS: - { - - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); - if (eventmgr) - { - gamesensor = new SCA_AlwaysSensor(eventmgr, gameobj); - } - - break; - } - - case SENS_DELAY: + if (!(sens->flag & SENS_DEACTIVATE)) { + SCA_ISensor* gamesensor=NULL; + /* All sensors have a pulse toggle, skipped ticks parameter, and invert field. */ + /* These are extracted here, and set when the sensor is added to the */ + /* list. */ + pos_pulsemode = (sens->pulse & SENS_PULSE_REPEAT)!=0; + neg_pulsemode = (sens->pulse & SENS_NEG_PULSE_MODE)!=0; + + skipped_ticks = sens->freq; + invert = !(sens->invert == 0); + level = !(sens->level == 0); + tap = !(sens->tap == 0); + + switch (sens->type) { - // we can reuse the Always event manager for the delay sensor - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); - if (eventmgr) + case SENS_ALWAYS: { - bDelaySensor* delaysensor = (bDelaySensor*)sens->data; - gamesensor = new SCA_DelaySensor(eventmgr, - gameobj, - delaysensor->delay, - delaysensor->duration, - (delaysensor->flag & SENS_DELAY_REPEAT) != 0); + + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); + if (eventmgr) + { + gamesensor = new SCA_AlwaysSensor(eventmgr, gameobj); + } + + break; } - break; - } - case SENS_COLLISION: - { - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); - if (eventmgr) + case SENS_DELAY: { - // collision sensor can sense both materials and properties. - - bool bFindMaterial = false, bTouchPulse = false; - - bCollisionSensor* blendertouchsensor = (bCollisionSensor*)sens->data; - - bFindMaterial = (blendertouchsensor->mode & SENS_COLLISION_MATERIAL); - bTouchPulse = (blendertouchsensor->mode & SENS_COLLISION_PULSE); - - - const STR_String touchPropOrMatName = bFindMaterial ? - blendertouchsensor->materialName : blendertouchsensor->name; - - - if (gameobj->GetPhysicsController()) + // we can reuse the Always event manager for the delay sensor + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); + if (eventmgr) { - gamesensor = new KX_TouchSensor(eventmgr, + bDelaySensor* delaysensor = (bDelaySensor*)sens->data; + gamesensor = new SCA_DelaySensor(eventmgr, gameobj, - bFindMaterial, - bTouchPulse, - touchPropOrMatName); + delaysensor->delay, + delaysensor->duration, + (delaysensor->flag & SENS_DELAY_REPEAT) != 0); } - - } - - break; - } - case SENS_MESSAGE: - { - KX_NetworkEventManager* eventmgr = (KX_NetworkEventManager*) - logicmgr->FindEventManager(SCA_EventManager::NETWORK_EVENTMGR); - if (eventmgr) { - bMessageSensor* msgSens = (bMessageSensor*) sens->data; - - /* Get our NetworkScene */ - NG_NetworkScene *NetworkScene = kxscene->GetNetworkScene(); - /* filter on the incoming subjects, might be empty */ - const STR_String subject = msgSens->subject; - - gamesensor = new KX_NetworkMessageSensor( - eventmgr, // our eventmanager - NetworkScene, // our NetworkScene - gameobj, // the sensor controlling object - subject); // subject to filter on + break; } - break; - } - case SENS_NEAR: - { - - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); - if (eventmgr) + + case SENS_COLLISION: { - bNearSensor* blendernearsensor = (bNearSensor*)sens->data; - const STR_String nearpropertyname = (char *)blendernearsensor->name; - - //DT_ShapeHandle shape = DT_Sphere(0.0); - - // this sumoObject is not deleted by a gameobj, so delete it ourself - // later (memleaks)! - float radius = blendernearsensor->dist; - const MT_Vector3& wpos = gameobj->NodeGetWorldPosition(); - bool bFindMaterial = false; - PHY_IPhysicsController* physCtrl = kxscene->GetPhysicsEnvironment()->CreateSphereController(radius,wpos); - - //will be done in KX_TouchEventManager::RegisterSensor() - //if (isInActiveLayer) - // kxscene->GetPhysicsEnvironment()->addSensor(physCtrl); - - - - gamesensor = new KX_NearSensor(eventmgr,gameobj, - blendernearsensor->dist, - blendernearsensor->resetdist, - bFindMaterial, - nearpropertyname, - physCtrl); - + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); + if (eventmgr) + { + // collision sensor can sense both materials and properties. + + bool bFindMaterial = false, bTouchPulse = false; + + bCollisionSensor* blendertouchsensor = (bCollisionSensor*)sens->data; + + bFindMaterial = (blendertouchsensor->mode & SENS_COLLISION_MATERIAL); + bTouchPulse = (blendertouchsensor->mode & SENS_COLLISION_PULSE); + + + const STR_String touchPropOrMatName = bFindMaterial ? + blendertouchsensor->materialName : blendertouchsensor->name; + + + if (gameobj->GetPhysicsController()) + { + gamesensor = new KX_TouchSensor(eventmgr, + gameobj, + bFindMaterial, + bTouchPulse, + touchPropOrMatName); + } + + } + + break; } - break; - } - - - case SENS_KEYBOARD: - { - /* temporary input device, for converting the code for the keyboard sensor */ - - bKeyboardSensor* blenderkeybdsensor = (bKeyboardSensor*)sens->data; - SCA_KeyboardManager* eventmgr = (SCA_KeyboardManager*) logicmgr->FindEventManager(SCA_EventManager::KEYBOARD_EVENTMGR); - if (eventmgr) + case SENS_MESSAGE: { - gamesensor = new SCA_KeyboardSensor(eventmgr, - ConvertKeyCode(blenderkeybdsensor->key), - ConvertKeyCode(blenderkeybdsensor->qual), - ConvertKeyCode(blenderkeybdsensor->qual2), - (blenderkeybdsensor->type == SENS_ALL_KEYS), - blenderkeybdsensor->targetName, - blenderkeybdsensor->toggleName, - gameobj, - KX_KetsjiEngine::GetExitKey()); // blenderkeybdsensor->pad); - - } - - break; - } - case SENS_MOUSE: - { - int keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_NODEF; - int trackfocus = 0; - bMouseSensor *bmouse = (bMouseSensor *)sens->data; - - /* There are two main types of mouse sensors. If there is - * no focus-related behavior requested, we can make do - * with a basic sensor. This cuts down memory usage and - * gives a slight performance gain. */ - - SCA_MouseManager *eventmgr - = (SCA_MouseManager*) logicmgr->FindEventManager(SCA_EventManager::MOUSE_EVENTMGR); - if (eventmgr) { - - /* Determine key mode. There is at most one active mode. */ - switch (bmouse->type) { - case BL_SENS_MOUSE_LEFT_BUTTON: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_LEFTBUTTON; - break; - case BL_SENS_MOUSE_MIDDLE_BUTTON: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MIDDLEBUTTON; - break; - case BL_SENS_MOUSE_RIGHT_BUTTON: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_RIGHTBUTTON; - break; - case BL_SENS_MOUSE_WHEEL_UP: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELUP; - break; - case BL_SENS_MOUSE_WHEEL_DOWN: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELDOWN; - break; - case BL_SENS_MOUSE_MOVEMENT: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MOVEMENT; - break; - case BL_SENS_MOUSE_MOUSEOVER: - trackfocus = 1; - break; - case BL_SENS_MOUSE_MOUSEOVER_ANY: - trackfocus = 2; - break; - - default: - ; /* error */ + KX_NetworkEventManager* eventmgr = (KX_NetworkEventManager*) + logicmgr->FindEventManager(SCA_EventManager::NETWORK_EVENTMGR); + if (eventmgr) { + bMessageSensor* msgSens = (bMessageSensor*) sens->data; + + /* Get our NetworkScene */ + NG_NetworkScene *NetworkScene = kxscene->GetNetworkScene(); + /* filter on the incoming subjects, might be empty */ + const STR_String subject = msgSens->subject; + + gamesensor = new KX_NetworkMessageSensor( + eventmgr, // our eventmanager + NetworkScene, // our NetworkScene + gameobj, // the sensor controlling object + subject); // subject to filter on } - - /* initial mouse position */ - int startx = canvas->GetWidth()/2; - int starty = canvas->GetHeight()/2; - - if (!trackfocus) { - /* plain, simple mouse sensor */ - gamesensor = new SCA_MouseSensor(eventmgr, - startx,starty, - keytype, - gameobj); - } else { - /* give us a focus-aware sensor */ - bool bFindMaterial = (bmouse->mode & SENS_COLLISION_MATERIAL); - bool bXRay = (bmouse->flag & SENS_RAY_XRAY); - STR_String checkname = (bFindMaterial? bmouse->matname : bmouse->propname); - - gamesensor = new KX_MouseFocusSensor(eventmgr, - startx, - starty, - keytype, - trackfocus, - (bmouse->flag & SENS_MOUSE_FOCUS_PULSE) ? true:false, - checkname, + break; + } + case SENS_NEAR: + { + + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); + if (eventmgr) + { + bNearSensor* blendernearsensor = (bNearSensor*)sens->data; + const STR_String nearpropertyname = (char *)blendernearsensor->name; + + //DT_ShapeHandle shape = DT_Sphere(0.0); + + // this sumoObject is not deleted by a gameobj, so delete it ourself + // later (memleaks)! + float radius = blendernearsensor->dist; + const MT_Vector3& wpos = gameobj->NodeGetWorldPosition(); + bool bFindMaterial = false; + PHY_IPhysicsController* physCtrl = kxscene->GetPhysicsEnvironment()->CreateSphereController(radius,wpos); + + //will be done in KX_TouchEventManager::RegisterSensor() + //if (isInActiveLayer) + // kxscene->GetPhysicsEnvironment()->addSensor(physCtrl); + + + + gamesensor = new KX_NearSensor(eventmgr,gameobj, + blendernearsensor->dist, + blendernearsensor->resetdist, bFindMaterial, - bXRay, - kxscene, - kxengine, - gameobj); + nearpropertyname, + physCtrl); + } - } else { - // cout << "\n Could't find mouse event manager..."; - should throw an error here... + break; } - break; - } - case SENS_PROPERTY: - { - bPropertySensor* blenderpropsensor = (bPropertySensor*) sens->data; - SCA_EventManager* eventmgr - = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); - if (eventmgr) + + + case SENS_KEYBOARD: { - STR_String propname=blenderpropsensor->name; - STR_String propval=blenderpropsensor->value; - STR_String propmaxval=blenderpropsensor->maxvalue; - - SCA_PropertySensor::KX_PROPSENSOR_TYPE - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NODEF; - - /* Better do an explicit conversion here! (was implicit */ - /* before...) */ - switch (blenderpropsensor->type) { - case SENS_PROP_EQUAL: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EQUAL; - break; - case SENS_PROP_NEQUAL: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NOTEQUAL; - break; - case SENS_PROP_INTERVAL: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_INTERVAL; - break; - case SENS_PROP_CHANGED: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_CHANGED; - break; - case SENS_PROP_EXPRESSION: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EXPRESSION; - /* error */ - break; - case SENS_PROP_LESSTHAN: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_LESSTHAN; - break; - case SENS_PROP_GREATERTHAN: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_GREATERTHAN; - break; - default: - ; /* error */ + /* temporary input device, for converting the code for the keyboard sensor */ + + bKeyboardSensor* blenderkeybdsensor = (bKeyboardSensor*)sens->data; + SCA_KeyboardManager* eventmgr = (SCA_KeyboardManager*) logicmgr->FindEventManager(SCA_EventManager::KEYBOARD_EVENTMGR); + if (eventmgr) + { + gamesensor = new SCA_KeyboardSensor(eventmgr, + ConvertKeyCode(blenderkeybdsensor->key), + ConvertKeyCode(blenderkeybdsensor->qual), + ConvertKeyCode(blenderkeybdsensor->qual2), + (blenderkeybdsensor->type == SENS_ALL_KEYS), + blenderkeybdsensor->targetName, + blenderkeybdsensor->toggleName, + gameobj, + KX_KetsjiEngine::GetExitKey()); // blenderkeybdsensor->pad); + } - gamesensor = new SCA_PropertySensor(eventmgr,gameobj,propname,propval,propmaxval,propchecktype); + + break; } - - break; - } - case SENS_ACTUATOR: - { - bActuatorSensor* blenderactsensor = (bActuatorSensor*) sens->data; - // we will reuse the property event manager, there is nothing special with this sensor - SCA_EventManager* eventmgr - = logicmgr->FindEventManager(SCA_EventManager::ACTUATOR_EVENTMGR); - if (eventmgr) + case SENS_MOUSE: + { + int keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_NODEF; + int trackfocus = 0; + bMouseSensor *bmouse = (bMouseSensor *)sens->data; + + /* There are two main types of mouse sensors. If there is + * no focus-related behavior requested, we can make do + * with a basic sensor. This cuts down memory usage and + * gives a slight performance gain. */ + + SCA_MouseManager *eventmgr + = (SCA_MouseManager*) logicmgr->FindEventManager(SCA_EventManager::MOUSE_EVENTMGR); + if (eventmgr) { + + /* Determine key mode. There is at most one active mode. */ + switch (bmouse->type) { + case BL_SENS_MOUSE_LEFT_BUTTON: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_LEFTBUTTON; + break; + case BL_SENS_MOUSE_MIDDLE_BUTTON: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MIDDLEBUTTON; + break; + case BL_SENS_MOUSE_RIGHT_BUTTON: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_RIGHTBUTTON; + break; + case BL_SENS_MOUSE_WHEEL_UP: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELUP; + break; + case BL_SENS_MOUSE_WHEEL_DOWN: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELDOWN; + break; + case BL_SENS_MOUSE_MOVEMENT: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MOVEMENT; + break; + case BL_SENS_MOUSE_MOUSEOVER: + trackfocus = 1; + break; + case BL_SENS_MOUSE_MOUSEOVER_ANY: + trackfocus = 2; + break; + + default: + ; /* error */ + } + + /* initial mouse position */ + int startx = canvas->GetWidth()/2; + int starty = canvas->GetHeight()/2; + + if (!trackfocus) { + /* plain, simple mouse sensor */ + gamesensor = new SCA_MouseSensor(eventmgr, + startx,starty, + keytype, + gameobj); + } else { + /* give us a focus-aware sensor */ + bool bFindMaterial = (bmouse->mode & SENS_COLLISION_MATERIAL); + bool bXRay = (bmouse->flag & SENS_RAY_XRAY); + STR_String checkname = (bFindMaterial? bmouse->matname : bmouse->propname); + + gamesensor = new KX_MouseFocusSensor(eventmgr, + startx, + starty, + keytype, + trackfocus, + (bmouse->flag & SENS_MOUSE_FOCUS_PULSE) ? true:false, + checkname, + bFindMaterial, + bXRay, + kxscene, + kxengine, + gameobj); + } + } else { + // cout << "\n Could't find mouse event manager..."; - should throw an error here... + } + break; + } + case SENS_PROPERTY: { - STR_String propname=blenderactsensor->name; - gamesensor = new SCA_ActuatorSensor(eventmgr,gameobj,propname); + bPropertySensor* blenderpropsensor = (bPropertySensor*) sens->data; + SCA_EventManager* eventmgr + = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); + if (eventmgr) + { + STR_String propname=blenderpropsensor->name; + STR_String propval=blenderpropsensor->value; + STR_String propmaxval=blenderpropsensor->maxvalue; + + SCA_PropertySensor::KX_PROPSENSOR_TYPE + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NODEF; + + /* Better do an explicit conversion here! (was implicit */ + /* before...) */ + switch (blenderpropsensor->type) { + case SENS_PROP_EQUAL: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EQUAL; + break; + case SENS_PROP_NEQUAL: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NOTEQUAL; + break; + case SENS_PROP_INTERVAL: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_INTERVAL; + break; + case SENS_PROP_CHANGED: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_CHANGED; + break; + case SENS_PROP_EXPRESSION: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EXPRESSION; + /* error */ + break; + case SENS_PROP_LESSTHAN: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_LESSTHAN; + break; + case SENS_PROP_GREATERTHAN: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_GREATERTHAN; + break; + default: + ; /* error */ + } + gamesensor = new SCA_PropertySensor(eventmgr,gameobj,propname,propval,propmaxval,propchecktype); + } + + break; } - break; - } - - case SENS_ARMATURE: - { - bArmatureSensor* blenderarmsensor = (bArmatureSensor*) sens->data; - // we will reuse the property event manager, there is nothing special with this sensor - SCA_EventManager* eventmgr - = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); - if (eventmgr) + case SENS_ACTUATOR: { - STR_String bonename=blenderarmsensor->posechannel; - STR_String constraintname=blenderarmsensor->constraint; - gamesensor = new KX_ArmatureSensor(eventmgr,gameobj,bonename,constraintname, blenderarmsensor->type, blenderarmsensor->value); + bActuatorSensor* blenderactsensor = (bActuatorSensor*) sens->data; + // we will reuse the property event manager, there is nothing special with this sensor + SCA_EventManager* eventmgr + = logicmgr->FindEventManager(SCA_EventManager::ACTUATOR_EVENTMGR); + if (eventmgr) + { + STR_String propname=blenderactsensor->name; + gamesensor = new SCA_ActuatorSensor(eventmgr,gameobj,propname); + } + break; } - break; - } - case SENS_RADAR: - { - - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); - if (eventmgr) + case SENS_ARMATURE: { - bRadarSensor* blenderradarsensor = (bRadarSensor*) sens->data; - const STR_String radarpropertyname = blenderradarsensor->name; - - int radaraxis = blenderradarsensor->axis; - - MT_Scalar coneheight = blenderradarsensor->range; - - // janco: the angle was doubled, so should I divide the factor in 2 - // or the blenderradarsensor->angle? - // nzc: the angle is the opening angle. We need to init with - // the axis-hull angle,so /2.0. - MT_Scalar factor = tan(blenderradarsensor->angle * 0.5f); - //MT_Scalar coneradius = coneheight * (factor / 2); - MT_Scalar coneradius = coneheight * factor; - - - // this sumoObject is not deleted by a gameobj, so delete it ourself - // later (memleaks)! - MT_Scalar smallmargin = 0.0; - MT_Scalar largemargin = 0.0; - - bool bFindMaterial = false; - PHY_IPhysicsController* ctrl = kxscene->GetPhysicsEnvironment()->CreateConeController((float)coneradius, (float)coneheight); - - gamesensor = new KX_RadarSensor( - eventmgr, - gameobj, - ctrl, - coneradius, - coneheight, - radaraxis, - smallmargin, - largemargin, - bFindMaterial, - radarpropertyname); - + bArmatureSensor* blenderarmsensor = (bArmatureSensor*) sens->data; + // we will reuse the property event manager, there is nothing special with this sensor + SCA_EventManager* eventmgr + = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); + if (eventmgr) + { + STR_String bonename=blenderarmsensor->posechannel; + STR_String constraintname=blenderarmsensor->constraint; + gamesensor = new KX_ArmatureSensor(eventmgr,gameobj,bonename,constraintname, blenderarmsensor->type, blenderarmsensor->value); + } + break; } - - break; - } - case SENS_RAY: - { - bRaySensor* blenderraysensor = (bRaySensor*) sens->data; - - //blenderradarsensor->angle; - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); - if (eventmgr) + + case SENS_RADAR: { - bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL); - bool bXRay = (blenderraysensor->mode & SENS_RAY_XRAY); - - STR_String checkname = (bFindMaterial? blenderraysensor->matname : blenderraysensor->propname); - - // don't want to get rays of length 0.0 or so - double distance = (blenderraysensor->range < 0.01f ? 0.01f : blenderraysensor->range); - int axis = blenderraysensor->axisflag; - - - gamesensor = new KX_RaySensor(eventmgr, - gameobj, - checkname, - bFindMaterial, - bXRay, - distance, - axis, - kxscene); + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); + if (eventmgr) + { + bRadarSensor* blenderradarsensor = (bRadarSensor*) sens->data; + const STR_String radarpropertyname = blenderradarsensor->name; + + int radaraxis = blenderradarsensor->axis; + + MT_Scalar coneheight = blenderradarsensor->range; + + // janco: the angle was doubled, so should I divide the factor in 2 + // or the blenderradarsensor->angle? + // nzc: the angle is the opening angle. We need to init with + // the axis-hull angle,so /2.0. + MT_Scalar factor = tan(blenderradarsensor->angle * 0.5f); + //MT_Scalar coneradius = coneheight * (factor / 2); + MT_Scalar coneradius = coneheight * factor; + + + // this sumoObject is not deleted by a gameobj, so delete it ourself + // later (memleaks)! + MT_Scalar smallmargin = 0.0; + MT_Scalar largemargin = 0.0; + + bool bFindMaterial = false; + PHY_IPhysicsController* ctrl = kxscene->GetPhysicsEnvironment()->CreateConeController((float)coneradius, (float)coneheight); + + gamesensor = new KX_RadarSensor( + eventmgr, + gameobj, + ctrl, + coneradius, + coneheight, + radaraxis, + smallmargin, + largemargin, + bFindMaterial, + radarpropertyname); + + } + + break; } - break; - } - - case SENS_RANDOM: - { - bRandomSensor* blenderrndsensor = (bRandomSensor*) sens->data; - // some files didn't write randomsensor, avoid crash now for NULL ptr's - if (blenderrndsensor) + case SENS_RAY: { + bRaySensor* blenderraysensor = (bRaySensor*) sens->data; + + //blenderradarsensor->angle; SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); if (eventmgr) { - int randomSeed = blenderrndsensor->seed; - if (randomSeed == 0) + bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL); + bool bXRay = (blenderraysensor->mode & SENS_RAY_XRAY); + + STR_String checkname = (bFindMaterial? blenderraysensor->matname : blenderraysensor->propname); + + // don't want to get rays of length 0.0 or so + double distance = (blenderraysensor->range < 0.01f ? 0.01f : blenderraysensor->range); + int axis = blenderraysensor->axisflag; + + + gamesensor = new KX_RaySensor(eventmgr, + gameobj, + checkname, + bFindMaterial, + bXRay, + distance, + axis, + kxscene); + + } + break; + } + + case SENS_RANDOM: + { + bRandomSensor* blenderrndsensor = (bRandomSensor*) sens->data; + // some files didn't write randomsensor, avoid crash now for NULL ptr's + if (blenderrndsensor) + { + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); + if (eventmgr) { - randomSeed = (int)(kxengine->GetRealTime()*100000.0); - randomSeed ^= (intptr_t)blenderrndsensor; + int randomSeed = blenderrndsensor->seed; + if (randomSeed == 0) + { + randomSeed = (int)(kxengine->GetRealTime()*100000.0); + randomSeed ^= (intptr_t)blenderrndsensor; + } + gamesensor = new SCA_RandomSensor(eventmgr, gameobj, randomSeed); } - gamesensor = new SCA_RandomSensor(eventmgr, gameobj, randomSeed); } + break; } - break; - } - case SENS_JOYSTICK: - { - int joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_NODEF; - - bJoystickSensor* bjoy = (bJoystickSensor*) sens->data; - - SCA_JoystickManager *eventmgr - = (SCA_JoystickManager*) logicmgr->FindEventManager(SCA_EventManager::JOY_EVENTMGR); - if (eventmgr) + case SENS_JOYSTICK: { - int axis =0; - int axisf =0; - int button =0; - int hat =0; - int hatf =0; - int prec =0; - - switch (bjoy->type) { - case SENS_JOY_AXIS: - axis = bjoy->axis; - axisf = bjoy->axisf; - prec = bjoy->precision; - joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS; - break; - case SENS_JOY_BUTTON: - button = bjoy->button; - joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_BUTTON; - break; - case SENS_JOY_HAT: - hat = bjoy->hat; - hatf = bjoy->hatf; - joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_HAT; - break; - case SENS_JOY_AXIS_SINGLE: - axis = bjoy->axis_single; - prec = bjoy->precision; - joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS_SINGLE; - break; - default: - printf("Error: bad case statement\n"); - break; + int joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_NODEF; + + bJoystickSensor* bjoy = (bJoystickSensor*) sens->data; + + SCA_JoystickManager *eventmgr + = (SCA_JoystickManager*) logicmgr->FindEventManager(SCA_EventManager::JOY_EVENTMGR); + if (eventmgr) + { + int axis =0; + int axisf =0; + int button =0; + int hat =0; + int hatf =0; + int prec =0; + + switch (bjoy->type) { + case SENS_JOY_AXIS: + axis = bjoy->axis; + axisf = bjoy->axisf; + prec = bjoy->precision; + joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS; + break; + case SENS_JOY_BUTTON: + button = bjoy->button; + joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_BUTTON; + break; + case SENS_JOY_HAT: + hat = bjoy->hat; + hatf = bjoy->hatf; + joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_HAT; + break; + case SENS_JOY_AXIS_SINGLE: + axis = bjoy->axis_single; + prec = bjoy->precision; + joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS_SINGLE; + break; + default: + printf("Error: bad case statement\n"); + break; + } + gamesensor = new SCA_JoystickSensor( + eventmgr, + gameobj, + bjoy->joyindex, + joysticktype, + axis,axisf, + prec, + button, + hat,hatf, + (bjoy->flag & SENS_JOY_ANY_EVENT)); } - gamesensor = new SCA_JoystickSensor( - eventmgr, - gameobj, - bjoy->joyindex, - joysticktype, - axis,axisf, - prec, - button, - hat,hatf, - (bjoy->flag & SENS_JOY_ANY_EVENT)); - } - else + else + { + printf("Error there was a problem finding the event manager\n"); + } + + break; + } + default: { - printf("Error there was a problem finding the event manager\n"); } - - break; } - default: - { - } - } - if (gamesensor && !(sens->flag & SENS_DEACTIVATE)) - { - gamesensor->SetExecutePriority(executePriority++); - STR_String uniquename = sens->name; - uniquename += "#SENS#"; - uniqueint++; - CIntValue* uniqueval = new CIntValue(uniqueint); - uniquename += uniqueval->GetText(); - uniqueval->Release(); - - /* Conversion succeeded, so we can set the generic props here. */ - gamesensor->SetPulseMode(pos_pulsemode, - neg_pulsemode, - skipped_ticks); - gamesensor->SetInvert(invert); - gamesensor->SetLevel(level); - gamesensor->SetTap(tap); - gamesensor->SetName(sens->name); - - gameobj->AddSensor(gamesensor); - - // only register to manager if it's in an active layer - // Make registration dynamic: only when sensor is activated - //if (isInActiveLayer) - // gamesensor->RegisterToManager(); - - gamesensor->ReserveController(sens->totlinks); - for (int i=0;itotlinks;i++) + if (gamesensor) { - bController* linkedcont = (bController*) sens->links[i]; - if (linkedcont) { - // If the controller is deactived doesn't register it - if (!(linkedcont->flag & CONT_DEACTIVATE)) { - SCA_IController* gamecont = converter->FindGameController(linkedcont); - - if (gamecont) { - logicmgr->RegisterToSensor(gamecont,gamesensor); - } - else { - printf("Warning, sensor \"%s\" could not find its controller " - "(link %d of %d) from object \"%s\"\n" - "\tthere has been an error converting the blender controller for the game engine," - "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); + gamesensor->SetExecutePriority(executePriority++); + STR_String uniquename = sens->name; + uniquename += "#SENS#"; + uniqueint++; + CIntValue* uniqueval = new CIntValue(uniqueint); + uniquename += uniqueval->GetText(); + uniqueval->Release(); + + /* Conversion succeeded, so we can set the generic props here. */ + gamesensor->SetPulseMode(pos_pulsemode, + neg_pulsemode, + skipped_ticks); + gamesensor->SetInvert(invert); + gamesensor->SetLevel(level); + gamesensor->SetTap(tap); + gamesensor->SetName(sens->name); + + gameobj->AddSensor(gamesensor); + + // only register to manager if it's in an active layer + // Make registration dynamic: only when sensor is activated + //if (isInActiveLayer) + // gamesensor->RegisterToManager(); + + gamesensor->ReserveController(sens->totlinks); + for (int i=0;itotlinks;i++) + { + bController* linkedcont = (bController*) sens->links[i]; + if (linkedcont) { + // If the controller is deactived doesn't register it + if (!(linkedcont->flag & CONT_DEACTIVATE)) { + SCA_IController* gamecont = converter->FindGameController(linkedcont); + + if (gamecont) { + logicmgr->RegisterToSensor(gamecont,gamesensor); + } + else { + printf("Warning, sensor \"%s\" could not find its controller " + "(link %d of %d) from object \"%s\"\n" + "\tthere has been an error converting the blender controller for the game engine," + "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); + } } } + else { + printf("Warning, sensor \"%s\" has lost a link to a controller " + "(link %d of %d) from object \"%s\"\n" + "\tpossible causes are partially appended objects or an error reading the file," + "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); + } } - else { - printf("Warning, sensor \"%s\" has lost a link to a controller " - "(link %d of %d) from object \"%s\"\n" - "\tpossible causes are partially appended objects or an error reading the file," - "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); + // special case: Keyboard sensor with no link + // this combination is usually used for key logging. + if (sens->type == SENS_KEYBOARD && sens->totlinks == 0) { + // Force the registration so that the sensor runs + gamesensor->IncLink(); } + + // done with gamesensor + gamesensor->Release(); + } - // special case: Keyboard sensor with no link - // this combination is usually used for key logging. - if (sens->type == SENS_KEYBOARD && sens->totlinks == 0) { - // Force the registration so that the sensor runs - gamesensor->IncLink(); - } - - // done with gamesensor - gamesensor->Release(); - } - else if (gamesensor) - gamesensor->Release(); sens=sens->next; } -- cgit v1.2.3 From 582fa5e36e031e08b2af39d055ac6790a12941ee Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 17 Apr 2015 12:27:27 +1200 Subject: Fix for Grease Pencil and negative frames While investigating T44412, I noticed some weirdness going on when trying to draw on frame 0 (i.e. strokes were getting added to frame 1 instead). Clearly, this seemed like an off-by-one error related to clamping to prevent negative frames which was also excluding frame 0. This commit reverts the fixes made for T36831 in: rBf18f2fbb33d90ecc91e6f3d063cb9f97f217e808 After thinking this over, I think these checks against drawing on negative frames aren't needed. Even if the current userpref setting doesn't allow navigating to negative frames, this may not be true for other users that may work on the same file (in a team environment). Also, negative frame values can get set via the dopesheet. --- source/blender/blenkernel/intern/gpencil.c | 4 +--- source/blender/makesrna/intern/rna_gpencil.c | 6 ++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 17d87394118..ba4077ed70a 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -133,7 +133,7 @@ bGPDframe *gpencil_frame_addnew(bGPDlayer *gpl, int cframe) short state = 0; /* error checking (neg frame only if they are not allowed in Blender!) */ - if ((gpl == NULL) || ((U.flag & USER_NONEGFRAMES) && (cframe <= 0))) + if (gpl == NULL) return NULL; /* allocate memory for this frame */ @@ -388,8 +388,6 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, short addnew) /* error checking */ if (gpl == NULL) return NULL; - /* No reason to forbid negative frames when they are allowed in Blender! */ - if ((U.flag & USER_NONEGFRAMES) && cframe <= 0) cframe = 1; /* check if there is already an active frame */ if (gpl->actframe) { diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 6b61b37ce5c..2f4e7881843 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -568,7 +568,7 @@ static void rna_def_gpencil_frame(BlenderRNA *brna) prop = RNA_def_property(srna, "frame_number", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "framenum"); /* XXX note: this cannot occur on the same frame as another sketch */ - RNA_def_property_range(prop, MINAFRAME, MAXFRAME); + RNA_def_property_range(prop, -MAXFRAME, MAXFRAME); RNA_def_property_ui_text(prop, "Frame Number", "The frame on which this sketch appears"); /* Flags */ @@ -579,7 +579,9 @@ static void rna_def_gpencil_frame(BlenderRNA *brna) prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_FRAME_SELECT); RNA_def_property_ui_text(prop, "Select", "Frame is selected for editing in the Dope Sheet"); - + + + /* API */ func = RNA_def_function(srna, "clear", "rna_GPencil_frame_clear"); RNA_def_function_ui_description(func, "Remove all the grease pencil frame data"); } -- cgit v1.2.3 From 09f2aa938248bedebf7e801fabd833055627fe46 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 17 Apr 2015 13:32:57 +1200 Subject: Fix T44412: Crash when trying to paint on a GPencil frame when the frames are out of order --- source/blender/blenkernel/intern/gpencil.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index ba4077ed70a..38a84296ca6 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -129,7 +129,7 @@ void BKE_gpencil_free(bGPdata *gpd) /* add a new gp-frame to the given layer */ bGPDframe *gpencil_frame_addnew(bGPDlayer *gpl, int cframe) { - bGPDframe *gpf, *gf; + bGPDframe *gpf = NULL, *gf = NULL; short state = 0; /* error checking (neg frame only if they are not allowed in Blender!) */ @@ -160,8 +160,14 @@ bGPDframe *gpencil_frame_addnew(bGPDlayer *gpl, int cframe) /* check whether frame was added successfully */ if (state == -1) { + printf("Error: Frame (%d) existed already for this layer. Using existing frame\n", cframe); + + /* free the newly created one, and use the old one instead */ MEM_freeN(gpf); - printf("Error: frame (%d) existed already for this layer\n", cframe); + + /* return existing frame instead... */ + BLI_assert(gf != NULL); + gpf = gf; } else if (state == 0) { /* add to end then! */ -- cgit v1.2.3 From 50522cba927e7280fb88e216fd19278fc2290b52 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 17 Apr 2015 08:09:16 +0200 Subject: Fix T44411: poll() function of MESH_OT_knife_project was not strict enough. We need a 3DView region here, not only the 3DView... --- source/blender/editors/mesh/editmesh_knife_project.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c index 553c1faa36a..0d3cc07589b 100644 --- a/source/blender/editors/mesh/editmesh_knife_project.c +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -166,7 +166,7 @@ void MESH_OT_knife_project(wmOperatorType *ot) /* callbacks */ ot->exec = knifeproject_exec; - ot->poll = ED_operator_editmesh_view3d; + ot->poll = ED_operator_editmesh_region_view3d; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; -- cgit v1.2.3 From e05f719b8bc11457b4555bdd8bddf8fe6858ef9d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 17 Apr 2015 17:31:56 +1000 Subject: Dyntopo: avoid redundant lookup on original data --- source/blender/bmesh/intern/bmesh_log.c | 18 ++++++++++++++++++ source/blender/bmesh/intern/bmesh_log.h | 5 +++++ source/blender/editors/sculpt_paint/sculpt.c | 20 ++++++++------------ 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index d2397faa7d1..abc502dae3e 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -1086,6 +1086,24 @@ float BM_log_original_mask(BMLog *log, BMVert *v) return lv->mask; } +void BM_log_original_vert_data( + BMLog *log, BMVert *v, + const float **r_co, const short **r_no) +{ + BMLogEntry *entry = log->current_entry; + const BMLogVert *lv; + unsigned v_id = bm_log_vert_id_get(log, v); + void *key = SET_UINT_IN_POINTER(v_id); + + BLI_assert(entry); + + BLI_assert(BLI_ghash_haskey(entry->modified_verts, key)); + + lv = BLI_ghash_lookup(entry->modified_verts, key); + *r_co = lv->co; + *r_no = lv->no; +} + /************************ Debugging and Testing ***********************/ /* For internal use only (unit testing) */ diff --git a/source/blender/bmesh/intern/bmesh_log.h b/source/blender/bmesh/intern/bmesh_log.h index 2147b5c64b4..dd1772af068 100644 --- a/source/blender/bmesh/intern/bmesh_log.h +++ b/source/blender/bmesh/intern/bmesh_log.h @@ -96,6 +96,11 @@ const short *BM_log_original_vert_no(BMLog *log, BMVert *v); /* Get the logged mask of a vertex */ float BM_log_original_mask(BMLog *log, BMVert *v); +/* Get the logged data of a vertex (avoid multiple lookups) */ +void BM_log_original_vert_data( + BMLog *log, BMVert *v, + const float **r_co, const short **r_no); + /* For internal use only (unit testing) */ BMLogEntry *BM_log_current_entry(BMLog *log); struct RangeTreeUInt *BM_log_unused_ids(BMLog *log); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 165de4ca791..2c76b3dee21 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -285,26 +285,22 @@ static void sculpt_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter) { if (orig_data->unode->type == SCULPT_UNDO_COORDS) { - if (orig_data->coords) { - orig_data->co = orig_data->coords[iter->i]; + if (orig_data->bm_log) { + BM_log_original_vert_data( + orig_data->bm_log, iter->bm_vert, + &orig_data->co, &orig_data->no); } else { - orig_data->co = BM_log_original_vert_co(orig_data->bm_log, iter->bm_vert); - } - - if (orig_data->normals) { + orig_data->co = orig_data->coords[iter->i]; orig_data->no = orig_data->normals[iter->i]; } - else { - orig_data->no = BM_log_original_vert_no(orig_data->bm_log, iter->bm_vert); - } } else if (orig_data->unode->type == SCULPT_UNDO_MASK) { - if (orig_data->vmasks) { - orig_data->mask = orig_data->vmasks[iter->i]; + if (orig_data->bm_log) { + orig_data->mask = BM_log_original_mask(orig_data->bm_log, iter->bm_vert); } else { - orig_data->mask = BM_log_original_mask(orig_data->bm_log, iter->bm_vert); + orig_data->mask = orig_data->vmasks[iter->i]; } } } -- cgit v1.2.3 From 02fba106fad37647ab015c228248ac0ec13a964b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 17 Apr 2015 18:07:08 +1000 Subject: Dyntopo: save 4 bytes per BMLogVert --- source/blender/bmesh/intern/bmesh_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index abc502dae3e..4db24478152 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -115,8 +115,8 @@ struct BMLog { typedef struct { float co[3]; short no[3]; - float mask; char hflag; + float mask; } BMLogVert; typedef struct { -- cgit v1.2.3 From 479b6696932d133078690063508d8447d6dc0a28 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Fri, 17 Apr 2015 09:48:31 -0300 Subject: Fix T44336: Unable to select cycles-specific passes in UV/image editor This approach gets rid of iuser->pass for good. Also, I'm commenting out the pass increase/decrease. This was broken since multiview. I will fix it later (before 2.75), but I didn't want to get this patch mangled with that fix. Thanks Sergey Sharybin for the review and feedbacks. Reviewers: sergey Differential Revision: https://developer.blender.org/D1232 --- source/blender/blenkernel/intern/image.c | 23 +++++------ source/blender/editors/render/render_internal.c | 3 +- source/blender/editors/space_image/image_buttons.c | 18 ++++++++- source/blender/editors/space_image/image_ops.c | 44 +--------------------- source/blender/makesdna/DNA_image_types.h | 6 +-- source/blender/makesrna/intern/rna_image.c | 5 --- source/blender/makesrna/intern/rna_render.c | 9 +---- source/blender/render/extern/include/RE_pipeline.h | 2 + source/blender/render/intern/source/pipeline.c | 12 +++++- 9 files changed, 44 insertions(+), 78 deletions(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 80828533a31..bb9fdba94fa 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2475,7 +2475,7 @@ static void image_init_imageuser(Image *ima, ImageUser *iuser) RenderResult *rr = ima->rr; iuser->multi_index = 0; - iuser->layer = iuser->pass = iuser->view = 0; + iuser->layer = iuser->view = 0; iuser->passtype = SCE_PASS_COMBINED; if (rr) { @@ -2649,15 +2649,14 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser) return NULL; if (iuser) { - short index = 0, rv_index, rl_index = 0, rp_index; + short index = 0, rv_index, rl_index = 0; bool is_stereo = (iuser->flag & IMA_SHOW_STEREO) && RE_RenderResult_is_stereo(rr); rv_index = is_stereo ? iuser->multiview_eye : iuser->view; + if (RE_HasFakeLayer(rr)) rl_index += 1; 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++) { + for (rpass = rl->passes.first; rpass; rpass = rpass->next, index++) { if (iuser->layer == rl_index && iuser->passtype == rpass->passtype && rv_index == rpass->view_id) @@ -2668,20 +2667,16 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser) if (rpass) break; } - - if (rpass) { - iuser->multi_index = index; - iuser->pass = rp_index; - } - else { - iuser->multi_index = 0; - iuser->pass = 0; - } + iuser->multi_index = (rpass ? index : 0); } + if (rpass == NULL) { rl = rr->layers.first; if (rl) rpass = rl->passes.first; + + if (rpass && iuser) + iuser->passtype = rpass->passtype; } return rpass; diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index fbfe8d93a22..2f279122ae4 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -188,7 +188,7 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu * - sergey - */ /* TODO(sergey): Need to check has_combined here? */ - if (iuser->pass == 0) { + if (iuser->passtype == SCE_PASS_COMBINED) { size_t view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname); /* find current float rect for display, first case is after composite... still weak */ rectf = RE_RenderViewGetRectf(rr, view_id); @@ -519,7 +519,6 @@ static void render_image_update_pass_and_layer(RenderJob *rj, RenderResult *rr, } } - iuser->pass = sima->iuser.pass; iuser->layer = sima->iuser.layer; RE_ReleaseResult(rj->re); diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index ee298a27b25..20da0f33c7f 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -435,7 +435,7 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void * passflag |= rpass->passtype; final: - uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->internal_name), 0, 0, + uiDefButI(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->internal_name), 0, 0, UI_UNIT_X * 5, UI_UNIT_X, &iuser->passtype, (float) rpass->passtype, 0.0, 0, -1, ""); } @@ -545,6 +545,8 @@ static void image_multi_declay_cb(bContext *C, void *rr_v, void *iuser_v) } static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v) { + /* this wasn't working before multiview, it needs to be fixed, but it wasn't working anyways --dfelinto */ +#if 0 RenderResult *rr = rr_v; ImageUser *iuser = iuser_v; RenderLayer *rl = BLI_findlink(&rr->layers, iuser->layer); @@ -561,9 +563,16 @@ static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v) WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); } } +#else + (void)C; + (void)rr_v; + (void)iuser_v; +#endif } static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) { + /* this wasn't working before multiview, it needs to be fixed, but it wasn't working anyways --dfelinto */ +#if 0 ImageUser *iuser = iuser_v; if (iuser->pass > 0) { @@ -571,6 +580,11 @@ static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) BKE_image_multilayer_index(rr_v, iuser); WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); } +#else + (void)C; + (void)rr_v; + (void)iuser_v; +#endif } /* 5 view button callbacks... */ @@ -657,7 +671,7 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes /* pass */ fake_name = ui_imageuser_pass_fake_name(rl); - rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass - (fake_name ? 1 : 0)) : NULL); + rpass = (rl ? RE_pass_find_by_type(rl, iuser->passtype, ((RenderView *)rr->views.first)->name) : NULL); display_name = rpass ? rpass->internal_name : (fake_name ? fake_name : ""); but = uiDefMenuBut(block, ui_imageuser_pass_menu, rnd_pt, display_name, 0, 0, wmenu3, UI_UNIT_Y, TIP_("Select Pass")); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index aa625210464..756f90fe560 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1533,41 +1533,6 @@ static void save_image_options_to_op(SaveImageOptions *simopts, wmOperator *op) RNA_string_set(op->ptr, "filepath", simopts->filepath); } -/* returns the pass index for the view_id */ -static int get_multiview_pass_id(RenderResult *rr, ImageUser *iuser, const int view_id) -{ - RenderLayer *rl; - RenderPass *rpass; - int passtype; - short rl_index = 0, rp_index; - - if (rr == NULL || iuser == NULL) - return 0; - - if (BLI_listbase_count_ex(&rr->views, 2) < 2) - return iuser->pass; - - if (RE_HasFakeLayer(rr)) - rl_index ++; /* fake compo/sequencer layer */ - - rl = BLI_findlink(&rr->layers, rl_index); - if (!rl) return iuser->pass; - - rpass = BLI_findlink(&rl->passes, iuser->pass); - passtype = rpass->passtype; - - rp_index = 0; - for (rpass = rl->passes.first; rpass; rpass = rpass->next, rp_index++) { - if (rpass->passtype == passtype && - rpass->view_id == view_id) - { - return rp_index; - } - } - - return iuser->pass; -} - static void save_image_post(wmOperator *op, ImBuf *ibuf, Image *ima, int ok, int save_copy, const char *relbase, int relative, int do_newpath, const char *filepath) { if (ok) { @@ -1761,13 +1726,10 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI iuser.view = i; iuser.flag &= ~IMA_SHOW_STEREO; - if (rr) { - iuser.pass = get_multiview_pass_id(rr, &sima->iuser, i); + if (rr) BKE_image_multilayer_index(rr, &iuser); - } - else { + else BKE_image_multiview_index(ima, &iuser); - } ibuf = BKE_image_acquire_ibuf(sima->image, &iuser, &lock); ibuf->planes = planes; @@ -1810,9 +1772,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI if (rr) { int id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name)); - iuser.pass = get_multiview_pass_id(rr, &sima->iuser, id); iuser.view = id; - BKE_image_multilayer_index(rr, &iuser); } else { diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index 79980c6d2d5..da5eee07e52 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -55,12 +55,10 @@ typedef struct ImageUser { char ok; char multiview_eye; /* multiview current eye - for internal use of drawing routines */ + int passtype; - short multi_index, view, layer, pass; /* listbase indices, for menu browsing or retrieve buffer */ - + short multi_index, view, layer; /* listbase indices, for menu browsing or retrieve buffer */ short flag; - short passtype; - } ImageUser; typedef struct ImageAnim { diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index bac5c4aadba..8b464e74569 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -538,11 +538,6 @@ static void rna_def_imageuser(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* image_multi_cb */ RNA_def_property_ui_text(prop, "Layer", "Layer in multilayer image"); - prop = RNA_def_property(srna, "multilayer_pass", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "pass"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* image_multi_cb */ - RNA_def_property_ui_text(prop, "Pass", "Pass in multilayer image"); - prop = RNA_def_property(srna, "multilayer_view", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "view"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* image_multi_cb */ diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 94fabb857e3..2f2d72577d5 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -384,14 +384,7 @@ static PointerRNA rna_BakePixel_next_get(PointerRNA *ptr) static RenderPass *rna_RenderPass_find_by_type(RenderLayer *rl, int passtype, const char *view) { - RenderPass *rp; - for (rp = rl->passes.first; rp; rp = rp->next) { - if (rp->passtype == passtype) { - if (STREQ(rp->view, view)) - return rp; - } - } - return NULL; + return RE_pass_find_by_type(rl, passtype, view); } #else /* RNA_RUNTIME */ diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 482677c7585..20678b29d0e 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -315,6 +315,8 @@ int RE_seq_render_active(struct Scene *scene, struct RenderData *rd); bool RE_layers_have_name(struct RenderResult *result); +struct RenderPass *RE_pass_find_by_type(struct RenderLayer *rl, int passtype, const char *viewname); + /* shaded view or baking options */ #define RE_BAKE_LIGHT 0 /* not listed in rna_scene.c -> can't be enabled! */ #define RE_BAKE_ALL 1 diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 24e66cbf3cb..e9b0a2bcbf4 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -3856,4 +3856,14 @@ bool RE_layers_have_name(struct RenderResult *rr) return false; } - +RenderPass *RE_pass_find_by_type(RenderLayer *rl, int passtype, const char *viewname) +{ + RenderPass *rp; + for (rp = rl->passes.first; rp; rp = rp->next) { + if (rp->passtype == passtype) { + if (STREQ(rp->view, viewname)) + return rp; + } + } + return NULL; +} -- cgit v1.2.3 From cd729e9a4ee16300ccf9ec47c73af440d195c792 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Fri, 17 Apr 2015 10:38:17 -0300 Subject: Image Editor: Fix passes increase/decrease buttons This was half-broken even in 2.74 (if you were using compositor), multiview did us the favour of breaking this for all cases (you are welcome). It is all working now. --- source/blender/editors/space_image/image_buttons.c | 67 +++++++++++++--------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 20da0f33c7f..cb490eb03a7 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -545,46 +545,61 @@ static void image_multi_declay_cb(bContext *C, void *rr_v, void *iuser_v) } static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v) { - /* this wasn't working before multiview, it needs to be fixed, but it wasn't working anyways --dfelinto */ -#if 0 RenderResult *rr = rr_v; ImageUser *iuser = iuser_v; - RenderLayer *rl = BLI_findlink(&rr->layers, iuser->layer); + RenderLayer *rl; + RenderPass *rp; + RenderPass *next = NULL; + int layer = iuser->layer; - if (rl) { - int tot = BLI_listbase_count(&rl->passes); + if (RE_HasFakeLayer(rr)) layer -= 1; + rl = BLI_findlink(&rr->layers, layer); - if (RE_HasFakeLayer(rr)) - tot++; /* fake compo/sequencer layer */ + if (rl) { + for (rp = rl->passes.first; rp; rp = rp->next) { + if (rp->passtype == iuser->passtype) { + next = rp->next; + if (next && (next->passtype == rp->passtype)) + next = next->next; + break; + } + } - if (iuser->pass < tot - 1) { - iuser->pass++; - BKE_image_multilayer_index(rr, iuser); + if (next != NULL && iuser->passtype != next->passtype) { + iuser->passtype = next->passtype; + BKE_image_multilayer_index(rr, iuser); WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); } } -#else - (void)C; - (void)rr_v; - (void)iuser_v; -#endif } static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) { - /* this wasn't working before multiview, it needs to be fixed, but it wasn't working anyways --dfelinto */ -#if 0 + RenderResult *rr = rr_v; ImageUser *iuser = iuser_v; + RenderLayer *rl; + RenderPass *rp; + RenderPass *prev= NULL; + int layer = iuser->layer; - if (iuser->pass > 0) { - iuser->pass--; - BKE_image_multilayer_index(rr_v, iuser); - WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); + if (RE_HasFakeLayer(rr)) layer -= 1; + rl = BLI_findlink(&rr->layers, layer); + + if (rl) { + for (rp = rl->passes.last; rp; rp = rp->prev) { + if (rp->passtype == iuser->passtype) { + prev = rp->prev; + if (prev && (prev->passtype == rp->passtype)) + prev = prev->prev; + break; + } + } + + if (prev != NULL && iuser->passtype != prev->passtype) { + iuser->passtype = prev->passtype; + BKE_image_multilayer_index(rr, iuser); + WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); + } } -#else - (void)C; - (void)rr_v; - (void)iuser_v; -#endif } /* 5 view button callbacks... */ -- cgit v1.2.3 From 80b4b437275646c8d10910880f31783dc26a8948 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Fri, 17 Apr 2015 10:41:31 -0300 Subject: Code cleanup (for previous commit) --- source/blender/editors/space_image/image_buttons.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index cb490eb03a7..c398d32dad5 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -552,14 +552,16 @@ static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v) RenderPass *next = NULL; int layer = iuser->layer; - if (RE_HasFakeLayer(rr)) layer -= 1; + if (RE_HasFakeLayer(rr)) + layer -= 1; + rl = BLI_findlink(&rr->layers, layer); if (rl) { for (rp = rl->passes.first; rp; rp = rp->next) { if (rp->passtype == iuser->passtype) { next = rp->next; - if (next && (next->passtype == rp->passtype)) + if (next != NULL && next->passtype == rp->passtype) next = next->next; break; } @@ -581,14 +583,16 @@ static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) RenderPass *prev= NULL; int layer = iuser->layer; - if (RE_HasFakeLayer(rr)) layer -= 1; + if (RE_HasFakeLayer(rr)) + layer -= 1; + rl = BLI_findlink(&rr->layers, layer); if (rl) { for (rp = rl->passes.last; rp; rp = rp->prev) { if (rp->passtype == iuser->passtype) { prev = rp->prev; - if (prev && (prev->passtype == rp->passtype)) + if (prev != NULL && prev->passtype == rp->passtype) prev = prev->prev; break; } -- cgit v1.2.3 From 15d3d8560d7cee0def23b8a1145ddd0801fca8ea Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 17 Apr 2015 20:55:33 +1000 Subject: Cleanup: remove unused face normals also use const --- extern/rangetree/range_tree_c_api.h | 6 +++--- source/blender/blenkernel/BKE_paint.h | 1 - source/blender/blenkernel/intern/paint.c | 2 -- source/blender/editors/sculpt_paint/sculpt.c | 25 +++---------------------- 4 files changed, 6 insertions(+), 28 deletions(-) diff --git a/extern/rangetree/range_tree_c_api.h b/extern/rangetree/range_tree_c_api.h index f0a2af4a29a..6abfb6bd55e 100644 --- a/extern/rangetree/range_tree_c_api.h +++ b/extern/rangetree/range_tree_c_api.h @@ -14,8 +14,8 @@ 02110-1301, USA. */ -#ifndef RANGE_TREE_C_API_H -#define RANGE_TREE_C_API_H +#ifndef __RANGE_TREE_C_API_H__ +#define __RANGE_TREE_C_API_H__ #ifdef __cplusplus extern "C" { @@ -59,4 +59,4 @@ unsigned int range_tree_uint_allocation_lower_bound(const RangeTreeUInt *rt); } #endif -#endif /* __DUALCON_H__ */ +#endif /* __RANGE_TREE_C_API_H__ */ diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 53c2a82fb8e..34b645ea62c 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -156,7 +156,6 @@ typedef struct SculptSession { struct MPoly *mpoly; struct MLoop *mloop; int totvert, totpoly; - float (*face_normals)[3]; struct KeyBlock *kb; float *vmask; diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index fd5d14b6cfc..3900ba8b5ea 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -788,7 +788,6 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, ss->mvert = NULL; ss->mpoly = NULL; ss->mloop = NULL; - ss->face_normals = NULL; } else { ss->totvert = me->totvert; @@ -796,7 +795,6 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, ss->mvert = me->mvert; ss->mpoly = me->mpoly; ss->mloop = me->mloop; - ss->face_normals = NULL; ss->multires = NULL; ss->vmask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK); } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 2c76b3dee21..67d81ab75b7 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -182,8 +182,6 @@ typedef struct StrokeCache { ViewContext *vc; Brush *brush; - float (*face_norms)[3]; /* Copy of the mesh faces' normals */ - float special_rotation; float grab_delta[3], grab_delta_symmetry[3]; float old_grab_location[3], orig_grab_location[3]; @@ -345,9 +343,7 @@ static int sculpt_stroke_dynamic_topology(const SculptSession *ss, static void paint_mesh_restore_co(Sculpt *sd, Object *ob) { SculptSession *ss = ob->sculpt; - StrokeCache *cache = ss->cache; const Brush *brush = BKE_paint_brush(&sd->paint); - int i; PBVHNode **nodes; int n, totnode; @@ -400,12 +396,6 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob) } } - if (ss->face_normals) { - for (i = 0; i < ss->totpoly; i++) { - copy_v3_v3(ss->face_normals[i], cache->face_norms[i]); - } - } - if (nodes) MEM_freeN(nodes); } @@ -505,7 +495,7 @@ static void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test) } } -BLI_INLINE bool sculpt_brush_test_clipping(SculptBrushTest *test, const float co[3]) +BLI_INLINE bool sculpt_brush_test_clipping(const SculptBrushTest *test, const float co[3]) { RegionView3D *rv3d = test->clip_rv3d; return (rv3d && (ED_view3d_clipping_test(rv3d, co, true))); @@ -543,7 +533,7 @@ static bool sculpt_brush_test_sq(SculptBrushTest *test, const float co[3]) } } -static bool sculpt_brush_test_fast(SculptBrushTest *test, float co[3]) +static bool sculpt_brush_test_fast(const SculptBrushTest *test, const float co[3]) { if (sculpt_brush_test_clipping(test, co)) { return 0; @@ -551,7 +541,7 @@ static bool sculpt_brush_test_fast(SculptBrushTest *test, float co[3]) return len_squared_v3v3(co, test->location) <= test->radius_squared; } -static bool sculpt_brush_test_cube(SculptBrushTest *test, float co[3], float local[4][4]) +static bool sculpt_brush_test_cube(SculptBrushTest *test, const float co[3], float local[4][4]) { float side = M_SQRT1_2; float local_co[3]; @@ -3503,8 +3493,6 @@ static const char *sculpt_tool_name(Sculpt *sd) static void sculpt_cache_free(StrokeCache *cache) { - if (cache->face_norms) - MEM_freeN(cache->face_norms); if (cache->dial) MEM_freeN(cache->dial); MEM_freeN(cache); @@ -3764,13 +3752,6 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio /* Make copies of the mesh vertex locations and normals for some tools */ if (brush->flag & BRUSH_ANCHORED) { - if (ss->face_normals) { - cache->face_norms = MEM_mallocN(sizeof(float) * 3 * ss->totpoly, "Sculpt face norms"); - for (i = 0; i < ss->totpoly; ++i) { - copy_v3_v3(cache->face_norms[i], ss->face_normals[i]); - } - } - cache->original = 1; } -- cgit v1.2.3 From 3a015bb76b0325cdf542356c89f2b7d2b196895a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 17 Apr 2015 18:55:47 +0500 Subject: Depsgraph: Report total time spent on scene update Previously was only per-thread timing. --- source/blender/blenkernel/intern/scene.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 60b05cea21b..07e2a186444 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1479,6 +1479,7 @@ static void scene_update_object_add_task(void *node, void *user_data) static void print_threads_statistics(ThreadedObjectUpdateState *state) { int i, tot_thread; + double finish_time; if ((G.debug & G_DEBUG_DEPSGRAPH) == 0) { return; @@ -1504,6 +1505,7 @@ static void print_threads_statistics(ThreadedObjectUpdateState *state) } } #else + finish_time = PIL_check_seconds_timer(); tot_thread = BLI_system_thread_count(); for (i = 0; i < tot_thread; i++) { @@ -1533,6 +1535,9 @@ static void print_threads_statistics(ThreadedObjectUpdateState *state) BLI_freelistN(&state->statistics[i]); } + if (state->has_updated_objects) { + printf("Scene update in %f sec\n", finish_time - state->base_time); + } #endif } -- cgit v1.2.3 From fa0f936a64acf6620991f1ba6f968cd25edd17df Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 17 Apr 2015 16:03:14 +0200 Subject: Fix BPlayer (c) --- source/blenderplayer/bad_level_call_stubs/stubs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 8fbc3c5be9c..f8a42159c27 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -235,6 +235,9 @@ void RE_engine_get_camera_model_matrix(struct RenderEngine *engine, struct Objec float RE_engine_get_camera_shift_x(struct RenderEngine *engine, struct Object *camera) RET_ZERO void RE_SetActiveRenderView(struct Render *re, const char *viewname) {STUB_ASSERT(0);} +struct RenderPass *RE_pass_find_by_type(struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL +bool RE_HasFakeLayer(RenderResult *res) RET_ZERO + /* zbuf.c stub */ void antialias_tagbuf(int xsize, int ysize, char *rectmove) RET_NONE void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nbd, int xsize, int ysize, float *newrect, float *imgrect, float *vecbufrect, float *zbufrect) RET_NONE -- cgit v1.2.3 From 45e929dc127e5b037c9e073ad84c3d76ca11ac50 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 18 Apr 2015 00:11:03 +1000 Subject: Cleanup: redundant casts --- source/blender/bmesh/intern/bmesh_log.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index 4db24478152..1f64f7b74cc 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -593,8 +593,8 @@ int BM_log_length(const BMLog *log) /* Apply a consistent ordering to BMesh vertices */ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log) { - void *varr; - void *farr; + unsigned int *varr; + unsigned int *farr; GHash *id_to_idx; @@ -602,41 +602,37 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log) BMVert *v; BMFace *f; - int i; + unsigned int i; /* Put all vertex IDs into an array */ - i = 0; varr = MEM_mallocN(sizeof(int) * (size_t)bm->totvert, __func__); - BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) { - ((unsigned int *)varr)[i++] = bm_log_vert_id_get(log, v); + BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) { + varr[i] = bm_log_vert_id_get(log, v); } /* Put all face IDs into an array */ - i = 0; farr = MEM_mallocN(sizeof(int) * (size_t)bm->totface, __func__); - BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) { - ((unsigned int *)farr)[i++] = bm_log_face_id_get(log, f); + BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) { + farr[i] = bm_log_face_id_get(log, f); } /* Create BMVert index remap array */ id_to_idx = bm_log_compress_ids_to_indices(varr, (unsigned int)bm->totvert); - i = 0; - BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) { const unsigned id = bm_log_vert_id_get(log, v); const void *key = SET_UINT_IN_POINTER(id); const void *val = BLI_ghash_lookup(id_to_idx, key); - ((unsigned int *)varr)[i++] = GET_UINT_FROM_POINTER(val); + varr[i] = GET_UINT_FROM_POINTER(val); } BLI_ghash_free(id_to_idx, NULL, NULL); /* Create BMFace index remap array */ id_to_idx = bm_log_compress_ids_to_indices(farr, (unsigned int)bm->totface); - i = 0; - BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) { + BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) { const unsigned id = bm_log_face_id_get(log, f); const void *key = SET_UINT_IN_POINTER(id); const void *val = BLI_ghash_lookup(id_to_idx, key); - ((unsigned int *)farr)[i++] = GET_UINT_FROM_POINTER(val); + farr[i] = GET_UINT_FROM_POINTER(val); } BLI_ghash_free(id_to_idx, NULL, NULL); -- cgit v1.2.3 From 394c5318c6fe981f94fc78f312fc0295209288dc Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Fri, 17 Apr 2015 12:25:37 -0300 Subject: Bake-API: reduce memory footprint when baking more than one object (Fix T41092) Combine all the highpoly pixel arrays into a single array with a lookup object_id for each of the highpoly objects. Note: This changes the Bake API, external engines should refer to the bake_api.c for the latest API. Many thanks for Sergey Sharybin for the complete review, changes suggestion and feedback. (you rock!) Reviewers: sergey Subscribers: pildanovak, marcclintdion, monio, metalliandy, brecht Maniphest Tasks: T41092 Differential Revision: https://developer.blender.org/D772 --- intern/cycles/blender/addon/__init__.py | 4 +- intern/cycles/blender/addon/engine.py | 4 +- intern/cycles/blender/blender_python.cpp | 6 +-- intern/cycles/blender/blender_session.cpp | 12 +++-- intern/cycles/blender/blender_session.h | 2 +- intern/cycles/render/bake.cpp | 5 ++ intern/cycles/render/bake.h | 1 + source/blender/editors/object/object_bake_api.c | 18 ++++---- source/blender/makesrna/intern/rna_render.c | 13 +++++- source/blender/render/extern/include/RE_bake.h | 7 ++- source/blender/render/extern/include/RE_engine.h | 2 +- source/blender/render/intern/source/bake_api.c | 54 +++++++++++----------- .../blender/render/intern/source/external_engine.c | 5 +- 13 files changed, 77 insertions(+), 56 deletions(-) diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index 5b0c6a84bb5..9c78e0c9a62 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -65,8 +65,8 @@ class CyclesRender(bpy.types.RenderEngine): def render(self, scene): engine.render(self) - def bake(self, scene, obj, pass_type, pixel_array, num_pixels, depth, result): - engine.bake(self, obj, pass_type, pixel_array, num_pixels, depth, result) + def bake(self, scene, obj, pass_type, object_id, pixel_array, num_pixels, depth, result): + engine.bake(self, obj, pass_type, object_id, pixel_array, num_pixels, depth, result) # viewport render def view_update(self, context): diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index e50a8e45b52..4187e2381ac 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -59,11 +59,11 @@ def render(engine): _cycles.render(engine.session) -def bake(engine, obj, pass_type, pixel_array, num_pixels, depth, result): +def bake(engine, obj, pass_type, object_id, pixel_array, num_pixels, depth, result): import _cycles session = getattr(engine, "session", None) if session is not None: - _cycles.bake(engine.session, obj.as_pointer(), pass_type, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer()) + _cycles.bake(engine.session, obj.as_pointer(), pass_type, object_id, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer()) def reset(engine, data, scene): diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index b9521090c93..200003fbf70 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -189,9 +189,9 @@ static PyObject *bake_func(PyObject * /*self*/, PyObject *args) PyObject *pysession, *pyobject; PyObject *pypixel_array, *pyresult; const char *pass_type; - int num_pixels, depth; + int num_pixels, depth, object_id; - if(!PyArg_ParseTuple(args, "OOsOiiO", &pysession, &pyobject, &pass_type, &pypixel_array, &num_pixels, &depth, &pyresult)) + if(!PyArg_ParseTuple(args, "OOsiOiiO", &pysession, &pyobject, &pass_type, &object_id, &pypixel_array, &num_pixels, &depth, &pyresult)) return NULL; BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession); @@ -208,7 +208,7 @@ static PyObject *bake_func(PyObject * /*self*/, PyObject *args) python_thread_state_save(&session->python_thread_state); - session->bake(b_object, pass_type, b_bake_pixel, (size_t)num_pixels, depth, (float *)b_result); + session->bake(b_object, pass_type, object_id, b_bake_pixel, (size_t)num_pixels, depth, (float *)b_result); python_thread_state_restore(&session->python_thread_state); diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index bdacea0cd7e..897514668f6 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -511,18 +511,22 @@ void BlenderSession::render() sync = NULL; } -static void populate_bake_data(BakeData *data, BL::BakePixel pixel_array, const int num_pixels) +static void populate_bake_data(BakeData *data, const int object_id, BL::BakePixel pixel_array, const int num_pixels) { BL::BakePixel bp = pixel_array; int i; for(i=0; i < num_pixels; i++) { - data->set(i, bp.primitive_id(), bp.uv(), bp.du_dx(), bp.du_dy(), bp.dv_dx(), bp.dv_dy()); + if(bp.object_id() == object_id) { + data->set(i, bp.primitive_id(), bp.uv(), bp.du_dx(), bp.du_dy(), bp.dv_dx(), bp.dv_dy()); + } else { + data->set_null(i); + } bp = bp.next(); } } -void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, const size_t num_pixels, const int /*depth*/, float result[]) +void BlenderSession::bake(BL::Object b_object, const string& pass_type, const int object_id, BL::BakePixel pixel_array, const size_t num_pixels, const int /*depth*/, float result[]) { ShaderEvalType shader_type = get_shader_type(pass_type); size_t object_index = OBJECT_NONE; @@ -578,7 +582,7 @@ void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::Bake BakeData *bake_data = scene->bake_manager->init(object, tri_offset, num_pixels); - populate_bake_data(bake_data, pixel_array, num_pixels); + populate_bake_data(bake_data, object_id, pixel_array, num_pixels); /* set number of samples */ session->tile_manager.set_samples(session_params.samples); diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index b6fc709b92e..708776dc8ca 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -52,7 +52,7 @@ public: /* offline render */ void render(); - void bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, const size_t num_pixels, const int depth, float pixels[]); + void bake(BL::Object b_object, const string& pass_type, const int object_id, BL::BakePixel pixel_array, const size_t num_pixels, const int depth, float pixels[]); void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile); void write_render_tile(RenderTile& rtile); diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp index c5201366bb2..4bbac0f91d1 100644 --- a/intern/cycles/render/bake.cpp +++ b/intern/cycles/render/bake.cpp @@ -55,6 +55,11 @@ void BakeData::set(int i, int prim, float uv[2], float dudx, float dudy, float d m_dvdy[i] = dvdy; } +void BakeData::set_null(int i) +{ + m_primitive[i] = -1; +} + int BakeData::object() { return m_object; diff --git a/intern/cycles/render/bake.h b/intern/cycles/render/bake.h index 9ff10dafa0e..14d975a4b4e 100644 --- a/intern/cycles/render/bake.h +++ b/intern/cycles/render/bake.h @@ -31,6 +31,7 @@ public: ~BakeData(); void set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy); + void set_null(int i); int object(); size_t size(); uint4 data(int i); diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index d492a4b9dda..578335a385b 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -574,6 +574,7 @@ static int bake( float *result = NULL; BakePixel *pixel_array_low = NULL; + BakePixel *pixel_array_high = NULL; const bool is_save_internal = (save_mode == R_BAKE_SAVE_INTERNAL); const bool is_noncolor = is_noncolor_pass(pass_type); @@ -682,6 +683,7 @@ static int bake( } pixel_array_low = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels low poly"); + pixel_array_high = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly"); result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels"); /* get the mesh as it arrives in the renderer */ @@ -755,8 +757,6 @@ static int bake( /* initialize highpoly_data */ highpoly[i].ob = ob_iter; highpoly[i].restrict_flag = ob_iter->restrictflag; - highpoly[i].pixel_array = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly"); - /* triangulating so BVH returns the primitive_id that will be used for rendering */ highpoly[i].tri_mod = ED_object_modifier_add( @@ -790,7 +790,7 @@ static int bake( /* populate the pixel arrays with the corresponding face data for each high poly object */ if (!RE_bake_pixels_populate_from_objects( - me_low, pixel_array_low, highpoly, tot_highpoly, num_pixels, ob_cage != NULL, + me_low, pixel_array_low, pixel_array_high, highpoly, tot_highpoly, num_pixels, ob_cage != NULL, cage_extrusion, ob_low->obmat, (ob_cage ? ob_cage->obmat : ob_low->obmat), me_cage)) { BKE_report(reports, RPT_ERROR, "Error handling selected objects"); @@ -799,8 +799,8 @@ static int bake( /* the baking itself */ for (i = 0; i < tot_highpoly; i++) { - ok = RE_bake_engine(re, highpoly[i].ob, highpoly[i].pixel_array, num_pixels, - depth, pass_type, result); + ok = RE_bake_engine(re, highpoly[i].ob, i, pixel_array_high, + num_pixels, depth, pass_type, result); if (!ok) { BKE_reportf(reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2); goto cage_cleanup; @@ -826,7 +826,7 @@ cage_cleanup: ob_low->restrictflag &= ~OB_RESTRICT_RENDER; if (RE_bake_has_engine(re)) { - ok = RE_bake_engine(re, ob_low, pixel_array_low, num_pixels, depth, pass_type, result); + ok = RE_bake_engine(re, ob_low, 0, pixel_array_low, num_pixels, depth, pass_type, result); } else { BKE_report(reports, RPT_ERROR, "Current render engine does not support baking"); @@ -990,9 +990,6 @@ cleanup: for (i = 0; i < tot_highpoly; i++) { highpoly[i].ob->restrictflag = highpoly[i].restrict_flag; - if (highpoly[i].pixel_array) - MEM_freeN(highpoly[i].pixel_array); - if (highpoly[i].tri_mod) ED_object_modifier_remove(reports, bmain, highpoly[i].ob, highpoly[i].tri_mod); @@ -1010,6 +1007,9 @@ cleanup: if (pixel_array_low) MEM_freeN(pixel_array_low); + if (pixel_array_high) + MEM_freeN(pixel_array_high); + if (bake_images.data) MEM_freeN(bake_images.data); diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 2f2d72577d5..dbb572b7333 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -154,8 +154,10 @@ static void engine_render(RenderEngine *engine, struct Scene *scene) RNA_parameter_list_free(&list); } -static void engine_bake(RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type, - const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result) +static void engine_bake(RenderEngine *engine, struct Scene *scene, + struct Object *object, const int pass_type, + const int object_id, const struct BakePixel *pixel_array, + const int num_pixels, const int depth, void *result) { extern FunctionRNA rna_RenderEngine_bake_func; PointerRNA ptr; @@ -169,6 +171,7 @@ static void engine_bake(RenderEngine *engine, struct Scene *scene, struct Object RNA_parameter_set_lookup(&list, "scene", &scene); RNA_parameter_set_lookup(&list, "object", &object); RNA_parameter_set_lookup(&list, "pass_type", &pass_type); + RNA_parameter_set_lookup(&list, "object_id", &object_id); RNA_parameter_set_lookup(&list, "pixel_array", &pixel_array); RNA_parameter_set_lookup(&list, "num_pixels", &num_pixels); RNA_parameter_set_lookup(&list, "depth", &depth); @@ -423,6 +426,8 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_REQUIRED); prop = RNA_def_enum(func, "pass_type", render_pass_type_items, 0, "Pass", "Pass to bake"); RNA_def_property_flag(prop, PROP_REQUIRED); + prop = RNA_def_int(func, "object_id", 0, 0, INT_MAX, "Object Id", "Id of the current object being baked in relation to the others", 0, INT_MAX); + RNA_def_property_flag(prop, PROP_REQUIRED); prop = RNA_def_pointer(func, "pixel_array", "BakePixel", "", ""); RNA_def_property_flag(prop, PROP_REQUIRED); prop = RNA_def_int(func, "num_pixels", 0, 0, INT_MAX, "Number of Pixels", "Size of the baking batch", 0, INT_MAX); @@ -816,6 +821,10 @@ static void rna_def_render_bake_pixel(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "primitive_id"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop = RNA_def_property(srna, "object_id", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "object_id"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop = RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE); RNA_def_property_array(prop, 2); RNA_def_property_float_sdna(prop, NULL, "uv"); diff --git a/source/blender/render/extern/include/RE_bake.h b/source/blender/render/extern/include/RE_bake.h index ffc1246b878..e8a8986714d 100644 --- a/source/blender/render/extern/include/RE_bake.h +++ b/source/blender/render/extern/include/RE_bake.h @@ -50,14 +50,13 @@ typedef struct BakeImages { } BakeImages; typedef struct BakePixel { - int primitive_id; + int primitive_id, object_id; float uv[2]; float du_dx, du_dy; float dv_dx, dv_dy; } BakePixel; typedef struct BakeHighPolyData { - struct BakePixel *pixel_array; struct Object *ob; struct ModifierData *tri_mod; struct Mesh *me; @@ -72,7 +71,7 @@ typedef struct BakeHighPolyData { bool RE_bake_has_engine(struct Render *re); bool RE_bake_engine( - struct Render *re, struct Object *object, const BakePixel pixel_array[], + struct Render *re, struct Object *object, const int object_id, const BakePixel pixel_array[], const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]); /* bake.c */ @@ -82,7 +81,7 @@ bool RE_bake_internal( const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]); bool RE_bake_pixels_populate_from_objects( - struct Mesh *me_low, BakePixel pixel_array_from[], + struct Mesh *me_low, BakePixel pixel_array_from[], BakePixel pixel_array_to[], BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage, const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage); diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 4857c409f08..9d3c74163d5 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -88,7 +88,7 @@ typedef struct RenderEngineType { void (*update)(struct RenderEngine *engine, struct Main *bmain, struct Scene *scene); void (*render)(struct RenderEngine *engine, struct Scene *scene); - void (*bake)(struct RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type, const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result); + void (*bake)(struct RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type, const int object_id, const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result); void (*view_update)(struct RenderEngine *engine, const struct bContext *context); void (*view_draw)(struct RenderEngine *engine, const struct bContext *context); diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c index ecfb86c8d17..1f7555bc5c5 100644 --- a/source/blender/render/intern/source/bake_api.c +++ b/source/blender/render/intern/source/bake_api.c @@ -30,10 +30,11 @@ * * The Bake API is fully implemented with Python rna functions. The operator expects/call a function: * - * ``def bake(scene, object, pass_type, pixel_array, num_pixels, depth, result)`` + * ``def bake(scene, object, pass_type, object_id, pixel_array, num_pixels, depth, result)`` * - scene: current scene (Python object) * - object: object to render (Python object) * - pass_type: pass to render (string, e.g., "COMBINED", "AO", "NORMAL", ...) + * - object_id: index of object to bake (to use with the pixel_array) * - pixel_array: list of primitive ids and barycentric coordinates to bake(Python object, see bake_pixel) * - num_pixels: size of pixel_array, number of pixels to bake (int) * - depth: depth of pixels to return (int, assuming always 4 now) @@ -47,7 +48,7 @@ * * \code{.c} * struct BakePixel { - * int primitive_id; + * int primitive_id, object_id; * float uv[2]; * float du_dx, du_dy; * float dv_dx, dv_dy; @@ -55,7 +56,7 @@ * \endcode * * In python you have access to: - * - ``primitive_id``, ``uv``, ``du_dx``, ``du_dy``, ``next`` + * - ``primitive_id``, ``object_id``, ``uv``, ``du_dx``, ``du_dy``, ``next`` * - ``next()`` is a function that returns the next #BakePixel in the array. * * \note Pixels that should not be baked have ``primitive_id == -1`` @@ -126,12 +127,16 @@ static void store_bake_pixel(void *handle, int x, int y, float u, float v) pixel = &bd->pixel_array[i]; pixel->primitive_id = bd->primitive_id; + /* At this point object_id is always 0, since this function runs for the + * lowpoly mesh only. The object_id lookup indices are set afterwards. */ + copy_v2_fl2(pixel->uv, u, v); pixel->du_dx = bd->du_dx; pixel->du_dy = bd->du_dy; pixel->dv_dx = bd->dv_dx; pixel->dv_dy = bd->dv_dy; + pixel->object_id = 0; } void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, char *mask) @@ -271,7 +276,7 @@ static void calc_barycentric_from_point( * This function populates pixel_array and returns TRUE if things are correct */ static bool cast_ray_highpoly( - BVHTreeFromMesh *treeData, TriTessFace *triangles[], BakeHighPolyData *highpoly, + BVHTreeFromMesh *treeData, TriTessFace *triangles[], BakePixel *pixel_array, BakeHighPolyData *highpoly, const float co[3], const float dir[3], const int pixel_id, const int tot_highpoly, const float du_dx, const float du_dy, const float dv_dx, const float dv_dy) { @@ -322,22 +327,22 @@ static bool cast_ray_highpoly( } } - for (i = 0; i < tot_highpoly; i++) { - if (hit_mesh == i) { - calc_barycentric_from_point(triangles[i], hits[i].index, hits[i].co, &primitive_id, uv); - highpoly[i].pixel_array[pixel_id].primitive_id = primitive_id; - copy_v2_v2(highpoly[i].pixel_array[pixel_id].uv, uv); - - /* the differentials are relative to the UV/image space, so the highpoly differentials - * are the same as the low poly differentials */ - highpoly[i].pixel_array[pixel_id].du_dx = du_dx; - highpoly[i].pixel_array[pixel_id].du_dy = du_dy; - highpoly[i].pixel_array[pixel_id].dv_dx = dv_dx; - highpoly[i].pixel_array[pixel_id].dv_dy = dv_dy; - } - else { - highpoly[i].pixel_array[pixel_id].primitive_id = -1; - } + if (hit_mesh != -1) { + calc_barycentric_from_point(triangles[hit_mesh], hits[hit_mesh].index, hits[hit_mesh].co, &primitive_id, uv); + pixel_array[pixel_id].primitive_id = primitive_id; + pixel_array[pixel_id].object_id = hit_mesh; + copy_v2_v2(pixel_array[pixel_id].uv, uv); + + /* the differentials are relative to the UV/image space, so the highpoly differentials + * are the same as the low poly differentials */ + pixel_array[pixel_id].du_dx = du_dx; + pixel_array[pixel_id].du_dy = du_dy; + pixel_array[pixel_id].dv_dx = dv_dx; + pixel_array[pixel_id].dv_dy = dv_dy; + } + else { + pixel_array[pixel_id].primitive_id = -1; + pixel_array[pixel_id].object_id = -1; } MEM_freeN(hits); @@ -437,7 +442,7 @@ static void mesh_calc_tri_tessface( } bool RE_bake_pixels_populate_from_objects( - struct Mesh *me_low, BakePixel pixel_array_from[], + struct Mesh *me_low, BakePixel pixel_array_from[], BakePixel pixel_array_to[], BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage, const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage) { @@ -508,10 +513,7 @@ bool RE_bake_pixels_populate_from_objects( primitive_id = pixel_array_from[i].primitive_id; if (primitive_id == -1) { - int j; - for (j = 0; j < tot_highpoly; j++) { - highpoly[j].pixel_array[i].primitive_id = -1; - } + pixel_array_to[i].primitive_id = -1; continue; } @@ -530,7 +532,7 @@ bool RE_bake_pixels_populate_from_objects( } /* cast ray */ - if (!cast_ray_highpoly(treeData, tris_high, highpoly, co, dir, i, tot_highpoly, + if (!cast_ray_highpoly(treeData, tris_high, pixel_array_to, highpoly, co, dir, i, tot_highpoly, pixel_array_from[i].du_dx, pixel_array_from[i].du_dy, pixel_array_from[i].dv_dx, pixel_array_from[i].dv_dy)) { /* if it fails mask out the original pixel array */ diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 343c4a9387a..653af7460f9 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -463,7 +463,8 @@ bool RE_bake_has_engine(Render *re) } bool RE_bake_engine( - Render *re, Object *object, const BakePixel pixel_array[], + Render *re, Object *object, + const int object_id, const BakePixel pixel_array[], const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]) { @@ -501,7 +502,7 @@ bool RE_bake_engine( type->update(engine, re->main, re->scene); if (type->bake) - type->bake(engine, re->scene, object, pass_type, pixel_array, num_pixels, depth, result); + type->bake(engine, re->scene, object, pass_type, object_id, pixel_array, num_pixels, depth, result); engine->tile_x = 0; engine->tile_y = 0; -- cgit v1.2.3 From e0aeafdf0a22c18bf4970d7f9a34326bcebe491b Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Fri, 17 Apr 2015 18:10:34 +0200 Subject: BGE : Fix light layer check The layers in Blender are using a bit field for the 20 layers. The light layer value was limited to 20, so the highest usable light layer was five. The patch modify the range and add layer out of range error messages. Reviewers: sybren, hg1, moguri Reviewed By: hg1, moguri Projects: #game_engine Differential Revision: https://developer.blender.org/D1238 --- source/gameengine/Ketsji/KX_Light.cpp | 28 ++++++++++++++++------------ source/gameengine/Ketsji/KX_Light.h | 2 ++ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 33cfec57fc0..d6b84e98aec 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -166,27 +166,31 @@ PyAttributeDef KX_LightObject::Attributes[] = { PyObject *KX_LightObject::pyattr_get_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_LightObject* self = static_cast(self_v); + KX_LightObject *self = static_cast(self_v); return PyLong_FromLong(self->m_lightobj->m_layer); } int KX_LightObject::pyattr_set_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_LightObject* self = static_cast(self_v); + KX_LightObject *self = static_cast(self_v); + int layer = PyLong_AsLong(value); - if (PyLong_Check(value)) { - int val = PyLong_AsLong(value); - if (val < 1) - val = 1; - else if (val > 20) - val = 20; + if (layer == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name); + return PY_SET_ATTR_FAIL; + } - self->m_lightobj->m_layer = val; - return PY_SET_ATTR_SUCCESS; + if (layer < 1) { + PyErr_Format(PyExc_TypeError, "expected an integer greater than 1 for attribute \"%s\"", attrdef->m_name); + return PY_SET_ATTR_FAIL; + } + else if(layer > MAX_LIGHT_LAYERS) { + PyErr_Format(PyExc_TypeError, "expected an integer less than %i for attribute \"%s\"", MAX_LIGHT_LAYERS, attrdef->m_name); + return PY_SET_ATTR_FAIL; } - PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name); - return PY_SET_ATTR_FAIL; + self->SetLayer(layer); + return PY_SET_ATTR_SUCCESS; } PyObject *KX_LightObject::pyattr_get_energy(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index 503ed7411e9..386f8e95789 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -34,6 +34,8 @@ #include "KX_GameObject.h" +#define MAX_LIGHT_LAYERS ((1 << 20) - 1) + struct GPULamp; struct Scene; struct Base; -- cgit v1.2.3 From 28b9a0276fd6cfce0da7a8f434c13b252fc2cbbb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 18 Apr 2015 02:50:58 +1000 Subject: Cleanup: simplify sculpt plane accumulation --- source/blender/editors/sculpt_paint/sculpt.c | 100 +++++++++++---------------- 1 file changed, 39 insertions(+), 61 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 67d81ab75b7..436375707e7 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2263,88 +2263,66 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob, PBVHVertexIter vd; SculptBrushTest test; SculptUndoNode *unode; - float private_an[3] = {0.0f, 0.0f, 0.0f}; - float private_out_flip[3] = {0.0f, 0.0f, 0.0f}; - float private_fc[3] = {0.0f, 0.0f, 0.0f}; - float private_fc_flip[3] = {0.0f, 0.0f, 0.0f}; - int private_count = 0; - int private_count_flip = 0; + /* 0=towards view, 1=flipped */ + float private_co[2][3] = {{0.0f}}; + float private_no[2][3] = {{0.0f}}; + int private_count[2] = {0, 0}; + bool use_original; unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); sculpt_brush_test_init(ss, &test); - if (ss->cache->original && unode->co) { - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - if (sculpt_brush_test_fast(&test, unode->co[vd.i])) { - /* for area normal */ - float fno[3]; + use_original = (ss->cache->original && unode->co); - normal_short_to_float_v3(fno, unode->no[vd.i]); + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + { + const float *co; - if (dot_v3v3(ss->cache->view_normal, fno) > 0) { - add_v3_v3(private_an, fno); - add_v3_v3(private_fc, unode->co[vd.i]); - private_count++; - } - else { - add_v3_v3(private_out_flip, fno); - add_v3_v3(private_fc_flip, unode->co[vd.i]); - private_count_flip++; - } - } + if (use_original) { + co = unode->co[vd.i]; + } + else { + co = vd.co; } - BKE_pbvh_vertex_iter_end; - } - else { - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - if (sculpt_brush_test_fast(&test, vd.co)) { - /* for area normal */ - if (vd.no) { - float fno[3]; - normal_short_to_float_v3(fno, vd.no); + if (sculpt_brush_test_fast(&test, co)) { + float no_buf[3]; + const float *no; + int flip_index; - if (dot_v3v3(ss->cache->view_normal, fno) > 0) { - add_v3_v3(private_an, fno); - add_v3_v3(private_fc, vd.co); - private_count++; - } - else { - add_v3_v3(private_out_flip, fno); - add_v3_v3(private_fc_flip, vd.co); - private_count_flip++; - } + if (use_original) { + normal_short_to_float_v3(no_buf, unode->no[vd.i]); + no = no_buf; + } + else { + if (vd.no) { + normal_short_to_float_v3(no_buf, vd.no); + no = no_buf; } else { - if (dot_v3v3(ss->cache->view_normal, vd.fno) > 0) { - add_v3_v3(private_an, vd.fno); - add_v3_v3(private_fc, vd.co); - private_count++; - } - else { - add_v3_v3(private_out_flip, vd.fno); - add_v3_v3(private_fc_flip, vd.co); - private_count_flip++; - } + no = vd.fno; } } + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_co[flip_index], co); + add_v3_v3(private_no[flip_index], no); + private_count[flip_index] += 1; } - BKE_pbvh_vertex_iter_end; } + BKE_pbvh_vertex_iter_end; #pragma omp critical { /* for area normal */ - add_v3_v3(an, private_an); - add_v3_v3(out_flip, private_out_flip); + add_v3_v3(an, private_no[0]); + add_v3_v3(out_flip, private_no[1]); /* for flatten center */ - add_v3_v3(fc, private_fc); - add_v3_v3(fc_flip, private_fc_flip); - count += private_count; - count_flipped += private_count_flip; + add_v3_v3(fc, private_co[0]); + add_v3_v3(fc_flip, private_co[1]); + count += private_count[0]; + count_flipped += private_count[1]; } } -- cgit v1.2.3 From b0c2fdd927d1478ca76a312442f0c452a704607f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 18 Apr 2015 03:09:16 +1000 Subject: Cleanup: simplify sculpt normal accumulation --- source/blender/editors/sculpt_paint/sculpt.c | 84 ++++++++++++---------------- 1 file changed, 35 insertions(+), 49 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 436375707e7..63b95aa9c64 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2156,73 +2156,59 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to PBVHVertexIter vd; SculptBrushTest test; SculptUndoNode *unode; - float private_fc[3] = {0.0f, 0.0f, 0.0f}; - float private_fc_flip[3] = {0.0f, 0.0f, 0.0f}; - int private_count = 0; - int private_count_flip = 0; + /* 0=towards view, 1=flipped */ + float private_co[2][3] = {{0.0f}}; + int private_count[2] = {0, 0}; + bool use_original; unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); sculpt_brush_test_init(ss, &test); - if (ss->cache->original && unode->co) { - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - if (sculpt_brush_test_fast(&test, unode->co[vd.i])) { - float fno[3]; + use_original = (ss->cache->original && unode->co); - normal_short_to_float_v3(fno, unode->no[vd.i]); - if (dot_v3v3(ss->cache->view_normal, fno) > 0) { - add_v3_v3(private_fc, unode->co[vd.i]); - private_count++; - } - else { - add_v3_v3(private_fc_flip, unode->co[vd.i]); - private_count_flip++; - } - } + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + { + const float *co; + + if (use_original) { + co = unode->co[vd.i]; + } + else { + co = vd.co; } - BKE_pbvh_vertex_iter_end; - } - else { - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - if (sculpt_brush_test_fast(&test, vd.co)) { - /* for area normal */ - if (vd.no) { - float fno[3]; - normal_short_to_float_v3(fno, vd.no); + if (sculpt_brush_test_fast(&test, co)) { + float no_buf[3]; + const float *no; + int flip_index; - if (dot_v3v3(ss->cache->view_normal, fno) > 0) { - add_v3_v3(private_fc, vd.co); - private_count++; - } - else { - add_v3_v3(private_fc_flip, vd.co); - private_count_flip++; - } + if (use_original) { + normal_short_to_float_v3(no_buf, unode->no[vd.i]); + no = no_buf; + } + else { + if (vd.no) { + normal_short_to_float_v3(no_buf, vd.no); + no = no_buf; } else { - if (dot_v3v3(ss->cache->view_normal, vd.fno) > 0) { - add_v3_v3(private_fc, vd.co); - private_count++; - } - else { - add_v3_v3(private_fc_flip, vd.co); - private_count_flip++; - } + no = vd.fno; } } + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_co[flip_index], co); + private_count[flip_index] += 1; } BKE_pbvh_vertex_iter_end; } #pragma omp critical { - add_v3_v3(fc, private_fc); - add_v3_v3(fc_flip, private_fc_flip); - count += private_count; - count_flip += private_count_flip; + add_v3_v3(fc, private_co[0]); + add_v3_v3(fc_flip, private_co[1]); + count += private_count[0]; + count_flip += private_count[1]; } } if (count != 0) -- cgit v1.2.3 From 05b6de545ac59dfa8487c94c0f2a7e75063fb8b3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 18 Apr 2015 04:57:23 +1000 Subject: Fix T44390: Clay brush weirdness part-1 Clay brush had a feedback loop with dyntopo, getting the plane from the cursor center didn't support original data. --- source/blender/blenkernel/BKE_pbvh.h | 3 + source/blender/blenkernel/intern/pbvh.c | 9 ++ source/blender/editors/sculpt_paint/sculpt.c | 175 +++++++++++++++++++-------- 3 files changed, 136 insertions(+), 51 deletions(-) diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 035c8aa9515..03ad1765f8d 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -334,6 +334,9 @@ void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *pro void BKE_pbvh_node_free_proxies(PBVHNode *node); PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node); void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***nodes, int *totnode); +void BKE_pbvh_node_get_bm_orco_data( + PBVHNode *node, + int (**r_orco_tris)[3], int *r_orco_tris_num, float (**r_orco_coords)[3]); //void BKE_pbvh_node_BB_reset(PBVHNode *node); //void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]); diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index e12d685fb67..fdda72e4f7d 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1430,6 +1430,15 @@ void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *pro } } +void BKE_pbvh_node_get_bm_orco_data( + PBVHNode *node, + int (**r_orco_tris)[3], int *r_orco_tris_num, float (**r_orco_coords)[3]) +{ + *r_orco_tris = node->bm_ortri; + *r_orco_tris_num = node->bm_tot_ortri; + *r_orco_coords = node->bm_orco; +} + /********************************* Raycast ***********************************/ typedef struct { diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 63b95aa9c64..41f53769c4e 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2164,43 +2164,79 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); sculpt_brush_test_init(ss, &test); - use_original = (ss->cache->original && unode->co); - - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - const float *co; - - if (use_original) { - co = unode->co[vd.i]; - } - else { - co = vd.co; + use_original = (ss->cache->original && (unode->co || unode->bm_entry)); + + /* when the mesh is edited we can't rely on original coords + * (original mesh may not even have verts in brush radius) */ + if (use_original && unode->bm_entry) { + float (*orco_coords)[3]; + int (*orco_tris)[3]; + int orco_tris_num; + int i; + + BKE_pbvh_node_get_bm_orco_data( + nodes[n], + &orco_tris, &orco_tris_num, &orco_coords); + + for (i = 0; i < orco_tris_num; i++) { + const float *co_tri[3] = { + orco_coords[orco_tris[i][0]], + orco_coords[orco_tris[i][1]], + orco_coords[orco_tris[i][2]], + }; + float co[3]; + + closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri)); + + if (sculpt_brush_test_fast(&test, co)) { + float no[3]; + int flip_index; + + normal_tri_v3(no, UNPACK3(co_tri)); + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_co[flip_index], co); + private_count[flip_index] += 1; + } } - - if (sculpt_brush_test_fast(&test, co)) { - float no_buf[3]; - const float *no; - int flip_index; + } + else { + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + { + const float *co; if (use_original) { - normal_short_to_float_v3(no_buf, unode->no[vd.i]); - no = no_buf; + co = unode->co[vd.i]; } else { - if (vd.no) { - normal_short_to_float_v3(no_buf, vd.no); + co = vd.co; + } + + if (sculpt_brush_test_fast(&test, co)) { + float no_buf[3]; + const float *no; + int flip_index; + + if (use_original) { + normal_short_to_float_v3(no_buf, unode->no[vd.i]); no = no_buf; } else { - no = vd.fno; + if (vd.no) { + normal_short_to_float_v3(no_buf, vd.no); + no = no_buf; + } + else { + no = vd.fno; + } } - } - flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); - add_v3_v3(private_co[flip_index], co); - private_count[flip_index] += 1; + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_co[flip_index], co); + private_count[flip_index] += 1; + } + BKE_pbvh_vertex_iter_end; } - BKE_pbvh_vertex_iter_end; } #pragma omp critical @@ -2258,45 +2294,82 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob, unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); sculpt_brush_test_init(ss, &test); - use_original = (ss->cache->original && unode->co); + use_original = (ss->cache->original && (unode->co || unode->bm_entry)); - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - const float *co; + /* when the mesh is edited we can't rely on original coords + * (original mesh may not even have verts in brush radius) */ + if (use_original && unode->bm_entry) { + float (*orco_coords)[3]; + int (*orco_tris)[3]; + int orco_tris_num; + int i; - if (use_original) { - co = unode->co[vd.i]; - } - else { - co = vd.co; - } + BKE_pbvh_node_get_bm_orco_data( + nodes[n], + &orco_tris, &orco_tris_num, &orco_coords); + + for (i = 0; i < orco_tris_num; i++) { + const float *co_tri[3] = { + orco_coords[orco_tris[i][0]], + orco_coords[orco_tris[i][1]], + orco_coords[orco_tris[i][2]], + }; + float co[3]; + + closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri)); + + if (sculpt_brush_test_fast(&test, co)) { + float no[3]; + int flip_index; - if (sculpt_brush_test_fast(&test, co)) { - float no_buf[3]; - const float *no; - int flip_index; + normal_tri_v3(no, UNPACK3(co_tri)); + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_co[flip_index], co); + add_v3_v3(private_no[flip_index], no); + private_count[flip_index] += 1; + } + } + } + else { + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + { + const float *co; if (use_original) { - normal_short_to_float_v3(no_buf, unode->no[vd.i]); - no = no_buf; + co = unode->co[vd.i]; } else { - if (vd.no) { - normal_short_to_float_v3(no_buf, vd.no); + co = vd.co; + } + + if (sculpt_brush_test_fast(&test, co)) { + float no_buf[3]; + const float *no; + int flip_index; + + if (use_original) { + normal_short_to_float_v3(no_buf, unode->no[vd.i]); no = no_buf; } else { - no = vd.fno; + if (vd.no) { + normal_short_to_float_v3(no_buf, vd.no); + no = no_buf; + } + else { + no = vd.fno; + } } - } - flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); - add_v3_v3(private_co[flip_index], co); - add_v3_v3(private_no[flip_index], no); - private_count[flip_index] += 1; + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_co[flip_index], co); + add_v3_v3(private_no[flip_index], no); + private_count[flip_index] += 1; + } } + BKE_pbvh_vertex_iter_end; } - BKE_pbvh_vertex_iter_end; #pragma omp critical { -- cgit v1.2.3 From 3a4a2a942703762bd8c999af5b910f92b13df180 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 18 Apr 2015 05:03:29 +1000 Subject: Fix T44390: Clay brush weirdness part-2 Use the normal of the plane instead of the vertex normal, since projecting using the vertex normal frequently causes artifacts. --- source/blender/editors/sculpt_paint/sculpt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 41f53769c4e..95eddbf2a69 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2645,8 +2645,10 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) sub_v3_v3v3(val, intr, vd.co); if (plane_trim(ss->cache, brush, val)) { + /* note, the normal from the vertices is ignored, + * causes glitch with planes, see: T44390 */ const float fade = bstrength * tex_strength(ss, brush, vd.co, sqrtf(test.dist), - vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); + NULL, an, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -2746,9 +2748,11 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t sub_v3_v3v3(val, intr, vd.co); if (plane_trim(ss->cache, brush, val)) { + /* note, the normal from the vertices is ignored, + * causes glitch with planes, see: T44390 */ const float fade = bstrength * tex_strength(ss, brush, vd.co, ss->cache->radius * test.dist, - vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); + NULL, an, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], val, fade); -- cgit v1.2.3 From 4f2657bf47808b29cc72ed5712938a640898b603 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Sat, 18 Apr 2015 12:28:19 +0200 Subject: BGE: New Draw debug shadow box for sun lamp New Check option "Show Shadow Box" in shadow panel of sun lamp to get feedback about which objects project shadows. Minor tweaks by Campbell Barton and Jorge Bernal Reviewers: moguri, sybren, kupoman, dfelinto, lordloki, campbellbarton Reviewed By: lordloki, campbellbarton Subscribers: sergey, lordloki Projects: #game_engine Differential Revision: https://developer.blender.org/D1149 --- release/scripts/startup/bl_ui/properties_game.py | 2 + source/blender/editors/space_view3d/drawobject.c | 115 +++++++++++++++++++---- source/blender/makesdna/DNA_lamp_types.h | 1 + source/blender/makesrna/intern/rna_lamp.c | 5 + 4 files changed, 106 insertions(+), 17 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py index 84ad2426aa0..f39a73ec00b 100644 --- a/release/scripts/startup/bl_ui/properties_game.py +++ b/release/scripts/startup/bl_ui/properties_game.py @@ -731,6 +731,8 @@ class DATA_PT_shadow_game(DataButtonsPanel, Panel): col = split.column() col.prop(lamp, "shadow_color", text="") + if lamp.type == 'SUN': + col.prop(lamp, "show_shadow_box") col = split.column() col.prop(lamp, "use_shadow_layer", text="This Layer Only") diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index ecc2499a63f..ece195aa22b 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -214,6 +214,7 @@ static void drawcube_size(float size); static void drawcircle_size(float size); static void draw_empty_sphere(float size); static void draw_empty_cone(float size); +static void draw_box(float vec[8][3], bool solid); static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac) { @@ -1144,6 +1145,52 @@ static void draw_transp_spot_volume(Lamp *la, float x, float z) glCullFace(GL_BACK); } +#ifdef WITH_GAMEENGINE +static void draw_transp_sun_volume(Lamp *la) +{ + float box[8][3]; + + /* construct box */ + box[0][0] = box[1][0] = box[2][0] = box[3][0] = -la->shadow_frustum_size; + box[4][0] = box[5][0] = box[6][0] = box[7][0] = +la->shadow_frustum_size; + box[0][1] = box[1][1] = box[4][1] = box[5][1] = -la->shadow_frustum_size; + box[2][1] = box[3][1] = box[6][1] = box[7][1] = +la->shadow_frustum_size; + box[0][2] = box[3][2] = box[4][2] = box[7][2] = -la->clipend; + box[1][2] = box[2][2] = box[5][2] = box[6][2] = -la->clipsta; + + /* draw edges */ + draw_box(box, false); + + /* draw faces */ + glEnable(GL_CULL_FACE); + glEnable(GL_BLEND); + glDepthMask(0); + + /* draw backside darkening */ + glCullFace(GL_FRONT); + + glBlendFunc(GL_ZERO, GL_SRC_ALPHA); + glColor4f(0.0f, 0.0f, 0.0f, 0.4f); + + draw_box(box, true); + + /* draw front side lighting */ + glCullFace(GL_BACK); + + glBlendFunc(GL_ONE, GL_ONE); + glColor4f(0.2f, 0.2f, 0.2f, 1.0f); + + draw_box(box, true); + + /* restore state */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_BLEND); + glDepthMask(1); + glDisable(GL_CULL_FACE); + glCullFace(GL_BACK); +} +#endif + static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact) { @@ -1166,7 +1213,22 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, !(base->flag & OB_FROMDUPLI) && !is_view); - if (drawcone && !v3d->transp) { +#ifdef WITH_GAMEENGINE + const bool drawshadowbox = ( + (rv3d->rflag & RV3D_IS_GAME_ENGINE) && + (dt > OB_WIRE) && + !(G.f & G_PICKSEL) && + (la->type == LA_SUN) && + ((la->mode & LA_SHAD_BUF) || + (la->mode & LA_SHAD_RAY)) && + (la->mode & LA_SHOW_SHADOW_BOX) && + !(base->flag & OB_FROMDUPLI) && + !is_view); +#else + const bool drawshadowbox = false; +#endif + + if ((drawcone || drawshadowbox) && !v3d->transp) { /* in this case we need to draw delayed */ ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag); return; @@ -1411,6 +1473,13 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, dir = -dir; } } + +#ifdef WITH_GAMEENGINE + if (drawshadowbox) { + draw_transp_sun_volume(la); + } +#endif + } else if (la->type == LA_AREA) { setlinestyle(3); @@ -7037,19 +7106,31 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, setlinestyle(0); } -static void draw_box(float vec[8][3]) +static void draw_box(float vec[8][3], bool solid) { - glBegin(GL_LINE_STRIP); - glVertex3fv(vec[0]); glVertex3fv(vec[1]); glVertex3fv(vec[2]); glVertex3fv(vec[3]); - glVertex3fv(vec[0]); glVertex3fv(vec[4]); glVertex3fv(vec[5]); glVertex3fv(vec[6]); - glVertex3fv(vec[7]); glVertex3fv(vec[4]); - glEnd(); + if (!solid) { + glBegin(GL_LINE_STRIP); + glVertex3fv(vec[0]); glVertex3fv(vec[1]); glVertex3fv(vec[2]); glVertex3fv(vec[3]); + glVertex3fv(vec[0]); glVertex3fv(vec[4]); glVertex3fv(vec[5]); glVertex3fv(vec[6]); + glVertex3fv(vec[7]); glVertex3fv(vec[4]); + glEnd(); - glBegin(GL_LINES); - glVertex3fv(vec[1]); glVertex3fv(vec[5]); - glVertex3fv(vec[2]); glVertex3fv(vec[6]); - glVertex3fv(vec[3]); glVertex3fv(vec[7]); - glEnd(); + glBegin(GL_LINES); + glVertex3fv(vec[1]); glVertex3fv(vec[5]); + glVertex3fv(vec[2]); glVertex3fv(vec[6]); + glVertex3fv(vec[3]); glVertex3fv(vec[7]); + glEnd(); + } + else { + glBegin(GL_QUADS); + glVertex3fv(vec[0]); glVertex3fv(vec[1]); glVertex3fv(vec[2]); glVertex3fv(vec[3]); + glVertex3fv(vec[7]); glVertex3fv(vec[6]); glVertex3fv(vec[5]); glVertex3fv(vec[4]); + glVertex3fv(vec[4]); glVertex3fv(vec[5]); glVertex3fv(vec[1]); glVertex3fv(vec[0]); + glVertex3fv(vec[3]); glVertex3fv(vec[2]); glVertex3fv(vec[6]); glVertex3fv(vec[7]); + glVertex3fv(vec[3]); glVertex3fv(vec[7]); glVertex3fv(vec[4]); glVertex3fv(vec[0]); + glVertex3fv(vec[1]); glVertex3fv(vec[5]); glVertex3fv(vec[6]); glVertex3fv(vec[2]); + glEnd(); + } } static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin) @@ -7143,7 +7224,7 @@ static void draw_bounding_volume(Object *ob, char type) vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2]; vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2]; - draw_box(vec); + draw_box(vec, false); } else { draw_bb_quadric(bb, type, true); @@ -7151,7 +7232,7 @@ static void draw_bounding_volume(Object *ob, char type) } else { if (type == OB_BOUND_BOX) - draw_box(bb->vec); + draw_box(bb->vec, false); else draw_bb_quadric(bb, type, false); } @@ -7187,7 +7268,7 @@ static void drawtexspace(Object *ob) setlinestyle(2); - draw_box(vec); + draw_box(vec, false); setlinestyle(0); } @@ -7464,7 +7545,7 @@ static void draw_rigidbody_shape(Object *ob) vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2]; vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2]; - draw_box(vec); + draw_box(vec, false); break; case RB_SHAPE_SPHERE: draw_bb_quadric(bb, OB_BOUND_SPHERE, true); @@ -7928,7 +8009,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short VECSUBFAC(p0, sds->p0, sds->cell_size, sds->adapt_res); VECADDFAC(p1, sds->p1, sds->cell_size, sds->adapt_res); BKE_boundbox_init_from_minmax(&bb, p0, p1); - draw_box(bb.vec); + draw_box(bb.vec, false); #if 0 /* draw base resolution bounds */ diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h index a920182d5a3..ce8e86cb512 100644 --- a/source/blender/makesdna/DNA_lamp_types.h +++ b/source/blender/makesdna/DNA_lamp_types.h @@ -151,6 +151,7 @@ typedef struct Lamp { #define LA_LAYER_SHADOW (1 << 15) #define LA_SHAD_TEX (1 << 16) #define LA_SHOW_CONE (1 << 17) +#define LA_SHOW_SHADOW_BOX (1 << 18) /* layer_shadow */ #define LA_LAYER_SHADOW_BOTH 0 diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index c915acdeeac..481d139a9de 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -825,6 +825,11 @@ static void rna_def_sun_lamp(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.001, 100.0, 2, 1); RNA_def_property_ui_text(prop, "Frustum Size", "Size of the frustum used for creating the shadow map"); RNA_def_property_update(prop, 0, "rna_Lamp_draw_update"); + + prop = RNA_def_property(srna, "show_shadow_box", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mode", LA_SHOW_SHADOW_BOX); + RNA_def_property_ui_text(prop, "Show Shadow Box", "Draw box in 3D view to visualize which object are contained in it"); + RNA_def_property_update(prop, 0, "rna_Lamp_draw_update"); } static void rna_def_hemi_lamp(BlenderRNA *brna) -- cgit v1.2.3 From 230712e6cb8c5ff5c8ca2edc81b10ee036eed86a Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Sat, 18 Apr 2015 15:50:29 +0200 Subject: Autosave: Flush edits only when saving global undo. This will stop freeing of PBVH in sculpt mode, which introduces some pretty severe freezes, especially in dyntopo. For global undo we flush the contents of the global undo buffer which does not include localized edits of sculpt/edit mode, so those data will not get saved anyway. --- source/blender/windowmanager/intern/wm_files.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index fdad108d44d..e80f789d3ab 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -1137,8 +1137,6 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *UNUSED(w } } - ED_editors_flush_edits(C, false); - wm_autosave_location(filepath); if (U.uiflag & USER_GLOBALUNDO) { @@ -1149,6 +1147,8 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *UNUSED(w /* save as regular blend file */ int fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN | G_FILE_HISTORY); + ED_editors_flush_edits(C, false); + /* no error reporting to console */ BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL); } -- cgit v1.2.3 From 38bea4e86c90c514d345f34f865da831e6d2f83f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 18 Apr 2015 17:33:04 +0200 Subject: Cleanup: use BLO_memfile prefix --- source/blender/blenkernel/intern/blender.c | 8 ++++---- source/blender/blenloader/BLO_undofile.h | 6 +++--- source/blender/blenloader/intern/undofile.c | 8 ++++---- source/blender/blenloader/intern/writefile.c | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 4b2c6ef5e0e..791fa3df3b9 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -705,7 +705,7 @@ void BKE_write_undo(bContext *C, const char *name) while (undobase.last != curundo) { uel = undobase.last; BLI_remlink(&undobase, uel); - BLO_free_memfile(&uel->memfile); + BLO_memfile_free(&uel->memfile); MEM_freeN(uel); } @@ -727,7 +727,7 @@ void BKE_write_undo(bContext *C, const char *name) UndoElem *first = undobase.first; BLI_remlink(&undobase, first); /* the merge is because of compression */ - BLO_merge_memfile(&first->memfile, &first->next->memfile); + BLO_memfile_merge(&first->memfile, &first->next->memfile); MEM_freeN(first); } } @@ -782,7 +782,7 @@ void BKE_write_undo(bContext *C, const char *name) UndoElem *first = undobase.first; BLI_remlink(&undobase, first); /* the merge is because of compression */ - BLO_merge_memfile(&first->memfile, &first->next->memfile); + BLO_memfile_merge(&first->memfile, &first->next->memfile); MEM_freeN(first); } } @@ -827,7 +827,7 @@ void BKE_reset_undo(void) uel = undobase.first; while (uel) { - BLO_free_memfile(&uel->memfile); + BLO_memfile_free(&uel->memfile); uel = uel->next; } diff --git a/source/blender/blenloader/BLO_undofile.h b/source/blender/blenloader/BLO_undofile.h index f716b47ea2e..fb96ec75e62 100644 --- a/source/blender/blenloader/BLO_undofile.h +++ b/source/blender/blenloader/BLO_undofile.h @@ -47,11 +47,11 @@ typedef struct MemFile { } MemFile; /* actually only used writefile.c */ -extern void add_memfilechunk(MemFile *compare, MemFile *current, const char *buf, unsigned int size); +extern void memfile_chunk_add(MemFile *compare, MemFile *current, const char *buf, unsigned int size); /* exports */ -extern void BLO_free_memfile(MemFile *memfile); -extern void BLO_merge_memfile(MemFile *first, MemFile *second); +extern void BLO_memfile_free(MemFile *memfile); +extern void BLO_memfile_merge(MemFile *first, MemFile *second); #endif diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c index f70d889828f..d0dc9a88cc0 100644 --- a/source/blender/blenloader/intern/undofile.c +++ b/source/blender/blenloader/intern/undofile.c @@ -46,7 +46,7 @@ /* **************** support for memory-write, for undo buffers *************** */ /* not memfile itself */ -void BLO_free_memfile(MemFile *memfile) +void BLO_memfile_free(MemFile *memfile) { MemFileChunk *chunk; @@ -60,7 +60,7 @@ void BLO_free_memfile(MemFile *memfile) /* to keep list of memfiles consistent, 'first' is always first in list */ /* result is that 'first' is being freed */ -void BLO_merge_memfile(MemFile *first, MemFile *second) +void BLO_memfile_merge(MemFile *first, MemFile *second) { MemFileChunk *fc, *sc; @@ -77,7 +77,7 @@ void BLO_merge_memfile(MemFile *first, MemFile *second) if (sc) sc = sc->next; } - BLO_free_memfile(first); + BLO_memfile_free(first); } static int my_memcmp(const int *mem1, const int *mem2, const int len) @@ -94,7 +94,7 @@ static int my_memcmp(const int *mem1, const int *mem2, const int len) return 0; } -void add_memfilechunk(MemFile *compare, MemFile *current, const char *buf, unsigned int size) +void memfile_chunk_add(MemFile *compare, MemFile *current, const char *buf, unsigned int size) { static MemFileChunk *compchunk = NULL; MemFileChunk *curchunk; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 2580ba64622..12c4f4922dc 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -333,7 +333,7 @@ static void writedata_do_write(WriteData *wd, const void *mem, int memlen) /* memory based save */ if (wd->current) { - add_memfilechunk(NULL, wd->current, mem, memlen); + memfile_chunk_add(NULL, wd->current, mem, memlen); } else { if (wd->ww->write(wd->ww, mem, memlen) != memlen) { @@ -421,7 +421,7 @@ static WriteData *bgnwrite(WriteWrap *ww, MemFile *compare, MemFile *current) wd->compare= compare; wd->current= current; /* this inits comparing */ - add_memfilechunk(compare, NULL, NULL, 0); + memfile_chunk_add(compare, NULL, NULL, 0); return wd; } -- cgit v1.2.3 From 252b0cf5d28c5ce6397a64cb4bb399a6c5a438fa Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 18 Apr 2015 15:41:12 +0200 Subject: Cleanup: API naming use BKE_undo_ prefix --- source/blender/blenkernel/BKE_blender.h | 18 +++++++++--------- source/blender/blenkernel/intern/blender.c | 22 ++++++++++++---------- source/blender/editors/include/ED_paint.h | 4 ++-- source/blender/editors/include/ED_particle.h | 4 ++-- source/blender/editors/include/ED_util.h | 2 +- source/blender/editors/physics/particle_edit.c | 11 ++++++----- source/blender/editors/sculpt_paint/paint_undo.c | 17 +++++++++-------- source/blender/editors/util/editmode_undo.c | 11 ++++++----- source/blender/editors/util/undo.c | 17 +++++++++-------- source/blender/editors/util/util_intern.h | 12 ++++++------ source/blender/windowmanager/intern/wm_files.c | 10 +++++----- source/blender/windowmanager/intern/wm_init_exit.c | 4 ++-- source/blender/windowmanager/intern/wm_operators.c | 2 +- source/creator/creator.c | 4 ++-- 14 files changed, 72 insertions(+), 66 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 86576f9a11b..0789335de6a 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -93,15 +93,15 @@ int blender_test_break(void); #define BKE_UNDO_STR_MAX 64 /* global undo */ -extern void BKE_write_undo(struct bContext *C, const char *name); -extern void BKE_undo_step(struct bContext *C, int step); -extern void BKE_undo_name(struct bContext *C, const char *name); -extern int BKE_undo_valid(const char *name); -extern void BKE_reset_undo(void); -extern void BKE_undo_number(struct bContext *C, int nr); -extern const char *BKE_undo_get_name(int nr, int *active); -extern bool BKE_undo_save_file(const char *filename); -extern struct Main *BKE_undo_get_main(struct Scene **scene); +extern void BKE_undo_write(struct bContext *C, const char *name); +extern void BKE_undo_step(struct bContext *C, int step); +extern void BKE_undo_name(struct bContext *C, const char *name); +extern bool BKE_undo_is_valid(const char *name); +extern void BKE_undo_reset(void); +extern void BKE_undo_number(struct bContext *C, int nr); +extern const char *BKE_undo_get_name(int nr, bool *r_active); +extern bool BKE_undo_save_file(const char *filename); +extern struct Main *BKE_undo_get_main(struct Scene **r_scene); /* copybuffer */ void BKE_copybuffer_begin(struct Main *bmain); diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 791fa3df3b9..2085fefdb93 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -687,7 +687,7 @@ static int read_undosave(bContext *C, UndoElem *uel) } /* name can be a dynamic string */ -void BKE_write_undo(bContext *C, const char *name) +void BKE_undo_write(bContext *C, const char *name) { uintptr_t maxmem, totmem, memused; int nr /*, success */ /* UNUSED */; @@ -821,7 +821,7 @@ void BKE_undo_step(bContext *C, int step) } } -void BKE_reset_undo(void) +void BKE_undo_reset(void) { UndoElem *uel; @@ -854,7 +854,7 @@ void BKE_undo_name(bContext *C, const char *name) } /* name optional */ -int BKE_undo_valid(const char *name) +bool BKE_undo_is_valid(const char *name) { if (name) { UndoElem *uel = BLI_rfindstring(&undobase, name, offsetof(UndoElem, name)); @@ -866,15 +866,16 @@ int BKE_undo_valid(const char *name) /* get name of undo item, return null if no item with this index */ /* if active pointer, set it to 1 if true */ -const char *BKE_undo_get_name(int nr, int *active) +const char *BKE_undo_get_name(int nr, bool *r_active) { UndoElem *uel = BLI_findlink(&undobase, nr); - if (active) *active = 0; + if (r_active) *r_active = false; if (uel) { - if (active && uel == curundo) - *active = 1; + if (r_active && (uel == curundo)) { + *r_active = true; + } return uel->name; } return NULL; @@ -940,15 +941,16 @@ bool BKE_undo_save_file(const char *filename) } /* sets curscene */ -Main *BKE_undo_get_main(Scene **scene) +Main *BKE_undo_get_main(Scene **r_scene) { Main *mainp = NULL; BlendFileData *bfd = BLO_read_from_memfile(G.main, G.main->name, &curundo->memfile, NULL); if (bfd) { mainp = bfd->main; - if (scene) - *scene = bfd->curscene; + if (r_scene) { + *r_scene = bfd->curscene; + } MEM_freeN(bfd); } diff --git a/source/blender/editors/include/ED_paint.h b/source/blender/editors/include/ED_paint.h index c3a411a2b97..822dab61a06 100644 --- a/source/blender/editors/include/ED_paint.h +++ b/source/blender/editors/include/ED_paint.h @@ -46,9 +46,9 @@ typedef bool (*UndoCleanupCb)(struct bContext *C, struct ListBase *lb); int ED_undo_paint_step(struct bContext *C, int type, int step, const char *name); void ED_undo_paint_step_num(struct bContext *C, int type, int num); -const char *ED_undo_paint_get_name(struct bContext *C, int type, int nr, int *active); +const char *ED_undo_paint_get_name(struct bContext *C, int type, int nr, bool *r_active); void ED_undo_paint_free(void); -int ED_undo_paint_valid(int type, const char *name); +bool ED_undo_paint_is_valid(int type, const char *name); bool ED_undo_paint_empty(int type); void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free, UndoCleanupCb cleanup); void ED_undo_paint_push_end(int type); diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h index 56a4bfa7e21..6cb8c0cfb19 100644 --- a/source/blender/editors/include/ED_particle.h +++ b/source/blender/editors/include/ED_particle.h @@ -66,9 +66,9 @@ void PE_undo_push(struct Scene *scene, const char *str); void PE_undo_step(struct Scene *scene, int step); void PE_undo(struct Scene *scene); void PE_redo(struct Scene *scene); -int PE_undo_valid(struct Scene *scene); +bool PE_undo_is_valid(struct Scene *scene); void PE_undo_number(struct Scene *scene, int nr); -const char *PE_undo_get_name(struct Scene *scene, int nr, int *active); +const char *PE_undo_get_name(struct Scene *scene, int nr, bool *r_active); #endif /* __ED_PARTICLE_H__ */ diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index 6fa92e1953d..9556c601d1f 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -60,7 +60,7 @@ int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op); void ED_undo_operator_repeat_cb(struct bContext *C, void *arg_op, void *arg_unused); void ED_undo_operator_repeat_cb_evt(struct bContext *C, void *arg_op, int arg_unused); -int ED_undo_valid(const struct bContext *C, const char *undoname); +bool ED_undo_is_valid(const struct bContext *C, const char *undoname); /* undo_editmode.c */ void undo_editmode_push(struct bContext *C, const char *name, diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 6c90e319bc6..a0420dfa46e 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -4445,7 +4445,7 @@ void PE_undo_step(Scene *scene, int step) DAG_id_tag_update(&OBACT->id, OB_RECALC_DATA); } -int PE_undo_valid(Scene *scene) +bool PE_undo_is_valid(Scene *scene) { PTCacheEdit *edit= PE_get_current(scene, OBACT); @@ -4496,18 +4496,19 @@ void PE_undo_number(Scene *scene, int nr) /* get name of undo item, return null if no item with this index */ /* if active pointer, set it to 1 if true */ -const char *PE_undo_get_name(Scene *scene, int nr, int *active) +const char *PE_undo_get_name(Scene *scene, int nr, bool *r_active) { PTCacheEdit *edit= PE_get_current(scene, OBACT); PTCacheUndo *undo; - if (active) *active= 0; + if (r_active) *r_active = false; if (edit) { undo= BLI_findlink(&edit->undo, nr); if (undo) { - if (active && undo==edit->curundo) - *active= 1; + if (r_active && (undo == edit->curundo)) { + *r_active = true; + } return undo->name; } } diff --git a/source/blender/editors/sculpt_paint/paint_undo.c b/source/blender/editors/sculpt_paint/paint_undo.c index 0293a0bfc00..42f0aaab173 100644 --- a/source/blender/editors/sculpt_paint/paint_undo.c +++ b/source/blender/editors/sculpt_paint/paint_undo.c @@ -331,32 +331,33 @@ void ED_undo_paint_step_num(bContext *C, int type, int step) undo_step_num(C, &MeshUndoStack, step); } -static char *undo_stack_get_name(UndoStack *stack, int nr, int *active) +static char *undo_stack_get_name(UndoStack *stack, int nr, bool *r_active) { UndoElem *uel; - if (active) *active = 0; + if (r_active) *r_active = false; uel = BLI_findlink(&stack->elems, nr); if (uel) { - if (active && uel == stack->current) - *active = 1; + if (r_active && (uel == stack->current)) { + *r_active = true; + } return uel->name; } return NULL; } -const char *ED_undo_paint_get_name(bContext *C, int type, int nr, int *active) +const char *ED_undo_paint_get_name(bContext *C, int type, int nr, bool *r_active) { if (type == UNDO_PAINT_IMAGE) { undo_stack_cleanup(&ImageUndoStack, C); - return undo_stack_get_name(&ImageUndoStack, nr, active); + return undo_stack_get_name(&ImageUndoStack, nr, r_active); } else if (type == UNDO_PAINT_MESH) { undo_stack_cleanup(&MeshUndoStack, C); - return undo_stack_get_name(&MeshUndoStack, nr, active); + return undo_stack_get_name(&MeshUndoStack, nr, r_active); } return NULL; } @@ -379,7 +380,7 @@ bool ED_undo_paint_empty(int type) return false; } -int ED_undo_paint_valid(int type, const char *name) +bool ED_undo_paint_is_valid(int type, const char *name) { UndoStack *stack; diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c index 7f5edb5ea9e..bc7a8374c73 100644 --- a/source/blender/editors/util/editmode_undo.c +++ b/source/blender/editors/util/editmode_undo.c @@ -315,7 +315,7 @@ void undo_editmode_name(bContext *C, const char *undoname) } /* undoname optionally, if NULL it just checks for existing undo steps */ -int undo_editmode_valid(const char *undoname) +bool undo_editmode_is_valid(const char *undoname) { if (undoname) { UndoElem *uel; @@ -332,19 +332,20 @@ int undo_editmode_valid(const char *undoname) /* get name of undo item, return null if no item with this index */ /* if active pointer, set it to 1 if true */ -const char *undo_editmode_get_name(bContext *C, int nr, int *active) +const char *undo_editmode_get_name(bContext *C, int nr, bool *r_active) { UndoElem *uel; /* prevent wrong numbers to be returned */ undo_clean_stack(C); - if (active) *active = 0; + if (r_active) *r_active = false; uel = BLI_findlink(&undobase, nr); if (uel) { - if (active && uel == curundo) - *active = 1; + if (r_active && (uel == curundo)) { + *r_active = true; + } return uel->name; } return NULL; diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c index ab882a388ad..ee6101d2952 100644 --- a/source/blender/editors/util/undo.c +++ b/source/blender/editors/util/undo.c @@ -108,7 +108,7 @@ void ED_undo_push(bContext *C, const char *str) /* do nothing for now */ } else { - BKE_write_undo(C, str); + BKE_undo_write(C, str); } if (wm->file_saved) { @@ -244,7 +244,7 @@ void ED_undo_pop_op(bContext *C, wmOperator *op) } /* name optionally, function used to check for operator redo panel */ -int ED_undo_valid(const bContext *C, const char *undoname) +bool ED_undo_is_valid(const bContext *C, const char *undoname) { Object *obedit = CTX_data_edit_object(C); Object *obact = CTX_data_active_object(C); @@ -263,7 +263,7 @@ int ED_undo_valid(const bContext *C, const char *undoname) } else if (obedit) { if (OB_TYPE_SUPPORT_EDITMODE(obedit->type)) { - return undo_editmode_valid(undoname); + return undo_editmode_is_valid(undoname); } } else { @@ -271,19 +271,19 @@ int ED_undo_valid(const bContext *C, const char *undoname) /* if below tests fail, global undo gets executed */ if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) { - if (ED_undo_paint_valid(UNDO_PAINT_IMAGE, undoname)) + if (ED_undo_paint_is_valid(UNDO_PAINT_IMAGE, undoname)) return 1; } else if (obact && obact->mode & OB_MODE_SCULPT) { - if (ED_undo_paint_valid(UNDO_PAINT_MESH, undoname)) + if (ED_undo_paint_is_valid(UNDO_PAINT_MESH, undoname)) return 1; } else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) { - return PE_undo_valid(CTX_data_scene(C)); + return PE_undo_is_valid(CTX_data_scene(C)); } if (U.uiflag & USER_GLOBALUNDO) { - return BKE_undo_valid(undoname); + return BKE_undo_is_valid(undoname); } } return 0; @@ -487,7 +487,8 @@ static int get_undo_system(bContext *C) static EnumPropertyItem *rna_undo_itemf(bContext *C, int undosys, int *totitem) { EnumPropertyItem item_tmp = {0}, *item = NULL; - int active, i = 0; + int i = 0; + bool active; while (true) { const char *name = NULL; diff --git a/source/blender/editors/util/util_intern.h b/source/blender/editors/util/util_intern.h index d366ad7997f..0f650330951 100644 --- a/source/blender/editors/util/util_intern.h +++ b/source/blender/editors/util/util_intern.h @@ -35,12 +35,12 @@ /* internal exports only */ /* editmode_undo.c */ -void undo_editmode_name (struct bContext *C, const char *undoname); -int undo_editmode_valid (const char *undoname); -const char *undo_editmode_get_name (struct bContext *C, int nr, int *active); -void *undo_editmode_get_prev (struct Object *ob); -void undo_editmode_step (struct bContext *C, int step); -void undo_editmode_number (struct bContext *C, int nr); +void undo_editmode_name(struct bContext *C, const char *undoname); +bool undo_editmode_is_valid(const char *undoname); +const char *undo_editmode_get_name(struct bContext *C, int nr, bool *r_active); +void *undo_editmode_get_prev(struct Object *ob); +void undo_editmode_step(struct bContext *C, int step); +void undo_editmode_number(struct bContext *C, int nr); #endif /* __UTIL_INTERN_H__ */ diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index e80f789d3ab..df0d27bc43e 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -506,13 +506,13 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) } #endif - BKE_reset_undo(); - BKE_write_undo(C, "original"); /* save current state */ + BKE_undo_reset(); + BKE_undo_write(C, "original"); /* save current state */ success = true; } else if (retval == BKE_READ_EXOTIC_OK_OTHER) - BKE_write_undo(C, "Import file"); + BKE_undo_write(C, "Import file"); else if (retval == BKE_READ_EXOTIC_FAIL_OPEN) { BKE_reportf(reports, RPT_ERROR, "Cannot read file '%s': %s", filepath, errno ? strerror(errno) : TIP_("unable to open the file")); @@ -660,8 +660,8 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c // refresh_interface_font(); // undo_editmode_clear(); - BKE_reset_undo(); - BKE_write_undo(C, "original"); /* save current state */ + BKE_undo_reset(); + BKE_undo_write(C, "original"); /* save current state */ ED_editors_init(C); DAG_on_visible_update(CTX_data_main(C), true); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 4f019c0a913..71a025f3660 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -407,7 +407,7 @@ void WM_exit_ext(bContext *C, const bool do_python) wmWindow *win; if (!G.background) { - if ((U.uiflag2 & USER_KEEP_SESSION) || BKE_undo_valid(NULL)) { + if ((U.uiflag2 & USER_KEEP_SESSION) || BKE_undo_is_valid(NULL)) { /* save the undo state as quit.blend */ char filename[FILE_MAX]; bool has_edited; @@ -517,7 +517,7 @@ void WM_exit_ext(bContext *C, const bool do_python) GPU_exit(); } - BKE_reset_undo(); + BKE_undo_reset(); ED_file_exit(); /* for fsmenu */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 19a6b86db90..cb2db94f609 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1404,7 +1404,7 @@ bool WM_operator_check_ui_enabled(const bContext *C, const char *idname) wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = CTX_data_scene(C); - return !(ED_undo_valid(C, idname) == 0 || WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY)); + return !((ED_undo_is_valid(C, idname) == false) || WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY)); } wmOperator *WM_operator_last_redo(const bContext *C) diff --git a/source/creator/creator.c b/source/creator/creator.c index 5b4f828842e..440710f0572 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1369,8 +1369,8 @@ static int load_file(int UNUSED(argc), const char **argv, void *data) BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST); /* happens for the UI on file reading too (huh? (ton))*/ - // XXX BKE_reset_undo(); - // BKE_write_undo("original"); /* save current state */ + // XXX BKE_undo_reset(); + // BKE_undo_write("original"); /* save current state */ } else { /* we are not running in background mode here, but start blender in UI mode with -- cgit v1.2.3 From a2f9a0cfd940049f22cb89a8812629948a3580ae Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Sat, 18 Apr 2015 21:32:48 +0200 Subject: BGE: Fix T43536 logic.getCurrentScene() returning wrong scene in pre_draw and post_draw calls A simple insert of KX_SetActiveScene(scene) before pre_draw and post_draw calls solves the issue. Reviewers: dfelinto, sybren, brita_, campbellbarton, moguri, lordloki Reviewed By: moguri, lordloki Projects: #game_logic, #game_engine Differential Revision: https://developer.blender.org/D1129 --- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 6c2e34d92f8..f0b47684092 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -312,6 +312,7 @@ void KX_KetsjiEngine::RenderDome() // for each scene, call the proceed functions { scene = *sceneit; + KX_SetActiveScene(scene); KX_Camera* cam = scene->GetActiveCamera(); // pass the scene's worldsettings to the rasterizer @@ -389,8 +390,10 @@ void KX_KetsjiEngine::RenderDome() ); } m_dome->Draw(); + // Draw Callback for the last scene #ifdef WITH_PYTHON + PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); scene->RunDrawingCallbacks(scene->GetPostDrawCB()); #endif EndFrame(); @@ -1102,6 +1105,9 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) if (!cam) return; + + KX_SetActiveScene(scene); + GetSceneViewport(scene, cam, area, viewport); // store the computed viewport in the scene @@ -1214,6 +1220,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) SG_SetActiveStage(SG_STAGE_RENDER); #ifdef WITH_PYTHON + PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); // Run any pre-drawing python callbacks scene->RunDrawingCallbacks(scene->GetPreDrawCB()); #endif @@ -1232,12 +1239,16 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) */ void KX_KetsjiEngine::PostRenderScene(KX_Scene* scene) { + KX_SetActiveScene(scene); + // We need to first make sure our viewport is correct (enabling multiple viewports can mess this up) m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight()); m_rasterizer->FlushDebugShapes(); scene->Render2DFilters(m_canvas); + #ifdef WITH_PYTHON + PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); scene->RunDrawingCallbacks(scene->GetPostDrawCB()); #endif } -- cgit v1.2.3 From 3d55859924713aada6f35ca7d9a0ed270bdad08b Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Sun, 19 Apr 2015 01:01:17 +0200 Subject: BGE: Support for collision group/mask from the api + activated on EndObject. A Python API for the collision group / mask has been added: ``` KX_GameObject.collisionGroup KX_GameObject.collisionMask ``` The maximum number of collision groups and masked has been increased from eight to sixteen. This means that the max value of collisionGroup/Mask is (2 ** 16) - 1 EndObject will now activate objects that were sleeping and colliding with the removed object. This means that, unlike now, if a rigid body starts sleeping on top of another object, when the latter is removed the rigid body will activate and fall, rather than float midair as before. Collision groups that do not intersect used to collide on the first frame. Now this has been fixed so that they collide appropriately. Thanks to agoose77 for his help. Reviewers: scorpion81, hg1, agoose77, sergof Reviewed By: agoose77, sergof Subscribers: sergof, moguri Projects: #game_physics, #game_engine Differential Revision: https://developer.blender.org/D1243 --- .../rst/bge_types/bge.types.KX_GameObject.rst | 12 ++++ source/blender/blenkernel/intern/object.c | 2 +- source/blender/makesdna/DNA_object_types.h | 2 +- .../Converter/BL_BlenderDataConversion.cpp | 4 +- source/gameengine/Ketsji/KX_GameObject.cpp | 70 +++++++++++++++++++++- source/gameengine/Ketsji/KX_GameObject.h | 14 +++-- .../Physics/Bullet/CcdPhysicsController.cpp | 28 ++++++++- .../Physics/Bullet/CcdPhysicsController.h | 19 +++++- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 11 +++- .../Physics/common/PHY_IPhysicsController.h | 1 + 10 files changed, 150 insertions(+), 13 deletions(-) diff --git a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst index b2cfeb5edc7..7b2f68b019c 100644 --- a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst +++ b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst @@ -161,6 +161,18 @@ base class --- :class:`SCA_IObject` :type: :class:`KX_GameObject` or None + .. attribute:: collisionGroup + + The object's collision group. + + :type: bitfield + + .. attribute:: collisionMask + + The object's collision mask. + + :type: bitfield + .. attribute:: collisionCallbacks A list of functions to be called when a collision occurs. diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index c485e00ed69..f14f72614f4 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1048,7 +1048,7 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name) ob->jump_speed = 10.0f; ob->fall_speed = 55.0f; ob->col_group = 0x01; - ob->col_mask = 0xff; + ob->col_mask = 0xffff; /* NT fluid sim defaults */ ob->fluidsimSettings = NULL; diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 286461f1b69..8bd676caa5e 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -530,7 +530,7 @@ enum { #define OB_MAX_STATES 30 /* collision masks */ -#define OB_MAX_COL_MASKS 8 +#define OB_MAX_COL_MASKS 16 /* ob->gameflag */ enum { diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index de5e27baf58..2f62ffdd698 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1347,8 +1347,8 @@ static void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, if (!(blenderobject->gameflag & OB_COLLISION)) { // Respond to all collisions so that Near sensors work on No Collision // objects. - gameobj->SetUserCollisionGroup(0xff); - gameobj->SetUserCollisionMask(0xff); + gameobj->SetUserCollisionGroup(0xffff); + gameobj->SetUserCollisionMask(0xffff); return; } diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 412a0b823c7..1536b31d1ba 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -47,6 +47,7 @@ #include "KX_MeshProxy.h" #include "KX_PolyProxy.h" #include // printf +#include // USHRT_MAX #include "SG_Controller.h" #include "PHY_IGraphicController.h" #include "SG_Node.h" @@ -561,13 +562,26 @@ void KX_GameObject::ActivateGraphicController(bool recurse) } } -void KX_GameObject::SetUserCollisionGroup(short group) +void KX_GameObject::SetUserCollisionGroup(unsigned short group) { m_userCollisionGroup = group; + if (m_pPhysicsController) + m_pPhysicsController->RefreshCollisions(); } -void KX_GameObject::SetUserCollisionMask(short mask) +void KX_GameObject::SetUserCollisionMask(unsigned short mask) { m_userCollisionMask = mask; + if (m_pPhysicsController) + m_pPhysicsController->RefreshCollisions(); +} + +unsigned short KX_GameObject::GetUserCollisionGroup() +{ + return m_userCollisionGroup; +} +unsigned short KX_GameObject::GetUserCollisionMask() +{ + return m_userCollisionMask; } bool KX_GameObject::CheckCollision(KX_GameObject* other) @@ -2003,6 +2017,8 @@ PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("scaling", KX_GameObject, pyattr_get_worldScaling, pyattr_set_localScaling), KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset), KX_PYATTRIBUTE_RW_FUNCTION("collisionCallbacks", KX_GameObject, pyattr_get_collisionCallbacks, pyattr_set_collisionCallbacks), + KX_PYATTRIBUTE_RW_FUNCTION("collisionGroup", KX_GameObject, pyattr_get_collisionGroup, pyattr_set_collisionGroup), + KX_PYATTRIBUTE_RW_FUNCTION("collisionMask", KX_GameObject, pyattr_get_collisionMask, pyattr_set_collisionMask), KX_PYATTRIBUTE_RW_FUNCTION("state", KX_GameObject, pyattr_get_state, pyattr_set_state), KX_PYATTRIBUTE_RO_FUNCTION("meshes", KX_GameObject, pyattr_get_meshes), KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation), @@ -2349,6 +2365,56 @@ int KX_GameObject::pyattr_set_collisionCallbacks(void *self_v, const KX_PYATTRIB return PY_SET_ATTR_SUCCESS; } +PyObject *KX_GameObject::pyattr_get_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast(self_v); + return PyLong_FromLong(self->GetUserCollisionGroup()); +} + +int KX_GameObject::pyattr_set_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self = static_cast(self_v); + int val = PyLong_AsLong(value); + + if (val == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "gameOb.collisionGroup = int: KX_GameObject, expected an int bit field"); + return PY_SET_ATTR_FAIL; + } + + if (val < 0 || val > USHRT_MAX) { + PyErr_Format(PyExc_AttributeError, "gameOb.collisionGroup = int: KX_GameObject, expected a int bit field between 0 and %i", USHRT_MAX); + return PY_SET_ATTR_FAIL; + } + + self->SetUserCollisionGroup(val); + return PY_SET_ATTR_SUCCESS; +} + +PyObject *KX_GameObject::pyattr_get_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast(self_v); + return PyLong_FromLong(self->GetUserCollisionMask()); +} + +int KX_GameObject::pyattr_set_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self = static_cast(self_v); + int val = PyLong_AsLong(value); + + if (val == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "gameOb.collisionMask = int: KX_GameObject, expected an int bit field"); + return PY_SET_ATTR_FAIL; + } + + if (val < 0 || val > USHRT_MAX) { + PyErr_Format(PyExc_AttributeError, "gameOb.collisionMask = int: KX_GameObject, expected a int bit field between 0 and %i", USHRT_MAX); + return PY_SET_ATTR_FAIL; + } + + self->SetUserCollisionMask(val); + return PY_SET_ATTR_SUCCESS; +} + PyObject* KX_GameObject::pyattr_get_scene(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject *self = static_cast(self_v); diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 5038feb2d68..54bb6ee2605 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -100,8 +100,8 @@ protected: MT_Vector4 m_objectColor; // Bit fields for user control over physics collisions - short m_userCollisionGroup; - short m_userCollisionMask; + unsigned short m_userCollisionGroup; + unsigned short m_userCollisionMask; // visible = user setting // culled = while rendering, depending on camera @@ -517,8 +517,10 @@ public: */ void ActivateGraphicController(bool recurse); - void SetUserCollisionGroup(short filter); - void SetUserCollisionMask(short mask); + void SetUserCollisionGroup(unsigned short filter); + void SetUserCollisionMask(unsigned short mask); + unsigned short GetUserCollisionGroup(); + unsigned short GetUserCollisionMask(); /** * Extra broadphase check for user controllable collisions */ @@ -1087,6 +1089,10 @@ public: static int pyattr_set_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_collisionCallbacks(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_collisionCallbacks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_collisionGroup(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_collisionMask(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 5adff8f7f02..b2b8f30a706 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -65,7 +65,6 @@ extern bool gDisableDeactivation; float gLinearSleepingTreshold; float gAngularSleepingTreshold; - BlenderBulletCharacterController::BlenderBulletCharacterController(btMotionState *motionState, btPairCachingGhostObject *ghost, btConvexShape* shape, float stepHeight) : btKinematicCharacterController(ghost,shape,stepHeight,2), m_motionState(motionState), @@ -118,6 +117,20 @@ const btVector3& BlenderBulletCharacterController::getWalkDirection() return m_walkDirection; } +bool CleanPairCallback::processOverlap(btBroadphasePair &pair) +{ + if ((pair.m_pProxy0 == m_cleanProxy) || (pair.m_pProxy1 == m_cleanProxy)) { + m_pairCache->cleanOverlappingPair(pair, m_dispatcher); + CcdPhysicsController *ctrl0 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy0->m_clientObject)->getUserPointer()); + CcdPhysicsController *ctrl1 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy1->m_clientObject)->getUserPointer()); + if (ctrl0 && ctrl1) { + ctrl0->GetRigidBody()->activate(true); + ctrl1->GetRigidBody()->activate(true); + } + } + return false; +} + CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci) :m_cci(ci) { @@ -1082,6 +1095,19 @@ void CcdPhysicsController::ResolveCombinedVelocities(float linvelX,float linvel { } +void CcdPhysicsController::RefreshCollisions() +{ + btSoftRigidDynamicsWorld *dw = GetPhysicsEnvironment()->GetDynamicsWorld(); + btBroadphaseProxy *proxy = m_object->getBroadphaseHandle(); + btDispatcher *dispatcher = dw->getDispatcher(); + btOverlappingPairCache *pairCache = dw->getPairCache(); + + CleanPairCallback cleanPairs(proxy, pairCache, dispatcher); + pairCache->processAllOverlappingPairs(&cleanPairs, dispatcher); + // Forcibly recreate the physics object + GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, m_cci.m_mass, m_cci.m_collisionFlags, m_cci.m_collisionFilterGroup, m_cci.m_collisionFilterMask); +} + void CcdPhysicsController::SuspendDynamics(bool ghost) { btRigidBody *body = GetRigidBody(); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 56d67ca2f64..4fcdc70c5a8 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -447,6 +447,23 @@ public: #endif }; +class CleanPairCallback : public btOverlapCallback +{ + btBroadphaseProxy *m_cleanProxy; + btOverlappingPairCache *m_pairCache; + btDispatcher *m_dispatcher; + +public: + CleanPairCallback(btBroadphaseProxy *cleanProxy, btOverlappingPairCache *pairCache, btDispatcher *dispatcher) + :m_cleanProxy(cleanProxy), + m_pairCache(pairCache), + m_dispatcher(dispatcher) + { + } + + virtual bool processOverlap(btBroadphasePair &pair); +}; + ///CcdPhysicsController is a physics object that supports continuous collision detection and time of impact based physics resolution. class CcdPhysicsController : public PHY_IPhysicsController { @@ -598,7 +615,7 @@ protected: virtual void ResolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ); - + virtual void RefreshCollisions(); virtual void SuspendDynamics(bool ghost); virtual void RestoreDynamics(); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 6d3f6d9ddcb..984273ec63e 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -509,6 +509,13 @@ bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctr btRigidBody* body = ctrl->GetRigidBody(); if (body) { + btBroadphaseProxy *proxy = ctrl->GetCollisionObject()->getBroadphaseHandle(); + btDispatcher *dispatcher = m_dynamicsWorld->getDispatcher(); + btOverlappingPairCache *pairCache = m_dynamicsWorld->getPairCache(); + + CleanPairCallback cleanPairs(proxy, pairCache, dispatcher); + pairCache->processAllOverlappingPairs(&cleanPairs, dispatcher); + for (int i = ctrl->getNumCcdConstraintRefs() - 1; i >= 0; i--) { btTypedConstraint* con = ctrl->getCcdConstraintRef(i); @@ -3525,12 +3532,14 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject if (isbulletdyna) gameobj->SetRecordAnimation(true); + physicscontroller->SetNewClientInfo(gameobj->getClientInfo()); + // don't add automatically sensor object, they are added when a collision sensor is registered if (!isbulletsensor && (blenderobject->lay & activeLayerBitInfo) != 0) { this->AddCcdPhysicsController( physicscontroller); } - physicscontroller->SetNewClientInfo(gameobj->getClientInfo()); + { btRigidBody* rbody = physicscontroller->GetRigidBody(); diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h index b6cd480e655..3e2337f01ea 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsController.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h @@ -96,6 +96,7 @@ class PHY_IPhysicsController : public PHY_IController virtual void SetAngularDamping(float damping)=0; virtual void SetDamping(float linear, float angular)=0; + virtual void RefreshCollisions() = 0; virtual void SuspendDynamics(bool ghost=false)=0; virtual void RestoreDynamics()=0; -- cgit v1.2.3 From 9ac618a90eddf90071a1d94fa2ae076ce239c785 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 19 Apr 2015 14:21:23 +1000 Subject: Sculpt: smooth brush, exclude self from average Was including the vertices own location when accumulating. --- source/blender/blenkernel/BKE_mesh.h | 13 +++++++------ source/blender/blenkernel/intern/mesh.c | 15 +++++++++------ source/blender/editors/sculpt_paint/sculpt.c | 19 +++++++++---------- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 05c20410458..c0d8902eb71 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -69,12 +69,13 @@ extern "C" { struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me, struct Object *ob); -int poly_find_loop_from_vert(const struct MPoly *poly, - const struct MLoop *loopstart, - unsigned vert); - -int poly_get_adj_loops_from_vert(unsigned r_adj[3], const struct MPoly *poly, - const struct MLoop *mloop, unsigned vert); +int poly_find_loop_from_vert( + const struct MPoly *poly, + const struct MLoop *loopstart, + unsigned vert); +int poly_get_adj_loops_from_vert( + unsigned r_adj[2], const struct MPoly *poly, + const struct MLoop *mloop, unsigned vert); int BKE_mesh_edge_other_vert(const struct MEdge *e, int v); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 840ef473691..eec2b108ca3 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1821,8 +1821,9 @@ float (*BKE_mesh_vertexCos_get(const Mesh *me, int *r_numVerts))[3] * Find the index of the loop in 'poly' which references vertex, * returns -1 if not found */ -int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart, - unsigned vert) +int poly_find_loop_from_vert( + const MPoly *poly, const MLoop *loopstart, + unsigned vert) { int j; for (j = 0; j < poly->totloop; j++, loopstart++) { @@ -1838,20 +1839,22 @@ int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart, * vertex. Returns the index of the loop matching vertex, or -1 if the * vertex is not in \a poly */ -int poly_get_adj_loops_from_vert(unsigned r_adj[3], const MPoly *poly, - const MLoop *mloop, unsigned vert) +int poly_get_adj_loops_from_vert( + unsigned r_adj[2], const MPoly *poly, + const MLoop *mloop, unsigned vert) { int corner = poly_find_loop_from_vert(poly, &mloop[poly->loopstart], vert); if (corner != -1) { +#if 0 /* unused - this loop */ const MLoop *ml = &mloop[poly->loopstart + corner]; +#endif /* vertex was found */ r_adj[0] = ME_POLY_LOOP_PREV(mloop, poly, corner)->v; - r_adj[1] = ml->v; - r_adj[2] = ME_POLY_LOOP_NEXT(mloop, poly, corner)->v; + r_adj[1] = ME_POLY_LOOP_NEXT(mloop, poly, corner)->v; } return corner; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 95eddbf2a69..73a9abeac41 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1177,12 +1177,11 @@ static void neighbor_average(SculptSession *ss, float avg[3], unsigned vert) for (i = 0; i < vert_map->count; i++) { const MPoly *p = &ss->mpoly[vert_map->indices[i]]; - unsigned f_adj_v[3]; + unsigned f_adj_v[2]; if (poly_get_adj_loops_from_vert(f_adj_v, p, ss->mloop, vert) != -1) { int j; - - for (j = 0; j < 3; j++) { + for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) { if (vert_map->count != 2 || ss->pmap[f_adj_v[j]].count <= 2) { add_v3_v3(avg, deform_co ? deform_co[f_adj_v[j]] : mvert[f_adj_v[j]].co); @@ -1213,12 +1212,11 @@ static float neighbor_average_mask(SculptSession *ss, unsigned vert) for (i = 0; i < ss->pmap[vert].count; i++) { const MPoly *p = &ss->mpoly[ss->pmap[vert].indices[i]]; - unsigned f_adj_v[3]; + unsigned f_adj_v[2]; if (poly_get_adj_loops_from_vert(f_adj_v, p, ss->mloop, vert) != -1) { int j; - - for (j = 0; j < 3; j++) { + for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) { avg += vmask[f_adj_v[j]]; total++; } @@ -1245,9 +1243,9 @@ static void bmesh_neighbor_average(float avg[3], BMVert *v) int i, total = 0; BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - BMVert *adj_v[3] = {l->prev->v, v, l->next->v}; + BMVert *adj_v[2] = {l->prev->v, l->next->v}; - for (i = 0; i < 3; i++) { + for (i = 0; i < ARRAY_SIZE(adj_v); i++) { if (vfcount != 2 || BM_vert_face_count(adj_v[i]) <= 2) { add_v3_v3(avg, adj_v[i]->co); total++; @@ -1273,9 +1271,10 @@ static float bmesh_neighbor_average_mask(BMesh *bm, BMVert *v) int i, total = 0; BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - BMVert *adj_v[3] = {l->prev->v, v, l->next->v}; + /* skip this vertex */ + BMVert *adj_v[2] = {l->prev->v, l->next->v}; - for (i = 0; i < 3; i++) { + for (i = 0; i < ARRAY_SIZE(adj_v); i++) { BMVert *v2 = adj_v[i]; float *vmask = CustomData_bmesh_get(&bm->vdata, v2->head.data, -- cgit v1.2.3 From 2448c21cb365af0afc22008953f4ebe08de7cb0f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 19 Apr 2015 14:38:16 +1000 Subject: Sculpt: avoid CD lookup /w mask smooth --- source/blender/editors/sculpt_paint/sculpt.c | 35 +++++++++++++--------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 73a9abeac41..8efd6ab3fbe 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1169,12 +1169,12 @@ static void neighbor_average(SculptSession *ss, float avg[3], unsigned vert) const MVert *mvert = ss->mvert; float (*deform_co)[3] = ss->deform_cos; - zero_v3(avg); - /* Don't modify corner vertices */ if (vert_map->count > 1) { int i, total = 0; + zero_v3(avg); + for (i = 0; i < vert_map->count; i++) { const MPoly *p = &ss->mpoly[vert_map->indices[i]]; unsigned f_adj_v[2]; @@ -1234,20 +1234,21 @@ static void bmesh_neighbor_average(float avg[3], BMVert *v) { const int vfcount = BM_vert_face_count(v); - zero_v3(avg); - /* Don't modify corner vertices */ if (vfcount > 1) { BMIter liter; BMLoop *l; int i, total = 0; + zero_v3(avg); + BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - BMVert *adj_v[2] = {l->prev->v, l->next->v}; + const BMVert *adj_v[2] = {l->prev->v, l->next->v}; for (i = 0; i < ARRAY_SIZE(adj_v); i++) { - if (vfcount != 2 || BM_vert_face_count(adj_v[i]) <= 2) { - add_v3_v3(avg, adj_v[i]->co); + const BMVert *v_other = adj_v[i]; + if (vfcount != 2 || BM_vert_face_count(v_other) <= 2) { + add_v3_v3(avg, v_other->co); total++; } } @@ -1263,7 +1264,7 @@ static void bmesh_neighbor_average(float avg[3], BMVert *v) } /* Same logic as neighbor_average_mask(), but for bmesh rather than mesh */ -static float bmesh_neighbor_average_mask(BMesh *bm, BMVert *v) +static float bmesh_neighbor_average_mask(BMVert *v, const int cd_vert_mask_offset) { BMIter liter; BMLoop *l; @@ -1272,13 +1273,11 @@ static float bmesh_neighbor_average_mask(BMesh *bm, BMVert *v) BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { /* skip this vertex */ - BMVert *adj_v[2] = {l->prev->v, l->next->v}; + const BMVert *adj_v[2] = {l->prev->v, l->next->v}; for (i = 0; i < ARRAY_SIZE(adj_v); i++) { - BMVert *v2 = adj_v[i]; - float *vmask = CustomData_bmesh_get(&bm->vdata, - v2->head.data, - CD_PAINT_MASK); + const BMVert *v_other = adj_v[i]; + const float *vmask = BM_ELEM_CD_GET_VOID_P(v_other, cd_vert_mask_offset); avg += (*vmask); total++; } @@ -1288,9 +1287,7 @@ static float bmesh_neighbor_average_mask(BMesh *bm, BMVert *v) return avg / (float)total; } else { - float *vmask = CustomData_bmesh_get(&bm->vdata, - v->head.data, - CD_PAINT_MASK); + const float *vmask = BM_ELEM_CD_GET_VOID_P(v, cd_vert_mask_offset); return (*vmask); } } @@ -1353,7 +1350,7 @@ static void do_bmesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node, vd.no, vd.fno, smooth_mask ? 0 : *vd.mask); if (smooth_mask) { - float val = bmesh_neighbor_average_mask(ss->bm, vd.bm_vert) - *vd.mask; + float val = bmesh_neighbor_average_mask(vd.bm_vert, vd.cd_vert_mask_offset) - *vd.mask; val *= fade * bstrength; *vd.mask += val; CLAMP(*vd.mask, 0, 1); @@ -1389,7 +1386,7 @@ static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *no float *tmpgrid_mask, *tmprow_mask; int v1, v2, v3, v4; int thread_num; - BLI_bitmap **grid_hidden; + BLI_bitmap * const *grid_hidden; int *grid_indices, totgrid, gridsize, i, x, y; sculpt_brush_test_init(ss, &test); @@ -1414,7 +1411,7 @@ static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *no for (i = 0; i < totgrid; ++i) { int gi = grid_indices[i]; - BLI_bitmap *gh = grid_hidden[gi]; + const BLI_bitmap *gh = grid_hidden[gi]; data = griddata[gi]; adj = &gridadj[gi]; -- cgit v1.2.3 From 550c3c2c1ec6fb3ad064a59cfd23f2472766a4d2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 19 Apr 2015 14:42:54 +1000 Subject: Dyntopo: avoid over-counting /w neighbor average --- source/blender/editors/sculpt_paint/sculpt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 8efd6ab3fbe..b0f4cf062f6 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1232,7 +1232,8 @@ static float neighbor_average_mask(SculptSession *ss, unsigned vert) /* Same logic as neighbor_average(), but for bmesh rather than mesh */ static void bmesh_neighbor_average(float avg[3], BMVert *v) { - const int vfcount = BM_vert_face_count(v); + /* logic for 3 or more is identical */ + const int vfcount = BM_vert_face_count_ex(v, 3); /* Don't modify corner vertices */ if (vfcount > 1) { @@ -1247,7 +1248,7 @@ static void bmesh_neighbor_average(float avg[3], BMVert *v) for (i = 0; i < ARRAY_SIZE(adj_v); i++) { const BMVert *v_other = adj_v[i]; - if (vfcount != 2 || BM_vert_face_count(v_other) <= 2) { + if (vfcount != 2 || BM_vert_face_count_ex(v_other, 2) <= 2) { add_v3_v3(avg, v_other->co); total++; } -- cgit v1.2.3 From d09a9a9597018471af9f0df3d2263d1c57954a8c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 19 Apr 2015 16:03:12 +1000 Subject: Dyntopo: USE_EDGEQUEUE_TAG broke even subdiv While adding edges to the queue multiple times is redundant, walking over them is still needed. --- source/blender/blenkernel/intern/pbvh_bmesh.c | 92 ++++++++++++++++++--------- 1 file changed, 63 insertions(+), 29 deletions(-) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index d54c598e988..a6939180013 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -49,6 +49,15 @@ /* don't add edges into the queue multiple times */ #define USE_EDGEQUEUE_TAG +/** + * Ensure we don't have dirty tags for the edge queue, and that they are left cleared. + * (slow, even for debug mode, so leave disabled for now). + */ +#if defined(USE_EDGEQUEUE_TAG) +# if !defined(NDEBUG) +# define USE_EDGEQUEUE_TAG_VERIFY +# endif +#endif // #define USE_VERIFY @@ -606,6 +615,37 @@ typedef struct { # define EDGE_QUEUE_DISABLE(e) BM_elem_flag_disable((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG) #endif +#ifdef USE_EDGEQUEUE_TAG_VERIFY +/* simply check no edges are tagged + * (it's a requirement that edges enter and leave a clean tag state) */ +static void pbvh_bmesh_edge_tag_verify(PBVH *bvh) +{ + int n; + + for (n = 0; n < bvh->totnode; n++) { + PBVHNode *node = &bvh->nodes[n]; + GSetIterator gs_iter; + if (node->bm_faces) { + GSET_ITER (gs_iter, node->bm_faces) { + BMFace *f = BLI_gsetIterator_getKey(&gs_iter); + BMEdge *e_tri[3]; + BMLoop *l_iter; + + BLI_assert(f->len == 3); + l_iter = BM_FACE_FIRST_LOOP(f); + e_tri[0] = l_iter->e; l_iter = l_iter->next; + e_tri[1] = l_iter->e; l_iter = l_iter->next; + e_tri[2] = l_iter->e; + + BLI_assert((EDGE_QUEUE_TEST(e_tri[0]) == false) && + (EDGE_QUEUE_TEST(e_tri[1]) == false) && + (EDGE_QUEUE_TEST(e_tri[2]) == false)); + } + } + } +} +#endif + static bool edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f) { BMVert *v_tri[3]; @@ -675,7 +715,13 @@ static void long_edge_queue_edge_add_recursive( const float len_sq, float limit_len) { BLI_assert(len_sq > SQUARE(limit_len)); - edge_queue_insert(eq_ctx, l_edge->e, -len_sq); + +#ifdef USE_EDGEQUEUE_TAG + if (EDGE_QUEUE_TEST(l_edge->e) == false) +#endif + { + edge_queue_insert(eq_ctx, l_edge->e, -len_sq); + } /* temp support previous behavior! */ if (UNLIKELY(G.debug_value == 1234)) { @@ -703,17 +749,12 @@ static void long_edge_queue_edge_add_recursive( BMLoop *l_adjacent[2] = {l_iter->next, l_iter->prev}; int i; for (i = 0; i < ARRAY_SIZE(l_adjacent); i++) { -#ifdef USE_EDGEQUEUE_TAG - if (EDGE_QUEUE_TEST(l_adjacent[i]->e) == false) -#endif - { - len_sq_other = BM_edge_calc_length_squared(l_adjacent[i]->e); - if (len_sq_other > max_ff(len_sq_cmp, limit_len_sq)) { -// edge_queue_insert(eq_ctx, l_adjacent[i]->e, -len_sq_other); - long_edge_queue_edge_add_recursive( - eq_ctx, l_adjacent[i]->radial_next, l_adjacent[i], - len_sq_other, limit_len); - } + len_sq_other = BM_edge_calc_length_squared(l_adjacent[i]->e); + if (len_sq_other > max_ff(len_sq_cmp, limit_len_sq)) { +// edge_queue_insert(eq_ctx, l_adjacent[i]->e, -len_sq_other); + long_edge_queue_edge_add_recursive( + eq_ctx, l_adjacent[i]->radial_next, l_adjacent[i], + len_sq_other, limit_len); } } } while ((l_iter = l_iter->radial_next) != l_end); @@ -748,9 +789,6 @@ static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, /* Check each edge of the face */ l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { -#ifdef USE_EDGEQUEUE_TAG - if (EDGE_QUEUE_TEST(l_iter->e) == false) -#endif { #ifdef USE_EDGEQUEUE_EVEN_SUBDIV const float len_sq = BM_edge_calc_length_squared(l_iter->e); @@ -805,6 +843,11 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx, eq_ctx->q->limit_len = bvh->bm_max_edge_len; #endif +#ifdef USE_EDGEQUEUE_TAG_VERIFY + pbvh_bmesh_edge_tag_verify(bvh); +#endif + + for (n = 0; n < bvh->totnode; n++) { PBVHNode *node = &bvh->nodes[n]; @@ -999,9 +1042,8 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh, { bool any_subdivided = false; -#if defined(USE_EDGEQUEUE_TAG) && !defined(NDEBUG) -# define USE_EDGEQUEUE_TAG_VALIDATE - int heap_tot = 0, heap_overlap = 0; +#ifdef USE_EDGEQUEUE_TAG_VERIFY + pbvh_bmesh_edge_tag_verify(bvh); #endif @@ -1013,15 +1055,8 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh, BLI_mempool_free(eq_ctx->pool, pair); pair = NULL; -#ifdef USE_EDGEQUEUE_TAG_VALIDATE - heap_tot += 1; -#endif - /* Check that the edge still exists */ if (!(e = BM_edge_exists(v1, v2))) { -#ifdef USE_EDGEQUEUE_TAG_VALIDATE - heap_overlap += 1; -#endif continue; } #ifdef USE_EDGEQUEUE_TAG @@ -1052,11 +1087,10 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh, pbvh_bmesh_split_edge(eq_ctx, bvh, e, edge_loops); } -#ifdef USE_EDGEQUEUE_TAG_VALIDATE - // printf("%d %d\n", heap_total, heap_overlap); - BLI_assert(heap_overlap == 0); -#undef USE_EDGEQUEUE_TAG_VALIDATE +#ifdef USE_EDGEQUEUE_TAG_VERIFY + pbvh_bmesh_edge_tag_verify(bvh); #endif + return any_subdivided; } -- cgit v1.2.3 From eb4fb4f4feabe7746d7a3e8ea9fe6db49cfe0122 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 19 Apr 2015 16:06:40 +1000 Subject: disable verify from last commit (too slow) --- source/blender/blenkernel/intern/pbvh_bmesh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index a6939180013..5977243a21c 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -53,7 +53,7 @@ * Ensure we don't have dirty tags for the edge queue, and that they are left cleared. * (slow, even for debug mode, so leave disabled for now). */ -#if defined(USE_EDGEQUEUE_TAG) +#if defined(USE_EDGEQUEUE_TAG) && 0 # if !defined(NDEBUG) # define USE_EDGEQUEUE_TAG_VERIFY # endif -- cgit v1.2.3 From 57b020528b802feb15ada3bfd9de74029ed0bb89 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 19 Apr 2015 17:03:51 +1000 Subject: Cleanup: calculating sculpt center & normal also avoid sqrt calculating dyntopo center (only checks for flipping) --- source/blender/editors/sculpt_paint/sculpt.c | 118 ++++++++++++++------------- 1 file changed, 62 insertions(+), 56 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index b0f4cf062f6..1f57059cd64 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2134,28 +2134,28 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno } } -static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float fc[3]) +static void calc_flatten_center( + Sculpt *sd, Object *ob, + PBVHNode **nodes, int totnode, + float r_area_co[3]) { SculptSession *ss = ob->sculpt; int n; - int count = 0; - int count_flip = 0; + /* 0=towards view, 1=flipped */ + float area_co[2][3] = {{0.0f}}; - float fc_flip[3] = {0.0, 0.0, 0.0}; + int count[2] = {0}; (void)sd; /* unused w/o openmp */ - zero_v3(fc); - #pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) for (n = 0; n < totnode; n++) { PBVHVertexIter vd; SculptBrushTest test; SculptUndoNode *unode; - /* 0=towards view, 1=flipped */ float private_co[2][3] = {{0.0f}}; - int private_count[2] = {0, 0}; + int private_count[2] = {0}; bool use_original; unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); @@ -2189,7 +2189,7 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to float no[3]; int flip_index; - normal_tri_v3(no, UNPACK3(co_tri)); + cross_tri_v3(no, UNPACK3(co_tri)); flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); add_v3_v3(private_co[flip_index], co); @@ -2232,60 +2232,60 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to add_v3_v3(private_co[flip_index], co); private_count[flip_index] += 1; } - BKE_pbvh_vertex_iter_end; } + BKE_pbvh_vertex_iter_end; } #pragma omp critical { - add_v3_v3(fc, private_co[0]); - add_v3_v3(fc_flip, private_co[1]); - count += private_count[0]; - count_flip += private_count[1]; + /* for flatten center */ + add_v3_v3(area_co[0], private_co[0]); + add_v3_v3(area_co[1], private_co[1]); + + /* weights */ + count[0] += private_count[0]; + count[1] += private_count[1]; } } - if (count != 0) - mul_v3_fl(fc, 1.0f / count); - else if (count_flip != 0) - mul_v3_v3fl(fc, fc_flip, 1.0f / count_flip); - else - zero_v3(fc); + + /* for flatten center */ + for (n = 0; n < ARRAY_SIZE(area_co); n++) { + if (count[n] != 0) { + mul_v3_v3fl(r_area_co, area_co[n], 1.0f / count[n]); + break; + } + } + if (n == 2) { + zero_v3(r_area_co); + } } /* this calculates flatten center and area normal together, * amortizing the memory bandwidth and loop overhead to calculate both at the same time */ -static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob, - PBVHNode **nodes, int totnode, - float an[3], float fc[3]) +static void calc_area_normal_and_flatten_center( + Sculpt *sd, Object *ob, + PBVHNode **nodes, int totnode, + float r_area_no[3], float r_area_co[3]) { SculptSession *ss = ob->sculpt; int n; - /* for area normal */ - float out_flip[3] = {0.0f, 0.0f, 0.0f}; - float fc_flip[3] = {0.0f, 0.0f, 0.0f}; + /* 0=towards view, 1=flipped */ + float area_co[2][3] = {{0.0f}}; + float area_no[2][3] = {{0.0f}}; - /* for flatten center */ - int count = 0; - int count_flipped = 0; + int count[2] = {0}; (void)sd; /* unused w/o openmp */ - - /* for area normal */ - zero_v3(an); - - /* for flatten center */ - zero_v3(fc); #pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) for (n = 0; n < totnode; n++) { PBVHVertexIter vd; SculptBrushTest test; SculptUndoNode *unode; - /* 0=towards view, 1=flipped */ float private_co[2][3] = {{0.0f}}; float private_no[2][3] = {{0.0f}}; - int private_count[2] = {0, 0}; + int private_count[2] = {0}; bool use_original; unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); @@ -2370,31 +2370,37 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob, #pragma omp critical { + /* for flatten center */ + add_v3_v3(area_co[0], private_co[0]); + add_v3_v3(area_co[1], private_co[1]); + /* for area normal */ - add_v3_v3(an, private_no[0]); - add_v3_v3(out_flip, private_no[1]); + add_v3_v3(area_no[0], private_no[0]); + add_v3_v3(area_no[1], private_no[1]); - /* for flatten center */ - add_v3_v3(fc, private_co[0]); - add_v3_v3(fc_flip, private_co[1]); - count += private_count[0]; - count_flipped += private_count[1]; + /* weights */ + count[0] += private_count[0]; + count[1] += private_count[1]; } } - /* for area normal */ - if (is_zero_v3(an)) - copy_v3_v3(an, out_flip); - - normalize_v3(an); - /* for flatten center */ - if (count != 0) - mul_v3_fl(fc, 1.0f / count); - else if (count_flipped != 0) - mul_v3_v3fl(fc, fc_flip, 1.0f / count_flipped); - else - zero_v3(fc); + for (n = 0; n < ARRAY_SIZE(area_co); n++) { + if (count[n] != 0) { + mul_v3_v3fl(r_area_co, area_co[n], 1.0f / count[n]); + break; + } + } + if (n == 2) { + zero_v3(r_area_co); + } + + /* for area normal */ + for (n = 0; n < ARRAY_SIZE(area_no); n++) { + if (normalize_v3_v3(r_area_no, area_no[n]) != 0.0f) { + break; + } + } } static void calc_sculpt_plane(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float an[3], float fc[3]) -- cgit v1.2.3 From fe39ebea12aa7d16e3b01b44ba2faa8884ad2585 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 19 Apr 2015 17:52:35 +1000 Subject: Cleanup: move project code into util function --- source/blender/editors/sculpt_paint/sculpt.c | 64 ++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 1f57059cd64..a08ea2ba60e 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -303,6 +303,47 @@ static void sculpt_orig_vert_data_update(SculptOrigVertData *orig_data, } } +/** \name SculptProjectVector + * + * Fast-path for #project_plane_v3_v3v3 + * + * \{ */ + +typedef struct SculptProjectVector { + float plane[3]; + float len_sq; + float len_sq_inv_neg; + bool is_valid; + +} SculptProjectVector; + +/** + * \param plane Direction, can be any length. + */ +static void sculpt_project_v3_cache_init( + SculptProjectVector *spvc, const float plane[3]) +{ + copy_v3_v3(spvc->plane, plane); + spvc->len_sq = len_squared_v3(spvc->plane); + spvc->is_valid = (spvc->len_sq > FLT_EPSILON); + spvc->len_sq_inv_neg = (spvc->is_valid) ? -1.0f / spvc->len_sq : 0.0f; +} + +static void sculpt_project_v3( + const SculptProjectVector *spvc, const float vec[3], + float r_vec[3]) +{ +#if 0 + project_plane_v3_v3v3(r_vec, vec, spvc->plane); +#else + /* inline the projection, cache `-1.0 / dot_v3_v3(v_proj, v_proj)` */ + madd_v3_v3fl(r_vec, spvc->plane, dot_v3v3(vec, spvc->plane) * spvc->len_sq_inv_neg); +#endif +} + +/** \} */ + + /**********************************************************************/ /* Returns true if the stroke will use dynamic topology, false @@ -1682,15 +1723,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod float brush_alpha; int n; - /* vars for handling projection when calculating the pinch vector. - * Use surface normal for 'pinch_proj', so the vertices are pinched towards a line instead of a single point. - * Without this we get a 'flat' surface surrounding the pinch */ - const float *pinch_proj = ss->cache->sculpt_normal_symm; - const float pinch_proj_len_sq = len_squared_v3(pinch_proj); - const bool do_pinch_proj = (pinch_proj_len_sq > FLT_EPSILON); - /* simplifies projection calc below */ - const float pinch_proj_len_sq_inv_neg = do_pinch_proj ? -1.0f / pinch_proj_len_sq : 0.0f; - + SculptProjectVector spvc; /* offset with as much as possible factored in already */ mul_v3_v3fl(offset, ss->cache->sculpt_normal_symm, ss->cache->radius); @@ -1708,6 +1741,10 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod if (brush->sculpt_tool == SCULPT_TOOL_BLOB) flippedbstrength *= -1.0f; + /* Use surface normal for 'spvc', so the vertices are pinched towards a line instead of a single point. + * Without this we get a 'flat' surface surrounding the pinch */ + sculpt_project_v3_cache_init(&spvc, ss->cache->sculpt_normal_symm); + /* threaded loop over nodes */ #pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) for (n = 0; n < totnode; n++) { @@ -1732,14 +1769,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod sub_v3_v3v3(val1, test.location, vd.co); mul_v3_fl(val1, fade * flippedbstrength); - if (do_pinch_proj) { -#if 0 - project_plane_v3_v3v3(val1, val1, v_proj); -#else - /* inline the projection, cache `-1.0 / dot_v3_v3(v_proj, v_proj)` */ - madd_v3_v3fl(val1, pinch_proj, dot_v3v3(val1, pinch_proj) * pinch_proj_len_sq_inv_neg); -#endif - } + sculpt_project_v3(&spvc, val1, val1); /* then we draw */ mul_v3_v3fl(val2, offset, fade); -- cgit v1.2.3 From fb6a0d24e1078574135ca1d083c2b933191d9bda Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 19 Apr 2015 18:22:25 +1000 Subject: Dyntopo: support for original normal access Rename calc_flatten_center to calc_area_center, since theres no 'flatten' spesific logic there. Also refactor calc_area_center, calc_area_normal, calc_area_normal_and_center so they're next to eachother - they're almost the same, having them scattered about isn't helpful. --- source/blender/editors/sculpt_paint/sculpt.c | 1037 ++++++++++++++------------ 1 file changed, 549 insertions(+), 488 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index a08ea2ba60e..4e3d03f916f 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -729,6 +729,429 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache) } } +/** \name Calculate Normal and Center + * + * Calculate geometry surrounding the brush center. + * (optionally using original coordinates). + * + * Functions are: + * - #calc_area_center + * - #calc_area_normal + * - #calc_area_normal_and_center + * + * \note These are all _very_ similar, when changing one, check others. + * \{ */ + +static void calc_area_center( + Sculpt *sd, Object *ob, + PBVHNode **nodes, int totnode, + float r_area_co[3]) +{ + SculptSession *ss = ob->sculpt; + int n; + + /* 0=towards view, 1=flipped */ + float area_co[2][3] = {{0.0f}}; + + int count[2] = {0}; + + (void)sd; /* unused w/o openmp */ + +#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) + for (n = 0; n < totnode; n++) { + PBVHVertexIter vd; + SculptBrushTest test; + SculptUndoNode *unode; + float private_co[2][3] = {{0.0f}}; + int private_count[2] = {0}; + bool use_original; + + unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); + sculpt_brush_test_init(ss, &test); + + use_original = (ss->cache->original && (unode->co || unode->bm_entry)); + + /* when the mesh is edited we can't rely on original coords + * (original mesh may not even have verts in brush radius) */ + if (use_original && unode->bm_entry) { + float (*orco_coords)[3]; + int (*orco_tris)[3]; + int orco_tris_num; + int i; + + BKE_pbvh_node_get_bm_orco_data( + nodes[n], + &orco_tris, &orco_tris_num, &orco_coords); + + for (i = 0; i < orco_tris_num; i++) { + const float *co_tri[3] = { + orco_coords[orco_tris[i][0]], + orco_coords[orco_tris[i][1]], + orco_coords[orco_tris[i][2]], + }; + float co[3]; + + closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri)); + + if (sculpt_brush_test_fast(&test, co)) { + float no[3]; + int flip_index; + + cross_tri_v3(no, UNPACK3(co_tri)); + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_co[flip_index], co); + private_count[flip_index] += 1; + } + } + } + else { + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + { + const float *co; + + if (use_original) { + co = unode->co[vd.i]; + } + else { + co = vd.co; + } + + if (sculpt_brush_test_fast(&test, co)) { + float no_buf[3]; + const float *no; + int flip_index; + + if (use_original) { + normal_short_to_float_v3(no_buf, unode->no[vd.i]); + no = no_buf; + } + else { + if (vd.no) { + normal_short_to_float_v3(no_buf, vd.no); + no = no_buf; + } + else { + no = vd.fno; + } + } + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_co[flip_index], co); + private_count[flip_index] += 1; + } + } + BKE_pbvh_vertex_iter_end; + } + +#pragma omp critical + { + /* for flatten center */ + add_v3_v3(area_co[0], private_co[0]); + add_v3_v3(area_co[1], private_co[1]); + + /* weights */ + count[0] += private_count[0]; + count[1] += private_count[1]; + } + } + + /* for flatten center */ + for (n = 0; n < ARRAY_SIZE(area_co); n++) { + if (count[n] != 0) { + mul_v3_v3fl(r_area_co, area_co[n], 1.0f / count[n]); + break; + } + } + if (n == 2) { + zero_v3(r_area_co); + } +} + + +static void calc_area_normal( + Sculpt *sd, Object *ob, + PBVHNode **nodes, int totnode, + float r_area_no[3]) +{ + const Brush *brush = BKE_paint_brush(&sd->paint); + SculptSession *ss = ob->sculpt; + int n; + + /* 0=towards view, 1=flipped */ + float area_no[2][3] = {{0.0f}}; + + int count[2] = {0}; + + /* Grab brush requires to test on original data (see T25371) */ + bool original; + + original = (brush->sculpt_tool == SCULPT_TOOL_GRAB) ? true : ss->cache->original; + /* In general the original coords are not available with dynamic + * topology + * + * Mask tool could not use undo nodes to get coordinates from + * since the coordinates are not stored in those nodes. + * And mask tool is not gonna to modify vertex coordinates, + * so we don't actually need to use modified coords. + */ + if (brush->sculpt_tool == SCULPT_TOOL_MASK) { + original = false; + } + +#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) + for (n = 0; n < totnode; n++) { + PBVHVertexIter vd; + SculptBrushTest test; + SculptUndoNode *unode; + float private_no[2][3] = {{0.0f}}; + int private_count[2] = {0}; + bool use_original; + + unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); + sculpt_brush_test_init(ss, &test); + + use_original = (original && (unode->co || unode->bm_entry)); + + /* when the mesh is edited we can't rely on original coords + * (original mesh may not even have verts in brush radius) */ + if (use_original && unode->bm_entry) { + float (*orco_coords)[3]; + int (*orco_tris)[3]; + int orco_tris_num; + int i; + + BKE_pbvh_node_get_bm_orco_data( + nodes[n], + &orco_tris, &orco_tris_num, &orco_coords); + + for (i = 0; i < orco_tris_num; i++) { + const float *co_tri[3] = { + orco_coords[orco_tris[i][0]], + orco_coords[orco_tris[i][1]], + orco_coords[orco_tris[i][2]], + }; + float co[3]; + + closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri)); + + if (sculpt_brush_test_fast(&test, co)) { + float no[3]; + int flip_index; + + normal_tri_v3(no, UNPACK3(co_tri)); + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_no[flip_index], no); + private_count[flip_index] += 1; + } + } + } + else { + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + { + const float *co; + + if (use_original) { + co = unode->co[vd.i]; + } + else { + co = vd.co; + } + + if (sculpt_brush_test_fast(&test, co)) { + float no_buf[3]; + const float *no; + int flip_index; + + if (use_original) { + normal_short_to_float_v3(no_buf, unode->no[vd.i]); + no = no_buf; + } + else { + if (vd.no) { + normal_short_to_float_v3(no_buf, vd.no); + no = no_buf; + } + else { + no = vd.fno; + } + } + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_no[flip_index], no); + private_count[flip_index] += 1; + } + } + BKE_pbvh_vertex_iter_end; + } + +#pragma omp critical + { + /* for area normal */ + add_v3_v3(area_no[0], private_no[0]); + add_v3_v3(area_no[1], private_no[1]); + + /* weights */ + count[0] += private_count[0]; + count[1] += private_count[1]; + } + } + + /* for area normal */ + for (n = 0; n < ARRAY_SIZE(area_no); n++) { + if (normalize_v3_v3(r_area_no, area_no[n]) != 0.0f) { + break; + } + } +} + +/* this calculates flatten center and area normal together, + * amortizing the memory bandwidth and loop overhead to calculate both at the same time */ +static void calc_area_normal_and_center( + Sculpt *sd, Object *ob, + PBVHNode **nodes, int totnode, + float r_area_no[3], float r_area_co[3]) +{ + SculptSession *ss = ob->sculpt; + int n; + + /* 0=towards view, 1=flipped */ + float area_co[2][3] = {{0.0f}}; + float area_no[2][3] = {{0.0f}}; + + int count[2] = {0}; + + (void)sd; /* unused w/o openmp */ + +#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) + for (n = 0; n < totnode; n++) { + PBVHVertexIter vd; + SculptBrushTest test; + SculptUndoNode *unode; + float private_co[2][3] = {{0.0f}}; + float private_no[2][3] = {{0.0f}}; + int private_count[2] = {0}; + bool use_original; + + unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); + sculpt_brush_test_init(ss, &test); + + use_original = (ss->cache->original && (unode->co || unode->bm_entry)); + + /* when the mesh is edited we can't rely on original coords + * (original mesh may not even have verts in brush radius) */ + if (use_original && unode->bm_entry) { + float (*orco_coords)[3]; + int (*orco_tris)[3]; + int orco_tris_num; + int i; + + BKE_pbvh_node_get_bm_orco_data( + nodes[n], + &orco_tris, &orco_tris_num, &orco_coords); + + for (i = 0; i < orco_tris_num; i++) { + const float *co_tri[3] = { + orco_coords[orco_tris[i][0]], + orco_coords[orco_tris[i][1]], + orco_coords[orco_tris[i][2]], + }; + float co[3]; + + closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri)); + + if (sculpt_brush_test_fast(&test, co)) { + float no[3]; + int flip_index; + + normal_tri_v3(no, UNPACK3(co_tri)); + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_co[flip_index], co); + add_v3_v3(private_no[flip_index], no); + private_count[flip_index] += 1; + } + } + } + else { + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + { + const float *co; + + if (use_original) { + co = unode->co[vd.i]; + } + else { + co = vd.co; + } + + if (sculpt_brush_test_fast(&test, co)) { + float no_buf[3]; + const float *no; + int flip_index; + + if (use_original) { + normal_short_to_float_v3(no_buf, unode->no[vd.i]); + no = no_buf; + } + else { + if (vd.no) { + normal_short_to_float_v3(no_buf, vd.no); + no = no_buf; + } + else { + no = vd.fno; + } + } + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_co[flip_index], co); + add_v3_v3(private_no[flip_index], no); + private_count[flip_index] += 1; + } + } + BKE_pbvh_vertex_iter_end; + } + +#pragma omp critical + { + /* for flatten center */ + add_v3_v3(area_co[0], private_co[0]); + add_v3_v3(area_co[1], private_co[1]); + + /* for area normal */ + add_v3_v3(area_no[0], private_no[0]); + add_v3_v3(area_no[1], private_no[1]); + + /* weights */ + count[0] += private_count[0]; + count[1] += private_count[1]; + } + } + + /* for flatten center */ + for (n = 0; n < ARRAY_SIZE(area_co); n++) { + if (count[n] != 0) { + mul_v3_v3fl(r_area_co, area_co[n], 1.0f / count[n]); + break; + } + } + if (n == 2) { + zero_v3(r_area_co); + } + + /* for area normal */ + for (n = 0; n < ARRAY_SIZE(area_no); n++) { + if (normalize_v3_v3(r_area_no, area_no[n]) != 0.0f) { + break; + } + } +} + +/** \} */ + + /* Return modified brush strength. Includes the direction of the brush, positive * values pull vertices, negative values push. Uses tablet pressure and a * special multiplier found experimentally to scale the strength factor. */ @@ -928,123 +1351,30 @@ static bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v) if (bb_min[i] > center[i]) nearest[i] = bb_min[i]; else if (bb_max[i] < center[i]) - nearest[i] = bb_max[i]; - else - nearest[i] = center[i]; - } - - sub_v3_v3v3(t, center, nearest); - - return len_squared_v3(t) < data->radius_squared; -} - -/* Handles clipping against a mirror modifier and SCULPT_LOCK axis flags */ -static void sculpt_clip(Sculpt *sd, SculptSession *ss, float co[3], const float val[3]) -{ - int i; - - for (i = 0; i < 3; ++i) { - if (sd->flags & (SCULPT_LOCK_X << i)) - continue; - - if ((ss->cache->flag & (CLIP_X << i)) && (fabsf(co[i]) <= ss->cache->clip_tolerance[i])) - co[i] = 0.0f; - else - co[i] = val[i]; - } -} - -static void add_norm_if(float view_vec[3], float out[3], float out_flip[3], float fno[3]) -{ - if ((dot_v3v3(view_vec, fno)) > 0) { - add_v3_v3(out, fno); - } - else { - add_v3_v3(out_flip, fno); /* out_flip is used when out is {0,0,0} */ - } -} - -static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nodes, int totnode) -{ - float out_flip[3] = {0.0f, 0.0f, 0.0f}; - - SculptSession *ss = ob->sculpt; - const Brush *brush = BKE_paint_brush(&sd->paint); - int n; - bool original; - - /* Grab brush requires to test on original data (see r33888 and - * bug #25371) */ - original = (BKE_paint_brush(&sd->paint)->sculpt_tool == SCULPT_TOOL_GRAB ? - true : ss->cache->original); - - /* In general the original coords are not available with dynamic - * topology - * - * Mask tool could not use undo nodes to get coordinates from - * since the coordinates are not stored in those odes. - * And mask tool is not gonna to modify vertex coordinates, - * so we don't actually need to use modified coords. - */ - if (ss->bm || brush->sculpt_tool == SCULPT_TOOL_MASK) - original = false; - - (void)sd; /* unused w/o openmp */ - - zero_v3(an); - -#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) - for (n = 0; n < totnode; n++) { - PBVHVertexIter vd; - SculptBrushTest test; - SculptUndoNode *unode; - float private_an[3] = {0.0f, 0.0f, 0.0f}; - float private_out_flip[3] = {0.0f, 0.0f, 0.0f}; - - unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); - sculpt_brush_test_init(ss, &test); + nearest[i] = bb_max[i]; + else + nearest[i] = center[i]; + } + + sub_v3_v3v3(t, center, nearest); - if (original) { - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - if (sculpt_brush_test_fast(&test, unode->co[vd.i])) { - float fno[3]; + return len_squared_v3(t) < data->radius_squared; +} - normal_short_to_float_v3(fno, unode->no[vd.i]); - add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno); - } - } - BKE_pbvh_vertex_iter_end; - } - else { - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - if (sculpt_brush_test_fast(&test, vd.co)) { - if (vd.no) { - float fno[3]; +/* Handles clipping against a mirror modifier and SCULPT_LOCK axis flags */ +static void sculpt_clip(Sculpt *sd, SculptSession *ss, float co[3], const float val[3]) +{ + int i; - normal_short_to_float_v3(fno, vd.no); - add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno); - } - else { - add_norm_if(ss->cache->view_normal, private_an, private_out_flip, vd.fno); - } - } - } - BKE_pbvh_vertex_iter_end; - } + for (i = 0; i < 3; ++i) { + if (sd->flags & (SCULPT_LOCK_X << i)) + continue; -#pragma omp critical - { - add_v3_v3(an, private_an); - add_v3_v3(out_flip, private_out_flip); - } + if ((ss->cache->flag & (CLIP_X << i)) && (fabsf(co[i]) <= ss->cache->clip_tolerance[i])) + co[i] = 0.0f; + else + co[i] = val[i]; } - - if (is_zero_v3(an)) - copy_v3_v3(an, out_flip); - - normalize_v3(an); } /* Calculate primary direction of movement for many brushes */ @@ -1079,7 +1409,7 @@ static void calc_sculpt_normal(Sculpt *sd, Object *ob, break; case SCULPT_DISP_DIR_AREA: - calc_area_normal(sd, ob, an, nodes, totnode); + calc_area_normal(sd, ob, nodes, totnode, an); break; default: @@ -2014,422 +2344,153 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod Brush *brush = BKE_paint_brush(&sd->paint); float bstrength = ss->cache->bstrength; int n; - static const int flip[8] = { 1, -1, -1, 1, -1, 1, 1, -1 }; - float angle = ss->cache->vertex_rotation * flip[ss->cache->mirror_symmetry_pass]; - -#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) - for (n = 0; n < totnode; n++) { - PBVHVertexIter vd; - SculptBrushTest test; - SculptOrigVertData orig_data; - float (*proxy)[3]; - - sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]); - - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; - - sculpt_brush_test_init(ss, &test); - - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - sculpt_orig_vert_data_update(&orig_data, &vd); - - if (sculpt_brush_test(&test, orig_data.co)) { - float vec[3], rot[3][3]; - const float fade = bstrength * tex_strength(ss, brush, - orig_data.co, - test.dist, - orig_data.no, - NULL, vd.mask ? *vd.mask : 0.0f); - - sub_v3_v3v3(vec, orig_data.co, ss->cache->location); - axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade); - mul_v3_m3v3(proxy[vd.i], rot, vec); - add_v3_v3(proxy[vd.i], ss->cache->location); - sub_v3_v3(proxy[vd.i], orig_data.co); - - if (vd.mvert) - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - BKE_pbvh_vertex_iter_end; - } -} - -static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) -{ - SculptSession *ss = ob->sculpt; - Brush *brush = BKE_paint_brush(&sd->paint); - float bstrength = ss->cache->bstrength; - float offset[3]; - float lim = brush->height; - int n; - - if (bstrength < 0) - lim = -lim; - - mul_v3_v3v3(offset, ss->cache->scale, ss->cache->sculpt_normal_symm); - -#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) - for (n = 0; n < totnode; n++) { - PBVHVertexIter vd; - SculptBrushTest test; - SculptOrigVertData orig_data; - float *layer_disp; - /* XXX: layer brush needs conversion to proxy but its more complicated */ - /* proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; */ - - sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]); - -#pragma omp critical - { - layer_disp = BKE_pbvh_node_layer_disp_get(ss->pbvh, nodes[n]); - } - - sculpt_brush_test_init(ss, &test); - - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - sculpt_orig_vert_data_update(&orig_data, &vd); - - if (sculpt_brush_test(&test, orig_data.co)) { - const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, - vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); - float *disp = &layer_disp[vd.i]; - float val[3]; - - *disp += fade; - - /* Don't let the displacement go past the limit */ - if ((lim < 0 && *disp < lim) || (lim >= 0 && *disp > lim)) - *disp = lim; - - mul_v3_v3fl(val, offset, *disp); - - if (!ss->multires && !ss->bm && ss->layer_co && (brush->flag & BRUSH_PERSISTENT)) { - int index = vd.vert_indices[vd.i]; - - /* persistent base */ - add_v3_v3(val, ss->layer_co[index]); - } - else { - add_v3_v3(val, orig_data.co); - } - - sculpt_clip(sd, ss, vd.co, val); - - if (vd.mvert) - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - BKE_pbvh_vertex_iter_end; - } -} - -static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) -{ - SculptSession *ss = ob->sculpt; - Brush *brush = BKE_paint_brush(&sd->paint); - float bstrength = ss->cache->bstrength; - int n; - -#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) - for (n = 0; n < totnode; n++) { - PBVHVertexIter vd; - SculptBrushTest test; - float (*proxy)[3]; - - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; - - sculpt_brush_test_init(ss, &test); - - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - if (sculpt_brush_test(&test, vd.co)) { - const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, - vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); - float val[3]; - - if (vd.fno) copy_v3_v3(val, vd.fno); - else normal_short_to_float_v3(val, vd.no); - - mul_v3_fl(val, fade * ss->cache->radius); - mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale); - - if (vd.mvert) - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - BKE_pbvh_vertex_iter_end; - } -} - -static void calc_flatten_center( - Sculpt *sd, Object *ob, - PBVHNode **nodes, int totnode, - float r_area_co[3]) -{ - SculptSession *ss = ob->sculpt; - int n; - - /* 0=towards view, 1=flipped */ - float area_co[2][3] = {{0.0f}}; - - int count[2] = {0}; - - (void)sd; /* unused w/o openmp */ - -#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) - for (n = 0; n < totnode; n++) { - PBVHVertexIter vd; - SculptBrushTest test; - SculptUndoNode *unode; - float private_co[2][3] = {{0.0f}}; - int private_count[2] = {0}; - bool use_original; - - unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); - sculpt_brush_test_init(ss, &test); - - use_original = (ss->cache->original && (unode->co || unode->bm_entry)); - - /* when the mesh is edited we can't rely on original coords - * (original mesh may not even have verts in brush radius) */ - if (use_original && unode->bm_entry) { - float (*orco_coords)[3]; - int (*orco_tris)[3]; - int orco_tris_num; - int i; - - BKE_pbvh_node_get_bm_orco_data( - nodes[n], - &orco_tris, &orco_tris_num, &orco_coords); - - for (i = 0; i < orco_tris_num; i++) { - const float *co_tri[3] = { - orco_coords[orco_tris[i][0]], - orco_coords[orco_tris[i][1]], - orco_coords[orco_tris[i][2]], - }; - float co[3]; - - closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri)); - - if (sculpt_brush_test_fast(&test, co)) { - float no[3]; - int flip_index; - - cross_tri_v3(no, UNPACK3(co_tri)); - - flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); - add_v3_v3(private_co[flip_index], co); - private_count[flip_index] += 1; - } - } - } - else { - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - const float *co; + static const int flip[8] = { 1, -1, -1, 1, -1, 1, 1, -1 }; + float angle = ss->cache->vertex_rotation * flip[ss->cache->mirror_symmetry_pass]; - if (use_original) { - co = unode->co[vd.i]; - } - else { - co = vd.co; - } +#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) + for (n = 0; n < totnode; n++) { + PBVHVertexIter vd; + SculptBrushTest test; + SculptOrigVertData orig_data; + float (*proxy)[3]; - if (sculpt_brush_test_fast(&test, co)) { - float no_buf[3]; - const float *no; - int flip_index; + sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]); - if (use_original) { - normal_short_to_float_v3(no_buf, unode->no[vd.i]); - no = no_buf; - } - else { - if (vd.no) { - normal_short_to_float_v3(no_buf, vd.no); - no = no_buf; - } - else { - no = vd.fno; - } - } + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; - flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); - add_v3_v3(private_co[flip_index], co); - private_count[flip_index] += 1; - } - } - BKE_pbvh_vertex_iter_end; - } + sculpt_brush_test_init(ss, &test); -#pragma omp critical + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { - /* for flatten center */ - add_v3_v3(area_co[0], private_co[0]); - add_v3_v3(area_co[1], private_co[1]); + sculpt_orig_vert_data_update(&orig_data, &vd); - /* weights */ - count[0] += private_count[0]; - count[1] += private_count[1]; - } - } + if (sculpt_brush_test(&test, orig_data.co)) { + float vec[3], rot[3][3]; + const float fade = bstrength * tex_strength(ss, brush, + orig_data.co, + test.dist, + orig_data.no, + NULL, vd.mask ? *vd.mask : 0.0f); - /* for flatten center */ - for (n = 0; n < ARRAY_SIZE(area_co); n++) { - if (count[n] != 0) { - mul_v3_v3fl(r_area_co, area_co[n], 1.0f / count[n]); - break; + sub_v3_v3v3(vec, orig_data.co, ss->cache->location); + axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade); + mul_v3_m3v3(proxy[vd.i], rot, vec); + add_v3_v3(proxy[vd.i], ss->cache->location); + sub_v3_v3(proxy[vd.i], orig_data.co); + + if (vd.mvert) + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } } - } - if (n == 2) { - zero_v3(r_area_co); + BKE_pbvh_vertex_iter_end; } } -/* this calculates flatten center and area normal together, - * amortizing the memory bandwidth and loop overhead to calculate both at the same time */ -static void calc_area_normal_and_flatten_center( - Sculpt *sd, Object *ob, - PBVHNode **nodes, int totnode, - float r_area_no[3], float r_area_co[3]) +static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) { SculptSession *ss = ob->sculpt; + Brush *brush = BKE_paint_brush(&sd->paint); + float bstrength = ss->cache->bstrength; + float offset[3]; + float lim = brush->height; int n; - /* 0=towards view, 1=flipped */ - float area_co[2][3] = {{0.0f}}; - float area_no[2][3] = {{0.0f}}; - - int count[2] = {0}; + if (bstrength < 0) + lim = -lim; - (void)sd; /* unused w/o openmp */ + mul_v3_v3v3(offset, ss->cache->scale, ss->cache->sculpt_normal_symm); #pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) for (n = 0; n < totnode; n++) { PBVHVertexIter vd; SculptBrushTest test; - SculptUndoNode *unode; - float private_co[2][3] = {{0.0f}}; - float private_no[2][3] = {{0.0f}}; - int private_count[2] = {0}; - bool use_original; + SculptOrigVertData orig_data; + float *layer_disp; + /* XXX: layer brush needs conversion to proxy but its more complicated */ + /* proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; */ + + sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]); - unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); +#pragma omp critical + { + layer_disp = BKE_pbvh_node_layer_disp_get(ss->pbvh, nodes[n]); + } + sculpt_brush_test_init(ss, &test); - use_original = (ss->cache->original && (unode->co || unode->bm_entry)); - - /* when the mesh is edited we can't rely on original coords - * (original mesh may not even have verts in brush radius) */ - if (use_original && unode->bm_entry) { - float (*orco_coords)[3]; - int (*orco_tris)[3]; - int orco_tris_num; - int i; - - BKE_pbvh_node_get_bm_orco_data( - nodes[n], - &orco_tris, &orco_tris_num, &orco_coords); + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + { + sculpt_orig_vert_data_update(&orig_data, &vd); - for (i = 0; i < orco_tris_num; i++) { - const float *co_tri[3] = { - orco_coords[orco_tris[i][0]], - orco_coords[orco_tris[i][1]], - orco_coords[orco_tris[i][2]], - }; - float co[3]; + if (sculpt_brush_test(&test, orig_data.co)) { + const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, + vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); + float *disp = &layer_disp[vd.i]; + float val[3]; - closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri)); + *disp += fade; - if (sculpt_brush_test_fast(&test, co)) { - float no[3]; - int flip_index; + /* Don't let the displacement go past the limit */ + if ((lim < 0 && *disp < lim) || (lim >= 0 && *disp > lim)) + *disp = lim; - normal_tri_v3(no, UNPACK3(co_tri)); + mul_v3_v3fl(val, offset, *disp); - flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); - add_v3_v3(private_co[flip_index], co); - add_v3_v3(private_no[flip_index], no); - private_count[flip_index] += 1; - } - } - } - else { - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - const float *co; + if (!ss->multires && !ss->bm && ss->layer_co && (brush->flag & BRUSH_PERSISTENT)) { + int index = vd.vert_indices[vd.i]; - if (use_original) { - co = unode->co[vd.i]; + /* persistent base */ + add_v3_v3(val, ss->layer_co[index]); } else { - co = vd.co; + add_v3_v3(val, orig_data.co); } - if (sculpt_brush_test_fast(&test, co)) { - float no_buf[3]; - const float *no; - int flip_index; - - if (use_original) { - normal_short_to_float_v3(no_buf, unode->no[vd.i]); - no = no_buf; - } - else { - if (vd.no) { - normal_short_to_float_v3(no_buf, vd.no); - no = no_buf; - } - else { - no = vd.fno; - } - } + sculpt_clip(sd, ss, vd.co, val); - flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); - add_v3_v3(private_co[flip_index], co); - add_v3_v3(private_no[flip_index], no); - private_count[flip_index] += 1; - } + if (vd.mvert) + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } - BKE_pbvh_vertex_iter_end; } + BKE_pbvh_vertex_iter_end; + } +} -#pragma omp critical - { - /* for flatten center */ - add_v3_v3(area_co[0], private_co[0]); - add_v3_v3(area_co[1], private_co[1]); +static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) +{ + SculptSession *ss = ob->sculpt; + Brush *brush = BKE_paint_brush(&sd->paint); + float bstrength = ss->cache->bstrength; + int n; - /* for area normal */ - add_v3_v3(area_no[0], private_no[0]); - add_v3_v3(area_no[1], private_no[1]); +#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) + for (n = 0; n < totnode; n++) { + PBVHVertexIter vd; + SculptBrushTest test; + float (*proxy)[3]; - /* weights */ - count[0] += private_count[0]; - count[1] += private_count[1]; - } - } + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; - /* for flatten center */ - for (n = 0; n < ARRAY_SIZE(area_co); n++) { - if (count[n] != 0) { - mul_v3_v3fl(r_area_co, area_co[n], 1.0f / count[n]); - break; - } - } - if (n == 2) { - zero_v3(r_area_co); - } + sculpt_brush_test_init(ss, &test); - /* for area normal */ - for (n = 0; n < ARRAY_SIZE(area_no); n++) { - if (normalize_v3_v3(r_area_no, area_no[n]) != 0.0f) { - break; + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + { + if (sculpt_brush_test(&test, vd.co)) { + const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, + vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); + float val[3]; + + if (vd.fno) copy_v3_v3(val, vd.fno); + else normal_short_to_float_v3(val, vd.no); + + mul_v3_fl(val, fade * ss->cache->radius); + mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale); + + if (vd.mvert) + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } } + BKE_pbvh_vertex_iter_end; } } @@ -2466,7 +2527,7 @@ static void calc_sculpt_plane(Sculpt *sd, Object *ob, PBVHNode **nodes, int totn break; case SCULPT_DISP_DIR_AREA: - calc_area_normal_and_flatten_center(sd, ob, nodes, totnode, an, fc); + calc_area_normal_and_center(sd, ob, nodes, totnode, an, fc); break; default: @@ -2476,7 +2537,7 @@ static void calc_sculpt_plane(Sculpt *sd, Object *ob, PBVHNode **nodes, int totn /* for flatten center */ /* flatten center has not been calculated yet if we are not using the area normal */ if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA) - calc_flatten_center(sd, ob, nodes, totnode, fc); + calc_area_center(sd, ob, nodes, totnode, fc); /* for area normal */ copy_v3_v3(ss->cache->sculpt_normal, an); @@ -2722,7 +2783,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t calc_sculpt_plane(sd, ob, nodes, totnode, sn, fc); if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA || (brush->flag & BRUSH_ORIGINAL_NORMAL)) - calc_area_normal(sd, ob, an, nodes, totnode); + calc_area_normal(sd, ob, nodes, totnode, an); else copy_v3_v3(an, sn); -- cgit v1.2.3 From ac73fe5fe0443dd3b0f237eb37523fd9c79dff4e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 19 Apr 2015 18:36:53 +1000 Subject: Cleanup: use meaningful names re: (fc, an, sn) --- source/blender/editors/sculpt_paint/sculpt.c | 154 +++++++++++++-------------- 1 file changed, 73 insertions(+), 81 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 4e3d03f916f..7ab80e8d791 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -635,7 +635,7 @@ static float frontface(Brush *br, const float sculpt_normal[3], #if 0 -static bool sculpt_brush_test_cyl(SculptBrushTest *test, float co[3], float location[3], float an[3]) +static bool sculpt_brush_test_cyl(SculptBrushTest *test, float co[3], float location[3], const float area_no[3]) { if (sculpt_brush_test_fast(test, co)) { float t1[3], t2[3], t3[3], dist; @@ -643,7 +643,7 @@ static bool sculpt_brush_test_cyl(SculptBrushTest *test, float co[3], float loca sub_v3_v3v3(t1, location, co); sub_v3_v3v3(t2, x2, location); - cross_v3_v3v3(t3, an, t1); + cross_v3_v3v3(t3, area_no, t1); dist = len_v3(t3) / len_v3(t2); @@ -1378,38 +1378,33 @@ static void sculpt_clip(Sculpt *sd, SculptSession *ss, float co[3], const float } /* Calculate primary direction of movement for many brushes */ -static void calc_sculpt_normal(Sculpt *sd, Object *ob, - PBVHNode **nodes, int totnode, - float an[3]) +static void calc_sculpt_normal( + Sculpt *sd, Object *ob, + PBVHNode **nodes, int totnode, + float r_area_no[3]) { const Brush *brush = BKE_paint_brush(&sd->paint); const SculptSession *ss = ob->sculpt; switch (brush->sculpt_plane) { case SCULPT_DISP_DIR_VIEW: - copy_v3_v3(an, ss->cache->true_view_normal); + copy_v3_v3(r_area_no, ss->cache->true_view_normal); break; case SCULPT_DISP_DIR_X: - an[1] = 0.0; - an[2] = 0.0; - an[0] = 1.0; + ARRAY_SET_ITEMS(r_area_no, 1, 0, 0); break; case SCULPT_DISP_DIR_Y: - an[0] = 0.0; - an[2] = 0.0; - an[1] = 1.0; + ARRAY_SET_ITEMS(r_area_no, 0, 1, 0); break; case SCULPT_DISP_DIR_Z: - an[0] = 0.0; - an[1] = 0.0; - an[2] = 1.0; + ARRAY_SET_ITEMS(r_area_no, 0, 0, 1); break; case SCULPT_DISP_DIR_AREA: - calc_area_normal(sd, ob, nodes, totnode, an); + calc_area_normal(sd, ob, nodes, totnode, r_area_no); break; default: @@ -2494,7 +2489,10 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno } } -static void calc_sculpt_plane(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float an[3], float fc[3]) +static void calc_sculpt_plane( + Sculpt *sd, Object *ob, + PBVHNode **nodes, int totnode, + float r_area_no[3], float r_area_co[3]) { SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -2505,29 +2503,23 @@ static void calc_sculpt_plane(Sculpt *sd, Object *ob, PBVHNode **nodes, int totn { switch (brush->sculpt_plane) { case SCULPT_DISP_DIR_VIEW: - copy_v3_v3(an, ss->cache->true_view_normal); + copy_v3_v3(r_area_no, ss->cache->true_view_normal); break; case SCULPT_DISP_DIR_X: - an[1] = 0.0; - an[2] = 0.0; - an[0] = 1.0; + ARRAY_SET_ITEMS(r_area_no, 1, 0, 0); break; case SCULPT_DISP_DIR_Y: - an[0] = 0.0; - an[2] = 0.0; - an[1] = 1.0; + ARRAY_SET_ITEMS(r_area_no, 0, 1, 0); break; case SCULPT_DISP_DIR_Z: - an[0] = 0.0; - an[1] = 0.0; - an[2] = 1.0; + ARRAY_SET_ITEMS(r_area_no, 0, 0, 1); break; case SCULPT_DISP_DIR_AREA: - calc_area_normal_and_center(sd, ob, nodes, totnode, an, fc); + calc_area_normal_and_center(sd, ob, nodes, totnode, r_area_no, r_area_co); break; default: @@ -2537,32 +2529,32 @@ static void calc_sculpt_plane(Sculpt *sd, Object *ob, PBVHNode **nodes, int totn /* for flatten center */ /* flatten center has not been calculated yet if we are not using the area normal */ if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA) - calc_area_center(sd, ob, nodes, totnode, fc); + calc_area_center(sd, ob, nodes, totnode, r_area_co); /* for area normal */ - copy_v3_v3(ss->cache->sculpt_normal, an); + copy_v3_v3(ss->cache->sculpt_normal, r_area_no); /* for flatten center */ - copy_v3_v3(ss->cache->last_center, fc); + copy_v3_v3(ss->cache->last_center, r_area_co); } else { /* for area normal */ - copy_v3_v3(an, ss->cache->sculpt_normal); + copy_v3_v3(r_area_no, ss->cache->sculpt_normal); /* for flatten center */ - copy_v3_v3(fc, ss->cache->last_center); + copy_v3_v3(r_area_co, ss->cache->last_center); /* for area normal */ - flip_v3(an, ss->cache->mirror_symmetry_pass); + flip_v3(r_area_no, ss->cache->mirror_symmetry_pass); /* for flatten center */ - flip_v3(fc, ss->cache->mirror_symmetry_pass); + flip_v3(r_area_co, ss->cache->mirror_symmetry_pass); /* for area normal */ - mul_m4_v3(ss->cache->symm_rot_mat, an); + mul_m4_v3(ss->cache->symm_rot_mat, r_area_no); /* for flatten center */ - mul_m4_v3(ss->cache->symm_rot_mat, fc); + mul_m4_v3(ss->cache->symm_rot_mat, r_area_co); } } @@ -2626,8 +2618,8 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno float bstrength = ss->cache->bstrength; const float radius = ss->cache->radius; - float an[3]; - float fc[3]; + float area_no[3]; + float area_co[3]; float offset = get_offset(sd, ss); @@ -2637,13 +2629,13 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno float temp[3]; - calc_sculpt_plane(sd, ob, nodes, totnode, an, fc); + calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co); displace = radius * offset; - mul_v3_v3v3(temp, an, ss->cache->scale); + mul_v3_v3v3(temp, area_no, ss->cache->scale); mul_v3_fl(temp, displace); - add_v3_v3(fc, temp); + add_v3_v3(area_co, temp); #pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) for (n = 0; n < totnode; n++) { @@ -2661,7 +2653,7 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno float intr[3]; float val[3]; - point_plane_project(intr, vd.co, an, fc); + point_plane_project(intr, vd.co, area_no, area_co); sub_v3_v3v3(val, intr, vd.co); @@ -2691,8 +2683,8 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) float displace; - float an[3]; - float fc[3]; + float area_no[3]; + float area_co[3]; int n; @@ -2700,7 +2692,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) bool flip; - calc_sculpt_plane(sd, ob, nodes, totnode, an, fc); + calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co); flip = bstrength < 0; @@ -2711,11 +2703,11 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) displace = radius * (0.25f + offset); - mul_v3_v3v3(temp, an, ss->cache->scale); + mul_v3_v3v3(temp, area_no, ss->cache->scale); mul_v3_fl(temp, displace); - add_v3_v3(fc, temp); + add_v3_v3(area_co, temp); - /* add_v3_v3v3(p, ss->cache->location, an); */ + /* add_v3_v3v3(p, ss->cache->location, area_no); */ #pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) for (n = 0; n < totnode; n++) { @@ -2730,11 +2722,11 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq(&test, vd.co)) { - if (plane_point_side_flip(vd.co, an, fc, flip)) { + if (plane_point_side_flip(vd.co, area_no, area_co, flip)) { float intr[3]; float val[3]; - point_plane_project(intr, vd.co, an, fc); + point_plane_project(intr, vd.co, area_no, area_co); sub_v3_v3v3(val, intr, vd.co); @@ -2742,7 +2734,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) /* note, the normal from the vertices is ignored, * causes glitch with planes, see: T44390 */ const float fade = bstrength * tex_strength(ss, brush, vd.co, sqrtf(test.dist), - NULL, an, vd.mask ? *vd.mask : 0.0f); + NULL, area_no, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -2767,9 +2759,9 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t float displace; - float sn[3]; - float an[3]; - float fc[3]; + float area_no_sp[3]; /* the sculpt-plane normal (whatever its set to) */ + float area_no[3]; /* geometry normal */ + float area_co[3]; int n; @@ -2780,12 +2772,12 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t bool flip; - calc_sculpt_plane(sd, ob, nodes, totnode, sn, fc); + calc_sculpt_plane(sd, ob, nodes, totnode, area_no_sp, area_co); if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA || (brush->flag & BRUSH_ORIGINAL_NORMAL)) - calc_area_normal(sd, ob, nodes, totnode, an); + calc_area_normal(sd, ob, nodes, totnode, area_no); else - copy_v3_v3(an, sn); + copy_v3_v3(area_no, area_no_sp); /* delay the first daub because grab delta is not setup */ if (ss->cache->first_time) @@ -2800,16 +2792,16 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t displace = radius * (0.25f + offset); - mul_v3_v3v3(temp, sn, ss->cache->scale); + mul_v3_v3v3(temp, area_no_sp, ss->cache->scale); mul_v3_fl(temp, displace); - add_v3_v3(fc, temp); + add_v3_v3(area_co, temp); /* init mat */ - cross_v3_v3v3(mat[0], an, ss->cache->grab_delta_symmetry); + cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry); mat[0][3] = 0; - cross_v3_v3v3(mat[1], an, mat[0]); + cross_v3_v3v3(mat[1], area_no, mat[0]); mat[1][3] = 0; - copy_v3_v3(mat[2], an); + copy_v3_v3(mat[2], area_no); mat[2][3] = 0; copy_v3_v3(mat[3], ss->cache->location); mat[3][3] = 1; @@ -2833,11 +2825,11 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_cube(&test, vd.co, mat)) { - if (plane_point_side_flip(vd.co, sn, fc, flip)) { + if (plane_point_side_flip(vd.co, area_no_sp, area_co, flip)) { float intr[3]; float val[3]; - point_plane_project(intr, vd.co, sn, fc); + point_plane_project(intr, vd.co, area_no_sp, area_co); sub_v3_v3v3(val, intr, vd.co); @@ -2846,7 +2838,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t * causes glitch with planes, see: T44390 */ const float fade = bstrength * tex_strength(ss, brush, vd.co, ss->cache->radius * test.dist, - NULL, an, vd.mask ? *vd.mask : 0.0f); + NULL, area_no, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -2868,8 +2860,8 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) float bstrength = ss->cache->bstrength; const float radius = ss->cache->radius; - float an[3]; - float fc[3]; + float area_no[3]; + float area_co[3]; float offset = get_offset(sd, ss); float displace; @@ -2878,13 +2870,13 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) float temp[3]; - calc_sculpt_plane(sd, ob, nodes, totnode, an, fc); + calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co); displace = radius * offset; - mul_v3_v3v3(temp, an, ss->cache->scale); + mul_v3_v3v3(temp, area_no, ss->cache->scale); mul_v3_fl(temp, displace); - add_v3_v3(fc, temp); + add_v3_v3(area_co, temp); #pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) for (n = 0; n < totnode; n++) { @@ -2899,11 +2891,11 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq(&test, vd.co)) { - if (plane_point_side(vd.co, an, fc)) { + if (plane_point_side(vd.co, area_no, area_co)) { float intr[3]; float val[3]; - point_plane_project(intr, vd.co, an, fc); + point_plane_project(intr, vd.co, area_no, area_co); sub_v3_v3v3(val, intr, vd.co); @@ -2932,8 +2924,8 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod float bstrength = ss->cache->bstrength; const float radius = ss->cache->radius; - float an[3]; - float fc[3]; + float area_no[3]; + float area_co[3]; float offset = get_offset(sd, ss); float displace; @@ -2942,13 +2934,13 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod float temp[3]; - calc_sculpt_plane(sd, ob, nodes, totnode, an, fc); + calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co); displace = -radius * offset; - mul_v3_v3v3(temp, an, ss->cache->scale); + mul_v3_v3v3(temp, area_no, ss->cache->scale); mul_v3_fl(temp, displace); - add_v3_v3(fc, temp); + add_v3_v3(area_co, temp); #pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) for (n = 0; n < totnode; n++) { @@ -2963,11 +2955,11 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq(&test, vd.co)) { - if (!plane_point_side(vd.co, an, fc)) { + if (!plane_point_side(vd.co, area_no, area_co)) { float intr[3]; float val[3]; - point_plane_project(intr, vd.co, an, fc); + point_plane_project(intr, vd.co, area_no, area_co); sub_v3_v3v3(val, intr, vd.co); @@ -2993,7 +2985,7 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); - float offset[3]/*, an[3]*/; + float offset[3]/*, area_no[3]*/; int n; float gravity_vector[3]; -- cgit v1.2.3 From e5048dd4ca8b8b40dacda52b87fce642fa51e922 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 19 Apr 2015 19:51:02 +1000 Subject: Dyntopo: non-topology tool origdata support Brushes that don't change topology didn't have access to original data. --- source/blender/editors/sculpt_paint/sculpt.c | 52 +++++++++++++++++++--------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 7ab80e8d791..0af93e625ac 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -389,10 +389,6 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob) PBVHNode **nodes; int n, totnode; -#ifndef _OPENMP - (void)sd; /* quied unused warning */ -#endif - BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); /* Disable OpenMP when dynamic-topology is enabled. Otherwise, new @@ -747,7 +743,9 @@ static void calc_area_center( PBVHNode **nodes, int totnode, float r_area_co[3]) { + const Brush *brush = BKE_paint_brush(&sd->paint); SculptSession *ss = ob->sculpt; + const bool has_bm_orco = ss->bm && sculpt_stroke_dynamic_topology(ss, brush); int n; /* 0=towards view, 1=flipped */ @@ -755,8 +753,6 @@ static void calc_area_center( int count[2] = {0}; - (void)sd; /* unused w/o openmp */ - #pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) for (n = 0; n < totnode; n++) { PBVHVertexIter vd; @@ -773,7 +769,7 @@ static void calc_area_center( /* when the mesh is edited we can't rely on original coords * (original mesh may not even have verts in brush radius) */ - if (use_original && unode->bm_entry) { + if (use_original && has_bm_orco) { float (*orco_coords)[3]; int (*orco_tris)[3]; int orco_tris_num; @@ -809,9 +805,16 @@ static void calc_area_center( BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { const float *co; + const short *no_s; /* bm_vert only */ if (use_original) { - co = unode->co[vd.i]; + if (unode->bm_entry) { + BM_log_original_vert_data(ss->bm_log, vd.bm_vert, &co, &no_s); + } + else { + co = unode->co[vd.i]; + no_s = unode->no[vd.i]; + } } else { co = vd.co; @@ -823,7 +826,7 @@ static void calc_area_center( int flip_index; if (use_original) { - normal_short_to_float_v3(no_buf, unode->no[vd.i]); + normal_short_to_float_v3(no_buf, no_s); no = no_buf; } else { @@ -876,6 +879,7 @@ static void calc_area_normal( { const Brush *brush = BKE_paint_brush(&sd->paint); SculptSession *ss = ob->sculpt; + const bool has_bm_orco = ss->bm && sculpt_stroke_dynamic_topology(ss, brush); int n; /* 0=towards view, 1=flipped */ @@ -915,7 +919,7 @@ static void calc_area_normal( /* when the mesh is edited we can't rely on original coords * (original mesh may not even have verts in brush radius) */ - if (use_original && unode->bm_entry) { + if (use_original && has_bm_orco) { float (*orco_coords)[3]; int (*orco_tris)[3]; int orco_tris_num; @@ -951,9 +955,16 @@ static void calc_area_normal( BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { const float *co; + const short *no_s; /* bm_vert only */ if (use_original) { - co = unode->co[vd.i]; + if (unode->bm_entry) { + BM_log_original_vert_data(ss->bm_log, vd.bm_vert, &co, &no_s); + } + else { + co = unode->co[vd.i]; + no_s = unode->no[vd.i]; + } } else { co = vd.co; @@ -965,7 +976,7 @@ static void calc_area_normal( int flip_index; if (use_original) { - normal_short_to_float_v3(no_buf, unode->no[vd.i]); + normal_short_to_float_v3(no_buf, no_s); no = no_buf; } else { @@ -1013,7 +1024,9 @@ static void calc_area_normal_and_center( PBVHNode **nodes, int totnode, float r_area_no[3], float r_area_co[3]) { + const Brush *brush = BKE_paint_brush(&sd->paint); SculptSession *ss = ob->sculpt; + const bool has_bm_orco = ss->bm && sculpt_stroke_dynamic_topology(ss, brush); int n; /* 0=towards view, 1=flipped */ @@ -1022,8 +1035,6 @@ static void calc_area_normal_and_center( int count[2] = {0}; - (void)sd; /* unused w/o openmp */ - #pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) for (n = 0; n < totnode; n++) { PBVHVertexIter vd; @@ -1041,7 +1052,7 @@ static void calc_area_normal_and_center( /* when the mesh is edited we can't rely on original coords * (original mesh may not even have verts in brush radius) */ - if (use_original && unode->bm_entry) { + if (use_original && has_bm_orco) { float (*orco_coords)[3]; int (*orco_tris)[3]; int orco_tris_num; @@ -1078,9 +1089,16 @@ static void calc_area_normal_and_center( BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { const float *co; + const short *no_s; /* bm_vert only */ if (use_original) { - co = unode->co[vd.i]; + if (unode->bm_entry) { + BM_log_original_vert_data(ss->bm_log, vd.bm_vert, &co, &no_s); + } + else { + co = unode->co[vd.i]; + no_s = unode->no[vd.i]; + } } else { co = vd.co; @@ -1092,7 +1110,7 @@ static void calc_area_normal_and_center( int flip_index; if (use_original) { - normal_short_to_float_v3(no_buf, unode->no[vd.i]); + normal_short_to_float_v3(no_buf, no_s); no = no_buf; } else { -- cgit v1.2.3 From 6f0f1dc3be9c88b8d54abce290acee1c948c248b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 19 Apr 2015 22:03:42 +1000 Subject: Cleanup: warnings --- extern/libmv/intern/stub.cc | 14 +++++++------- source/blender/blenkernel/intern/camera.c | 3 ++- source/blender/blenkernel/intern/customdata.c | 4 ++-- source/blender/blenkernel/intern/image.c | 8 +++++--- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/extern/libmv/intern/stub.cc b/extern/libmv/intern/stub.cc index f02509de90a..5d667baa880 100644 --- a/extern/libmv/intern/stub.cc +++ b/extern/libmv/intern/stub.cc @@ -179,20 +179,20 @@ void libmv_reconstructionDestroy( /* ************ Feature detector ************ */ -libmv_Features *libmv_detectFeaturesByte(const unsigned char */*image_buffer*/, +libmv_Features *libmv_detectFeaturesByte(const unsigned char * /*image_buffer*/, int /*width*/, int /*height*/, int /*channels*/, - libmv_DetectOptions */*options*/) { + libmv_DetectOptions * /*options*/) { return NULL; } struct libmv_Features *libmv_detectFeaturesFloat( - const float */*image_buffer*/, + const float * /*image_buffer*/, int /*width*/, int /*height*/, int /*channels*/, - libmv_DetectOptions */*options*/) { + libmv_DetectOptions * /*options*/) { return NULL; } @@ -247,7 +247,7 @@ void libmv_cameraIntrinsicsSetThreads( } void libmv_cameraIntrinsicsExtractOptions( - const libmv_CameraIntrinsics */*libmv_intrinsics*/, + const libmv_CameraIntrinsics * /*libmv_intrinsics*/, libmv_CameraIntrinsicsOptions *camera_intrinsics_options) { memset(camera_intrinsics_options, 0, sizeof(libmv_CameraIntrinsicsOptions)); camera_intrinsics_options->focal_length = 1.0; @@ -355,7 +355,7 @@ void libmv_autoTrackSetOptions(libmv_AutoTrack* /*libmv_autotrack*/, int libmv_autoTrackMarker(libmv_AutoTrack* /*libmv_autotrack*/, const libmv_TrackRegionOptions* /*libmv_options*/, - libmv_Marker */*libmv_tracker_marker*/, + libmv_Marker * /*libmv_tracker_marker*/, libmv_TrackRegionResult* /*libmv_result*/) { return 0; @@ -390,7 +390,7 @@ void libmv_FrameAccessorDestroy(libmv_FrameAccessor* /*frame_accessor*/) } int64_t libmv_frameAccessorgetTransformKey( - const libmv_FrameTransform */*transform*/) + const libmv_FrameTransform * /*transform*/) { return 0; } diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index d62628baa9e..87d81a9e921 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -728,7 +728,8 @@ static void camera_stereo3d_model_matrix(Object *camera, const bool is_left, flo if (((pivot == CAM_S3D_PIVOT_LEFT) && is_left) || ((pivot == CAM_S3D_PIVOT_RIGHT) && !is_left)) { - return camera_model_matrix(camera, r_modelmat); + camera_model_matrix(camera, r_modelmat); + return; } else { float size[3]; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 999f411cece..add6bb0fd0b 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -2294,7 +2294,7 @@ void CustomData_interp(const CustomData *source, CustomData *dest, } } - if (count > SOURCE_BUF_SIZE) MEM_freeN(sources); + if (count > SOURCE_BUF_SIZE) MEM_freeN((void *)sources); } void CustomData_swap(struct CustomData *data, int index, const int *corner_indices) @@ -3852,7 +3852,7 @@ void CustomData_data_transfer(const MeshPairRemap *me_remap, const CustomDataTra if (tmp_data_src) { if (UNLIKELY(sources_num > tmp_buff_size)) { tmp_buff_size = (size_t)sources_num; - tmp_data_src = MEM_reallocN(tmp_data_src, sizeof(*tmp_data_src) * tmp_buff_size); + tmp_data_src = MEM_reallocN((void *)tmp_data_src, sizeof(*tmp_data_src) * tmp_buff_size); } for (j = 0; j < sources_num; j++) { diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index bb9fdba94fa..a09c42e9178 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -960,8 +960,10 @@ void BKE_image_memorypack(Image *ima) { ImBuf *ibuf; - if ((ima->flag & IMA_IS_MULTIVIEW)) - return image_memorypack_multiview(ima); + if ((ima->flag & IMA_IS_MULTIVIEW)) { + image_memorypack_multiview(ima); + return; + } ibuf = image_get_cached_ibuf_for_index_frame(ima, IMA_NO_INDEX, 0); @@ -2494,7 +2496,7 @@ static void image_init_imageuser(Image *ima, ImageUser *iuser) void BKE_image_init_imageuser(Image *ima, ImageUser *iuser) { - return image_init_imageuser(ima, iuser); + image_init_imageuser(ima, iuser); } void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) -- cgit v1.2.3 From 62f79856e9a14337e32355db8a6add14badb372f Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Sun, 19 Apr 2015 20:32:14 +0200 Subject: BGE : Standardization of callbacks execution. A new function (RunPythonCallBackList) to call all python functions contained in a python list was developed. This function has: - first argument is the python list of callbacks - second argument is a python list of arguments - third argument is the minimum quantity of arguments - forth argument is the maximum quantity of arguments It improves flexibility and supports *args. Reviewers: moguri, dfelinto, campbellbarton, sybren Reviewed By: campbellbarton, sybren Subscribers: sybren Projects: #game_engine Differential Revision: https://developer.blender.org/D1102 --- source/gameengine/Expressions/CMakeLists.txt | 2 + .../gameengine/Expressions/KX_PythonCallBack.cpp | 116 +++++++++++++++++++++ source/gameengine/Expressions/KX_PythonCallBack.h | 40 +++++++ source/gameengine/Ketsji/KX_GameObject.cpp | 66 ++---------- source/gameengine/Ketsji/KX_Scene.cpp | 27 +---- 5 files changed, 169 insertions(+), 82 deletions(-) create mode 100644 source/gameengine/Expressions/KX_PythonCallBack.cpp create mode 100644 source/gameengine/Expressions/KX_PythonCallBack.h diff --git a/source/gameengine/Expressions/CMakeLists.txt b/source/gameengine/Expressions/CMakeLists.txt index 6907f314503..48c10d75a17 100644 --- a/source/gameengine/Expressions/CMakeLists.txt +++ b/source/gameengine/Expressions/CMakeLists.txt @@ -55,6 +55,7 @@ set(SRC StringValue.cpp Value.cpp VectorValue.cpp + KX_PythonCallBack.cpp BoolValue.h ConstExpr.h @@ -77,6 +78,7 @@ set(SRC Value.h VectorValue.h VoidValue.h + KX_PythonCallBack.h ) blender_add_lib(ge_logic_expressions "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/gameengine/Expressions/KX_PythonCallBack.cpp b/source/gameengine/Expressions/KX_PythonCallBack.cpp new file mode 100644 index 00000000000..637441d3a9d --- /dev/null +++ b/source/gameengine/Expressions/KX_PythonCallBack.cpp @@ -0,0 +1,116 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Porteries Tristan. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file gameengine/Expressions/KX_PythonCallBack.cpp + * \ingroup expressions + */ + +#include "KX_PythonCallBack.h" +#include +#include + +/** Check if a python value is a function and have the correct number of arguments. + * \param value The python value to check. + * \param minargcount The minimum of arguments possible. + * \param maxargcount The maximum of arguments possible. + * \param r_argcount The number of argument of this function, this variable will be + * changed in the function. + */ +static PyObject *CheckPythonFunction(PyObject *value, unsigned int minargcount, unsigned int maxargcount, unsigned int &r_argcount) +{ + if (PyMethod_Check(value)) { + PyCodeObject *code = ((PyCodeObject *)PyFunction_GET_CODE(PyMethod_GET_FUNCTION(value))); + // *args support + r_argcount = (code->co_flags & CO_VARARGS) ? maxargcount : (code->co_argcount - 1); + } + else if (PyFunction_Check(value)) { + PyCodeObject *code = ((PyCodeObject *)PyFunction_GET_CODE(value)); + // *args support + r_argcount = (code->co_flags & CO_VARARGS) ? maxargcount : code->co_argcount; + } + else { // is not a methode or a function + PyErr_Format(PyExc_TypeError, "items must be functions or methodes, not %s", + Py_TYPE(value)->tp_name); + return NULL; + } + + if (r_argcount < minargcount || r_argcount > maxargcount) { + // wrong number of arguments + PyErr_Format(PyExc_TypeError, "methode or function (%s) has invalid number of arguments (%i) must be between %i and %i", + Py_TYPE(value)->tp_name, r_argcount, minargcount, maxargcount); + return NULL; + } + + return value; +} + +/** Create a python tuple to call a python function + * \param argcount The lenght of the tuple. + * \param arglist The fully list of python arguments [size >= argcount]. + */ +static PyObject *CreatePythonTuple(unsigned int argcount, PyObject **arglist) +{ + PyObject *tuple = PyTuple_New(argcount); + + for (unsigned int i = 0; i < argcount; ++i) { + PyObject *item = arglist[i]; + // increment reference and copy it in a new tuple + Py_INCREF(item); + PyTuple_SET_ITEM(tuple, i, item); + } + + return tuple; +} + +void RunPythonCallBackList(PyObject *functionlist, PyObject **arglist, unsigned int minargcount, unsigned int maxargcount) +{ + unsigned int size = PyList_Size(functionlist); + PyObject *argTuples[(maxargcount - minargcount) + 1] = {NULL}; + + for (unsigned int i = 0; i < size; ++i) { + unsigned int funcargcount = 0; + + PyObject *item = PyList_GET_ITEM(functionlist, i); + PyObject *func = CheckPythonFunction(item, minargcount, maxargcount, funcargcount); + if (!func) { // this item fails the check + PyErr_Print(); + PyErr_Clear(); + continue; + } + + // get correct argument tuple. + PyObject *tuple = argTuples[funcargcount - minargcount]; + if (!tuple) + argTuples[funcargcount - minargcount] = tuple = CreatePythonTuple(funcargcount, arglist); + + PyObject *ret = PyObject_Call(func, tuple, NULL); + if (!ret) { // if ret is NULL this seems that the function doesn't work ! + PyErr_Print(); + PyErr_Clear(); + } + else + Py_DECREF(ret); + } + + for (unsigned int i = 0; i <= (maxargcount - minargcount); ++i) + Py_XDECREF(argTuples[i]); +} diff --git a/source/gameengine/Expressions/KX_PythonCallBack.h b/source/gameengine/Expressions/KX_PythonCallBack.h new file mode 100644 index 00000000000..2ff6e305d67 --- /dev/null +++ b/source/gameengine/Expressions/KX_PythonCallBack.h @@ -0,0 +1,40 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Porteries Tristan. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file KX_PythonCallBack.h + * \ingroup expressions + */ + +#ifndef __KX_PYTHON_CALLBACK_H__ +#define __KX_PYTHON_CALLBACK_H__ + +#include "KX_Python.h" + +/** Execute each functions with at least one argument + * \param functionlist The python list which contains callbacks. + * \param arglist The first item in the tuple to execute callbacks (can be NULL for no arguments). + * \param minargcount The minimum of quantity of arguments possible. + * \param maxargcount The maximum of quantity of arguments possible. + */ +void RunPythonCallBackList(PyObject *functionlist, PyObject **arglist, unsigned int minargcount, unsigned int maxargcount); + +#endif // __KX_PYTHON_CALLBACK_H__ diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 1536b31d1ba..e464883016e 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -69,6 +69,7 @@ #include "BL_ActionManager.h" #include "BL_Action.h" +#include "KX_PythonCallBack.h" #include "PyObjectPlus.h" /* python stuff */ #include "BLI_utildefines.h" #include "python_utildefines.h" @@ -1565,67 +1566,14 @@ void KX_GameObject::RegisterCollisionCallbacks() void KX_GameObject::RunCollisionCallbacks(KX_GameObject *collider, const MT_Vector3 &point, const MT_Vector3 &normal) { #ifdef WITH_PYTHON - Py_ssize_t len; - PyObject* collision_callbacks = m_collisionCallbacks; - - if (collision_callbacks && (len=PyList_GET_SIZE(collision_callbacks))) - { - // Argument tuples are created lazily, only when they are needed. - PyObject *args_3 = NULL; - PyObject *args_1 = NULL; // Only for compatibility with pre-2.74 callbacks that take 1 argument. - - PyObject *func; - PyObject *ret; - int co_argcount; - - // Iterate the list and run the callbacks - for (Py_ssize_t pos=0; pos < len; pos++) - { - func = PyList_GET_ITEM(collision_callbacks, pos); - - // Get the number of arguments, supporting functions, methods and generic callables. - if (PyMethod_Check(func)) { - // Take away the 'self' argument for methods. - co_argcount = ((PyCodeObject *)PyFunction_GET_CODE(PyMethod_GET_FUNCTION(func)))->co_argcount - 1; - } else if (PyFunction_Check(func)) { - co_argcount = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_argcount; - } else { - // We'll just assume the callable takes the correct number of arguments. - co_argcount = 3; - } - - // Check whether the function expects the colliding object only, - // or also the point and normal. - if (co_argcount <= 1) { - // One argument, or *args (which gives co_argcount == 0) - if (args_1 == NULL) { - args_1 = PyTuple_New(1); - PyTuple_SET_ITEMS(args_1, collider->GetProxy()); - } - ret = PyObject_Call(func, args_1, NULL); - } else { - // More than one argument, assume we can give point & normal. - if (args_3 == NULL) { - args_3 = PyTuple_New(3); - PyTuple_SET_ITEMS(args_3, - collider->GetProxy(), - PyObjectFrom(point), - PyObjectFrom(normal)); - } - ret = PyObject_Call(func, args_3, NULL); - } + if (!m_collisionCallbacks || PyList_GET_SIZE(m_collisionCallbacks) == 0) + return; - if (ret == NULL) { - PyErr_Print(); - PyErr_Clear(); - } - else { - Py_DECREF(ret); - } - } + PyObject *args[] = {collider->GetProxy(), PyObjectFrom(point), PyObjectFrom(normal)}; + RunPythonCallBackList(m_collisionCallbacks, args, 1, ARRAY_SIZE(args)); - if (args_3) Py_DECREF(args_3); - if (args_1) Py_DECREF(args_1); + for (unsigned int i = 0; i < ARRAY_SIZE(args); ++i) { + Py_DECREF(args[i]); } #endif } diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index db4ed58d65f..a3e1d1562c9 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -43,6 +43,7 @@ #include "KX_FontObject.h" #include "RAS_IPolygonMaterial.h" #include "ListValue.h" +#include "KX_PythonCallBack.h" #include "SCA_LogicManager.h" #include "SCA_TimeEventManager.h" //#include "SCA_AlwaysEventManager.h" @@ -2132,30 +2133,10 @@ void KX_Scene::Render2DFilters(RAS_ICanvas* canvas) void KX_Scene::RunDrawingCallbacks(PyObject *cb_list) { - Py_ssize_t len; - - if (cb_list && (len=PyList_GET_SIZE(cb_list))) - { - PyObject *args = PyTuple_New(0); // save python creating each call - PyObject *func; - PyObject *ret; - - // Iterate the list and run the callbacks - for (Py_ssize_t pos=0; pos < len; pos++) - { - func= PyList_GET_ITEM(cb_list, pos); - ret= PyObject_Call(func, args, NULL); - if (ret==NULL) { - PyErr_Print(); - PyErr_Clear(); - } - else { - Py_DECREF(ret); - } - } + if (!cb_list || PyList_GET_SIZE(cb_list) == 0) + return; - Py_DECREF(args); - } + RunPythonCallBackList(cb_list, NULL, 0, 0); } //---------------------------------------------------------------------------- -- cgit v1.2.3 From 5db143efbbe1fd7c8ecbfc643c5687fdf4e85e2a Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sun, 19 Apr 2015 22:04:23 +0200 Subject: Fix T44449, sm_52 kernel missing in CMake builds. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 68f248ab818..03b7f229eb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -359,7 +359,7 @@ option(WITH_CYCLES_STANDALONE "Build cycles standalone application" OFF) option(WITH_CYCLES_STANDALONE_GUI "Build cycles standalone with GUI" OFF) option(WITH_CYCLES_OSL "Build Cycles with OSL support" ${_init_CYCLES_OSL}) option(WITH_CYCLES_CUDA_BINARIES "Build cycles CUDA binaries" OFF) -set(CYCLES_CUDA_BINARIES_ARCH sm_20 sm_21 sm_30 sm_35 sm_50 CACHE STRING "CUDA architectures to build binaries for") +set(CYCLES_CUDA_BINARIES_ARCH sm_20 sm_21 sm_30 sm_35 sm_50 sm_52 CACHE STRING "CUDA architectures to build binaries for") mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH) unset(PLATFORM_DEFAULT) option(WITH_CYCLES_LOGGING "Build cycles with logging support" ON) -- cgit v1.2.3 From 07a7d77ec1a27d64784412eddfe21a6fbd874e1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Mon, 20 Apr 2015 10:58:25 +0800 Subject: Fix: solved BGE compiler error on Linux/gcc --- source/gameengine/Expressions/KX_PythonCallBack.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/gameengine/Expressions/KX_PythonCallBack.cpp b/source/gameengine/Expressions/KX_PythonCallBack.cpp index 637441d3a9d..946a385f306 100644 --- a/source/gameengine/Expressions/KX_PythonCallBack.cpp +++ b/source/gameengine/Expressions/KX_PythonCallBack.cpp @@ -84,7 +84,9 @@ static PyObject *CreatePythonTuple(unsigned int argcount, PyObject **arglist) void RunPythonCallBackList(PyObject *functionlist, PyObject **arglist, unsigned int minargcount, unsigned int maxargcount) { unsigned int size = PyList_Size(functionlist); - PyObject *argTuples[(maxargcount - minargcount) + 1] = {NULL}; + PyObject *argTuples[(maxargcount - minargcount) + 1]; + + argTuples[0] = NULL; for (unsigned int i = 0; i < size; ++i) { unsigned int funcargcount = 0; -- cgit v1.2.3 From 436004b6b17a99b878f6ac9ba79ed3c00c6d39c0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 20 Apr 2015 12:35:49 +1000 Subject: Sculpt: clay-strips was missing accumulate button Correct & de-duplicate check for accumulate. --- source/blender/editors/sculpt_paint/sculpt.c | 117 +++++++++++++-------------- source/blender/makesdna/DNA_brush_types.h | 30 +++++++ source/blender/makesrna/intern/rna_brush.c | 6 +- 3 files changed, 90 insertions(+), 63 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 0af93e625ac..9c7edb5b567 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -116,6 +116,13 @@ static int system_physical_thread_count(void) } #endif /* __APPLE__ */ +/** \name Tool Capabilities + * + * Avoid duplicate checks, internal logic only, + * share logic with #rna_def_sculpt_capabilities where possible. + * + * \{ */ + /* Check if there are any active modifiers in stack (used for flushing updates at enter/exit sculpt mode) */ static bool sculpt_has_active_modifiers(Scene *scene, Object *ob) { @@ -133,6 +140,43 @@ static bool sculpt_has_active_modifiers(Scene *scene, Object *ob) return 0; } +static bool sculpt_tool_needs_original(const char sculpt_tool) +{ + return ELEM(sculpt_tool, + SCULPT_TOOL_GRAB, + SCULPT_TOOL_ROTATE, + SCULPT_TOOL_THUMB, + SCULPT_TOOL_LAYER); +} + +static bool sculpt_tool_is_proxy_used(const char sculpt_tool) +{ + return ELEM(sculpt_tool, + SCULPT_TOOL_SMOOTH, + SCULPT_TOOL_LAYER); +} + +/** + * Test whether the #StrokeCache.sculpt_normal needs update in #do_brush_action + */ +static int sculpt_brush_needs_normal(const Brush *brush) +{ + return ((SCULPT_TOOL_HAS_NORMAL_WEIGHT(brush->sculpt_tool) && + (brush->normal_weight > 0)) || + + ELEM(brush->sculpt_tool, + SCULPT_TOOL_BLOB, + SCULPT_TOOL_CREASE, + SCULPT_TOOL_DRAW, + SCULPT_TOOL_LAYER, + SCULPT_TOOL_NUDGE, + SCULPT_TOOL_ROTATE, + SCULPT_TOOL_THUMB) || + + (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA)); +} + +/** \} */ typedef enum StrokeFlags { @@ -352,8 +396,8 @@ static void sculpt_project_v3( * Factors: some brushes like grab cannot do dynamic topology. * Others, like smooth, are better without. Same goes for alt- * key smoothing. */ -static int sculpt_stroke_dynamic_topology(const SculptSession *ss, - const Brush *brush) +static bool sculpt_stroke_is_dynamic_topology( + const SculptSession *ss, const Brush *brush) { return ((BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) && @@ -364,19 +408,7 @@ static int sculpt_stroke_dynamic_topology(const SculptSession *ss, !(brush->flag & BRUSH_ANCHORED) && !(brush->flag & BRUSH_DRAG_DOT) && - (!ELEM(brush->sculpt_tool, - /* These brushes, as currently coded, cannot - * support dynamic topology */ - SCULPT_TOOL_GRAB, - SCULPT_TOOL_ROTATE, - SCULPT_TOOL_THUMB, - SCULPT_TOOL_LAYER, - - /* These brushes could handle dynamic topology, - * but user feedback indicates it's better not - * to */ - SCULPT_TOOL_SMOOTH, - SCULPT_TOOL_MASK))); + SCULPT_TOOL_HAS_DYNTOPO(brush->sculpt_tool)); } /*** paint mesh ***/ @@ -745,7 +777,7 @@ static void calc_area_center( { const Brush *brush = BKE_paint_brush(&sd->paint); SculptSession *ss = ob->sculpt; - const bool has_bm_orco = ss->bm && sculpt_stroke_dynamic_topology(ss, brush); + const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush); int n; /* 0=towards view, 1=flipped */ @@ -879,7 +911,7 @@ static void calc_area_normal( { const Brush *brush = BKE_paint_brush(&sd->paint); SculptSession *ss = ob->sculpt; - const bool has_bm_orco = ss->bm && sculpt_stroke_dynamic_topology(ss, brush); + const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush); int n; /* 0=towards view, 1=flipped */ @@ -1026,7 +1058,7 @@ static void calc_area_normal_and_center( { const Brush *brush = BKE_paint_brush(&sd->paint); SculptSession *ss = ob->sculpt; - const bool has_bm_orco = ss->bm && sculpt_stroke_dynamic_topology(ss, brush); + const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush); int n; /* 0=towards view, 1=flipped */ @@ -1523,27 +1555,6 @@ static void update_brush_local_mat(Sculpt *sd, Object *ob) } } -/* Test whether the StrokeCache.sculpt_normal needs update in - * do_brush_action() */ -static int brush_needs_sculpt_normal(const Brush *brush) -{ - return ((ELEM(brush->sculpt_tool, - SCULPT_TOOL_GRAB, - SCULPT_TOOL_SNAKE_HOOK) && - (brush->normal_weight > 0)) || - - ELEM(brush->sculpt_tool, - SCULPT_TOOL_BLOB, - SCULPT_TOOL_CREASE, - SCULPT_TOOL_DRAW, - SCULPT_TOOL_LAYER, - SCULPT_TOOL_NUDGE, - SCULPT_TOOL_ROTATE, - SCULPT_TOOL_THUMB) || - - (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA)); -} - /* For the smooth brush, uses the neighboring vertices around vert to calculate * a smoothed location for vert. Skips corner vertices (used by only one * polygon.) */ @@ -3100,11 +3111,7 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush, Unified radius = ss->cache->radius * 1.25f; data.radius_squared = radius * radius; - data.original = ELEM(brush->sculpt_tool, - SCULPT_TOOL_GRAB, - SCULPT_TOOL_ROTATE, - SCULPT_TOOL_THUMB, - SCULPT_TOOL_LAYER) ? true : ss->cache->original; + data.original = sculpt_tool_needs_original(brush->sculpt_tool) ? true : ss->cache->original; BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode); @@ -3159,11 +3166,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe data.ss = ss; data.sd = sd; data.radius_squared = ss->cache->radius_squared; - data.original = ELEM(brush->sculpt_tool, - SCULPT_TOOL_GRAB, - SCULPT_TOOL_ROTATE, - SCULPT_TOOL_THUMB, - SCULPT_TOOL_LAYER) ? true : ss->cache->original; + data.original = sculpt_tool_needs_original(brush->sculpt_tool) ? true : ss->cache->original; BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode); /* Only act if some verts are inside the brush area */ @@ -3178,7 +3181,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe BKE_pbvh_node_mark_update(nodes[n]); } - if (brush_needs_sculpt_normal(brush)) + if (sculpt_brush_needs_normal(brush)) update_sculpt_normal(sd, ob, nodes, totnode); if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA) @@ -3298,8 +3301,8 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob) BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode); /* first line is tools that don't support proxies */ - if (!ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_LAYER) || - ss->cache->supports_gravity) + if (ss->cache->supports_gravity || + (sculpt_tool_is_proxy_used(brush->sculpt_tool) == false)) { /* these brushes start from original coordinates */ const bool use_orco = ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB, @@ -3377,7 +3380,7 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob) SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); - if (ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_LAYER)) { + if (sculpt_tool_is_proxy_used(brush->sculpt_tool)) { /* this brushes aren't using proxies, so sculpt_combine_proxies() wouldn't * propagate needed deformation to original base */ @@ -3900,11 +3903,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio cache->original = 1; } - if (ELEM(brush->sculpt_tool, - SCULPT_TOOL_DRAW, SCULPT_TOOL_CREASE, SCULPT_TOOL_BLOB, - SCULPT_TOOL_LAYER, SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY, - SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_ROTATE, SCULPT_TOOL_FLATTEN)) - { + if (SCULPT_TOOL_HAS_ACCUMULATE(brush->sculpt_tool)) { if (!(brush->flag & BRUSH_ACCUMULATE)) { cache->original = 1; } @@ -4404,7 +4403,7 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *UNUSED(st (float)(sd->detail_size * U.pixelsize) / 0.4f); } - if (sculpt_stroke_dynamic_topology(ss, brush)) { + if (sculpt_stroke_is_dynamic_topology(ss, brush)) { do_symmetrical_brush_actions(sd, ob, sculpt_topology_update, ups); } diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index a711f2ae100..f83caea66a2 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -255,6 +255,36 @@ typedef enum BrushSculptTool { SCULPT_TOOL_MASK = 19 } BrushSculptTool; +/** When #BRUSH_ACCUMULATE is used */ +#define SCULPT_TOOL_HAS_ACCUMULATE(t) ELEM(t, \ + SCULPT_TOOL_DRAW, \ + SCULPT_TOOL_CREASE, \ + SCULPT_TOOL_BLOB, \ + SCULPT_TOOL_LAYER, \ + SCULPT_TOOL_INFLATE, \ + SCULPT_TOOL_CLAY, \ + SCULPT_TOOL_CLAY_STRIPS, \ + SCULPT_TOOL_ROTATE, \ + SCULPT_TOOL_FLATTEN \ + ) + +#define SCULPT_TOOL_HAS_NORMAL_WEIGHT(t) ELEM(t, \ + SCULPT_TOOL_GRAB, \ + SCULPT_TOOL_SNAKE_HOOK \ + ) + +#define SCULPT_TOOL_HAS_DYNTOPO(t) (ELEM(t, \ + /* These brushes, as currently coded, cannot support dynamic topology */ \ + SCULPT_TOOL_GRAB, \ + SCULPT_TOOL_ROTATE, \ + SCULPT_TOOL_THUMB, \ + SCULPT_TOOL_LAYER, \ + \ + /* These brushes could handle dynamic topology, but user feedback indicates it's better not to */ \ + SCULPT_TOOL_SMOOTH, \ + SCULPT_TOOL_MASK \ + ) == 0) + /* ImagePaintSettings.tool */ typedef enum BrushImagePaintTool { PAINT_TOOL_DRAW = 0, diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 81ba3a9066f..362cf77a332 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -125,9 +125,7 @@ EnumPropertyItem brush_image_tool_items[] = { static int rna_SculptToolCapabilities_has_accumulate_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; - return ELEM(br->sculpt_tool, - SCULPT_TOOL_BLOB, SCULPT_TOOL_CLAY, SCULPT_TOOL_CREASE, - SCULPT_TOOL_DRAW, SCULPT_TOOL_INFLATE, SCULPT_TOOL_LAYER); + return SCULPT_TOOL_HAS_ACCUMULATE(br->sculpt_tool); } static int rna_SculptToolCapabilities_has_auto_smooth_get(PointerRNA *ptr) @@ -155,7 +153,7 @@ static int rna_SculptToolCapabilities_has_jitter_get(PointerRNA *ptr) static int rna_SculptToolCapabilities_has_normal_weight_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; - return ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK); + return SCULPT_TOOL_HAS_NORMAL_WEIGHT(br->sculpt_tool); } static int rna_BrushCapabilities_has_overlay_get(PointerRNA *ptr) -- cgit v1.2.3 From 79319b3fba306524eef71946098deda71a449134 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 20 Apr 2015 13:36:51 +1000 Subject: Sculpt: remove workaround T25371 It's no longer needed, and made calc_area_normal different to the normal from calc_area_normal_and_center. --- source/blender/editors/sculpt_paint/sculpt.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 9c7edb5b567..40ef8970d68 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -919,22 +919,6 @@ static void calc_area_normal( int count[2] = {0}; - /* Grab brush requires to test on original data (see T25371) */ - bool original; - - original = (brush->sculpt_tool == SCULPT_TOOL_GRAB) ? true : ss->cache->original; - /* In general the original coords are not available with dynamic - * topology - * - * Mask tool could not use undo nodes to get coordinates from - * since the coordinates are not stored in those nodes. - * And mask tool is not gonna to modify vertex coordinates, - * so we don't actually need to use modified coords. - */ - if (brush->sculpt_tool == SCULPT_TOOL_MASK) { - original = false; - } - #pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) for (n = 0; n < totnode; n++) { PBVHVertexIter vd; @@ -947,7 +931,7 @@ static void calc_area_normal( unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); sculpt_brush_test_init(ss, &test); - use_original = (original && (unode->co || unode->bm_entry)); + use_original = (ss->cache->original && (unode->co || unode->bm_entry)); /* when the mesh is edited we can't rely on original coords * (original mesh may not even have verts in brush radius) */ -- cgit v1.2.3 From 5f6b958e969d3300502933ea6276abf46e75c675 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 20 Apr 2015 01:02:49 +1200 Subject: Fix: "show_points" setting for Grease Pencil drawing didn't work As reported by zeffi, the "show_points" option was not working in master. It probably broke recently, after some changes meant that the point sizes weren't geting set prior to drawing these points anymore. Since this was originally added as a debugging tool (though it is now somewhat redundant due to the stroke editing functionality, which uses/exposes the same points), this option wasn't really that important. I have decided to add back a toggle for this to the UI though, since it can be used for some interesting effects... --- release/scripts/startup/bl_ui/properties_grease_pencil_common.py | 4 +--- source/blender/editors/gpencil/drawgpencil.c | 6 +++++- source/blender/makesrna/intern/rna_gpencil.c | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index 50886231347..e86fc79e343 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -414,9 +414,7 @@ class GreasePencilDataPanel: col = split.column(align=True) col.prop(gpl, "show_x_ray") - - # if debug: - # layout.prop(gpl, "show_points") + col.prop(gpl, "show_points", text="Points") layout.separator() diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 08926926861..0d35d3ce716 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -443,6 +443,8 @@ static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness /* draw debug points of curve on top? */ /* XXX: for now, we represent "selected" strokes in the same way as debug, which isn't used anymore */ if (debug) { + glPointSize((float)(thickness + 2)); + glBegin(GL_POINTS); for (i = 0, pt = points; i < totpoints && pt; i++, pt++) glVertex3fv(&pt->x); @@ -617,6 +619,8 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness bGPDspoint *pt; int i; + glPointSize((float)(thickness_s + 2)); + glBegin(GL_POINTS); for (i = 0, pt = points; i < totpoints && pt; i++, pt++) { float co[2]; @@ -876,7 +880,7 @@ static void gp_draw_strokes_edit(bGPDframe *gpf, int offsx, int offsy, int winx, /* draw onion-skinning for a layer */ static void gp_draw_onionskins(bGPDlayer *gpl, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, - int UNUSED(cfra), int dflag, short debug, short lthick) + int UNUSED(cfra), int dflag, bool debug, short lthick) { const float alpha = gpl->color[3]; float color[4]; diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 2f4e7881843..7d7df0f91a7 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -775,8 +775,8 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) prop = RNA_def_property(srna, "show_points", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_DRAWDEBUG); RNA_def_property_ui_text(prop, "Show Points", "Draw the points which make up the strokes (for debugging purposes)"); - RNA_def_property_update_runtime(prop, "rna_GPencil_update"); - + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); + /* X-Ray */ prop = RNA_def_property(srna, "show_x_ray", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_LAYER_NO_XRAY); -- cgit v1.2.3 From e4fbc8fc8ddf5c212146fa90c38437389ef25db5 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 20 Apr 2015 12:28:50 +1200 Subject: Fix: Changing actions in the Action Editor using the Browse dropdown should happen in tweakmode When a NLA strip is being tweaked, it should not be possible to use the Action Editor to change the action that it uses. Instead of changing the action in tweakmode, it now exits tweakmode first before doing so. --- source/blender/makesrna/intern/rna_space.c | 34 +++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 8e3c4e5e877..300752d8cf5 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -237,6 +237,7 @@ static EnumPropertyItem buttons_texture_context_items[] = { #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_depsgraph.h" +#include "BKE_nla.h" #include "BKE_paint.h" #include "BKE_scene.h" #include "BKE_screen.h" @@ -1223,17 +1224,34 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *UNUSED(bmain), Scene *s } /* set action */ + // FIXME: this overlaps a lot with the BKE_animdata_set_action() API method if (adt) { - /* fix id-count of action we're replacing */ - if (adt->action) { - id_us_min(&adt->action->id); + /* Don't do anything if old and new actions are the same... */ + if (adt->action != saction->action) { + /* NLA Tweak Mode needs special handling... */ + if (adt->flag & ADT_NLA_EDIT_ON) { + /* Exit editmode first - we cannot change actions while in tweakmode + * NOTE: This will clear the action ref properly + */ + BKE_nla_tweakmode_exit(adt); + + /* Assign new action, and adjust the usercounts accordingly */ + adt->action = saction->action; + id_us_plus(&adt->action->id); + } + else { + /* fix id-count of action we're replacing */ + if (adt->action) { + id_us_min(&adt->action->id); + } + + /* Assign new action, and adjust the usercounts accordingly */ + adt->action = saction->action; + id_us_plus(&adt->action->id); + } } - /* assign new action, and adjust the usercounts accordingly */ - adt->action = saction->action; - id_us_plus(&adt->action->id); - - /* force update of animdata */ + /* Force update of animdata */ adt->recalc |= ADT_RECALC_ANIM; } -- cgit v1.2.3 From 689241b6e5d962c14a6650082fc0ecf4a3a0aa5e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 20 Apr 2015 12:30:29 +1200 Subject: Fix for potential null-pointer-dereference if the new action is NULL --- source/blender/makesrna/intern/rna_space.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 300752d8cf5..0c94575de4c 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -1237,7 +1237,7 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *UNUSED(bmain), Scene *s /* Assign new action, and adjust the usercounts accordingly */ adt->action = saction->action; - id_us_plus(&adt->action->id); + id_us_plus((ID *)adt->action); } else { /* fix id-count of action we're replacing */ @@ -1247,7 +1247,7 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *UNUSED(bmain), Scene *s /* Assign new action, and adjust the usercounts accordingly */ adt->action = saction->action; - id_us_plus(&adt->action->id); + id_us_plus((ID *)adt->action); } } -- cgit v1.2.3 From a0e1b6573ad742cb77c47780b78d6a26fa206c73 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 20 Apr 2015 17:21:05 +1200 Subject: Action Editor "Browse" Fix: Stash active action if nothing else uses it Following the initial action management commits for 2.74, blurrymind pointed out a problematic workflow involving the "Browse Action" dropdown in the Action Editor which would lead to actions being accidentally lost. Namely, it turns out that game animators frequently flip between different actions from the Browse menu while working. While the new up/down operators and/or other NLA based tools are better suited to this without the problems of actions getting lost, some additional precautions were needed for the Browse menu as well. So now, if the active action will have no users as a result of the switch (i.e. it was a new action, and the user is checking on a previous action via the Browse menu), this action will now get stashed. This workflow is not perfect though, as there is the problem of the stashed action strips not reflecting the actions they reference. --- source/blender/makesrna/intern/rna_space.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 0c94575de4c..e174d1ce5d0 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -1240,9 +1240,26 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *UNUSED(bmain), Scene *s id_us_plus((ID *)adt->action); } else { - /* fix id-count of action we're replacing */ + /* Handle old action... */ if (adt->action) { + /* Fix id-count of action we're replacing */ id_us_min(&adt->action->id); + + /* To prevent data loss (i.e. if users flip between actions using the Browse menu), + * stash this action if nothing else uses it. + * + * EXCEPTION: + * This callback runs when unlinking actions. In that case, we don't want to + * stash the action, as the user is signalling that they want to detach it. + * This can be reviewed again later, but it could get annoying if we keep these instead. + */ + if ((adt->action->id.us <= 0) && (saction->action != NULL)) { + /* XXX: Things here get dodgy if this action is only partially completed, + * and the user then uses the browse menu to get back to this action, + * assigning it as the active action (i.e. the stash strip gets out of sync) + */ + BKE_nla_action_stash(adt); + } } /* Assign new action, and adjust the usercounts accordingly */ -- cgit v1.2.3 From dbb2b29beab46a81c1ea95521a2afe39145717c5 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 20 Apr 2015 17:25:00 +1200 Subject: Action Stashing: Newly stashed strips now get "sync length" option enabled by default --- source/blender/blenkernel/intern/nla.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 650efea2e96..1ad6446eb05 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1649,6 +1649,12 @@ bool BKE_nla_action_stash(AnimData *adt) nlt->flag = (NLATRACK_MUTED | NLATRACK_PROTECTED); strip->flag &= ~(NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE); + /* also mark the strip for auto syncing the length, so that the strips accurately + * reflect the length of the action + * XXX: we could do with some extra flags here to prevent repeats/scaling options from working! + */ + strip->flag |= NLASTRIP_FLAG_SYNC_LENGTH; + /* succeeded */ return true; } -- cgit v1.2.3 From bf6bde232d42c3e1a41a3841292150fae3d214cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Mon, 20 Apr 2015 13:53:06 +0800 Subject: Fix: BGE crashes when RunPythonCallBackList() is called with maxargcount != minargcount --- source/gameengine/Expressions/KX_PythonCallBack.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source/gameengine/Expressions/KX_PythonCallBack.cpp b/source/gameengine/Expressions/KX_PythonCallBack.cpp index 946a385f306..1d97a8c7384 100644 --- a/source/gameengine/Expressions/KX_PythonCallBack.cpp +++ b/source/gameengine/Expressions/KX_PythonCallBack.cpp @@ -84,9 +84,8 @@ static PyObject *CreatePythonTuple(unsigned int argcount, PyObject **arglist) void RunPythonCallBackList(PyObject *functionlist, PyObject **arglist, unsigned int minargcount, unsigned int maxargcount) { unsigned int size = PyList_Size(functionlist); - PyObject *argTuples[(maxargcount - minargcount) + 1]; - - argTuples[0] = NULL; + PyObject *argTuples[maxargcount - minargcount + 1]; + memset(argTuples, 0, sizeof(PyObject *) * (maxargcount - minargcount + 1)); for (unsigned int i = 0; i < size; ++i) { unsigned int funcargcount = 0; -- cgit v1.2.3 From 0aa2eed0c2e039b3ec69f15e306af212d51f2f5d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 20 Apr 2015 14:07:26 +0500 Subject: Compilation error fix for MSVC: It does not support expressions in array declarations --- source/gameengine/Expressions/KX_PythonCallBack.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/gameengine/Expressions/KX_PythonCallBack.cpp b/source/gameengine/Expressions/KX_PythonCallBack.cpp index 1d97a8c7384..fbc250a1b3d 100644 --- a/source/gameengine/Expressions/KX_PythonCallBack.cpp +++ b/source/gameengine/Expressions/KX_PythonCallBack.cpp @@ -28,6 +28,8 @@ #include #include +#include "BLI_alloca.h" + /** Check if a python value is a function and have the correct number of arguments. * \param value The python value to check. * \param minargcount The minimum of arguments possible. @@ -84,7 +86,7 @@ static PyObject *CreatePythonTuple(unsigned int argcount, PyObject **arglist) void RunPythonCallBackList(PyObject *functionlist, PyObject **arglist, unsigned int minargcount, unsigned int maxargcount) { unsigned int size = PyList_Size(functionlist); - PyObject *argTuples[maxargcount - minargcount + 1]; + PyObject **argTuples = (PyObject **)BLI_array_alloca(argTuples, maxargcount - minargcount + 1); memset(argTuples, 0, sizeof(PyObject *) * (maxargcount - minargcount + 1)); for (unsigned int i = 0; i < size; ++i) { -- cgit v1.2.3 From 9b4c8a25076fcba566997137140fd23166d52654 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 20 Apr 2015 11:51:43 +0200 Subject: Fix T44458 strip modifier mask not copied correctly when doing scene copy. What happens is that the strip is copied, but it still refers to the old scene. Here we need to fix this by referring to the copy of the strip and also do it after copying to make it order independent. --- source/blender/blenkernel/intern/sequencer.c | 34 ++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 339432c2b77..535dcd6ba4d 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -5227,10 +5227,6 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup MEM_dupallocN(seq->strip->stripdata); } else if (seq->type >= SEQ_TYPE_EFFECT) { - if (seq->seq1 && seq->seq1->tmp) seqn->seq1 = seq->seq1->tmp; - if (seq->seq2 && seq->seq2->tmp) seqn->seq2 = seq->seq2->tmp; - if (seq->seq3 && seq->seq3->tmp) seqn->seq3 = seq->seq3->tmp; - if (seq->type & SEQ_TYPE_EFFECT) { struct SeqEffectHandle sh; sh = BKE_sequence_get_effect(seq); @@ -5255,6 +5251,28 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup return seqn; } +static void seq_new_fix_links_recursive(Sequence *seq) +{ + SequenceModifierData *smd; + + if (seq->type >= SEQ_TYPE_EFFECT) { + if (seq->seq1 && seq->seq1->tmp) seq->seq1 = seq->seq1->tmp; + if (seq->seq2 && seq->seq2->tmp) seq->seq2 = seq->seq2->tmp; + if (seq->seq3 && seq->seq3->tmp) seq->seq3 = seq->seq3->tmp; + } + else if (seq->type == SEQ_TYPE_META) { + Sequence *seqn; + for (seqn = seq->seqbase.first; seqn; seqn = seqn->next) { + seq_new_fix_links_recursive(seqn); + } + } + + for (smd = seq->modifiers.first; smd; smd = smd->next) { + if (smd->mask_sequence && smd->mask_sequence->tmp) + smd->mask_sequence = smd->mask_sequence->tmp; + } +} + Sequence *BKE_sequence_dupli_recursive(Scene *scene, Scene *scene_to, Sequence *seq, int dupe_flag) { Sequence *seqn = seq_dupli(scene, scene_to, seq, dupe_flag); @@ -5267,6 +5285,9 @@ Sequence *BKE_sequence_dupli_recursive(Scene *scene, Scene *scene_to, Sequence * } } } + + seq_new_fix_links_recursive(seqn); + return seqn; } @@ -5305,6 +5326,11 @@ void BKE_sequence_base_dupli_recursive( } } } + + /* fix modifier linking */ + for (seq = nseqbase->first; seq; seq = seq->next) { + seq_new_fix_links_recursive(seq); + } } /* called on draw, needs to be fast, -- cgit v1.2.3 From 437f69ab4593785743c99c1e116f7f9380642f3d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 20 Apr 2015 20:20:08 +1000 Subject: Allow Python overrides for materials. --- source/blender/blenkernel/intern/material.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index b5b7f3d06aa..c7e6b3ba1b3 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -806,9 +806,13 @@ void assign_material_id(ID *id, Material *ma, short act) if (act > MAXMAT) return; if (act < 1) act = 1; + /* this is needed for Python overrides, + * we just have to take care that the UI can't do this */ +#if 0 /* prevent crashing when using accidentally */ BLI_assert(id->lib == NULL); if (id->lib) return; +#endif /* test arraylens */ -- cgit v1.2.3 From fa761dfe6d5cd1467f8fea5dcf808ffe9a8ddcb7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 20 Apr 2015 21:10:52 +1000 Subject: Fix T44419: extruding when using lasso deselect --- source/blender/editors/mesh/mesh_ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 126d1cb0ad9..2855af063c0 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -409,7 +409,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) /* use KM_CLICK because same key is used for tweaks */ kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "rotate_source", true); - kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_PRESS, KM_SHIFT | KM_CTRL, 0); + kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_SHIFT | KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "rotate_source", false); WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_delete", XKEY, KM_PRESS, 0, 0); -- cgit v1.2.3 From 6bc26540c2a46d9324c14aee06a17aac6efc3077 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 20 Apr 2015 21:20:39 +1000 Subject: Fix T44452: Inconsistent gpencil color in prefs --- source/blender/makesrna/intern/rna_userdef.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index ef52fe2a084..b5ce031dd80 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3648,7 +3648,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Grease Pencil Eraser Radius", "Radius of eraser 'brush'"); - prop = RNA_def_property(srna, "grease_pencil_default_color", PROP_FLOAT, PROP_COLOR); + prop = RNA_def_property(srna, "grease_pencil_default_color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "gpencil_new_layer_col"); RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Grease Pencil Default Color", "Color of new Grease Pencil layers"); -- cgit v1.2.3 From b07c630676978498895f9e6d6c8cc00ad8215812 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 20 Apr 2015 14:27:20 +0200 Subject: I18n: Add Vietnamese language. --- release/scripts/modules/bl_i18n_utils/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py index c1d9b926924..30ee3cdc7d8 100644 --- a/release/scripts/modules/bl_i18n_utils/settings.py +++ b/release/scripts/modules/bl_i18n_utils/settings.py @@ -88,6 +88,7 @@ LANGUAGES = ( (38, "Uzbek (Oʻzbek)", "uz_UZ"), (39, "Uzbek Cyrillic (Ўзбек)", "uz_UZ@cyrillic"), (40, "Hindi (मानक हिन्दी)", "hi_IN"), + (41, "Vietnamese (tiếng Việt)", "vi_VN"), ) # Default context, in py! -- cgit v1.2.3 From cd44449578faa87c22776a0e8ecb792e18ed9a1b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 2 Apr 2015 20:37:57 +0500 Subject: Cycles: Synchronize images after building mesh BVH This way memory overhead caused by the BVH building is not so visible and peak memory usage will be reduced. Implementing this idea is not so straightforward actually, because we need to synchronize images used for true displacement before meshes. Detecting whether image is used for true displacement is not so striaghtforward, so for now all all displacement types will synchronize images used for them. Such change brings memory usage from 4.1G to 4.0G with the 01_01_01_D scene from gooseberry. With 01_01_01_G scene it's 7.6G vs. 6.8G (before and after the patch). Reviewers: campbellbarton, juicyfruit, brecht Subscribers: eyecandy Differential Revision: https://developer.blender.org/D1217 --- intern/cycles/render/graph.h | 1 + intern/cycles/render/image.cpp | 27 +++++++++++++++++ intern/cycles/render/image.h | 1 + intern/cycles/render/mesh.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++ intern/cycles/render/mesh.h | 1 + intern/cycles/render/nodes.cpp | 4 +-- intern/cycles/render/nodes.h | 21 +++++++++++--- intern/cycles/render/scene.cpp | 10 +++---- 8 files changed, 120 insertions(+), 11 deletions(-) diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index b39b3dae324..301938aa158 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -81,6 +81,7 @@ enum ShaderNodeSpecialType { SHADER_SPECIAL_TYPE_GEOMETRY, SHADER_SPECIAL_TYPE_SCRIPT, SHADER_SPECIAL_TYPE_BACKGROUND, + SHADER_SPECIAL_TYPE_IMAGE_SLOT, }; /* Enum diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 6e63b433709..f0608965d09 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -791,6 +791,33 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress& need_update = false; } +void ImageManager::device_update_slot(Device *device, + DeviceScene *dscene, + int slot, + Progress *progress) +{ + Image *image; + if(slot >= tex_image_byte_start) { + int byte_slot = slot - tex_image_byte_start; + assert(images[byte_slot] != NULL); + image = images[byte_slot]; + } + else { + assert(float_images[slot] != NULL); + image = float_images[slot]; + } + if(image->users == 0) { + device_free_image(device, dscene, slot); + } + else if(image->need_load) { + if(!osl_texture_system || float_images[slot]->builtin_data) + device_load_image(device, + dscene, + slot, + progress); + } +} + void ImageManager::device_pack_images(Device *device, DeviceScene *dscene, Progress& /*progess*/) diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 1045b4532e4..70cc4935daa 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -63,6 +63,7 @@ public: bool is_float_image(const string& filename, void *builtin_data, bool& is_linear); void device_update(Device *device, DeviceScene *dscene, Progress& progress); + void device_update_slot(Device *device, DeviceScene *dscene, int slot, Progress *progress); void device_free(Device *device, DeviceScene *dscene); void device_free_builtin(Device *device, DeviceScene *dscene); diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 74ea3c94593..b6f3cb3502b 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -20,9 +20,11 @@ #include "camera.h" #include "curves.h" #include "device.h" +#include "graph.h" #include "shader.h" #include "light.h" #include "mesh.h" +#include "nodes.h" #include "object.h" #include "scene.h" @@ -1148,6 +1150,55 @@ void MeshManager::device_update_flags(Device * /*device*/, need_flags_update = false; } +void MeshManager::device_update_displacement_images(Device *device, + DeviceScene *dscene, + Scene *scene, + Progress& progress) +{ + progress.set_status("Updating Displacement Images"); + TaskPool pool; + ImageManager *image_manager = scene->image_manager; + set bump_images; + foreach(Mesh *mesh, scene->meshes) { + if(mesh->need_update) { + foreach(uint shader_index, mesh->used_shaders) { + Shader *shader = scene->shaders[shader_index]; + if(shader->graph_bump == NULL) { + continue; + } + foreach(ShaderNode* node, shader->graph_bump->nodes) { + if(node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) { + continue; + } + if(device->info.pack_images) { + /* If device requires packed images we need to update all + * images now, even if they're not used for displacement. + */ + image_manager->device_update(device, + dscene, + progress); + return; + } + ImageSlotNode *image_node = static_cast(node); + int slot = image_node->slot; + if(slot != -1) { + bump_images.insert(slot); + } + } + } + } + } + foreach(int slot, bump_images) { + pool.push(function_bind(&ImageManager::device_update_slot, + image_manager, + device, + dscene, + slot, + &progress)); + } + pool.wait_work(); +} + void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { VLOG(1) << "Total " << scene->meshes.size() << " meshes."; @@ -1170,6 +1221,21 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen } } + /* Update images needed for true displacement. */ + bool need_displacement_images = false; + foreach(Mesh *mesh, scene->meshes) { + if(mesh->need_update && + mesh->displacement_method != Mesh::DISPLACE_BUMP) + { + need_displacement_images = true; + break; + } + } + if(need_displacement_images) { + VLOG(1) << "Updating images used for true displacement."; + device_update_displacement_images(device, dscene, scene, progress); + } + /* device update */ device_free(device, dscene); diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index 6eaafea8729..76c186a3feb 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -167,6 +167,7 @@ public: void device_update_attributes(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_update_flags(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); + void device_update_displacement_images(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_free(Device *device, DeviceScene *dscene); void tag_update(Scene *scene); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 40bb82c6330..747bafcc904 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -186,7 +186,7 @@ ShaderEnum ImageTextureNode::color_space_enum = color_space_init(); ShaderEnum ImageTextureNode::projection_enum = image_projection_init(); ImageTextureNode::ImageTextureNode() -: TextureNode("image_texture") +: ImageSlotTextureNode("image_texture") { image_manager = NULL; slot = -1; @@ -380,7 +380,7 @@ ShaderEnum EnvironmentTextureNode::color_space_enum = color_space_init(); ShaderEnum EnvironmentTextureNode::projection_enum = env_projection_init(); EnvironmentTextureNode::EnvironmentTextureNode() -: TextureNode("environment_texture") +: ImageSlotTextureNode("environment_texture") { image_manager = NULL; slot = -1; diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 0ec0fce512f..ee984773dcf 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -55,13 +55,28 @@ public: /* Nodes */ +/* Any node which uses image manager's slot should be a subclass of this one. */ +class ImageSlotNode : public ShaderNode { +public: + ImageSlotNode(const char *name_) : ShaderNode(name_) { + special_type = SHADER_SPECIAL_TYPE_IMAGE_SLOT; + } + int slot; +}; + class TextureNode : public ShaderNode { public: TextureNode(const char *name_) : ShaderNode(name_) {} TextureMapping tex_mapping; }; -class ImageTextureNode : public TextureNode { +class ImageSlotTextureNode : public ImageSlotNode { +public: + ImageSlotTextureNode(const char *name_) : ImageSlotNode(name_) {} + TextureMapping tex_mapping; +}; + +class ImageTextureNode : public ImageSlotTextureNode { public: SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode) ~ImageTextureNode(); @@ -69,7 +84,6 @@ public: void attributes(Shader *shader, AttributeRequestSet *attributes); ImageManager *image_manager; - int slot; int is_float; bool is_linear; bool use_alpha; @@ -85,7 +99,7 @@ public: static ShaderEnum projection_enum; }; -class EnvironmentTextureNode : public TextureNode { +class EnvironmentTextureNode : public ImageSlotTextureNode { public: SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode) ~EnvironmentTextureNode(); @@ -93,7 +107,6 @@ public: void attributes(Shader *shader, AttributeRequestSet *attributes); ImageManager *image_manager; - int slot; int is_float; bool is_linear; bool use_alpha; diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 524574f096d..71741c0dfd1 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -160,11 +160,6 @@ void Scene::device_update(Device *device_, Progress& progress) if(progress.get_cancel() || device->have_error()) return; - progress.set_status("Updating Images"); - image_manager->device_update(device, &dscene, progress); - - if(progress.get_cancel() || device->have_error()) return; - progress.set_status("Updating Background"); background->device_update(device, &dscene, this); @@ -195,6 +190,11 @@ void Scene::device_update(Device *device_, Progress& progress) if(progress.get_cancel() || device->have_error()) return; + progress.set_status("Updating Images"); + image_manager->device_update(device, &dscene, progress); + + if(progress.get_cancel() || device->have_error()) return; + progress.set_status("Updating Camera Volume"); camera->device_update_volume(device, &dscene, this); -- cgit v1.2.3 From 828abaf11c3cd5177ae37e5943492a9ec23ce399 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 13 Apr 2015 23:05:09 +0500 Subject: Cycles: Split BVH nodes storage into inner and leaf nodes This way we can get rid of inefficient memory usage caused by BVH boundbox part being unused by leaf nodes but still being allocated for them. Doing such split allows to save 6 of float4 values for QBVH per leaf node and 3 of float4 values for regular BVH per leaf node. This translates into following memory save using 01.01.01.G rendered without hair: Device memory size Device memory peak Global memory peak Before the patch: 4957 5051 7668 With the patch: 4467 4562 7332 The measurements are done against current master. Still need to run speed tests and it's hard to predict if it's faster or not: on the one hand leaf nodes are now much more coherent in cache, on the other hand they're not so much coherent with regular nodes anymore. Reviewers: brecht, juicyfruit Subscribers: venomgfx, eyecandy Differential Revision: https://developer.blender.org/D1236 --- intern/cycles/bvh/bvh.cpp | 208 ++++++++++++++--------- intern/cycles/bvh/bvh.h | 11 +- intern/cycles/kernel/geom/geom.h | 2 + intern/cycles/kernel/geom/geom_bvh_shadow.h | 2 +- intern/cycles/kernel/geom/geom_bvh_subsurface.h | 2 +- intern/cycles/kernel/geom/geom_bvh_traversal.h | 2 +- intern/cycles/kernel/geom/geom_bvh_volume.h | 2 +- intern/cycles/kernel/geom/geom_qbvh_shadow.h | 2 +- intern/cycles/kernel/geom/geom_qbvh_subsurface.h | 2 +- intern/cycles/kernel/geom/geom_qbvh_traversal.h | 2 +- intern/cycles/kernel/geom/geom_qbvh_volume.h | 2 +- intern/cycles/kernel/kernel_textures.h | 1 + intern/cycles/kernel/svm/svm_image.h | 2 +- intern/cycles/render/mesh.cpp | 5 + intern/cycles/render/scene.h | 1 + 15 files changed, 151 insertions(+), 95 deletions(-) diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index f2777c4a15b..d1c3feed963 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -28,6 +28,7 @@ #include "util_cache.h" #include "util_debug.h" #include "util_foreach.h" +#include "util_logging.h" #include "util_map.h" #include "util_progress.h" #include "util_system.h" @@ -111,8 +112,7 @@ bool BVH::cache_read(CacheData& key) value.read(pack.prim_type) && value.read(pack.prim_visibility) && value.read(pack.prim_index) && - value.read(pack.prim_object) && - value.read(pack.is_leaf))) + value.read(pack.prim_object))) { /* Clear the pack if load failed. */ pack.root_index = 0; @@ -124,7 +124,6 @@ bool BVH::cache_read(CacheData& key) pack.prim_visibility.clear(); pack.prim_index.clear(); pack.prim_object.clear(); - pack.is_leaf.clear(); return false; } return true; @@ -147,7 +146,6 @@ void BVH::cache_write(CacheData& key) value.add(pack.prim_visibility); value.add(pack.prim_index); value.add(pack.prim_object); - value.add(pack.is_leaf); Cache::global.insert(key, value); @@ -322,13 +320,14 @@ void BVH::pack_primitives() /* Pack Instances */ -void BVH::pack_instances(size_t nodes_size) +void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size) { /* The BVH's for instances are built separately, but for traversal all * BVH's are stored in global arrays. This function merges them into the * top level BVH, adjusting indexes and offsets where appropriate. */ bool use_qbvh = params.use_qbvh; size_t nsize = (use_qbvh)? BVH_QNODE_SIZE: BVH_NODE_SIZE; + size_t nsize_leaf = (use_qbvh)? BVH_QNODE_LEAF_SIZE: BVH_NODE_LEAF_SIZE; /* adjust primitive index to point to the triangle in the global array, for * meshes with transform applied and already in the top level BVH */ @@ -343,6 +342,7 @@ void BVH::pack_instances(size_t nodes_size) /* track offsets of instanced BVH data in global array */ size_t prim_offset = pack.prim_index.size(); size_t nodes_offset = nodes_size; + size_t nodes_leaf_offset = leaf_nodes_size; /* clear array that gives the node indexes for instanced objects */ pack.object_node.clear(); @@ -354,6 +354,7 @@ void BVH::pack_instances(size_t nodes_size) size_t pack_prim_index_offset = prim_index_size; size_t pack_tri_woop_offset = tri_woop_size; size_t pack_nodes_offset = nodes_size; + size_t pack_leaf_nodes_offset = leaf_nodes_size; size_t object_offset = 0; map mesh_map; @@ -367,6 +368,7 @@ void BVH::pack_instances(size_t nodes_size) prim_index_size += bvh->pack.prim_index.size(); tri_woop_size += bvh->pack.tri_woop.size(); nodes_size += bvh->pack.nodes.size(); + leaf_nodes_size += bvh->pack.leaf_nodes.size(); mesh_map[mesh] = 1; } @@ -381,6 +383,7 @@ void BVH::pack_instances(size_t nodes_size) pack.prim_visibility.resize(prim_index_size); pack.tri_woop.resize(tri_woop_size); pack.nodes.resize(nodes_size); + pack.leaf_nodes.resize(leaf_nodes_size); pack.object_node.resize(objects.size()); int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL; @@ -389,6 +392,7 @@ void BVH::pack_instances(size_t nodes_size) uint *pack_prim_visibility = (pack.prim_visibility.size())? &pack.prim_visibility[0]: NULL; float4 *pack_tri_woop = (pack.tri_woop.size())? &pack.tri_woop[0]: NULL; int4 *pack_nodes = (pack.nodes.size())? &pack.nodes[0]: NULL; + int4 *pack_leaf_nodes = (pack.leaf_nodes.size())? &pack.leaf_nodes[0]: NULL; /* merge */ foreach(Object *ob, objects) { @@ -414,12 +418,13 @@ void BVH::pack_instances(size_t nodes_size) BVH *bvh = mesh->bvh; int noffset = nodes_offset/nsize; + int noffset_leaf = nodes_leaf_offset/nsize_leaf; int mesh_tri_offset = mesh->tri_offset; int mesh_curve_offset = mesh->curve_offset; /* fill in node indexes for instances */ - if((bvh->pack.is_leaf.size() != 0) && bvh->pack.is_leaf[0]) - pack.object_node[object_offset++] = -noffset-1; + if(bvh->pack.root_index == -1) + pack.object_node[object_offset++] = -noffset_leaf-1; else pack.object_node[object_offset++] = noffset; @@ -453,6 +458,18 @@ void BVH::pack_instances(size_t nodes_size) } /* merge nodes */ + if(bvh->pack.leaf_nodes.size()) { + int4 *leaf_nodes_offset = &bvh->pack.leaf_nodes[0]; + size_t leaf_nodes_offset_size = bvh->pack.leaf_nodes.size(); + for(size_t i = 0, j = 0; i < leaf_nodes_offset_size; i+=nsize_leaf, j++) { + int4 data = leaf_nodes_offset[i]; + data.x += prim_offset; + data.y += prim_offset; + pack_leaf_nodes[pack_leaf_nodes_offset] = data; + pack_leaf_nodes_offset += nsize_leaf; + } + } + if(bvh->pack.nodes.size()) { /* For QBVH we're packing a child bbox into 6 float4, * and for regular BVH they're packed into 3 float4. @@ -460,7 +477,6 @@ void BVH::pack_instances(size_t nodes_size) size_t nsize_bbox = (use_qbvh)? 6: 3; int4 *bvh_nodes = &bvh->pack.nodes[0]; size_t bvh_nodes_size = bvh->pack.nodes.size(); - bool *bvh_is_leaf = (bvh->pack.is_leaf.size() != 0) ? &bvh->pack.is_leaf[0] : NULL; for(size_t i = 0, j = 0; i < bvh_nodes_size; i+=nsize, j++) { memcpy(pack_nodes + pack_nodes_offset, bvh_nodes + i, nsize_bbox*sizeof(int4)); @@ -468,18 +484,12 @@ void BVH::pack_instances(size_t nodes_size) /* modify offsets into arrays */ int4 data = bvh_nodes[i + nsize_bbox]; - if(bvh_is_leaf && bvh_is_leaf[j]) { - data.x += prim_offset; - data.y += prim_offset; - } - else { - data.x += (data.x < 0)? -noffset: noffset; - data.y += (data.y < 0)? -noffset: noffset; + data.x += (data.x < 0)? -noffset_leaf: noffset; + data.y += (data.y < 0)? -noffset_leaf: noffset; - if(use_qbvh) { - data.z += (data.z < 0)? -noffset: noffset; - data.w += (data.w < 0)? -noffset: noffset; - } + if(use_qbvh) { + data.z += (data.z < 0)? -noffset_leaf: noffset; + data.w += (data.w < 0)? -noffset_leaf: noffset; } pack_nodes[pack_nodes_offset + nsize_bbox] = data; @@ -496,6 +506,7 @@ void BVH::pack_instances(size_t nodes_size) } nodes_offset += bvh->pack.nodes.size(); + nodes_leaf_offset += bvh->pack.leaf_nodes.size(); prim_offset += bvh->pack.prim_index.size(); } } @@ -509,20 +520,24 @@ RegularBVH::RegularBVH(const BVHParams& params_, const vector& objects_ void RegularBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf) { + float4 data[BVH_NODE_LEAF_SIZE]; + memset(data, 0, sizeof(data)); if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) { /* object */ - pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, ~(leaf->m_lo), 0, - leaf->m_visibility, leaf->m_visibility); + data[0].x = __int_as_float(~(leaf->m_lo)); + data[0].y = __int_as_float(0); } else { - int prim_type = leaf->num_triangles() ? pack.prim_type[leaf->m_lo] : 0; - /* Triangle/curve primitive leaf. */ - pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, - leaf->m_lo, leaf->m_hi, - leaf->m_visibility, - prim_type); + /* triangle */ + data[0].x = __int_as_float(leaf->m_lo); + data[0].y = __int_as_float(leaf->m_hi); + } + data[0].z = __uint_as_float(leaf->m_visibility); + if(leaf->num_triangles() != 0) { + data[0].w = __uint_as_float(pack.prim_type[leaf->m_lo]); } + memcpy(&pack.leaf_nodes[e.idx * BVH_NODE_LEAF_SIZE], data, sizeof(float4)*BVH_NODE_LEAF_SIZE); } void RegularBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry& e0, const BVHStackEntry& e1) @@ -545,31 +560,36 @@ void RegularBVH::pack_node(int idx, const BoundBox& b0, const BoundBox& b1, int void RegularBVH::pack_nodes(const BVHNode *root) { - size_t node_size = root->getSubtreeSize(BVH_STAT_NODE_COUNT); + size_t tot_node_size = root->getSubtreeSize(BVH_STAT_NODE_COUNT); + size_t leaf_node_size = root->getSubtreeSize(BVH_STAT_LEAF_COUNT); + size_t node_size = tot_node_size - leaf_node_size; /* resize arrays */ pack.nodes.clear(); - pack.is_leaf.clear(); - pack.is_leaf.resize(node_size); /* for top level BVH, first merge existing BVH's so we know the offsets */ - if(params.top_level) - pack_instances(node_size*BVH_NODE_SIZE); - else + if(params.top_level) { + pack_instances(node_size*BVH_NODE_SIZE, + leaf_node_size*BVH_NODE_LEAF_SIZE); + } + else { pack.nodes.resize(node_size*BVH_NODE_SIZE); + pack.leaf_nodes.resize(leaf_node_size*BVH_NODE_LEAF_SIZE); + } - int nextNodeIdx = 0; + int nextNodeIdx = 0, nextLeafNodeIdx = 0; vector stack; stack.reserve(BVHParams::MAX_DEPTH*2); - stack.push_back(BVHStackEntry(root, nextNodeIdx++)); + if(root->is_leaf()) + stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++)); + else + stack.push_back(BVHStackEntry(root, nextNodeIdx++)); while(stack.size()) { BVHStackEntry e = stack.back(); stack.pop_back(); - pack.is_leaf[e.idx] = e.node->is_leaf(); - if(e.node->is_leaf()) { /* leaf node */ const LeafNode* leaf = reinterpret_cast(e.node); @@ -577,15 +597,17 @@ void RegularBVH::pack_nodes(const BVHNode *root) } else { /* innner node */ - stack.push_back(BVHStackEntry(e.node->get_child(0), nextNodeIdx++)); - stack.push_back(BVHStackEntry(e.node->get_child(1), nextNodeIdx++)); + int idx0 = (e.node->get_child(0)->is_leaf())? (nextLeafNodeIdx++) : (nextNodeIdx++); + int idx1 = (e.node->get_child(1)->is_leaf())? (nextLeafNodeIdx++) : (nextNodeIdx++); + stack.push_back(BVHStackEntry(e.node->get_child(0), idx0)); + stack.push_back(BVHStackEntry(e.node->get_child(1), idx1)); pack_inner(e, stack[stack.size()-2], stack[stack.size()-1]); } } /* root index to start traversal at, to handle case of single leaf node */ - pack.root_index = (pack.is_leaf[0])? -1: 0; + pack.root_index = (root->is_leaf())? -1: 0; } void RegularBVH::refit_nodes() @@ -594,17 +616,15 @@ void RegularBVH::refit_nodes() BoundBox bbox = BoundBox::empty; uint visibility = 0; - refit_node(0, (pack.is_leaf[0])? true: false, bbox, visibility); + refit_node(0, (pack.root_index == -1)? true: false, bbox, visibility); } void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility) { - int4 *data = &pack.nodes[idx*BVH_NODE_SIZE]; - - int c0 = data[3].x; - int c1 = data[3].y; - if(leaf) { + int4 *data = &pack.leaf_nodes[idx*BVH_NODE_LEAF_SIZE]; + int c0 = data[0].x; + int c1 = data[0].y; /* refit leaf node */ for(int prim = c0; prim < c1; prim++) { int pidx = pack.prim_index[prim]; @@ -670,9 +690,20 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility visibility |= ob->visibility; } - pack_node(idx, bbox, bbox, c0, c1, visibility, data[3].w); + /* TODO(sergey): De-duplicate with pack_leaf(). */ + float4 leaf_data[BVH_NODE_LEAF_SIZE]; + leaf_data[0].x = __int_as_float(c0); + leaf_data[0].y = __int_as_float(c1); + leaf_data[0].z = __uint_as_float(visibility); + leaf_data[0].w = __uint_as_float(data[0].w); + memcpy(&pack.leaf_nodes[idx * BVH_NODE_LEAF_SIZE], + leaf_data, + sizeof(float4)*BVH_NODE_LEAF_SIZE); } else { + int4 *data = &pack.nodes[idx*BVH_NODE_SIZE]; + int c0 = data[3].x; + int c1 = data[3].y; /* refit inner node, set bbox from children */ BoundBox bbox0 = BoundBox::empty, bbox1 = BoundBox::empty; uint visibility0 = 0, visibility1 = 0; @@ -698,26 +729,24 @@ QBVH::QBVH(const BVHParams& params_, const vector& objects_) void QBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf) { - float4 data[BVH_QNODE_SIZE]; - + float4 data[BVH_QNODE_LEAF_SIZE]; memset(data, 0, sizeof(data)); - if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) { /* object */ - data[6].x = __int_as_float(~(leaf->m_lo)); - data[6].y = __int_as_float(0); + data[0].x = __int_as_float(~(leaf->m_lo)); + data[0].y = __int_as_float(0); } else { /* triangle */ - data[6].x = __int_as_float(leaf->m_lo); - data[6].y = __int_as_float(leaf->m_hi); + data[0].x = __int_as_float(leaf->m_lo); + data[0].y = __int_as_float(leaf->m_hi); } - data[6].z = __uint_as_float(leaf->m_visibility); + data[0].z = __uint_as_float(leaf->m_visibility); if(leaf->num_triangles() != 0) { - data[6].w = __uint_as_float(pack.prim_type[leaf->m_lo]); + data[0].w = __uint_as_float(pack.prim_type[leaf->m_lo]); } - memcpy(&pack.nodes[e.idx * BVH_QNODE_SIZE], data, sizeof(float4)*BVH_QNODE_SIZE); + memcpy(&pack.leaf_nodes[e.idx * BVH_QNODE_LEAF_SIZE], data, sizeof(float4)*BVH_QNODE_LEAF_SIZE); } void QBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry *en, int num) @@ -761,31 +790,39 @@ void QBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry *en, int num) void QBVH::pack_nodes(const BVHNode *root) { - size_t node_size = root->getSubtreeSize(BVH_STAT_QNODE_COUNT); + size_t tot_node_size = root->getSubtreeSize(BVH_STAT_QNODE_COUNT); + size_t leaf_node_size = root->getSubtreeSize(BVH_STAT_LEAF_COUNT); + size_t node_size = tot_node_size - leaf_node_size; /* resize arrays */ pack.nodes.clear(); - pack.is_leaf.clear(); - pack.is_leaf.resize(node_size); + pack.leaf_nodes.clear(); /* for top level BVH, first merge existing BVH's so we know the offsets */ - if(params.top_level) - pack_instances(node_size*BVH_QNODE_SIZE); - else + if(params.top_level) { + pack_instances(node_size*BVH_QNODE_SIZE, + leaf_node_size*BVH_QNODE_LEAF_SIZE); + } + else { pack.nodes.resize(node_size*BVH_QNODE_SIZE); + pack.leaf_nodes.resize(leaf_node_size*BVH_QNODE_LEAF_SIZE); + } - int nextNodeIdx = 0; + int nextNodeIdx = 0, nextLeafNodeIdx = 0; vector stack; stack.reserve(BVHParams::MAX_DEPTH*2); - stack.push_back(BVHStackEntry(root, nextNodeIdx++)); + if(root->is_leaf()) { + stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++)); + } + else { + stack.push_back(BVHStackEntry(root, nextNodeIdx++)); + } while(stack.size()) { BVHStackEntry e = stack.back(); stack.pop_back(); - pack.is_leaf[e.idx] = e.node->is_leaf(); - if(e.node->is_leaf()) { /* leaf node */ const LeafNode* leaf = reinterpret_cast(e.node); @@ -818,8 +855,16 @@ void QBVH::pack_nodes(const BVHNode *root) } /* push entries on the stack */ - for(int i = 0; i < numnodes; i++) - stack.push_back(BVHStackEntry(nodes[i], nextNodeIdx++)); + for(int i = 0; i < numnodes; i++) { + int idx; + if(nodes[i]->is_leaf()) { + idx = nextLeafNodeIdx++; + } + else { + idx = nextNodeIdx++; + } + stack.push_back(BVHStackEntry(nodes[i], idx)); + } /* set node */ pack_inner(e, &stack[stack.size()-numnodes], numnodes); @@ -827,7 +872,7 @@ void QBVH::pack_nodes(const BVHNode *root) } /* root index to start traversal at, to handle case of single leaf node */ - pack.root_index = (pack.is_leaf[0])? -1: 0; + pack.root_index = (root->is_leaf())? -1: 0; } void QBVH::refit_nodes() @@ -836,14 +881,14 @@ void QBVH::refit_nodes() BoundBox bbox = BoundBox::empty; uint visibility = 0; - refit_node(0, (pack.is_leaf[0])? true: false, bbox, visibility); + refit_node(0, (pack.root_index == -1)? true: false, bbox, visibility); } void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility) { - int4 *data = &pack.nodes[idx*BVH_QNODE_SIZE]; - int4 c = data[6]; if(leaf) { + int4 *data = &pack.leaf_nodes[idx*BVH_QNODE_LEAF_SIZE]; + int4 c = data[0]; /* Refit leaf node. */ for(int prim = c.x; prim < c.y; prim++) { int pidx = pack.prim_index[prim]; @@ -919,17 +964,18 @@ void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility) * * Same applies to the inner nodes case below. */ - float4 leaf_data[BVH_QNODE_SIZE]; - memset(leaf_data, 0, sizeof(leaf_data)); - leaf_data[6].x = __int_as_float(c.x); - leaf_data[6].y = __int_as_float(c.y); - leaf_data[6].z = __uint_as_float(visibility); - leaf_data[6].w = __uint_as_float(c.w); - memcpy(&pack.nodes[idx * BVH_QNODE_SIZE], + float4 leaf_data[BVH_QNODE_LEAF_SIZE]; + leaf_data[0].x = __int_as_float(c.x); + leaf_data[0].y = __int_as_float(c.y); + leaf_data[0].z = __uint_as_float(visibility); + leaf_data[0].w = __uint_as_float(c.w); + memcpy(&pack.leaf_nodes[idx * BVH_QNODE_LEAF_SIZE], leaf_data, - sizeof(float4)*BVH_QNODE_SIZE); + sizeof(float4)*BVH_QNODE_LEAF_SIZE); } else { + int4 *data = &pack.nodes[idx*BVH_QNODE_SIZE]; + int4 c = data[6]; /* Refit inner node, set bbox from children. */ BoundBox child_bbox[4] = {BoundBox::empty, BoundBox::empty, diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h index 40f039541eb..669d2ccdcd5 100644 --- a/intern/cycles/bvh/bvh.h +++ b/intern/cycles/bvh/bvh.h @@ -36,7 +36,9 @@ class Object; class Progress; #define BVH_NODE_SIZE 4 +#define BVH_NODE_LEAF_SIZE 1 #define BVH_QNODE_SIZE 7 +#define BVH_QNODE_LEAF_SIZE 1 #define BVH_ALIGN 4096 #define TRI_NODE_SIZE 3 @@ -47,7 +49,9 @@ class Progress; struct PackedBVH { /* BVH nodes storage, one node is 4x int4, and contains two bounding boxes, * and child, triangle or object indexes depending on the node type */ - array nodes; + array nodes; + /* BVH leaf nodes storage. */ + array leaf_nodes; /* object index to BVH node index mapping for instances */ array object_node; /* precomputed triangle intersection data, one triangle is 4x float4 */ @@ -61,9 +65,6 @@ struct PackedBVH { array prim_index; /* mapping from BVH primitive index, to the object id of that primitive. */ array prim_object; - /* quick array to lookup if a node is a leaf, not used for traversal, only - * for instance BVH merging */ - array is_leaf; /* index of the root node. */ int root_index; @@ -108,7 +109,7 @@ protected: void pack_triangle(int idx, float4 woop[3]); /* merge instance BVH's */ - void pack_instances(size_t nodes_size); + void pack_instances(size_t nodes_size, size_t leaf_nodes_size); /* for subclasses to implement */ virtual void pack_nodes(const BVHNode *root) = 0; diff --git a/intern/cycles/kernel/geom/geom.h b/intern/cycles/kernel/geom/geom.h index bf0d86e6206..5ab900d47aa 100644 --- a/intern/cycles/kernel/geom/geom.h +++ b/intern/cycles/kernel/geom/geom.h @@ -22,7 +22,9 @@ #define BVH_STACK_SIZE 192 #define BVH_QSTACK_SIZE 384 #define BVH_NODE_SIZE 4 +#define BVH_NODE_LEAF_SIZE 1 #define BVH_QNODE_SIZE 7 +#define BVH_QNODE_LEAF_SIZE 1 #define TRI_NODE_SIZE 3 /* silly workaround for float extended precision that happens when compiling diff --git a/intern/cycles/kernel/geom/geom_bvh_shadow.h b/intern/cycles/kernel/geom/geom_bvh_shadow.h index d2609fc029a..e4cba99dc96 100644 --- a/intern/cycles/kernel/geom/geom_bvh_shadow.h +++ b/intern/cycles/kernel/geom/geom_bvh_shadow.h @@ -200,7 +200,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, /* if node is leaf, fetch triangle list */ if(nodeAddr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+3); + float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE); int primAddr = __float_as_int(leaf.x); #if BVH_FEATURE(BVH_INSTANCING) diff --git a/intern/cycles/kernel/geom/geom_bvh_subsurface.h b/intern/cycles/kernel/geom/geom_bvh_subsurface.h index 73d392b2ea6..a73139f9c88 100644 --- a/intern/cycles/kernel/geom/geom_bvh_subsurface.h +++ b/intern/cycles/kernel/geom/geom_bvh_subsurface.h @@ -187,7 +187,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, /* if node is leaf, fetch triangle list */ if(nodeAddr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+3); + float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE); int primAddr = __float_as_int(leaf.x); #if BVH_FEATURE(BVH_INSTANCING) diff --git a/intern/cycles/kernel/geom/geom_bvh_traversal.h b/intern/cycles/kernel/geom/geom_bvh_traversal.h index c4d2a1bdc6a..87f8ccd01b1 100644 --- a/intern/cycles/kernel/geom/geom_bvh_traversal.h +++ b/intern/cycles/kernel/geom/geom_bvh_traversal.h @@ -248,7 +248,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, /* if node is leaf, fetch triangle list */ if(nodeAddr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+3); + float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE); int primAddr = __float_as_int(leaf.x); #if BVH_FEATURE(BVH_INSTANCING) diff --git a/intern/cycles/kernel/geom/geom_bvh_volume.h b/intern/cycles/kernel/geom/geom_bvh_volume.h index 111f840cb95..41c784869f2 100644 --- a/intern/cycles/kernel/geom/geom_bvh_volume.h +++ b/intern/cycles/kernel/geom/geom_bvh_volume.h @@ -188,7 +188,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, /* if node is leaf, fetch triangle list */ if(nodeAddr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+3); + float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE); int primAddr = __float_as_int(leaf.x); #if BVH_FEATURE(BVH_INSTANCING) diff --git a/intern/cycles/kernel/geom/geom_qbvh_shadow.h b/intern/cycles/kernel/geom/geom_qbvh_shadow.h index 2adebb28c28..f79b2ed9f34 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_shadow.h +++ b/intern/cycles/kernel/geom/geom_qbvh_shadow.h @@ -206,7 +206,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, /* If node is leaf, fetch triangle list. */ if(nodeAddr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_QNODE_SIZE+6); + float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE); #ifdef __VISIBILITY_FLAG__ if((__float_as_uint(leaf.z) & PATH_RAY_SHADOW) == 0) { /* Pop. */ diff --git a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h index 654c5cf1493..d85e1a4691e 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h +++ b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h @@ -202,7 +202,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, /* If node is leaf, fetch triangle list. */ if(nodeAddr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_QNODE_SIZE+6); + float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE); int primAddr = __float_as_int(leaf.x); #if BVH_FEATURE(BVH_INSTANCING) diff --git a/intern/cycles/kernel/geom/geom_qbvh_traversal.h b/intern/cycles/kernel/geom/geom_qbvh_traversal.h index 6c61296ad1f..cc20ebd8154 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_traversal.h +++ b/intern/cycles/kernel/geom/geom_qbvh_traversal.h @@ -260,7 +260,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, /* If node is leaf, fetch triangle list. */ if(nodeAddr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_QNODE_SIZE+6); + float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE); #ifdef __VISIBILITY_FLAG__ if(UNLIKELY((nodeDist > isect->t) || ((__float_as_uint(leaf.z) & visibility) == 0))) diff --git a/intern/cycles/kernel/geom/geom_qbvh_volume.h b/intern/cycles/kernel/geom/geom_qbvh_volume.h index 1c9ace68d53..e3a5dcffee5 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_volume.h +++ b/intern/cycles/kernel/geom/geom_qbvh_volume.h @@ -208,7 +208,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, /* If node is leaf, fetch triangle list. */ if(nodeAddr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_QNODE_SIZE+6); + float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE); int primAddr = __float_as_int(leaf.x); #if BVH_FEATURE(BVH_INSTANCING) diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index 374dc6d1dd9..f545a056cc8 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -24,6 +24,7 @@ /* bvh */ KERNEL_TEX(float4, texture_float4, __bvh_nodes) +KERNEL_TEX(float4, texture_float4, __bvh_leaf_nodes) KERNEL_TEX(float4, texture_float4, __tri_woop) KERNEL_TEX(uint, texture_uint, __prim_type) KERNEL_TEX(uint, texture_uint, __prim_visibility) diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index e927d46d404..ccc1e3df730 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -251,9 +251,9 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, case 95: r = kernel_tex_image_interp(__tex_image_095, x, y); break; case 96: r = kernel_tex_image_interp(__tex_image_096, x, y); break; case 97: r = kernel_tex_image_interp(__tex_image_097, x, y); break; - case 98: r = kernel_tex_image_interp(__tex_image_098, x, y); break; #if defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 300) + case 98: r = kernel_tex_image_interp(__tex_image_098, x, y); break; case 99: r = kernel_tex_image_interp(__tex_image_099, x, y); break; case 100: r = kernel_tex_image_interp(__tex_image_100, x, y); break; case 101: r = kernel_tex_image_interp(__tex_image_101, x, y); break; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index b6f3cb3502b..19ca159d03f 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -1101,6 +1101,10 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene * dscene->bvh_nodes.reference((float4*)&pack.nodes[0], pack.nodes.size()); device->tex_alloc("__bvh_nodes", dscene->bvh_nodes); } + if(pack.leaf_nodes.size()) { + dscene->bvh_leaf_nodes.reference((float4*)&pack.leaf_nodes[0], pack.leaf_nodes.size()); + device->tex_alloc("__bvh_leaf_nodes", dscene->bvh_leaf_nodes); + } if(pack.object_node.size()) { dscene->object_node.reference((uint*)&pack.object_node[0], pack.object_node.size()); device->tex_alloc("__object_node", dscene->object_node); @@ -1315,6 +1319,7 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen void MeshManager::device_free(Device *device, DeviceScene *dscene) { device->tex_free(dscene->bvh_nodes); + device->tex_free(dscene->bvh_leaf_nodes); device->tex_free(dscene->object_node); device->tex_free(dscene->tri_woop); device->tex_free(dscene->prim_type); diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 53c3a95903c..851e5ac0b72 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -62,6 +62,7 @@ class DeviceScene { public: /* BVH */ device_vector bvh_nodes; + device_vector bvh_leaf_nodes; device_vector object_node; device_vector tri_woop; device_vector prim_type; -- cgit v1.2.3 From 4d5446cea7c3498eeca05ea4917b7b7594bef3ac Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 20 Apr 2015 14:45:40 +0200 Subject: Usual UI messages fixes... --- source/blender/makesrna/intern/rna_lamp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index 481d139a9de..6140a34b271 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -828,7 +828,8 @@ static void rna_def_sun_lamp(BlenderRNA *brna) prop = RNA_def_property(srna, "show_shadow_box", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", LA_SHOW_SHADOW_BOX); - RNA_def_property_ui_text(prop, "Show Shadow Box", "Draw box in 3D view to visualize which object are contained in it"); + RNA_def_property_ui_text(prop, "Show Shadow Box", + "Draw a box in 3D view to visualize which objects are contained in it"); RNA_def_property_update(prop, 0, "rna_Lamp_draw_update"); } -- cgit v1.2.3 From 42e427905cd77dc5e8d805b121c754e1be54737f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 20 Apr 2015 18:30:26 +0500 Subject: CMake: Move performance tests under the cmake option This way running full sweep of regression tests does not require waiting for the performance test to finish. --- CMakeLists.txt | 1 + tests/gtests/blenlib/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 03b7f229eb4..cd37aa17468 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -395,6 +395,7 @@ option(WITH_BOOST "Enable features depending on boost" ON) # Unit testsing option(WITH_GTESTS "Enable GTest unit testing" OFF) +option(WITH_TESTS_PERFORMANCE "Enable performance tests" OFF) # Documentation diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt index 152b65617a4..20b876053d9 100644 --- a/tests/gtests/blenlib/CMakeLists.txt +++ b/tests/gtests/blenlib/CMakeLists.txt @@ -45,4 +45,6 @@ BLENDER_TEST(BLI_listbase "bf_blenlib") BLENDER_TEST(BLI_hash_mm2a "bf_blenlib") BLENDER_TEST(BLI_ghash "bf_blenlib") -BLENDER_TEST(BLI_ghash_performance "bf_blenlib") +if(WITH_TESTS_PERFORMANCE) + BLENDER_TEST(BLI_ghash_performance "bf_blenlib") +endif() -- cgit v1.2.3 From 6298632bfa00b90198bd76b82aa249985530e4fa Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 20 Apr 2015 19:23:25 +0500 Subject: Guardedalloc: Don't use aligned blocks to calculate memory sloppyness Aligned memory is allocated with memalign() and malloc_usable_size() can't be used to measure this block. --- intern/guardedalloc/intern/mallocn_guarded_impl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/guardedalloc/intern/mallocn_guarded_impl.c b/intern/guardedalloc/intern/mallocn_guarded_impl.c index bdcace243d9..88d6f35d438 100644 --- a/intern/guardedalloc/intern/mallocn_guarded_impl.c +++ b/intern/guardedalloc/intern/mallocn_guarded_impl.c @@ -711,7 +711,7 @@ void MEM_guarded_printmemlist_stats(void) totpb++; pb++; - if (!membl->mmap) { + if (!membl->mmap && membl->alignment == 0) { mem_in_use_slop += (sizeof(MemHead) + sizeof(MemTail) + malloc_usable_size((void *)membl)) - membl->len; } -- cgit v1.2.3 From 57d9badc2100001df3bb60c44f9da68595bac0f5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 20 Apr 2015 23:37:04 +1000 Subject: Cleanup: use bool /w flag checks --- source/blender/blenfont/intern/blf_glyph.c | 8 +- source/blender/blenkernel/intern/mesh.c | 6 +- source/blender/blenloader/intern/readfile.c | 2 +- source/blender/editors/curve/editcurve_add.c | 2 +- source/blender/editors/gpencil/drawgpencil.c | 2 +- source/blender/editors/include/ED_mesh.h | 4 +- source/blender/editors/include/ED_view3d.h | 7 +- source/blender/editors/mask/mask_draw.c | 4 +- source/blender/editors/mesh/editmesh_select.c | 36 ++-- source/blender/editors/object/object_vgroup.c | 2 +- source/blender/editors/render/render_opengl.c | 4 +- source/blender/editors/sculpt_paint/paint_vertex.c | 8 +- source/blender/editors/space_node/node_draw.c | 6 +- source/blender/editors/space_node/node_group.c | 4 +- .../editors/space_sequencer/space_sequencer.c | 5 +- source/blender/editors/space_view3d/drawmesh.c | 4 +- source/blender/editors/space_view3d/drawobject.c | 2 +- source/blender/editors/space_view3d/drawvolume.c | 2 +- source/blender/editors/space_view3d/view3d_draw.c | 6 +- .../blender/editors/space_view3d/view3d_select.c | 8 +- source/blender/editors/transform/transform.c | 2 +- .../editors/transform/transform_conversions.c | 198 +++++++++++---------- source/blender/editors/uvedit/uvedit_ops.c | 7 +- .../blender/imbuf/intern/openexr/openexr_api.cpp | 18 +- source/blender/makesrna/intern/rna_object.c | 4 +- source/blender/modifiers/intern/MOD_decimate.c | 4 +- source/blender/modifiers/intern/MOD_mirror.c | 2 +- source/blender/modifiers/intern/MOD_screw.c | 4 +- source/blender/modifiers/intern/MOD_solidify.c | 2 +- source/blender/modifiers/intern/MOD_uvproject.c | 2 +- source/blender/modifiers/intern/MOD_weightvgmix.c | 2 +- .../modifiers/intern/MOD_weightvgproximity.c | 2 +- .../blender/render/intern/source/multires_bake.c | 10 +- .../blender/render/intern/source/texture_ocean.c | 2 +- .../blender/windowmanager/intern/wm_event_system.c | 2 +- source/blender/windowmanager/intern/wm_operators.c | 4 +- 36 files changed, 204 insertions(+), 183 deletions(-) diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index c65a0825a49..215d2484c18 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -199,7 +199,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) GlyphBLF *g; FT_Error err; FT_Bitmap bitmap, tempbitmap; - int sharp = (U.text_render & USER_TEXT_DISABLE_AA); + const bool is_sharp = (U.text_render & USER_TEXT_DISABLE_AA) != 0; int flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP; FT_BBox bbox; unsigned int key; @@ -224,7 +224,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) if (font->flags & BLF_HINTING) flags &= ~FT_LOAD_NO_HINTING; - if (sharp) + if (is_sharp) err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_MONO); else err = FT_Load_Glyph(font->face, (FT_UInt)index, flags); @@ -237,7 +237,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) /* get the glyph. */ slot = font->face->glyph; - if (sharp) { + if (is_sharp) { err = FT_Render_Glyph(slot, FT_RENDER_MODE_MONO); /* Convert result from 1 bit per pixel to 8 bit per pixel */ @@ -266,7 +266,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) g->height = (int)bitmap.rows; if (g->width && g->height) { - if (sharp) { + if (is_sharp) { /* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */ int i; for (i = 0; i < (g->width * g->height); i++) { diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index eec2b108ca3..87325a7ff47 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1265,7 +1265,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase, dl = dispbase->first; while (dl) { - int smooth = dl->rt & CU_SMOOTH ? 1 : 0; + const bool is_smooth = (dl->rt & CU_SMOOTH) != 0; if (dl->type == DL_SEGM) { startvert = vertcount; @@ -1344,7 +1344,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase, } } - if (smooth) mpoly->flag |= ME_SMOOTH; + if (is_smooth) mpoly->flag |= ME_SMOOTH; mpoly++; mloop += 3; index += 3; @@ -1423,7 +1423,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase, } } - if (smooth) mpoly->flag |= ME_SMOOTH; + if (is_smooth) mpoly->flag |= ME_SMOOTH; mpoly++; mloop += 4; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9dd5245dcbf..21d69fe33c3 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2639,7 +2639,7 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open)) * New file versions already have input/output nodes with duplicate links, * in that case just remove the invalid links. */ - int create_io_nodes = (ntree->flag & NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE); + const bool create_io_nodes = (ntree->flag & NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE) != 0; float input_locx = 1000000.0f, input_locy = 0.0f; float output_locx = -1000000.0f, output_locy = 0.0f; diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c index 7c53896b969..d319adca388 100644 --- a/source/blender/editors/curve/editcurve_add.c +++ b/source/blender/editors/curve/editcurve_add.c @@ -121,7 +121,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type const float grid = 1.0f; const int cutype = (type & CU_TYPE); // poly, bezier, nurbs, etc const int stype = (type & CU_PRIMITIVE); - const int force_3d = ((Curve *)obedit->data)->flag & CU_3D; /* could be adding to an existing 3D curve */ + const bool force_3d = (((Curve *)obedit->data)->flag & CU_3D) != 0; /* could be adding to an existing 3D curve */ unit_m4(umat); unit_m4(viewmat); diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 0d35d3ce716..ffcd204135f 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -761,7 +761,7 @@ static void gp_draw_strokes_edit(bGPDframe *gpf, int offsx, int offsy, int winx, { bGPDstroke *gps; - const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY); + const bool no_xray = (dflag & GP_DRAWDATA_NO_XRAY) != 0; int mask_orig = 0; /* set up depth masks... */ diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 8fb6fcbd0d7..f8be5251b53 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -137,7 +137,9 @@ bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2] short xmin, short ymin, short xmax, short ymax); bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads); -struct BMVert *EDBM_vert_find_nearest(struct ViewContext *vc, float *r_dist, const bool sel, const bool strict); +struct BMVert *EDBM_vert_find_nearest( + struct ViewContext *vc, float *r_dist, + const bool use_select_bias, const bool is_strict); struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, float *r_dist); struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, float *r_dist); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index ff4b8a5b631..50199ade929 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -269,9 +269,10 @@ void drawcircball(int mode, const float cent[3], float rad, float tmat[4][4]); /* backbuffer select and draw support */ void view3d_validate_backbuf(struct ViewContext *vc); struct ImBuf *view3d_read_backbuf(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax); -unsigned int view3d_sample_backbuf_rect(struct ViewContext *vc, const int mval[2], int size, - unsigned int min, unsigned int max, float *dist, short strict, - void *handle, bool (*indextest)(void *handle, unsigned int index)); +unsigned int view3d_sample_backbuf_rect( + struct ViewContext *vc, const int mval[2], int size, + unsigned int min, unsigned int max, float *dist, const bool is_strict, + void *handle, bool (*indextest)(void *handle, unsigned int index)); unsigned int view3d_sample_backbuf(struct ViewContext *vc, int x, int y); /* draws and does a 4x4 sample */ diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 7e767d8f6c8..2efa9e211c9 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -253,7 +253,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline return; if (sc) - undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0; + undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT); /* TODO, add this to sequence editor */ handle_size = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize; @@ -422,7 +422,7 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (* float (*points)[2] = orig_points; if (sc) { - int undistort = sc->clip && sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT; + const bool undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT); if (undistort) { int i; diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 0c3f69e4996..d5e60cfd7fd 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -390,28 +390,32 @@ static bool findnearestvert__backbufIndextest(void *handle, unsigned int index) return !(eve && BM_elem_flag_test(eve, BM_ELEM_SELECT)); } /** - * findnearestvert - * - * dist (in/out): minimal distance to the nearest and at the end, actual distance - * sel: selection bias - * if SELECT, selected vertice are given a 5 pixel bias to make them further than unselect verts - * if 0, unselected vertice are given the bias - * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased + * Nearest vertex under the cursor. + * + * \param r_dist (in/out), minimal distance to the nearest and at the end, actual distance + * \param use_select_bias + * - When true, selected vertice are given a 5 pixel bias to make them further than unselect verts. + * - When false, unselected vertice are given the bias. + * \param is_strict When true, the vertice corresponding to the sel parameter are ignored and not just biased */ -BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist, const bool sel, const bool strict) +BMVert *EDBM_vert_find_nearest( + ViewContext *vc, float *r_dist, + const bool use_select_bias, const bool is_strict) { if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) { float distance; unsigned int index; BMVert *eve; - if (strict) { - index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, - strict, vc->em, findnearestvert__backbufIndextest); + if (is_strict) { + index = view3d_sample_backbuf_rect( + vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, + is_strict, vc->em, findnearestvert__backbufIndextest); } else { - index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, - 0, NULL, NULL); + index = view3d_sample_backbuf_rect( + vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, + 0, NULL, NULL); } eve = index ? BM_vert_at_index_find(vc->em->bm, index - 1) : NULL; @@ -438,9 +442,9 @@ BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist, const bool sel, c data.lastIndex = lastSelectedIndex; data.mval_fl[0] = vc->mval[0]; data.mval_fl[1] = vc->mval[1]; - data.select = sel ? BM_ELEM_SELECT : 0; + data.select = use_select_bias ? BM_ELEM_SELECT : 0; data.dist = *r_dist; - data.strict = strict; + data.strict = is_strict; data.closest = NULL; data.closestIndex = 0; @@ -653,7 +657,7 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, view3d_validate_backbuf(vc); if (em->selectmode & SCE_SELECT_VERTEX) - *r_eve = EDBM_vert_find_nearest(vc, &dist, BM_ELEM_SELECT, 0); + *r_eve = EDBM_vert_find_nearest(vc, &dist, true, false); if (em->selectmode & SCE_SELECT_FACE) *r_efa = EDBM_face_find_nearest(vc, &dist); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index f885cbbb24f..960b29ae38e 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -2062,7 +2062,7 @@ void ED_vgroup_mirror(Object *ob, /* object mode / weight paint */ MVert *mv, *mv_mirr; int vidx, vidx_mirr; - const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; + const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; if (me->dvert == NULL) { goto cleanup; diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index ded2489e1e5..0a605297a4c 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -338,7 +338,9 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) /* render 3d view */ if (rv3d->persp == RV3D_CAMOB && v3d->camera) { - /*int is_ortho = scene->r.mode & R_ORTHO;*/ +#if 0 + const bool is_ortho = (scene->r.mode & R_ORTHO) != 0; +#endif camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, viewname); RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat); if (camera->type == OB_CAMERA) { diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 9bca0fd2976..2a7e736417d 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -209,7 +209,7 @@ static void do_shared_vertex_tesscol(Mesh *me, bool *mfacetag) { /* if no mcol: do not do */ /* if tface: only the involved faces, otherwise all */ - const int use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL); + const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; MFace *mface; int a; short *scolmain, *scol; @@ -280,7 +280,7 @@ static void do_shared_vertex_tesscol(Mesh *me, bool *mfacetag) static void do_shared_vertexcol(Mesh *me, bool *mlooptag, bool *mfacetag, const bool do_tessface) { - const int use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL); + const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; MPoly *mp; int (*scol)[4]; int i, j; @@ -1091,7 +1091,7 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even me = BKE_mesh_from_object(vc.obact); if (me && me->dvert && vc.v3d && vc.rv3d) { - const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; + const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; int v_idx_best = -1; unsigned int index; @@ -1177,7 +1177,7 @@ static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA if (me && me->dvert && vc.v3d && vc.rv3d && vc.obact->defbase.first) { const int defbase_tot = BLI_listbase_count(&vc.obact->defbase); - const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; + const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; int *groups = MEM_callocN(defbase_tot * sizeof(int), "groups"); bool found = false; unsigned int index; diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 87a64e95e63..e27cb041dc5 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -163,14 +163,14 @@ void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree) ntreeTexCheckCyclics(ntree); } -static int compare_nodes(bNode *a, bNode *b) +static bool compare_nodes(const bNode *a, const bNode *b) { bNode *parent; /* These tell if either the node or any of the parent nodes is selected. * A selected parent means an unselected node is also in foreground! */ - int a_select = (a->flag & NODE_SELECT), b_select = (b->flag & NODE_SELECT); - int a_active = (a->flag & NODE_ACTIVE), b_active = (b->flag & NODE_ACTIVE); + bool a_select = (a->flag & NODE_SELECT) != 0, b_select = (b->flag & NODE_SELECT) != 0; + bool a_active = (a->flag & NODE_ACTIVE) != 0, b_active = (b->flag & NODE_ACTIVE) != 0; /* if one is an ancestor of the other */ /* XXX there might be a better sorting algorithm for stable topological sort, this is O(n^2) worst case */ diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index b69808d4e81..f1d9d4efcc6 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -456,8 +456,8 @@ static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, flo /* add internal links to the ntree */ for (link = ngroup->links.first; link; link = link_next) { - int fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT)); - int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT)); + const bool fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT)); + const bool toselect = (link->tonode && (link->tonode->flag & NODE_SELECT)); link_next = link->next; if (make_copy) { diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 7a7f189b187..769718e1567 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -564,7 +564,10 @@ static void sequencer_preview_area_draw(const bContext *C, ARegion *ar) SpaceSeq *sseq = sa->spacedata.first; Scene *scene = CTX_data_scene(C); wmWindowManager *wm = CTX_wm_manager(C); - int show_split = scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW && sseq->mainb == SEQ_DRAW_IMG_IMBUF; + const bool show_split = ( + scene->ed && + (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) && + (sseq->mainb == SEQ_DRAW_IMG_IMBUF)); /* XXX temp fix for wrong setting in sseq->mainb */ if (sseq->mainb == SEQ_DRAW_SEQUENCE) sseq->mainb = SEQ_DRAW_IMG_IMBUF; diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index b1f8d112765..b374ce64319 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -775,7 +775,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl) for (a = 0, mp = mface; a < totpoly; a++, mtpoly++, mp++) { short matnr = mp->mat_nr; - int mf_smooth = mp->flag & ME_SMOOTH; + const bool mf_smooth = (mp->flag & ME_SMOOTH) != 0; Material *mat = (me->mat) ? me->mat[matnr] : NULL; int mode = mat ? mat->game.flag : GEMAT_INVISIBLE; @@ -1107,7 +1107,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Mesh *me = ob->data; TexMatCallback data = {scene, ob, me, dm}; bool (*set_face_cb)(void *, int); - int glsl, picking = (G.f & G_PICKSEL); + bool glsl, picking = (G.f & G_PICKSEL) != 0; /* face hiding callback depending on mode */ if (ob == scene->obedit) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index ece195aa22b..f53fd967daa 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -4225,7 +4225,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } if (is_obact && BKE_paint_select_vert_test(ob)) { - const int use_depth = (v3d->flag & V3D_ZBUF_SELECT); + const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) != 0; glColor3f(0.0f, 0.0f, 0.0f); glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index 50ccde6da01..d6691f431dd 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -105,7 +105,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, float cor[3] = {1.0f, 1.0f, 1.0f}; int gl_depth = 0, gl_blend = 0; - int use_fire = (sds->active_fields & SM_ACTIVE_FIRE); + const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) != 0; /* draw slices of smoke is adapted from c++ code authored * by: Johannes Schmid and Ingemar Rask, 2006, johnny@grob.org */ diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index fd6288b1601..bfb4f60cdff 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1542,8 +1542,8 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, /* smart function to sample a rect spiralling outside, nice for backbuf selection */ unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int size, - unsigned int min, unsigned int max, float *r_dist, short strict, - void *handle, bool (*indextest)(void *handle, unsigned int index)) + unsigned int min, unsigned int max, float *r_dist, const bool is_strict, + void *handle, bool (*indextest)(void *handle, unsigned int index)) { struct ImBuf *buf; unsigned int *bufmin, *bufmax, *tbuf; @@ -1577,7 +1577,7 @@ unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int for (a = 0; a < 2; a++) { for (b = 0; b < nr; b++, distance++) { if (*tbuf && *tbuf >= min && *tbuf < max) { /* we got a hit */ - if (strict) { + if (is_strict) { indexok = indextest(handle, *tbuf - min + 1); if (indexok) { *r_dist = sqrtf((float)distance); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index d0f22ba58c5..587dac722e4 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -725,7 +725,7 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, } static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select) { - const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT); + const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0; Object *ob = vc->obact; Mesh *me = ob->data; rcti rect; @@ -1641,7 +1641,7 @@ static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, con } static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) { - const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT); + const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0; Mesh *me; MVert *mvert; struct ImBuf *ibuf; @@ -2185,7 +2185,7 @@ void VIEW3D_OT_select_border(wmOperatorType *ot) static bool mouse_weight_paint_vertex_select(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, Object *obact) { View3D *v3d = CTX_wm_view3d(C); - const int use_zbuf = (v3d->flag & V3D_ZBUF_SELECT); + const bool use_zbuf = (v3d->flag & V3D_ZBUF_SELECT) != 0; Mesh *me = obact->data; /* already checked for NULL */ unsigned int index = 0; @@ -2453,7 +2453,7 @@ static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, } static void paint_vertsel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) { - const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT); + const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0; Object *ob = vc->obact; Mesh *me = ob->data; bool bbsel; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index f8e529aa4bf..a7b984fc76a 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -911,7 +911,7 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm { if (!(t->flag & T_NO_CONSTRAINT)) { int constraint_axis, constraint_plane; - int edit_2d = (t->flag & T_2D_EDIT); + const bool edit_2d = (t->flag & T_2D_EDIT) != 0; const char *msg1 = "", *msg2 = "", *msg3 = ""; char axis; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index a5f247d7172..0cdc2b5eb6c 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -341,20 +341,20 @@ static void createTransEdge(TransInfo *t) BMIter iter; float mtx[3][3], smtx[3][3]; int count = 0, countsel = 0; - int propmode = t->flag & T_PROP_EDIT; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; int cd_edge_float_offset; BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) countsel++; - if (propmode) count++; + if (is_prop_edit) count++; } } if (countsel == 0) return; - if (propmode) { + if (is_prop_edit) { t->total = count; } else { @@ -380,7 +380,7 @@ static void createTransEdge(TransInfo *t) BLI_assert(cd_edge_float_offset != -1); BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { - if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || propmode)) { + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || is_prop_edit)) { float *fl_ptr; /* need to set center for center calculations */ mid_v3_v3v3(td->center, eed->v1->co, eed->v2->co); @@ -1330,18 +1330,18 @@ static void createTransMBallVerts(TransInfo *t) TransDataExtension *tx; float mtx[3][3], smtx[3][3]; int count = 0, countsel = 0; - int propmode = t->flag & T_PROP_EDIT; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; /* count totals */ for (ml = mb->editelems->first; ml; ml = ml->next) { if (ml->flag & SELECT) countsel++; - if (propmode) count++; + if (is_prop_edit) count++; } /* note: in prop mode we need at least 1 selected */ if (countsel == 0) return; - if (propmode) t->total = count; + if (is_prop_edit) t->total = count; else t->total = countsel; td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(MBall EditMode)"); @@ -1351,7 +1351,7 @@ static void createTransMBallVerts(TransInfo *t) pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); for (ml = mb->editelems->first; ml; ml = ml->next) { - if (propmode || (ml->flag & SELECT)) { + if (is_prop_edit || (ml->flag & SELECT)) { td->loc = &ml->x; copy_v3_v3(td->iloc, td->loc); copy_v3_v3(td->center, td->loc); @@ -1464,7 +1464,7 @@ static void createTransCurveVerts(TransInfo *t) float mtx[3][3], smtx[3][3]; int a; int count = 0, countsel = 0; - int propmode = t->flag & T_PROP_EDIT; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; short hide_handles = (cu->drawflag & CU_HIDE_HANDLES); ListBase *nurbs; @@ -1479,13 +1479,13 @@ static void createTransCurveVerts(TransInfo *t) if (bezt->hide == 0) { if (hide_handles) { if (bezt->f2 & SELECT) countsel += 3; - if (propmode) count += 3; + if (is_prop_edit) count += 3; } else { if (bezt->f1 & SELECT) countsel++; if (bezt->f2 & SELECT) countsel++; if (bezt->f3 & SELECT) countsel++; - if (propmode) count += 3; + if (is_prop_edit) count += 3; } } } @@ -1493,7 +1493,7 @@ static void createTransCurveVerts(TransInfo *t) else { for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) { if (bp->hide == 0) { - if (propmode) count++; + if (is_prop_edit) count++; if (bp->f1 & SELECT) countsel++; } } @@ -1502,7 +1502,7 @@ static void createTransCurveVerts(TransInfo *t) /* note: in prop mode we need at least 1 selected */ if (countsel == 0) return; - if (propmode) t->total = count; + if (is_prop_edit) t->total = count; else t->total = countsel; t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Curve EditMode)"); @@ -1537,7 +1537,7 @@ static void createTransCurveVerts(TransInfo *t) } } - if (propmode || + if (is_prop_edit || ((bezt->f2 & SELECT) && hide_handles) || ((bezt->f1 & SELECT) && hide_handles == 0)) { @@ -1571,7 +1571,7 @@ static void createTransCurveVerts(TransInfo *t) } /* This is the Curve Point, the other two are handles */ - if (propmode || (bezt->f2 & SELECT)) { + if (is_prop_edit || (bezt->f2 & SELECT)) { copy_v3_v3(td->iloc, bezt->vec[1]); td->loc = bezt->vec[1]; copy_v3_v3(td->center, td->loc); @@ -1607,7 +1607,7 @@ static void createTransCurveVerts(TransInfo *t) count++; tail++; } - if (propmode || + if (is_prop_edit || ((bezt->f2 & SELECT) && hide_handles) || ((bezt->f3 & SELECT) && hide_handles == 0)) { @@ -1644,12 +1644,12 @@ static void createTransCurveVerts(TransInfo *t) (void)hdata; /* quiet warning */ } - else if (propmode && head != tail) { + else if (is_prop_edit && head != tail) { calc_distanceCurveVerts(head, tail - 1); head = tail; } } - if (propmode && head != tail) + if (is_prop_edit && head != tail) calc_distanceCurveVerts(head, tail - 1); /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandles @@ -1664,7 +1664,7 @@ static void createTransCurveVerts(TransInfo *t) head = tail = td; for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) { if (bp->hide == 0) { - if (propmode || (bp->f1 & SELECT)) { + if (is_prop_edit || (bp->f1 & SELECT)) { copy_v3_v3(td->iloc, bp->vec); td->loc = bp->vec; copy_v3_v3(td->center, td->loc); @@ -1689,12 +1689,12 @@ static void createTransCurveVerts(TransInfo *t) tail++; } } - else if (propmode && head != tail) { + else if (is_prop_edit && head != tail) { calc_distanceCurveVerts(head, tail - 1); head = tail; } } - if (propmode && head != tail) + if (is_prop_edit && head != tail) calc_distanceCurveVerts(head, tail - 1); } } @@ -1710,14 +1710,14 @@ static void createTransLatticeVerts(TransInfo *t) float mtx[3][3], smtx[3][3]; int a; int count = 0, countsel = 0; - int propmode = t->flag & T_PROP_EDIT; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; bp = latt->def; a = latt->pntsu * latt->pntsv * latt->pntsw; while (a--) { if (bp->hide == 0) { if (bp->f1 & SELECT) countsel++; - if (propmode) count++; + if (is_prop_edit) count++; } bp++; } @@ -1725,7 +1725,7 @@ static void createTransLatticeVerts(TransInfo *t) /* note: in prop mode we need at least 1 selected */ if (countsel == 0) return; - if (propmode) t->total = count; + if (is_prop_edit) t->total = count; else t->total = countsel; t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Lattice EditMode)"); @@ -1736,7 +1736,7 @@ static void createTransLatticeVerts(TransInfo *t) bp = latt->def; a = latt->pntsu * latt->pntsv * latt->pntsw; while (a--) { - if (propmode || (bp->f1 & SELECT)) { + if (is_prop_edit || (bp->f1 & SELECT)) { if (bp->hide == 0) { copy_v3_v3(td->iloc, bp->vec); td->loc = bp->vec; @@ -1777,7 +1777,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) float mat[4][4]; int i, k, transformparticle; int count = 0, hasselected = 0; - int propmode = t->flag & T_PROP_EDIT; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; if (edit == NULL || t->settings->particle.selectmode == SCE_SELECT_PATH) return; @@ -1799,7 +1799,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) hasselected = 1; transformparticle = 1; } - else if (propmode) + else if (is_prop_edit) transformparticle = 1; } } @@ -1849,7 +1849,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) if (key->flag & PEK_SELECT) td->flag |= TD_SELECTED; - else if (!propmode) + else if (!is_prop_edit) td->flag |= TD_SKIP; unit_m3(td->mtx); @@ -1878,7 +1878,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) tx++; tail++; } - if (propmode && head != tail) + if (is_prop_edit && head != tail) calc_distanceCurveVerts(head, tail - 1); } } @@ -1894,7 +1894,8 @@ void flushTransParticles(TransInfo *t) PTCacheEditKey *key; TransData *td; float mat[4][4], imat[4][4], co[3]; - int i, k, propmode = t->flag & T_PROP_EDIT; + int i, k; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; if (psys) psmd = psys_get_modifier(ob, psys); @@ -1915,7 +1916,7 @@ void flushTransParticles(TransInfo *t) /* optimization for proportional edit */ - if (!propmode || !compare_v3v3(key->co, co, 0.0001f)) { + if (!is_prop_edit || !compare_v3v3(key->co, co, 0.0001f)) { copy_v3_v3(key->co, co); point->flag |= PEP_EDIT_RECALC; } @@ -2282,7 +2283,7 @@ static void createTransEditVerts(TransInfo *t) float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL; float *dists = NULL; int a; - int propmode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0; + const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0; int mirror = 0; int cd_vert_bweight_offset = -1; bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; @@ -2322,7 +2323,7 @@ static void createTransEditVerts(TransInfo *t) cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); } - if (propmode) { + if (prop_mode) { unsigned int count = 0; BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { @@ -2333,7 +2334,7 @@ static void createTransEditVerts(TransInfo *t) t->total = count; /* allocating scratch arrays */ - if (propmode & T_PROP_CONNECTED) + if (prop_mode & T_PROP_CONNECTED) dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears"); } else { @@ -2355,7 +2356,7 @@ static void createTransEditVerts(TransInfo *t) * matrix inversion still works and we can still moving along the other */ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); - if (propmode & T_PROP_CONNECTED) { + if (prop_mode & T_PROP_CONNECTED) { editmesh_set_connectivity_distance(em->bm, mtx, dists); } @@ -2384,7 +2385,7 @@ static void createTransEditVerts(TransInfo *t) { mappedcos = BKE_crazyspace_get_mapped_editverts(t->scene, t->obedit); quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats"); - BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !propmode); + BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode); if (mappedcos) MEM_freeN(mappedcos); } @@ -2409,7 +2410,7 @@ static void createTransEditVerts(TransInfo *t) BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - if (propmode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { struct TransIslandData *v_island = (island_info && island_vert_map[a] != -1) ? &island_info[island_vert_map[a]] : NULL; float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL; @@ -2422,8 +2423,8 @@ static void createTransEditVerts(TransInfo *t) if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) tob->flag |= TD_SELECTED; - if (propmode) { - if (propmode & T_PROP_CONNECTED) { + if (prop_mode) { + if (prop_mode & T_PROP_CONNECTED) { tob->dist = dists[a]; } else { @@ -2728,15 +2729,15 @@ static void createTransUVs(bContext *C, TransInfo *t) UvElementMap *elementmap = NULL; BLI_bitmap *island_enabled = NULL; int count = 0, countsel = 0, count_rejected = 0; - const bool propmode = (t->flag & T_PROP_EDIT) != 0; - const bool propconnected = (t->flag & T_PROP_CONNECTED) != 0; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; + const bool is_prop_connected = (t->flag & T_PROP_CONNECTED) != 0; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); if (!ED_space_image_show_uvedit(sima, t->obedit)) return; /* count */ - if (propconnected) { + if (is_prop_connected) { /* create element map with island information */ if (ts->uv_flag & UV_SYNC_SELECTION) { elementmap = BM_uv_element_map_create(em->bm, false, true); @@ -2760,14 +2761,14 @@ static void createTransUVs(bContext *C, TransInfo *t) if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { countsel++; - if (propconnected) { + if (is_prop_connected) { UvElement *element = BM_uv_element_get(elementmap, efa, l); BLI_BITMAP_ENABLE(island_enabled, element->island); } } - if (propmode) { + if (is_prop_edit) { count++; } } @@ -2775,13 +2776,13 @@ static void createTransUVs(bContext *C, TransInfo *t) /* note: in prop mode we need at least 1 selected */ if (countsel == 0) { - if (propconnected) { + if (is_prop_connected) { MEM_freeN(island_enabled); } return; } - t->total = (propmode) ? count : countsel; + t->total = (is_prop_edit) ? count : countsel; t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(UV Editing)"); /* for each 2d uv coord a 3d vector is allocated, so that they can be * treated just as if they were 3d verts */ @@ -2798,10 +2799,10 @@ static void createTransUVs(bContext *C, TransInfo *t) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (!propmode && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) + if (!is_prop_edit && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) continue; - if (propconnected) { + if (is_prop_connected) { UvElement *element = BM_uv_element_get(elementmap, efa, l); if (!BLI_BITMAP_TEST(island_enabled, element->island)) { count_rejected++; @@ -2814,7 +2815,7 @@ static void createTransUVs(bContext *C, TransInfo *t) } } - if (propconnected) { + if (is_prop_connected) { t->total -= count_rejected; BM_uv_element_map_free(elementmap); MEM_freeN(island_enabled); @@ -3329,7 +3330,7 @@ static void posttrans_action_clean(bAnimContext *ac, bAction *act) /* ----------------------------- */ /* fully select selected beztriples, but only include if it's on the right side of cfra */ -static int count_fcurve_keys(FCurve *fcu, char side, float cfra, bool propedit) +static int count_fcurve_keys(FCurve *fcu, char side, float cfra, bool is_prop_edit) { BezTriple *bezt; int i, count = 0, count_all = 0; @@ -3349,13 +3350,13 @@ static int count_fcurve_keys(FCurve *fcu, char side, float cfra, bool propedit) } } - if (propedit && count > 0) + if (is_prop_edit && count > 0) return count_all; else return count; } /* fully select selected beztriples, but only include if it's on the right side of cfra */ -static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra, bool propedit) +static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra, bool is_prop_edit) { bGPDframe *gpf; int count = 0, count_all = 0; @@ -3372,14 +3373,14 @@ static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra, bool prop } } - if (propedit && count > 0) + if (is_prop_edit && count > 0) return count_all; else return count; } /* fully select selected beztriples, but only include if it's on the right side of cfra */ -static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, bool propedit) +static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, bool is_prop_edit) { MaskLayerShape *masklayer_shape; int count = 0, count_all = 0; @@ -3396,7 +3397,7 @@ static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, boo } } - if (propedit && count > 0) + if (is_prop_edit && count > 0) return count_all; else return count; @@ -3426,7 +3427,7 @@ static void TimeToTransData(TransData *td, float *time, AnimData *adt, float ypo * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data * on the named side are used. */ -static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra, bool propedit, float ypos) +static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra, bool is_prop_edit, float ypos) { BezTriple *bezt; TransData2D *td2d = *td2dv; @@ -3437,7 +3438,7 @@ static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FC for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { /* only add selected keyframes (for now, proportional edit is not enabled) */ - if (propedit || (bezt->f2 & SELECT)) { /* note this MUST match count_fcurve_keys(), so can't use BEZSELECTED() macro */ + if (is_prop_edit || (bezt->f2 & SELECT)) { /* note this MUST match count_fcurve_keys(), so can't use BEZSELECTED() macro */ /* only add if on the right 'side' of the current frame */ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) { TimeToTransData(td, bezt->vec[1], adt, ypos); @@ -3495,14 +3496,14 @@ void flushTransIntFrameActionData(TransInfo *t) * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data * on the named side are used. */ -static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra, bool propedit, float ypos) +static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra, bool is_prop_edit, float ypos) { bGPDframe *gpf; int count = 0; /* check for select frames on right side of current frame */ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - if (propedit || (gpf->flag & GP_FRAME_SELECT)) { + if (is_prop_edit || (gpf->flag & GP_FRAME_SELECT)) { if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) { /* memory is calloc'ed, so that should zero everything nicely for us */ td->val = &tfd->val; @@ -3526,14 +3527,14 @@ static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, } /* refer to comment above #GPLayerToTransData, this is the same but for masks */ -static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra, bool propedit, float ypos) +static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra, bool is_prop_edit, float ypos) { MaskLayerShape *masklay_shape; int count = 0; /* check for select frames on right side of current frame */ for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { - if (propedit || (masklay_shape->flag & MASK_SHAPE_SELECT)) { + if (is_prop_edit || (masklay_shape->flag & MASK_SHAPE_SELECT)) { if (FrameOnMouseSide(side, (float)masklay_shape->frame, cfra)) { /* memory is calloc'ed, so that should zero everything nicely for us */ td->val = &tfd->val; @@ -3576,7 +3577,7 @@ static void createTransActionData(bContext *C, TransInfo *t) ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; - const bool propedit = (t->flag & T_PROP_EDIT) != 0; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; int count = 0; float cfra; @@ -3619,11 +3620,11 @@ static void createTransActionData(bContext *C, TransInfo *t) cfra = (float)CFRA; if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) - adt_count = count_fcurve_keys(ale->key_data, t->frame_side, cfra, propedit); + adt_count = count_fcurve_keys(ale->key_data, t->frame_side, cfra, is_prop_edit); else if (ale->type == ANIMTYPE_GPLAYER) - adt_count = count_gplayer_frames(ale->data, t->frame_side, cfra, propedit); + adt_count = count_gplayer_frames(ale->data, t->frame_side, cfra, is_prop_edit); else if (ale->type == ANIMTYPE_MASKLAYER) - adt_count = count_masklayer_frames(ale->data, t->frame_side, cfra, propedit); + adt_count = count_masklayer_frames(ale->data, t->frame_side, cfra, is_prop_edit); else BLI_assert(0); @@ -3669,7 +3670,7 @@ static void createTransActionData(bContext *C, TransInfo *t) for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt; - if (propedit && !ale->tag) + if (is_prop_edit && !ale->tag) continue; adt = ANIM_nla_mapping_get(&ac, ale); @@ -3682,7 +3683,7 @@ static void createTransActionData(bContext *C, TransInfo *t) bGPDlayer *gpl = (bGPDlayer *)ale->data; int i; - i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, propedit, ypos); + i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, is_prop_edit, ypos); td += i; tfd += i; } @@ -3690,7 +3691,7 @@ static void createTransActionData(bContext *C, TransInfo *t) MaskLayer *masklay = (MaskLayer *)ale->data; int i; - i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, propedit, ypos); + i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, is_prop_edit, ypos); td += i; tfd += i; } @@ -3698,7 +3699,7 @@ static void createTransActionData(bContext *C, TransInfo *t) AnimData *adt = ANIM_nla_mapping_get(&ac, ale); FCurve *fcu = (FCurve *)ale->key_data; - td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, propedit, ypos); + td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, is_prop_edit, ypos); } } @@ -3728,7 +3729,7 @@ static void createTransActionData(bContext *C, TransInfo *t) } /* calculate distances for proportional editing */ - if (propedit) { + if (is_prop_edit) { td = t->data; for (ale = anim_data.first; ale; ale = ale->next) { @@ -3976,7 +3977,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) const bool is_translation_mode = graph_edit_is_translation_mode(t); const bool use_handle = !(sipo->flag & SIPO_NOHANDLES); const bool use_local_center = graph_edit_use_local_center(t); - const bool propedit = (t->flag & T_PROP_EDIT) != 0; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS; /* determine what type of data we are operating on */ @@ -4030,7 +4031,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2; const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; - if (propedit) { + if (is_prop_edit) { curvecount += 3; if (sel2 || sel1 || sel3) selected = true; @@ -4054,7 +4055,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) } } - if (propedit) { + if (is_prop_edit) { if (selected) { count += curvecount; ale->tag = true; @@ -4110,7 +4111,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) float cfra; /* F-Curve may not have any keyframes */ - if (fcu->bezt == NULL || (propedit && ale->tag == 0)) + if (fcu->bezt == NULL || (is_prop_edit && ale->tag == 0)) continue; /* convert current-frame to action-time (slightly less accurate, especially under @@ -4133,7 +4134,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) TransDataCurveHandleFlags *hdata = NULL; /* short h1=1, h2=1; */ /* UNUSED */ - if (propedit) { + if (is_prop_edit) { bool is_sel = (sel2 || sel1 || sel3); /* we always select all handles for proportional editing if central handle is selected */ initTransDataCurveHandles(td, bezt); @@ -4205,7 +4206,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) testhandles_fcurve(fcu, use_handle); } - if (propedit) { + if (is_prop_edit) { /* loop 2: build transdata arrays */ td = t->data; @@ -6317,7 +6318,7 @@ static void createTransObject(bContext *C, TransInfo *t) TransData *td = NULL; TransDataExtension *tx; - int propmode = t->flag & T_PROP_EDIT; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; set_trans_object_base_flags(t); @@ -6330,7 +6331,7 @@ static void createTransObject(bContext *C, TransInfo *t) return; } - if (propmode) { + if (is_prop_edit) { t->total += count_proportional_objects(t); } @@ -6363,7 +6364,7 @@ static void createTransObject(bContext *C, TransInfo *t) } CTX_DATA_END; - if (propmode) { + if (is_prop_edit) { View3D *v3d = t->view; Base *base; @@ -7120,9 +7121,10 @@ static void MaskHandleToTransData(MaskSplinePoint *point, eMaskWhichHandle which } } -static void MaskPointToTransData(Scene *scene, MaskSplinePoint *point, - TransData *td, TransData2D *td2d, TransDataMasking *tdm, - const int propmode, const float asp[2]) +static void MaskPointToTransData( + Scene *scene, MaskSplinePoint *point, + TransData *td, TransData2D *td2d, TransDataMasking *tdm, + const bool is_prop_edit, const float asp[2]) { BezTriple *bezt = &point->bezt; const bool is_sel_point = MASKPOINT_ISSEL_KNOT(point); @@ -7132,7 +7134,7 @@ static void MaskPointToTransData(Scene *scene, MaskSplinePoint *point, BKE_mask_point_parent_matrix_get(point, CFRA, parent_matrix); invert_m3_m3(parent_inverse_matrix, parent_matrix); - if (propmode || is_sel_point) { + if (is_prop_edit || is_sel_point) { int i; tdm->point = point; @@ -7252,7 +7254,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t) TransData2D *td2d = NULL; TransDataMasking *tdm = NULL; int count = 0, countsel = 0; - int propmode = t->flag & T_PROP_EDIT; + const bool is_prop_edit = (t->flag & T_PROP_EDIT); float asp[2]; t->total = 0; @@ -7302,7 +7304,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t) } } - if (propmode) + if (is_prop_edit) count += 3; } } @@ -7315,7 +7317,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t) ED_mask_get_aspect(t->sa, t->ar, &asp[0], &asp[1]); - t->total = (propmode) ? count : countsel; + t->total = (is_prop_edit) ? count : countsel; td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Mask Editing)"); /* for each 2d uv coord a 3d vector is allocated, so that they can be * treated just as if they were 3d verts */ @@ -7338,10 +7340,10 @@ static void createTransMaskingData(bContext *C, TransInfo *t) for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - if (propmode || MASKPOINT_ISSEL_ANY(point)) { - MaskPointToTransData(scene, point, td, td2d, tdm, propmode, asp); + if (is_prop_edit || MASKPOINT_ISSEL_ANY(point)) { + MaskPointToTransData(scene, point, td, td2d, tdm, is_prop_edit, asp); - if (propmode || MASKPOINT_ISSEL_KNOT(point)) { + if (is_prop_edit || MASKPOINT_ISSEL_KNOT(point)) { td += 3; td2d += 3; tdm += 3; @@ -7584,8 +7586,8 @@ static void createTransGPencil(bContext *C, TransInfo *t) const Scene *scene = CTX_data_scene(C); const int cfra = CFRA; - const int propedit = (t->flag & T_PROP_EDIT); - const int propedit_connected = (t->flag & T_PROP_CONNECTED); + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; + const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0; /* == Grease Pencil Strokes to Transform Data == @@ -7616,9 +7618,9 @@ static void createTransGPencil(bContext *C, TransInfo *t) continue; } - if (propedit) { + if (is_prop_edit) { /* Proportional Editing... */ - if (propedit_connected) { + if (is_prop_edit_connected) { /* connected only - so only if selected */ if (gps->flag & GP_STROKE_SELECT) t->total += gps->totpoints; @@ -7725,8 +7727,8 @@ static void createTransGPencil(bContext *C, TransInfo *t) } /* What we need to include depends on proportional editing settings... */ - if (propedit) { - if (propedit_connected) { + if (is_prop_edit) { + if (is_prop_edit_connected) { /* A) "Connected" - Only those in selected strokes */ stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0; } @@ -7745,7 +7747,7 @@ static void createTransGPencil(bContext *C, TransInfo *t) bGPDspoint *pt; int i; -#if 0 /* XXX: this isn't needed anymore; cannot calculate center this way or propedit breaks */ +#if 0 /* XXX: this isn't needed anymore; cannot calculate center this way or is_prop_edit breaks */ const float ninv = 1.0f / gps->totpoints; float center[3] = {0.0f}; @@ -7760,7 +7762,7 @@ static void createTransGPencil(bContext *C, TransInfo *t) bool point_ok; /* include point? */ - if (propedit) { + if (is_prop_edit) { /* Always all points in strokes that get included */ point_ok = true; } @@ -7803,7 +7805,7 @@ static void createTransGPencil(bContext *C, TransInfo *t) } /* March over these points, and calculate the proportional editing distances */ - if (propedit && (head != tail)) { + if (is_prop_edit && (head != tail)) { /* XXX: for now, we are similar enough that this works... */ calc_distanceCurveVerts(head, tail - 1); } diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 444c579a62b..2ec7fe677ae 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -3098,9 +3098,10 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo Scene *scene = CTX_data_scene(C); ToolSettings *ts = scene->toolsettings; BMEditMesh *em = BKE_editmesh_from_object(obedit); - const int use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ? - (ts->selectmode == SCE_SELECT_FACE) : - (ts->uv_selectmode == UV_SELECT_FACE); + const bool use_face_center = ( + (ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE)); const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 1262f0af95d..f3b89f26703 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -111,8 +111,8 @@ extern "C" static struct ExrPass *imb_exr_get_pass(ListBase *lb, char *passname); static bool exr_has_multiview(MultiPartInputFile& file); static bool exr_has_multipart_file(MultiPartInputFile& file); -static int exr_has_alpha(MultiPartInputFile& file); -static int exr_has_zbuffer(MultiPartInputFile& file); +static bool exr_has_alpha(MultiPartInputFile& file); +static bool exr_has_zbuffer(MultiPartInputFile& file); static void exr_printf(const char *__restrict format, ...); static void imb_exr_type_by_channels(ChannelList& channels, StringVector& views, bool *r_singlelayer, bool *r_multilayer, bool *r_multiview); @@ -368,8 +368,8 @@ static bool imb_save_openexr_half(ImBuf *ibuf, const char *name, const int flags ImBuf * (*getbuffer)(void *base, const size_t view_id)) { const int channels = ibuf->channels; - const int is_alpha = (channels >= 4) && (ibuf->planes == 32); - const int is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ + const bool is_alpha = (channels >= 4) && (ibuf->planes == 32); + const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ const int width = ibuf->x; const int height = ibuf->y; const bool is_multiview = (flags & IB_multiview) && ibuf->userdata; @@ -485,8 +485,8 @@ static bool imb_save_openexr_float(ImBuf *ibuf, const char *name, const int flag ImBuf * (*getbuffer)(void *base, const size_t view_id)) { const int channels = ibuf->channels; - const int is_alpha = (channels >= 4) && (ibuf->planes == 32); - const int is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ + const bool is_alpha = (channels >= 4) && (ibuf->planes == 32); + const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ const int width = ibuf->x; const int height = ibuf->y; const bool is_multiview = (flags & IB_multiview) && ibuf->userdata; @@ -1266,7 +1266,7 @@ void IMB_exr_multiview_convert(void *handle, void *base, ExrLayer *lay; ExrPass *pass; ImBuf *ibuf = NULL; - const int is_alpha = exr_has_alpha(*file); + const bool is_alpha = exr_has_alpha(*file); Box2i dw = file->header(0).dataWindow(); const size_t width = dw.max.x - dw.min.x + 1; const size_t height = dw.max.y - dw.min.y + 1; @@ -1691,12 +1691,12 @@ static bool exr_has_chroma(MultiPartInputFile& file) file.header(0).channels().findChannel("RY") != NULL; } -static int exr_has_zbuffer(MultiPartInputFile& file) +static bool exr_has_zbuffer(MultiPartInputFile& file) { return !(file.header(0).channels().findChannel("Z") == NULL); } -static int exr_has_alpha(MultiPartInputFile& file) +static bool exr_has_alpha(MultiPartInputFile& file) { return !(file.header(0).channels().findChannel("A") == NULL); } diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 73206ea310c..e2df903ac95 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1009,7 +1009,7 @@ static int rna_GameObjectSettings_physics_type_get(PointerRNA *ptr) static void rna_GameObjectSettings_physics_type_set(PointerRNA *ptr, int value) { Object *ob = (Object *)ptr->id.data; - const int was_navmesh = (ob->gameflag & OB_NAVMESH); + const int gameflag_prev = ob->gameflag; ob->body_type = value; switch (ob->body_type) { @@ -1067,7 +1067,7 @@ static void rna_GameObjectSettings_physics_type_set(PointerRNA *ptr, int value) break; } - if (was_navmesh != (ob->gameflag & OB_NAVMESH)) { + if ((gameflag_prev & OB_NAVMESH) != (ob->gameflag & OB_NAVMESH)) { if (ob->type == OB_MESH) { /* this is needed to refresh the derived meshes draw func */ DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA); diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index 8a92deec8eb..542c75f3276 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -163,7 +163,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, switch (dmd->mode) { case MOD_DECIM_MODE_COLLAPSE: { - const int do_triangulate = (dmd->flag & MOD_DECIM_FLAG_TRIANGULATE) != 0; + const bool do_triangulate = (dmd->flag & MOD_DECIM_FLAG_TRIANGULATE) != 0; BM_mesh_decimate_collapse(bm, dmd->percent, vweights, do_triangulate); break; } @@ -174,7 +174,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, } case MOD_DECIM_MODE_DISSOLVE: { - const int do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0; + const bool do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0; BM_mesh_decimate_dissolve(bm, dmd->angle, do_dissolve_boundaries, (BMO_Delimit)dmd->delimit); break; } diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index 5285bc4124d..d34d68d4dee 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -94,7 +94,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, int axis) { const float tolerance_sq = mmd->tolerance * mmd->tolerance; - const int do_vtargetmap = !(mmd->flag & MOD_MIR_NO_MERGE); + const bool do_vtargetmap = (mmd->flag & MOD_MIR_NO_MERGE) != 0; int tot_vtargetmap = 0; /* total merge vertices */ DerivedMesh *result; diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index 2c9f5e32440..a9160189a7b 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -138,14 +138,14 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm = derivedData; DerivedMesh *result; ScrewModifierData *ltmd = (ScrewModifierData *) md; - const int useRenderParams = flag & MOD_APPLY_RENDER; + const bool use_render_params = (flag & MOD_APPLY_RENDER) != 0; int *origindex; int mpoly_index = 0; unsigned int step; unsigned int i, j; unsigned int i1, i2; - unsigned int step_tot = useRenderParams ? ltmd->render_steps : ltmd->steps; + unsigned int step_tot = use_render_params ? ltmd->render_steps : ltmd->steps; const bool do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0; const int quad_ord[4] = { diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index 08b8854c728..c96080d8cf9 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -255,7 +255,7 @@ static DerivedMesh *applyModifier( /* weights */ MDeformVert *dvert; - const int defgrp_invert = ((smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0); + const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0; int defgrp_index; /* array size is doubled in case of using a shell */ diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index a10386a6f41..113f1654d02 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -139,7 +139,7 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, Image *image = umd->image; MPoly *mpoly, *mp; MLoop *mloop; - int override_image = ((umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0); + const bool override_image = (umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0; Projector projectors[MOD_UVPROJECT_MAXPROJECTORS]; int num_projectors = 0; char uvname[MAX_CUSTOMDATA_LAYER_NAME]; diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index 4433922f9bb..266cfcc59a6 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -234,7 +234,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der int i; /* Flags. */ #if 0 - int do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview); + const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0; #endif /* Get number of verts. */ diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 057674f1144..390475b57f5 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -366,7 +366,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der int i; /* Flags. */ #if 0 - int do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview); + const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0; #endif #ifdef USE_TIMEIT diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c index 6ba85ea5329..de57d4e7ba6 100644 --- a/source/blender/render/intern/source/multires_bake.c +++ b/source/blender/render/intern/source/multires_bake.c @@ -127,9 +127,13 @@ typedef struct { static void multiresbake_get_normal(const MResolvePixelData *data, float norm[],const int face_num, const int vert_index) { - unsigned int indices[] = {data->mface[face_num].v1, data->mface[face_num].v2, - data->mface[face_num].v3, data->mface[face_num].v4}; - const int smoothnormal = (data->mface[face_num].flag & ME_SMOOTH); + const unsigned int indices[] = { + data->mface[face_num].v1, + data->mface[face_num].v2, + data->mface[face_num].v3, + data->mface[face_num].v4, + }; + const bool smoothnormal = (data->mface[face_num].flag & ME_SMOOTH) != 0; if (!smoothnormal) { /* flat */ if (data->precomputed_normals) { diff --git a/source/blender/render/intern/source/texture_ocean.c b/source/blender/render/intern/source/texture_ocean.c index 5261374b34d..a932123243d 100644 --- a/source/blender/render/intern/source/texture_ocean.c +++ b/source/blender/render/intern/source/texture_ocean.c @@ -73,7 +73,7 @@ int ocean_texture(Tex *tex, const float texvec[2], TexResult *texres) return 0; } else { - const int do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS); + const bool do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS) != 0; int cfra = R.r.cfra; int retval = TEX_INT; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 2280782f7bd..e79359a078e 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1843,7 +1843,7 @@ static int wm_action_not_handled(int action) static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers) { #ifndef NDEBUG - const int do_debug_handler = (G.debug & G_DEBUG_HANDLERS) && + const bool do_debug_handler = (G.debug & G_DEBUG_HANDLERS) && /* comment this out to flood the console! (if you really want to test) */ !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) ; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index cb2db94f609..434e47d344e 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -341,7 +341,9 @@ static int wm_macro_modal(bContext *C, wmOperator *op, const wmEvent *event) * */ if (op->opm->type->flag & OPTYPE_BLOCKING) { int bounds[4] = {-1, -1, -1, -1}; - int wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) && ((op->opm->flag & OP_GRAB_POINTER) || (op->opm->type->flag & OPTYPE_GRAB_POINTER)); + const bool wrap = ( + (U.uiflag & USER_CONTINUOUS_MOUSE) && + ((op->opm->flag & OP_GRAB_POINTER) || (op->opm->type->flag & OPTYPE_GRAB_POINTER))); if (wrap) { ARegion *ar = CTX_wm_region(C); -- cgit v1.2.3 From 60e8e2013246e2c6b9675a9d7e634fe1c1ba9e75 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 20 Apr 2015 23:39:54 +1000 Subject: Cleanup: use macro for common view3d zbuf check --- source/blender/editors/include/ED_view3d.h | 5 +++-- source/blender/editors/mesh/editmesh_select.c | 12 ++++++------ source/blender/editors/physics/particle_edit.c | 6 +++--- source/blender/editors/space_view3d/view3d_draw.c | 6 +++--- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 50199ade929..94399c24a15 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -344,8 +344,6 @@ bool ED_view3d_lock(struct RegionView3D *rv3d); uint64_t ED_view3d_datamask(const struct Scene *scene, const struct View3D *v3d); uint64_t ED_view3d_screen_datamask(const struct bScreen *screen); -bool ED_view3d_view_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d); - bool ED_view3d_offset_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d); /* camera lock functions */ @@ -392,4 +390,7 @@ void ED_view3d_operator_properties_viewmat_get(struct wmOperator *op, int *winx, void ED_view3d_stop_render_preview(struct wmWindowManager *wm, struct ARegion *ar); void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View3D *v3d, struct ScrArea *sa); +#define V3D_IS_ZBUF(v3d) \ + (((v3d)->flag & V3D_ZBUF_SELECT) && ((v3d)->drawtype > OB_WIRE)) + #endif /* __ED_VIEW3D_H__ */ diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index d5e60cfd7fd..403a80ee6f4 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -196,7 +196,7 @@ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xma unsigned int *dr; int a; - if (vc->obedit == NULL || vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) { + if (vc->obedit == NULL || !V3D_IS_ZBUF(vc->v3d)) { return false; } @@ -271,7 +271,7 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short return false; } } - else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) { + else if (!V3D_IS_ZBUF(vc->v3d)) { return false; } @@ -320,7 +320,7 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) return false; } } - else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) { + else if (!V3D_IS_ZBUF(vc->v3d)) { return false; } @@ -402,7 +402,7 @@ BMVert *EDBM_vert_find_nearest( ViewContext *vc, float *r_dist, const bool use_select_bias, const bool is_strict) { - if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) { + if (V3D_IS_ZBUF(vc->v3d)) { float distance; unsigned int index; BMVert *eve; @@ -502,7 +502,7 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) { - if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) { + if (V3D_IS_ZBUF(vc->v3d)) { float distance; unsigned int index; BMEdge *eed; @@ -576,7 +576,7 @@ static void findnearestface__doClosest(void *userData, BMFace *efa, const float BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) { - if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) { + if (V3D_IS_ZBUF(vc->v3d)) { unsigned int index; BMFace *efa; diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index a0420dfa46e..04764aaa978 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -400,7 +400,7 @@ static void PE_set_view3d_data(bContext *C, PEData *data) /* note, the object argument means the modelview matrix does not account for the objects matrix, use viewmat rather than (obmat * viewmat) */ view3d_get_transformation(data->vc.ar, data->vc.rv3d, NULL, &data->mats); - if ((data->vc.v3d->drawtype>OB_WIRE) && (data->vc.v3d->flag & V3D_ZBUF_SELECT)) { + if (V3D_IS_ZBUF(data->vc.v3d)) { if (data->vc.v3d->flag & V3D_INVALID_BACKBUF) { /* needed or else the draw matrix can be incorrect */ view3d_operator_needs_opengl(C); @@ -443,8 +443,8 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[ float depth; /* nothing to do */ - if ((v3d->drawtype<=OB_WIRE) || (v3d->flag & V3D_ZBUF_SELECT)==0) - return 1; + if (!V3D_IS_ZBUF(v3d)) + return true; /* used to calculate here but all callers have the screen_co already, so pass as arg */ #if 0 diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index bfb4f60cdff..39e21e297e8 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1327,12 +1327,12 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d) /* do nothing */ } else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) && - v3d->drawtype > OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT)) + V3D_IS_ZBUF(v3d)) { /* do nothing */ } - else if (scene->obedit && v3d->drawtype > OB_WIRE && - (v3d->flag & V3D_ZBUF_SELECT)) + else if (scene->obedit && + V3D_IS_ZBUF(v3d)) { /* do nothing */ } -- cgit v1.2.3 From 0626d27bf62e41bf34191d011fe0e52a4c622ec6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 21 Apr 2015 01:33:09 +1000 Subject: Editmesh select nearest fixes - distance from edge check wasn't clamping 0-1 - vertex bias wasn't taking pixelsize into account. - index & pass counter were floats Also some improvements - use BMesh lookup tables when available. - use structs to avoid issues getting out of sync. --- source/blender/bmesh/intern/bmesh_mesh.c | 35 +++++ source/blender/bmesh/intern/bmesh_mesh.h | 4 + source/blender/editors/mesh/editmesh_select.c | 184 +++++++++++++++++--------- 3 files changed, 157 insertions(+), 66 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 9a2869b64ef..ba08f9eab25 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -1379,6 +1379,41 @@ BMFace *BM_face_at_index_find(BMesh *bm, const int index) return BLI_mempool_findelem(bm->fpool, index); } +/** + * Use lookup table when available, else use slower find functions. + * + * \note Try to use #BM_mesh_elem_table_ensure instead. + */ +BMVert *BM_vert_at_index_find_or_table(BMesh *bm, const int index) +{ + if ((bm->elem_table_dirty & BM_VERT) == 0) { + return (index < bm->totvert) ? bm->vtable[index] : NULL; + } + else { + return BM_vert_at_index_find(bm, index); + } +} + +BMEdge *BM_edge_at_index_find_or_table(BMesh *bm, const int index) +{ + if ((bm->elem_table_dirty & BM_EDGE) == 0) { + return (index < bm->totedge) ? bm->etable[index] : NULL; + } + else { + return BM_edge_at_index_find(bm, index); + } +} + +BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index) +{ + if ((bm->elem_table_dirty & BM_FACE) == 0) { + return (index < bm->totface) ? bm->ftable[index] : NULL; + } + else { + return BM_face_at_index_find(bm, index); + } +} + /** * Return the amount of element of type 'type' in a given bmesh. diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index bac5da8347e..59feea2e2ff 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -68,6 +68,10 @@ BMVert *BM_vert_at_index_find(BMesh *bm, const int index); BMEdge *BM_edge_at_index_find(BMesh *bm, const int index); BMFace *BM_face_at_index_find(BMesh *bm, const int index); +BMVert *BM_vert_at_index_find_or_table(BMesh *bm, const int index); +BMEdge *BM_edge_at_index_find_or_table(BMesh *bm, const int index); +BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index); + // XXX int BM_mesh_elem_count(BMesh *bm, const char htype); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 403a80ee6f4..80b60c4fa42 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -350,23 +350,42 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) } + +/* -------------------------------------------------------------------- */ + +/** \name Find Nearest Vert/Edge/Face + * \{ */ + +#define FIND_NEAR_THRESHOLD_MIN 3 + +struct NearestVertUserData { + float mval_fl[2]; + int pass; + char hflag_select; + bool is_strict; + float dist; + int index_last; + int index_nearest; + BMVert *vert_nearest; +}; + static void findnearestvert__doClosest(void *userData, BMVert *eve, const float screen_co[2], int index) { - struct { float mval_fl[2], pass, select, strict; float dist, lastIndex, closestIndex; BMVert *closest; } *data = userData; + struct NearestVertUserData *data = userData; if (data->pass == 0) { - if (index <= data->lastIndex) + if (index <= data->index_last) return; } else { - if (index > data->lastIndex) + if (index > data->index_last) return; } - if (data->dist > 3) { + if (data->dist > FIND_NEAR_THRESHOLD_MIN) { float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); - if (BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->select) { - if (data->strict == 1) { + if (BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->hflag_select) { + if (data->is_strict == true) { return; } else { @@ -376,8 +395,8 @@ static void findnearestvert__doClosest(void *userData, BMVert *eve, const float if (dist_test < data->dist) { data->dist = dist_test; - data->closest = eve; - data->closestIndex = index; + data->vert_nearest = eve; + data->index_nearest = index; } } } @@ -402,6 +421,8 @@ BMVert *EDBM_vert_find_nearest( ViewContext *vc, float *r_dist, const bool use_select_bias, const bool is_strict) { + BMesh *bm = vc->em->bm; + if (V3D_IS_ZBUF(vc->v3d)) { float distance; unsigned int index; @@ -418,7 +439,7 @@ BMVert *EDBM_vert_find_nearest( 0, NULL, NULL); } - eve = index ? BM_vert_at_index_find(vc->em->bm, index - 1) : NULL; + eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; if (eve && distance < *r_dist) { *r_dist = distance; @@ -427,26 +448,26 @@ BMVert *EDBM_vert_find_nearest( else { return NULL; } - } else { - struct { float mval_fl[2], pass, select, strict; float dist, lastIndex, closestIndex; BMVert *closest; } data; - static int lastSelectedIndex = 0; - static BMVert *lastSelected = NULL; - - if (lastSelected && BM_vert_at_index_find(vc->em->bm, lastSelectedIndex) != lastSelected) { - lastSelectedIndex = 0; - lastSelected = NULL; + struct NearestVertUserData data; + + static int prev_select_index = 0; + static const BMVert *prev_select_elem = NULL; + + if (prev_select_elem && (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index))) { + prev_select_index = 0; + prev_select_elem = NULL; } - data.lastIndex = lastSelectedIndex; + data.index_last = prev_select_index; data.mval_fl[0] = vc->mval[0]; data.mval_fl[1] = vc->mval[1]; - data.select = use_select_bias ? BM_ELEM_SELECT : 0; + data.hflag_select = use_select_bias ? BM_ELEM_SELECT : 0; data.dist = *r_dist; - data.strict = is_strict; - data.closest = NULL; - data.closestIndex = 0; + data.is_strict = is_strict; + data.vert_nearest = NULL; + data.index_nearest = 0; data.pass = 0; @@ -454,23 +475,30 @@ BMVert *EDBM_vert_find_nearest( mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - if (data.dist > 3) { + if (data.dist > FIND_NEAR_THRESHOLD_MIN) { data.pass = 1; mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } *r_dist = data.dist; - lastSelected = data.closest; - lastSelectedIndex = data.closestIndex; + prev_select_elem = data.vert_nearest; + prev_select_index = data.index_nearest; - return data.closest; + return data.vert_nearest; } } +struct NearestEdgeUserData { + ViewContext vc; + float mval_fl[2]; + float dist; + BMEdge *edge_nearest; +}; + /* note; uses v3d, so needs active 3d window */ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index)) { - struct { ViewContext vc; float mval_fl[2]; float dist; BMEdge *closest; } *data = userData; + struct NearestEdgeUserData *data = userData; int distance; distance = dist_to_line_segment_v2(data->mval_fl, screen_co_a, screen_co_b); @@ -481,26 +509,26 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float if (distance < data->dist) { if (data->vc.rv3d->rflag & RV3D_CLIPPING) { - float lambda = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b); + float fac = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b); float vec[3]; - vec[0] = eed->v1->co[0] + lambda * (eed->v2->co[0] - eed->v1->co[0]); - vec[1] = eed->v1->co[1] + lambda * (eed->v2->co[1] - eed->v1->co[1]); - vec[2] = eed->v1->co[2] + lambda * (eed->v2->co[2] - eed->v1->co[2]); - + CLAMP(fac, 0, 1); + interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac); if (ED_view3d_clipping_test(data->vc.rv3d, vec, true) == 0) { data->dist = distance; - data->closest = eed; + data->edge_nearest = eed; } } else { data->dist = distance; - data->closest = eed; + data->edge_nearest = eed; } } } + BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) { + BMesh *bm = vc->em->bm; if (V3D_IS_ZBUF(vc->v3d)) { float distance; @@ -510,7 +538,7 @@ BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) view3d_validate_backbuf(vc); index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_solidoffs, bm_wireoffs, &distance, 0, NULL, NULL); - eed = index ? BM_edge_at_index_find(vc->em->bm, index - 1) : NULL; + eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; if (eed && distance < *r_dist) { *r_dist = distance; @@ -521,27 +549,42 @@ BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) } } else { - struct { ViewContext vc; float mval_fl[2]; float dist; BMEdge *closest; } data; + struct NearestEdgeUserData data; data.vc = *vc; data.mval_fl[0] = vc->mval[0]; data.mval_fl[1] = vc->mval[1]; data.dist = *r_dist; - data.closest = NULL; + data.edge_nearest = NULL; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, V3D_PROJ_TEST_CLIP_WIN); *r_dist = data.dist; - return data.closest; + return data.edge_nearest; } } -static void findnearestface__getDistance(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index)) +struct NearestFaceUserData_ZBuf { + float mval_fl[2]; + float dist; + const BMFace *face_test; +}; + +struct NearestFaceUserData_Closest { + float mval_fl[2]; + int pass; + float dist; + int index_last; + int index_nearest; + BMFace *face_nearest; +}; + +static void findnearestface__doZBuf(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index)) { - struct { float mval_fl[2]; float dist; BMFace *toFace; } *data = userData; + struct NearestFaceUserData_ZBuf *data = userData; - if (efa == data->toFace) { + if (efa == data->face_test) { const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); if (dist_test < data->dist) { @@ -549,32 +592,35 @@ static void findnearestface__getDistance(void *userData, BMFace *efa, const floa } } } + + static void findnearestface__doClosest(void *userData, BMFace *efa, const float screen_co[2], int index) { - struct { float mval_fl[2], pass; float dist, lastIndex, closestIndex; BMFace *closest; } *data = userData; + struct NearestFaceUserData_Closest *data = userData; if (data->pass == 0) { - if (index <= data->lastIndex) + if (index <= data->index_last) return; } else { - if (index > data->lastIndex) + if (index > data->index_last) return; } - if (data->dist > 3) { + if (data->dist > FIND_NEAR_THRESHOLD_MIN) { const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); if (dist_test < data->dist) { data->dist = dist_test; - data->closest = efa; - data->closestIndex = index; + data->face_nearest = efa; + data->index_nearest = index; } } } BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) { + BMesh *bm = vc->em->bm; if (V3D_IS_ZBUF(vc->v3d)) { unsigned int index; @@ -583,19 +629,19 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) view3d_validate_backbuf(vc); index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]); - efa = index ? BM_face_at_index_find(vc->em->bm, index - 1) : NULL; + efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL; if (efa) { - struct { float mval_fl[2]; float dist; BMFace *toFace; } data; + struct NearestFaceUserData_ZBuf data; data.mval_fl[0] = vc->mval[0]; data.mval_fl[1] = vc->mval[1]; data.dist = FLT_MAX; - data.toFace = efa; + data.face_test = efa; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenFace(vc, findnearestface__getDistance, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenFace(vc, findnearestface__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); if ((vc->em->selectmode == SCE_SELECT_FACE) || (data.dist < *r_dist)) { /* only faces, no dist check */ *r_dist = data.dist; @@ -606,39 +652,40 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) return NULL; } else { - struct { float mval_fl[2], pass; float dist, lastIndex, closestIndex; BMFace *closest; } data; - static int lastSelectedIndex = 0; - static BMFace *lastSelected = NULL; + struct NearestFaceUserData_Closest data; + static int prev_select_index = 0; + static const BMFace *prev_select_elem = NULL; - if (lastSelected && BM_face_at_index_find(vc->em->bm, lastSelectedIndex) != lastSelected) { - lastSelectedIndex = 0; - lastSelected = NULL; + if (prev_select_elem && (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index))) { + prev_select_index = 0; + prev_select_elem = NULL; } - data.lastIndex = lastSelectedIndex; + data.index_last = prev_select_index; data.mval_fl[0] = vc->mval[0]; data.mval_fl[1] = vc->mval[1]; data.dist = *r_dist; - data.closest = NULL; - data.closestIndex = 0; + data.face_nearest = NULL; + data.index_nearest = 0; data.pass = 0; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - if (data.dist > 3.0f) { + if (data.dist > FIND_NEAR_THRESHOLD_MIN) { data.pass = 1; mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } *r_dist = data.dist; - lastSelected = data.closest; - lastSelectedIndex = data.closestIndex; + prev_select_elem = data.face_nearest; + prev_select_index = data.index_nearest; - return data.closest; + return data.face_nearest; } } + /* best distance based on screen coords. * use em->selectmode to define how to use * selected vertices and edges get disadvantage @@ -647,7 +694,8 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa) { BMEditMesh *em = vc->em; - float dist = ED_view3d_select_dist_px(); + const float dist_init = ED_view3d_select_dist_px(); + float dist = dist_init; *r_eve = NULL; *r_eed = NULL; @@ -661,7 +709,8 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, if (em->selectmode & SCE_SELECT_FACE) *r_efa = EDBM_face_find_nearest(vc, &dist); - dist -= 20; /* since edges select lines, we give dots advantage of 20 pix */ + /* since edges select lines, we give dots advantage of 20 pix */ + dist -= dist_init / 3.75f; if (em->selectmode & SCE_SELECT_EDGE) *r_eed = EDBM_edge_find_nearest(vc, &dist); @@ -676,6 +725,9 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, return (*r_eve || *r_eed || *r_efa); } +/** \} */ + + /* **************** SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */ static EnumPropertyItem prop_similar_compare_types[] = { {SIM_CMP_EQ, "EQUAL", 0, "Equal", ""}, -- cgit v1.2.3 From d57a93a7cb4d54e1ce0d890540926ef6ab88270a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 21 Apr 2015 02:06:20 +1000 Subject: Fix T44383: Select face fails in some positions When mixing vert/edge/face with select-visible, face selection could fail when not close enough to the center. This also fixes a bug where the bias for verts over edges would prefer faces over edges too, making edges harder to pick. Mixing edge with other selection modes works more predictably now. --- source/blender/editors/include/ED_mesh.h | 15 +++- source/blender/editors/include/ED_view3d.h | 1 + source/blender/editors/mesh/editmesh_path.c | 2 +- source/blender/editors/mesh/editmesh_select.c | 89 +++++++++++++++++------ source/blender/editors/space_view3d/view3d_draw.c | 9 +++ 5 files changed, 88 insertions(+), 28 deletions(-) diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index f8be5251b53..91b05cdc1ba 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -137,11 +137,20 @@ bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2] short xmin, short ymin, short xmax, short ymax); bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads); -struct BMVert *EDBM_vert_find_nearest( +struct BMVert *EDBM_vert_find_nearest_ex( struct ViewContext *vc, float *r_dist, const bool use_select_bias, const bool is_strict); -struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, float *r_dist); -struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, float *r_dist); +struct BMVert *EDBM_vert_find_nearest( + struct ViewContext *vc, float *r_dist); + +struct BMEdge *EDBM_edge_find_nearest( + struct ViewContext *vc, float *r_dist); + +struct BMFace *EDBM_face_find_nearest_ex( + struct ViewContext *vc, float *r_dist, + struct BMFace **r_efa_zbuf); +struct BMFace *EDBM_face_find_nearest( + struct ViewContext *vc, float *r_dist); bool EDBM_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 94399c24a15..e5ac8c2f46a 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -273,6 +273,7 @@ unsigned int view3d_sample_backbuf_rect( struct ViewContext *vc, const int mval[2], int size, unsigned int min, unsigned int max, float *dist, const bool is_strict, void *handle, bool (*indextest)(void *handle, unsigned int index)); +int view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist); unsigned int view3d_sample_backbuf(struct ViewContext *vc, int x, int y); /* draws and does a 4x4 sample */ diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index 4eaac6cc1d3..72dfb89e5f3 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -94,7 +94,7 @@ static bool mouse_mesh_shortest_path_vert(ViewContext *vc) float dist = ED_view3d_select_dist_px(); const bool use_length = true; - v_dst = EDBM_vert_find_nearest(vc, &dist, false, false); + v_dst = EDBM_vert_find_nearest(vc, &dist); if (v_dst) { struct UserData user_data = {bm, vc->obedit->data, vc->scene}; LinkNode *path = NULL; diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 80b60c4fa42..244cfe28da6 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -417,25 +417,26 @@ static bool findnearestvert__backbufIndextest(void *handle, unsigned int index) * - When false, unselected vertice are given the bias. * \param is_strict When true, the vertice corresponding to the sel parameter are ignored and not just biased */ -BMVert *EDBM_vert_find_nearest( +BMVert *EDBM_vert_find_nearest_ex( ViewContext *vc, float *r_dist, const bool use_select_bias, const bool is_strict) { BMesh *bm = vc->em->bm; if (V3D_IS_ZBUF(vc->v3d)) { + const int dist_px = view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); float distance; unsigned int index; BMVert *eve; if (is_strict) { index = view3d_sample_backbuf_rect( - vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, + vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &distance, is_strict, vc->em, findnearestvert__backbufIndextest); } else { index = view3d_sample_backbuf_rect( - vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, + vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &distance, 0, NULL, NULL); } @@ -488,6 +489,12 @@ BMVert *EDBM_vert_find_nearest( } } +BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist) +{ + return EDBM_vert_find_nearest_ex(vc, r_dist, false, false); +} + + struct NearestEdgeUserData { ViewContext vc; float mval_fl[2]; @@ -531,13 +538,14 @@ BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) BMesh *bm = vc->em->bm; if (V3D_IS_ZBUF(vc->v3d)) { + const int dist_px = view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); float distance; unsigned int index; BMEdge *eed; view3d_validate_backbuf(vc); - - index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_solidoffs, bm_wireoffs, &distance, 0, NULL, NULL); + + index = view3d_sample_backbuf_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &distance, 0, NULL, NULL); eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; if (eed && distance < *r_dist) { @@ -618,7 +626,10 @@ static void findnearestface__doClosest(void *userData, BMFace *efa, const float } } -BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) + +BMFace *EDBM_face_find_nearest_ex( + ViewContext *vc, float *r_dist, + BMFace **r_efa_zbuf) { BMesh *bm = vc->em->bm; @@ -631,6 +642,10 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]); efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL; + if (r_efa_zbuf) { + *r_efa_zbuf = efa; + } + if (efa) { struct NearestFaceUserData_ZBuf data; @@ -685,6 +700,11 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) } } +BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) +{ + return EDBM_face_find_nearest_ex(vc, r_dist, NULL); +} + /* best distance based on screen coords. * use em->selectmode to define how to use @@ -695,34 +715,55 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, { BMEditMesh *em = vc->em; const float dist_init = ED_view3d_select_dist_px(); + /* since edges select lines, we give dots advantage of 20 pix */ + const float dist_edge_bias = (dist_init / 3.75f); float dist = dist_init; + float dist_vert = dist_init; + BMFace *efa_zbuf = NULL; - *r_eve = NULL; - *r_eed = NULL; - *r_efa = NULL; + BMVert *eve = NULL; + BMEdge *eed = NULL; + BMFace *efa = NULL; /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ view3d_validate_backbuf(vc); - - if (em->selectmode & SCE_SELECT_VERTEX) - *r_eve = EDBM_vert_find_nearest(vc, &dist, true, false); - if (em->selectmode & SCE_SELECT_FACE) - *r_efa = EDBM_face_find_nearest(vc, &dist); - /* since edges select lines, we give dots advantage of 20 pix */ - dist -= dist_init / 3.75f; - if (em->selectmode & SCE_SELECT_EDGE) - *r_eed = EDBM_edge_find_nearest(vc, &dist); + if (em->selectmode & SCE_SELECT_VERTEX) { + eve = EDBM_vert_find_nearest_ex(vc, &dist, true, false); + dist_vert = dist; + } + + if (em->selectmode & SCE_SELECT_FACE) { + efa = EDBM_face_find_nearest_ex(vc, &dist, eve ? &efa_zbuf : NULL); + } + + /* distance bias from verts (not faces) */ + dist = min_ff(dist, dist_vert - dist_edge_bias); + if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) { + eed = EDBM_edge_find_nearest(vc, &dist); + } /* return only one of 3 pointers, for frontbuffer redraws */ - if (*r_eed) { - *r_efa = NULL; *r_eve = NULL; + if (eed) { + efa = NULL; eve = NULL; } - else if (*r_efa) { - *r_eve = NULL; + else if (efa) { + eve = NULL; } - - return (*r_eve || *r_eed || *r_efa); + + /* there may be a face under the cursor, but who's center if too far away + * use this if all else fails, it makes sense to select this */ + if ((eve || eed || efa) == 0) { + if (efa_zbuf) { + efa = efa_zbuf; + } + } + + *r_eve = eve; + *r_eed = eed; + *r_efa = efa; + + return (eve || eed || efa); } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 39e21e297e8..6cfc6ae4ddd 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1460,6 +1460,15 @@ void view3d_validate_backbuf(ViewContext *vc) backdrawview3d(vc->scene, vc->ar, vc->v3d); } +/** + * allow for small values [0.5 - 2.5], + * and large values, FLT_MAX by clamping by the area size + */ +int view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) +{ + return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); +} + /* samples a single pixel (copied from vpaint) */ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y) { -- cgit v1.2.3 From aa880bb815e7707255f7d450f4add1b042f119fa Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 21 Apr 2015 03:19:27 +1000 Subject: Cleanup: use ED_view3d_backbuf_* prefix --- source/blender/editors/include/ED_view3d.h | 10 ++++----- source/blender/editors/mesh/editface.c | 2 +- source/blender/editors/mesh/editmesh_select.c | 26 +++++++++++----------- source/blender/editors/mesh/meshtools.c | 8 +++---- source/blender/editors/physics/particle_edit.c | 2 +- source/blender/editors/sculpt_paint/paint_utils.c | 2 +- source/blender/editors/sculpt_paint/paint_vertex.c | 2 +- source/blender/editors/space_view3d/view3d_draw.c | 17 +++++++------- .../blender/editors/space_view3d/view3d_select.c | 2 +- 9 files changed, 36 insertions(+), 35 deletions(-) diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index e5ac8c2f46a..f68b52d9a6e 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -267,14 +267,14 @@ float ED_view3d_radius_to_dist( void drawcircball(int mode, const float cent[3], float rad, float tmat[4][4]); /* backbuffer select and draw support */ -void view3d_validate_backbuf(struct ViewContext *vc); -struct ImBuf *view3d_read_backbuf(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax); -unsigned int view3d_sample_backbuf_rect( +void ED_view3d_backbuf_validate(struct ViewContext *vc); +struct ImBuf *ED_view3d_backbuf_read(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax); +unsigned int ED_view3d_backbuf_sample_rect( struct ViewContext *vc, const int mval[2], int size, unsigned int min, unsigned int max, float *dist, const bool is_strict, void *handle, bool (*indextest)(void *handle, unsigned int index)); -int view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist); -unsigned int view3d_sample_backbuf(struct ViewContext *vc, int x, int y); +int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist); +unsigned int ED_view3d_backbuf_sample(struct ViewContext *vc, int x, int y); /* draws and does a 4x4 sample */ bool ED_view3d_autodist(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 113f0f71b53..35fc4483702 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -446,7 +446,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool exten } } - view3d_validate_backbuf(vc); + ED_view3d_backbuf_validate(vc); ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect); rt = ibuf->rect; diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 244cfe28da6..a3a61c30aeb 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -200,7 +200,7 @@ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xma return false; } - buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); + buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); if (buf == NULL) return false; if (bm_vertoffs == 0) return false; @@ -275,7 +275,7 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short return false; } - buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); + buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); if (buf == NULL) return false; if (bm_vertoffs == 0) return false; @@ -326,7 +326,7 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) xmin = xs - rads; xmax = xs + rads; ymin = ys - rads; ymax = ys + rads; - buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); + buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); if (bm_vertoffs == 0) return false; if (buf == NULL) return false; @@ -424,18 +424,18 @@ BMVert *EDBM_vert_find_nearest_ex( BMesh *bm = vc->em->bm; if (V3D_IS_ZBUF(vc->v3d)) { - const int dist_px = view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); + const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); float distance; unsigned int index; BMVert *eve; if (is_strict) { - index = view3d_sample_backbuf_rect( + index = ED_view3d_backbuf_sample_rect( vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &distance, is_strict, vc->em, findnearestvert__backbufIndextest); } else { - index = view3d_sample_backbuf_rect( + index = ED_view3d_backbuf_sample_rect( vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &distance, 0, NULL, NULL); } @@ -538,14 +538,14 @@ BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) BMesh *bm = vc->em->bm; if (V3D_IS_ZBUF(vc->v3d)) { - const int dist_px = view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); + const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); float distance; unsigned int index; BMEdge *eed; - view3d_validate_backbuf(vc); + ED_view3d_backbuf_validate(vc); - index = view3d_sample_backbuf_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &distance, 0, NULL, NULL); + index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &distance, 0, NULL, NULL); eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; if (eed && distance < *r_dist) { @@ -637,9 +637,9 @@ BMFace *EDBM_face_find_nearest_ex( unsigned int index; BMFace *efa; - view3d_validate_backbuf(vc); + ED_view3d_backbuf_validate(vc); - index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]); + index = ED_view3d_backbuf_sample(vc, vc->mval[0], vc->mval[1]); efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL; if (r_efa_zbuf) { @@ -726,7 +726,7 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, BMFace *efa = NULL; /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ - view3d_validate_backbuf(vc); + ED_view3d_backbuf_validate(vc); if (em->selectmode & SCE_SELECT_VERTEX) { eve = EDBM_vert_find_nearest_ex(vc, &dist, true, false); @@ -1383,7 +1383,7 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de em = vc.em; /* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */ - view3d_validate_backbuf(&vc); + ED_view3d_backbuf_validate(&vc); eed = EDBM_edge_find_nearest(&vc, &dist); if (eed == NULL) { diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 00d79b22e99..acd745637d2 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -1082,11 +1082,11 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int * on an edge in the backbuf, we can still select a face */ float dummy_dist; - *index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist, 0, NULL, NULL); + *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist, 0, NULL, NULL); } else { /* sample only on the exact position */ - *index = view3d_sample_backbuf(&vc, mval[0], mval[1]); + *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]); } if ((*index) == 0 || (*index) > (unsigned int)me->totpoly) @@ -1248,11 +1248,11 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int * on an face in the backbuf, we can still select a vert */ float dummy_dist; - *index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist, 0, NULL, NULL); + *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist, 0, NULL, NULL); } else { /* sample only on the exact position */ - *index = view3d_sample_backbuf(&vc, mval[0], mval[1]); + *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]); } if ((*index) == 0 || (*index) > (unsigned int)me->totvert) diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 04764aaa978..7abd6f4c8ef 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -405,7 +405,7 @@ static void PE_set_view3d_data(bContext *C, PEData *data) /* needed or else the draw matrix can be incorrect */ view3d_operator_needs_opengl(C); - view3d_validate_backbuf(&data->vc); + ED_view3d_backbuf_validate(&data->vc); /* we may need to force an update here by setting the rv3d as dirty * for now it seems ok, but take care!: * rv3d->depths->dirty = 1; */ diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index b19cced2f8e..f1edf8a5fd9 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -379,7 +379,7 @@ static int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int * return 0; /* sample only on the exact position */ - *r_index = view3d_sample_backbuf(vc, mval[0], mval[1]); + *r_index = ED_view3d_backbuf_sample(vc, mval[0], mval[1]); if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) { return 0; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 2a7e736417d..1a31442faf4 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -878,7 +878,7 @@ static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x * brushes with size > 64, why is this here? */ /*if (size > 64.0) size = 64.0;*/ - ibuf = view3d_read_backbuf(vc, x - size, y - size, x + size, y + size); + ibuf = ED_view3d_backbuf_read(vc, x - size, y - size, x + size, y + size); if (ibuf) { unsigned int *rt = ibuf->rect; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 6cfc6ae4ddd..678daa6dd88 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1454,7 +1454,7 @@ static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); } -void view3d_validate_backbuf(ViewContext *vc) +void ED_view3d_backbuf_validate(ViewContext *vc) { if (vc->v3d->flag & V3D_INVALID_BACKBUF) backdrawview3d(vc->scene, vc->ar, vc->v3d); @@ -1464,13 +1464,13 @@ void view3d_validate_backbuf(ViewContext *vc) * allow for small values [0.5 - 2.5], * and large values, FLT_MAX by clamping by the area size */ -int view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) +int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) { return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); } /* samples a single pixel (copied from vpaint) */ -unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y) +unsigned int ED_view3d_backbuf_sample(ViewContext *vc, int x, int y) { unsigned int col; @@ -1478,7 +1478,7 @@ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y) return 0; } - view3d_validate_backbuf(vc); + ED_view3d_backbuf_validate(vc); view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); glReadBuffer(GL_BACK); @@ -1491,7 +1491,7 @@ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y) } /* reads full rect, converts indices */ -ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) +ImBuf *ED_view3d_backbuf_read(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) { unsigned int *dr, *rd; struct ImBuf *ibuf, *ibuf1; @@ -1510,7 +1510,7 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, ibuf = IMB_allocImBuf((xmaxc - xminc + 1), (ymaxc - yminc + 1), 32, IB_rect); - view3d_validate_backbuf(vc); + ED_view3d_backbuf_validate(vc); view3d_opengl_read_pixels(vc->ar, xminc, yminc, @@ -1550,7 +1550,8 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, } /* smart function to sample a rect spiralling outside, nice for backbuf selection */ -unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int size, +unsigned int ED_view3d_backbuf_sample_rect( + ViewContext *vc, const int mval[2], int size, unsigned int min, unsigned int max, float *r_dist, const bool is_strict, void *handle, bool (*indextest)(void *handle, unsigned int index)) { @@ -1566,7 +1567,7 @@ unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int minx = mval[0] - (amount + 1); miny = mval[1] - (amount + 1); - buf = view3d_read_backbuf(vc, minx, miny, minx + size - 1, miny + size - 1); + buf = ED_view3d_backbuf_read(vc, minx, miny, minx + size - 1, miny + size - 1); if (!buf) return 0; rc = 0; diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 587dac722e4..49e42cf164a 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1662,7 +1662,7 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, boo if (use_zbuf) { selar = MEM_callocN(me->totvert + 1, "selar"); - view3d_validate_backbuf(vc); + ED_view3d_backbuf_validate(vc); ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect); rt = ibuf->rect; -- cgit v1.2.3 From 62e149881a311e2f2b41131eb201d86a59031c77 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 21 Apr 2015 04:45:26 +1000 Subject: Fixes for backbuf selection logic - Fix ED_view3d_backbuf_sample_rect, r_dist was set completely wrong. - Avoid duplicate calculations picking the nearest edge. - Bias against picking selected edges is now optional. - Remove unused callback reading the backbuf. - Remove unused strict option picking vertices. --- source/blender/editors/include/ED_mesh.h | 5 +- source/blender/editors/include/ED_view3d.h | 3 +- source/blender/editors/mesh/editmesh_select.c | 88 ++++++++++++----------- source/blender/editors/mesh/meshtools.c | 4 +- source/blender/editors/space_view3d/view3d_draw.c | 34 +++++---- 5 files changed, 69 insertions(+), 65 deletions(-) diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 91b05cdc1ba..3c672362a54 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -139,10 +139,13 @@ bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short struct BMVert *EDBM_vert_find_nearest_ex( struct ViewContext *vc, float *r_dist, - const bool use_select_bias, const bool is_strict); + const bool use_select_bias); struct BMVert *EDBM_vert_find_nearest( struct ViewContext *vc, float *r_dist); +struct BMEdge *EDBM_edge_find_nearest_ex( + struct ViewContext *vc, float *r_dist, + const bool use_select_bias); struct BMEdge *EDBM_edge_find_nearest( struct ViewContext *vc, float *r_dist); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index f68b52d9a6e..6be7f706f28 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -271,8 +271,7 @@ void ED_view3d_backbuf_validate(struct ViewContext *vc); struct ImBuf *ED_view3d_backbuf_read(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax); unsigned int ED_view3d_backbuf_sample_rect( struct ViewContext *vc, const int mval[2], int size, - unsigned int min, unsigned int max, float *dist, const bool is_strict, - void *handle, bool (*indextest)(void *handle, unsigned int index)); + unsigned int min, unsigned int max, float *dist); int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist); unsigned int ED_view3d_backbuf_sample(struct ViewContext *vc, int x, int y); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index a3a61c30aeb..84ca945bf48 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -357,12 +357,12 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) * \{ */ #define FIND_NEAR_THRESHOLD_MIN 3 +#define FIND_NEAR_BIAS 5 struct NearestVertUserData { float mval_fl[2]; int pass; - char hflag_select; - bool is_strict; + bool use_select_bias; float dist; int index_last; int index_nearest; @@ -384,13 +384,9 @@ static void findnearestvert__doClosest(void *userData, BMVert *eve, const float if (data->dist > FIND_NEAR_THRESHOLD_MIN) { float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); - if (BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->hflag_select) { - if (data->is_strict == true) { - return; - } - else { - dist_test += 5; - } + + if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + dist_test += FIND_NEAR_BIAS; } if (dist_test < data->dist) { @@ -401,13 +397,6 @@ static void findnearestvert__doClosest(void *userData, BMVert *eve, const float } } - -static bool findnearestvert__backbufIndextest(void *handle, unsigned int index) -{ - BMEditMesh *em = (BMEditMesh *)handle; - BMVert *eve = BM_vert_at_index_find(em->bm, index - 1); - return !(eve && BM_elem_flag_test(eve, BM_ELEM_SELECT)); -} /** * Nearest vertex under the cursor. * @@ -419,7 +408,7 @@ static bool findnearestvert__backbufIndextest(void *handle, unsigned int index) */ BMVert *EDBM_vert_find_nearest_ex( ViewContext *vc, float *r_dist, - const bool use_select_bias, const bool is_strict) + const bool use_select_bias) { BMesh *bm = vc->em->bm; @@ -429,17 +418,9 @@ BMVert *EDBM_vert_find_nearest_ex( unsigned int index; BMVert *eve; - if (is_strict) { - index = ED_view3d_backbuf_sample_rect( - vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &distance, - is_strict, vc->em, findnearestvert__backbufIndextest); - } - else { - index = ED_view3d_backbuf_sample_rect( - vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &distance, - 0, NULL, NULL); - } - + index = ED_view3d_backbuf_sample_rect( + vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &distance); + eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; if (eve && distance < *r_dist) { @@ -464,9 +445,9 @@ BMVert *EDBM_vert_find_nearest_ex( data.index_last = prev_select_index; data.mval_fl[0] = vc->mval[0]; data.mval_fl[1] = vc->mval[1]; - data.hflag_select = use_select_bias ? BM_ELEM_SELECT : 0; + data.use_select_bias = use_select_bias; data.dist = *r_dist; - data.is_strict = is_strict; + data.vert_nearest = NULL; data.index_nearest = 0; @@ -491,13 +472,15 @@ BMVert *EDBM_vert_find_nearest_ex( BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist) { - return EDBM_vert_find_nearest_ex(vc, r_dist, false, false); + return EDBM_vert_find_nearest_ex(vc, r_dist, false); } struct NearestEdgeUserData { ViewContext vc; float mval_fl[2]; + bool use_select_bias; + char hflag_select; float dist; BMEdge *edge_nearest; }; @@ -506,20 +489,32 @@ struct NearestEdgeUserData { static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index)) { struct NearestEdgeUserData *data = userData; - int distance; + float fac = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b); + float distance; + float screen_co[2]; - distance = dist_to_line_segment_v2(data->mval_fl, screen_co_a, screen_co_b); - - if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { - distance += 5; + if (fac <= 0.0f) { + fac = 0.0f; + copy_v2_v2(screen_co, screen_co_a); + } + else if (fac >= 1.0f) { + fac = 1.0f; + copy_v2_v2(screen_co, screen_co_b); + } + else { + interp_v3_v3v3(screen_co, screen_co_a, screen_co_b, fac); + } + + distance = len_manhattan_v2v2(data->mval_fl, screen_co); + + if (data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) { + distance += FIND_NEAR_BIAS; } if (distance < data->dist) { if (data->vc.rv3d->rflag & RV3D_CLIPPING) { - float fac = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b); float vec[3]; - CLAMP(fac, 0, 1); interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac); if (ED_view3d_clipping_test(data->vc.rv3d, vec, true) == 0) { data->dist = distance; @@ -533,7 +528,9 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float } } -BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) +BMEdge *EDBM_edge_find_nearest_ex( + ViewContext *vc, float *r_dist, + const bool use_select_bias) { BMesh *bm = vc->em->bm; @@ -545,7 +542,7 @@ BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) ED_view3d_backbuf_validate(vc); - index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &distance, 0, NULL, NULL); + index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &distance); eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; if (eed && distance < *r_dist) { @@ -562,6 +559,7 @@ BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) data.vc = *vc; data.mval_fl[0] = vc->mval[0]; data.mval_fl[1] = vc->mval[1]; + data.use_select_bias = use_select_bias; data.dist = *r_dist; data.edge_nearest = NULL; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); @@ -573,6 +571,12 @@ BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) } } +BMEdge *EDBM_edge_find_nearest( + ViewContext *vc, float *r_dist) +{ + return EDBM_edge_find_nearest_ex(vc, r_dist, false); +} + struct NearestFaceUserData_ZBuf { float mval_fl[2]; float dist; @@ -729,7 +733,7 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, ED_view3d_backbuf_validate(vc); if (em->selectmode & SCE_SELECT_VERTEX) { - eve = EDBM_vert_find_nearest_ex(vc, &dist, true, false); + eve = EDBM_vert_find_nearest_ex(vc, &dist, true); dist_vert = dist; } @@ -740,7 +744,7 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, /* distance bias from verts (not faces) */ dist = min_ff(dist, dist_vert - dist_edge_bias); if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) { - eed = EDBM_edge_find_nearest(vc, &dist); + eed = EDBM_edge_find_nearest_ex(vc, &dist, true); } /* return only one of 3 pointers, for frontbuffer redraws */ diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index acd745637d2..2491685161c 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -1082,7 +1082,7 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int * on an edge in the backbuf, we can still select a face */ float dummy_dist; - *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist, 0, NULL, NULL); + *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist); } else { /* sample only on the exact position */ @@ -1248,7 +1248,7 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int * on an face in the backbuf, we can still select a vert */ float dummy_dist; - *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist, 0, NULL, NULL); + *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist); } else { /* sample only on the exact position */ diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 678daa6dd88..9fcdb77ef7f 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1552,16 +1552,14 @@ ImBuf *ED_view3d_backbuf_read(ViewContext *vc, short xmin, short ymin, short xma /* smart function to sample a rect spiralling outside, nice for backbuf selection */ unsigned int ED_view3d_backbuf_sample_rect( ViewContext *vc, const int mval[2], int size, - unsigned int min, unsigned int max, float *r_dist, const bool is_strict, - void *handle, bool (*indextest)(void *handle, unsigned int index)) + unsigned int min, unsigned int max, float *r_dist) { struct ImBuf *buf; - unsigned int *bufmin, *bufmax, *tbuf; + const unsigned int *bufmin, *bufmax, *tbuf; int minx, miny; int a, b, rc, nr, amount, dirvec[4][2]; int distance = 0; unsigned int index = 0; - bool indexok = false; amount = (size - 1) / 2; @@ -1586,20 +1584,20 @@ unsigned int ED_view3d_backbuf_sample_rect( for (a = 0; a < 2; a++) { for (b = 0; b < nr; b++, distance++) { - if (*tbuf && *tbuf >= min && *tbuf < max) { /* we got a hit */ - if (is_strict) { - indexok = indextest(handle, *tbuf - min + 1); - if (indexok) { - *r_dist = sqrtf((float)distance); - index = *tbuf - min + 1; - goto exit; - } - } - else { - *r_dist = sqrtf((float)distance); /* XXX, this distance is wrong - */ - index = *tbuf - min + 1; /* messy yah, but indices start at 1 */ - goto exit; - } + if (*tbuf && *tbuf >= min && *tbuf < max) { + /* we got a hit */ + + /* get x,y pixel coords from the offset */ + const float delta[2] = { + ((tbuf - buf->rect) % size) - (size / 2), + ((tbuf - buf->rect) / size) - (size / 2), + }; + + *r_dist = len_v2(delta); + + /* indices start at 1 here */ + index = (*tbuf - min) + 1; + goto exit; } tbuf += (dirvec[rc][0] + dirvec[rc][1]); -- cgit v1.2.3 From 912397756a8adfde91e2c307ab9f17d873e002f8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 21 Apr 2015 13:10:32 +1000 Subject: Fix T44432: Zoom to mouse fails /w FCurve editor --- source/blender/editors/interface/view2d_ops.c | 8 ++++++-- source/blender/makesdna/DNA_view2d_types.h | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 5730c967880..58b51ef8e28 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -661,7 +661,9 @@ static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool const float zoomx = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur); /* only move view to mouse if zoom fac is inside minzoom/maxzoom */ - if (IN_RANGE_INCL(zoomx, v2d->minzoom, v2d->maxzoom)) { + if (((v2d->keepzoom & V2D_LIMITZOOM) == 0) || + IN_RANGE_INCL(zoomx, v2d->minzoom, v2d->maxzoom)) + { float mval_fac = (vzd->mx_2d - cur_old.xmin) / BLI_rctf_size_x(&cur_old); float mval_faci = 1.0f - mval_fac; float ofs = (mval_fac * dx) - (mval_faci * dx); @@ -692,7 +694,9 @@ static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool const float zoomy = (float)(BLI_rcti_size_y(&v2d->mask) + 1) / BLI_rctf_size_y(&v2d->cur); /* only move view to mouse if zoom fac is inside minzoom/maxzoom */ - if (IN_RANGE_INCL(zoomy, v2d->minzoom, v2d->maxzoom)) { + if (((v2d->keepzoom & V2D_LIMITZOOM) == 0) || + IN_RANGE_INCL(zoomy, v2d->minzoom, v2d->maxzoom)) + { float mval_fac = (vzd->my_2d - cur_old.ymin) / BLI_rctf_size_y(&cur_old); float mval_faci = 1.0f - mval_fac; float ofs = (mval_fac * dy) - (mval_faci * dy); diff --git a/source/blender/makesdna/DNA_view2d_types.h b/source/blender/makesdna/DNA_view2d_types.h index a7921be44d5..6f2e347c84d 100644 --- a/source/blender/makesdna/DNA_view2d_types.h +++ b/source/blender/makesdna/DNA_view2d_types.h @@ -43,7 +43,7 @@ typedef struct View2D { rcti mask; /* mask - region (in screenspace) within which 'cur' can be viewed */ float min[2], max[2]; /* min/max sizes of 'cur' rect (only when keepzoom not set) */ - float minzoom, maxzoom; /* self explanatory. allowable zoom factor range (only when keepzoom set) */ + float minzoom, maxzoom; /* allowable zoom factor range (only when (keepzoom & V2D_LIMITZOOM)) is set */ short scroll; /* scroll - scrollbars to display (bitflag) */ short scroll_ui; /* scroll_ui - temp settings used for UI drawing of scrollers */ -- cgit v1.2.3 From 56a93e9cb12a2269427de1414d191207012b54f4 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 21 Apr 2015 14:24:13 +1000 Subject: Add eyedropper for selecting object & obdata In addition to the unlink icon to clear a value, When cleared, show an eyedropper to select objects or object-data (was already available via the EKey). --- source/blender/editors/interface/interface.c | 40 +++++++++++++++++++++ .../editors/interface/interface_eyedropper.c | 2 ++ .../blender/editors/interface/interface_handlers.c | 41 +++++++++++++--------- .../blender/editors/interface/interface_intern.h | 10 +++++- .../blender/editors/interface/interface_widgets.c | 17 +++++++-- 5 files changed, 91 insertions(+), 19 deletions(-) diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 5714a40d508..bda74bf5af8 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -37,6 +37,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_userdef_types.h" @@ -1951,6 +1952,45 @@ uiBut *ui_but_drag_multi_edit_get(uiBut *but) return but_iter; } +/** \name Check to show extra icons + * + * Extra icons are shown on the right hand side of buttons. + * \{ */ + +static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but) +{ + BLI_assert(but->type == UI_BTYPE_SEARCH_MENU); + return ((but->editstr == NULL) && + (but->drawstr[0] != '\0') && + (but->flag & UI_BUT_SEARCH_UNLINK)); +} + +static bool ui_but_icon_extra_is_visible_eyedropper(uiBut *but) +{ + StructRNA *type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop); + const short idcode = RNA_type_to_ID_code(type); + + BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_SEARCH_UNLINK)); + + return ((but->editstr == NULL) && + (idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode))); +} + +uiButExtraIconType ui_but_icon_extra_get(uiBut *but) +{ + if (ui_but_icon_extra_is_visible_search_unlink(but)) { + return UI_BUT_ICONEXTRA_UNLINK; + } + else if (ui_but_icon_extra_is_visible_eyedropper(but)) { + return UI_BUT_ICONEXTRA_EYEDROPPER; + } + + return UI_BUT_ICONEXTRA_NONE; +} + +/** \} */ + + static double ui_get_but_scale_unit(uiBut *but, double value) { UnitSettings *unit = but->block->unit; diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index f5847a9d701..80b01b69647 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -456,6 +456,8 @@ static void datadropper_exit(bContext *C, wmOperator *op) op->customdata = NULL; } + + WM_event_add_mousemove(C); } static void datadropper_cancel(bContext *C, wmOperator *op) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index bc35fde633c..7d34754e5a4 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3301,9 +3301,11 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) { + uiButExtraIconType extra_icon_type; + /* unlink icon is on right */ - if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS && - ui_but_is_search_unlink_visible(but)) + if ((ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY)) && + ((extra_icon_type = ui_but_icon_extra_get(but)) != UI_BUT_ICONEXTRA_NONE)) { ARegion *ar = data->region; rcti rect; @@ -3314,14 +3316,29 @@ static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHa BLI_rcti_rctf_copy(&rect, &but->rect); rect.xmin = rect.xmax - (BLI_rcti_size_y(&rect)); + /* handle click on unlink/eyedropper icon */ if (BLI_rcti_isect_pt(&rect, x, y)) { - /* most likely NULL, but let's check, and give it temp zero string */ - if (data->str == NULL) - data->str = MEM_callocN(1, "temp str"); - data->str[0] = 0; + /* doing this on KM_PRESS calls eyedropper after clicking unlink icon */ + if (event->val == KM_RELEASE) { + /* unlink */ + if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) { + /* most likely NULL, but let's check, and give it temp zero string */ + if (data->str == NULL) { + data->str = MEM_callocN(1, "temp str"); + } + data->str[0] = 0; - ui_apply_but_TEX(C, but, data); - button_activate_state(C, but, BUTTON_STATE_EXIT); + ui_apply_but_TEX(C, but, data); + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + /* eyedropper */ + else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) { + WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL); + } + else { + BLI_assert(0); + } + } return WM_UI_HANDLER_BREAK; } @@ -6861,14 +6878,6 @@ static bool ui_but_is_interactive(const uiBut *but, const bool labeledit) return true; } -bool ui_but_is_search_unlink_visible(const uiBut *but) -{ - BLI_assert(but->type == UI_BTYPE_SEARCH_MENU); - return ((but->editstr == NULL) && - (but->drawstr[0] != '\0') && - (but->flag & UI_BUT_SEARCH_UNLINK)); -} - /* x and y are only used in case event is NULL... */ static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bool labeledit) { diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index d7b6824f812..d9558af5f71 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -121,6 +121,14 @@ enum { /* warn: rest of uiBut->flag in UI_interface.h */ }; +/* some buttons display icons only under special conditions + * (e.g. 'x' icon in search menu) - used with ui_but_icon_extra_get */ +typedef enum uiButExtraIconType { + UI_BUT_ICONEXTRA_NONE = 1, + UI_BUT_ICONEXTRA_UNLINK, + UI_BUT_ICONEXTRA_EYEDROPPER, +} uiButExtraIconType; + /* but->pie_dir */ typedef enum RadialDirection { UI_RADIAL_NONE = -1, @@ -456,6 +464,7 @@ extern bool ui_but_string_set(struct bContext *C, uiBut *but, const char *str) A extern bool ui_but_string_set_eval_num(struct bContext *C, uiBut *but, const char *str, double *value) ATTR_NONNULL(); extern int ui_but_string_get_max_length(uiBut *but); extern uiBut *ui_but_drag_multi_edit_get(uiBut *but); +extern uiButExtraIconType ui_but_icon_extra_get(uiBut *but); extern void ui_but_default_set(struct bContext *C, const bool all, const bool use_afterfunc); @@ -466,7 +475,6 @@ extern bool ui_but_is_unit(const uiBut *but) ATTR_WARN_UNUSED_RESULT; extern bool ui_but_is_compatible(const uiBut *but_a, const uiBut *but_b) ATTR_WARN_UNUSED_RESULT; extern bool ui_but_is_rna_valid(uiBut *but) ATTR_WARN_UNUSED_RESULT; extern bool ui_but_is_utf8(const uiBut *but) ATTR_WARN_UNUSED_RESULT; -extern bool ui_but_is_search_unlink_visible(const uiBut *but) ATTR_WARN_UNUSED_RESULT; extern int ui_but_is_pushed_ex(uiBut *but, double *value) ATTR_WARN_UNUSED_RESULT; extern int ui_but_is_pushed(uiBut *but) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index b3c3d7f53a9..08bd2d3360c 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1501,6 +1501,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB const bool show_menu_icon = ui_but_draw_menu_icon(but); float alpha = (float)wcol->text[3] / 255.0f; char password_str[UI_MAX_DRAW_STR]; + uiButExtraIconType extra_icon_type; ui_but_text_password_hide(password_str, but, false); @@ -1540,11 +1541,23 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB } /* unlink icon for this button type */ - if ((but->type == UI_BTYPE_SEARCH_MENU) && ui_but_is_search_unlink_visible(but)) { + if ((but->type == UI_BTYPE_SEARCH_MENU) && + ((extra_icon_type = ui_but_icon_extra_get(but)) != UI_BUT_ICONEXTRA_NONE)) + { rcti temp = *rect; temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f); - widget_draw_icon(but, ICON_X, alpha, &temp, false); + + if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) { + widget_draw_icon(but, ICON_X, alpha, &temp, false); + } + else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) { + widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, false); + } + else { + BLI_assert(0); + } + rect->xmax -= ICON_SIZE_FROM_BUTRECT(rect); } -- cgit v1.2.3 From f36e91ad0af2aa6c474f476d0a27fd30f42d45ab Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 21 Apr 2015 15:18:16 +1000 Subject: Correct crash in last commit (spacebar search) --- source/blender/editors/interface/interface.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index bda74bf5af8..1e738668f9d 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1967,18 +1967,29 @@ static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but) static bool ui_but_icon_extra_is_visible_eyedropper(uiBut *but) { - StructRNA *type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop); - const short idcode = RNA_type_to_ID_code(type); + StructRNA *type; + short idcode; BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_SEARCH_UNLINK)); + if (but->rnaprop == NULL) { + return false; + } + + type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop); + idcode = RNA_type_to_ID_code(type); + + return ((but->editstr == NULL) && (idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode))); } uiButExtraIconType ui_but_icon_extra_get(uiBut *but) { - if (ui_but_icon_extra_is_visible_search_unlink(but)) { + if ((but->flag & UI_BUT_SEARCH_UNLINK) == 0) { + /* pass */ + } + else if (ui_but_icon_extra_is_visible_search_unlink(but)) { return UI_BUT_ICONEXTRA_UNLINK; } else if (ui_but_icon_extra_is_visible_eyedropper(but)) { -- cgit v1.2.3 From b82d571c85abe3e7631d2966115dcae2bb076be6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 21 Apr 2015 15:53:32 +1000 Subject: Cleanup: style --- intern/cycles/kernel/shaders/node_image_texture.osl | 6 +++--- intern/cycles/kernel/shaders/node_math.osl | 4 ++-- source/blender/editors/space_image/image_buttons.c | 2 +- source/blender/gpu/intern/gpu_draw.c | 2 +- source/blender/nodes/composite/node_composite_util.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/intern/cycles/kernel/shaders/node_image_texture.osl b/intern/cycles/kernel/shaders/node_image_texture.osl index 526a87525cd..46a02cab32e 100644 --- a/intern/cycles/kernel/shaders/node_image_texture.osl +++ b/intern/cycles/kernel/shaders/node_image_texture.osl @@ -26,7 +26,7 @@ point map_to_tube(vector dir) { float u, v; v = (dir[2] + 1.0) * 0.5; - float len = sqrt(dir[0]*dir[0] + dir[1]*dir[1]); + float len = sqrt(dir[0] * dir[0] + dir[1] * dir[1]); if (len > 0.0) { u = (1.0 - (atan2(dir[0] / len, dir[1] / len) / M_PI)) * 0.5; } @@ -40,8 +40,8 @@ point map_to_sphere(vector dir) { float len = length(dir); float v, u; - if(len > 0.0) { - if(dir[0] == 0.0 && dir[1] == 0.0) { + if (len > 0.0) { + if (dir[0] == 0.0 && dir[1] == 0.0) { u = 0.0; /* Othwise domain error. */ } else { diff --git a/intern/cycles/kernel/shaders/node_math.osl b/intern/cycles/kernel/shaders/node_math.osl index bbc008b4299..7eef97fd7e8 100644 --- a/intern/cycles/kernel/shaders/node_math.osl +++ b/intern/cycles/kernel/shaders/node_math.osl @@ -93,8 +93,8 @@ shader node_math( Value = Value1 > Value2; else if (type == "Modulo") Value = safe_modulo(Value1, Value2); - else if (type == "Absolute") - Value = fabs(Value1); + else if (type == "Absolute") + Value = fabs(Value1); if (Clamp) Value = clamp(Value, 0.0, 1.0); diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index c398d32dad5..2e9c2d96be5 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -580,7 +580,7 @@ static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) ImageUser *iuser = iuser_v; RenderLayer *rl; RenderPass *rp; - RenderPass *prev= NULL; + RenderPass *prev = NULL; int layer = iuser->layer; if (RE_HasFakeLayer(rr)) diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index daf6b90f604..7d41746659f 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -117,7 +117,7 @@ void GPU_render_text(MTFace *tface, int mode, /* color has been set */ if (tface->mode & TF_OBCOL) - col= NULL; + col = NULL; else if (!col) glColor3f(1.0f, 1.0f, 1.0f); diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c index 8e279cf6d68..bbfb07a316d 100644 --- a/source/blender/nodes/composite/node_composite_util.c +++ b/source/blender/nodes/composite/node_composite_util.c @@ -43,7 +43,7 @@ void cmp_node_update_default(bNodeTree *UNUSED(ntree), bNode *node) for (sock = node->outputs.first; sock; sock = sock->next) { if (sock->cache) { //free_compbuf(sock->cache); - //sock->cache= NULL; + //sock->cache = NULL; } } node->need_exec = 1; -- cgit v1.2.3 From e0ae23b4d69be4ac78cde50b37cbbaed87a39ea4 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 21 Apr 2015 11:57:31 +0200 Subject: Allow editing of active strip proxy settings again in addition to the set operator --- release/scripts/startup/bl_ui/space_sequencer.py | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 4bb65ff7869..3aed000223c 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -948,23 +948,13 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel): if proxy.use_proxy_custom_file: flow.prop(proxy, "filepath") - layout.label("Enabled Proxies:") - enabled = "" row = layout.row() - if (proxy.build_25): - enabled += "25% " - if (proxy.build_50): - enabled += "50% " - if (proxy.build_75): - enabled += "75% " - if (proxy.build_100): - enabled += "100% " - - row.label(enabled) - if (proxy.use_overwrite): - layout.label("Overwrite On") - else: - layout.label("Overwrite Off") + row.prop(strip.proxy, "build_25") + row.prop(strip.proxy, "build_50") + row.prop(strip.proxy, "build_75") + row.prop(strip.proxy, "build_100") + + layout.prop(proxy, "use_overwrite") col = layout.column() col.label(text="Build JPEG quality") -- cgit v1.2.3 From 907d4d310f697a2a9b5c83bb2fc428175a7daaf2 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 21 Apr 2015 12:13:02 +0200 Subject: Backdrop strictly shows image result only - it could get influenced by scopes setting of space if one changed the space type back and forth. Thanks to Sergey for reporting. --- source/blender/editors/space_sequencer/sequencer_draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index baadc28cd65..965a988a2bd 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1037,7 +1037,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq sequencer_display_size(scene, sseq, viewrect); - if (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0) { + if (!draw_backdrop && (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0)) { SequencerScopes *scopes = &sseq->scopes; sequencer_check_scopes(scopes, ibuf); -- cgit v1.2.3 From e3a6440e7af7f90432319aec9f6ad43b557def31 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 21 Apr 2015 21:16:19 +1000 Subject: BMesh: mesh-data picking, general improvements Generalize logic for vert/edge/face selection: - index cycling. - selection bias with mixed modes. Details: - Edges now support index cycling (as verts/faces did already) - Cycling over near elements is now only enabled when the mouse position remains the same. - No longer do 2 selection passes to perform index cycling. Fixes: - Edges behind the view could be selected (surprising nobody reported!) - Selection bias now only changes the element that gets picked without interning the return distance (was buggy with mixed modes). --- source/blender/editors/include/ED_mesh.h | 14 +- source/blender/editors/include/ED_view3d.h | 2 +- source/blender/editors/mesh/editmesh_select.c | 381 +++++++++++++--------- source/blender/editors/space_view3d/view3d_draw.c | 12 +- 4 files changed, 244 insertions(+), 165 deletions(-) diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 3c672362a54..b982ff2a83b 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -137,20 +137,18 @@ bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2] short xmin, short ymin, short xmax, short ymax); bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads); -struct BMVert *EDBM_vert_find_nearest_ex( - struct ViewContext *vc, float *r_dist, - const bool use_select_bias); +struct BMVert *EDBM_vert_find_nearest_ex(struct ViewContext *vc, float *r_dist, + const bool use_select_bias, bool use_cycle); struct BMVert *EDBM_vert_find_nearest( struct ViewContext *vc, float *r_dist); -struct BMEdge *EDBM_edge_find_nearest_ex( - struct ViewContext *vc, float *r_dist, - const bool use_select_bias); +struct BMEdge *EDBM_edge_find_nearest_ex(struct ViewContext *vc, float *r_dist, + const bool use_select_bias, const bool use_cycle); struct BMEdge *EDBM_edge_find_nearest( struct ViewContext *vc, float *r_dist); -struct BMFace *EDBM_face_find_nearest_ex( - struct ViewContext *vc, float *r_dist, +struct BMFace *EDBM_face_find_nearest_ex(struct ViewContext *vc, float *r_dist, + const bool use_select_bias, const bool use_cycle, struct BMFace **r_efa_zbuf); struct BMFace *EDBM_face_find_nearest( struct ViewContext *vc, float *r_dist); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 6be7f706f28..ab270f657a4 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -271,7 +271,7 @@ void ED_view3d_backbuf_validate(struct ViewContext *vc); struct ImBuf *ED_view3d_backbuf_read(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax); unsigned int ED_view3d_backbuf_sample_rect( struct ViewContext *vc, const int mval[2], int size, - unsigned int min, unsigned int max, float *dist); + unsigned int min, unsigned int max, float *r_dist); int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist); unsigned int ED_view3d_backbuf_sample(struct ViewContext *vc, int x, int y); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 84ca945bf48..92c7dde1f6f 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -354,45 +354,62 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) /* -------------------------------------------------------------------- */ /** \name Find Nearest Vert/Edge/Face + * + * \note Screen-space manhatten distances are used here, + * since its faster and good enough for the purpose of selection. + * + * \note \a dist_bias is used so we can bias against selected items. + * when choosing between elements of a single type, but return the real distance + * to avoid the bias interfering with distance comparisons when mixing types. * \{ */ -#define FIND_NEAR_THRESHOLD_MIN 3 -#define FIND_NEAR_BIAS 5 +#define FIND_NEAR_SELECT_BIAS 5 +#define FIND_NEAR_CYCLE_THRESHOLD_MIN 3 + +struct NearestVertUserData_Hit { + float dist; + float dist_bias; + int index; + BMVert *vert; +}; struct NearestVertUserData { float mval_fl[2]; - int pass; bool use_select_bias; - float dist; - int index_last; - int index_nearest; - BMVert *vert_nearest; + bool use_cycle; + int cycle_index_prev; + + struct NearestVertUserData_Hit hit; + struct NearestVertUserData_Hit hit_cycle; }; static void findnearestvert__doClosest(void *userData, BMVert *eve, const float screen_co[2], int index) { struct NearestVertUserData *data = userData; + float dist_test, dist_test_bias; - if (data->pass == 0) { - if (index <= data->index_last) - return; - } - else { - if (index > data->index_last) - return; - } + dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co); - if (data->dist > FIND_NEAR_THRESHOLD_MIN) { - float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); + if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + dist_test_bias += FIND_NEAR_SELECT_BIAS; + } - if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - dist_test += FIND_NEAR_BIAS; - } + if (dist_test_bias < data->hit.dist_bias) { + data->hit.dist_bias = dist_test_bias; + data->hit.dist = dist_test; + data->hit.index = index; + data->hit.vert = eve; + } - if (dist_test < data->dist) { - data->dist = dist_test; - data->vert_nearest = eve; - data->index_nearest = index; + if (data->use_cycle) { + if ((data->hit_cycle.vert == NULL) && + (index > data->cycle_index_prev) && + (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN)) + { + data->hit_cycle.dist_bias = dist_test_bias; + data->hit_cycle.dist = dist_test; + data->hit_cycle.index = index; + data->hit_cycle.vert = eve; } } } @@ -408,89 +425,94 @@ static void findnearestvert__doClosest(void *userData, BMVert *eve, const float */ BMVert *EDBM_vert_find_nearest_ex( ViewContext *vc, float *r_dist, - const bool use_select_bias) + const bool use_select_bias, bool use_cycle) { BMesh *bm = vc->em->bm; if (V3D_IS_ZBUF(vc->v3d)) { const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); - float distance; + float dist_test; unsigned int index; BMVert *eve; index = ED_view3d_backbuf_sample_rect( - vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &distance); - + vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test); eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; - if (eve && distance < *r_dist) { - *r_dist = distance; - return eve; - } - else { - return NULL; + if (eve) { + if (dist_test < *r_dist) { + *r_dist = dist_test; + return eve; + } } + return NULL; } else { - struct NearestVertUserData data; + struct NearestVertUserData data = {{0}}; + const struct NearestVertUserData_Hit *hit; + const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT; static int prev_select_index = 0; static const BMVert *prev_select_elem = NULL; - if (prev_select_elem && (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index))) { + if ((use_cycle == false) || + (prev_select_elem && (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index)))) + { prev_select_index = 0; prev_select_elem = NULL; } - data.index_last = prev_select_index; data.mval_fl[0] = vc->mval[0]; data.mval_fl[1] = vc->mval[1]; data.use_select_bias = use_select_bias; - data.dist = *r_dist; - - data.vert_nearest = NULL; - data.index_nearest = 0; - - data.pass = 0; + data.use_cycle = use_cycle; + data.hit.dist = data.hit_cycle.dist = \ + data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist; + data.cycle_index_prev = prev_select_index; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag); - mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - - if (data.dist > FIND_NEAR_THRESHOLD_MIN) { - data.pass = 1; - mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - } + hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit; + *r_dist = hit->dist; - *r_dist = data.dist; - prev_select_elem = data.vert_nearest; - prev_select_index = data.index_nearest; + prev_select_elem = hit->vert; + prev_select_index = hit->index; - return data.vert_nearest; + return hit->vert; } } BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist) { - return EDBM_vert_find_nearest_ex(vc, r_dist, false); + return EDBM_vert_find_nearest_ex(vc, r_dist, false, false); } +struct NearestEdgeUserData_Hit { + float dist; + float dist_bias; + int index; + BMEdge *edge; +}; struct NearestEdgeUserData { ViewContext vc; float mval_fl[2]; bool use_select_bias; - char hflag_select; - float dist; - BMEdge *edge_nearest; + bool use_cycle; + int cycle_index_prev; + + struct NearestEdgeUserData_Hit hit; + struct NearestEdgeUserData_Hit hit_cycle; }; /* note; uses v3d, so needs active 3d window */ -static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index)) +static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { struct NearestEdgeUserData *data = userData; + float dist_test, dist_test_bias; + float fac = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b); - float distance; float screen_co[2]; if (fac <= 0.0f) { @@ -505,93 +527,117 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float interp_v3_v3v3(screen_co, screen_co_a, screen_co_b, fac); } - distance = len_manhattan_v2v2(data->mval_fl, screen_co); + dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co); if (data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) { - distance += FIND_NEAR_BIAS; + dist_test += FIND_NEAR_SELECT_BIAS; } - if (distance < data->dist) { - if (data->vc.rv3d->rflag & RV3D_CLIPPING) { - float vec[3]; + if (data->vc.rv3d->rflag & RV3D_CLIPPING) { + float vec[3]; - interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac); - if (ED_view3d_clipping_test(data->vc.rv3d, vec, true) == 0) { - data->dist = distance; - data->edge_nearest = eed; - } + interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac); + if (ED_view3d_clipping_test(data->vc.rv3d, vec, true)) { + return; } - else { - data->dist = distance; - data->edge_nearest = eed; + } + + if (dist_test_bias < data->hit.dist_bias) { + data->hit.dist_bias = dist_test_bias; + data->hit.dist = dist_test; + data->hit.index = index; + data->hit.edge = eed; + } + + if (data->use_cycle) { + if ((data->hit_cycle.edge == NULL) && + (index > data->cycle_index_prev) && + (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN)) + { + data->hit_cycle.dist_bias = dist_test_bias; + data->hit_cycle.dist = dist_test; + data->hit_cycle.index = index; + data->hit_cycle.edge = eed; } } } BMEdge *EDBM_edge_find_nearest_ex( ViewContext *vc, float *r_dist, - const bool use_select_bias) + const bool use_select_bias, const bool use_cycle) { BMesh *bm = vc->em->bm; if (V3D_IS_ZBUF(vc->v3d)) { const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); - float distance; + float dist_test; unsigned int index; BMEdge *eed; ED_view3d_backbuf_validate(vc); - index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &distance); + index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test); eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; - if (eed && distance < *r_dist) { - *r_dist = distance; - return eed; - } - else { - return NULL; + if (eed) { + if (dist_test < *r_dist) { + *r_dist = dist_test; + return eed; + } } + return NULL; } else { - struct NearestEdgeUserData data; + struct NearestEdgeUserData data = {{0}}; + const struct NearestEdgeUserData_Hit *hit; + /* interpolate along the edge before doing a boundbox check */ + const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB; + + static int prev_select_index = 0; + static const BMEdge *prev_select_elem = NULL; + + if ((use_cycle == false) || + (prev_select_elem && (prev_select_elem != BM_edge_at_index_find_or_table(bm, prev_select_index)))) + { + prev_select_index = 0; + prev_select_elem = NULL; + } data.vc = *vc; data.mval_fl[0] = vc->mval[0]; data.mval_fl[1] = vc->mval[1]; data.use_select_bias = use_select_bias; - data.dist = *r_dist; - data.edge_nearest = NULL; + data.use_cycle = use_cycle; + data.hit.dist = data.hit_cycle.dist = \ + data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist; + data.cycle_index_prev = prev_select_index; + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, clip_flag); - mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, V3D_PROJ_TEST_CLIP_WIN); + hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit; + *r_dist = hit->dist; - *r_dist = data.dist; - return data.edge_nearest; + prev_select_elem = hit->edge; + prev_select_index = hit->index; + + return hit->edge; } } BMEdge *EDBM_edge_find_nearest( ViewContext *vc, float *r_dist) { - return EDBM_edge_find_nearest_ex(vc, r_dist, false); + return EDBM_edge_find_nearest_ex(vc, r_dist, false, false); } +/* find the distance to the face we already have */ struct NearestFaceUserData_ZBuf { float mval_fl[2]; float dist; const BMFace *face_test; }; -struct NearestFaceUserData_Closest { - float mval_fl[2]; - int pass; - float dist; - int index_last; - int index_nearest; - BMFace *face_nearest; -}; - static void findnearestface__doZBuf(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index)) { struct NearestFaceUserData_ZBuf *data = userData; @@ -606,26 +652,50 @@ static void findnearestface__doZBuf(void *userData, BMFace *efa, const float scr } +struct NearestFaceUserData_Hit { + float dist; + float dist_bias; + int index; + BMFace *face; +}; + +struct NearestFaceUserData { + float mval_fl[2]; + bool use_select_bias; + bool use_cycle; + int cycle_index_prev; + + struct NearestFaceUserData_Hit hit; + struct NearestFaceUserData_Hit hit_cycle; +}; + static void findnearestface__doClosest(void *userData, BMFace *efa, const float screen_co[2], int index) { - struct NearestFaceUserData_Closest *data = userData; + struct NearestFaceUserData *data = userData; + float dist_test, dist_test_bias; - if (data->pass == 0) { - if (index <= data->index_last) - return; - } - else { - if (index > data->index_last) - return; + dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co); + + if (data->use_select_bias && BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + dist_test_bias += FIND_NEAR_SELECT_BIAS; } - if (data->dist > FIND_NEAR_THRESHOLD_MIN) { - const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); + if (dist_test_bias < data->hit.dist_bias) { + data->hit.dist_bias = dist_test_bias; + data->hit.dist = dist_test; + data->hit.index = index; + data->hit.face = efa; + } - if (dist_test < data->dist) { - data->dist = dist_test; - data->face_nearest = efa; - data->index_nearest = index; + if (data->use_cycle) { + if ((data->hit_cycle.face == NULL) && + (index > data->cycle_index_prev) && + (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN)) + { + data->hit_cycle.dist_bias = dist_test_bias; + data->hit_cycle.dist = dist_test; + data->hit_cycle.index = index; + data->hit_cycle.face = efa; } } } @@ -633,11 +703,13 @@ static void findnearestface__doClosest(void *userData, BMFace *efa, const float BMFace *EDBM_face_find_nearest_ex( ViewContext *vc, float *r_dist, + const bool use_select_bias, const bool use_cycle, BMFace **r_efa_zbuf) { BMesh *bm = vc->em->bm; if (V3D_IS_ZBUF(vc->v3d)) { + float dist_test; unsigned int index; BMFace *efa; @@ -650,6 +722,7 @@ BMFace *EDBM_face_find_nearest_ex( *r_efa_zbuf = efa; } + /* exception for faces (verts/edges don't need this) */ if (efa) { struct NearestFaceUserData_ZBuf data; @@ -662,51 +735,57 @@ BMFace *EDBM_face_find_nearest_ex( mesh_foreachScreenFace(vc, findnearestface__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - if ((vc->em->selectmode == SCE_SELECT_FACE) || (data.dist < *r_dist)) { /* only faces, no dist check */ - *r_dist = data.dist; + dist_test = data.dist; + } + /* end exception */ + + if (efa) { + if (dist_test < *r_dist) { + *r_dist = dist_test; return efa; } } - return NULL; } else { - struct NearestFaceUserData_Closest data; + struct NearestFaceUserData data = {{0}}; + const struct NearestFaceUserData_Hit *hit; + const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT; + static int prev_select_index = 0; static const BMFace *prev_select_elem = NULL; - if (prev_select_elem && (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index))) { + if ((use_cycle == false) || + (prev_select_elem && (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index)))) + { prev_select_index = 0; prev_select_elem = NULL; } - data.index_last = prev_select_index; data.mval_fl[0] = vc->mval[0]; data.mval_fl[1] = vc->mval[1]; - data.dist = *r_dist; - data.face_nearest = NULL; - data.index_nearest = 0; + data.use_select_bias = use_select_bias; + data.use_cycle = use_cycle; + data.hit.dist = data.hit_cycle.dist = \ + data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist; + data.cycle_index_prev = prev_select_index; - data.pass = 0; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag); - if (data.dist > FIND_NEAR_THRESHOLD_MIN) { - data.pass = 1; - mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - } + hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit; + *r_dist = hit->dist; - *r_dist = data.dist; - prev_select_elem = data.face_nearest; - prev_select_index = data.index_nearest; + prev_select_elem = hit->face; + prev_select_index = hit->index; - return data.face_nearest; + return hit->face; } } BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) { - return EDBM_face_find_nearest_ex(vc, r_dist, NULL); + return EDBM_face_find_nearest_ex(vc, r_dist, false, false, NULL); } @@ -718,44 +797,45 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa) { BMEditMesh *em = vc->em; + static short mval_prev[2] = {-1, -1}; + /* only cycle while the mouse remains still */ + const bool use_cycle = ((mval_prev[0] == vc->mval[0]) && (mval_prev[1] == vc->mval[1])); const float dist_init = ED_view3d_select_dist_px(); - /* since edges select lines, we give dots advantage of 20 pix */ - const float dist_edge_bias = (dist_init / 3.75f); + /* since edges select lines, we give dots advantage of ~20 pix */ + const float dist_bias = (dist_init / 4); float dist = dist_init; - float dist_vert = dist_init; BMFace *efa_zbuf = NULL; BMVert *eve = NULL; BMEdge *eed = NULL; BMFace *efa = NULL; - + + /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ ED_view3d_backbuf_validate(vc); - if (em->selectmode & SCE_SELECT_VERTEX) { - eve = EDBM_vert_find_nearest_ex(vc, &dist, true); - dist_vert = dist; + if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) { + efa = EDBM_face_find_nearest_ex(vc, &dist, true, use_cycle, &efa_zbuf); } - if (em->selectmode & SCE_SELECT_FACE) { - efa = EDBM_face_find_nearest_ex(vc, &dist, eve ? &efa_zbuf : NULL); + if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) { + eed = EDBM_edge_find_nearest_ex(vc, &dist, true, use_cycle); + dist = min_ff(dist + dist_bias, dist_init); } - /* distance bias from verts (not faces) */ - dist = min_ff(dist, dist_vert - dist_edge_bias); - if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) { - eed = EDBM_edge_find_nearest_ex(vc, &dist, true); + if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) { + eve = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle); } /* return only one of 3 pointers, for frontbuffer redraws */ - if (eed) { - efa = NULL; eve = NULL; + if (eve) { + efa = NULL; eed = NULL; } - else if (efa) { - eve = NULL; + else if (eed) { + efa = NULL; } - /* there may be a face under the cursor, but who's center if too far away + /* there may be a face under the cursor, who's center if too far away * use this if all else fails, it makes sense to select this */ if ((eve || eed || efa) == 0) { if (efa_zbuf) { @@ -763,6 +843,9 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, } } + mval_prev[0] = vc->mval[0]; + mval_prev[1] = vc->mval[1]; + *r_eve = eve; *r_eed = eed; *r_efa = efa; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 9fcdb77ef7f..a69a6be298e 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1587,13 +1587,11 @@ unsigned int ED_view3d_backbuf_sample_rect( if (*tbuf && *tbuf >= min && *tbuf < max) { /* we got a hit */ - /* get x,y pixel coords from the offset */ - const float delta[2] = { - ((tbuf - buf->rect) % size) - (size / 2), - ((tbuf - buf->rect) / size) - (size / 2), - }; - - *r_dist = len_v2(delta); + /* get x,y pixel coords from the offset + * (manhatten distance in keeping with other screen-based selection) */ + *r_dist = (float)( + abs(((tbuf - buf->rect) % size) - (size / 2)) + + abs(((tbuf - buf->rect) / size) - (size / 2))); /* indices start at 1 here */ index = (*tbuf - min) + 1; -- cgit v1.2.3 From de687b6fa02138146294c0a9a810c5234f1ac0dc Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 21 Apr 2015 16:04:14 +0200 Subject: Fix T44465: Crash using VSE OGL render + Grease Pencil Likely caused by rBd5f1b9c22233 --- source/blender/editors/render/render_opengl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 0a605297a4c..35478cc864f 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -248,6 +248,7 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) Object *camera = NULL; ImBuf *ibuf; float winmat[4][4]; + float *rectf = RE_RenderViewGetRectf(rr, oglrender->view_id); int sizex = oglrender->sizex; int sizey = oglrender->sizey; const short view_context = (v3d != NULL); @@ -271,7 +272,6 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) ibuf = BKE_sequencer_give_ibuf(&context, CFRA, chanshown); if (ibuf) { - float *rectf; ImBuf *linear_ibuf; BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y)); @@ -292,7 +292,6 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) BKE_sequencer_imbuf_from_sequencer_space(scene, linear_ibuf); } - rectf = RE_RenderViewGetRectf(rr, oglrender->view_id); memcpy(rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey); IMB_freeImBuf(linear_ibuf); @@ -317,10 +316,12 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) gp_rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect"); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, gp_rect); + BLI_assert(rectf != NULL); + for (i = 0; i < sizex * sizey * 4; i += 4) { float col_src[4]; rgba_uchar_to_float(col_src, &gp_rect[i]); - blend_color_mix_float(&rr->rectf[i], &rr->rectf[i], col_src); + blend_color_mix_float(&rectf[i], &rectf[i], col_src); } GPU_offscreen_unbind(oglrender->ofs, true); -- cgit v1.2.3 From 3a3f80673cde9e4e9ca5f9d28b48b1c0587bbbea Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 22 Apr 2015 00:13:33 +1000 Subject: Cleanup: minor corrections --- source/blender/editors/mesh/editmesh_select.c | 7 +++++-- source/blender/editors/space_view3d/view3d_draw.c | 15 ++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 92c7dde1f6f..f3e3bd9e7c0 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -421,7 +421,7 @@ static void findnearestvert__doClosest(void *userData, BMVert *eve, const float * \param use_select_bias * - When true, selected vertice are given a 5 pixel bias to make them further than unselect verts. * - When false, unselected vertice are given the bias. - * \param is_strict When true, the vertice corresponding to the sel parameter are ignored and not just biased + * \param use_cycle Cycle over elements within #FIND_NEAR_CYCLE_THRESHOLD_MIN in order of index. */ BMVert *EDBM_vert_find_nearest_ex( ViewContext *vc, float *r_dist, @@ -590,7 +590,7 @@ BMEdge *EDBM_edge_find_nearest_ex( else { struct NearestEdgeUserData data = {{0}}; const struct NearestEdgeUserData_Hit *hit; - /* interpolate along the edge before doing a boundbox check */ + /* interpolate along the edge before doing a clipping plane test */ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB; static int prev_select_index = 0; @@ -788,6 +788,9 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) return EDBM_face_find_nearest_ex(vc, r_dist, false, false, NULL); } +#undef FIND_NEAR_SELECT_BIAS +#undef FIND_NEAR_CYCLE_THRESHOLD_MIN + /* best distance based on screen coords. * use em->selectmode to define how to use diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index a69a6be298e..0be1ad66ec8 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1558,7 +1558,6 @@ unsigned int ED_view3d_backbuf_sample_rect( const unsigned int *bufmin, *bufmax, *tbuf; int minx, miny; int a, b, rc, nr, amount, dirvec[4][2]; - int distance = 0; unsigned int index = 0; amount = (size - 1) / 2; @@ -1583,7 +1582,7 @@ unsigned int ED_view3d_backbuf_sample_rect( for (nr = 1; nr <= size; nr++) { for (a = 0; a < 2; a++) { - for (b = 0; b < nr; b++, distance++) { + for (b = 0; b < nr; b++) { if (*tbuf && *tbuf >= min && *tbuf < max) { /* we got a hit */ @@ -1622,17 +1621,19 @@ static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, Ima if ((ima->flag & IMA_IS_STEREO)) { iuser->flag |= IMA_SHOW_STEREO; - if ((scene->r.scemode & R_MULTIVIEW) == 0) + if ((scene->r.scemode & R_MULTIVIEW) == 0) { iuser->multiview_eye = STEREO_LEFT_ID; - - /* show only left or right camera */ - else if (v3d->stereo3d_camera != STEREO_3D_ID) + } + else if (v3d->stereo3d_camera != STEREO_3D_ID) { + /* show only left or right camera */ iuser->multiview_eye = v3d->stereo3d_camera; + } BKE_image_multiview_index(ima, iuser); } - else + else { iuser->flag &= ~IMA_SHOW_STEREO; + } } static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, -- cgit v1.2.3 From 84d117b3add3eec0df7566f183ebb476fff70d0b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 22 Apr 2015 00:43:31 +1000 Subject: Minor edit to edit-mesh selection bias only choose verts over edges (not faces) --- source/blender/editors/mesh/editmesh_select.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index f3e3bd9e7c0..da6a886e2af 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -823,7 +823,9 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) { eed = EDBM_edge_find_nearest_ex(vc, &dist, true, use_cycle); - dist = min_ff(dist + dist_bias, dist_init); + if (eed) { + dist = min_ff(dist + dist_bias, dist_init); + } } if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) { -- cgit v1.2.3 From f9972fa53eaab4d1e8fd7b435f6f65c1ac5501e1 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 21 Apr 2015 17:35:11 +0200 Subject: VSE: Allow GPencil drawing without having a strip loaded Previously the GPencil strokes were just not drawn (even though they were generated) until a strip was loaded. --- .../editors/space_sequencer/sequencer_draw.c | 171 ++++++++++++--------- 1 file changed, 97 insertions(+), 74 deletions(-) diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 965a988a2bd..f07be97ff9f 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -980,6 +980,76 @@ static void sequencer_display_size(Scene *scene, SpaceSeq *sseq, float r_viewrec } } +static void sequencer_draw_gpencil(const bContext *C) +{ + /* draw grease-pencil (image aligned) */ + ED_gpencil_draw_2dimage(C); + + /* ortho at pixel level */ + UI_view2d_view_restore(C); + + /* draw grease-pencil (screen aligned) */ + ED_gpencil_draw_view2d(C, 0); +} + +/* draws content borders plus safety borders if needed */ +static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, const Scene *scene) +{ + float x1 = v2d->tot.xmin; + float y1 = v2d->tot.ymin; + float x2 = v2d->tot.xmax; + float y2 = v2d->tot.ymax; + + /* border */ + setlinestyle(3); + + UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0); + + glBegin(GL_LINE_LOOP); + glVertex2f(x1 - 0.5f, y1 - 0.5f); + glVertex2f(x1 - 0.5f, y2 + 0.5f); + glVertex2f(x2 + 0.5f, y2 + 0.5f); + glVertex2f(x2 + 0.5f, y1 - 0.5f); + glEnd(); + + /* safety border */ + if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) { + UI_draw_safe_areas( + x1, x2, y1, y2, + scene->safe_areas.title, + scene->safe_areas.action); + + if (sseq->flag & SEQ_SHOW_SAFE_CENTER) { + UI_draw_safe_areas( + x1, x2, y1, y2, + scene->safe_areas.title_center, + scene->safe_areas.action_center); + } + } + + setlinestyle(0); +} + +/* draws checkerboard background for transparent content */ +static void sequencer_draw_background(const SpaceSeq *sseq, View2D *v2d, const float viewrect[2]) +{ + /* setting up the view */ + UI_view2d_totRect_set(v2d, viewrect[0] + 0.5f, viewrect[1] + 0.5f); + UI_view2d_curRect_validate(v2d); + UI_view2d_view_ortho(v2d); + + /* only draw alpha for main buffer */ + if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { + if (sseq->flag & SEQ_USE_ALPHA) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax); + glColor4f(1.0, 1.0, 1.0, 1.0); + } + } +} + void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, bool draw_overlay, bool draw_backdrop) { struct Main *bmain = CTX_data_main(C); @@ -996,6 +1066,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq const bool is_imbuf = ED_space_sequencer_check_show_imbuf(sseq); int format, type; bool glsl_used = false; + const bool draw_gpencil = ((sseq->flag & SEQ_SHOW_GPENCIL) && sseq->gpd); const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; if (G.is_rendering == false && (scene->r.seq_flag & R_SEQ_GL_PREV) == 0) { @@ -1018,6 +1089,9 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq glClear(GL_COLOR_BUFFER_BIT); } + /* without this colors can flicker from previous opengl state */ + glColor4ub(255, 255, 255, 255); + /* only initialize the preview if a render is in progress */ if (G.is_rendering) return; @@ -1029,11 +1103,20 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq /* for now we only support Left/Right */ ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs, names[sseq->multiview_eye]); - if (ibuf == NULL) - return; + if ((ibuf == NULL) || + (ibuf->rect == NULL && ibuf->rect_float == NULL)) + { + /* gpencil can also be drawn if no imbuf is invalid */ + if (draw_gpencil && is_imbuf) { + sequencer_display_size(scene, sseq, viewrect); + + sequencer_draw_background(sseq, v2d, viewrect); + sequencer_draw_borders(sseq, v2d, scene); - if (ibuf->rect == NULL && ibuf->rect_float == NULL) + sequencer_draw_gpencil(C); + } return; + } sequencer_display_size(scene, sseq, viewrect); @@ -1096,28 +1179,10 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq } } - /* without this colors can flicker from previous opengl state */ - glColor4ub(255, 255, 255, 255); - if (!draw_backdrop) { - UI_view2d_totRect_set(v2d, viewrect[0] + 0.5f, viewrect[1] + 0.5f); - UI_view2d_curRect_validate(v2d); - - /* setting up the view - actual drawing starts here */ - UI_view2d_view_ortho(v2d); - - /* only draw alpha for main buffer */ - if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { - if (sseq->flag & SEQ_USE_ALPHA) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax); - glColor4f(1.0, 1.0, 1.0, 1.0); - } - } + sequencer_draw_background(sseq, v2d, viewrect); } - + if (scope) { IMB_freeImBuf(ibuf); ibuf = scope; @@ -1286,63 +1351,21 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq if (!scope) IMB_freeImBuf(ibuf); - + if (draw_backdrop) { return; } - - if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { - - float x1 = v2d->tot.xmin; - float y1 = v2d->tot.ymin; - float x2 = v2d->tot.xmax; - float y2 = v2d->tot.ymax; - - /* border */ - setlinestyle(3); - UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0); - - glBegin(GL_LINE_LOOP); - glVertex2f(x1 - 0.5f, y1 - 0.5f); - glVertex2f(x1 - 0.5f, y2 + 0.5f); - glVertex2f(x2 + 0.5f, y2 + 0.5f); - glVertex2f(x2 + 0.5f, y1 - 0.5f); - glEnd(); - - /* safety border */ - if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) { - UI_draw_safe_areas( - x1, x2, y1, y2, - scene->safe_areas.title, - scene->safe_areas.action); - - if (sseq->flag & SEQ_SHOW_SAFE_CENTER) { - UI_draw_safe_areas( - x1, x2, y1, y2, - scene->safe_areas.title_center, - scene->safe_areas.action_center); - } - } - - setlinestyle(0); + if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { + sequencer_draw_borders(sseq, v2d, scene); } - - if (sseq->flag & SEQ_SHOW_GPENCIL) { - if (is_imbuf) { - /* draw grease-pencil (image aligned) */ - ED_gpencil_draw_2dimage(C); - } + + if (draw_gpencil && is_imbuf) { + sequencer_draw_gpencil(C); } - - /* ortho at pixel level */ - UI_view2d_view_restore(C); - - if (sseq->flag & SEQ_SHOW_GPENCIL) { - if (is_imbuf) { - /* draw grease-pencil (screen aligned) */ - ED_gpencil_draw_view2d(C, 0); - } + else { + /* ortho at pixel level */ + UI_view2d_view_restore(C); } -- cgit v1.2.3 From 50bfc4bfa0eabb68fcb5b5e82f80281fbaddcfeb Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 20 Apr 2015 19:57:57 +0200 Subject: Metadata display support - patch by Julian and me. Basically, blender adds a few metadata fields to images when we render an image. Those metadata can now be viewed in the image editor. Also, made sure metadata are available when we write imbufs to disc with "Save As". There may be more cases here that need fixing, but this means that loading an image with metadata will now properly preserve them in blender. --- release/scripts/startup/bl_ui/space_image.py | 1 + source/blender/editors/include/ED_screen.h | 1 + source/blender/editors/include/ED_util.h | 2 + source/blender/editors/screen/area.c | 197 +++++++++++++++++++++++ source/blender/editors/space_image/image_draw.c | 25 +-- source/blender/editors/space_image/image_ops.c | 7 + source/blender/editors/space_image/space_image.c | 2 +- source/blender/editors/util/CMakeLists.txt | 1 + source/blender/imbuf/IMB_imbuf.h | 15 +- source/blender/imbuf/intern/IMB_metadata.h | 10 -- source/blender/imbuf/intern/metadata.c | 7 + source/blender/makesdna/DNA_space_types.h | 1 + source/blender/makesrna/intern/rna_space.c | 5 + 13 files changed, 253 insertions(+), 21 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index e4542163086..bd48116e8b5 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -84,6 +84,7 @@ class IMAGE_MT_view(Menu): layout.prop(toolsettings, "show_uv_local_view") layout.prop(uv, "show_other_objects") + layout.prop(uv, "show_metadata") if paint.brush and (context.image_paint_object or sima.mode == 'PAINT'): layout.prop(uv, "show_texpaint") layout.prop(toolsettings, "show_uv_local_view", text="Show same material") diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 90b0b3510bc..b7c261cad6c 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -66,6 +66,7 @@ void ED_region_header_init(struct ARegion *ar); void ED_region_header(const struct bContext *C, struct ARegion *ar); void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar); void ED_region_info_draw(struct ARegion *ar, const char *text, int block, float fill_color[4]); +void ED_region_image_metadata_draw(struct ARegion *ar, struct ImBuf *ibuf, float zoomx, float zoomy); void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy); float ED_region_blend_factor(struct ARegion *ar); void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect); diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index 9556c601d1f..96d7828ffe9 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -42,6 +42,8 @@ void ED_editors_exit(struct bContext *C); bool ED_editors_flush_edits(const struct bContext *C, bool for_render); +void ED_draw_ibuf_meta_data(const bContext *C, struct ImBuf *ibuf); + /* ************** Undo ************************ */ /* undo.c */ diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index d786c0cfc36..1c87d959dc4 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -61,6 +61,9 @@ #include "BIF_glutil.h" #include "BLF_api.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + #include "UI_interface.h" #include "UI_interface_icons.h" #include "UI_resources.h" @@ -2027,6 +2030,200 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float fill_co glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); } +#define MAX_METADATA_STR 1024 + +const char *meta_data_list[] = +{ + "File", + "Strip", + "Note", + "Date", + "RenderTime", + "Marker", + "Time", + "Frame", + "Camera", + "Scene" +}; + +BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index) +{ + return (IMB_metadata_get_field(ibuf, meta_data_list[index], r_str, MAX_METADATA_STR) && r_str[0]); +} + +static void metadata_draw_lines(ImBuf *ibuf, rcti rect, int fontid, const bool is_top) +{ + char temp_str[MAX_METADATA_STR]; + int line_width, line_height; + int ofs_y = 0; + short line_index; + short i; + + for (line_index = 0; line_index < 4 && is_top == true; line_index++) { + /* first line */ + if (line_index == 0) { + int len; + bool do_newline = false; + float height = 0.0; + BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]); + len = strlen(temp_str); + if (metadata_is_valid(ibuf, temp_str + len, 0)) { + BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit), + rect.ymax - (1.5f * U.widget_unit - UI_UNIT_Y), 0.0f); + BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + do_newline = true; + height = BLF_height(fontid, temp_str, strlen(temp_str)); + } + + BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]); + len = strlen(temp_str); + if (metadata_is_valid(ibuf, temp_str + len, 1)) { + len = strlen(temp_str); + line_width = BLF_width(fontid, temp_str, len); + BLF_position(fontid, rect.xmax - line_width - (0.2f * U.widget_unit), + rect.ymax - (1.5f * U.widget_unit - UI_UNIT_Y), 0.0f); + BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + do_newline = true; + height = max_ff(BLF_height(fontid, temp_str, len), height); + } + + if (do_newline) + ofs_y += (height + (0.2f * U.widget_unit)); + } + else if (line_index == 1) { + if (metadata_is_valid(ibuf, temp_str, line_index + 1)) { + BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit), + rect.ymax - (1.5f * U.widget_unit - UI_UNIT_Y) - ofs_y, 0.0f); + BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + ofs_y += (BLF_height(fontid, temp_str, strlen(temp_str)) + (0.2f * U.widget_unit)); + } + } + else { + if (metadata_is_valid(ibuf, temp_str, line_index + 1)) { + BLF_position(fontid, rect.xmax + (0.2f * U.widget_unit), + rect.ymax - (1.5f * U.widget_unit - UI_UNIT_Y) - ofs_y, 0.0f); + BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + ofs_y += (BLF_height(fontid, temp_str, strlen(temp_str)) + (0.2f * U.widget_unit)); + } + } + } + + if (is_top == false) { + int ofs_x = 0; + for (i = 5; i < 10; i++) { + if (metadata_is_valid(ibuf, temp_str, i)) { + line_height = BLF_height(fontid, temp_str, strlen(temp_str)); + BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit) + ofs_x, + rect.ymin - line_height + (1.5f * U.widget_unit), 0.0f); + BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + + ofs_x += BLF_width(fontid, temp_str, strlen(temp_str)) + UI_UNIT_X; + } + } + } +} + +static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top) +{ + char str[MAX_METADATA_STR]; + float height = 0; + short i; + + if (is_top) { + for (i = 0; i < 5 ; i++) { + if (metadata_is_valid(ibuf, str, i)) { + height += BLF_height(fontid, str, strlen(str)); + } + } + } + else { + for (i = 5; i < 10; i++) { + if (metadata_is_valid(ibuf, str, i)) { + height += BLF_height(fontid, str, strlen(str)); + } + } + } + + if (height) { + return (height + (0.2f * U.widget_unit)); + } + + return 0; +} + +#undef MAX_METADATA_STR + +void ED_region_image_metadata_draw(ARegion *ar, ImBuf *ibuf, float zoomx, float zoomy) +{ + uiStyle *style = UI_style_get_dpi(); + int fontid = style->widget.uifont_id; + float box_y; + rcti rect; + int x, y; + + if (!ibuf->metadata) + return; + + /* find window pixel coordinates of origin */ + UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y); + + glPushMatrix(); + + /* offset and zoom using ogl */ + glTranslatef(x, y, 0.0f); + glScalef(zoomx, zoomy, 1.0f); + + /* *** upper box*** */ + + /* get needed box height */ + box_y = metadata_box_height_get(ibuf, fontid, true); + + if (box_y) { + glColor3f(0.1f, 0.1f, 0.1f); + //glColor3f(1.0f, 0.15f, 0.8f); /* Pinkyfied version for Pablo */ + + /* set up rect */ + BLI_rcti_init(&rect, 0, ibuf->x, ibuf->y, ibuf->y + box_y); + /* draw top box */ + glRecti(rect.xmin, rect.ymin, rect.xmax, rect.ymax); + + BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + BLF_enable(fontid, BLF_CLIPPING); + + glColor3f(1.0f, 1.0f, 1.0f); + + metadata_draw_lines(ibuf, rect, fontid, true); + + BLF_disable(fontid, BLF_CLIPPING); + } + + + /* *** lower box*** */ + + box_y = metadata_box_height_get(ibuf, fontid, false); + + if (box_y) { + glColor3f(0.1f, 0.1f, 0.1f); + //glColor3f(1.0f, 0.15f, 0.8f); /* Pinkyfied version for Pablo */ + + /* set up box rect */ + BLI_rcti_init(&rect, 0, ibuf->x, -box_y, 0); + /* draw top box */ + glRecti(rect.xmin, rect.ymin, rect.xmax, rect.ymax); + + BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + BLF_enable(fontid, BLF_CLIPPING); + + glColor3f(1.0f, 1.0f, 1.0f); + + metadata_draw_lines(ibuf, rect, fontid, false); + + BLF_disable(fontid, BLF_CLIPPING); + } + + glPopMatrix(); +} + void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy) { float gridsize, gridstep = 1.0f / 32.0f; diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 5a3c3e90618..04e874bbae1 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -836,14 +836,23 @@ void draw_image_main(const bContext *C, ARegion *ar) ibuf = ED_space_image_acquire_buffer(sima, &lock); /* draw the image or grid */ - if (ibuf == NULL) + if (ibuf == NULL) { ED_region_grid_draw(ar, zoomx, zoomy); - else if (sima->flag & SI_DRAW_TILE) - draw_image_buffer_repeated(C, sima, ar, scene, ima, ibuf, zoomx, zoomy); - else if (ima && (ima->tpageflag & IMA_TILES)) - draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, 0.0f, 0.0, zoomx, zoomy); - else - draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy); + } + else { + + if (sima->flag & SI_DRAW_TILE) + draw_image_buffer_repeated(C, sima, ar, scene, ima, ibuf, zoomx, zoomy); + else if (ima && (ima->tpageflag & IMA_TILES)) + draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, 0.0f, 0.0, zoomx, zoomy); + else + draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy); + + if (sima->flag & SI_DRAW_METADATA) + ED_region_image_metadata_draw(ar, ibuf, zoomx, zoomy); + } + + ED_space_image_release_buffer(sima, ibuf, lock); /* paint helpers */ if (show_paint) @@ -866,8 +875,6 @@ void draw_image_main(const bContext *C, ARegion *ar) } #endif - ED_space_image_release_buffer(sima, ibuf, lock); - if (show_viewer) { BLI_unlock_thread(LOCK_DRAW_IMAGE); } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 756f90fe560..2fe2e6615a6 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1672,6 +1672,12 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI goto cleanup; } } + if (1) { + Scene *scene = CTX_data_scene(C); + if (scene && scene->camera) { + BKE_imbuf_stamp_info(scene, scene->camera, ibuf); + } + } } /* fancy multiview OpenEXR */ @@ -1693,6 +1699,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI } else { colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf); + IMB_metadata_copy(colormanaged_ibuf, ibuf); ok = BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, imf, save_copy); save_imbuf_post(ibuf, colormanaged_ibuf); } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 32584a3a2df..a9a5e601e10 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -683,7 +683,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) View2D *v2d = &ar->v2d; //View2DScrollers *scrollers; float col[3]; - + /* XXX not supported yet, disabling for now */ scene->r.scemode &= ~R_COMP_CROP; diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index f4189a18da4..d1495d85e64 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../blenkernel ../../blenlib ../../bmesh + ../../imbuf ../../gpu ../../makesdna ../../makesrna diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index a39832dd1cb..7c7f2db09d2 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -547,8 +547,21 @@ void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, const float col[4], struct ColorManagedDisplay *display, int x1, int y1, int x2, int y2); -/* defined in metadata.c */ +/** + * + * \attention Defined in metadata.c + */ +/** read the field from the image info into the field + * \param img - the ImBuf that contains the image data + * \param key - the key of the field + * \param value - the data in the field, first one found with key is returned, + * memory has to be allocated by user. + * \param len - length of value buffer allocated by user. + * \return - 1 (true) if ImageInfo present and value for the key found, 0 (false) otherwise + */ +bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *value, const size_t len); bool IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *field); +void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb); /* exported for image tools in blender, to quickly allocate 32 bits rect */ bool imb_addrectImBuf(struct ImBuf *ibuf); diff --git a/source/blender/imbuf/intern/IMB_metadata.h b/source/blender/imbuf/intern/IMB_metadata.h index 5d4a0028ee1..bc0b2c70ecb 100644 --- a/source/blender/imbuf/intern/IMB_metadata.h +++ b/source/blender/imbuf/intern/IMB_metadata.h @@ -47,16 +47,6 @@ struct ImBuf; /* free blender ImMetaData struct */ void IMB_metadata_free(struct ImBuf *img); -/** read the field from the image info into the field - * \param img - the ImBuf that contains the image data - * \param key - the key of the field - * \param value - the data in the field, first one found with key is returned, - * memory has to be allocated by user. - * \param len - length of value buffer allocated by user. - * \return - 1 (true) if ImageInfo present and value for the key found, 0 (false) otherwise - */ -bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *value, const size_t len); - /** set user data in the ImMetaData struct, which has to be allocated with IMB_metadata_create * before calling this function. * \param img - the ImBuf that contains the image data diff --git a/source/blender/imbuf/intern/metadata.c b/source/blender/imbuf/intern/metadata.c index 8cb5070dd62..134bbe88f15 100644 --- a/source/blender/imbuf/intern/metadata.c +++ b/source/blender/imbuf/intern/metadata.c @@ -79,6 +79,13 @@ bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *field, con return retval; } +void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb) +{ + if (simb->metadata) { + dimb->metadata = IDP_CopyProperty(simb->metadata); + } +} + bool IMB_metadata_add_field(struct ImBuf *img, const char *key, const char *value) { IDProperty *prop; diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 29b78c158fd..09651bdbf3a 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -834,6 +834,7 @@ typedef enum eSpaceImage_Flag { SI_COLOR_CORRECTION = (1 << 24), SI_NO_DRAW_TEXPAINT = (1 << 25), + SI_DRAW_METADATA = (1 << 26) } eSpaceImage_Flag; /* Text Editor ============================================ */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index e174d1ce5d0..fd03840b145 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -1917,6 +1917,11 @@ static void rna_def_space_image_uv(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Draw Other Objects", "Draw other selected objects that share the same image"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); + prop = RNA_def_property(srna, "show_metadata", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_DRAW_METADATA); + RNA_def_property_ui_text(prop, "Draw Metadata", "Draw metadata properties of the image"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); + prop = RNA_def_property(srna, "show_texpaint", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SI_NO_DRAW_TEXPAINT); RNA_def_property_ui_text(prop, "Draw Texture Paint UVs", "Draw overlay of texture paint uv layer"); -- cgit v1.2.3 From 3091ea49fec8b85b602aa94f229992f78c335b7a Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 21 Apr 2015 17:15:40 +0200 Subject: Metadata: * Theme support for metadata display * Increase text DPI with scaling. --- source/blender/editors/include/UI_resources.h | 5 +- source/blender/editors/interface/resources.c | 7 ++ source/blender/editors/screen/area.c | 126 +++++++++++++------------- source/blender/makesdna/DNA_userdef_types.h | 3 + source/blender/makesrna/intern/rna_userdef.c | 12 +++ 5 files changed, 91 insertions(+), 62 deletions(-) diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 3923c5c4432..2b19b6180e5 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -294,7 +294,10 @@ enum { TH_INFO_DEBUG_TEXT, TH_VIEW_OVERLAY, - TH_V3D_CLIPPING_BORDER + TH_V3D_CLIPPING_BORDER, + + TH_METADATA_BG, + TH_METADATA_TEXT }; /* XXX WARNING: previous is saved in file, so do not change order! */ diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 15e742c930a..b90c1c10093 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -569,6 +569,13 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo cp = ts->paint_curve_pivot; break; + case TH_METADATA_BG: + cp =ts->metadatabg; + break; + case TH_METADATA_TEXT: + cp =ts->metadatatext; + break; + case TH_UV_OTHERS: cp = ts->uv_others; break; diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 1c87d959dc4..fff55842f71 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2046,75 +2046,81 @@ const char *meta_data_list[] = "Scene" }; -BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index) +BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index, int offset) { - return (IMB_metadata_get_field(ibuf, meta_data_list[index], r_str, MAX_METADATA_STR) && r_str[0]); + return (IMB_metadata_get_field(ibuf, meta_data_list[index], r_str + offset, MAX_METADATA_STR - offset) && r_str[0]); } -static void metadata_draw_lines(ImBuf *ibuf, rcti rect, int fontid, const bool is_top) +static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool is_top, float factor) { char temp_str[MAX_METADATA_STR]; int line_width, line_height; int ofs_y = 0; - short line_index; short i; + int len; - for (line_index = 0; line_index < 4 && is_top == true; line_index++) { - /* first line */ - if (line_index == 0) { - int len; - bool do_newline = false; - float height = 0.0; - BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]); - len = strlen(temp_str); - if (metadata_is_valid(ibuf, temp_str + len, 0)) { - BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit), - rect.ymax - (1.5f * U.widget_unit - UI_UNIT_Y), 0.0f); - BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); - do_newline = true; - height = BLF_height(fontid, temp_str, strlen(temp_str)); - } + if (is_top) { + for (i = 0; i < 4; i++) { + /* first line */ + if (i == 0) { + bool do_newline = false; + float height = 0.0; + BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]); + len = strlen(temp_str); + if (metadata_is_valid(ibuf, temp_str, 0, len)) { + BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit), + rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y), 0.0f); + BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + do_newline = true; + height = BLF_height(fontid, temp_str, strlen(temp_str)); + } - BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]); - len = strlen(temp_str); - if (metadata_is_valid(ibuf, temp_str + len, 1)) { + BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[1]); len = strlen(temp_str); - line_width = BLF_width(fontid, temp_str, len); - BLF_position(fontid, rect.xmax - line_width - (0.2f * U.widget_unit), - rect.ymax - (1.5f * U.widget_unit - UI_UNIT_Y), 0.0f); - BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); - do_newline = true; - height = max_ff(BLF_height(fontid, temp_str, len), height); - } + if (metadata_is_valid(ibuf, temp_str, 1, len)) { + len = strlen(temp_str); + line_width = BLF_width(fontid, temp_str, len); + BLF_position(fontid, rect.xmax - line_width - (0.2f * U.widget_unit), + rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y), 0.0f); + BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + do_newline = true; + height = max_ff(BLF_height(fontid, temp_str, len), height); + } - if (do_newline) - ofs_y += (height + (0.2f * U.widget_unit)); - } - else if (line_index == 1) { - if (metadata_is_valid(ibuf, temp_str, line_index + 1)) { - BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit), - rect.ymax - (1.5f * U.widget_unit - UI_UNIT_Y) - ofs_y, 0.0f); - BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); - ofs_y += (BLF_height(fontid, temp_str, strlen(temp_str)) + (0.2f * U.widget_unit)); + if (do_newline) + ofs_y += (height + (0.2f * U.widget_unit)); } - } - else { - if (metadata_is_valid(ibuf, temp_str, line_index + 1)) { - BLF_position(fontid, rect.xmax + (0.2f * U.widget_unit), - rect.ymax - (1.5f * U.widget_unit - UI_UNIT_Y) - ofs_y, 0.0f); - BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); - ofs_y += (BLF_height(fontid, temp_str, strlen(temp_str)) + (0.2f * U.widget_unit)); + else if (i == 1) { + BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]); + len = strlen(temp_str); + if (metadata_is_valid(ibuf, temp_str, i + 1, len)) { + BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit), + rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y) - ofs_y, 0.0f); + BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + ofs_y += (BLF_height(fontid, temp_str, strlen(temp_str)) + (0.2f * U.widget_unit)); + } + } + else { + BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]); + len = strlen(temp_str); + if (metadata_is_valid(ibuf, temp_str, i + 1, len)) { + BLF_position(fontid, rect.xmax + (0.2f * U.widget_unit), + rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y) - ofs_y, 0.0f); + BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + ofs_y += (BLF_height(fontid, temp_str, strlen(temp_str)) + (0.2f * U.widget_unit)); + } } } } - - if (is_top == false) { + else { int ofs_x = 0; for (i = 5; i < 10; i++) { - if (metadata_is_valid(ibuf, temp_str, i)) { + BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i]); + len = strlen(temp_str); + if (metadata_is_valid(ibuf, temp_str, i, len)) { line_height = BLF_height(fontid, temp_str, strlen(temp_str)); BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit) + ofs_x, - rect.ymin - line_height + (1.5f * U.widget_unit), 0.0f); + rect.ymin - line_height + factor * (1.5f * U.widget_unit), 0.0f); BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); ofs_x += BLF_width(fontid, temp_str, strlen(temp_str)) + UI_UNIT_X; @@ -2131,14 +2137,14 @@ static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top) if (is_top) { for (i = 0; i < 5 ; i++) { - if (metadata_is_valid(ibuf, str, i)) { + if (metadata_is_valid(ibuf, str, i, 0)) { height += BLF_height(fontid, str, strlen(str)); } } } else { for (i = 5; i < 10; i++) { - if (metadata_is_valid(ibuf, str, i)) { + if (metadata_is_valid(ibuf, str, i, 0)) { height += BLF_height(fontid, str, strlen(str)); } } @@ -2173,14 +2179,15 @@ void ED_region_image_metadata_draw(ARegion *ar, ImBuf *ibuf, float zoomx, float glTranslatef(x, y, 0.0f); glScalef(zoomx, zoomy, 1.0f); + BLF_size(fontid, style->widgetlabel.points, U.dpi * zoomy); + /* *** upper box*** */ /* get needed box height */ box_y = metadata_box_height_get(ibuf, fontid, true); if (box_y) { - glColor3f(0.1f, 0.1f, 0.1f); - //glColor3f(1.0f, 0.15f, 0.8f); /* Pinkyfied version for Pablo */ + UI_ThemeColor(TH_METADATA_BG); /* set up rect */ BLI_rcti_init(&rect, 0, ibuf->x, ibuf->y, ibuf->y + box_y); @@ -2190,9 +2197,8 @@ void ED_region_image_metadata_draw(ARegion *ar, ImBuf *ibuf, float zoomx, float BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax); BLF_enable(fontid, BLF_CLIPPING); - glColor3f(1.0f, 1.0f, 1.0f); - - metadata_draw_lines(ibuf, rect, fontid, true); + UI_ThemeColor(TH_TEXT_HI); + metadata_draw_imbuf(ibuf, rect, fontid, true, zoomy); BLF_disable(fontid, BLF_CLIPPING); } @@ -2203,8 +2209,7 @@ void ED_region_image_metadata_draw(ARegion *ar, ImBuf *ibuf, float zoomx, float box_y = metadata_box_height_get(ibuf, fontid, false); if (box_y) { - glColor3f(0.1f, 0.1f, 0.1f); - //glColor3f(1.0f, 0.15f, 0.8f); /* Pinkyfied version for Pablo */ + UI_ThemeColor(TH_METADATA_BG); /* set up box rect */ BLI_rcti_init(&rect, 0, ibuf->x, -box_y, 0); @@ -2214,9 +2219,8 @@ void ED_region_image_metadata_draw(ARegion *ar, ImBuf *ibuf, float zoomx, float BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax); BLF_enable(fontid, BLF_CLIPPING); - glColor3f(1.0f, 1.0f, 1.0f); - - metadata_draw_lines(ibuf, rect, fontid, false); + UI_ThemeColor(TH_TEXT_HI); + metadata_draw_imbuf(ibuf, rect, fontid, false, zoomy); BLF_disable(fontid, BLF_CLIPPING); } diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index afa1f03a8ca..e0b51a1b25b 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -338,6 +338,9 @@ typedef struct ThemeSpace { char paint_curve_pivot[4]; char paint_curve_handle[4]; + + char metadatabg[4]; + char metadatatext[4]; } ThemeSpace; diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index b5ce031dd80..58f355bdf52 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2386,6 +2386,18 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Current Frame", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + prop = RNA_def_property(srna, "metadatabg", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "metadatabg"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Metadata Background", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "metadatatext", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "metadatatext"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Metadata Text", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + rna_def_userdef_theme_spaces_curves(srna, false, false, false, true); rna_def_userdef_theme_spaces_paint_curves(srna); -- cgit v1.2.3 From 58c511fb0149339b8942bb2124c215fd70219b63 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 21 Apr 2015 18:33:33 +0200 Subject: Stamp refactoring: Write those on render result during rendering, so we can cleanly write a render result image after rendering. --- source/blender/blenkernel/BKE_image.h | 6 ++- source/blender/blenkernel/intern/image.c | 56 ++++++++++++++-------- source/blender/editors/render/render_opengl.c | 6 ++- source/blender/editors/space_image/image_ops.c | 7 +-- source/blender/render/extern/include/RE_pipeline.h | 5 +- source/blender/render/intern/source/pipeline.c | 26 ++++++---- .../blender/render/intern/source/render_result.c | 4 +- 7 files changed, 70 insertions(+), 40 deletions(-) diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index ad191968a40..abfe0e98acf 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -46,6 +46,7 @@ struct ImageFormatData; struct ImagePool; struct Main; struct ReportList; +struct RenderResult; #define IMA_MAX_SPACE 64 @@ -58,10 +59,11 @@ void BKE_image_free_buffers(struct Image *image); /* call from library */ void BKE_image_free(struct Image *image); -void BKE_imbuf_stamp_info(struct Scene *scene, struct Object *camera, struct ImBuf *ibuf); +void BKE_render_result_stamp_info(struct Scene *scene, struct Object *camera, struct RenderResult *rr); +void BKE_imbuf_stamp_info(struct RenderResult *rr, struct ImBuf *ibuf); void BKE_image_stamp_buf(struct Scene *scene, struct Object *camera, unsigned char *rect, float *rectf, int width, int height, int channels); bool BKE_imbuf_alpha_test(struct ImBuf *ibuf); -int BKE_imbuf_write_stamp(struct Scene *scene, struct Object *camera, struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf); +int BKE_imbuf_write_stamp(struct Scene *scene, struct RenderResult *rr, struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf); void BKE_imbuf_write_prepare(struct ImBuf *ibuf, struct ImageFormatData *imf); int BKE_imbuf_write(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf); int BKE_imbuf_write_as(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf, const bool is_copy); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index a09c42e9178..88a96ddef18 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2028,26 +2028,45 @@ void BKE_image_stamp_buf( #undef BUFF_MARGIN_Y } -void BKE_imbuf_stamp_info(Scene *scene, Object *camera, struct ImBuf *ibuf) +void BKE_render_result_stamp_info(Scene *scene, Object *camera, struct RenderResult *rr) { - struct StampData stamp_data; + struct StampData *stamp_data; + + if (!(scene && scene->r.stamp & R_STAMP_ALL)) + return; + + if (!rr->stamp_data) { + stamp_data = MEM_callocN(sizeof(StampData), "RenderResult.stamp_data"); + } + else { + stamp_data = rr->stamp_data; + } - if (!ibuf) return; + stampdata(scene, camera, stamp_data, 0); - /* fill all the data values, no prefix */ - stampdata(scene, camera, &stamp_data, 0); + if (!rr->stamp_data) { + rr->stamp_data = stamp_data; + } +} - if (stamp_data.file[0]) IMB_metadata_change_field(ibuf, "File", stamp_data.file); - if (stamp_data.note[0]) IMB_metadata_change_field(ibuf, "Note", stamp_data.note); - if (stamp_data.date[0]) IMB_metadata_change_field(ibuf, "Date", stamp_data.date); - if (stamp_data.marker[0]) IMB_metadata_change_field(ibuf, "Marker", stamp_data.marker); - if (stamp_data.time[0]) IMB_metadata_change_field(ibuf, "Time", stamp_data.time); - if (stamp_data.frame[0]) IMB_metadata_change_field(ibuf, "Frame", stamp_data.frame); - if (stamp_data.camera[0]) IMB_metadata_change_field(ibuf, "Camera", stamp_data.camera); - if (stamp_data.cameralens[0]) IMB_metadata_change_field(ibuf, "Lens", stamp_data.cameralens); - if (stamp_data.scene[0]) IMB_metadata_change_field(ibuf, "Scene", stamp_data.scene); - if (stamp_data.strip[0]) IMB_metadata_change_field(ibuf, "Strip", stamp_data.strip); - if (stamp_data.rendertime[0]) IMB_metadata_change_field(ibuf, "RenderTime", stamp_data.rendertime); + +void BKE_imbuf_stamp_info(RenderResult *rr, struct ImBuf *ibuf) +{ + struct StampData *stamp_data = rr->stamp_data; + + if (!ibuf || !stamp_data) return; + + if (stamp_data->file[0]) IMB_metadata_change_field(ibuf, "File", stamp_data->file); + if (stamp_data->note[0]) IMB_metadata_change_field(ibuf, "Note", stamp_data->note); + if (stamp_data->date[0]) IMB_metadata_change_field(ibuf, "Date", stamp_data->date); + if (stamp_data->marker[0]) IMB_metadata_change_field(ibuf, "Marker", stamp_data->marker); + if (stamp_data->time[0]) IMB_metadata_change_field(ibuf, "Time", stamp_data->time); + if (stamp_data->frame[0]) IMB_metadata_change_field(ibuf, "Frame", stamp_data->frame); + if (stamp_data->camera[0]) IMB_metadata_change_field(ibuf, "Camera", stamp_data->camera); + if (stamp_data->cameralens[0]) IMB_metadata_change_field(ibuf, "Lens", stamp_data->cameralens); + if (stamp_data->scene[0]) IMB_metadata_change_field(ibuf, "Scene", stamp_data->scene); + if (stamp_data->strip[0]) IMB_metadata_change_field(ibuf, "Strip", stamp_data->strip); + if (stamp_data->rendertime[0]) IMB_metadata_change_field(ibuf, "RenderTime", stamp_data->rendertime); } bool BKE_imbuf_alpha_test(ImBuf *ibuf) @@ -2242,15 +2261,14 @@ int BKE_imbuf_write_as(ImBuf *ibuf, const char *name, ImageFormatData *imf, return ok; } -int BKE_imbuf_write_stamp(Scene *scene, struct Object *camera, ImBuf *ibuf, const char *name, struct ImageFormatData *imf) +int BKE_imbuf_write_stamp(Scene *scene, struct RenderResult *rr, ImBuf *ibuf, const char *name, struct ImageFormatData *imf) { if (scene && scene->r.stamp & R_STAMP_ALL) - BKE_imbuf_stamp_info(scene, camera, ibuf); + BKE_imbuf_stamp_info(rr, ibuf); return BKE_imbuf_write(ibuf, name, imf); } - static void do_makepicstring( char *string, const char *base, const char *relbase, int frame, const char imtype, const ImageFormatData *im_format, const short use_ext, const short use_frames, diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 35478cc864f..164f5f4bfd7 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -478,12 +478,14 @@ static void screen_opengl_render_write(OGLRender *oglrender) rr = RE_AcquireResultRead(oglrender->re); + BKE_render_result_stamp_info(scene, camera, rr); + BKE_image_path_from_imformat( name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false, NULL); /* write images as individual images or stereo */ - ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, camera, false, name); + ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, false, name); RE_ReleaseResultImage(oglrender->re); @@ -805,7 +807,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) } } else { - ok = RE_WriteRenderViewsImage(op->reports, rr, scene, scene->camera, true, name); + ok = RE_WriteRenderViewsImage(op->reports, rr, scene, true, name); if (ok) { printf("Saved: %s", name); BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 2fe2e6615a6..db4029d9678 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1672,12 +1672,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI goto cleanup; } } - if (1) { - Scene *scene = CTX_data_scene(C); - if (scene && scene->camera) { - BKE_imbuf_stamp_info(scene, scene->camera, ibuf); - } - } + BKE_imbuf_stamp_info(rr, ibuf); } /* fancy multiview OpenEXR */ diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 20678b29d0e..39e17c28162 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -49,6 +49,7 @@ struct Scene; struct SceneRenderLayer; struct EnvMap; struct RenderResult; +struct StampData; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* this include is what is exposed of render to outside world */ @@ -171,6 +172,8 @@ typedef struct RenderResult { /* render info text */ char *text; char *error; + + struct StampData *stamp_data; } RenderResult; @@ -261,7 +264,7 @@ void RE_init_threadcount(Render *re); /* the main processor, assumes all was set OK! */ void RE_TileProcessor(struct Render *re); -bool RE_WriteRenderViewsImage(struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, struct Object *camera, const bool stamp, char *name); +bool RE_WriteRenderViewsImage(struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, const bool stamp, char *name); bool RE_WriteRenderViewsMovie(struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, struct RenderData *rd, struct bMovieHandle *mh, const size_t width, const size_t height, void **movie_ctx_arr, const size_t totvideos, bool preview); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index e9b0a2bcbf4..d25de64978e 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -363,6 +363,7 @@ void RE_AcquireResultImageViews(Render *re, RenderResult *rr) rr->layers = re->result->layers; rr->xof = re->disprect.xmin; rr->yof = re->disprect.ymin; + rr->stamp_data = re->result->stamp_data; } } } @@ -3026,12 +3027,17 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr scene->r.cfra = frame; if (render_initialize_from_main(re, &scene->r, bmain, scene, srl, camera_override, lay_override, 0, 0)) { + Object *camera; MEM_reset_peak_memory(); BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE); do_render_all_options(re); + /* save render result stamp if needed */ + camera = RE_GetCamera(re); + BKE_render_result_stamp_info(scene, camera, re->result); + if (write_still && !G.is_break) { if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { /* operator checks this but in case its called from elsewhere */ @@ -3082,7 +3088,7 @@ void RE_RenderFreestyleExternal(Render *re) } #endif -bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scene, struct Object *camera, const bool stamp, char *name) +bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scene, const bool stamp, char *name) { bool is_mono; bool ok = true; @@ -3125,8 +3131,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen if (stamp) { /* writes the name of the individual cameras */ - Object *view_camera = BKE_camera_multiview_render(scene, camera, rv->name); - ok = BKE_imbuf_write_stamp(scene, view_camera, ibuf, name, &rd->im_format); + ok = BKE_imbuf_write_stamp(scene, rr, ibuf, name, &rd->im_format); } else { ok = BKE_imbuf_write(ibuf, name, &rd->im_format); @@ -3152,8 +3157,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen if (stamp) { /* writes the name of the individual cameras */ - Object *view_camera = BKE_camera_multiview_render(scene, camera, rv->name); - ok = BKE_imbuf_write_stamp(scene, view_camera, ibuf, name, &rd->im_format); + ok = BKE_imbuf_write_stamp(scene, rr, ibuf, name, &rd->im_format); } else { ok = BKE_imbuf_write(ibuf, name, &rd->im_format); @@ -3188,7 +3192,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen ibuf_arr[2] = IMB_stereo3d_ImBuf(&scene->r.im_format, ibuf_arr[0], ibuf_arr[1]); if (stamp) - ok = BKE_imbuf_write_stamp(scene, camera, ibuf_arr[2], name, &rd->im_format); + ok = BKE_imbuf_write_stamp(scene, rr, ibuf_arr[2], name, &rd->im_format); else ok = BKE_imbuf_write(ibuf_arr[2], name, &rd->im_format); @@ -3214,7 +3218,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen &scene->display_settings, &imf); if (stamp) - ok = BKE_imbuf_write_stamp(scene, camera, ibuf_arr[2], name, &rd->im_format); + ok = BKE_imbuf_write_stamp(scene, rr, ibuf_arr[2], name, &rd->im_format); else ok = BKE_imbuf_write(ibuf_arr[2], name, &imf); @@ -3324,7 +3328,6 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie RenderResult rres; double render_time; bool ok = true; - Object *camera = RE_GetCamera(re); RE_AcquireResultImageViews(re, &rres); @@ -3341,7 +3344,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL); /* write images as individual images or stereo */ - ok = RE_WriteRenderViewsImage(re->reports, &rres, scene, camera, true, name); + ok = RE_WriteRenderViewsImage(re->reports, &rres, scene, true, name); } RE_ReleaseResultImageViews(re, &rres); @@ -3469,6 +3472,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri } else { for (nfra = sfra, scene->r.cfra = sfra; scene->r.cfra <= efra; scene->r.cfra++) { + Object *camera; char name[FILE_MAX]; /* only border now, todo: camera lens. (ton) */ @@ -3567,6 +3571,10 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri do_render_all_options(re); totrendered++; + /* save render result stamp if needed */ + camera = RE_GetCamera(re); + BKE_render_result_stamp_info(scene, camera, re->result); + if (re->test_break(re->tbh) == 0) { if (!G.is_break) if (!do_write_image_or_movie(re, bmain, scene, mh, totvideos, NULL)) diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 303494d2beb..0d3720a9eca 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -115,7 +115,9 @@ void render_result_free(RenderResult *res) MEM_freeN(res->text); if (res->error) MEM_freeN(res->error); - + if (res->stamp_data) + MEM_freeN(res->stamp_data); + MEM_freeN(res); } -- cgit v1.2.3 From e1ce83f7629750a5900e0c0e83c6aa2860160aec Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 21 Apr 2015 19:01:09 +0200 Subject: Initialize and use the theme for metadata text --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/editors/interface/resources.c | 9 +++++++++ source/blender/editors/screen/area.c | 4 ++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 0789335de6a..081553826f4 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 274 -#define BLENDER_SUBVERSION 4 +#define BLENDER_SUBVERSION 5 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 5 diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index b90c1c10093..76985331568 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -2609,6 +2609,15 @@ void init_userdef_do_versions(void) cp[3] = 255; } } + + if (U.versionfile < 274 || (U.versionfile == 274 && U.subversionfile < 5)) { + bTheme *btheme; + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + copy_v4_v4_char(btheme->tima.metadatatext, btheme->tima.text_hi); + copy_v4_v4_char(btheme->tseq.metadatatext, btheme->tseq.text_hi); + } + } + if (U.pixelsize == 0.0f) U.pixelsize = 1.0f; diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index fff55842f71..63eaf7d0296 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2197,7 +2197,7 @@ void ED_region_image_metadata_draw(ARegion *ar, ImBuf *ibuf, float zoomx, float BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax); BLF_enable(fontid, BLF_CLIPPING); - UI_ThemeColor(TH_TEXT_HI); + UI_ThemeColor(TH_METADATA_TEXT); metadata_draw_imbuf(ibuf, rect, fontid, true, zoomy); BLF_disable(fontid, BLF_CLIPPING); @@ -2219,7 +2219,7 @@ void ED_region_image_metadata_draw(ARegion *ar, ImBuf *ibuf, float zoomx, float BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax); BLF_enable(fontid, BLF_CLIPPING); - UI_ThemeColor(TH_TEXT_HI); + UI_ThemeColor(TH_METADATA_TEXT); metadata_draw_imbuf(ibuf, rect, fontid, false, zoomy); BLF_disable(fontid, BLF_CLIPPING); -- cgit v1.2.3 From b47892e9f5e279bb8d9ee2e0ea6f31cff099103a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 22 Apr 2015 04:43:13 +1000 Subject: Minor edits to metadata commit No need to calculate height of each line, just use height of font. --- source/blender/editors/interface/resources.c | 4 ++-- source/blender/editors/screen/area.c | 17 +++++++---------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 76985331568..8e003e50df3 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -570,10 +570,10 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo break; case TH_METADATA_BG: - cp =ts->metadatabg; + cp = ts->metadatabg; break; case TH_METADATA_TEXT: - cp =ts->metadatatext; + cp = ts->metadatatext; break; case TH_UV_OTHERS: diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 63eaf7d0296..4b0d1d02198 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2054,17 +2054,17 @@ BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index, int off static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool is_top, float factor) { char temp_str[MAX_METADATA_STR]; - int line_width, line_height; + int line_width; int ofs_y = 0; short i; int len; + const float height = BLF_height_max(fontid); if (is_top) { for (i = 0; i < 4; i++) { /* first line */ if (i == 0) { bool do_newline = false; - float height = 0.0; BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]); len = strlen(temp_str); if (metadata_is_valid(ibuf, temp_str, 0, len)) { @@ -2072,19 +2072,16 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y), 0.0f); BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); do_newline = true; - height = BLF_height(fontid, temp_str, strlen(temp_str)); } BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[1]); len = strlen(temp_str); if (metadata_is_valid(ibuf, temp_str, 1, len)) { - len = strlen(temp_str); - line_width = BLF_width(fontid, temp_str, len); + line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); BLF_position(fontid, rect.xmax - line_width - (0.2f * U.widget_unit), rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y), 0.0f); BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); do_newline = true; - height = max_ff(BLF_height(fontid, temp_str, len), height); } if (do_newline) @@ -2097,7 +2094,7 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit), rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y) - ofs_y, 0.0f); BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); - ofs_y += (BLF_height(fontid, temp_str, strlen(temp_str)) + (0.2f * U.widget_unit)); + ofs_y += (height + (0.2f * U.widget_unit)); } } else { @@ -2107,7 +2104,7 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i BLF_position(fontid, rect.xmax + (0.2f * U.widget_unit), rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y) - ofs_y, 0.0f); BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); - ofs_y += (BLF_height(fontid, temp_str, strlen(temp_str)) + (0.2f * U.widget_unit)); + ofs_y += (height + (0.2f * U.widget_unit)); } } } @@ -2118,12 +2115,12 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i]); len = strlen(temp_str); if (metadata_is_valid(ibuf, temp_str, i, len)) { - line_height = BLF_height(fontid, temp_str, strlen(temp_str)); + const int line_height = height; BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit) + ofs_x, rect.ymin - line_height + factor * (1.5f * U.widget_unit), 0.0f); BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); - ofs_x += BLF_width(fontid, temp_str, strlen(temp_str)) + UI_UNIT_X; + ofs_x += BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX) + UI_UNIT_X; } } } -- cgit v1.2.3 From c9f9e295387a8cb96a92acf5a66d94149e750850 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 22 Apr 2015 04:10:15 +1000 Subject: Math Lib: handling bits handling into own file --- source/blender/blenlib/BLI_math_base.h | 3 -- source/blender/blenlib/BLI_math_bits.h | 45 ++++++++++++++++++++++ source/blender/blenlib/CMakeLists.txt | 2 + source/blender/blenlib/intern/math_base_inline.c | 19 --------- source/blender/blenlib/intern/math_bits_inline.c | 49 ++++++++++++++++++++++++ source/blender/editors/mesh/editmesh_select.c | 1 + 6 files changed, 97 insertions(+), 22 deletions(-) create mode 100644 source/blender/blenlib/BLI_math_bits.h create mode 100644 source/blender/blenlib/intern/math_bits_inline.c diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index daa7db8e3cf..ae2b6a4da9f 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -214,9 +214,6 @@ MINLINE int iroundf(float a); MINLINE int divide_round_i(int a, int b); MINLINE int mod_i(int i, int n); -MINLINE unsigned int highest_order_bit_i(unsigned int n); -MINLINE unsigned short highest_order_bit_s(unsigned short n); - double double_round(double x, int ndigits); #ifdef BLI_MATH_GCC_WARN_PRAGMA diff --git a/source/blender/blenlib/BLI_math_bits.h b/source/blender/blenlib/BLI_math_bits.h new file mode 100644 index 00000000000..2569c4cb41e --- /dev/null +++ b/source/blender/blenlib/BLI_math_bits.h @@ -0,0 +1,45 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + * */ + +#ifndef __BLI_MATH_BITS_H__ +#define __BLI_MATH_BITS_H__ + +/** \file BLI_math_bits.h + * \ingroup bli + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "BLI_math_inline.h" + +MINLINE unsigned int highest_order_bit_i(unsigned int n); +MINLINE unsigned short highest_order_bit_s(unsigned short n); + +#if BLI_MATH_DO_INLINE +#include "intern/math_bits_inline.c" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __BLI_MATH_BITS_H__ */ diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 73bd4869566..797bdaa2ae4 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -75,6 +75,7 @@ set(SRC intern/listbase.c intern/math_base.c intern/math_base_inline.c + intern/math_bits_inline.c intern/math_color.c intern/math_color_blend_inline.c intern/math_color_inline.c @@ -209,6 +210,7 @@ endif() # no need to compile object files for inline headers. set_source_files_properties( intern/math_base_inline.c + intern/math_bits_inline.c intern/math_color_blend_inline.c intern/math_color_inline.c intern/math_geom_inline.c diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index f5713824296..facee8b0a89 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -198,25 +198,6 @@ MINLINE int mod_i(int i, int n) return (i % n + n) % n; } -MINLINE unsigned int highest_order_bit_i(unsigned int n) -{ - n |= (n >> 1); - n |= (n >> 2); - n |= (n >> 4); - n |= (n >> 8); - n |= (n >> 16); - return n - (n >> 1); -} - -MINLINE unsigned short highest_order_bit_s(unsigned short n) -{ - n |= (n >> 1); - n |= (n >> 2); - n |= (n >> 4); - n |= (n >> 8); - return (unsigned short)(n - (n >> 1)); -} - MINLINE float min_ff(float a, float b) { return (a < b) ? a : b; diff --git a/source/blender/blenlib/intern/math_bits_inline.c b/source/blender/blenlib/intern/math_bits_inline.c new file mode 100644 index 00000000000..f5bec405b2c --- /dev/null +++ b/source/blender/blenlib/intern/math_bits_inline.c @@ -0,0 +1,49 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + * */ + +/** \file blender/blenlib/intern/math_bits_inline.c + * \ingroup bli + */ + +#ifndef __MATH_BITS_INLINE_C__ +#define __MATH_BITS_INLINE_C__ + +#include "BLI_math_bits.h" + +MINLINE unsigned int highest_order_bit_i(unsigned int n) +{ + n |= (n >> 1); + n |= (n >> 2); + n |= (n >> 4); + n |= (n >> 8); + n |= (n >> 16); + return n - (n >> 1); +} + +MINLINE unsigned short highest_order_bit_s(unsigned short n) +{ + n |= (n >> 1); + n |= (n >> 2); + n |= (n >> 4); + n |= (n >> 8); + return (unsigned short)(n - (n >> 1)); +} + +#endif /* __MATH_BITS_INLINE_C__ */ diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index da6a886e2af..90b683c5abd 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -36,6 +36,7 @@ #include "BLI_linklist.h" #include "BLI_linklist_stack.h" #include "BLI_math.h" +#include "BLI_math_bits.h" #include "BLI_rand.h" #include "BLI_array.h" -- cgit v1.2.3 From bf69453ae7f67e5e33d9f50d6abab095c058d740 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 22 Apr 2015 05:37:22 +1000 Subject: BLI_string: add BLI_snprintf_rlen use when the length of the destination string is needed. --- source/blender/blenkernel/intern/sequencer.c | 2 +- source/blender/blenkernel/intern/unit.c | 7 +--- source/blender/blenlib/BLI_string.h | 2 + source/blender/blenlib/intern/string.c | 43 ++++++++++++++++++++++ source/blender/blenlib/intern/timecode.c | 28 +++++++------- source/blender/editors/interface/interface.c | 4 +- source/blender/editors/screen/area.c | 15 +++----- source/blender/editors/space_nla/nla_draw.c | 6 +-- source/blender/editors/space_node/space_node.c | 6 +-- .../editors/space_sequencer/sequencer_draw.c | 4 +- source/blender/editors/space_view3d/drawobject.c | 22 +++++------ source/blender/editors/space_view3d/view3d_fly.c | 4 +- source/blender/editors/space_view3d/view3d_walk.c | 2 +- 13 files changed, 89 insertions(+), 56 deletions(-) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 535dcd6ba4d..f370570750f 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -4640,7 +4640,7 @@ static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char char name_esc[SEQ_NAME_MAXSTR * 2]; BLI_strescape(name_esc, name, sizeof(name_esc)); - return BLI_snprintf(str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc); + return BLI_snprintf_rlen(str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc); } /* XXX - hackish function needed for transforming strips! TODO - have some better solution */ diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index 5a2c77b5619..0d83695d2f1 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -370,12 +370,7 @@ static size_t unit_as_string(char *str, int len_max, double value, int prec, bUn value_conv = value / unit->scalar; /* Convert to a string */ - { - len = BLI_snprintf(str, len_max, "%.*f", prec, value_conv); - - if (len >= len_max) - len = len_max; - } + len = BLI_snprintf_rlen(str, len_max, "%.*f", prec, value_conv); /* Add unit prefix and strip zeros */ diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index c4853e37398..e6c1cc8b4b6 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -59,8 +59,10 @@ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict char *BLI_replacestrN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC; size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) ATTR_NONNULL(1, 3) ATTR_PRINTF_FORMAT(3, 4); +size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) ATTR_NONNULL(1, 3) ATTR_PRINTF_FORMAT(3, 4); size_t BLI_vsnprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, va_list arg) ATTR_PRINTF_FORMAT(3, 0); +size_t BLI_vsnprintf_rlen(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg) ATTR_PRINTF_FORMAT(3, 0); char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1, 2); diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index cc5a90dbc39..e41e52a7c6e 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -230,6 +230,30 @@ size_t BLI_vsnprintf(char *__restrict buffer, size_t maxncpy, const char *__rest return n; } +/** + * A version of #BLI_vsnprintf that returns ``strlen(buffer)`` + */ +size_t BLI_vsnprintf_rlen(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg) +{ + size_t n; + + BLI_assert(buffer != NULL); + BLI_assert(maxncpy > 0); + BLI_assert(format != NULL); + + n = (size_t)vsnprintf(buffer, maxncpy, format, arg); + + if (n != -1 && n < maxncpy) { + /* pass */ + } + else { + n = maxncpy - 1; + } + buffer[n] = '\0'; + + return n; +} + /** * Portable replacement for #snprintf */ @@ -249,6 +273,25 @@ size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict return n; } +/** + * A version of #BLI_snprintf that returns ``strlen(dst)`` + */ +size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) +{ + size_t n; + va_list arg; + +#ifdef DEBUG_STRSIZE + memset(dst, 0xff, sizeof(*dst) * maxncpy); +#endif + + va_start(arg, format); + n = BLI_vsnprintf_rlen(dst, maxncpy, format, arg); + va_end(arg); + + return n; +} + /** * Print formatted string into a newly #MEM_mallocN'd string * and return it. diff --git a/source/blender/blenlib/intern/timecode.c b/source/blender/blenlib/intern/timecode.c index 0c8834008b6..7b98d7830ee 100644 --- a/source/blender/blenlib/intern/timecode.c +++ b/source/blender/blenlib/intern/timecode.c @@ -113,22 +113,22 @@ size_t BLI_timecode_string_from_time( if (power <= 0) { /* include "frames" in display */ if (hours) { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d+%02d", neg, hours, minutes, seconds, frames); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d+%02d", neg, hours, minutes, seconds, frames); } else if (minutes) { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d+%02d", neg, minutes, seconds, frames); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d+%02d", neg, minutes, seconds, frames); } else { - rlen = BLI_snprintf(str, maxncpy, "%s%d+%02d", neg, seconds, frames); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%d+%02d", neg, seconds, frames); } } else { /* don't include 'frames' in display */ if (hours) { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d", neg, hours, minutes, seconds); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d", neg, hours, minutes, seconds); } else { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d", neg, minutes, seconds); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d", neg, minutes, seconds); } } break; @@ -137,10 +137,10 @@ size_t BLI_timecode_string_from_time( { /* reduced SMPTE format that always shows minutes, seconds, frames. Hours only shown as needed. */ if (hours) { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames); } else { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d", neg, minutes, seconds, frames); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d", neg, minutes, seconds, frames); } break; } @@ -156,10 +156,10 @@ size_t BLI_timecode_string_from_time( const int s_pad = ms_dp + 3; if (hours) { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%0*.*f", neg, hours, minutes, s_pad, ms_dp, time); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%0*.*f", neg, hours, minutes, s_pad, ms_dp, time); } else { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%0*.*f", neg, minutes, s_pad, ms_dp, time); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%0*.*f", neg, minutes, s_pad, ms_dp, time); } break; } @@ -168,10 +168,10 @@ size_t BLI_timecode_string_from_time( /* only show the original seconds display */ /* round to whole numbers if power is >= 1 (i.e. scale is coarse) */ if (power <= 0) { - rlen = BLI_snprintf(str, maxncpy, "%.*f", 1 - power, time_seconds); + rlen = BLI_snprintf_rlen(str, maxncpy, "%.*f", 1 - power, time_seconds); } else { - rlen = BLI_snprintf(str, maxncpy, "%d", iroundf(time_seconds)); + rlen = BLI_snprintf_rlen(str, maxncpy, "%d", iroundf(time_seconds)); } break; } @@ -179,7 +179,7 @@ size_t BLI_timecode_string_from_time( default: { /* full SMPTE format */ - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames); break; } } @@ -208,10 +208,10 @@ size_t BLI_timecode_string_from_time_simple( /* round to whole numbers if power is >= 1 (i.e. scale is coarse) */ if (power <= 0) { - rlen = BLI_snprintf(str, maxncpy, "%.*f", 1 - power, time_seconds); + rlen = BLI_snprintf_rlen(str, maxncpy, "%.*f", 1 - power, time_seconds); } else { - rlen = BLI_snprintf(str, maxncpy, "%d", iroundf(time_seconds)); + rlen = BLI_snprintf_rlen(str, maxncpy, "%d", iroundf(time_seconds)); } return rlen; diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 1e738668f9d..5c548d3afd5 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2765,11 +2765,11 @@ void ui_but_update(uiBut *but) } else { const int prec = ui_but_calc_float_precision(but, value); - slen += BLI_snprintf(but->drawstr + slen, sizeof(but->drawstr) - slen, "%.*f", prec, value); + slen += BLI_snprintf_rlen(but->drawstr + slen, sizeof(but->drawstr) - slen, "%.*f", prec, value); } } else { - slen += BLI_snprintf(but->drawstr + slen, sizeof(but->drawstr) - slen, "%d", (int)value); + slen += BLI_snprintf_rlen(but->drawstr + slen, sizeof(but->drawstr) - slen, "%d", (int)value); } if (but->rnaprop) { diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 4b0d1d02198..c6de4e5df88 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2065,8 +2065,7 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i /* first line */ if (i == 0) { bool do_newline = false; - BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]); - len = strlen(temp_str); + len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]); if (metadata_is_valid(ibuf, temp_str, 0, len)) { BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit), rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y), 0.0f); @@ -2074,8 +2073,7 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i do_newline = true; } - BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[1]); - len = strlen(temp_str); + len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[1]); if (metadata_is_valid(ibuf, temp_str, 1, len)) { line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); BLF_position(fontid, rect.xmax - line_width - (0.2f * U.widget_unit), @@ -2088,8 +2086,7 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i ofs_y += (height + (0.2f * U.widget_unit)); } else if (i == 1) { - BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]); - len = strlen(temp_str); + len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]); if (metadata_is_valid(ibuf, temp_str, i + 1, len)) { BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit), rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y) - ofs_y, 0.0f); @@ -2098,8 +2095,7 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i } } else { - BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]); - len = strlen(temp_str); + len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]); if (metadata_is_valid(ibuf, temp_str, i + 1, len)) { BLF_position(fontid, rect.xmax + (0.2f * U.widget_unit), rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y) - ofs_y, 0.0f); @@ -2112,8 +2108,7 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i else { int ofs_x = 0; for (i = 5; i < 10; i++) { - BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i]); - len = strlen(temp_str); + len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i]); if (metadata_is_valid(ibuf, temp_str, i, len)) { const int line_height = height; BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit) + ofs_x, diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 52156a2394e..4d37fcc9276 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -433,7 +433,7 @@ static void nla_draw_strip_text(AnimData *adt, NlaTrack *nlt, NlaStrip *strip, i /* just print the name and the range */ if (strip->flag & NLASTRIP_FLAG_TEMP_META) { - str_len = BLI_snprintf(str, sizeof(str), "%d) Temp-Meta", index); + str_len = BLI_snprintf_rlen(str, sizeof(str), "%d) Temp-Meta", index); } else { str_len = BLI_strncpy_rlen(str, strip->name, sizeof(str)); @@ -490,11 +490,11 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V * while also preserving some accuracy, since we do use floats */ /* start frame */ - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->start); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->start); UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, numstr_len, col); /* end frame */ - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->end); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->end); UI_view2d_text_cache_add(v2d, strip->end, ymaxc + ytol, numstr, numstr_len, col); } diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 62cb0bc73cd..de90c417bdd 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -203,12 +203,10 @@ void ED_node_tree_path_get_fixedbuf(SpaceNode *snode, char *value, int max_lengt value[0] = '\0'; for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) { if (i == 0) { - BLI_strncpy(value, path->node_name, max_length); - size = strlen(path->node_name); + size = BLI_strncpy_rlen(value, path->node_name, max_length); } else { - BLI_snprintf(value, max_length, "/%s", path->node_name); - size = strlen(path->node_name) + 1; + size = BLI_snprintf_rlen(value, max_length, "/%s", path->node_name); } max_length -= size; if (max_length <= 0) diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index f07be97ff9f..abe2e866a75 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -425,12 +425,12 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla size_t numstr_len; if (direction == SEQ_LEFTHANDLE) { - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", seq->startdisp); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->startdisp); x1 = rx1; y1 -= 0.45f; } else { - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", seq->enddisp - 1); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->enddisp - 1); x1 = x2 - handsize_clamped * 0.75f; y1 = y2 + 0.05f; } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index f53fd967daa..24b814da44d 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -3372,7 +3372,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe unit->system, B_UNIT_LENGTH, do_split, false); } else { - numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2)); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2)); } view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); @@ -3449,7 +3449,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe angle = angle_normalized_v3v3(no_a, no_b); - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); } @@ -3474,7 +3474,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe 3, unit->system, B_UNIT_AREA, do_split, false); \ } \ else { \ - numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \ + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, area); \ } \ view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); \ } (void)0 @@ -3592,7 +3592,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe angle = angle_v3v3v3(v1, v2, v3); - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); interp_v3_v3v3(fvec, vmid, v2_local, 0.8f); view3d_cached_text_draw_add(fvec, numstr, numstr_len, 0, txt_flag, col); } @@ -3623,7 +3623,7 @@ static void draw_em_indices(BMEditMesh *em) UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col); BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); view3d_cached_text_draw_add(v->co, numstr, numstr_len, 0, txt_flag, col); } i++; @@ -3635,7 +3635,7 @@ static void draw_em_indices(BMEditMesh *em) UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col); BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); mid_v3_v3v3(pos, e->v1->co, e->v2->co); view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col); } @@ -3649,7 +3649,7 @@ static void draw_em_indices(BMEditMesh *em) BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { BM_face_calc_center_mean(f, pos); - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col); } i++; @@ -5397,15 +5397,15 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if (part->draw & PART_DRAW_NUM) { if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) { - numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health); + numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health); } else { - numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%d", a); + numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d", a); } } else { if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) { - numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%.2f", pa_health); + numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%.2f", pa_health); } } @@ -5646,7 +5646,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { float vec_txt[3]; - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%i", a); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%i", a); /* use worldspace because object matrix is already applied */ mul_v3_m4v3(vec_txt, ob->imat, cache[a]->co); view3d_cached_text_draw_add(vec_txt, numstr, numstr_len, diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index a3dfd62ba6b..469a7e63903 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -296,10 +296,10 @@ static void fly_update_header(bContext *C, FlyInfo *fly) "Ctrl: free look, " "X: Upright x axis (%s), " "Z: Upright z axis (%s), " - "(+/- | Wheel): speed"), + "(+/- | Wheel): speed"), WM_bool_as_string(fly->xlock != FLY_AXISLOCK_STATE_OFF), - WM_bool_as_string(fly->zlock != FLY_AXISLOCK_STATE_OFF)); + WM_bool_as_string(fly->zlock != FLY_AXISLOCK_STATE_OFF)); ED_area_headerprint(CTX_wm_area(C), header); #undef HEADER_LENGTH diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 11756e4feca..fb98f8b91a7 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -344,7 +344,7 @@ static void walk_update_header(bContext *C, WalkInfo *walk) char header[HEADER_LENGTH]; BLI_snprintf(header, HEADER_LENGTH, IFACE_("LMB/Return: confirm, Esc/RMB: cancel, " - "Tab: gravity (%s), " + "Tab: gravity (%s), " "WASD: move around, " "Shift: fast, Alt: slow, " "QE: up and down, MMB/Space: teleport, V: jump, " -- cgit v1.2.3 From 6885d316b1b4e275f055fc2adea9a21a03cbc260 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 21 Apr 2015 21:55:10 +0200 Subject: Fix T44474: Rotation manipulator not hidden completely with all axes locked Really doesn't look like a bug on a first glance but the line of code that was there previously seemed to be there to prevent the manipulator from drawing in this case. --- source/blender/editors/transform/transform_manipulator.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index fc8e6cd0286..ae8cbc721e3 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -895,6 +895,11 @@ static void postOrtho(const bool ortho) } } +BLI_INLINE bool manipulator_rotate_is_visible(const int drawflags) +{ + return (drawflags & (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z)); +} + static void draw_manipulator_rotate( View3D *v3d, RegionView3D *rv3d, const int drawflags, const int combo, const bool is_moving, const bool is_picksel) @@ -908,8 +913,8 @@ static void draw_manipulator_rotate( const int colcode = (is_moving) ? MAN_MOVECOL : MAN_RGB; bool ortho; - /* when called while moving in mixed mode, do not draw when... */ - if ((drawflags & MAN_ROT_C) == 0) return; + /* skip drawing if all axes are locked */ + if (manipulator_rotate_is_visible(drawflags) == false) return; /* Init stuff */ glDisable(GL_DEPTH_TEST); @@ -1448,8 +1453,8 @@ static void draw_manipulator_rotate_cyl( int axis_order[3] = {2, 0, 1}; int i; - /* when called while moving in mixed mode, do not draw when... */ - if ((drawflags & MAN_ROT_C) == 0) return; + /* skip drawing if all axes are locked */ + if (manipulator_rotate_is_visible(drawflags) == false) return; manipulator_axis_order(rv3d, axis_order); -- cgit v1.2.3 From f2956d5fc727e4d5233dc2fbb308764e58f71827 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 22 Apr 2015 01:35:32 +0500 Subject: Tracking: Fix over-allocation in plane track's point tracks pointers when removing point track --- source/blender/editors/space_clip/clip_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 5f919c9b51d..6a2a01620cd 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -221,7 +221,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) int track_index; MovieTrackingTrack **new_point_tracks; - new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * plane_track->point_tracksnr, + new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * (plane_track->point_tracksnr - 1), "new point tracks array"); for (i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) { -- cgit v1.2.3 From 9425a8ff381b51e519e19d9bd7484cf095a78c30 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Tue, 21 Apr 2015 17:36:18 -0300 Subject: BGE: scene.pre_draw_setup[] callback This callback allows the user to change the camera data right before the rendering calculations. scene.pre_draw[] is not enough here, because if you want to change the camera matrices (projection/modelview) the culling test is done before that (after pre_draw_setup[] though). Reviewers: moguri, campbellbarton Differential Revision: https://developer.blender.org/D1251 Python sample code using this. The sample scene would need a default camera (not used for rendering), a dummy camera ('Camera.VR'), and two cameras ('Camera.Left', 'Camera.Right') that will be used for the actual rendering. ``` import bge def callback(): scene = bge.logic.getCurrentScene() objects = scene.objects vr_camera = objects.get('Camera.VR') if bge.render.getStereoEye() == bge.render.LEFT_EYE: camera = objects.get('Camera.Left') else: camera = objects.get('Camera.Right') vr_camera.worldOrientation = camera.worldOrientation vr_camera.worldPosition = camera.worldPosition def init(): scene = bge.logic.getCurrentScene() main_camera = scene.active_camera main_camera.useViewport = True scene.pre_draw_setup.append(callback) objects = scene.objects vr_camera = objects.get('Camera.VR') vr_camera.useViewport = True vr_camera.setViewport( 0, 0, bge.render.getWindowWidth(), bge.render.getWindowHeight() ) ``` --- .../rst/bge_types/bge.types.KX_Scene.rst | 6 +++++ source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 4 +++ source/gameengine/Ketsji/KX_Scene.cpp | 29 ++++++++++++++++++++++ source/gameengine/Ketsji/KX_Scene.h | 4 +++ 4 files changed, 43 insertions(+) diff --git a/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst b/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst index a6135054058..f4846cd9265 100644 --- a/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst +++ b/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst @@ -125,6 +125,12 @@ base class --- :class:`PyObjectPlus` :type: list + .. attribute:: pre_draw_setup + + A list of callables to be run before the drawing setup (i.e., before the model view and projection matrices are computed). + + :type: list + .. attribute:: gravity The scene gravity using the world x, y and z axis. diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index f0b47684092..40af9b4ca39 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -1108,6 +1108,10 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) KX_SetActiveScene(scene); +#ifdef WITH_PYTHON + scene->RunDrawingCallbacks(scene->GetPreDrawSetupCB()); +#endif + GetSceneViewport(scene, cam, area, viewport); // store the computed viewport in the scene diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index a3e1d1562c9..ca4d017fe8c 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -238,6 +238,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_attr_dict = NULL; m_draw_call_pre = NULL; m_draw_call_post = NULL; + m_draw_setup_call_pre = NULL; #endif } @@ -2399,6 +2400,17 @@ PyObject *KX_Scene::pyattr_get_drawing_callback_post(void *self_v, const KX_PYAT return self->m_draw_call_post; } +PyObject *KX_Scene::pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self = static_cast(self_v); + + if (self->m_draw_setup_call_pre == NULL) + self->m_draw_setup_call_pre = PyList_New(0); + + Py_INCREF(self->m_draw_setup_call_pre); + return self->m_draw_setup_call_pre; +} + int KX_Scene::pyattr_set_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_Scene* self = static_cast(self_v); @@ -2433,6 +2445,22 @@ int KX_Scene::pyattr_set_drawing_callback_post(void *self_v, const KX_PYATTRIBUT return PY_SET_ATTR_SUCCESS; } +int KX_Scene::pyattr_set_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Scene* self = static_cast(self_v); + + if (!PyList_CheckExact(value)) { + PyErr_SetString(PyExc_ValueError, "Expected a list"); + return PY_SET_ATTR_FAIL; + } + + Py_XDECREF(self->m_draw_setup_call_pre); + Py_INCREF(value); + + self->m_draw_setup_call_pre = value; + return PY_SET_ATTR_SUCCESS; +} + PyObject *KX_Scene::pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_Scene* self = static_cast(self_v); @@ -2462,6 +2490,7 @@ PyAttributeDef KX_Scene::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera), KX_PYATTRIBUTE_RW_FUNCTION("pre_draw", KX_Scene, pyattr_get_drawing_callback_pre, pyattr_set_drawing_callback_pre), KX_PYATTRIBUTE_RW_FUNCTION("post_draw", KX_Scene, pyattr_get_drawing_callback_post, pyattr_set_drawing_callback_post), + KX_PYATTRIBUTE_RW_FUNCTION("pre_draw_setup", KX_Scene, pyattr_get_drawing_setup_callback_pre, pyattr_set_drawing_setup_callback_pre), KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_Scene, pyattr_get_gravity, pyattr_set_gravity), KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend), KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling), diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 93e764851a9..a5645ea6448 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -107,6 +107,7 @@ class KX_Scene : public PyObjectPlus, public SCA_IScene PyObject* m_attr_dict; PyObject* m_draw_call_pre; PyObject* m_draw_call_post; + PyObject* m_draw_setup_call_pre; #endif struct CullingInfo { @@ -631,6 +632,8 @@ public: static int pyattr_set_drawing_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_drawing_callback_post(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_drawing_setup_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_gravity(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); @@ -647,6 +650,7 @@ public: PyObject *GetPreDrawCB() { return m_draw_call_pre; } PyObject *GetPostDrawCB() { return m_draw_call_post; } + PyObject *GetPreDrawSetupCB() { return m_draw_setup_call_pre; } #endif /** -- cgit v1.2.3 From 260f75a2cad9f4af24682af063e3c2a7b38e2e39 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 22 Apr 2015 01:54:45 +0500 Subject: Tracking: Cleanup, move some plane tracks code to utility functions --- source/blender/blenkernel/BKE_tracking.h | 8 ++++ source/blender/blenkernel/intern/tracking.c | 58 ++++++++++++++++++++++++++ source/blender/editors/space_clip/clip_utils.c | 46 +------------------- 3 files changed, 67 insertions(+), 45 deletions(-) diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index ef997446c6c..5af05f4ca80 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -136,6 +136,14 @@ struct MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_active(struct Movie void BKE_tracking_plane_tracks_deselect_all(struct ListBase *plane_tracks_base); +bool BKE_tracking_plane_track_has_point_track(struct MovieTrackingPlaneTrack *plane_track, + struct MovieTrackingTrack *track); +bool BKE_tracking_plane_track_remove_point_track(struct MovieTrackingPlaneTrack *plane_track, + struct MovieTrackingTrack *track); + +void BKE_tracking_plane_tracks_remove_point_track(struct MovieTracking *tracking, + struct MovieTrackingTrack *track); + /* **** Plane Marker **** */ struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(struct MovieTrackingPlaneTrack *plane_track, struct MovieTrackingPlaneMarker *plane_marker); diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 83db0639468..e7dccc09376 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1302,6 +1302,64 @@ void BKE_tracking_plane_tracks_deselect_all(ListBase *plane_tracks_base) } } +bool BKE_tracking_plane_track_has_point_track(MovieTrackingPlaneTrack *plane_track, + MovieTrackingTrack *track) +{ + int i; + for (i = 0; i < plane_track->point_tracksnr; i++) { + if (plane_track->point_tracks[i] == track) { + return true; + } + } + return false; +} + +bool BKE_tracking_plane_track_remove_point_track(MovieTrackingPlaneTrack *plane_track, + MovieTrackingTrack *track) +{ + int i, track_index; + MovieTrackingTrack **new_point_tracks; + + if (plane_track->point_tracksnr <= 4) { + return false; + } + + new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * (plane_track->point_tracksnr - 1), + "new point tracks array"); + + for (i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) { + if (plane_track->point_tracks[i] != track) { + new_point_tracks[track_index++] = plane_track->point_tracks[i]; + } + } + + MEM_freeN(plane_track->point_tracks); + plane_track->point_tracks = new_point_tracks; + plane_track->point_tracksnr--; + + return true; +} + +void BKE_tracking_plane_tracks_remove_point_track(MovieTracking *tracking, + MovieTrackingTrack *track) +{ + MovieTrackingPlaneTrack *plane_track, *next_plane_track; + ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); + for (plane_track = plane_tracks_base->first; + plane_track; + plane_track = next_plane_track) + { + next_plane_track = plane_track->next; + if (BKE_tracking_plane_track_has_point_track(plane_track, track)) { + if (!BKE_tracking_plane_track_remove_point_track(plane_track, track)) { + /* Delete planes with less than 3 point tracks in it. */ + BKE_tracking_plane_track_free(plane_track); + BLI_freelinkN(plane_tracks_base, plane_track); + } + } + } +} + /*********************** Plane Marker *************************/ MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(MovieTrackingPlaneTrack *plane_track, diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 6a2a01620cd..48f8f587106 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -177,9 +177,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) MovieTracking *tracking = &clip->tracking; MovieTrackingStabilization *stab = &tracking->stabilization; MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking); - MovieTrackingPlaneTrack *plane_track, *next_plane_track; ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); - ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); bool has_bundle = false, update_stab = false; char track_name_escaped[MAX_NAME], prefix[MAX_NAME * 2]; @@ -197,49 +195,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) has_bundle = true; /* Make sure no plane will use freed track */ - for (plane_track = plane_tracks_base->first; - plane_track; - plane_track = next_plane_track) - { - bool found = false; - int i; - - next_plane_track = plane_track->next; - - for (i = 0; i < plane_track->point_tracksnr; i++) { - if (plane_track->point_tracks[i] == track) { - found = true; - break; - } - } - - if (!found) { - continue; - } - - if (plane_track->point_tracksnr > 4) { - int track_index; - MovieTrackingTrack **new_point_tracks; - - new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * (plane_track->point_tracksnr - 1), - "new point tracks array"); - - for (i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) { - if (plane_track->point_tracks[i] != track) { - new_point_tracks[track_index++] = plane_track->point_tracks[i]; - } - } - - MEM_freeN(plane_track->point_tracks); - plane_track->point_tracks = new_point_tracks; - plane_track->point_tracksnr--; - } - else { - /* Delete planes with less than 3 point tracks in it. */ - BKE_tracking_plane_track_free(plane_track); - BLI_freelinkN(plane_tracks_base, plane_track); - } - } + BKE_tracking_plane_tracks_remove_point_track(tracking, track); /* Delete f-curves associated with the track (such as weight, i.e.) */ BLI_strescape(track_name_escaped, track->name, sizeof(track_name_escaped)); -- cgit v1.2.3 From b35743d39f574717731899669117d8de79fce082 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 22 Apr 2015 02:10:13 +0500 Subject: Tracking: Add missing plane track remapping when joining two point tracks --- source/blender/blenkernel/BKE_tracking.h | 7 ++++++ source/blender/blenkernel/intern/tracking.c | 31 ++++++++++++++++++++++++ source/blender/editors/space_clip/tracking_ops.c | 6 +++++ 3 files changed, 44 insertions(+) diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 5af05f4ca80..ea56c084fb5 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -144,6 +144,13 @@ bool BKE_tracking_plane_track_remove_point_track(struct MovieTrackingPlaneTrack void BKE_tracking_plane_tracks_remove_point_track(struct MovieTracking *tracking, struct MovieTrackingTrack *track); +void BKE_tracking_plane_track_replace_point_track(struct MovieTrackingPlaneTrack *plane_track, + struct MovieTrackingTrack *old_track, + struct MovieTrackingTrack *new_track); +void BKE_tracking_plane_tracks_replace_point_track(struct MovieTracking *tracking, + struct MovieTrackingTrack *old_track, + struct MovieTrackingTrack *new_track); + /* **** Plane Marker **** */ struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(struct MovieTrackingPlaneTrack *plane_track, struct MovieTrackingPlaneMarker *plane_marker); diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index e7dccc09376..e3f04296f50 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1360,6 +1360,37 @@ void BKE_tracking_plane_tracks_remove_point_track(MovieTracking *tracking, } } +void BKE_tracking_plane_track_replace_point_track(MovieTrackingPlaneTrack *plane_track, + MovieTrackingTrack *old_track, + MovieTrackingTrack *new_track) +{ + int i; + for (i = 0; i < plane_track->point_tracksnr; i++) { + if (plane_track->point_tracks[i] == old_track) { + plane_track->point_tracks[i] = new_track; + break; + } + } +} + +void BKE_tracking_plane_tracks_replace_point_track(MovieTracking *tracking, + MovieTrackingTrack *old_track, + MovieTrackingTrack *new_track) +{ + MovieTrackingPlaneTrack *plane_track; + ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); + for (plane_track = plane_tracks_base->first; + plane_track; + plane_track = plane_track->next) + { + if (BKE_tracking_plane_track_has_point_track(plane_track, old_track)) { + BKE_tracking_plane_track_replace_point_track(plane_track, + old_track, + new_track); + } + } +} + /*********************** Plane Marker *************************/ MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(MovieTrackingPlaneTrack *plane_track, diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index db8881a865e..5c88ad8b3f7 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -3117,6 +3117,12 @@ static int join_tracks_exec(bContext *C, wmOperator *op) if (tracking->stabilization.rot_track == track) tracking->stabilization.rot_track = act_track; + /* TODO(sergey): Re-evaluate planes with auto-key. */ + BKE_tracking_plane_tracks_replace_point_track(tracking, + track, + act_track); + + BKE_tracking_track_free(track); BLI_freelinkN(tracksbase, track); } -- cgit v1.2.3 From a8adeeb6fbd3b8c60ba868ea70032aa052e60301 Mon Sep 17 00:00:00 2001 From: Tristan Porteries Date: Tue, 21 Apr 2015 23:33:24 +0200 Subject: Logic Editor: Buttons for moving game properties up/down D1163 by @panzergame, with minor edits by me (@Severin) --- release/scripts/startup/bl_ui/space_logic.py | 7 +++ source/blender/editors/object/object_edit.c | 64 +++++++++++++++++++++++++++ source/blender/editors/object/object_intern.h | 1 + source/blender/editors/object/object_ops.c | 1 + 4 files changed, 73 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_logic.py b/release/scripts/startup/bl_ui/space_logic.py index 16182da1018..1633a37169b 100644 --- a/release/scripts/startup/bl_ui/space_logic.py +++ b/release/scripts/startup/bl_ui/space_logic.py @@ -71,6 +71,13 @@ class LOGIC_PT_properties(Panel): row.prop(prop, "type", text="") row.prop(prop, "value", text="") row.prop(prop, "show_debug", text="", toggle=True, icon='INFO') + sub = row.row(align=True) + props = sub.operator("object.game_property_move", text="", icon='TRIA_UP') + props.index = i + props.direction = "UP" + props = sub.operator("object.game_property_move", text="", icon='TRIA_DOWN') + props.index = i + props.direction = "DOWN" row.operator("object.game_property_remove", text="", icon='X', emboss=False).index = i diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index f7d51eb403f..562f566c562 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1769,6 +1769,70 @@ void OBJECT_OT_game_property_remove(wmOperatorType *ot) RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Property index to remove ", 0, INT_MAX); } +#define GAME_PROPERTY_MOVE_UP 1 +#define GAME_PROPERTY_MOVE_DOWN -1 + +static int game_property_move(bContext *C, wmOperator *op) +{ + Object *ob = CTX_data_active_object(C); + bProperty *prop; + bProperty *otherprop = NULL; + const int index = RNA_int_get(op->ptr, "index"); + const int dir = RNA_int_get(op->ptr, "direction"); + + if (ob == NULL) + return OPERATOR_CANCELLED; + + prop = BLI_findlink(&ob->prop, index); + if (dir == GAME_PROPERTY_MOVE_UP) { + otherprop = prop->prev; + } + else if (dir == GAME_PROPERTY_MOVE_DOWN) { + otherprop = prop->next; + } + else { + BLI_assert(0); + } + + if (prop && otherprop) { + BLI_listbase_swaplinks(&ob->prop, prop, otherprop); + + WM_event_add_notifier(C, NC_LOGIC, NULL); + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void OBJECT_OT_game_property_move(wmOperatorType *ot) +{ + static EnumPropertyItem direction_property_move[] = { + {GAME_PROPERTY_MOVE_UP, "UP", 0, "Up", ""}, + {GAME_PROPERTY_MOVE_DOWN, "DOWN", 0, "Down", ""}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "Move Game Property"; + ot->description = "Move game property"; + ot->idname = "OBJECT_OT_game_property_move"; + + /* api callbacks */ + ot->exec = game_property_move; + ot->poll = ED_operator_object_active_editable; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Property index to move", 0, INT_MAX); + RNA_def_enum(ot->srna, "direction", direction_property_move, 0, "Direction", + "Direction for moving the property"); +} + +#undef GAME_PROPERTY_MOVE_UP +#undef GAME_PROPERTY_MOVE_DOWN + #define COPY_PROPERTIES_REPLACE 1 #define COPY_PROPERTIES_MERGE 2 #define COPY_PROPERTIES_COPY 3 diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index d535457fc5b..2801d2711e7 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -94,6 +94,7 @@ void OBJECT_OT_game_property_new(struct wmOperatorType *ot); void OBJECT_OT_game_property_remove(struct wmOperatorType *ot); void OBJECT_OT_game_property_copy(struct wmOperatorType *ot); void OBJECT_OT_game_property_clear(struct wmOperatorType *ot); +void OBJECT_OT_game_property_move(struct wmOperatorType *ot); void OBJECT_OT_logic_bricks_copy(struct wmOperatorType *ot); void OBJECT_OT_game_physics_copy(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 422f0c12e51..00c6a41423a 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -206,6 +206,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_game_property_remove); WM_operatortype_append(OBJECT_OT_game_property_copy); WM_operatortype_append(OBJECT_OT_game_property_clear); + WM_operatortype_append(OBJECT_OT_game_property_move); WM_operatortype_append(OBJECT_OT_logic_bricks_copy); WM_operatortype_append(OBJECT_OT_game_physics_copy); -- cgit v1.2.3 From e1a53b6d52f1ce3598e9e35b96eaab2318aba4ad Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 22 Apr 2015 07:54:14 +0200 Subject: Fix T44475: Merge option of Mirror Modifier behavior reversed. Glitch in rB57d9badc. --- source/blender/modifiers/intern/MOD_mirror.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index d34d68d4dee..73bc61e5519 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -94,7 +94,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, int axis) { const float tolerance_sq = mmd->tolerance * mmd->tolerance; - const bool do_vtargetmap = (mmd->flag & MOD_MIR_NO_MERGE) != 0; + const bool do_vtargetmap = (mmd->flag & MOD_MIR_NO_MERGE) == 0; int tot_vtargetmap = 0; /* total merge vertices */ DerivedMesh *result; -- cgit v1.2.3 From 4da050674e2c6a0ecc7d50733f7de8df3e77ee73 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 22 Apr 2015 08:15:05 +0200 Subject: Fix T44470: File Selection sometimes surpresses last Character. Tweak hack of `file_draw_string()` (there may be better solution, but not worth spending time on this, the whole filebrowser drawing code is to be rewritten anyway). --- source/blender/editors/space_file/file_draw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index a6f3a73841e..9763efbc7b5 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -307,10 +307,10 @@ static void file_draw_string(int sx, int sy, const char *string, float width, in /* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict (for buttons it works) */ rect.xmin = sx; - rect.xmax = (int)(sx + ceil(width + 4.0f)); + rect.xmax = (int)(sx + ceil(width + 5.0f / UI_DPI_FAC)); rect.ymin = sy - height; rect.ymax = sy; - + UI_fontstyle_draw(&fs, &rect, fname); } -- cgit v1.2.3 From e6ceecdf97f927a497d567f0f271d2c51964d193 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 22 Apr 2015 16:26:00 +1000 Subject: Cleanup: pep8, spelling --- release/scripts/startup/bl_operators/__init__.py | 2 +- release/scripts/startup/bl_operators/add_mesh_torus.py | 18 +++++++++--------- release/scripts/startup/bl_operators/clip.py | 6 +++--- .../startup/bl_operators/screen_play_rendered_anim.py | 1 - release/scripts/startup/bl_ui/__init__.py | 2 +- .../scripts/startup/bl_ui/properties_data_camera.py | 6 +++--- release/scripts/startup/bl_ui/properties_data_curve.py | 2 +- release/scripts/startup/bl_ui/properties_freestyle.py | 4 ++-- release/scripts/startup/bl_ui/properties_game.py | 2 +- .../scripts/startup/bl_ui/properties_mask_common.py | 2 +- release/scripts/startup/bl_ui/properties_render.py | 2 +- release/scripts/startup/bl_ui/space_filebrowser.py | 4 ++-- release/scripts/startup/bl_ui/space_graph.py | 1 + release/scripts/startup/bl_ui/space_logic.py | 8 ++++---- release/scripts/startup/bl_ui/space_view3d.py | 3 +-- release/scripts/templates_py/addon_add_object.py | 5 +++-- source/blender/blenlib/intern/convexhull2d.c | 2 +- source/blender/blenlib/intern/polyfill2d.c | 2 +- tests/python/bl_load_addons.py | 1 + 19 files changed, 37 insertions(+), 36 deletions(-) diff --git a/release/scripts/startup/bl_operators/__init__.py b/release/scripts/startup/bl_operators/__init__.py index 65f7bde1809..4047505652f 100644 --- a/release/scripts/startup/bl_operators/__init__.py +++ b/release/scripts/startup/bl_operators/__init__.py @@ -54,7 +54,7 @@ if bpy.app.build_options.freestyle: _modules.append("freestyle") __import__(name=__name__, fromlist=_modules) _namespace = globals() -_modules_loaded = {name: _namespace[name] for name in _modules if name != 'bpy'} +_modules_loaded = {name: _namespace[name] for name in _modules if name != "bpy"} del _namespace diff --git a/release/scripts/startup/bl_operators/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py index dfb734e9b5b..82014c87be9 100644 --- a/release/scripts/startup/bl_operators/add_mesh_torus.py +++ b/release/scripts/startup/bl_operators/add_mesh_torus.py @@ -153,40 +153,40 @@ class AddTorus(Operator, object_utils.AddObjectHelper): col = layout.column(align=True) col.label(text="Location") - col.prop(self, 'location', text="") + col.prop(self, "location", text="") col = layout.column(align=True) col.label(text="Rotation") - col.prop(self, 'rotation', text="") + col.prop(self, "rotation", text="") col = layout.column(align=True) col.label(text="Major Segments") - col.prop(self, 'major_segments', text="") + col.prop(self, "major_segments", text="") col = layout.column(align=True) col.label(text="Minor Segments") - col.prop(self, 'minor_segments', text="") + col.prop(self, "minor_segments", text="") col = layout.column(align=True) col.label(text="Torus Dimensions") - col.row().prop(self, 'mode', expand=True) + col.row().prop(self, "mode", expand=True) if self.mode == 'MAJOR_MINOR': col = layout.column(align=True) col.label(text="Major Radius") - col.prop(self, 'major_radius', text="") + col.prop(self, "major_radius", text="") col = layout.column(align=True) col.label(text="Minor Radius") - col.prop(self, 'minor_radius', text="") + col.prop(self, "minor_radius", text="") else: col = layout.column(align=True) col.label(text="Exterior Radius") - col.prop(self, 'abso_major_rad', text="") + col.prop(self, "abso_major_rad", text="") col = layout.column(align=True) col.label(text="Interior Radius") - col.prop(self, 'abso_minor_rad', text="") + col.prop(self, "abso_minor_rad", text="") def invoke(self, context, event): object_utils.object_add_grid_scale_apply_operator(self, context) diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py index 7e4e0ea9246..8049ba3bbe2 100644 --- a/release/scripts/startup/bl_operators/clip.py +++ b/release/scripts/startup/bl_operators/clip.py @@ -552,8 +552,8 @@ class CLIP_OT_setup_tracking_scene(Operator): world.light_settings.sample_method = 'ADAPTIVE_QMC' world.light_settings.samples = 7 world.light_settings.threshold = 0.005 - if hasattr(scene, 'cycles'): - world.light_settings.ao_factor = 0.05 + if hasattr(scene, "cycles"): + world.light_settings.ao_factor = 0.05 @staticmethod def _findOrCreateCamera(context): @@ -841,7 +841,7 @@ class CLIP_OT_setup_tracking_scene(Operator): self._offsetNodes(tree) scene.render.alpha_mode = 'TRANSPARENT' - if hasattr(scene, 'cycles'): + if hasattr(scene, "cycles"): scene.cycles.film_transparent = True @staticmethod diff --git a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py index 5fe74eec709..a5565699364 100644 --- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py +++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py @@ -122,7 +122,6 @@ class PlayRenderedAnim(Operator): if not os.path.exists(file): self.report({'WARNING'}, "File %r not found" % file) - cmd = [player_path] # extra options, fps controls etc. if scene.use_preview_range: diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py index 51117f68558..c110b429aad 100644 --- a/release/scripts/startup/bl_ui/__init__.py +++ b/release/scripts/startup/bl_ui/__init__.py @@ -86,7 +86,7 @@ if bpy.app.build_options.freestyle: _modules.append("properties_freestyle") __import__(name=__name__, fromlist=_modules) _namespace = globals() -_modules_loaded = {name: _namespace[name] for name in _modules if name != 'bpy'} +_modules_loaded = {name: _namespace[name] for name in _modules if name != "bpy"} del _namespace diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py index 6c87af8ad68..24a67a22c1f 100644 --- a/release/scripts/startup/bl_ui/properties_data_camera.py +++ b/release/scripts/startup/bl_ui/properties_data_camera.py @@ -142,12 +142,12 @@ class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel): @classmethod def poll(cls, context): render = context.scene.render - return (super().poll(context) and render.use_multiview \ - and render.views_format == 'STEREO_3D') + return (super().poll(context) and render.use_multiview and + render.views_format == 'STEREO_3D') def draw(self, context): layout = self.layout - render = context.scene.render + # render = context.scene.render st = context.camera.stereo col = layout.column() diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py index 9277bbe20f9..eb8ffa1fb60 100644 --- a/release/scripts/startup/bl_ui/properties_data_curve.py +++ b/release/scripts/startup/bl_ui/properties_data_curve.py @@ -321,7 +321,7 @@ class DATA_PT_font(CurveButtonsPanelText, Panel): row.label(text="Bold & Italic") row.template_ID(text, "font_bold_italic", open="font.open", unlink="font.unlink") - #layout.prop(text, "font") + # layout.prop(text, "font") split = layout.split() diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py index adc706569b1..8f8d8470fec 100644 --- a/release/scripts/startup/bl_ui/properties_freestyle.py +++ b/release/scripts/startup/bl_ui/properties_freestyle.py @@ -74,8 +74,8 @@ class RenderLayerFreestyleButtonsPanel: rd = context.scene.render with_freestyle = bpy.app.build_options.freestyle - return (scene and with_freestyle and rd.use_freestyle - and rd.layers.active and(scene.render.engine in cls.COMPAT_ENGINES)) + return (scene and with_freestyle and rd.use_freestyle and + rd.layers.active and(scene.render.engine in cls.COMPAT_ENGINES)) class RenderLayerFreestyleEditorButtonsPanel(RenderLayerFreestyleButtonsPanel): diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py index f39a73ec00b..616c5fdb854 100644 --- a/release/scripts/startup/bl_ui/properties_game.py +++ b/release/scripts/startup/bl_ui/properties_game.py @@ -542,7 +542,7 @@ class SCENE_PT_game_hysteresis(SceneButtonsPanel, Panel): row.prop(gs, "scene_hysteresis_percentage", text="") -class WorldButtonsPanel(): +class WorldButtonsPanel: bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "world" diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py index 9d94d5efa2e..f4836da50bc 100644 --- a/release/scripts/startup/bl_ui/properties_mask_common.py +++ b/release/scripts/startup/bl_ui/properties_mask_common.py @@ -190,7 +190,7 @@ class MASK_PT_point: col.prop_search(parent, "parent", tracking, "objects", icon='OBJECT_DATA', text="Object:") - tracks_list = "tracks" if parent.type == 'POINT_TRACK' else 'plane_tracks' + tracks_list = "tracks" if parent.type == 'POINT_TRACK' else "plane_tracks" if parent.parent in tracking.objects: object = tracking.objects[parent.parent] diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 35f77e02834..6908668ec86 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -274,7 +274,7 @@ class RENDER_PT_performance(RenderButtonsPanel, Panel): col.prop(rd, "tile_y", text="Y") col.separator() - col.prop(rd, 'preview_start_resolution') + col.prop(rd, "preview_start_resolution") col = split.column() col.label(text="Memory:") diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py index 44dfe2a688e..8acf8cfaef3 100644 --- a/release/scripts/startup/bl_ui/space_filebrowser.py +++ b/release/scripts/startup/bl_ui/space_filebrowser.py @@ -84,7 +84,7 @@ class FILEBROWSER_HT_header(Header): class FILEBROWSER_UL_dir(bpy.types.UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): direntry = item - space = context.space_data + # space = context.space_data icon = 'NONE' if active_propname == "system_folders_active": icon = 'DISK_DRIVE' @@ -99,7 +99,7 @@ class FILEBROWSER_UL_dir(bpy.types.UIList): row = layout.row(align=True) row.enabled = direntry.is_valid # Non-editable entries would show grayed-out, which is bad in this specific case, so switch to mere label. - if direntry.is_property_readonly('name'): + if direntry.is_property_readonly("name"): row.label(text=direntry.name, icon=icon) else: row.prop(direntry, "name", text="", emboss=False, icon=icon) diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index 27928ae3be1..2f5381e58c8 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -281,6 +281,7 @@ class GRAPH_MT_key_transform(Menu): layout.operator("transform.rotate", text="Rotate") layout.operator("transform.resize", text="Scale") + class GRAPH_MT_delete(Menu): bl_label = "Delete" diff --git a/release/scripts/startup/bl_ui/space_logic.py b/release/scripts/startup/bl_ui/space_logic.py index 1633a37169b..48b54feba17 100644 --- a/release/scripts/startup/bl_ui/space_logic.py +++ b/release/scripts/startup/bl_ui/space_logic.py @@ -54,11 +54,11 @@ class LOGIC_PT_properties(Panel): row.label("See Text Object") else: props = layout.operator("object.game_property_new", text="Add Text Game Property", icon='ZOOMIN') - props.name = 'Text' + props.name = "Text" props.type = 'STRING' props = layout.operator("object.game_property_new", text="Add Game Property", icon='ZOOMIN') - props.name = '' + props.name = "" for i, prop in enumerate(game.properties): @@ -74,10 +74,10 @@ class LOGIC_PT_properties(Panel): sub = row.row(align=True) props = sub.operator("object.game_property_move", text="", icon='TRIA_UP') props.index = i - props.direction = "UP" + props.direction = 'UP' props = sub.operator("object.game_property_move", text="", icon='TRIA_DOWN') props.index = i - props.direction = "DOWN" + props.direction = 'DOWN' row.operator("object.game_property_remove", text="", icon='X', emboss=False).index = i diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 4d8230e2f4d..07631f37339 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -935,7 +935,7 @@ class VIEW3D_MT_angle_control(Menu): settings = UnifiedPaintPanel.paint_settings(context) brush = settings.brush - sculpt = (context.sculpt_object != None) + sculpt = (context.sculpt_object is not None) tex_slot = brush.texture_slot @@ -3020,7 +3020,6 @@ class VIEW3D_PT_view3d_shading(Panel): if obj and obj.mode == 'EDIT': col.prop(view, "show_occlude_wire") - fx_settings = view.fx_settings sub = col.column() diff --git a/release/scripts/templates_py/addon_add_object.py b/release/scripts/templates_py/addon_add_object.py index f0d8bede6d5..8e57d7ef8f8 100644 --- a/release/scripts/templates_py/addon_add_object.py +++ b/release/scripts/templates_py/addon_add_object.py @@ -2,12 +2,13 @@ bl_info = { "name": "New Object", "author": "Your Name Here", "version": (1, 0), - "blender": (2, 65, 0), + "blender": (2, 75, 0), "location": "View3D > Add > Mesh > New Object", "description": "Adds a new Mesh Object", "warning": "", "wiki_url": "", - "category": "Add Mesh"} + "category": "Add Mesh", + } import bpy diff --git a/source/blender/blenlib/intern/convexhull2d.c b/source/blender/blenlib/intern/convexhull2d.c index 5f64088f433..f77beac1982 100644 --- a/source/blender/blenlib/intern/convexhull2d.c +++ b/source/blender/blenlib/intern/convexhull2d.c @@ -239,7 +239,7 @@ int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[]) * * Intended to be used with #BLI_convexhull_2d * - * \param points Orded hull points + * \param points Ordered hull points * (result of #BLI_convexhull_2d mapped to a contiguous array). * * \note we could return the index of the best edge too if its needed. diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill2d.c index 3aadbe5f1df..629bed10191 100644 --- a/source/blender/blenlib/intern/polyfill2d.c +++ b/source/blender/blenlib/intern/polyfill2d.c @@ -179,7 +179,7 @@ BLI_INLINE eSign signum_enum(float a) * alternative version of #area_tri_signed_v2 * needed because of float precision issues * - * \note removes / 2 since its not needed since we only need ths sign. + * \note removes / 2 since its not needed since we only need the sign. */ BLI_INLINE float area_tri_signed_v2_alt_2x(const float v1[2], const float v2[2], const float v3[2]) { diff --git a/tests/python/bl_load_addons.py b/tests/python/bl_load_addons.py index 85b2f1270f5..6bb0eaecd3d 100644 --- a/tests/python/bl_load_addons.py +++ b/tests/python/bl_load_addons.py @@ -36,6 +36,7 @@ BLACKLIST_DIRS = ( ) + tuple(addon_utils.paths()[1:]) BLACKLIST_ADDONS = set() + def _init_addon_blacklist(): # in case we built without cycles -- cgit v1.2.3 From 18a47b67fd248080e8cf1b306324f0e7157b382d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 22 Apr 2015 12:34:01 +0500 Subject: Tracking: Code cleanup, de-duplicate some code in tracking context finish --- source/blender/blenkernel/intern/tracking_auto.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index 4cb3f2ca493..76261bddfbc 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -534,19 +534,9 @@ void BKE_autotrack_context_finish(AutoTrackContext *context) if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) { int track; for (track = 0; track < context->num_tracks; ++track) { - MovieTrackingTrack *old_track; - bool do_update = false; - int j; - - old_track = context->options[track].track; - for (j = 0; j < plane_track->point_tracksnr; j++) { - if (plane_track->point_tracks[j] == old_track) { - do_update = true; - break; - } - } - - if (do_update) { + if (BKE_tracking_plane_track_has_point_track(plane_track, + context->options[track].track)) + { BKE_tracking_track_plane_from_existing_motion( plane_track, context->first_frame); -- cgit v1.2.3 From 414990b0f181bdfb15a602fd07cb0169b7e19543 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 22 Apr 2015 12:46:29 +0500 Subject: Tracking: Some more code de-duplication --- source/blender/editors/space_clip/tracking_ops.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 5c88ad8b3f7..4521e980687 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -825,12 +825,8 @@ static void apply_mouse_slide(bContext *C, SlideMarkerData *data) plane_track = plane_track->next) { if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) { - int i; - for (i = 0; i < plane_track->point_tracksnr; i++) { - if (plane_track->point_tracks[i] == data->track) { - BKE_tracking_track_plane_from_existing_motion(plane_track, framenr); - break; - } + if (BKE_tracking_plane_track_has_point_track(plane_track, data->track)) { + BKE_tracking_track_plane_from_existing_motion(plane_track, framenr); } } } -- cgit v1.2.3 From 97587dc5d6b44625ffc00525b12181f64c80b409 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 22 Apr 2015 11:50:57 +0200 Subject: Stamp cannot be written to file. Make sure stamp data is avaliable before writing stamp to image - this still does not fix stamp, looks like issue is availability of the images themselves for the view, investigating next. --- source/blender/render/intern/source/pipeline.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index d25de64978e..73f837e095a 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2615,6 +2615,8 @@ static void do_render_seq(Render *re) /* main loop: doing sequence + fields + blur + 3d render + compositing */ static void do_render_all_options(Render *re) { + Object *camera; + re->current_scene_update(re->suh, re->scene); BKE_scene_camera_switch_update(re->scene); @@ -2648,6 +2650,10 @@ static void do_render_all_options(Render *re) re->stats_draw(re->sdh, &re->i); + /* save render result stamp if needed */ + camera = RE_GetCamera(re); + BKE_render_result_stamp_info(re->scene, camera, re->result); + /* stamp image info here */ if ((re->r.stamp & R_STAMP_ALL) && (re->r.stamp & R_STAMP_DRAW)) { renderresult_stampinfo(re); @@ -3027,17 +3033,12 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr scene->r.cfra = frame; if (render_initialize_from_main(re, &scene->r, bmain, scene, srl, camera_override, lay_override, 0, 0)) { - Object *camera; MEM_reset_peak_memory(); BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE); do_render_all_options(re); - /* save render result stamp if needed */ - camera = RE_GetCamera(re); - BKE_render_result_stamp_info(scene, camera, re->result); - if (write_still && !G.is_break) { if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { /* operator checks this but in case its called from elsewhere */ @@ -3472,7 +3473,6 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri } else { for (nfra = sfra, scene->r.cfra = sfra; scene->r.cfra <= efra; scene->r.cfra++) { - Object *camera; char name[FILE_MAX]; /* only border now, todo: camera lens. (ton) */ @@ -3571,10 +3571,6 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri do_render_all_options(re); totrendered++; - /* save render result stamp if needed */ - camera = RE_GetCamera(re); - BKE_render_result_stamp_info(scene, camera, re->result); - if (re->test_break(re->tbh) == 0) { if (!G.is_break) if (!do_write_image_or_movie(re, bmain, scene, mh, totvideos, NULL)) -- cgit v1.2.3 From 818a0cdc7687c42bde76d372bfed0c6c15c153f9 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 22 Apr 2015 12:03:06 +0200 Subject: Fix stamp missing after multiview merge. Was not using acquired render result correctly, most likely a copy paste error. --- source/blender/render/intern/source/pipeline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 73f837e095a..a1fbe7c5365 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2484,7 +2484,7 @@ static void renderresult_stampinfo(Render *re) for (rv = re->result->views.first;rv;rv = rv->next, nr++) { RE_SetActiveRenderView(re, rv->name); RE_AcquireResultImage(re, &rres, nr); - BKE_image_stamp_buf(re->scene, RE_GetCamera(re), (unsigned char *)rv->rect32, rv->rectf, rres.rectx, rres.recty, 4); + BKE_image_stamp_buf(re->scene, RE_GetCamera(re), (unsigned char *)rres.rect32, rres.rectf, rres.rectx, rres.recty, 4); RE_ReleaseResultImage(re); } } -- cgit v1.2.3 From a069b8d5d8195b9eb517c604f151366b51578d1e Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 22 Apr 2015 12:35:59 +0200 Subject: Rename stamp panel to metadata panel. Rationale - this panel also enables metadata that get written on files. Also moved draw_stamp property in the panel - to make it clearer it only controls the drawing, not individual metadata. --- release/scripts/startup/bl_ui/properties_render.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 6908668ec86..0c68d98a8e1 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -334,28 +334,25 @@ class RENDER_PT_post_processing(RenderButtonsPanel, Panel): class RENDER_PT_stamp(RenderButtonsPanel, Panel): - bl_label = "Stamp" + bl_label = "Metadata" bl_options = {'DEFAULT_CLOSED'} COMPAT_ENGINES = {'BLENDER_RENDER'} - def draw_header(self, context): - rd = context.scene.render - - self.layout.prop(rd, "use_stamp", text="") - def draw(self, context): layout = self.layout rd = context.scene.render - layout.active = rd.use_stamp + layout.prop(rd, "use_stamp", text="Stamp Output") + col = layout.column() + col.active = rd.use_stamp + col.prop(rd, "stamp_font_size", text="Font Size") - layout.prop(rd, "stamp_font_size", text="Font Size") - - row = layout.row() + row = col.row() row.column().prop(rd, "stamp_foreground", slider=True) row.column().prop(rd, "stamp_background", slider=True) + layout.label("Enabled Metadata") split = layout.split() col = split.column() -- cgit v1.2.3 From 1044dfd965a8a0b85095ce51b34eb3876701d967 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 22 Apr 2015 13:19:58 +0200 Subject: Fix and simplify vertical positioning and calculation of metadata display more. --- source/blender/editors/include/ED_util.h | 2 -- source/blender/editors/screen/area.c | 22 +++++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index 96d7828ffe9..9556c601d1f 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -42,8 +42,6 @@ void ED_editors_exit(struct bContext *C); bool ED_editors_flush_edits(const struct bContext *C, bool for_render); -void ED_draw_ibuf_meta_data(const bContext *C, struct ImBuf *ibuf); - /* ************** Undo ************************ */ /* undo.c */ diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index c6de4e5df88..8844f344a6b 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2097,7 +2097,8 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i else { len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]); if (metadata_is_valid(ibuf, temp_str, i + 1, len)) { - BLF_position(fontid, rect.xmax + (0.2f * U.widget_unit), + line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + BLF_position(fontid, rect.xmax - line_width - (0.2f * U.widget_unit), rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y) - ofs_y, 0.0f); BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); ofs_y += (height + (0.2f * U.widget_unit)); @@ -2112,7 +2113,7 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i if (metadata_is_valid(ibuf, temp_str, i, len)) { const int line_height = height; BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit) + ofs_x, - rect.ymin - line_height + factor * (1.5f * U.widget_unit), 0.0f); + rect.ymin - line_height + factor * (U.widget_unit), 0.0f); BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); ofs_x += BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX) + UI_UNIT_X; @@ -2124,26 +2125,29 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top) { char str[MAX_METADATA_STR]; - float height = 0; - short i; + short i, count = 0; + const float height = BLF_height_max(fontid) + 0.2f * U.widget_unit; if (is_top) { - for (i = 0; i < 5 ; i++) { + if (metadata_is_valid(ibuf, str, 0, 0) || metadata_is_valid(ibuf, str, 1, 0)) { + count++; + } + for (i = 2; i < 5; i++) { if (metadata_is_valid(ibuf, str, i, 0)) { - height += BLF_height(fontid, str, strlen(str)); + count++; } } } else { for (i = 5; i < 10; i++) { if (metadata_is_valid(ibuf, str, i, 0)) { - height += BLF_height(fontid, str, strlen(str)); + count = 1; } } } - if (height) { - return (height + (0.2f * U.widget_unit)); + if (count) { + return (height * count + (0.2f * U.widget_unit)); } return 0; -- cgit v1.2.3 From 18aaae101afe7ae4c120d656e85bd078d0995ea7 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 22 Apr 2015 13:41:26 +0200 Subject: Fix T44477: Overlapping tooltips in Outliner Tooltips for buttons in the Outliner could overlap the Outliner's RMB menu in some cases (and there's no way to get rid of the tooltip again). This disables the button's tooltip before creating the menu (as we do it for the normal RMB menu) --- source/blender/editors/include/UI_interface.h | 1 + source/blender/editors/interface/interface_handlers.c | 16 ++++++++-------- source/blender/editors/space_outliner/outliner_tools.c | 5 +++++ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 4ca0be7c80d..66b946811ea 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -675,6 +675,7 @@ void UI_but_func_drawextra_set( void *arg1, void *arg2); void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *argN); +void UI_but_tooltip_timer_remove(struct bContext *C, uiBut *but); bool UI_textbutton_activate_rna(const struct bContext *C, struct ARegion *ar, const void *rna_poin_data, const char *rna_prop_id); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 7d34754e5a4..57a26ce62ec 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -332,7 +332,6 @@ static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *da const bool mousemove, const bool onfree); static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *userdata); static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type); -static void button_timers_tooltip_remove(bContext *C, uiBut *but); #ifdef USE_DRAG_MULTINUM static void ui_multibut_restore(uiHandleButtonData *data, uiBlock *block); @@ -5956,7 +5955,7 @@ static void menu_add_shortcut_cancel(struct bContext *C, void *arg1) static void popup_change_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) { uiBut *but = (uiBut *)arg1; - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); UI_popup_block_invoke(C, menu_change_shortcut, but); } @@ -5977,7 +5976,7 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) { uiBut *but = (uiBut *)arg1; - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but); } @@ -6026,7 +6025,7 @@ static bool ui_but_menu(bContext *C, uiBut *but) return false; } - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); /* highly unlikely getting the label ever fails */ UI_but_string_info_get(C, but, &label, NULL); @@ -6965,7 +6964,8 @@ static bool button_modal_state(uiHandleButtonState state) BUTTON_STATE_MENU_OPEN); } -static void button_timers_tooltip_remove(bContext *C, uiBut *but) +/* removes tooltip timer from active but (meaning tooltip is disabled until it's reenabled again) */ +void UI_but_tooltip_timer_remove(bContext *C, uiBut *but) { uiHandleButtonData *data; @@ -7049,7 +7049,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s } else { but->flag |= UI_SELECT; - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); } /* text editing */ @@ -7678,7 +7678,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) case WHEELDOWNMOUSE: case MIDDLEMOUSE: case MOUSEPAN: - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); /* fall-through */ default: /* handle button type specific events */ @@ -8653,7 +8653,7 @@ static int ui_handle_menu_event( { if (!but || !ui_but_contains_point_px(ar, but, event->x, event->y)) { if (but) { - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); } menu->is_grab = true; diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index e5833103658..4c4378e004e 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -1654,9 +1654,14 @@ static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent Scene *scene = CTX_data_scene(C); ARegion *ar = CTX_wm_region(C); SpaceOops *soops = CTX_wm_space_outliner(C); + uiBut *but = UI_context_active_but_get(C); TreeElement *te; float fmval[2]; + if (but) { + UI_but_tooltip_timer_remove(C, but); + } + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); for (te = soops->tree.first; te; te = te->next) { -- cgit v1.2.3 From dc36e1fe39f87fabfc9e398139d20f935caf74c3 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 22 Apr 2015 14:02:48 +0200 Subject: Fix T44476: Hiding Grease Pencil from Outliner RMB doesn't update 3D View --- source/blender/editors/space_view3d/space_view3d.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index f8345e91afd..bd070ea25fb 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -1011,7 +1011,7 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN break; case NC_GPENCIL: - if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { + if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { ED_region_tag_redraw(ar); } break; -- cgit v1.2.3 From 62d10cd83324f066a11b4966bd29fc9579e5f76d Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 20 Apr 2015 16:33:10 +0200 Subject: Placeholders for sequencer take one. Placeholder images, means that the image sequence reserves a range for images, displaying black while we wait for them to finish rendering. This is meant as a feature to not break the layout of gooseberry sequence edits while we wait for those frames to arrive. --- .../editors/space_sequencer/sequencer_add.c | 62 ++++++++++++++++++---- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 373095d68f9..ddb9d1196d5 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "MEM_guardedalloc.h" @@ -763,11 +764,18 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) Strip *strip; StripElem *se; + int i; + bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders"); seq_load_operator_info(&seq_load, op); /* images are unique in how they handle this - 1 per strip elem */ - seq_load.len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); + if (use_placeholders) { + seq_load.len = seq_load.end_frame - seq_load.start_frame; + } + else { + seq_load.len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); + } if (seq_load.len == 0) return OPERATOR_CANCELLED; @@ -775,20 +783,54 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) if (seq_load.flag & SEQ_LOAD_REPLACE_SEL) ED_sequencer_deselect_all(scene); - /* main adding function */ seq = BKE_sequencer_add_image_strip(C, ed->seqbasep, &seq_load); strip = seq->strip; se = strip->stripdata; - RNA_BEGIN (op->ptr, itemptr, "files") - { - char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); - BLI_strncpy(se->name, filename, sizeof(se->name)); - MEM_freeN(filename); - se++; + if (use_placeholders) { + char *filename = NULL, *filename_stripped; + RNA_BEGIN (op->ptr, itemptr, "files") + { + /* just get the first filename */ + filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); + break; + } + RNA_END; + + filename_stripped = filename; + + if (filename_stripped) { + + /* strip numeric extensions */ + while (*filename_stripped && isdigit(*filename_stripped)) { + filename_stripped++; + } + + /* was the number really an extension? */ + if (*filename_stripped == '.') + filename_stripped++; + else { + filename_stripped = filename; + } + + for (i = 0; i < seq_load.len; i++, se++) { + BLI_snprintf(se->name, sizeof(se->name), "%04d.%s", seq_load.start_frame + i, filename_stripped); + } + + MEM_freeN(filename); + } + } + else { + RNA_BEGIN (op->ptr, itemptr, "files") + { + char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); + BLI_strncpy(se->name, filename, sizeof(se->name)); + MEM_freeN(filename); + se++; + } + RNA_END; } - RNA_END; if (seq_load.len == 1) { if (seq_load.start_frame < seq_load.end_frame) { @@ -861,6 +903,8 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot) WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY); sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME); + + RNA_def_boolean(ot->srna, "use_placeholders", false, "Use Placeholders", "Use placeholders for missing frames of the strip"); } -- cgit v1.2.3 From e7c2d244c39affb71821f9e81ace9df3c87d2130 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 20 Apr 2015 17:35:09 +0200 Subject: Placeholder image strips feedback session changes no.1: Autodetect range of strips. --- .../editors/space_sequencer/sequencer_add.c | 44 ++++++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index ddb9d1196d5..27346ce2bde 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -756,7 +756,7 @@ void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot) static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) { /* cant use the generic function for this */ - + int minframe = INT32_MAX, maxframe = INT32_MIN; Scene *scene = CTX_data_scene(C); /* only for sound */ Editing *ed = BKE_sequencer_editing_get(scene, true); SeqLoadInfo seq_load; @@ -771,7 +771,45 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) /* images are unique in how they handle this - 1 per strip elem */ if (use_placeholders) { - seq_load.len = seq_load.end_frame - seq_load.start_frame; + + RNA_BEGIN (op->ptr, itemptr, "files") + { + char *filename = NULL, *filename_stripped; + int frame; + /* just get the first filename */ + filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); + + if (filename) { + bool is_numeric; + + filename_stripped = filename; + + /* strip numeric extensions */ + while (*filename_stripped && isdigit(*filename_stripped)) { + filename_stripped++; + } + + is_numeric = (filename_stripped != filename && *filename_stripped == '.'); + + if (is_numeric) { + /* was the number really an extension? */ + *filename_stripped = 0; + frame = atoi(filename); + minframe = min_ii(minframe, frame); + maxframe = max_ii(maxframe, frame); + } + + MEM_freeN(filename); + } + } + RNA_END; + + if (minframe == INT32_MAX) { + minframe = seq_load.start_frame; + maxframe = minframe + 1; + } + + seq_load.len = maxframe - minframe + 1; } else { seq_load.len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); @@ -815,7 +853,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) } for (i = 0; i < seq_load.len; i++, se++) { - BLI_snprintf(se->name, sizeof(se->name), "%04d.%s", seq_load.start_frame + i, filename_stripped); + BLI_snprintf(se->name, sizeof(se->name), "%04d.%s", minframe + i, filename_stripped); } MEM_freeN(filename); -- cgit v1.2.3 From d354eeab7460ba76f92f3dcce3eea069010635b3 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 20 Apr 2015 18:07:34 +0200 Subject: Placeholder image strips feedback session changes no.2: Change paths operator can also have the same placeholder logic now --- .../editors/space_sequencer/sequencer_add.c | 160 +++++++++++---------- .../editors/space_sequencer/sequencer_edit.c | 31 ++-- .../editors/space_sequencer/sequencer_intern.h | 6 + 3 files changed, 116 insertions(+), 81 deletions(-) diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 27346ce2bde..f4b1afba6c4 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -752,64 +752,108 @@ void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot) RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory"); } -/* add image operator */ -static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) +int sequencer_image_seq_get_minmax_frame(wmOperator *op, int sfra, int *r_minframe) { - /* cant use the generic function for this */ int minframe = INT32_MAX, maxframe = INT32_MIN; - Scene *scene = CTX_data_scene(C); /* only for sound */ - Editing *ed = BKE_sequencer_editing_get(scene, true); - SeqLoadInfo seq_load; - Sequence *seq; - Strip *strip; - StripElem *se; - int i; - bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders"); + RNA_BEGIN (op->ptr, itemptr, "files") + { + char *filename = NULL, *filename_stripped; + int frame; + /* just get the first filename */ + filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); - seq_load_operator_info(&seq_load, op); + if (filename) { + bool is_numeric; - /* images are unique in how they handle this - 1 per strip elem */ - if (use_placeholders) { + filename_stripped = filename; - RNA_BEGIN (op->ptr, itemptr, "files") - { - char *filename = NULL, *filename_stripped; - int frame; - /* just get the first filename */ - filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); + /* strip numeric extensions */ + while (*filename_stripped && isdigit(*filename_stripped)) { + filename_stripped++; + } - if (filename) { - bool is_numeric; + is_numeric = (filename_stripped != filename && *filename_stripped == '.'); - filename_stripped = filename; + if (is_numeric) { + /* was the number really an extension? */ + *filename_stripped = 0; + frame = atoi(filename); + minframe = min_ii(minframe, frame); + maxframe = max_ii(maxframe, frame); + } - /* strip numeric extensions */ - while (*filename_stripped && isdigit(*filename_stripped)) { - filename_stripped++; - } + MEM_freeN(filename); + } + } + RNA_END; - is_numeric = (filename_stripped != filename && *filename_stripped == '.'); + if (minframe == INT32_MAX) { + minframe = sfra; + maxframe = minframe + 1; + } - if (is_numeric) { - /* was the number really an extension? */ - *filename_stripped = 0; - frame = atoi(filename); - minframe = min_ii(minframe, frame); - maxframe = max_ii(maxframe, frame); - } + *r_minframe = minframe; - MEM_freeN(filename); - } + return maxframe - minframe + 1; +} + +void sequencer_image_seq_reserve_frames(wmOperator *op, StripElem *se, int len, int minframe) +{ + int i; + char *filename = NULL, *filename_stripped; + RNA_BEGIN (op->ptr, itemptr, "files") + { + /* just get the first filename */ + filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); + break; + } + RNA_END; + + filename_stripped = filename; + + if (filename_stripped) { + + /* strip numeric extensions */ + while (*filename_stripped && isdigit(*filename_stripped)) { + filename_stripped++; + } + + /* was the number really an extension? */ + if (*filename_stripped == '.') + filename_stripped++; + else { + filename_stripped = filename; } - RNA_END; - if (minframe == INT32_MAX) { - minframe = seq_load.start_frame; - maxframe = minframe + 1; + for (i = 0; i < len; i++, se++) { + BLI_snprintf(se->name, sizeof(se->name), "%04d.%s", minframe + i, filename_stripped); } - seq_load.len = maxframe - minframe + 1; + MEM_freeN(filename); + } +} + + +/* add image operator */ +static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) +{ + int minframe; + /* cant use the generic function for this */ + Scene *scene = CTX_data_scene(C); /* only for sound */ + Editing *ed = BKE_sequencer_editing_get(scene, true); + SeqLoadInfo seq_load; + Sequence *seq; + + Strip *strip; + StripElem *se; + const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders"); + + seq_load_operator_info(&seq_load, op); + + /* images are unique in how they handle this - 1 per strip elem */ + if (use_placeholders) { + seq_load.len = sequencer_image_seq_get_minmax_frame(op, seq_load.start_frame, &minframe); } else { seq_load.len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); @@ -827,37 +871,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) se = strip->stripdata; if (use_placeholders) { - char *filename = NULL, *filename_stripped; - RNA_BEGIN (op->ptr, itemptr, "files") - { - /* just get the first filename */ - filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); - break; - } - RNA_END; - - filename_stripped = filename; - - if (filename_stripped) { - - /* strip numeric extensions */ - while (*filename_stripped && isdigit(*filename_stripped)) { - filename_stripped++; - } - - /* was the number really an extension? */ - if (*filename_stripped == '.') - filename_stripped++; - else { - filename_stripped = filename; - } - - for (i = 0; i < seq_load.len; i++, se++) { - BLI_snprintf(se->name, sizeof(se->name), "%04d.%s", minframe + i, filename_stripped); - } - - MEM_freeN(filename); - } + sequencer_image_seq_reserve_frames(op, se, seq_load.len, minframe); } else { RNA_BEGIN (op->ptr, itemptr, "files") diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 138d9b943fc..39023f5c0a3 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -3694,12 +3694,21 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = BKE_sequencer_active_get(scene); const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path"); + const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders"); + int minframe; if (seq->type == SEQ_TYPE_IMAGE) { char directory[FILE_MAX]; - const int len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); + int len; StripElem *se; + /* need to find min/max frame for placeholders */ + if (use_placeholders) { + len = sequencer_image_seq_get_minmax_frame(op, seq->sfra, &minframe); + } + else { + len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); + } if (len == 0) return OPERATOR_CANCELLED; @@ -3717,14 +3726,19 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) } seq->strip->stripdata = se = MEM_callocN(len * sizeof(StripElem), "stripelem"); - RNA_BEGIN (op->ptr, itemptr, "files") - { - char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); - BLI_strncpy(se->name, filename, sizeof(se->name)); - MEM_freeN(filename); - se++; + if (use_placeholders) { + sequencer_image_seq_reserve_frames(op, se, len, minframe); + } + else { + RNA_BEGIN (op->ptr, itemptr, "files") + { + char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); + BLI_strncpy(se->name, filename, sizeof(se->name)); + MEM_freeN(filename); + se++; + } + RNA_END; } - RNA_END; /* reset these else we wont see all the images */ seq->anim_startofs = seq->anim_endofs = 0; @@ -3799,4 +3813,5 @@ void SEQUENCER_OT_change_path(struct wmOperatorType *ot) WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILEPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY); + RNA_def_boolean(ot->srna, "use_placeholders", false, "Use Placeholders", "Use placeholders for missing frames of the strip"); } diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index 78255507321..0158a2d4872 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -45,6 +45,8 @@ struct ARegion; struct ARegionType; struct Scene; struct Main; +struct wmOperator; +struct StripElem; /* space_sequencer.c */ struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa); @@ -202,5 +204,9 @@ void SEQUENCER_OT_sample(struct wmOperatorType *ot); /* sequencer_preview.c */ void sequencer_preview_add_sound(const struct bContext *C, struct Sequence *seq); +/* sequencer_add */ +int sequencer_image_seq_get_minmax_frame(struct wmOperator *op, int sfra, int *r_minframe); +void sequencer_image_seq_reserve_frames(struct wmOperator *op, struct StripElem *se, int len, int minframe); + #endif /* __SEQUENCER_INTERN_H__ */ -- cgit v1.2.3 From 798facbff3a3aca7dc09e4609c2e848cd6bf26c9 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 22 Apr 2015 17:19:23 +0200 Subject: Fix crashes when moving game property with invalid index (from py/redo panel) Also hides index option in redo panel to be consistent with similar operators --- source/blender/editors/object/object_edit.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 562f566c562..706ca5fbdfe 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1784,6 +1784,10 @@ static int game_property_move(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; prop = BLI_findlink(&ob->prop, index); + /* invalid index */ + if (prop == NULL) + return OPERATOR_CANCELLED; + if (dir == GAME_PROPERTY_MOVE_UP) { otherprop = prop->prev; } @@ -1812,10 +1816,11 @@ void OBJECT_OT_game_property_move(wmOperatorType *ot) {GAME_PROPERTY_MOVE_DOWN, "DOWN", 0, "Down", ""}, {0, NULL, 0, NULL, NULL} }; + PropertyRNA *prop; /* identifiers */ ot->name = "Move Game Property"; - ot->description = "Move game property"; + ot->description = "Move game property"; ot->idname = "OBJECT_OT_game_property_move"; /* api callbacks */ @@ -1825,7 +1830,9 @@ void OBJECT_OT_game_property_move(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Property index to move", 0, INT_MAX); + /* properties */ + prop = RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Property index to move", 0, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN); RNA_def_enum(ot->srna, "direction", direction_property_move, 0, "Direction", "Direction for moving the property"); } -- cgit v1.2.3 From 3da722684462f0ef6c7fedbdac67a67943815455 Mon Sep 17 00:00:00 2001 From: Tamito Kajiyama Date: Wed, 22 Apr 2015 23:19:43 +0900 Subject: Freestyle: Fixed a crash due to missing call of StrokeShader.__init__() in Python. Many thanks to the problem report by flokkievids (Folkert de Vries) through a comment in Patch D963. --- source/blender/freestyle/intern/python/BPy_Operators.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp index a214fc444c7..1b2b18c2c99 100644 --- a/source/blender/freestyle/intern/python/BPy_Operators.cpp +++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp @@ -34,6 +34,8 @@ #include "BPy_StrokeShader.h" #include "BPy_Convert.h" +#include + #ifdef __cplusplus extern "C" { #endif @@ -539,7 +541,15 @@ static PyObject *Operators_create(BPy_Operators * /*self*/, PyObject *args, PyOb PyErr_SetString(PyExc_TypeError, "Operators.create(): 2nd argument must be a list of StrokeShader objects"); return NULL; } - shaders.push_back(((BPy_StrokeShader *)py_ss)->ss); + StrokeShader *shader = ((BPy_StrokeShader *)py_ss)->ss; + if (!shader) { + stringstream ss; + ss << "Operators.create(): item " << (i + 1) + << " of the shaders list is invalid likely due to missing call of StrokeShader.__init__()"; + PyErr_SetString(PyExc_TypeError, ss.str().c_str()); + return NULL; + } + shaders.push_back(shader); } if (Operators::create(*(((BPy_UnaryPredicate1D *)obj1)->up1D), shaders) < 0) { if (!PyErr_Occurred()) -- cgit v1.2.3 From 3174cbe8f2d3fa384b644a62b3c265a946ab866f Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 22 Apr 2015 15:42:03 +0200 Subject: Double click selection on animation channels selects all keyframes of the range --- .../blender/editors/animation/anim_channels_edit.c | 152 ++++++++++++++++++--- 1 file changed, 134 insertions(+), 18 deletions(-) diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 4828343fa0e..67485248bf1 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -2496,12 +2496,13 @@ static void ANIM_OT_channels_select_border(wmOperatorType *ot) /* ******************* Rename Operator ***************************** */ /* Allow renaming some channels by clicking on them */ -static void rename_anim_channels(bAnimContext *ac, int channel_index) +static bool rename_anim_channels(bAnimContext *ac, int channel_index) { ListBase anim_data = {NULL, NULL}; const bAnimChannelType *acf; bAnimListElem *ale; int filter; + bool success = false; /* get the channel that was clicked on */ /* filter channels */ @@ -2516,7 +2517,7 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index) printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index); ANIM_animdata_freelist(&anim_data); - return; + return false; } /* check that channel can be renamed */ @@ -2536,6 +2537,7 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index) */ if (ac->ads) { ac->ads->renameIndex = channel_index + 1; + success = true; } } } @@ -2543,22 +2545,18 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index) /* free temp data and tag for refresh */ ANIM_animdata_freelist(&anim_data); ED_region_tag_redraw(ac->ar); + return success; } -static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +static int animchannels_channel_get(bAnimContext *ac, const int mval[2]) { - bAnimContext ac; ARegion *ar; View2D *v2d; int channel_index; float x, y; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - /* get useful pointers from animation context data */ - ar = ac.ar; + ar = ac->ar; v2d = &ar->v2d; /* figure out which channel user clicked in @@ -2566,20 +2564,36 @@ static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const * so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use * ACHANNEL_HEIGHT_HALF. */ - UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y); + UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); - if (ac.datatype == ANIMCONT_NLA) { - SpaceNla *snla = (SpaceNla *)ac.sl; + if (ac->datatype == ANIMCONT_NLA) { + SpaceNla *snla = (SpaceNla *)ac->sl; UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index); } else { UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index); } - + + return channel_index; +} + +static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + bAnimContext ac; + int channel_index; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + channel_index = animchannels_channel_get(&ac, event->mval); + /* handle click */ - rename_anim_channels(&ac, channel_index); - - return OPERATOR_FINISHED; + if (rename_anim_channels(&ac, channel_index)) + return OPERATOR_FINISHED; + else + /* allow event to be handled by selectall operator */ + return OPERATOR_PASS_THROUGH; } static void ANIM_OT_channels_rename(wmOperatorType *ot) @@ -3008,6 +3022,105 @@ static void ANIM_OT_channels_click(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +static bool select_anim_channel_keys(bAnimContext *ac, int channel_index, bool extend) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + bool success = false; + FCurve *fcu; + int i; + + /* get the channel that was clicked on */ + /* filter channels */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* get channel from index */ + ale = BLI_findlink(&anim_data, channel_index); + if (ale == NULL) { + /* channel not found */ + if (G.debug & G_DEBUG) + printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index); + + ANIM_animdata_freelist(&anim_data); + return false; + } + + fcu = (FCurve *)ale->key_data; + success = (fcu != NULL); + + ANIM_animdata_freelist(&anim_data); + + /* F-Curve may not have any keyframes */ + if (fcu->bezt) { + BezTriple *bezt; + + if (!extend) { + filter = (ANIMFILTER_DATA_VISIBLE); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu_inner = (FCurve *)ale->key_data; + + if (fcu_inner) { + for (i = 0, bezt = fcu_inner->bezt; i < fcu_inner->totvert; i++, bezt++) { + bezt->f2 = bezt->f1 = bezt->f3 = 0; + } + } + } + + ANIM_animdata_freelist(&anim_data); + } + + for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { + bezt->f2 = bezt->f1 = bezt->f3 = SELECT; + } + } + + /* free temp data and tag for refresh */ + ED_region_tag_redraw(ac->ar); + return success; +} + +static int animchannels_channel_select_keys_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + bAnimContext ac; + int channel_index; + bool extend = RNA_boolean_get(op->ptr, "extend"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + channel_index = animchannels_channel_get(&ac, event->mval); + + /* handle click */ + if (select_anim_channel_keys(&ac, channel_index, extend)) { + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + return OPERATOR_FINISHED; + } + else + /* allow event to be handled by selectall operator */ + return OPERATOR_PASS_THROUGH; +} + +static void ANIM_OT_channel_select_keys(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Select Channel keyframes"; + ot->idname = "ANIM_OT_channel_select_keys"; + ot->description = "Select all keyframes of channel under mouse"; + + /* api callbacks */ + ot->invoke = animchannels_channel_select_keys_invoke; + ot->poll = animedit_poll_channels_active; + + prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); +} + /* ************************************************************************** */ /* Operator Registration */ @@ -3017,8 +3130,9 @@ void ED_operatortypes_animchannels(void) WM_operatortype_append(ANIM_OT_channels_select_border); WM_operatortype_append(ANIM_OT_channels_click); + WM_operatortype_append(ANIM_OT_channel_select_keys); WM_operatortype_append(ANIM_OT_channels_rename); - + WM_operatortype_append(ANIM_OT_channels_find); WM_operatortype_append(ANIM_OT_channels_setting_enable); @@ -3058,7 +3172,9 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf) /* rename */ WM_keymap_add_item(keymap, "ANIM_OT_channels_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "ANIM_OT_channels_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0); - + WM_keymap_add_item(keymap, "ANIM_OT_channel_select_keys", LEFTMOUSE, KM_DBL_CLICK, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channel_select_keys", LEFTMOUSE, KM_DBL_CLICK, KM_SHIFT, 0)->ptr, "extend", true); + /* find (i.e. a shortcut for setting the name filter) */ WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0); -- cgit v1.2.3 From f35489fa94f6e8f11b228f848c4eecc4dbd3cd9e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 22 Apr 2015 23:00:41 +0500 Subject: Tracking: Fix missing pointer array check when reading plane track This could cause memory corruption when moving files from system with one bitness to another. --- source/blender/blenloader/intern/readfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 21d69fe33c3..9dcb8722c23 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7075,7 +7075,7 @@ static void direct_link_moviePlaneTracks(FileData *fd, ListBase *plane_tracks_ba int i; plane_track->point_tracks = newdataadr(fd, plane_track->point_tracks); - + test_pointer_array(fd, (void**)&plane_track->point_tracks); for (i = 0; i < plane_track->point_tracksnr; i++) { plane_track->point_tracks[i] = newdataadr(fd, plane_track->point_tracks[i]); } -- cgit v1.2.3 From 147d0cdf985147d82c6b2f93c77e2052ab343e25 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 22 Apr 2015 23:20:00 +0500 Subject: Tracking: Show plane track outline if image failed to load --- source/blender/editors/space_clip/clip_draw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 6c55d8d034e..d0210025183 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -1123,7 +1123,9 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane { bool tiny = (sc->flag & SC_SHOW_TINY_MARKER) != 0; bool is_selected_track = (plane_track->flag & SELECT) != 0; - bool draw_plane_quad = plane_track->image == NULL || plane_track->image_opacity == 0.0f; + const bool has_image = plane_track->image != NULL && + BKE_image_has_ibuf(plane_track->image, NULL); + const bool draw_plane_quad = !has_image || plane_track->image_opacity == 0.0f; float px[2]; if (draw_outline) { -- cgit v1.2.3 From 31f984bc3ffcc83834372fb8302091fdaa7e98c8 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 22 Apr 2015 20:42:26 +0200 Subject: Show buttons to change render layer/pass in UV Editor header Previousely this was "hidden" in the Properties Region, this makes it more visible/usable. Requested by @sebastian_k --- source/blender/editors/space_image/image_buttons.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 2e9c2d96be5..2fb0a7e7c57 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -728,12 +728,12 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes } } -static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser, short *render_slot) +static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser, + int menus_width, short *render_slot) { uiBlock *block = uiLayoutGetBlock(layout); uiLayout *row; uiBut *but; - const float dpi_fac = UI_DPI_FAC; row = uiLayoutRow(layout, true); @@ -750,7 +750,7 @@ static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, Image *image, Ren but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_TRIA_RIGHT, 0, 0, 0.90f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Next Layer")); UI_but_func_set(but, image_multi_inclay_cb, rr, iuser); - uiblock_layer_pass_buttons(row, image, rr, iuser, 230 * dpi_fac, render_slot); + uiblock_layer_pass_buttons(row, image, rr, iuser, menus_width, render_slot); /* decrease, increase arrows */ but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_TRIA_LEFT, 0, 0, 0.85f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Previous Pass")); @@ -867,10 +867,11 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char else if (ima->type == IMA_TYPE_R_RESULT) { /* browse layer/passes */ RenderResult *rr; + const float dpi_fac = UI_DPI_FAC; /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */ rr = BKE_image_acquire_renderresult(scene, ima); - uiblock_layer_pass_arrow_buttons(layout, ima, rr, iuser, &ima->render_slot); + uiblock_layer_pass_arrow_buttons(layout, ima, rr, iuser, 230 * dpi_fac, &ima->render_slot); BKE_image_release_renderresult(scene, ima); } } @@ -903,7 +904,8 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char /* multilayer? */ if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) { - uiblock_layer_pass_arrow_buttons(layout, ima, ima->rr, iuser, NULL); + const float dpi_fac = UI_DPI_FAC; + uiblock_layer_pass_arrow_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL); } else if (ima->source != IMA_SRC_GENERATED) { if (compact == 0) { @@ -1211,12 +1213,18 @@ void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser /* render layers and passes */ if (ima && iuser) { - const float dpi_fac = UI_DPI_FAC; RenderResult *rr; + const float dpi_fac = UI_DPI_FAC; + const int menus_width = 160 * dpi_fac; /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */ rr = BKE_image_acquire_renderresult(scene, ima); - uiblock_layer_pass_buttons(layout, ima, rr, iuser, 160 * dpi_fac, (ima->type == IMA_TYPE_R_RESULT) ? &ima->render_slot : NULL); + if (ima->type == IMA_TYPE_R_RESULT) { + uiblock_layer_pass_arrow_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot); + } + else { + uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, NULL); + } BKE_image_release_renderresult(scene, ima); } } -- cgit v1.2.3 From 4a8421faa45c89399cb58ea7b372a6fe65721a55 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Wed, 22 Apr 2015 16:38:30 -0300 Subject: Fix T44463 - crash on "Full Sample" --- source/blender/render/intern/source/pipeline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index a1fbe7c5365..7b5692fbdb6 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2233,7 +2233,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) } } - for (nr = 0, rv = re->result->views.first; rv; rv = rv->next, nr++) { + for (nr = 0, rv = rectfs->first; rv; rv = rv->next, nr++) { rectf = rv->rectf; /* ensure we get either composited result or the active layer */ -- cgit v1.2.3 From 90b765233496aef50203e589fa8e2910fa980d78 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 22 Apr 2015 21:50:21 +0200 Subject: Fix T44472: Stereo 3D save options missing in File Browser --- source/blender/editors/space_image/image_ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index db4029d9678..24eb1195ab1 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1933,7 +1933,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) uiLayout *layout = op->layout; ImageFormatData *imf = op->customdata; PointerRNA imf_ptr, ptr; - const bool is_multiview = RNA_boolean_get(op->ptr, "use_multiview"); + const bool is_multiview = RNA_boolean_get(op->ptr, "show_multiview"); /* image template */ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr); @@ -1945,7 +1945,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) /* multiview template */ if (is_multiview) - uiTemplateImageFormatViews(layout, &imf_ptr, NULL); + uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr); } static int image_save_as_poll(bContext *C) -- cgit v1.2.3 From 6a1c123df461ef0820373c92573e411e2488a89c Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 22 Apr 2015 22:40:19 +0200 Subject: Fix broken uiTemplateIconView(). Was using enum **value** as **icon id**... tripple sigh! Guess it was working for its only current use (matcaps), but still. --- .../editors/interface/interface_templates.c | 25 +++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index c3a9d17d255..d333ab9f4c1 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1634,7 +1634,7 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem) static RNAUpdateCb cb; uiBlock *block; uiBut *but; - int icon; + int icon, value; EnumPropertyItem *item; int a; bool free; @@ -1659,7 +1659,9 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem) y = (a / 8) * UI_UNIT_X * 5; icon = item[a].icon; - but = uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, icon, x, y, UI_UNIT_X * 5, UI_UNIT_Y * 5, &cb.ptr, cb.prop, -1, 0, icon, -1, -1, NULL); + value = item[a].value; + but = uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, icon, x, y, UI_UNIT_X * 5, UI_UNIT_Y * 5, + &cb.ptr, cb.prop, -1, 0, value, -1, -1, NULL); UI_but_flag_enable(but, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); } @@ -1677,16 +1679,22 @@ void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); RNAUpdateCb *cb; + EnumPropertyItem *items; uiBlock *block; uiBut *but; // rctf rect; /* UNUSED */ - int icon; + int value, icon = ICON_NONE, tot_items; + bool free_items; if (!prop || RNA_property_type(prop) != PROP_ENUM) return; - - icon = RNA_property_enum_get(ptr, prop); - + + block = uiLayoutAbsoluteBlock(layout); + + RNA_property_enum_items(block->evil_C, ptr, prop, &items, &tot_items, &free_items); + value = RNA_property_enum_get(ptr, prop); + RNA_enum_icon_from_value(items, value, &icon); + cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); cb->ptr = *ptr; cb->prop = prop; @@ -1694,8 +1702,6 @@ void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname) // rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X; // rect.ymin = 0; rect.ymax = 10.0f * UI_UNIT_X; - block = uiLayoutAbsoluteBlock(layout); - but = uiDefBlockButN(block, ui_icon_view_menu_cb, MEM_dupallocN(cb), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); @@ -1707,6 +1713,9 @@ void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname) UI_but_funcN_set(but, rna_update_cb, MEM_dupallocN(cb), NULL); MEM_freeN(cb); + if (free_items) { + MEM_freeN(items); + } } /********************* Histogram Template ************************/ -- cgit v1.2.3 From ecb3362a244f082d58c6b73a044d661e4b80f320 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Wed, 22 Apr 2015 18:44:30 -0300 Subject: Fix T44396 - Compositing render slots don't work Note 1: If you go to a render slot previously rendered and change something in the compositing the buffer will still vanish. This is an old bug, T44181, and not addressed here (I'm basically just fixing the regression introduced with multiview) Note 2: I have a work in progress patch to get rid of RenderResult->rectf/rect32/rectz entirely. It still not working, and we should have a working code base before doing refactoring anyways. --- source/blender/blenkernel/intern/image.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 88a96ddef18..d743c067cb3 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -3522,6 +3522,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ { Render *re; RenderResult rres; + RenderView *rv; float *rectf, *rectz; unsigned int *rect; float dither; @@ -3570,10 +3571,14 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ *lock_r = re; } + rv = BLI_findlink(&rres.views, actview); + if (rv == NULL) + rv = rres.views.first; + /* this gives active layer, composite or sequence result */ - rect = (unsigned int *)rres.rect32; - rectf = rres.rectf; - rectz = rres.rectz; + rect = (unsigned int *)rv->rect32; + rectf = rv->rectf; + rectz = rv->rectz; dither = iuser->scene->r.dither_intensity; /* combined layer gets added as first layer */ -- cgit v1.2.3 From 0287b394680441b6836c43b8f01512c1c8e37800 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 23 Apr 2015 12:57:58 +1000 Subject: Py API: Remove deprecated callback_add --- release/scripts/modules/bpy_types.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 9b0352b7887..92dbd2dbd0e 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -781,24 +781,6 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta): layout.menu(cls.__name__, icon='COLLAPSEMENU') -class Region(StructRNA): - __slots__ = () - - def callback_add(self, cb, args, draw_mode): - """ - Append a draw function to this region, - deprecated, instead use bpy.types.SpaceView3D.draw_handler_add - """ - for area in self.id_data.areas: - for region in area.regions: - if region == self: - spacetype = type(area.spaces[0]) - return spacetype.draw_handler_add(cb, args, self.type, - draw_mode) - - return None - - class NodeTree(bpy_types.ID, metaclass=RNAMetaPropGroup): __slots__ = () -- cgit v1.2.3 From 87b3e62b3d2110d4701e49389492f1b3528c9cdf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 23 Apr 2015 16:09:30 +1000 Subject: Cleanup: warnings --- source/blender/blenkernel/intern/ocean.c | 4 ++-- source/blender/editors/space_view3d/view3d_draw.c | 4 ++-- source/blender/editors/transform/transform_conversions.c | 15 +++++++++------ .../gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index b89b5ab4bbc..1a178fb2bdf 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -738,8 +738,8 @@ static void set_height_normalize_factor(struct Ocean *oc) for (i = 0; i < oc->_M; ++i) { for (j = 0; j < oc->_N; ++j) { - if (max_h < fabsf(oc->_disp_y[i * oc->_N + j])) { - max_h = fabsf(oc->_disp_y[i * oc->_N + j]); + if (max_h < fabs(oc->_disp_y[i * oc->_N + j])) { + max_h = fabs(oc->_disp_y[i * oc->_N + j]); } } } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 0be1ad66ec8..520ad4f89b4 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1589,8 +1589,8 @@ unsigned int ED_view3d_backbuf_sample_rect( /* get x,y pixel coords from the offset * (manhatten distance in keeping with other screen-based selection) */ *r_dist = (float)( - abs(((tbuf - buf->rect) % size) - (size / 2)) + - abs(((tbuf - buf->rect) / size) - (size / 2))); + abs(((int)(tbuf - buf->rect) % size) - (size / 2)) + + abs(((int)(tbuf - buf->rect) / size) - (size / 2))); /* indices start at 1 here */ index = (*tbuf - min) + 1; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 0cdc2b5eb6c..8aa26c32413 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -31,6 +31,7 @@ #include #include +#include #include "DNA_anim_types.h" #include "DNA_brush_types.h" @@ -3755,13 +3756,14 @@ static void createTransActionData(bContext *C, TransInfo *t) } else { bGPDframe *gpf_iter; - float min = FLT_MAX; + int min = INT_MAX; for (gpf_iter = gpl->frames.first; gpf_iter; gpf_iter = gpf->next) { if (gpf_iter->flag & GP_FRAME_SELECT) { if (FrameOnMouseSide(t->frame_side, (float)gpf_iter->framenum, cfra)) { - float val = fabsf(gpf->framenum - gpf_iter->framenum); - if (val < min) + int val = abs(gpf->framenum - gpf_iter->framenum); + if (val < min) { min = val; + } } } } @@ -3781,13 +3783,14 @@ static void createTransActionData(bContext *C, TransInfo *t) } else { MaskLayerShape *masklay_iter; - float min = FLT_MAX; + int min = INT_MAX; for (masklay_iter = masklay->splines_shapes.first; masklay_iter; masklay_iter = masklay_iter->next) { if (masklay_iter->flag & MASK_SHAPE_SELECT) { if (FrameOnMouseSide(t->frame_side, (float)masklay_iter->frame, cfra)) { - float val = fabsf(masklay_shape->frame - masklay_iter->frame); - if (val < min) + int val = abs(masklay_shape->frame - masklay_iter->frame); + if (val < min) { min = val; + } } } } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 984273ec63e..186abdfe598 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -3672,7 +3672,7 @@ void CcdPhysicsEnvironment::SetupObjectConstraints(KX_GameObject *obj_src, KX_Ga break; } - for (dof; dof < dof_max; dof++) { + for (; dof < dof_max; dof++) { if (dat->flag & dofbit) { phys_env->SetConstraintParam(constraintId, dof, dat->minLimit[dof], dat->maxLimit[dof]); } -- cgit v1.2.3 From 8010672bbc1a89e2b7c30bc22e936052325e4b75 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 23 Apr 2015 16:11:54 +1000 Subject: BMesh: mesh-data picking, edge+vert improvement When zoomed out vert bias over edges meant it wasn't possible to select edges. Now pick the edge if the cursor is closer to its center. --- source/blender/editors/include/ED_mesh.h | 14 ++- source/blender/editors/mesh/editmesh_select.c | 120 +++++++++++++++++++++----- 2 files changed, 110 insertions(+), 24 deletions(-) diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index b982ff2a83b..55a254c7941 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -137,17 +137,23 @@ bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2] short xmin, short ymin, short xmax, short ymax); bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads); -struct BMVert *EDBM_vert_find_nearest_ex(struct ViewContext *vc, float *r_dist, +struct BMVert *EDBM_vert_find_nearest_ex( + struct ViewContext *vc, float *r_dist, const bool use_select_bias, bool use_cycle); struct BMVert *EDBM_vert_find_nearest( struct ViewContext *vc, float *r_dist); -struct BMEdge *EDBM_edge_find_nearest_ex(struct ViewContext *vc, float *r_dist, - const bool use_select_bias, const bool use_cycle); +struct BMEdge *EDBM_edge_find_nearest_ex( + struct ViewContext *vc,float *r_dist, + float *r_dist_center, + const bool use_select_bias, const bool use_cycle, + struct BMEdge **r_eed_zbuf); struct BMEdge *EDBM_edge_find_nearest( struct ViewContext *vc, float *r_dist); -struct BMFace *EDBM_face_find_nearest_ex(struct ViewContext *vc, float *r_dist, +struct BMFace *EDBM_face_find_nearest_ex( + struct ViewContext *vc, float *r_dist, + float *r_dist_center, const bool use_select_bias, const bool use_cycle, struct BMFace **r_efa_zbuf); struct BMFace *EDBM_face_find_nearest( diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 90b683c5abd..3760ebcc2a4 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -489,11 +489,42 @@ BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist) return EDBM_vert_find_nearest_ex(vc, r_dist, false, false); } +/* find the distance to the edge we already have */ +struct NearestEdgeUserData_ZBuf { + float mval_fl[2]; + float dist; + const BMEdge *edge_test; +}; + +static void find_nearest_edge_center__doZBuf( + void *userData, BMEdge *eed, + const float screen_co_a[2], const float screen_co_b[2], + int UNUSED(index)) +{ + struct NearestEdgeUserData_ZBuf *data = userData; + + if (eed == data->edge_test) { + float dist_test; + float screen_co_mid[2]; + + mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b); + dist_test = len_manhattan_v2v2(data->mval_fl, screen_co_mid); + + if (dist_test < data->dist) { + data->dist = dist_test; + } + } +} + struct NearestEdgeUserData_Hit { float dist; float dist_bias; int index; BMEdge *edge; + + /* edges only, un-biased manhatten distance to which ever edge we pick + * (not used for choosing) */ + float dist_center; }; struct NearestEdgeUserData { @@ -508,7 +539,10 @@ struct NearestEdgeUserData { }; /* note; uses v3d, so needs active 3d window */ -static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) +static void find_nearest_edge__doClosest( + void *userData, BMEdge *eed, + const float screen_co_a[2], const float screen_co_b[2], + int index) { struct NearestEdgeUserData *data = userData; float dist_test, dist_test_bias; @@ -544,10 +578,15 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float } if (dist_test_bias < data->hit.dist_bias) { + float screen_co_mid[2]; + data->hit.dist_bias = dist_test_bias; data->hit.dist = dist_test; data->hit.index = index; data->hit.edge = eed; + + mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b); + data->hit.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid); } if (data->use_cycle) { @@ -555,23 +594,30 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float (index > data->cycle_index_prev) && (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN)) { + float screen_co_mid[2]; + data->hit_cycle.dist_bias = dist_test_bias; data->hit_cycle.dist = dist_test; data->hit_cycle.index = index; data->hit_cycle.edge = eed; + + mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b); + data->hit_cycle.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid); } } } BMEdge *EDBM_edge_find_nearest_ex( ViewContext *vc, float *r_dist, - const bool use_select_bias, const bool use_cycle) + float *r_dist_center, + const bool use_select_bias, const bool use_cycle, + BMEdge **r_eed_zbuf) { BMesh *bm = vc->em->bm; if (V3D_IS_ZBUF(vc->v3d)) { const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); - float dist_test; + float dist_test = 0.0f; unsigned int index; BMEdge *eed; @@ -579,7 +625,28 @@ BMEdge *EDBM_edge_find_nearest_ex( index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test); eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; - + + if (r_eed_zbuf) { + *r_eed_zbuf = eed; + } + + /* exception for faces (verts don't need this) */ + if (r_dist_center && eed) { + struct NearestEdgeUserData_ZBuf data; + + data.mval_fl[0] = vc->mval[0]; + data.mval_fl[1] = vc->mval[1]; + data.dist = FLT_MAX; + data.edge_test = eed; + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + + mesh_foreachScreenEdge(vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + + *r_dist_center = data.dist; + } + /* end exception */ + if (eed) { if (dist_test < *r_dist) { *r_dist = dist_test; @@ -614,10 +681,11 @@ BMEdge *EDBM_edge_find_nearest_ex( data.cycle_index_prev = prev_select_index; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, clip_flag); + mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag); hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit; *r_dist = hit->dist; + *r_dist_center = hit->dist_center; prev_select_elem = hit->edge; prev_select_index = hit->index; @@ -629,7 +697,7 @@ BMEdge *EDBM_edge_find_nearest_ex( BMEdge *EDBM_edge_find_nearest( ViewContext *vc, float *r_dist) { - return EDBM_edge_find_nearest_ex(vc, r_dist, false, false); + return EDBM_edge_find_nearest_ex(vc, r_dist, false, false, false, NULL); } /* find the distance to the face we already have */ @@ -639,7 +707,7 @@ struct NearestFaceUserData_ZBuf { const BMFace *face_test; }; -static void findnearestface__doZBuf(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index)) +static void find_nearest_face_center__doZBuf(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index)) { struct NearestFaceUserData_ZBuf *data = userData; @@ -704,13 +772,14 @@ static void findnearestface__doClosest(void *userData, BMFace *efa, const float BMFace *EDBM_face_find_nearest_ex( ViewContext *vc, float *r_dist, + float *r_dist_center, const bool use_select_bias, const bool use_cycle, BMFace **r_efa_zbuf) { BMesh *bm = vc->em->bm; if (V3D_IS_ZBUF(vc->v3d)) { - float dist_test; + float dist_test = 0.0f; unsigned int index; BMFace *efa; @@ -723,8 +792,8 @@ BMFace *EDBM_face_find_nearest_ex( *r_efa_zbuf = efa; } - /* exception for faces (verts/edges don't need this) */ - if (efa) { + /* exception for faces (verts don't need this) */ + if (r_dist_center && efa) { struct NearestFaceUserData_ZBuf data; data.mval_fl[0] = vc->mval[0]; @@ -734,9 +803,9 @@ BMFace *EDBM_face_find_nearest_ex( ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenFace(vc, findnearestface__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenFace(vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - dist_test = data.dist; + *r_dist_center = data.dist; } /* end exception */ @@ -775,7 +844,7 @@ BMFace *EDBM_face_find_nearest_ex( mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag); hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit; - *r_dist = hit->dist; + *r_dist = *r_dist_center = hit->dist; prev_select_elem = hit->face; prev_select_index = hit->index; @@ -786,7 +855,7 @@ BMFace *EDBM_face_find_nearest_ex( BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) { - return EDBM_face_find_nearest_ex(vc, r_dist, false, false, NULL); + return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL); } #undef FIND_NEAR_SELECT_BIAS @@ -806,9 +875,10 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, const bool use_cycle = ((mval_prev[0] == vc->mval[0]) && (mval_prev[1] == vc->mval[1])); const float dist_init = ED_view3d_select_dist_px(); /* since edges select lines, we give dots advantage of ~20 pix */ - const float dist_bias = (dist_init / 4); + const float dist_margin = (dist_init / 2); float dist = dist_init; BMFace *efa_zbuf = NULL; + BMEdge *eed_zbuf = NULL; BMVert *eve = NULL; BMEdge *eed = NULL; @@ -819,13 +889,20 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, ED_view3d_backbuf_validate(vc); if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) { - efa = EDBM_face_find_nearest_ex(vc, &dist, true, use_cycle, &efa_zbuf); + float dist_center = 0.0f; + float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL; + efa = EDBM_face_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf); + if (efa && dist_center_p) { + dist = min_ff(dist_margin, dist_center); + } } if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) { - eed = EDBM_edge_find_nearest_ex(vc, &dist, true, use_cycle); - if (eed) { - dist = min_ff(dist + dist_bias, dist_init); + float dist_center = 0.0f; + float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL; + eed = EDBM_edge_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf); + if (eed && dist_center_p) { + dist = min_ff(dist_margin, dist_center); } } @@ -844,7 +921,10 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, /* there may be a face under the cursor, who's center if too far away * use this if all else fails, it makes sense to select this */ if ((eve || eed || efa) == 0) { - if (efa_zbuf) { + if (eed_zbuf) { + eed = eed_zbuf; + } + else if (efa_zbuf) { efa = efa_zbuf; } } -- cgit v1.2.3 From 85e455b2458f68c1d2c75fed7b5963fce4a70027 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Thu, 23 Apr 2015 13:21:36 +0200 Subject: Fix slot menu not displayed if render result slot is empty Caused by own mistake in 31f984bc3ffcc83834, reported by @sebastian_k in IRC --- source/blender/editors/space_image/image_buttons.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 2fb0a7e7c57..09ee5a26634 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -1216,14 +1216,16 @@ void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser RenderResult *rr; const float dpi_fac = UI_DPI_FAC; const int menus_width = 160 * dpi_fac; + const bool is_render_result = (ima->type == IMA_TYPE_R_RESULT); /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */ rr = BKE_image_acquire_renderresult(scene, ima); - if (ima->type == IMA_TYPE_R_RESULT) { + if (rr && is_render_result) { uiblock_layer_pass_arrow_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot); } else { - uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, NULL); + uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, + is_render_result ? &ima->render_slot : NULL); } BKE_image_release_renderresult(scene, ima); } -- cgit v1.2.3 From 2dfbf31a41308ca440a440d5a66f59bf63df7589 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Thu, 23 Apr 2015 13:33:29 +0200 Subject: Display slot menu in Properties Region even if render slot is empty For the records, this one is caused by 31f984bc3ffcc838343, it wasn't implemented at all ;) --- source/blender/editors/space_image/image_buttons.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 09ee5a26634..1c668c33597 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -868,10 +868,16 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char /* browse layer/passes */ RenderResult *rr; const float dpi_fac = UI_DPI_FAC; + const int menus_width = 230 * dpi_fac; /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */ rr = BKE_image_acquire_renderresult(scene, ima); - uiblock_layer_pass_arrow_buttons(layout, ima, rr, iuser, 230 * dpi_fac, &ima->render_slot); + if (rr) { + uiblock_layer_pass_arrow_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot); + } + else { + uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot); + } BKE_image_release_renderresult(scene, ima); } } -- cgit v1.2.3 From bcac112dde72a82180ed26d1fddea08766a0a788 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 23 Apr 2015 14:23:28 +0200 Subject: Fix T44494 crop node changes values during execution. We used the node data as a store for node execution, bad idea, since the data itself is a template from which execution data should be derived, never to be modified during execution. --- .../compositor/operations/COM_CropOperation.cpp | 33 +++++++++++----------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/source/blender/compositor/operations/COM_CropOperation.cpp b/source/blender/compositor/operations/COM_CropOperation.cpp index 9bcc6fb2541..e5427589fce 100644 --- a/source/blender/compositor/operations/COM_CropOperation.cpp +++ b/source/blender/compositor/operations/COM_CropOperation.cpp @@ -36,27 +36,28 @@ void CropBaseOperation::updateArea() SocketReader *inputReference = this->getInputSocketReader(0); float width = inputReference->getWidth(); float height = inputReference->getHeight(); + NodeTwoXYs local_settings = *this->m_settings; if (width > 0.0f && height > 0.0f) { if (this->m_relative) { - this->m_settings->x1 = width * this->m_settings->fac_x1; - this->m_settings->x2 = width * this->m_settings->fac_x2; - this->m_settings->y1 = height * this->m_settings->fac_y1; - this->m_settings->y2 = height * this->m_settings->fac_y2; + local_settings.x1 = width * local_settings.fac_x1; + local_settings.x2 = width * local_settings.fac_x2; + local_settings.y1 = height * local_settings.fac_y1; + local_settings.y2 = height * local_settings.fac_y2; } - if (width <= this->m_settings->x1 + 1) - this->m_settings->x1 = width - 1; - if (height <= this->m_settings->y1 + 1) - this->m_settings->y1 = height - 1; - if (width <= this->m_settings->x2 + 1) - this->m_settings->x2 = width - 1; - if (height <= this->m_settings->y2 + 1) - this->m_settings->y2 = height - 1; + if (width <= local_settings.x1 + 1) + local_settings.x1 = width - 1; + if (height <= local_settings.y1 + 1) + local_settings.y1 = height - 1; + if (width <= local_settings.x2 + 1) + local_settings.x2 = width - 1; + if (height <= local_settings.y2 + 1) + local_settings.y2 = height - 1; - this->m_xmax = max(this->m_settings->x1, this->m_settings->x2) + 1; - this->m_xmin = min(this->m_settings->x1, this->m_settings->x2); - this->m_ymax = max(this->m_settings->y1, this->m_settings->y2) + 1; - this->m_ymin = min(this->m_settings->y1, this->m_settings->y2); + this->m_xmax = max(local_settings.x1, local_settings.x2) + 1; + this->m_xmin = min(local_settings.x1, local_settings.x2); + this->m_ymax = max(local_settings.y1, local_settings.y2) + 1; + this->m_ymin = min(local_settings.y1, local_settings.y2); } else { this->m_xmax = 0; -- cgit v1.2.3 From 22b564f93ef4bd7c981a7986addf5fe466954592 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 23 Apr 2015 10:59:35 -0300 Subject: Fix T44498 - Blender crashes in some files after render slots fix This is a temporary fix until I get to investigate it more carefully. It will help if the report could include the steps to reproduce it besides the buggy file. Note: RenderResult should *always* have at least a valid RenderView, which is not what happens here. --- source/blender/blenkernel/intern/image.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index d743c067cb3..b9a76a125a4 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -3575,10 +3575,18 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ if (rv == NULL) rv = rres.views.first; - /* this gives active layer, composite or sequence result */ - rect = (unsigned int *)rv->rect32; - rectf = rv->rectf; - rectz = rv->rectz; + if (rv != NULL) { + /* this gives active layer, composite or sequence result */ + rect = (unsigned int *)rv->rect32; + rectf = rv->rectf; + rectz = rv->rectz; + } + else { + /* XXX This should never happen, yet it does - T44498 + * I'm waiting to investigate more, but meanwhile this fix + * the immediate issue */ + rect = NULL; + } dither = iuser->scene->r.dither_intensity; /* combined layer gets added as first layer */ -- cgit v1.2.3 From 27e03dcd21872d9daf73adf42c69c04c5806ac07 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Apr 2015 00:12:16 +1000 Subject: Fix T44422: Zoom to mouse fails in camera view Camera now supports all zoom styles too. --- source/blender/editors/space_view3d/view3d_edit.c | 231 +++++++++++++++------- source/blender/makesdna/DNA_view3d_types.h | 5 +- 2 files changed, 167 insertions(+), 69 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 236fefc7088..3f6f17da334 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -517,6 +517,7 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip) typedef struct ViewOpsData { /* context pointers (assigned by viewops_data_alloc) */ + Scene *scene; ScrArea *sa; ARegion *ar; View3D *v3d; @@ -589,6 +590,7 @@ static void viewops_data_alloc(bContext *C, wmOperator *op) /* store data */ op->customdata = vod; + vod->scene = CTX_data_scene(C); vod->sa = CTX_wm_area(C); vod->ar = CTX_wm_region(C); vod->v3d = vod->sa->spacedata.first; @@ -2093,16 +2095,63 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom"); } -static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my) +static void view_zoom_mouseloc_camera( + Scene *scene, View3D *v3d, + ARegion *ar, float dfac, int mx, int my) { RegionView3D *rv3d = ar->regiondata; + const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom); + const float zoomfac_new = CLAMPIS(zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR); + const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new); + + + if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { + float zoomfac_px; + rctf camera_frame_old; + rctf camera_frame_new; + + const float pt_src[2] = {mx, my}; + float pt_dst[2]; + float delta_px[2]; + + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_old, false); + BLI_rctf_translate(&camera_frame_old, ar->winrct.xmin, ar->winrct.ymin); + + rv3d->camzoom = camzoom_new; + CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); + + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_new, false); + BLI_rctf_translate(&camera_frame_new, ar->winrct.xmin, ar->winrct.ymin); + + BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src); + sub_v2_v2v2(delta_px, pt_dst, pt_src); + + /* translate the camera offset using pixel space delta + * mapped back to the camera (same logic as panning in camera view) */ + zoomfac_px = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 2.0f; + + rv3d->camdx += delta_px[0] / (ar->winx * zoomfac_px); + rv3d->camdy += delta_px[1] / (ar->winy * zoomfac_px); + CLAMP(rv3d->camdx, -1.0f, 1.0f); + CLAMP(rv3d->camdy, -1.0f, 1.0f); + } + else { + rv3d->camzoom = camzoom_new; + CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); + } +} + +static void view_zoom_mouseloc_3d(ARegion *ar, float dfac, int mx, int my) +{ + RegionView3D *rv3d = ar->regiondata; + const float dist_new = rv3d->dist * dfac; if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { float dvec[3]; float tvec[3]; float tpos[3]; float mval_f[2]; - float new_dist; + float zfac; negate_v3_v3(tpos, rv3d->ofs); @@ -2119,105 +2168,133 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my) negate_v3(tvec); /* Offset to target position and dolly */ - new_dist = rv3d->dist * dfac; - copy_v3_v3(rv3d->ofs, tvec); - rv3d->dist = new_dist; + rv3d->dist = dist_new; /* Calculate final offset */ madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac); } else { - rv3d->dist *= dfac; + rv3d->dist = dist_new; } } - -static void viewzoom_apply(ViewOpsData *vod, const int xy[2], const short viewzoom, const short zoom_invert) +static float viewzoom_scale_value( + const rcti *winrct, + const short viewzoom, + const bool zoom_invert, const bool zoom_invert_force, + const int xy[2], const int xy_orig[2], + const float val, const float val_orig, + double *r_timer_lastdraw) { - float zfac = 1.0; - bool use_cam_zoom; - float dist_range[2]; - - use_cam_zoom = (vod->rv3d->persp == RV3D_CAMOB) && !(vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)); - - ED_view3d_dist_range_get(vod->v3d, dist_range); - - if (use_cam_zoom) { - float delta; - delta = (xy[0] - vod->origx + xy[1] - vod->origy) / 10.0f; - vod->rv3d->camzoom = vod->camzoom_prev + (zoom_invert ? -delta : delta); - - CLAMP(vod->rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); - } + float zfac; if (viewzoom == USER_ZOOM_CONT) { double time = PIL_check_seconds_timer(); - float time_step = (float)(time - vod->timer_lastdraw); + float time_step = (float)(time - *r_timer_lastdraw); float fac; if (U.uiflag & USER_ZOOM_HORIZ) { - fac = (float)(vod->origx - xy[0]); + fac = (float)(xy_orig[0] - xy[0]); } else { - fac = (float)(vod->origy - xy[1]); + fac = (float)(xy_orig[1] - xy[1]); } - if (zoom_invert) { + if (zoom_invert != zoom_invert_force) { fac = -fac; } /* oldstyle zoom */ zfac = 1.0f + ((fac / 20.0f) * time_step); - vod->timer_lastdraw = time; + *r_timer_lastdraw = time; } else if (viewzoom == USER_ZOOM_SCALE) { /* method which zooms based on how far you move the mouse */ const int ctr[2] = { - BLI_rcti_cent_x(&vod->ar->winrct), - BLI_rcti_cent_y(&vod->ar->winrct), + BLI_rcti_cent_x(winrct), + BLI_rcti_cent_y(winrct), }; - const float len_new = 5 + len_v2v2_int(ctr, xy); - const float len_old = 5 + len_v2v2_int(ctr, &vod->origx); - zfac = vod->dist_prev * ((len_old + 5) / (len_new + 5)) / vod->rv3d->dist; + float len_new = 5 + len_v2v2_int(ctr, xy); + float len_old = 5 + len_v2v2_int(ctr, xy_orig); + + /* intentionally ignore 'zoom_invert' for scale */ + if (zoom_invert_force) { + SWAP(float, len_new, len_old); + } + + zfac = val_orig * (len_old / max_ff(len_new, 1.0f)) / val; } else { /* USER_ZOOM_DOLLY */ - float len1, len2; - + float len_new = 5; + float len_old = 5; + if (U.uiflag & USER_ZOOM_HORIZ) { - len1 = (vod->ar->winrct.xmax - xy[0]) + 5; - len2 = (vod->ar->winrct.xmax - vod->origx) + 5; + len_new += (winrct->xmax - xy[0]); + len_old += (winrct->xmax - xy_orig[0]); } else { - len1 = (vod->ar->winrct.ymax - xy[1]) + 5; - len2 = (vod->ar->winrct.ymax - vod->origy) + 5; - } - if (zoom_invert) { - SWAP(float, len1, len2); + len_new += (winrct->ymax - xy[1]); + len_old += (winrct->ymax - xy_orig[1]); } - - if (use_cam_zoom) { - /* zfac is ignored in this case, see below */ -#if 0 - zfac = vod->camzoom_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->camzoom; -#endif - } - else { - zfac = vod->dist_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->dist; + + if (zoom_invert != zoom_invert_force) { + SWAP(float, len_new, len_old); } + + zfac = val_orig * (2.0f * ((len_new / max_ff(len_old, 1.0f)) - 1.0f) + 1.0f) / val; } - if (!use_cam_zoom) { - if (zfac != 1.0f) { - const float zfac_min = dist_range[0] / vod->rv3d->dist; - const float zfac_max = dist_range[1] / vod->rv3d->dist; - CLAMP(zfac, zfac_min, zfac_max); - if (zfac != 1.0f) { - view_zoom_mouseloc(vod->ar, zfac, vod->oldx, vod->oldy); - } - } + return zfac; +} + +static void viewzoom_apply_camera( + ViewOpsData *vod, const int xy[2], + const short viewzoom, const bool zoom_invert) +{ + float zfac; + float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->camzoom_prev) * 2.0f; + float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f; + + zfac = viewzoom_scale_value( + &vod->ar->winrct, viewzoom, zoom_invert, true, xy, &vod->origx, + zoomfac, zoomfac_prev, + &vod->timer_lastdraw); + + if (zfac != 1.0f && zfac != 0.0f) { + /* calculate inverted, then invert again (needed because of camera zoom scaling) */ + zfac = 1.0f / zfac; + view_zoom_mouseloc_camera( + vod->scene, vod->v3d, + vod->ar, zfac, vod->oldx, vod->oldy); + } + + ED_region_tag_redraw(vod->ar); +} + +static void viewzoom_apply_3d( + ViewOpsData *vod, const int xy[2], + const short viewzoom, const bool zoom_invert) +{ + float zfac; + float dist_range[2]; + + ED_view3d_dist_range_get(vod->v3d, dist_range); + + zfac = viewzoom_scale_value( + &vod->ar->winrct, viewzoom, zoom_invert, false, xy, &vod->origx, + vod->rv3d->dist, vod->dist_prev, + &vod->timer_lastdraw); + + if (zfac != 1.0f) { + const float zfac_min = dist_range[0] / vod->rv3d->dist; + const float zfac_max = dist_range[1] / vod->rv3d->dist; + CLAMP(zfac, zfac_min, zfac_max); + + view_zoom_mouseloc_3d( + vod->ar, zfac, vod->oldx, vod->oldy); } /* these limits were in old code too */ @@ -2231,6 +2308,19 @@ static void viewzoom_apply(ViewOpsData *vod, const int xy[2], const short viewzo ED_region_tag_redraw(vod->ar); } +static void viewzoom_apply( + ViewOpsData *vod, const int xy[2], + const short viewzoom, const bool zoom_invert) +{ + if ((vod->rv3d->persp == RV3D_CAMOB) && + (vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0) + { + viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert); + } + else { + viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert); + } +} static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event) { @@ -2291,6 +2381,7 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event) static int viewzoom_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); View3D *v3d; RegionView3D *rv3d; ScrArea *sa; @@ -2323,22 +2414,26 @@ static int viewzoom_exec(bContext *C, wmOperator *op) ED_view3d_dist_range_get(v3d, dist_range); if (delta < 0) { + const float step = 1.2f; /* this min and max is also in viewmove() */ if (use_cam_zoom) { - rv3d->camzoom -= 10.0f; - if (rv3d->camzoom < RV3D_CAMZOOM_MIN) rv3d->camzoom = RV3D_CAMZOOM_MIN; + view_zoom_mouseloc_camera(scene, v3d, ar, step, mx, my); } - else if (rv3d->dist < dist_range[1]) { - view_zoom_mouseloc(ar, 1.2f, mx, my); + else { + if (rv3d->dist < dist_range[1]) { + view_zoom_mouseloc_3d(ar, step, mx, my); + } } } else { + const float step = 1.0f / 1.2f; if (use_cam_zoom) { - rv3d->camzoom += 10.0f; - if (rv3d->camzoom > RV3D_CAMZOOM_MAX) rv3d->camzoom = RV3D_CAMZOOM_MAX; + view_zoom_mouseloc_camera(scene, v3d, ar, step, mx, my); } - else if (rv3d->dist > dist_range[0]) { - view_zoom_mouseloc(ar, 0.83333f, mx, my); + else { + if (rv3d->dist > dist_range[0]) { + view_zoom_mouseloc_3d(ar, step, mx, my); + } } } diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 66ee1fe4242..a0516590d43 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -379,6 +379,9 @@ enum { #define RV3D_CAMZOOM_MIN -30 #define RV3D_CAMZOOM_MAX 600 -#endif +/* #BKE_screen_view3d_zoom_to_fac() values above */ +#define RV3D_CAMZOOM_MIN_FACTOR 0.1657359312880714853f +#define RV3D_CAMZOOM_MAX_FACTOR 44.9852813742385702928f +#endif -- cgit v1.2.3 From 372752c7393025342997f8ba6c076576280b3019 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Apr 2015 01:37:12 +1000 Subject: Math Lib: add count_bits_i utility function --- source/blender/blenlib/BLI_math_bits.h | 6 ++++++ source/blender/blenlib/intern/math_bits_inline.c | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/source/blender/blenlib/BLI_math_bits.h b/source/blender/blenlib/BLI_math_bits.h index 2569c4cb41e..876c0d92e31 100644 --- a/source/blender/blenlib/BLI_math_bits.h +++ b/source/blender/blenlib/BLI_math_bits.h @@ -34,6 +34,12 @@ extern "C" { MINLINE unsigned int highest_order_bit_i(unsigned int n); MINLINE unsigned short highest_order_bit_s(unsigned short n); +#ifdef __GNUC__ +# define count_bits_i(i) __builtin_popcount(i) +#else +MINLINE int count_bits_i(unsigned int n); +#endif + #if BLI_MATH_DO_INLINE #include "intern/math_bits_inline.c" #endif diff --git a/source/blender/blenlib/intern/math_bits_inline.c b/source/blender/blenlib/intern/math_bits_inline.c index f5bec405b2c..11ee6e7fa5b 100644 --- a/source/blender/blenlib/intern/math_bits_inline.c +++ b/source/blender/blenlib/intern/math_bits_inline.c @@ -46,4 +46,14 @@ MINLINE unsigned short highest_order_bit_s(unsigned short n) return (unsigned short)(n - (n >> 1)); } +#ifndef __GNUC__ +MINLINE int count_bits_i(unsigned int i) +{ + /* variable-precision SWAR algorithm. */ + i = i - ((i >> 1) & 0x55555555); + i = (i & 0x33333333) + ((i >> 2) & 0x33333333); + return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; +} +#endif + #endif /* __MATH_BITS_INLINE_C__ */ -- cgit v1.2.3 From 61ac5dd5bac352bd2f5bf6229ba12357582c2044 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Apr 2015 02:38:15 +1000 Subject: Correct missing NULL check (own mistake) --- source/blender/editors/mesh/editmesh_select.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 3760ebcc2a4..be3cb1c5fe1 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -685,7 +685,9 @@ BMEdge *EDBM_edge_find_nearest_ex( hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit; *r_dist = hit->dist; - *r_dist_center = hit->dist_center; + if (r_dist_center) { + *r_dist_center = hit->dist_center; + } prev_select_elem = hit->edge; prev_select_index = hit->index; @@ -844,7 +846,10 @@ BMFace *EDBM_face_find_nearest_ex( mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag); hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit; - *r_dist = *r_dist_center = hit->dist; + *r_dist = hit->dist; + if (r_dist_center) { + *r_dist_center = hit->dist; + } prev_select_elem = hit->face; prev_select_index = hit->index; -- cgit v1.2.3 From d2f35d6d5001dbe190bb3e147caec1b974d373ab Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 23 Apr 2015 19:02:08 +0200 Subject: 3D textures: detect if we are pushing OpenGL too hard with the texture size. --- source/blender/gpu/intern/gpu_extensions.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 0d735d11902..9e361a49db3 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -561,6 +561,7 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f GLenum type, format, internalformat; void *pixels = NULL; const float vfBorderColor[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + int r_width; if (!GLEW_VERSION_1_2) return NULL; @@ -603,24 +604,37 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f internalformat = GL_INTENSITY; } + /* 3D textures are quite heavy, test if it's possible to create them first */ + glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL); + glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width); + + if (r_width == 0) { + fprintf(stderr, "OpenGL cannot handle a 3D texture of this size\n"); + glBindTexture(tex->target, 0); + GPU_texture_free(tex); + return NULL; + } + #if 0 if (fpixels) pixels = GPU_texture_convert_pixels(w*h*depth, fpixels); #endif - glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL); - GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D"); if (fpixels) { if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) { /* clear first to avoid unitialized pixels */ float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero"); - glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, format, type, zero); + glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL); + glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, GL_INTENSITY, GL_FLOAT, zero); + glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels); MEM_freeN(zero); } + else { + glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels); + } - glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels); GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D"); } -- cgit v1.2.3 From 18ee59372979b98f33c054dd5d92ed8cc72b321c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 3 Nov 2014 23:31:55 +0100 Subject: Expose CD_PAINT_MASK to Python API D782 by Stanislav Blinov --- source/blender/makesrna/intern/rna_mesh.c | 72 ++++++++++++++++++++++ .../python/bmesh/bmesh_py_types_customdata.c | 6 ++ 2 files changed, 78 insertions(+) diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index b1f0adb0d98..400e98befd0 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -1143,6 +1143,37 @@ static int rna_MeshSkinVertexLayer_data_length(PointerRNA *ptr) /* End skin vertices */ +/* Paint mask */ +DEFINE_CUSTOMDATA_LAYER_COLLECTION(vertex_paint_mask, vdata, CD_PAINT_MASK) + +static char *rna_MeshPaintMaskLayer_path(PointerRNA *ptr) +{ + CustomDataLayer *cdl = ptr->data; + char name_esc[sizeof(cdl->name) * 2]; + BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + return BLI_sprintfN("vertex_paint_masks[\"%s\"]", name_esc); +} + +static char *rna_MeshPaintMask_path(PointerRNA *ptr) +{ + return rna_VertCustomData_data_path(ptr, "vertex_paint_masks", CD_PAINT_MASK); +} + +static void rna_MeshPaintMaskLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + Mesh *me = rna_mesh(ptr); + CustomDataLayer *layer = (CustomDataLayer *)ptr->data; + rna_iterator_array_begin(iter, layer->data, sizeof(MFloatProperty), me->totvert, 0, NULL); +} + +static int rna_MeshPaintMaskLayer_data_length(PointerRNA *ptr) +{ + Mesh *me = rna_mesh(ptr); + return me->totvert; +} + +/* End paint mask */ + static void rna_TexturePoly_image_set(PointerRNA *ptr, PointerRNA value) { MTexPoly *tf = (MTexPoly *)ptr->data; @@ -1783,6 +1814,7 @@ static void UNUSED_FUNCTION(rna_mesh_unused)(void) { /* unused functions made by macros */ (void)rna_Mesh_skin_vertice_index_range; + (void)rna_Mesh_vertex_paint_mask_index_range; (void)rna_Mesh_tessface_uv_texture_active_set; (void)rna_Mesh_tessface_uv_texture_clone_get; (void)rna_Mesh_tessface_uv_texture_clone_index_get; @@ -3172,6 +3204,36 @@ static void rna_def_skin_vertices(BlenderRNA *brna, PropertyRNA *UNUSED(cprop)) RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); } +static void rna_def_paint_mask(BlenderRNA *brna, PropertyRNA *UNUSED(cprop)) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "MeshPaintMaskLayer", NULL); + RNA_def_struct_ui_text(srna, "Mesh Paint Mask Layer", "Per-vertex paint mask data"); + RNA_def_struct_sdna(srna, "CustomDataLayer"); + RNA_def_struct_path_func(srna, "rna_MeshPaintMaskLayer_path"); + + prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "MeshPaintMaskProperty"); + RNA_def_property_ui_text(prop, "Data", ""); + + RNA_def_property_collection_funcs(prop, "rna_MeshPaintMaskLayer_data_begin", "rna_iterator_array_next", + "rna_iterator_array_end", "rna_iterator_array_get", + "rna_MeshPaintMaskLayer_data_length", NULL, NULL, NULL); + + srna = RNA_def_struct(brna, "MeshPaintMaskProperty", NULL); + RNA_def_struct_sdna(srna, "MFloatProperty"); + RNA_def_struct_ui_text(srna, "Mesh Paint Mask Property", + "Floating point paint mask value"); + RNA_def_struct_path_func(srna, "rna_MeshPaintMask_path"); + + prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "f"); + RNA_def_property_ui_text(prop, "Value", ""); + RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); +} + static void rna_def_mesh(BlenderRNA *brna) { StructRNA *srna; @@ -3376,6 +3438,16 @@ static void rna_def_mesh(BlenderRNA *brna) rna_def_skin_vertices(brna, prop); /* End skin vertices */ + /* Paint mask */ + prop = RNA_def_property(srna, "vertex_paint_masks", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer"); + RNA_def_property_collection_funcs(prop, "rna_Mesh_vertex_paint_masks_begin", NULL, NULL, NULL, + "rna_Mesh_vertex_paint_masks_length", NULL, NULL, NULL); + RNA_def_property_struct_type(prop, "MeshPaintMaskLayer"); + RNA_def_property_ui_text(prop, "Vertex Paint Mask", "Vertex paint mask"); + rna_def_paint_mask(brna, prop); + /* End paint mask */ + prop = RNA_def_property(srna, "use_auto_smooth", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_AUTOSMOOTH); RNA_def_property_ui_text(prop, "Auto Smooth", diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c index 7b6e062896f..3adf37f78f0 100644 --- a/source/blender/python/bmesh/bmesh_py_types_customdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c @@ -116,6 +116,9 @@ PyDoc_STRVAR(bpy_bmlayeraccess_collection__color_doc, PyDoc_STRVAR(bpy_bmlayeraccess_collection__skin_doc, "Accessor for skin layer.\n\ntype: :class:`BMLayerCollection`" ); +PyDoc_STRVAR(bpy_bmlayeraccess_collection__paint_mask_doc, +"Accessor for paint mask layer.\n\ntype: :class:`BMLayerCollection`" +); #ifdef WITH_FREESTYLE PyDoc_STRVAR(bpy_bmlayeraccess_collection__freestyle_edge_doc, "Accessor for Freestyle edge layer.\n\ntype: :class:`BMLayerCollection`" @@ -196,6 +199,7 @@ static PyGetSetDef bpy_bmlayeraccess_vert_getseters[] = { {(char *)"shape", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__shape_doc, (void *)CD_SHAPEKEY}, {(char *)"bevel_weight", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__bevel_weight_doc, (void *)CD_BWEIGHT}, {(char *)"skin", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__skin_doc, (void *)CD_MVERT_SKIN}, + {(char *)"paint_mask", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__paint_mask_doc, (void *)CD_PAINT_MASK}, {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; @@ -984,6 +988,7 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer) break; } case CD_PROP_FLT: + case CD_PAINT_MASK: { ret = PyFloat_FromDouble(*(float *)value); break; @@ -1061,6 +1066,7 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj break; } case CD_PROP_FLT: + case CD_PAINT_MASK: { float tmp_val = PyFloat_AsDouble(py_value); if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) { -- cgit v1.2.3 From f75c89b3f42ffac51603e6e53459f9d94a8782cc Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 23 Apr 2015 20:43:29 +0200 Subject: Fix T44461: Crash and file corruption after calc_normals_split, calc_tessface execution. This one was nasty, issue comes with temp/nofree CD layers that get 'removed on the fly' from saved mesh CDData. Since mesh struct itself was written before that cleanup, it would still have the old, invalid number of layers. That would lead to a buffer overflow when loading data later (odd you had to do this twice (i.e. have 2 'ghost' layers) to get the crash). New code prevents that by always making a copy of the mesh (we were already doing that mostly anyway, since we were saving without tessfaces), copying (by ref of course) in it cddata, and then writing mesh struct. Makes code a bit more verbose, but... it works! --- source/blender/blenloader/intern/writefile.c | 73 +++++++++++++++++++--------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 12c4f4922dc..39096abf5fa 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1903,26 +1903,35 @@ static void write_grid_paint_mask(WriteData *wd, int count, GridPaintMask *grid_ static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data, int partial_type, int partial_count) { - CustomData data_tmp; int i; - /* This copy will automatically ignore/remove layers set as NO_COPY (and TEMPORARY). */ - CustomData_copy(data, &data_tmp, CD_MASK_EVERYTHING, CD_REFERENCE, count); + int nofree_buff[128]; + int *nofree; /* write external customdata (not for undo) */ - if (data_tmp.external && !wd->current) - CustomData_external_write(&data_tmp, id, CD_MASK_MESH, count, 0); + if (data->external && !wd->current) + CustomData_external_write(data, id, CD_MASK_MESH, count, 0); - for (i = 0; i < data_tmp.totlayer; i++) - data_tmp.layers[i].flag &= ~CD_FLAG_NOFREE; + if (data->totlayer > ARRAY_SIZE(nofree_buff)) { + nofree = MEM_mallocN(sizeof(*nofree) * (size_t)data->totlayer, __func__); + } + else { + nofree = nofree_buff; + } + + for (i = 0; i < data->totlayer; i++) { + nofree[i] = (data->layers[i].flag & CD_FLAG_NOFREE); + data->layers[i].flag &= ~CD_FLAG_NOFREE; + } - writestruct_at_address(wd, DATA, "CustomDataLayer", data_tmp.maxlayer, data->layers, data_tmp.layers); + writestruct(wd, DATA, "CustomDataLayer", data->maxlayer, data->layers); - for (i = 0; i < data_tmp.totlayer; i++) - data_tmp.layers[i].flag |= CD_FLAG_NOFREE; + for (i = 0; i < data->totlayer; i++) { + data->layers[i].flag |= nofree[i]; + } - for (i = 0; i < data_tmp.totlayer; i++) { - CustomDataLayer *layer= &data_tmp.layers[i]; + for (i = 0; i < data->totlayer; i++) { + CustomDataLayer *layer= &data->layers[i]; const char *structname; int structnum, datasize; @@ -1958,10 +1967,12 @@ static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data, } } - if (data_tmp.external) - writestruct_at_address(wd, DATA, "CustomDataExternal", 1, data->external, data_tmp.external); + if (data->external) + writestruct(wd, DATA, "CustomDataExternal", 1, data->external); - CustomData_free(&data_tmp, count); + if (nofree != nofree_buff) { + MEM_freeN(nofree); + } } static void write_meshes(WriteData *wd, ListBase *idbase) @@ -1978,23 +1989,30 @@ static void write_meshes(WriteData *wd, ListBase *idbase) if (mesh->id.us>0 || wd->current) { /* write LibData */ if (!save_for_old_blender) { - -#ifdef USE_BMESH_SAVE_WITHOUT_MFACE /* write a copy of the mesh, don't modify in place because it is * not thread safe for threaded renders that are reading this */ Mesh *old_mesh = mesh; Mesh copy_mesh = *mesh; mesh = ©_mesh; +#ifdef USE_BMESH_SAVE_WITHOUT_MFACE /* cache only - don't write */ mesh->mface = NULL; mesh->totface = 0; memset(&mesh->fdata, 0, sizeof(mesh->fdata)); +#endif /* USE_BMESH_SAVE_WITHOUT_MFACE */ + + /* Bummer! We need to do the copy *before* writing mesh's struct itself, + * because we eliminate NO_COPY & TEMPORARY layers here, which means + * **number of layers (data.totlayer) may be smaller!** + * If we do not do that, we can get crash by buffer-overflow on reading, see T44461. */ + CustomData_copy(&old_mesh->vdata, &mesh->vdata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totvert); + CustomData_copy(&old_mesh->edata, &mesh->edata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totedge); + CustomData_copy(&old_mesh->fdata, &mesh->fdata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totface); + CustomData_copy(&old_mesh->ldata, &mesh->ldata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totloop); + CustomData_copy(&old_mesh->pdata, &mesh->pdata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totpoly); writestruct_at_address(wd, ID_ME, "Mesh", 1, old_mesh, mesh); -#else - writestruct(wd, ID_ME, "Mesh", 1, mesh); -#endif /* USE_BMESH_SAVE_WITHOUT_MFACE */ /* direct data */ if (mesh->id.properties) IDP_WriteProperty(mesh->id.properties, wd); @@ -2010,11 +2028,14 @@ static void write_meshes(WriteData *wd, ListBase *idbase) write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, -1, 0); write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, -1, 0); -#ifdef USE_BMESH_SAVE_WITHOUT_MFACE + CustomData_free(&mesh->vdata, mesh->totvert); + CustomData_free(&mesh->edata, mesh->totedge); + CustomData_free(&mesh->fdata, mesh->totface); + CustomData_free(&mesh->ldata, mesh->totloop); + CustomData_free(&mesh->pdata, mesh->totpoly); + /* restore pointer */ mesh = old_mesh; -#endif /* USE_BMESH_SAVE_WITHOUT_MFACE */ - } else { @@ -2041,6 +2062,10 @@ static void write_meshes(WriteData *wd, ListBase *idbase) BKE_mesh_update_customdata_pointers(mesh, false); + /* See comment above. Note that loop/poly data are ignored here, and face ones are already handled. */ + CustomData_copy(&old_mesh->vdata, &mesh->vdata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totvert); + CustomData_copy(&old_mesh->edata, &mesh->edata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totedge); + writestruct_at_address(wd, ID_ME, "Mesh", 1, old_mesh, mesh); /* direct data */ @@ -2059,6 +2084,8 @@ static void write_meshes(WriteData *wd, ListBase *idbase) write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, -1, 0); #endif + CustomData_free(&mesh->vdata, mesh->totvert); + CustomData_free(&mesh->edata, mesh->totedge); CustomData_free(&mesh->fdata, mesh->totface); /* restore pointer */ -- cgit v1.2.3 From 97b1f22bc3c0648da9e3c2500f969f5451c74a03 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Apr 2015 06:40:59 +1000 Subject: Project Paint: minor optimization comparing angles --- .../editors/sculpt_paint/paint_image_proj.c | 23 +++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index b01d315650f..e100f2701a3 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -272,8 +272,10 @@ typedef struct ProjPaintState { bool do_mask_normal; /* mask out pixels based on their normals */ bool do_mask_cavity; /* mask out pixels based on cavity */ bool do_new_shading_nodes; /* cache BKE_scene_use_new_shading_nodes value */ - float normal_angle; /* what angle to mask at*/ + float normal_angle; /* what angle to mask at */ + float normal_angle__cos; /* cos(normal_angle), faster to compare */ float normal_angle_inner; + float normal_angle_inner__cos; float normal_angle_range; /* difference between normal_angle and normal_angle_inner, for easy access */ bool do_face_sel; /* quick access to (me->editflag & ME_EDIT_PAINT_FACE_SEL) */ @@ -1327,7 +1329,7 @@ static float project_paint_uvpixel_mask( /* calculate mask */ if (ps->do_mask_normal) { MFace *mf = &ps->dm_mface[face_index]; - float no[3], angle; + float no[3], angle_cos; if (mf->flag & ME_SMOOTH) { const short *no1, *no2, *no3; no1 = ps->dm_mvert[mf->v1].no; @@ -1368,7 +1370,7 @@ static float project_paint_uvpixel_mask( /* now we can use the normal as a mask */ if (ps->is_ortho) { - angle = angle_normalized_v3v3(ps->viewDir, no); + angle_cos = dot_v3v3(ps->viewDir, no); } else { /* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */ @@ -1390,14 +1392,14 @@ static float project_paint_uvpixel_mask( viewDirPersp[2] = (ps->viewPos[2] - (w[0] * co1[2] + w[1] * co2[2] + w[2] * co3[2])); normalize_v3(viewDirPersp); - angle = angle_normalized_v3v3(viewDirPersp, no); + angle_cos = dot_v3v3(viewDirPersp, no); } - if (angle >= ps->normal_angle) { + if (angle_cos <= ps->normal_angle__cos) { return 0.0f; /* outsize the normal limit*/ } - else if (angle > ps->normal_angle_inner) { - mask *= (ps->normal_angle - angle) / ps->normal_angle_range; + else if (angle_cos < ps->normal_angle_inner__cos) { + mask *= (ps->normal_angle - acosf(angle_cos)) / ps->normal_angle_range; } /* otherwise no mask normal is needed, were within the limit */ } @@ -3339,14 +3341,14 @@ static void proj_paint_state_vert_flags_init(ProjPaintState *ps) normal_short_to_float_v3(no, mv->no); if (ps->is_ortho) { - if (angle_normalized_v3v3(ps->viewDir, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */ + if (dot_v3v3(ps->viewDir, no) <= ps->normal_angle__cos) { /* 1 vert of this face is towards us */ ps->vertFlags[a] |= PROJ_VERT_CULL; } } else { sub_v3_v3v3(viewDirPersp, ps->viewPos, mv->co); normalize_v3(viewDirPersp); - if (angle_normalized_v3v3(viewDirPersp, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */ + if (dot_v3v3(viewDirPersp, no) <= ps->normal_angle__cos) { /* 1 vert of this face is towards us */ ps->vertFlags[a] |= PROJ_VERT_CULL; } } @@ -5001,6 +5003,9 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int if (ps->normal_angle_range <= 0.0f) ps->do_mask_normal = false; /* no need to do blending */ + ps->normal_angle__cos = cosf(ps->normal_angle); + ps->normal_angle_inner__cos = cosf(ps->normal_angle_inner); + ps->dither = settings->imapaint.dither; return; -- cgit v1.2.3 From dc734da46e65cd3fdb0bb4fe586672799f3e5d11 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Apr 2015 07:08:07 +1000 Subject: Cleanup: casts, correct debug ifdefs --- .../editors/sculpt_paint/paint_image_proj.c | 52 +++++++++++++--------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index e100f2701a3..c5be259a58b 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -134,6 +134,8 @@ BLI_INLINE unsigned char f_to_char(const float val) //#define PROJ_DEBUG_PRINT_CLIP 1 #define PROJ_DEBUG_WINCLIP 1 + +#ifndef PROJ_DEBUG_NOSEAMBLEED /* projectFaceSeamFlags options */ //#define PROJ_FACE_IGNORE (1<<0) /* When the face is hidden, backfacing or occluded */ //#define PROJ_FACE_INIT (1<<1) /* When we have initialized the faces data */ @@ -151,6 +153,13 @@ BLI_INLINE unsigned char f_to_char(const float val) #define PROJ_FACE_WINDING_INIT 1 #define PROJ_FACE_WINDING_CW 2 +/* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams + * as this number approaches 1.0f the likelihood increases of float precision errors where + * it is occluded by an adjacent face */ +#define PROJ_FACE_SCALE_SEAM 0.99f +#endif /* PROJ_DEBUG_NOSEAMBLEED */ + + #define PROJ_SRC_VIEW 1 #define PROJ_SRC_IMAGE_CAM 2 #define PROJ_SRC_IMAGE_VIEW 3 @@ -159,12 +168,6 @@ BLI_INLINE unsigned char f_to_char(const float val) #define PROJ_VIEW_DATA_ID "view_data" #define PROJ_VIEW_DATA_SIZE (4 * 4 + 4 * 4 + 3) /* viewmat + winmat + clipsta + clipend + is_ortho */ - -/* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams - * as this number approaches 1.0f the likelihood increases of float precision errors where - * it is occluded by an adjacent face */ -#define PROJ_FACE_SCALE_SEAM 0.99f - #define PROJ_BUCKET_NULL 0 #define PROJ_BUCKET_INIT (1 << 0) // #define PROJ_BUCKET_CLONE_INIT (1<<1) @@ -476,7 +479,9 @@ static float VecZDepthPersp( /* Return the top-most face index that the screen space coord 'pt' touches (or -1) */ -static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], float w[3], int *side) +static int project_paint_PickFace( + const ProjPaintState *ps, const float pt[2], + float w[3], int *r_side) { LinkNode *node; float w_tmp[3]; @@ -533,7 +538,7 @@ static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], f } } - *side = best_side; + *r_side = best_side; return best_face_index; /* will be -1 or a valid face */ } @@ -1230,22 +1235,22 @@ static void screen_px_from_persp( static void project_face_pixel( const MTFace *tf_other, ImBuf *ibuf_other, const float w[3], - int side, unsigned char rgba_ub[4], float rgba_f[4]) + bool side, unsigned char rgba_ub[4], float rgba_f[4]) { const float *uvCo1, *uvCo2, *uvCo3; float uv_other[2], x, y; - uvCo1 = (float *)tf_other->uv[0]; + uvCo1 = tf_other->uv[0]; if (side == 1) { - uvCo2 = (float *)tf_other->uv[2]; - uvCo3 = (float *)tf_other->uv[3]; + uvCo2 = tf_other->uv[2]; + uvCo3 = tf_other->uv[3]; } else { - uvCo2 = (float *)tf_other->uv[1]; - uvCo3 = (float *)tf_other->uv[2]; + uvCo2 = tf_other->uv[1]; + uvCo3 = tf_other->uv[2]; } - interp_v2_v2v2v2(uv_other, uvCo1, uvCo2, uvCo3, (float *)w); + interp_v2_v2v2v2(uv_other, uvCo1, uvCo2, uvCo3, w); /* use */ uvco_to_wrapped_pxco(uv_other, ibuf_other->x, ibuf_other->y, &x, &y); @@ -1264,7 +1269,7 @@ static void project_face_pixel( static float project_paint_uvpixel_mask( const ProjPaintState *ps, const int face_index, - const int side, + const bool side, const float w[3]) { float mask; @@ -1472,7 +1477,7 @@ static ProjPixel *project_paint_uvpixel_init( const int face_index, const float pixelScreenCo[4], const float world_spaceCo[3], - const int side, + const bool side, const float w[3]) { ProjPixel *projPixel; @@ -1593,7 +1598,7 @@ static ProjPixel *project_paint_uvpixel_init( } else { float co[2]; - sub_v2_v2v2(co, projPixel->projCoSS, (float *)ps->cloneOffset); + sub_v2_v2v2(co, projPixel->projCoSS, ps->cloneOffset); /* no need to initialize the bucket, we're only checking buckets faces and for this * the faces are already initialized in project_paint_delayed_face_init(...) */ @@ -2406,7 +2411,7 @@ static bool IsectPoly2Df(const float pt[2], float uv[][2], const int tot) static bool IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot) { int i; - int side = (line_point_side_v2(uv[tot - 1], uv[0], pt) > 0.0f); + bool side = (line_point_side_v2(uv[tot - 1], uv[0], pt) > 0.0f); for (i = 1; i < tot; i++) { if ((line_point_side_v2(uv[i - 1], uv[i], pt) > 0.0f) != side) @@ -2450,7 +2455,7 @@ static void project_paint_face_init( float mask; float uv[2]; /* Image floating point UV - same as x, y but from 0.0-1.0 */ - int side; + bool side; float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */ float *vCo[4]; /* vertex screenspace coords */ @@ -2853,6 +2858,8 @@ static void project_paint_face_init( } } } +#else + UNUSED_VARS(vCo, threaded); #endif // PROJ_DEBUG_NOSEAMBLEED } @@ -3236,6 +3243,8 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di CLAMP(ps->screenMin[1], (float)(-diameter), (float)(ps->winy + diameter)); CLAMP(ps->screenMax[1], (float)(-diameter), (float)(ps->winy + diameter)); +#else + UNUSED_VARS(diameter); #endif } else if (ps->source != PROJ_SRC_VIEW_FILL) { /* re-projection, use bounds */ @@ -4820,7 +4829,8 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po /* calculate pivot for rotation around seletion if needed */ if (U.uiflag & USER_ORBIT_SELECTION) { float w[3]; - int side, index; + int index; + int side; index = project_paint_PickFace(ps, pos, w, &side); -- cgit v1.2.3 From 1076adb4587c5fd61258dcb7c79fbfef36b74539 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 23 Apr 2015 18:16:33 -0300 Subject: OpenEXR: RenderResult should always have a RenderView --- source/blender/imbuf/intern/openexr/openexr_api.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index f3b89f26703..58c5be8b110 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -1235,9 +1235,15 @@ void IMB_exr_multilayer_convert(void *handle, void *base, ExrLayer *lay; ExrPass *pass; - /* add views to RenderResult */ - for (StringVector::const_iterator i = data->multiView->begin(); i != data->multiView->end(); ++i) { - addview(base, (*i).c_str()); + /* RenderResult needs at least one RenderView */ + if (data->multiView->size() == 0) { + addview(base, ""); + } + else { + /* add views to RenderResult */ + for (StringVector::const_iterator i = data->multiView->begin(); i != data->multiView->end(); ++i) { + addview(base, (*i).c_str()); + } } if (BLI_listbase_is_empty(&data->layers)) { -- cgit v1.2.3 From 0217e6517f56b85e0cb628a3799ad8e21fe36345 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Apr 2015 07:31:51 +1000 Subject: Cleanup: minor edits --- .../editors/sculpt_paint/paint_image_proj.c | 33 ++++++++++++++-------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index c5be259a58b..e8a0b6f384e 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -193,7 +193,7 @@ typedef struct ProjPaintImage { unsigned short **maskRect; /* the mask accumulation must happen on canvas, not on space screen bucket. * Here we store the mask rectangle */ bool **valid; /* store flag to enforce validation of undo rectangle */ - int touch; + bool touch; } ProjPaintImage; /* Main projection painting struct passed to all projection painting functions */ @@ -725,7 +725,7 @@ static bool project_bucket_point_occluded( int face_index; int isect_ret; float w[3]; /* not needed when clipping */ - const short do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0; + const bool do_clip = ps->rv3d ? (ps->rv3d->rflag & RV3D_CLIPPING) != 0 : 0; /* we could return 0 for 1 face buckets, as long as this function assumes * that the point its testing is only every originated from an existing face */ @@ -1983,7 +1983,10 @@ static float angle_2d_clockwise(const float p1[2], const float p2[2], const floa #define ISECT_ALL4 ((1 << 4) - 1) /* limit must be a fraction over 1.0f */ -static bool IsectPT2Df_limit(float pt[2], float v1[2], float v2[2], float v3[2], float limit) +static bool IsectPT2Df_limit( + const float pt[2], + const float v1[2], const float v2[2], const float v3[2], + const float limit) { return ((area_tri_v2(pt, v1, v2) + area_tri_v2(pt, v2, v3) + @@ -2052,7 +2055,7 @@ static bool line_rect_clip( static void project_bucket_clip_face( const bool is_ortho, const rctf *bucket_bounds, - float *v1coSS, float *v2coSS, float *v3coSS, + const float *v1coSS, const float *v2coSS, const float *v3coSS, const float *uv1co, const float *uv2co, const float *uv3co, float bucket_bounds_uv[8][2], int *tot, bool cull) @@ -2200,7 +2203,7 @@ static void project_bucket_clip_face( float cent[2] = {0.0f, 0.0f}; /*float up[2] = {0.0f, 1.0f};*/ int i; - short doubles; + bool doubles; (*tot) = 0; @@ -2430,7 +2433,8 @@ static bool IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot static void project_paint_face_init( const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, - const rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf, const short clamp_u, const short clamp_v) + const rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf, + const bool clamp_u, const bool clamp_v) { /* Projection vars, to get the 3D locations into screen space */ MemArena *arena = ps->arena_mt[thread_index]; @@ -2456,7 +2460,7 @@ static void project_paint_face_init( float uv[2]; /* Image floating point UV - same as x, y but from 0.0-1.0 */ bool side; - float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */ + const float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */ float *vCo[4]; /* vertex screenspace coords */ @@ -2545,7 +2549,7 @@ static void project_paint_face_init( v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, uv_clip, &uv_clip_tot, - ps->do_backfacecull || ps->do_occlude); + do_backfacecull || ps->do_occlude); /* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */ #if 0 @@ -2911,7 +2915,10 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index ima = ps->projImages[0].ima; for (node = ps->bucketFaces[bucket_index]; node; node = node->next) { - project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf, &tmpibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V); + project_paint_face_init( + ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, + bucket_bounds, ibuf, &tmpibuf, + (ima->tpageflag & IMA_CLAMP_U) != 0, (ima->tpageflag & IMA_CLAMP_V) != 0); } } else { @@ -2935,7 +2942,10 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index } /* context switching done */ - project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf, &tmpibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V); + project_paint_face_init( + ps, thread_index, bucket_index, face_index, image_index, + bucket_bounds, ibuf, &tmpibuf, + (ima->tpageflag & IMA_CLAMP_U) != 0, (ima->tpageflag & IMA_CLAMP_V) != 0); } } @@ -4425,7 +4435,8 @@ static void *do_projectpaint_thread(void *ph_v) const float brush_radius = ps->brush_size; const float brush_radius_sq = brush_radius * brush_radius; /* avoid a square root with every dist comparison */ - short lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? 0 : brush->flag & BRUSH_LOCK_ALPHA; + const bool lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? + 0 : (brush->flag & BRUSH_LOCK_ALPHA) != 0; LinkNode *smearPixels = NULL; LinkNode *smearPixels_f = NULL; -- cgit v1.2.3 From efe41ae7fd1b5b0161678fe7edbd8620a0687035 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 23 Apr 2015 19:01:49 -0300 Subject: Multiview: Quadbuffer (time sequential) working [debug builds only] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I'll enable this mode in Release builds once I figure out how to best handle opening files that are saved with the quadbuffer mode. In fact I think no display mode should be saved/read from a file. Tested in Linux with NVidia 3D Vision and NVidia 3D Vision Pro with NVidia Quadro FX 580 and Quadro FX 4600. (kudos for the Visgraf Lab at IMPA, for having me around with all those gadgets ;) Thanks for Cédric Paille (cedricp) for the code snippets and tests - T44327 --- source/blender/windowmanager/intern/wm_stereo.c | 26 ++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 328223645bc..b2cd1f03bc6 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -363,8 +363,7 @@ static bool wm_stereo3d_is_fullscreen_required(eStereoDisplayMode stereo_display { return ELEM(stereo_display, S3D_DISPLAY_SIDEBYSIDE, - S3D_DISPLAY_TOPBOTTOM, - S3D_DISPLAY_PAGEFLIP); + S3D_DISPLAY_TOPBOTTOM); } bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check) @@ -463,24 +462,25 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) /* pageflip requires a new window to be created with the proper OS flags */ if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { - if (wm_stereo3d_quadbuffer_supported() == false) { - BKE_report(op->reports, RPT_ERROR, "Quad-buffer not supported by the system"); - win->stereo3d_format->display_mode = display_mode; - return OPERATOR_CANCELLED; - } if (wm_window_duplicate_exec(C, op) == OPERATOR_FINISHED) { - wm_window_close(C, wm, win); - win = wm->windows.last; + if (wm_stereo3d_quadbuffer_supported()) { + wm_window_close(C, wm, win); + BKE_report(op->reports, RPT_INFO, "Quad-buffer window successfully created"); + } + else { + wmWindow *win_new = wm->windows.last; + wm_window_close(C, wm, win_new); + win->stereo3d_format->display_mode = display_mode; + BKE_report(op->reports, RPT_ERROR, "Quad-buffer not supported by the system"); + } } else { BKE_report(op->reports, RPT_ERROR, - "Fail to create a window compatible with time sequential (page-flip) display method"); + "Fail to create a window compatible with the time sequential display method"); win->stereo3d_format->display_mode = display_mode; - return OPERATOR_CANCELLED; } } - - if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) { + else if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) { if (!is_fullscreen) { BKE_report(op->reports, RPT_INFO, "Stereo 3D Mode requires the window to be fullscreen"); } -- cgit v1.2.3 From f829f556b430050ff8e87e7f287a468e94cd7e77 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Apr 2015 11:03:37 +1000 Subject: Fix project painting on a negative scaled object --- .../editors/sculpt_paint/paint_image_proj.c | 24 ++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index e8a0b6f384e..fcbe613a029 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -283,6 +283,7 @@ typedef struct ProjPaintState { bool do_face_sel; /* quick access to (me->editflag & ME_EDIT_PAINT_FACE_SEL) */ bool is_ortho; + bool is_flip_object; /* the object is negative scaled */ bool do_masking; /* use masking during painting. Some operations such as airbrush may disable */ bool is_texbrush; /* only to avoid running */ bool is_maskbrush; /* mask brush is applied before masking */ @@ -1373,6 +1374,10 @@ static float project_paint_uvpixel_mask( #endif } + if (UNLIKELY(ps->is_flip_object)) { + negate_v3(no); + } + /* now we can use the normal as a mask */ if (ps->is_ortho) { angle_cos = dot_v3v3(ps->viewDir, no); @@ -2053,7 +2058,7 @@ static bool line_rect_clip( static void project_bucket_clip_face( - const bool is_ortho, + const bool is_ortho, const bool is_flip_object, const rctf *bucket_bounds, const float *v1coSS, const float *v2coSS, const float *v3coSS, const float *uv1co, const float *uv2co, const float *uv3co, @@ -2081,7 +2086,8 @@ static void project_bucket_clip_face( inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v3coSS) << 2; if (inside_bucket_flag == ISECT_ALL3) { - flip = ((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != + /* is_flip_object is used here because we use the face winding */ + flip = (((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != is_flip_object) != (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f)); /* all screenspace points are inside the bucket bounding box, @@ -2484,6 +2490,7 @@ static void project_paint_face_init( float uv_clip[8][2]; int uv_clip_tot; const bool is_ortho = ps->is_ortho; + const bool is_flip_object = ps->is_flip_object; const bool do_backfacecull = ps->do_backfacecull; const bool do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0; @@ -2545,7 +2552,8 @@ static void project_paint_face_init( /* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/ project_bucket_clip_face( - is_ortho, bucket_bounds, + is_ortho, is_flip_object, + bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, uv_clip, &uv_clip_tot, @@ -3183,6 +3191,10 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps) mul_m3_v3(mat, ps->viewDir); normalize_v3(ps->viewDir); + if (UNLIKELY(ps->is_flip_object)) { + negate_v3(ps->viewDir); + } + /* viewPos - object relative */ copy_v3_v3(ps->viewPos, viewinv[3]); copy_m3_m4(mat, ps->ob->imat); @@ -3358,6 +3370,9 @@ static void proj_paint_state_vert_flags_init(ProjPaintState *ps) for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++) { normal_short_to_float_v3(no, mv->no); + if (UNLIKELY(ps->is_flip_object)) { + negate_v3(no); + } if (ps->is_ortho) { if (dot_v3v3(ps->viewDir, no) <= ps->normal_angle__cos) { /* 1 vert of this face is towards us */ @@ -3649,7 +3664,7 @@ static bool project_paint_backface_cull( } } else { - if (line_point_side_v2(coSS->v1, coSS->v2, coSS->v3) < 0.0f) { + if ((line_point_side_v2(coSS->v1, coSS->v2, coSS->v3) < 0.0f) != ps->is_flip_object) { return true; } @@ -3813,6 +3828,7 @@ static void project_paint_begin(ProjPaintState *ps) ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat); /* faster clipping lookups */ ps->do_face_sel = ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) != 0); + ps->is_flip_object = (ps->ob->transflag & OB_NEG_SCALE) != 0; /* paint onto the derived mesh */ if (!proj_paint_state_dm_init(ps)) { -- cgit v1.2.3 From bdf6393c98cf87d1e67e6b664037a00383806ffe Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Apr 2015 11:37:48 +1000 Subject: Math Lib: pow_i for int power-of --- source/blender/blenlib/BLI_math_base.h | 1 + source/blender/blenlib/intern/math_base.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index ae2b6a4da9f..79a2d57c966 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -214,6 +214,7 @@ MINLINE int iroundf(float a); MINLINE int divide_round_i(int a, int b); MINLINE int mod_i(int i, int n); +int pow_i(int base, int exp); double double_round(double x, int ndigits); #ifdef BLI_MATH_GCC_WARN_PRAGMA diff --git a/source/blender/blenlib/intern/math_base.c b/source/blender/blenlib/intern/math_base.c index cddfde371f5..0a1e9e8a8a1 100644 --- a/source/blender/blenlib/intern/math_base.c +++ b/source/blender/blenlib/intern/math_base.c @@ -31,6 +31,21 @@ #include "BLI_strict_flags.h" +int pow_i(int base, int exp) +{ + int result = 1; + BLI_assert(exp >= 0); + while (exp) { + if (exp & 1) { + result *= base; + } + exp >>= 1; + base *= base; + } + + return result; +} + /* from python 3.1 floatobject.c * ndigits must be between 0 and 21 */ double double_round(double x, int ndigits) -- cgit v1.2.3 From 9576d03f50fdc082aa0df91bb021a317b5c93090 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Apr 2015 19:11:02 +1000 Subject: CMake: add -Wformat-signedness --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index cd37aa17468..bdaefb0d590 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2524,6 +2524,7 @@ if(CMAKE_COMPILER_IS_GNUCC) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_MISSING_INCLUDE_DIRS -Wmissing-include-dirs) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_TYPE_LIMITS -Wtype-limits) + ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_FORMAT_SIGN -Wformat-signedness) # gcc 4.2 gives annoying warnings on every file with this if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3") @@ -2560,6 +2561,7 @@ if(CMAKE_COMPILER_IS_GNUCC) ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNUSED_PARAMETER -Wunused-parameter) ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_WRITE_STRINGS -Wwrite-strings) ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNDEF -Wundef) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_FORMAT_SIGN -Wformat-signedness) # gcc 4.2 gives annoying warnings on every file with this if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3") -- cgit v1.2.3 From c884ac28a7bb3fd69b29738467e7bba26b977f7e Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 24 Apr 2015 11:35:49 +0200 Subject: 3D Textures: If we fail allocating a proxy texture don't fail, instead create a smaller nearest filtered image to display in its place. This can make viewing slow (it's an extra O^3 operation), but this will probably help us render the tornado in 3D viewport in gooseberry and still actually see something - despite the rendering taking longer. I've added a debug print so we can know when this happens. --- source/blender/gpu/intern/gpu_extensions.c | 84 ++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 22 deletions(-) diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 9e361a49db3..b095eab6952 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -560,8 +560,8 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f GPUTexture *tex; GLenum type, format, internalformat; void *pixels = NULL; - const float vfBorderColor[4] = {0.0f, 0.0f, 0.0f, 0.0f}; int r_width; + bool rescale = false; if (!GLEW_VERSION_1_2) return NULL; @@ -608,13 +608,20 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width); - if (r_width == 0) { - fprintf(stderr, "OpenGL cannot handle a 3D texture of this size\n"); - glBindTexture(tex->target, 0); - GPU_texture_free(tex); - return NULL; + while (r_width == 0) { + rescale = true; + tex->w /= 2; + tex->h /= 2; + tex->depth /= 2; + glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL); + glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width); } + /* really unlikely to happen but keep this just in case */ + tex->w = max_ii(tex->w, 1); + tex->h = max_ii(tex->h, 1); + tex->depth = max_ii(tex->depth, 1); + #if 0 if (fpixels) pixels = GPU_texture_convert_pixels(w*h*depth, fpixels); @@ -622,32 +629,65 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D"); - if (fpixels) { - if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) { - /* clear first to avoid unitialized pixels */ - float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero"); - glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL); - glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, GL_INTENSITY, GL_FLOAT, zero); - glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels); - MEM_freeN(zero); - } - else { - glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels); + /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it + * for gooseberry */ + if (rescale && fpixels) { + unsigned int i, j, k; + unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth; + float *tex3d = MEM_mallocN(channels * sizeof(float)*tex->w*tex->h*tex->depth, "tex3d"); + + GPU_print_error_debug("You need to scale a 3D texture, feel the pain!"); + + for (k = 0; k < tex->depth; k++) { + for (j = 0; j < tex->h; j++) { + for (i = 0; i < tex->w; i++) { + /* obviously doing nearest filtering here, it's going to be slow in any case, let's not make it worse */ + float xb = i * xf; + float yb = j * yf; + float zb = k * zf; + unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j; + unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb); + + if (channels == 4) { + tex3d[offset * 4] = fpixels[offset_orig * 4]; + tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1]; + tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2]; + tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3]; + } + else + tex3d[offset] = fpixels[offset_orig]; + } + } } - GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D"); + glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d); + + MEM_freeN(tex3d); + } + else { + if (fpixels) { + if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) { + /* clear first to avoid unitialized pixels */ + float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero"); + glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL); + glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, GL_INTENSITY, GL_FLOAT, zero); + glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels); + MEM_freeN(zero); + } + else { + glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels); + } + + GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D"); + } } - glTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, vfBorderColor); - GPU_ASSERT_NO_GL_ERRORS("3D GL_TEXTURE_BORDER_COLOR"); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - GPU_ASSERT_NO_GL_ERRORS("3D GL_LINEAR"); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - GPU_ASSERT_NO_GL_ERRORS("3D GL_CLAMP_TO_BORDER"); if (pixels) MEM_freeN(pixels); -- cgit v1.2.3 From 546031b6944cd517d518b7ede5fca489c44c3d29 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Fri, 24 Apr 2015 11:56:58 +0200 Subject: BGE : fix bugs with physics collision mask/group Currently there are bugs with physics objects in inactive layers, character and softbody. I added a function in CcdPhysicsEnvironement to know if a physics controller is currently active and for soft body I added the correct function in UpdateCcdPhysicsController to re-add a softbody in the dynamics world. The bug was introduced in D1243 commit 3d55859 Reviewers: hg1, scorpion81, lordloki, moguri, agoose77, sergof Reviewed By: sergof Subscribers: youle, moguri Differential Revision: https://developer.blender.org/D1253 --- source/gameengine/Ketsji/KX_GameObject.h | 7 +++++++ source/gameengine/Physics/Bullet/CcdPhysicsController.cpp | 14 +++++++++----- source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp | 9 +++++++++ source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h | 2 ++ 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 54bb6ee2605..73dcae5a1a8 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -517,7 +517,14 @@ public: */ void ActivateGraphicController(bool recurse); + /** Set the object's collison group + * \param filter The group bitfield + */ void SetUserCollisionGroup(unsigned short filter); + + /** Set the object's collison mask + * \param filter The mask bitfield + */ void SetUserCollisionMask(unsigned short mask); unsigned short GetUserCollisionGroup(); unsigned short GetUserCollisionMask(); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index b2b8f30a706..0a71c0a7aac 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -123,10 +123,8 @@ bool CleanPairCallback::processOverlap(btBroadphasePair &pair) m_pairCache->cleanOverlappingPair(pair, m_dispatcher); CcdPhysicsController *ctrl0 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy0->m_clientObject)->getUserPointer()); CcdPhysicsController *ctrl1 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy1->m_clientObject)->getUserPointer()); - if (ctrl0 && ctrl1) { - ctrl0->GetRigidBody()->activate(true); - ctrl1->GetRigidBody()->activate(true); - } + ctrl0->GetCollisionObject()->activate(false); + ctrl1->GetCollisionObject()->activate(false); } return false; } @@ -1097,6 +1095,10 @@ void CcdPhysicsController::ResolveCombinedVelocities(float linvelX,float linvel void CcdPhysicsController::RefreshCollisions() { + // the object is in an inactive layer so it's useless to update it and can cause problems + if (!GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this)) + return; + btSoftRigidDynamicsWorld *dw = GetPhysicsEnvironment()->GetDynamicsWorld(); btBroadphaseProxy *proxy = m_object->getBroadphaseHandle(); btDispatcher *dispatcher = dw->getDispatcher(); @@ -1104,8 +1106,10 @@ void CcdPhysicsController::RefreshCollisions() CleanPairCallback cleanPairs(proxy, pairCache, dispatcher); pairCache->processAllOverlappingPairs(&cleanPairs, dispatcher); + // Forcibly recreate the physics object - GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, m_cci.m_mass, m_cci.m_collisionFlags, m_cci.m_collisionFilterGroup, m_cci.m_collisionFilterMask); + btBroadphaseProxy* handle = m_object->getBroadphaseHandle(); + GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, GetMass(), m_object->getCollisionFlags(), handle->m_collisionFilterGroup, handle->m_collisionFilterMask); } void CcdPhysicsController::SuspendDynamics(bool ghost) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 186abdfe598..0ecb79d91ea 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -569,6 +569,7 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr // this function is used when the collisionning group of a controller is changed // remove and add the collistioning object btRigidBody* body = ctrl->GetRigidBody(); + btSoftBody *softBody = ctrl->GetSoftBody(); btCollisionObject* obj = ctrl->GetCollisionObject(); if (obj) { @@ -582,6 +583,9 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr body->setMassProps(newMass, inertia); m_dynamicsWorld->addRigidBody(body, newCollisionGroup, newCollisionMask); } + else if (softBody) { + m_dynamicsWorld->addSoftBody(softBody); + } else { m_dynamicsWorld->addCollisionObject(obj, newCollisionGroup, newCollisionMask); } @@ -643,6 +647,11 @@ void CcdPhysicsEnvironment::RefreshCcdPhysicsController(CcdPhysicsController* ct } } +bool CcdPhysicsEnvironment::IsActiveCcdPhysicsController(CcdPhysicsController *ctrl) +{ + return (m_controllers.find(ctrl) != m_controllers.end()); +} + void CcdPhysicsEnvironment::AddCcdGraphicController(CcdGraphicController* ctrl) { if (m_cullingTree && !ctrl->GetBroadphaseHandle()) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 113db3348ca..3b1fe63db0b 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -227,6 +227,8 @@ protected: void RefreshCcdPhysicsController(CcdPhysicsController* ctrl); + bool IsActiveCcdPhysicsController(CcdPhysicsController *ctrl); + void AddCcdGraphicController(CcdGraphicController* ctrl); void RemoveCcdGraphicController(CcdGraphicController* ctrl); -- cgit v1.2.3 From c2f861453e3eb9e3cbb7840066fc074e015dfc87 Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Fri, 24 Apr 2015 07:27:47 -0400 Subject: Fix T44492: knife tool should cut across a split edge. Added filter condition in visibility check that prevented a "butting-up-against" face from obscuring an edge. --- source/blender/editors/mesh/editmesh_knife.c | 49 +++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index f3745ed72fb..f62fdf70192 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -1319,18 +1319,59 @@ static BMElem *bm_elem_from_knife_edge(KnifeEdge *kfe) return ele_test; } +/* Do edges e1 and e2 go between exactly the same coordinates? */ +static bool coinciding_edges(BMEdge *e1, BMEdge *e2) { + float *co11, *co12, *co21, *co22; + + co11 = e1->v1->co; + co12 = e1->v2->co; + co21 = e2->v1->co; + co22 = e2->v2->co; + if ((equals_v3v3(co11, co21) && equals_v3v3(co12, co22)) || + (equals_v3v3(co11, co22) && equals_v3v3(co12, co21))) + return true; + else + return false; +} + +/* Callback used in point_is_visible to exclude hits on the faces that are the same + * as or contain the hitting element (which is in user_data). + * Also (see T44492) want to exclude hits on faces that butt up to the hitting element + * (e.g., when you double an edge by an edge split). + */ static bool bm_ray_cast_cb_elem_not_in_face_check(BMFace *f, void *user_data) { + bool ans; + BMEdge *e, *e2; + BMIter iter; + switch (((BMElem *)user_data)->head.htype) { case BM_FACE: - return (BMFace *)user_data != f; + ans = (BMFace *)user_data != f; + break; case BM_EDGE: - return !BM_edge_in_face((BMEdge *)user_data, f); + e = (BMEdge *)user_data; + ans = !BM_edge_in_face(e, f); + if (ans) { + /* Is it a boundary edge, coincident with a split edge? */ + if (BM_edge_face_count(e) == 1) { + BM_ITER_ELEM(e2, &iter, f, BM_EDGES_OF_FACE) { + if (coinciding_edges(e, e2)) { + ans = false; + break; + } + } + } + } + break; case BM_VERT: - return !BM_vert_in_face((BMVert *)user_data, f); + ans = !BM_vert_in_face((BMVert *)user_data, f); + break; default: - return true; + ans = true; + break; } + return ans; } -- cgit v1.2.3 From 80d75cb3e45fe10904b887e04481761dc458c876 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 24 Apr 2015 14:11:05 +0200 Subject: Add debug option --debug-gpumem to show GPU memory used in status bar. Only used in ATIs and NVIDIAs. Used extensions are: https://www.opengl.org/registry/specs/ATI/meminfo.txt http://developer.download.nvidia.com/opengl/specs/ If you read the documentation, the numbers are not supposed to be exact and also depend on the time when the call is made. The numbers can also change quite quickly. It's only meant to give a rough measure of what is going on. --- source/blender/blenkernel/BKE_global.h | 3 ++- source/blender/editors/space_info/info_stats.c | 33 +++++++++++++++++++------- source/blender/gpu/GPU_extensions.h | 3 +++ source/blender/gpu/intern/gpu_extensions.c | 28 ++++++++++++++++++++++ source/blender/python/intern/bpy_app.c | 1 + source/creator/creator.c | 1 + 6 files changed, 59 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 935a922b3ec..22ddae88b28 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -126,10 +126,11 @@ enum { G_DEBUG_FREESTYLE = (1 << 7), /* freestyle messages */ G_DEBUG_DEPSGRAPH = (1 << 8), /* depsgraph messages */ G_DEBUG_SIMDATA = (1 << 9), /* sim debug data display */ + G_DEBUG_GPU_MEM = (1 << 10), /* gpu memory in status bar */ }; #define G_DEBUG_ALL (G_DEBUG | G_DEBUG_FFMPEG | G_DEBUG_PYTHON | G_DEBUG_EVENTS | G_DEBUG_WM | G_DEBUG_JOBS | \ - G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH) + G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_GPU_MEM) /* G.fileflags */ diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index a0dfb285a1c..48a39cd79fc 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -56,6 +56,8 @@ #include "ED_info.h" #include "ED_armature.h" +#include "GPU_extensions.h" + #define MAX_INFO_LEN 512 #define MAX_INFO_NUM_LEN 16 @@ -381,6 +383,7 @@ static void stats_string(Scene *scene) Object *ob = (scene->basact) ? scene->basact->object : NULL; uintptr_t mem_in_use, mmap_in_use; char memstr[MAX_INFO_MEM_LEN]; + char gpumemstr[MAX_INFO_MEM_LEN] = ""; char *s; size_t ofs = 0; @@ -416,11 +419,22 @@ static void stats_string(Scene *scene) /* get memory statistics */ - s = memstr; - ofs += BLI_snprintf(s + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" | Mem:%.2fM"), + ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem:%.2fM"), (double)((mem_in_use - mmap_in_use) >> 10) / 1024.0); if (mmap_in_use) - BLI_snprintf(s + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0); + BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0); + + if (GPU_mem_stats_supported()) { + int gpu_free_mem, gpu_tot_memory; + + GPU_mem_stats_get(&gpu_tot_memory, &gpu_free_mem); + + ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem:%.2fM"), (double)((gpu_free_mem)) / 1024.0); + + if (gpu_tot_memory) { + BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%.2fM"), (double)((gpu_tot_memory)) / 1024.0); + } + } s = stats->infostr; ofs = 0; @@ -447,22 +461,23 @@ static void stats_string(Scene *scene) } ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs); + ofs += BLI_strncpy_rlen(s + ofs, gpumemstr, MAX_INFO_LEN - ofs); } else if (ob && (ob->mode & OB_MODE_POSE)) { - ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Bones:%s/%s %s"), - stats_fmt.totbonesel, stats_fmt.totbone, memstr); + ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Bones:%s/%s %s%s"), + stats_fmt.totbonesel, stats_fmt.totbone, memstr, gpumemstr); } else if (stats_is_object_dynamic_topology_sculpt(ob)) { - ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s | Tris:%s"), stats_fmt.totvert, - stats_fmt.tottri); + ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s | Tris:%s%s"), stats_fmt.totvert, + stats_fmt.tottri, gpumemstr); } else { ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, - IFACE_("Verts:%s | Faces:%s | Tris:%s | Objects:%s/%s | Lamps:%s/%s%s"), + IFACE_("Verts:%s | Faces:%s | Tris:%s | Objects:%s/%s | Lamps:%s/%s%s%s"), stats_fmt.totvert, stats_fmt.totface, stats_fmt.tottri, stats_fmt.totobjsel, stats_fmt.totobj, stats_fmt.totlampsel, - stats_fmt.totlamp, memstr); + stats_fmt.totlamp, memstr, gpumemstr); } if (ob) diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 27a4396e5d8..f3927ba960b 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -71,6 +71,9 @@ int GPU_max_texture_size(void); int GPU_color_depth(void); void GPU_get_dfdy_factors(float fac[2]); +bool GPU_mem_stats_supported(void); +void GPU_mem_stats_get(int *totalmem, int *freemem); + void GPU_code_generate_glsl_lib(void); /* GPU Types */ diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index b095eab6952..54e3339eb29 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -2084,6 +2084,34 @@ void GPU_shader_free_builtin_shaders(void) } } +bool GPU_mem_stats_supported(void) +{ + return (GLEW_NVX_gpu_memory_info || (GLEW_ATI_meminfo)) && (G.debug & G_DEBUG_GPU_MEM); +} + + +void GPU_mem_stats_get(int *totalmem, int *freemem) +{ + if (GLEW_NVX_gpu_memory_info) { + /* returned value in Kb */ + glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem); + + glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem); + } + else if (GLEW_ATI_meminfo) { + int stats[4]; + + glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats); + *freemem = stats[0]; + *totalmem = 0; + } + else { + *totalmem = 0; + *freemem = 0; + } +} + + #if 0 /* unused */ /* GPUPixelBuffer */ diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index c8a4971847b..04ab34efeb4 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -287,6 +287,7 @@ static PyGetSetDef bpy_app_getsets[] = { {(char *)"debug_wm", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_WM}, {(char *)"debug_depsgraph", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH}, {(char *)"debug_simdata", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_SIMDATA}, + {(char *)"debug_gpumem", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_GPU_MEM}, {(char *)"debug_value", bpy_app_debug_value_get, bpy_app_debug_value_set, (char *)bpy_app_debug_value_doc, NULL}, {(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL}, diff --git a/source/creator/creator.c b/source/creator/creator.c index 440710f0572..d86ccd657d4 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1491,6 +1491,7 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle) BLI_argsAdd(ba, 1, NULL, "--debug-value", "\n\tSet debug value of on startup\n", set_debug_value, NULL); BLI_argsAdd(ba, 1, NULL, "--debug-jobs", "\n\tEnable time profiling for background jobs.", debug_mode_generic, (void *)G_DEBUG_JOBS); BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph", "\n\tEnable debug messages from dependency graph", debug_mode_generic, (void *)G_DEBUG_DEPSGRAPH); + BLI_argsAdd(ba, 1, NULL, "--debug-gpumem", "\n\tEnable GPU memory stats in status bar", debug_mode_generic, (void *)G_DEBUG_GPU_MEM); BLI_argsAdd(ba, 1, NULL, "--verbose", "\n\tSet logging verbosity level.", set_verbosity, NULL); -- cgit v1.2.3 From 324751259e229112ec31b62846de1af8f2ede104 Mon Sep 17 00:00:00 2001 From: Ines Almeida Date: Fri, 24 Apr 2015 14:08:31 +0100 Subject: correcting typos in python api docs --- doc/python_api/examples/bpy.ops.2.py | 13 ++++++++----- doc/python_api/examples/bpy.props.2.py | 2 +- doc/python_api/examples/bpy.props.py | 2 +- doc/python_api/examples/bpy.types.Menu.2.py | 7 +++---- doc/python_api/examples/bpy.types.Menu.py | 13 ++++++------- source/blender/python/intern/bpy_props.c | 7 ++++--- 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/doc/python_api/examples/bpy.ops.2.py b/doc/python_api/examples/bpy.ops.2.py index cf6df946873..87a2022e526 100644 --- a/doc/python_api/examples/bpy.ops.2.py +++ b/doc/python_api/examples/bpy.ops.2.py @@ -1,16 +1,19 @@ +.. _operator-execution_context: + """ Execution Context ----------------- When calling an operator you may want to pass the execution context. -This determines the context thats given to the operator to run in, and weather -invoke() is called or execute(). +This determines the context that is given for the operator to run in, and whether +invoke() is called or only execute(). -'EXEC_DEFAULT' is used by default but you may want the operator to take user -interaction with 'INVOKE_DEFAULT'. +'EXEC_DEFAULT' is used by default, running only the execute() method, but you may +want the operator to take user interaction with 'INVOKE_DEFAULT' which will also +call invoke() if existing. -The execution context is as a non keyword, string argument in: +The execution context is one of: ('INVOKE_DEFAULT', 'INVOKE_REGION_WIN', 'INVOKE_REGION_CHANNELS', 'INVOKE_REGION_PREVIEW', 'INVOKE_AREA', 'INVOKE_SCREEN', 'EXEC_DEFAULT', 'EXEC_REGION_WIN', 'EXEC_REGION_CHANNELS', 'EXEC_REGION_PREVIEW', 'EXEC_AREA', diff --git a/doc/python_api/examples/bpy.props.2.py b/doc/python_api/examples/bpy.props.2.py index 22fef5dc13a..ec9c838f5f2 100644 --- a/doc/python_api/examples/bpy.props.2.py +++ b/doc/python_api/examples/bpy.props.2.py @@ -3,7 +3,7 @@ PropertyGroup Example +++++++++++++++++++++ PropertyGroups can be used for collecting custom settings into one value -to avoid many indervidual settings mixed in together. +to avoid many individual settings mixed in together. """ import bpy diff --git a/doc/python_api/examples/bpy.props.py b/doc/python_api/examples/bpy.props.py index f6bc55d6824..c199bd9b83a 100644 --- a/doc/python_api/examples/bpy.props.py +++ b/doc/python_api/examples/bpy.props.py @@ -6,7 +6,7 @@ Custom properties can be added to any subclass of an :class:`ID`, :class:`Bone` and :class:`PoseBone`. These properties can be animated, accessed by the user interface and python -like blenders existing properties. +like Blender's existing properties. """ import bpy diff --git a/doc/python_api/examples/bpy.types.Menu.2.py b/doc/python_api/examples/bpy.types.Menu.2.py index c87b10cb6e7..26409f12f45 100644 --- a/doc/python_api/examples/bpy.types.Menu.2.py +++ b/doc/python_api/examples/bpy.types.Menu.2.py @@ -1,12 +1,11 @@ """ Extending Menus +++++++++++++++ -When creating menus for addons you can't reference menus in blenders default +When creating menus for addons you can't reference menus in Blender's default scripts. +Instead, the addon can add menu items to existing menus. -Instead the addon can add menu items to existing menus. - -The function menu_draw acts like Menu.draw +The function menu_draw acts like :class:`Menu.draw`. """ import bpy diff --git a/doc/python_api/examples/bpy.types.Menu.py b/doc/python_api/examples/bpy.types.Menu.py index 4ca18a67b78..e10e44f108e 100644 --- a/doc/python_api/examples/bpy.types.Menu.py +++ b/doc/python_api/examples/bpy.types.Menu.py @@ -1,21 +1,20 @@ """ Basic Menu Example ++++++++++++++++++ -This script is a simple menu, menus differ from panels in that they must +Here is an example of a simple menu. Menus differ from panels in that they must reference from a header, panel or another menu. -Notice the 'CATEGORY_MT_name' :class:`Menu.bl_idname`, this is a naming +Notice the 'CATEGORY_MT_name' in :class:`Menu.bl_idname`, this is a naming convention for menus. .. note:: - Menu subclasses must be registered before referencing them from blender. .. note:: - Menu's have their :class:`Layout.operator_context` initialized as - 'EXEC_REGION_WIN' rather then 'INVOKE_DEFAULT', so if the operator context - needs to initialize inputs from the :class:`Operator.invoke` function - then this needs to be explicitly set. + Menus have their :class:`Layout.operator_context` initialized as + 'EXEC_REGION_WIN' rather than 'INVOKE_DEFAULT' (see :ref:`Execution Context `). + If the operator context needs to initialize inputs from the + :class:`Operator.invoke` function, then this needs to be explicitly set. """ import bpy diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 8370aea4c99..0e9e6b74396 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -2965,9 +2965,10 @@ static struct PyMethodDef props_methods[] = { static struct PyModuleDef props_module = { PyModuleDef_HEAD_INIT, "bpy.props", - "This module defines properties to extend blenders internal data, the result of these functions" - " is used to assign properties to classes registered with blender and can't be used directly.\n" - ".. warning:: All parameters to these functions must be passed as keywords.", + "This module defines properties to extend Blender's internal data. The result of these functions" + " is used to assign properties to classes registered with Blender and can't be used directly.\n" + "\n" + ".. warning:: All parameters to these functions must be passed as keywords.\n", -1, /* multiple "initialization" just copies the module dict. */ props_methods, NULL, NULL, NULL, NULL -- cgit v1.2.3 From fb17a3fb765cf4d4eccb90bd2468dab930071792 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Fri, 24 Apr 2015 11:58:03 -0300 Subject: Multi-View: Time Sequencial (aka pageflip, aka quadbuffer) stereo support TODO: I would be nicer if we could set win at file opening to the current open window, but I'll implement this later. --- source/blender/blenloader/intern/readfile.c | 6 ++++++ source/blender/makesrna/intern/rna_scene.c | 2 -- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9dcb8722c23..060b5e97dde 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5819,6 +5819,12 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) win->lastcursor = 0; win->modalcursor = 0; win->stereo3d_format = newdataadr(fd, win->stereo3d_format); + + /* multiview always fallback to anaglyph at file opening + * otherwise quadbuffer saved files can break Blender */ + if (win->stereo3d_format) { + win->stereo3d_format->display_mode = S3D_DISPLAY_ANAGLYPH; + } } BLI_listbase_clear(&wm->timers); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index a47a777ee7c..f67af39d381 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -373,10 +373,8 @@ EnumPropertyItem stereo3d_display_items[] = { "(anaglyph glasses are required)"}, {S3D_DISPLAY_INTERLACE, "INTERLACE", 0, "Interlace", "Render views for left and right eyes interlaced in a single image (3D-ready monitor is required)"}, -#ifdef DEBUG /* MULTIVIEW_TODO: quadbuffer mode not fully working */ {S3D_DISPLAY_PAGEFLIP, "TIMESEQUENTIAL", 0, "Time Sequential", "Render alternate eyes (also known as page flip, quad buffer support in the graphic card is required)"}, -#endif {S3D_DISPLAY_SIDEBYSIDE, "SIDEBYSIDE", 0, "Side-by-Side", "Render views for left and right eyes side-by-side"}, {S3D_DISPLAY_TOPBOTTOM, "TOPBOTTOM", 0, "Top-Bottom", "Render views for left and right eyes one above another"}, {0, NULL, 0, NULL, NULL} -- cgit v1.2.3 From 27ac96dbae9d6fb166776ff689bae171bd7f095b Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Fri, 24 Apr 2015 12:51:20 -0300 Subject: Multi-View: rolls back to a non quadbuffer friendly window if displaymode changes from pageflip to something else In some cases the graphic card supports quadbuffer, but not the display. In this case it is nice to go back to a window that does not have quadbuffer if you change back to anaglyph, interlace, ... Otherwise you may be stuck with a flickering window --- source/blender/windowmanager/intern/wm_stereo.c | 33 ++++++++++++++++--------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index b2cd1f03bc6..4e13f6bc4d2 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -450,18 +450,28 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); const bool is_fullscreen = WM_window_is_fullscreen(win); - char display_mode = win->stereo3d_format->display_mode; + char prev_display_mode = win->stereo3d_format->display_mode; + Stereo3dData *s3dd = op->customdata; - if (G.background) + if (G.background || s3dd == NULL) return OPERATOR_CANCELLED; - if (op->customdata) { - Stereo3dData *s3dd = op->customdata; - *win->stereo3d_format = s3dd->stereo3d_format; - } + *win->stereo3d_format = s3dd->stereo3d_format; - /* pageflip requires a new window to be created with the proper OS flags */ - if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { + if (prev_display_mode == S3D_DISPLAY_PAGEFLIP && + prev_display_mode != win->stereo3d_format->display_mode) + { + /* in case the hardward supports pageflip but not the display */ + if (wm_window_duplicate_exec(C, op) == OPERATOR_FINISHED) { + wm_window_close(C, wm, win); + } + else { + BKE_report(op->reports, RPT_ERROR, + "Fail to create a window without quadbuffer support, you may experience flickering"); + } + } + else if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { + /* pageflip requires a new window to be created with the proper OS flags */ if (wm_window_duplicate_exec(C, op) == OPERATOR_FINISHED) { if (wm_stereo3d_quadbuffer_supported()) { wm_window_close(C, wm, win); @@ -470,17 +480,18 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) else { wmWindow *win_new = wm->windows.last; wm_window_close(C, wm, win_new); - win->stereo3d_format->display_mode = display_mode; + win->stereo3d_format->display_mode = prev_display_mode; BKE_report(op->reports, RPT_ERROR, "Quad-buffer not supported by the system"); } } else { BKE_report(op->reports, RPT_ERROR, "Fail to create a window compatible with the time sequential display method"); - win->stereo3d_format->display_mode = display_mode; + win->stereo3d_format->display_mode = prev_display_mode; } } - else if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) { + + if (wm_stereo3d_is_fullscreen_required(s3dd->stereo3d_format.display_mode)) { if (!is_fullscreen) { BKE_report(op->reports, RPT_INFO, "Stereo 3D Mode requires the window to be fullscreen"); } -- cgit v1.2.3 From 7e66f0e9d4d6b268a626e265b6dc085f239bf6c7 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Fri, 24 Apr 2015 13:06:04 -0300 Subject: Multi-View: Set Stereo 3D operator support for EXEC calls --- source/blender/windowmanager/intern/wm_stereo.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 4e13f6bc4d2..9178bd97257 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -451,11 +451,18 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) wmWindow *win = CTX_wm_window(C); const bool is_fullscreen = WM_window_is_fullscreen(win); char prev_display_mode = win->stereo3d_format->display_mode; - Stereo3dData *s3dd = op->customdata; + Stereo3dData *s3dd; - if (G.background || s3dd == NULL) + if (G.background) return OPERATOR_CANCELLED; + if (op->customdata == NULL) { + /* no invoke means we need to set the operator properties here */ + wm_stereo3d_set_init(C, op); + wm_stereo3d_set_properties(C, op); + } + + s3dd = op->customdata; *win->stereo3d_format = s3dd->stereo3d_format; if (prev_display_mode == S3D_DISPLAY_PAGEFLIP && @@ -497,9 +504,7 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) } } - if (op->customdata) { - MEM_freeN(op->customdata); - } + MEM_freeN(op->customdata); WM_event_add_notifier(C, NC_WINDOW, NULL); return OPERATOR_FINISHED; -- cgit v1.2.3 From de8e89d4f5f81416cd45d4efdd7c0cb4d412a451 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 24 Apr 2015 20:08:52 +0200 Subject: Fix T44405: Importing keyconfig with changed shortcut in "Screen Global" causes rapid fullscreen toggeling --- source/blender/editors/screen/screen_ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 67c18ac287e..9745d01fc89 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -4252,6 +4252,8 @@ void ED_keymap_screen(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "SCREEN_OT_area_dupli", EVT_ACTIONZONE_AREA, 0, KM_SHIFT, 0); WM_keymap_verify_item(keymap, "SCREEN_OT_area_swap", EVT_ACTIONZONE_AREA, 0, KM_CTRL, 0); WM_keymap_verify_item(keymap, "SCREEN_OT_region_scale", EVT_ACTIONZONE_REGION, 0, 0, 0); + kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", EVT_ACTIONZONE_FULLSCREEN, 0, 0, 0); + RNA_boolean_set(kmi->ptr, "use_hide_panels", true); /* area move after action zones */ WM_keymap_verify_item(keymap, "SCREEN_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0); @@ -4279,8 +4281,6 @@ void ED_keymap_screen(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_SHIFT, 0); kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", F10KEY, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "use_hide_panels", true); - kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", EVT_ACTIONZONE_FULLSCREEN, 0, 0, 0); - RNA_boolean_set(kmi->ptr, "use_hide_panels", true); WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "SCREEN_OT_screencast", F3KEY, KM_PRESS, KM_ALT, 0); -- cgit v1.2.3 From 3bffcc675b3fea221b0b93d1f2055173edd7f75b Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Sat, 25 Apr 2015 01:29:53 +0200 Subject: Fix T42495: Fullscreen area icon glitch Tried a couple of things to trigger an update/redraw for the exact right moment (sending azone update event, timer, delayed redraw, etc) but this seems to work rock solid without being *that* ugly. --- source/blender/editors/include/ED_screen.h | 1 + source/blender/editors/screen/area.c | 37 ++++++++++++++++++++++ source/blender/makesdna/DNA_screen_types.h | 2 ++ .../blender/windowmanager/intern/wm_event_system.c | 5 +++ 4 files changed, 45 insertions(+) diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index b7c261cad6c..5b0b4642644 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -86,6 +86,7 @@ void ED_area_tag_redraw(ScrArea *sa); void ED_area_tag_redraw_regiontype(ScrArea *sa, int type); void ED_area_tag_refresh(ScrArea *sa); void ED_area_do_refresh(struct bContext *C, ScrArea *sa); +void ED_area_azones_update(ScrArea *sa, const int mouse_xy[]); void ED_area_headerprint(ScrArea *sa, const char *str); void ED_area_newspace(struct bContext *C, ScrArea *sa, int type); void ED_area_prevspace(struct bContext *C, ScrArea *sa); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 8844f344a6b..4518aad1a5c 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -151,6 +151,34 @@ void ED_area_do_refresh(bContext *C, ScrArea *sa) sa->do_refresh = false; } +/** + * Action zones are only updated if the mouse is inside of them, but in some cases (currently only fullscreen icon) + * it might be needed to update their properties and redraw if the mouse isn't inside. + */ +void ED_area_azones_update(ScrArea *sa, const int mouse_xy[2]) +{ + AZone *az; + bool changed = false; + + for (az = sa->actionzones.first; az; az = az->next) { + if (az->type == AZONE_FULLSCREEN) { + /* only if mouse is not hovering the azone */ + if (BLI_rcti_isect_pt_v(&az->rect, mouse_xy) == false) { + az->alpha = 0.0f; + changed = true; + + /* can break since currently only this is handled here */ + break; + } + } + } + + if (changed) { + sa->flag &= ~AREA_FLAG_ACTIONZONES_UPDATE; + ED_area_tag_redraw(sa); + } +} + /** * \brief Corner widget use for quitting fullscreen. */ @@ -369,6 +397,11 @@ static void region_draw_azone_tria(AZone *az) glDisable(GL_BLEND); } +static void area_azone_tag_update(ScrArea *sa) +{ + sa->flag |= AREA_FLAG_ACTIONZONES_UPDATE; +} + static void region_draw_azones(ScrArea *sa, ARegion *ar) { AZone *az; @@ -409,6 +442,10 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar) } else if (az->type == AZONE_FULLSCREEN) { area_draw_azone_fullscreen(az->x1, az->y1, az->x2, az->y2, az->alpha); + + if (az->alpha != 0.0f) { + area_azone_tag_update(sa); + } } } } diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 84ac0c5e792..13365adeb58 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -281,6 +281,8 @@ enum { AREA_FLAG_TEMP_TYPE = (1 << 6), /* for temporary fullscreens (file browser, image editor render) that are opened above user set fullscreens */ AREA_FLAG_STACKED_FULLSCREEN = (1 << 7), + /* update action zones (even if the mouse is not intersecting them) */ + AREA_FLAG_ACTIONZONES_UPDATE = (1 << 8), }; #define EDGEWIDTH 1 diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index e79359a078e..a6d5113a03a 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2330,6 +2330,11 @@ void wm_event_do_handlers(bContext *C) break; } + /* update azones if needed - done here because it needs to be independent from redraws */ + if (sa->flag & AREA_FLAG_ACTIONZONES_UPDATE) { + ED_area_azones_update(sa, &event->x); + } + if (wm_event_inside_i(event, &sa->totrct)) { CTX_wm_area_set(C, sa); -- cgit v1.2.3 From 86d3a1f683ccc5905580e2a11222217d227db7de Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 25 Apr 2015 12:29:52 +1000 Subject: Cleanup --- source/blender/editors/include/ED_mesh.h | 2 +- source/blender/editors/mesh/editmesh_knife.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 55a254c7941..ea544135d3b 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -144,7 +144,7 @@ struct BMVert *EDBM_vert_find_nearest( struct ViewContext *vc, float *r_dist); struct BMEdge *EDBM_edge_find_nearest_ex( - struct ViewContext *vc,float *r_dist, + struct ViewContext *vc, float *r_dist, float *r_dist_center, const bool use_select_bias, const bool use_cycle, struct BMEdge **r_eed_zbuf); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index f62fdf70192..df91679b5f0 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -1320,8 +1320,9 @@ static BMElem *bm_elem_from_knife_edge(KnifeEdge *kfe) } /* Do edges e1 and e2 go between exactly the same coordinates? */ -static bool coinciding_edges(BMEdge *e1, BMEdge *e2) { - float *co11, *co12, *co21, *co22; +static bool coinciding_edges(BMEdge *e1, BMEdge *e2) +{ + const float *co11, *co12, *co21, *co22; co11 = e1->v1->co; co12 = e1->v2->co; @@ -1329,9 +1330,12 @@ static bool coinciding_edges(BMEdge *e1, BMEdge *e2) { co22 = e2->v2->co; if ((equals_v3v3(co11, co21) && equals_v3v3(co12, co22)) || (equals_v3v3(co11, co22) && equals_v3v3(co12, co21))) + { return true; - else + } + else { return false; + } } /* Callback used in point_is_visible to exclude hits on the faces that are the same @@ -1354,7 +1358,7 @@ static bool bm_ray_cast_cb_elem_not_in_face_check(BMFace *f, void *user_data) ans = !BM_edge_in_face(e, f); if (ans) { /* Is it a boundary edge, coincident with a split edge? */ - if (BM_edge_face_count(e) == 1) { + if (BM_edge_is_boundary(e)) { BM_ITER_ELEM(e2, &iter, f, BM_EDGES_OF_FACE) { if (coinciding_edges(e, e2)) { ans = false; -- cgit v1.2.3 From 0221a11c9516083eae22fe51bb63be532e47641f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 25 Apr 2015 12:52:51 +1000 Subject: Project Paint: save 8 bytes per pixel (re-align) --- source/blender/editors/sculpt_paint/paint_image_proj.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index fcbe613a029..d75b3f8ea3d 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -332,25 +332,27 @@ typedef union pixelStore { typedef struct ProjPixel { float projCoSS[2]; /* the floating point screen projection of this pixel */ float worldCoSS[3]; + + short x_px, y_px; + + unsigned short image_index; /* if anyone wants to paint onto more than 65535 images they can bite me */ + unsigned char bb_cell_index; + + /* for various reasons we may want to mask out painting onto this pixel */ + unsigned short mask; + /* Only used when the airbrush is disabled. * Store the max mask value to avoid painting over an area with a lower opacity * with an advantage that we can avoid touching the pixel at all, if the * new mask value is lower then mask_accum */ unsigned short *mask_accum; - /* for various reasons we may want to mask out painting onto this pixel */ - unsigned short mask; - - short x_px, y_px; /* horrible hack, store tile valid flag pointer here to re-validate tiles used for anchored and drag-dot strokes */ bool *valid; PixelPointer origColor; PixelStore newColor; PixelPointer pixel; - - short image_index; /* if anyone wants to paint onto more than 32768 images they can bite me */ - unsigned char bb_cell_index; } ProjPixel; typedef struct ProjPixelClone { -- cgit v1.2.3 From a4203814d1f52f475aad6fbe90bdeb2edec19d4a Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Sat, 25 Apr 2015 12:56:24 +1000 Subject: UI: Panel drag-collapse D1233, Adds a way to quickly open/close multiple panels by holding LMB and dragging over the desired panels, Suggested by @maxon The decision if the panels are opened or closed is made based on the first Panel the user drags over. If it is closed, all panels he drags over are opened (including the first one) if it's opened, they get closed (matching existing drag-toggle logic). --- source/blender/editors/interface/interface_panel.c | 219 +++++++++++++++++---- 1 file changed, 185 insertions(+), 34 deletions(-) diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 5aee8e18ba0..239d6f7c493 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -82,6 +82,14 @@ /* only show pin header button for pinned panels */ #define USE_PIN_HIDDEN +/* the state of the mouse position relative to the panel */ +typedef enum uiPanelMouseState { + PANEL_MOUSE_OUTSIDE, /* mouse is not in the panel */ + PANEL_MOUSE_INSIDE_CONTENT, /* mouse is in the actual panel content */ + PANEL_MOUSE_INSIDE_HEADER, /* mouse is in the panel header */ + PANEL_MOUSE_INSIDE_SCALE, /* mouse is inside panel scale widget */ +} uiPanelMouseState; + typedef enum uiHandlePanelState { PANEL_STATE_DRAG, PANEL_STATE_DRAG_SCALE, @@ -1128,6 +1136,158 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel) /******************* region level panel interaction *****************/ +static uiPanelMouseState ui_panel_mouse_state_get(const uiBlock *block, const Panel *pa, const int mx, const int my) +{ + /* open panel */ + if (pa->flag & PNL_CLOSEDX) { + if ((block->rect.xmin <= mx) && (block->rect.xmin + PNL_HEADER >= mx)) { + return PANEL_MOUSE_INSIDE_HEADER; + } + } + /* outside left/right side */ + else if ((block->rect.xmin > mx) || (block->rect.xmax < mx)) { + /* pass */ + } + else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) { + return PANEL_MOUSE_INSIDE_HEADER; + } + /* open panel */ + else if (!(pa->flag & PNL_CLOSEDY)) { + if (pa->control & UI_PNL_SCALE) { + if (block->rect.xmax - PNL_HEADER <= mx) { + if (block->rect.ymin + PNL_HEADER >= my) { + return PANEL_MOUSE_INSIDE_SCALE; + } + } + } + if ((block->rect.xmin <= mx) && (block->rect.xmax >= mx)) { + if ((block->rect.ymin <= my) && (block->rect.ymax + PNL_HEADER >= my)) { + return PANEL_MOUSE_INSIDE_CONTENT; + } + } + } + return PANEL_MOUSE_OUTSIDE; +} + +typedef struct uiPanelDragCollapseHandle { + bool was_first_open; + int xy_init[2]; +} uiPanelDragCollapseHandle; + +static void ui_panel_drag_collapse_handler_remove(bContext *UNUSED(C), void *userdata) +{ + uiPanelDragCollapseHandle *dragcol_data = userdata; + MEM_freeN(dragcol_data); +} + +static void ui_panel_drag_collapse(bContext *C, uiPanelDragCollapseHandle *dragcol_data, const int xy_dst[2]) +{ + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + uiBlock *block; + Panel *pa; + + for (block = ar->uiblocks.first; block; block = block->next) { + float xy_a_block[2] = {UNPACK2(dragcol_data->xy_init)}; + float xy_b_block[2] = {UNPACK2(xy_dst)}; + rctf rect = block->rect; + int oldflag; + const bool is_horizontal = (panel_aligned(sa, ar) == BUT_HORIZONTAL); + + if ((pa = block->panel) == 0 || (pa->type && (pa->type->flag & PNL_NO_HEADER))) { + continue; + } + oldflag = pa->flag; + + /* lock one axis */ + if (is_horizontal) { + xy_b_block[1] = dragcol_data->xy_init[1]; + } + else { + xy_b_block[0] = dragcol_data->xy_init[0]; + } + + /* use cursor coords in block space */ + ui_window_to_block_fl(ar, block, &xy_a_block[0], &xy_a_block[1]); + ui_window_to_block_fl(ar, block, &xy_b_block[0], &xy_b_block[1]); + + /* set up rect to match header size */ + rect.ymin = rect.ymax; + rect.ymax = rect.ymin + PNL_HEADER; + if (pa->flag & PNL_CLOSEDX) { + rect.xmin = rect.xmin; + rect.xmax = rect.xmin + PNL_HEADER; + } + + /* touch all panels between last mouse coord and the current one */ + if (BLI_rctf_isect_segment(&rect, xy_a_block, xy_b_block)) { + /* force panel to close */ + if (dragcol_data->was_first_open == true) { + pa->flag |= (is_horizontal ? PNL_CLOSEDX : PNL_CLOSEDY); + } + /* force panel to open */ + else { + pa->flag &= ~PNL_CLOSED; + } + + /* if pa->flag has changed this means a panel was opened/closed here */ + if (pa->flag != oldflag) { + panel_activate_state(C, pa, PANEL_STATE_ANIMATION); + } + } + } +} + +/** + * Panel drag-collapse (modal handler) + * Clicking and dragging over panels toggles their collapse state based on the panel that was first + * dragged over. If it was open all affected panels incl the initial one are closed and vise versa. + */ +static int ui_panel_drag_collapse_handler(bContext *C, const wmEvent *event, void *userdata) +{ + wmWindow *win = CTX_wm_window(C); + uiPanelDragCollapseHandle *dragcol_data = userdata; + short retval = WM_UI_HANDLER_CONTINUE; + + switch (event->type) { + case MOUSEMOVE: + ui_panel_drag_collapse(C, dragcol_data, &event->x); + + retval = WM_UI_HANDLER_BREAK; + break; + case LEFTMOUSE: + if (event->val == KM_RELEASE) { + /* done! */ + WM_event_remove_ui_handler( + &win->modalhandlers, + ui_panel_drag_collapse_handler, + ui_panel_drag_collapse_handler_remove, + dragcol_data, true); + ui_panel_drag_collapse_handler_remove(C, dragcol_data); + } + /* don't let any left-mouse event fall through! */ + retval = WM_UI_HANDLER_BREAK; + break; + } + + return retval; +} + +static void ui_panel_drag_collapse_handler_add(const bContext *C, const bool was_open) +{ + wmWindow *win = CTX_wm_window(C); + wmEvent *event = win->eventstate; + uiPanelDragCollapseHandle *dragcol_data = MEM_mallocN(sizeof(*dragcol_data), __func__); + + dragcol_data->was_first_open = was_open; + copy_v2_v2_int(dragcol_data->xy_init, &event->x); + + WM_event_add_ui_handler( + C, &win->modalhandlers, + ui_panel_drag_collapse_handler, + ui_panel_drag_collapse_handler_remove, + dragcol_data, false); +} /* this function is supposed to call general window drawing too */ /* also it supposes a block has panel, and isn't a menu */ @@ -1199,15 +1359,27 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in /* snap back up so full panel aligns with screen edge */ if (block->panel->snap & PNL_SNAP_BOTTOM) block->panel->ofsy = 0; + + if (event == LEFTMOUSE) { + ui_panel_drag_collapse_handler_add(C, false); + } } else if (align == BUT_HORIZONTAL) { block->panel->flag |= PNL_CLOSEDX; + + if (event == LEFTMOUSE) { + ui_panel_drag_collapse_handler_add(C, true); + } } else { - /* snap down to bottom screen edge*/ + /* snap down to bottom screen edge */ block->panel->flag |= PNL_CLOSEDY; if (block->panel->snap & PNL_SNAP_BOTTOM) block->panel->ofsy = -block->panel->sizey; + + if (event == LEFTMOUSE) { + ui_panel_drag_collapse_handler_add(C, true); + } } for (pa = ar->panels.first; pa; pa = pa->next) { @@ -1722,8 +1894,8 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) } for (block = ar->uiblocks.last; block; block = block->prev) { - bool inside = false, inside_header = false, inside_scale = false; - + uiPanelMouseState mouse_state; + mx = event->x; my = event->y; ui_window_to_block(ar, block, &mx, &my); @@ -1735,32 +1907,11 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) continue; if (pa->type && pa->type->flag & PNL_NO_HEADER) /* XXX - accessed freed panels when scripts reload, need to fix. */ continue; - - /* clicked at panel header? */ - if (pa->flag & PNL_CLOSEDX) { - if (block->rect.xmin <= mx && block->rect.xmin + PNL_HEADER >= mx) - inside_header = true; - } - else if (block->rect.xmin > mx || block->rect.xmax < mx) { - /* outside left/right side */ - } - else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) { - inside_header = true; - } - else if (!(pa->flag & PNL_CLOSEDY)) { - /* open panel */ - if (pa->control & UI_PNL_SCALE) { - if (block->rect.xmax - PNL_HEADER <= mx) - if (block->rect.ymin + PNL_HEADER >= my) - inside_scale = true; - } - if (block->rect.xmin <= mx && block->rect.xmax >= mx) - if (block->rect.ymin <= my && block->rect.ymax + PNL_HEADER >= my) - inside = true; - } - + + mouse_state = ui_panel_mouse_state_get(block, pa, mx, my); + /* XXX hardcoded key warning */ - if ((inside || inside_header) && event->val == KM_PRESS) { + if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER) && event->val == KM_PRESS) { if (event->type == AKEY && ((event->ctrl + event->oskey + event->shift + event->alt) == 0)) { if (pa->flag & PNL_CLOSEDY) { @@ -1779,13 +1930,13 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) if (ui_but_is_active(ar)) continue; - if (inside || inside_header) { + if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) { if (event->val == KM_PRESS) { /* open close on header */ if (ELEM(event->type, RETKEY, PADENTER)) { - if (inside_header) { + if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { ui_handle_panel_header(C, block, mx, my, RETKEY, event->ctrl, event->shift); retval = WM_UI_HANDLER_BREAK; break; @@ -1795,12 +1946,12 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) /* all inside clicks should return in break - overlapping/float panels */ retval = WM_UI_HANDLER_BREAK; - if (inside_header) { - ui_handle_panel_header(C, block, mx, my, 0, event->ctrl, event->shift); + if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { + ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->shift); retval = WM_UI_HANDLER_BREAK; break; } - else if (inside_scale && !(pa->flag & PNL_CLOSED)) { + else if ((mouse_state == PANEL_MOUSE_INSIDE_SCALE) && !(pa->flag & PNL_CLOSED)) { panel_activate_state(C, pa, PANEL_STATE_DRAG_SCALE); retval = WM_UI_HANDLER_BREAK; break; @@ -1808,7 +1959,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) } else if (event->type == RIGHTMOUSE) { - if (inside_header) { + if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { ui_panel_menu(C, ar, block->panel); retval = WM_UI_HANDLER_BREAK; break; -- cgit v1.2.3 From a7381cca34fb84eac486a5c65469e43895f75d66 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 25 Apr 2015 17:20:59 +1000 Subject: BMesh: simplify BM_face_create_ngon Was doing quite a lot of unnecessary steps. Now construct the sorted verts, edges /w error checking, in a single loop. --- source/blender/bmesh/intern/bmesh_construct.c | 194 ++++++++++---------------- 1 file changed, 75 insertions(+), 119 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index e0348fea636..d64b65e4a01 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -132,155 +132,111 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f, } /** - * \brief Make NGon - * - * Makes an ngon from an unordered list of edges. \a v1 and \a v2 - * must be the verts defining edges[0], - * and define the winding of the new face. - * - * \a edges are not required to be ordered, simply to to form - * a single closed loop as a whole. + * Given an array of edges, + * order them using the winding defined by \a v1 & \a v2 + * into \a edges_sort & \a verts_sort. * - * \note While this function will work fine when the edges - * are already sorted, if the edges are always going to be sorted, - * #BM_face_create should be considered over this function as it - * avoids some unnecessary work. + * All arrays must be \a len long. */ -BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag) +static bool bm_edges_sort_winding( + BMVert *v1, BMVert *v2, + BMEdge **edges, const int len, + BMEdge **edges_sort, BMVert **verts_sort) { - BMEdge **edges_sort = BLI_array_alloca(edges_sort, len); - BMVert **verts_sort = BLI_array_alloca(verts_sort, len + 1); - int esort_index = 0; - int vsort_index = 0; - - BMFace *f = NULL; - BMEdge *e; - BMVert *v, *ev1, *ev2; + BMEdge *e_iter, *e_first; + BMVert *v_iter; int i; - bool is_v1_found, is_reverse; - - /* this code is hideous, yeek. I'll have to think about ways of - * cleaning it up. basically, it now combines the old BM_face_create_ngon - * _and_ the old bmesh_mf functions, so its kindof smashed together - * - joeedh */ - - BLI_assert(len && v1 && v2 && edges && bm); - - /* put edges in correct order */ + /* all flags _must_ be cleared on exit! */ for (i = 0; i < len; i++) { BM_ELEM_API_FLAG_ENABLE(edges[i], _FLAG_MF); + BM_ELEM_API_FLAG_ENABLE(edges[i]->v1, _FLAG_MV); + BM_ELEM_API_FLAG_ENABLE(edges[i]->v2, _FLAG_MV); } - ev1 = edges[0]->v1; - ev2 = edges[0]->v2; - - BLI_assert(ELEM(v1, ev1, ev2) && ELEM(v2, ev1, ev2)); - - if (v1 == ev2) { - /* Swapping here improves performance and consistency of face - * structure in the special case that the edges are already in - * the correct order and winding */ - SWAP(BMVert *, ev1, ev2); - } - - verts_sort[vsort_index++] = ev1; - v = ev2; - e = edges[0]; + /* find first edge */ + v_iter = v1; + e_iter = e_first = v1->e; do { - BMEdge *e2 = e; - - /* vertex array is (len + 1) */ - if (UNLIKELY(vsort_index > len)) { - goto err; /* vertex in loop twice */ + if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF) && + (BM_edge_other_vert(e_iter, v_iter) == v2)) + { + break; } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first); + if (e_iter == e_first) { + goto error; + } - verts_sort[vsort_index++] = v; - edges_sort[esort_index++] = e; - - /* we only flag the verts to check if they are in the face more than once */ - BM_ELEM_API_FLAG_ENABLE(v, _FLAG_MV); - - do { - e2 = bmesh_disk_edge_next(e2, v); - if (e2 != e && BM_ELEM_API_FLAG_TEST(e2, _FLAG_MF)) { - v = BM_edge_other_vert(e2, v); - break; + i = 0; + do { + /* entering loop will always succeed */ + if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF)) { + if (UNLIKELY(BM_ELEM_API_FLAG_TEST(v_iter, _FLAG_MV) == false)) { + /* vert is in loop multiple times */ + goto error; } - } while (e2 != e); - if (UNLIKELY(e2 == e)) { - goto err; /* the edges do not form a closed loop */ - } + BM_ELEM_API_FLAG_DISABLE(e_iter, _FLAG_MF); + edges_sort[i] = e_iter; - e = e2; - } while (e != edges[0]); + BM_ELEM_API_FLAG_DISABLE(v_iter, _FLAG_MV); + verts_sort[i] = v_iter; - if (UNLIKELY(esort_index != len)) { - goto err; /* we didn't use all edges in forming the boundary loop */ - } + i += 1; - /* ok, edges are in correct order, now ensure they are going - * in the correct direction */ - is_v1_found = is_reverse = false; - for (i = 0; i < len; i++) { - if (BM_vert_in_edge(edges_sort[i], v1)) { - /* see if v1 and v2 are in the same edge */ - if (BM_vert_in_edge(edges_sort[i], v2)) { - /* if v1 is shared by the *next* edge, then the winding - * is incorrect */ - if (BM_vert_in_edge(edges_sort[(i + 1) % len], v1)) { - is_reverse = true; - break; + /* walk onto the next vertex */ + v_iter = BM_edge_other_vert(e_iter, v_iter); + if (i == len) { + if (UNLIKELY(v_iter != verts_sort[0])) { + goto error; } + break; } - is_v1_found = true; + e_first = e_iter; } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first); - if ((is_v1_found == false) && BM_vert_in_edge(edges_sort[i], v2)) { - is_reverse = true; - break; - } - } - - if (is_reverse) { - for (i = 0; i < len / 2; i++) { - v = verts_sort[i]; - verts_sort[i] = verts_sort[len - i - 1]; - verts_sort[len - i - 1] = v; - } + if (i == len) { + return true; } +error: for (i = 0; i < len; i++) { - edges_sort[i] = BM_edge_exists(verts_sort[i], verts_sort[(i + 1) % len]); - if (UNLIKELY(edges_sort[i] == NULL)) { - goto err; - } - - /* check if vert is in face more than once. if the flag is disabled. we've already visited */ - if (UNLIKELY(!BM_ELEM_API_FLAG_TEST(verts_sort[i], _FLAG_MV))) { - goto err; - } - BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV); + BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF); + BM_ELEM_API_FLAG_DISABLE(edges[i]->v1, _FLAG_MV); + BM_ELEM_API_FLAG_DISABLE(edges[i]->v2, _FLAG_MV); } - f = BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag); + return false; +} - /* clean up flags */ - for (i = 0; i < len; i++) { - BM_ELEM_API_FLAG_DISABLE(edges_sort[i], _FLAG_MF); - } +/** + * \brief Make NGon + * + * Makes an ngon from an unordered list of edges. + * Verts \a v1 and \a v2 define the winding of the new face. + * + * \a edges are not required to be ordered, simply to to form + * a single closed loop as a whole. + * + * \note While this function will work fine when the edges + * are already sorted, if the edges are always going to be sorted, + * #BM_face_create should be considered over this function as it + * avoids some unnecessary work. + */ +BMFace *BM_face_create_ngon( + BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag) +{ + BMEdge **edges_sort = BLI_array_alloca(edges_sort, len); + BMVert **verts_sort = BLI_array_alloca(verts_sort, len); - return f; + BLI_assert(len && v1 && v2 && edges && bm); -err: - for (i = 0; i < len; i++) { - BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF); - } - for (i = 0; i < vsort_index; i++) { - BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV); + if (bm_edges_sort_winding(v1, v2, edges, len, edges_sort, verts_sort)) { + return BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag); } return NULL; -- cgit v1.2.3 From 89f5a09ab4660cd0d5bdf4b82899549b50ee2f16 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 25 Apr 2015 20:15:20 +1000 Subject: Cleanup: use 8 space indent for multi-line args --- source/blender/blenkernel/intern/modifiers_bmesh.c | 5 +- source/blender/blenkernel/intern/pbvh_bmesh.c | 66 ++++++----- source/blender/blenkernel/intern/pbvh_intern.h | 7 +- source/blender/bmesh/intern/bmesh_construct.c | 61 +++++----- source/blender/bmesh/intern/bmesh_construct.h | 32 +++--- source/blender/bmesh/intern/bmesh_core.c | 67 ++++++----- source/blender/bmesh/intern/bmesh_core.h | 54 +++++---- source/blender/bmesh/intern/bmesh_edgeloop.c | 22 ++-- source/blender/bmesh/intern/bmesh_edgeloop.h | 22 ++-- source/blender/bmesh/intern/bmesh_interp.c | 36 +++--- source/blender/bmesh/intern/bmesh_iterators.c | 26 +++-- source/blender/bmesh/intern/bmesh_iterators.h | 19 ++-- source/blender/bmesh/intern/bmesh_marking.c | 25 +++-- source/blender/bmesh/intern/bmesh_marking.h | 22 ++-- source/blender/bmesh/intern/bmesh_mesh.c | 15 ++- source/blender/bmesh/intern/bmesh_mesh.h | 5 +- source/blender/bmesh/intern/bmesh_mesh_conv.c | 10 +- source/blender/bmesh/intern/bmesh_mesh_conv.h | 5 +- source/blender/bmesh/intern/bmesh_mods.c | 38 ++++--- source/blender/bmesh/intern/bmesh_mods.h | 56 ++++++---- source/blender/bmesh/intern/bmesh_operator_api.h | 108 ++++++++++-------- .../bmesh/intern/bmesh_operator_api_inline.h | 30 +++-- source/blender/bmesh/intern/bmesh_operators.c | 124 ++++++++++++--------- source/blender/bmesh/intern/bmesh_operators.h | 17 +-- source/blender/bmesh/intern/bmesh_polygon.c | 20 ++-- source/blender/bmesh/intern/bmesh_polygon.h | 10 +- source/blender/bmesh/intern/bmesh_queries.c | 19 ++-- source/blender/bmesh/intern/bmesh_queries.h | 21 ++-- source/blender/bmesh/intern/bmesh_walkers.c | 9 +- source/blender/bmesh/intern/bmesh_walkers.h | 9 +- source/blender/bmesh/tools/bmesh_beautify.c | 18 +-- source/blender/bmesh/tools/bmesh_bevel.c | 73 +++++++----- source/blender/bmesh/tools/bmesh_bevel.h | 9 +- source/blender/bmesh/tools/bmesh_decimate.h | 16 +-- .../blender/bmesh/tools/bmesh_decimate_collapse.c | 59 +++++----- .../blender/bmesh/tools/bmesh_decimate_dissolve.c | 16 +-- source/blender/bmesh/tools/bmesh_edgenet.c | 5 +- source/blender/bmesh/tools/bmesh_edgenet.h | 5 +- source/blender/bmesh/tools/bmesh_region_match.c | 10 +- source/blender/bmesh/tools/bmesh_triangulate.h | 5 +- source/blender/bmesh/tools/bmesh_wireframe.c | 5 +- source/blender/python/bmesh/bmesh_py_ops_call.c | 23 ++-- source/blender/python/bmesh/bmesh_py_types.c | 9 +- source/blender/python/bmesh/bmesh_py_types.h | 9 +- 44 files changed, 712 insertions(+), 510 deletions(-) diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c index 645567eea67..18f3db6bd15 100644 --- a/source/blender/blenkernel/intern/modifiers_bmesh.c +++ b/source/blender/blenkernel/intern/modifiers_bmesh.c @@ -37,8 +37,9 @@ #include "BKE_editmesh.h" /* Static function for alloc */ -static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml, - BMesh *bm, BMVert **vtable, BMEdge **etable) +static BMFace *bm_face_create_from_mpoly( + MPoly *mp, MLoop *ml, + BMesh *bm, BMVert **vtable, BMEdge **etable) { BMVert **verts = BLI_array_alloca(verts, mp->totloop); BMEdge **edges = BLI_array_alloca(edges, mp->totloop); diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 5977243a21c..bc193b74343 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -667,8 +667,9 @@ static bool check_mask(EdgeQueueContext *eq_ctx, BMVert *v) return (BM_ELEM_CD_GET_FLOAT(v, eq_ctx->cd_vert_mask_offset) < 1.0f); } -static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e, - float priority) +static void edge_queue_insert( + EdgeQueueContext *eq_ctx, BMEdge *e, + float priority) { BMVert **pair; @@ -694,8 +695,9 @@ static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e, } } -static void long_edge_queue_edge_add(EdgeQueueContext *eq_ctx, - BMEdge *e) +static void long_edge_queue_edge_add( + EdgeQueueContext *eq_ctx, + BMEdge *e) { #ifdef USE_EDGEQUEUE_TAG if (EDGE_QUEUE_TEST(e) == false) @@ -765,8 +767,9 @@ static void long_edge_queue_edge_add_recursive( } #endif /* USE_EDGEQUEUE_EVEN_SUBDIV */ -static void short_edge_queue_edge_add(EdgeQueueContext *eq_ctx, - BMEdge *e) +static void short_edge_queue_edge_add( + EdgeQueueContext *eq_ctx, + BMEdge *e) { #ifdef USE_EDGEQUEUE_TAG if (EDGE_QUEUE_TEST(e) == false) @@ -779,8 +782,9 @@ static void short_edge_queue_edge_add(EdgeQueueContext *eq_ctx, } } -static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, - BMFace *f) +static void long_edge_queue_face_add( + EdgeQueueContext *eq_ctx, + BMFace *f) { if (edge_queue_tri_in_sphere(eq_ctx->q, f)) { BMLoop *l_iter; @@ -805,8 +809,9 @@ static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, } } -static void short_edge_queue_face_add(EdgeQueueContext *eq_ctx, - BMFace *f) +static void short_edge_queue_face_add( + EdgeQueueContext *eq_ctx, + BMFace *f) { if (edge_queue_tri_in_sphere(eq_ctx->q, f)) { BMLoop *l_iter; @@ -829,9 +834,10 @@ static void short_edge_queue_face_add(EdgeQueueContext *eq_ctx, * * The highest priority (lowest number) is given to the longest edge. */ -static void long_edge_queue_create(EdgeQueueContext *eq_ctx, - PBVH *bvh, const float center[3], - float radius) +static void long_edge_queue_create( + EdgeQueueContext *eq_ctx, + PBVH *bvh, const float center[3], + float radius) { int n; @@ -877,9 +883,10 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx, * * The highest priority (lowest number) is given to the shortest edge. */ -static void short_edge_queue_create(EdgeQueueContext *eq_ctx, - PBVH *bvh, const float center[3], - float radius) +static void short_edge_queue_create( + EdgeQueueContext *eq_ctx, + PBVH *bvh, const float center[3], + float radius) { int n; @@ -920,8 +927,9 @@ static void bm_edges_from_tri(BMesh *bm, BMVert *v_tri[3], BMEdge *e_tri[3]) e_tri[2] = BM_edge_create(bm, v_tri[2], v_tri[0], NULL, BM_CREATE_NO_DOUBLE); } -static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh, - BMEdge *e, BLI_Buffer *edge_loops) +static void pbvh_bmesh_split_edge( + EdgeQueueContext *eq_ctx, PBVH *bvh, + BMEdge *e, BLI_Buffer *edge_loops) { BMVert *v_new; float co_mid[3], no_mid[3]; @@ -1037,8 +1045,9 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh, BM_edge_kill(bvh->bm, e); } -static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh, - BLI_Buffer *edge_loops) +static bool pbvh_bmesh_subdivide_long_edges( + EdgeQueueContext *eq_ctx, PBVH *bvh, + BLI_Buffer *edge_loops) { bool any_subdivided = false; @@ -1295,9 +1304,10 @@ static bool pbvh_bmesh_collapse_short_edges( /************************* Called from pbvh.c *************************/ -bool pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3], - const float ray_normal[3], float *dist, - bool use_original) +bool pbvh_bmesh_node_raycast( + PBVHNode *node, const float ray_start[3], + const float ray_normal[3], float *dist, + bool use_original) { bool hit = false; @@ -1433,8 +1443,9 @@ static void pbvh_bmesh_node_layers_reset(PBVH *bvh) /* Build a PBVH from a BMesh */ -void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log, - const int cd_vert_node_offset, const int cd_face_node_offset) +void BKE_pbvh_build_bmesh( + PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log, + const int cd_vert_node_offset, const int cd_face_node_offset) { BMIter iter; BMFace *f; @@ -1474,8 +1485,9 @@ void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log, } /* Collapse short edges, subdivide long edges */ -bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, - const float center[3], float radius) +bool BKE_pbvh_bmesh_update_topology( + PBVH *bvh, PBVHTopologyUpdateMode mode, + const float center[3], float radius) { /* 2 is enough for edge faces - manifold edge */ BLI_buffer_declare_static(BMLoop *, edge_loops, BLI_BUFFER_NOP, 2); diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h index 6b3ef8eb5da..a2b08a1f6d3 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -175,9 +175,10 @@ void BB_expand_with_bb(BB *bb, BB *bb2); void BBC_update_centroid(BBC *bbc); int BB_widest_axis(const BB *bb); void pbvh_grow_nodes(PBVH *bvh, int totnode); -bool ray_face_intersection(const float ray_start[3], const float ray_normal[3], - const float *t0, const float *t1, const float *t2, - const float *t3, float *fdist); +bool ray_face_intersection( + const float ray_start[3], const float ray_normal[3], + const float *t0, const float *t1, const float *t2, + const float *t3, float *fdist); void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag); /* pbvh_bmesh.c */ diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index d64b65e4a01..40fb24947d3 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -47,8 +47,9 @@ #define SELECT 1 /* prototypes */ -static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, - const BMLoop *source_loop, BMLoop *target_loop); +static void bm_loop_attrs_copy( + BMesh *source_mesh, BMesh *target_mesh, + const BMLoop *source_loop, BMLoop *target_loop); /** * \brief Make Quad/Triangle @@ -64,9 +65,10 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, * of the vertices in the vertex array. */ -BMFace *BM_face_create_quad_tri(BMesh *bm, - BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - const BMFace *f_example, const eBMCreateFlag create_flag) +BMFace *BM_face_create_quad_tri( + BMesh *bm, + BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, + const BMFace *f_example, const eBMCreateFlag create_flag) { BMVert *vtar[4] = {v1, v2, v3, v4}; return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true); @@ -81,8 +83,9 @@ BMFace *BM_face_create_quad_tri(BMesh *bm, * this is done since the face may not be completely surrounded by faces, * this way: a quad with 2 connected quads on either side will still get all 4 loops updated */ -void BM_face_copy_shared(BMesh *bm, BMFace *f, - BMElemFilterFunc filter_fn, void *user_data) +void BM_face_copy_shared( + BMesh *bm, BMFace *f, + BMElemFilterFunc filter_fn, void *user_data) { BMLoop *l_first; BMLoop *l_iter; @@ -250,9 +253,10 @@ BMFace *BM_face_create_ngon( * - Optionally create edges between vertices. * - Uses verts so no need to find edges (handy when you only have verts) */ -BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag, - const bool calc_winding, const bool create_edges) +BMFace *BM_face_create_ngon_verts( + BMesh *bm, BMVert **vert_arr, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag, + const bool calc_winding, const bool create_edges) { BMEdge **edge_arr = BLI_array_alloca(edge_arr, len); unsigned int winding[2] = {0, 0}; @@ -331,8 +335,9 @@ BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, * * \note Since this is a vcloud there is no direction. */ -BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, - const BMFace *f_example, const eBMCreateFlag create_flag) +BMFace *BM_face_create_ngon_vcloud( + BMesh *bm, BMVert **vert_arr, int len, + const BMFace *f_example, const eBMCreateFlag create_flag) { struct SortIntByFloat *vang = BLI_array_alloca(vang, len); BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len); @@ -453,8 +458,9 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, /*************************************************************/ -static void bm_vert_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, - const BMVert *source_vertex, BMVert *target_vertex) +static void bm_vert_attrs_copy( + BMesh *source_mesh, BMesh *target_mesh, + const BMVert *source_vertex, BMVert *target_vertex) { if ((source_mesh == target_mesh) && (source_vertex == target_vertex)) { BLI_assert(!"BMVert: source and targer match"); @@ -466,8 +472,9 @@ static void bm_vert_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, source_vertex->head.data, &target_vertex->head.data); } -static void bm_edge_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, - const BMEdge *source_edge, BMEdge *target_edge) +static void bm_edge_attrs_copy( + BMesh *source_mesh, BMesh *target_mesh, + const BMEdge *source_edge, BMEdge *target_edge) { if ((source_mesh == target_mesh) && (source_edge == target_edge)) { BLI_assert(!"BMEdge: source and targer match"); @@ -478,8 +485,9 @@ static void bm_edge_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, source_edge->head.data, &target_edge->head.data); } -static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, - const BMLoop *source_loop, BMLoop *target_loop) +static void bm_loop_attrs_copy( + BMesh *source_mesh, BMesh *target_mesh, + const BMLoop *source_loop, BMLoop *target_loop) { if ((source_mesh == target_mesh) && (source_loop == target_loop)) { BLI_assert(!"BMLoop: source and targer match"); @@ -490,8 +498,9 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, source_loop->head.data, &target_loop->head.data); } -static void bm_face_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, - const BMFace *source_face, BMFace *target_face) +static void bm_face_attrs_copy( + BMesh *source_mesh, BMesh *target_mesh, + const BMFace *source_face, BMFace *target_face) { if ((source_mesh == target_mesh) && (source_face == target_face)) { BLI_assert(!"BMFace: source and targer match"); @@ -511,8 +520,9 @@ static void bm_face_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, * Copies attributes, e.g. customdata, header flags, etc, from one element * to another of the same type. */ -void BM_elem_attrs_copy_ex(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v, - const char hflag_mask) +void BM_elem_attrs_copy_ex( + BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v, + const char hflag_mask) { const BMHeader *ele_src = ele_src_v; BMHeader *ele_dst = ele_dst_v; @@ -577,9 +587,10 @@ void BM_elem_select_copy(BMesh *bm_dst, BMesh *UNUSED(bm_src), void *ele_dst_v, } /* helper function for 'BM_mesh_copy' */ -static BMFace *bm_mesh_copy_new_face(BMesh *bm_new, BMesh *bm_old, - BMVert **vtable, BMEdge **etable, - BMFace *f) +static BMFace *bm_mesh_copy_new_face( + BMesh *bm_new, BMesh *bm_old, + BMVert **vtable, BMEdge **etable, + BMFace *f) { BMLoop **loops = BLI_array_alloca(loops, f->len); BMVert **verts = BLI_array_alloca(verts, f->len); diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h index 12d3a4bd474..0e3ca75681a 100644 --- a/source/blender/bmesh/intern/bmesh_construct.h +++ b/source/blender/bmesh/intern/bmesh_construct.h @@ -29,23 +29,29 @@ struct BMAllocTemplate; -BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - const BMFace *f_example, const eBMCreateFlag create_flag); +BMFace *BM_face_create_quad_tri( + BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, + const BMFace *f_example, const eBMCreateFlag create_flag); -void BM_face_copy_shared(BMesh *bm, BMFace *f, - BMElemFilterFunc filter_fn, void *user_data); +void BM_face_copy_shared( + BMesh *bm, BMFace *f, + BMElemFilterFunc filter_fn, void *user_data); -BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag); -BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag, - const bool calc_winding, const bool create_edges); +BMFace *BM_face_create_ngon( + BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag); +BMFace *BM_face_create_ngon_verts( + BMesh *bm, BMVert **vert_arr, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag, + const bool calc_winding, const bool create_edges); -BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, - const BMFace *f_example, const eBMCreateFlag create_flag); +BMFace *BM_face_create_ngon_vcloud( + BMesh *bm, BMVert **vert_arr, int len, + const BMFace *f_example, const eBMCreateFlag create_flag); -void BM_elem_attrs_copy_ex(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v, - const char hflag_mask); +void BM_elem_attrs_copy_ex( + BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v, + const char hflag_mask); void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v); void BM_elem_select_copy(BMesh *bm_dst, BMesh *bm_src, void *ele_dst_v, const void *ele_src_v); diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 7b54fcbffde..743dc8502d7 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -57,8 +57,9 @@ /** * \brief Main function for creating a new vertex. */ -BMVert *BM_vert_create(BMesh *bm, const float co[3], - const BMVert *v_example, const eBMCreateFlag create_flag) +BMVert *BM_vert_create( + BMesh *bm, const float co[3], + const BMVert *v_example, const eBMCreateFlag create_flag) { BMVert *v = BLI_mempool_alloc(bm->vpool); @@ -141,8 +142,9 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], * \note Duplicate edges are supported by the API however users should _never_ see them. * so unless you need a unique edge or know the edge won't exist, you should call with \a no_double = true */ -BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, - const BMEdge *e_example, const eBMCreateFlag create_flag) +BMEdge *BM_edge_create( + BMesh *bm, BMVert *v1, BMVert *v2, + const BMEdge *e_example, const eBMCreateFlag create_flag) { BMEdge *e; @@ -204,8 +206,9 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, return e; } -static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, - const BMLoop *l_example, const eBMCreateFlag create_flag) +static BMLoop *bm_loop_create( + BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, + const BMLoop *l_example, const eBMCreateFlag create_flag) { BMLoop *l = NULL; @@ -254,8 +257,9 @@ static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, return l; } -static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte, - const eBMCreateFlag create_flag) +static BMLoop *bm_face_boundary_add( + BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte, + const eBMCreateFlag create_flag) { #ifdef USE_BMESH_HOLES BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool); @@ -276,8 +280,9 @@ static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge return l; } -BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f, - const bool copy_verts, const bool copy_edges) +BMFace *BM_face_copy( + BMesh *bm_dst, BMesh *bm_src, BMFace *f, + const bool copy_verts, const bool copy_edges) { BMVert **verts = BLI_array_alloca(verts, f->len); BMEdge **edges = BLI_array_alloca(edges, f->len); @@ -400,8 +405,9 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) * \param len Length of the face * \param create_flag Options for creating the face */ -BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag) +BMFace *BM_face_create( + BMesh *bm, BMVert **verts, BMEdge **edges, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag) { BMFace *f = NULL; BMLoop *l, *startl, *lastl; @@ -474,8 +480,9 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, /** * Wrapper for #BM_face_create when you don't have an edge array */ -BMFace *BM_face_create_verts(BMesh *bm, BMVert **vert_arr, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges) +BMFace *BM_face_create_verts( + BMesh *bm, BMVert **vert_arr, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges) { BMEdge **edge_arr = BLI_array_alloca(edge_arr, len); int i, i_prev = len - 1; @@ -1327,14 +1334,14 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *f_example) * * \return A BMFace pointer */ -BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2, - BMLoop **r_l, +BMFace *bmesh_sfme( + BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2, + BMLoop **r_l, #ifdef USE_BMESH_HOLES - ListBase *holes, + ListBase *holes, #endif - BMEdge *e_example, - const bool no_double - ) + BMEdge *e_example, + const bool no_double) { #ifdef USE_BMESH_HOLES BMLoopList *lst, *lst2; @@ -1673,8 +1680,9 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) * faces with just 2 edges. It is up to the caller to decide what to do with * these faces. */ -BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, - const bool do_del, const bool check_edge_double) +BMEdge *bmesh_jekv( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, + const bool do_del, const bool check_edge_double) { BMEdge *e_old; BMVert *v_old, *tv; @@ -2074,8 +2082,9 @@ bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) * * \return Success */ -void bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, - const bool copy_select) +void bmesh_vert_separate( + BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, + const bool copy_select) { const int v_edgetot = BM_vert_face_count(v); BMEdge **stack = BLI_array_alloca(stack, v_edgetot); @@ -2206,8 +2215,9 @@ void bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len /** * High level function which wraps both #bmesh_vert_separate and #bmesh_edge_separate */ -void BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, - BMEdge **e_in, int e_in_len) +void BM_vert_separate( + BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, + BMEdge **e_in, int e_in_len) { int i; @@ -2274,8 +2284,9 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target) * \note Does nothing if \a l_sep is already the only loop in the * edge radial. */ -void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, - const bool copy_select) +void bmesh_edge_separate( + BMesh *bm, BMEdge *e, BMLoop *l_sep, + const bool copy_select) { BMEdge *e_new; #ifndef NDEBUG diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index ab847fc82eb..55bc6a62a88 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -27,8 +27,9 @@ * \ingroup bmesh */ -BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f, - const bool copy_verts, const bool copy_edges); +BMFace *BM_face_copy( + BMesh *bm_dst, BMesh *bm_src, BMFace *f, + const bool copy_verts, const bool copy_edges); typedef enum eBMCreateFlag { BM_CREATE_NOP = 0, @@ -40,15 +41,19 @@ typedef enum eBMCreateFlag { BM_CREATE_SKIP_CD = (1 << 2), } eBMCreateFlag; -BMVert *BM_vert_create(BMesh *bm, const float co[3], - const BMVert *v_example, const eBMCreateFlag create_flag); -BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, - const BMEdge *e_example, const eBMCreateFlag create_flag); -BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag); -BMFace *BM_face_create_verts(BMesh *bm, BMVert **verts, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag, - const bool create_edges); +BMVert *BM_vert_create( + BMesh *bm, const float co[3], + const BMVert *v_example, const eBMCreateFlag create_flag); +BMEdge *BM_edge_create( + BMesh *bm, BMVert *v1, BMVert *v2, + const BMEdge *e_example, const eBMCreateFlag create_flag); +BMFace *BM_face_create( + BMesh *bm, BMVert **verts, BMEdge **edges, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag); +BMFace *BM_face_create_verts( + BMesh *bm, BMVert **verts, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag, + const bool create_edges); void BM_face_edges_kill(BMesh *bm, BMFace *f); void BM_face_verts_kill(BMesh *bm, BMFace *f); @@ -57,25 +62,29 @@ void BM_face_kill(BMesh *bm, BMFace *f); void BM_edge_kill(BMesh *bm, BMEdge *e); void BM_vert_kill(BMesh *bm, BMVert *v); -void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, - const bool copy_select); +void bmesh_edge_separate( + BMesh *bm, BMEdge *e, BMLoop *l_sep, + const bool copy_select); bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target); bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target); bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b); -void bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, - const bool copy_select); +void bmesh_vert_separate( + BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, + const bool copy_select); bool bmesh_loop_reverse(BMesh *bm, BMFace *f); BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del); -void BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, - BMEdge **e_in, int e_in_len); +void BM_vert_separate( + BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, + BMEdge **e_in, int e_in_len); /* EULER API - For modifying structure */ -BMFace *bmesh_sfme(BMesh *bm, BMFace *f, - BMLoop *l1, BMLoop *l2, - BMLoop **r_l, +BMFace *bmesh_sfme( + BMesh *bm, BMFace *f, + BMLoop *l1, BMLoop *l2, + BMLoop **r_l, #ifdef USE_BMESH_HOLES ListBase *holes, #endif @@ -84,8 +93,9 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, ); BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e); -BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, - const bool do_del, const bool check_edge_splice); +BMEdge *bmesh_jekv( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, + const bool do_del, const bool check_edge_splice); BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e); BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep); BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep); diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c index aa1f511e8d7..eaa070151a6 100644 --- a/source/blender/bmesh/intern/bmesh_edgeloop.c +++ b/source/blender/bmesh/intern/bmesh_edgeloop.c @@ -52,8 +52,9 @@ typedef struct BMEdgeLoopStore { /* -------------------------------------------------------------------- */ /* BM_mesh_edgeloops_find & Util Functions */ -static int bm_vert_other_tag(BMVert *v, BMVert *v_prev, - BMEdge **r_e) +static int bm_vert_other_tag( + BMVert *v, BMVert *v_prev, + BMEdge **r_e) { BMIter iter; BMEdge *e, *e_next = NULL; @@ -125,8 +126,9 @@ static bool bm_loop_build(BMEdgeLoopStore *el_store, BMVert *v_prev, BMVert *v, /** * \return listbase of listbases, each linking to a vertex. */ -int BM_mesh_edgeloops_find(BMesh *bm, ListBase *r_eloops, - bool (*test_fn)(BMEdge *, void *user_data), void *user_data) +int BM_mesh_edgeloops_find( + BMesh *bm, ListBase *r_eloops, + bool (*test_fn)(BMEdge *, void *user_data), void *user_data) { BMIter iter; BMEdge *e; @@ -183,8 +185,9 @@ struct VertStep { BMVert *v; }; -static void vs_add(BLI_mempool *vs_pool, ListBase *lb, - BMVert *v, BMEdge *e_prev, const int iter_tot) +static void vs_add( + BLI_mempool *vs_pool, ListBase *lb, + BMVert *v, BMEdge *e_prev, const int iter_tot) { struct VertStep *vs_new = BLI_mempool_alloc(vs_pool); vs_new->v = v; @@ -256,9 +259,10 @@ static bool bm_loop_path_build_step(BLI_mempool *vs_pool, ListBase *lb, const in return (BLI_listbase_is_empty(lb) == false); } -bool BM_mesh_edgeloops_find_path(BMesh *bm, ListBase *r_eloops, - bool (*test_fn)(BMEdge *, void *user_data), void *user_data, - BMVert *v_src, BMVert *v_dst) +bool BM_mesh_edgeloops_find_path( + BMesh *bm, ListBase *r_eloops, + bool (*test_fn)(BMEdge *, void *user_data), void *user_data, + BMVert *v_src, BMVert *v_dst) { BMIter iter; BMEdge *e; diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.h b/source/blender/bmesh/intern/bmesh_edgeloop.h index 527dba120e1..5df4ee5848e 100644 --- a/source/blender/bmesh/intern/bmesh_edgeloop.h +++ b/source/blender/bmesh/intern/bmesh_edgeloop.h @@ -32,17 +32,20 @@ struct ListBase; struct BMEdgeLoopStore; /* multiple edgeloops (ListBase) */ -int BM_mesh_edgeloops_find(BMesh *bm, struct ListBase *r_lb, - bool (*test_fn)(BMEdge *, void *user_data), void *user_data); -bool BM_mesh_edgeloops_find_path(BMesh *bm, ListBase *r_eloops, - bool (*test_fn)(BMEdge *, void *user_data), void *user_data, - BMVert *v_src, BMVert *v_dst); +int BM_mesh_edgeloops_find( + BMesh *bm, struct ListBase *r_lb, + bool (*test_fn)(BMEdge *, void *user_data), void *user_data); +bool BM_mesh_edgeloops_find_path( + BMesh *bm, ListBase *r_eloops, + bool (*test_fn)(BMEdge *, void *user_data), void *user_data, + BMVert *v_src, BMVert *v_dst); void BM_mesh_edgeloops_free(struct ListBase *eloops); void BM_mesh_edgeloops_calc_center(BMesh *bm, struct ListBase *eloops); void BM_mesh_edgeloops_calc_normal(BMesh *bm, struct ListBase *eloops); -void BM_mesh_edgeloops_calc_normal_aligned(BMesh *bm, struct ListBase *eloops, - const float no_align[3]); +void BM_mesh_edgeloops_calc_normal_aligned( + BMesh *bm, struct ListBase *eloops, + const float no_align[3]); void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops, const bool use_normals); @@ -59,8 +62,9 @@ const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store); void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr); void BM_edgeloop_calc_center(BMesh *bm, struct BMEdgeLoopStore *el_store); bool BM_edgeloop_calc_normal(BMesh *bm, struct BMEdgeLoopStore *el_store); -bool BM_edgeloop_calc_normal_aligned(BMesh *bm, struct BMEdgeLoopStore *el_store, - const float no_align[3]); +bool BM_edgeloop_calc_normal_aligned( + BMesh *bm, struct BMEdgeLoopStore *el_store, + const float no_align[3]); void BM_edgeloop_flip(BMesh *bm, struct BMEdgeLoopStore *el_store); void BM_edgeloop_expand(BMesh *bm, struct BMEdgeLoopStore *el_store, int el_store_len); diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index f745972293e..f8306d22ba7 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -241,8 +241,9 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, con * y * */ -static int compute_mdisp_quad(BMLoop *l, float v1[3], float v2[3], float v3[3], float v4[3], - float e1[3], float e2[3]) +static int compute_mdisp_quad( + BMLoop *l, float v1[3], float v2[3], float v3[3], float v4[3], + float e1[3], float e2[3]) { float cent[3], n[3], p[3]; @@ -302,9 +303,10 @@ static float quad_coord(const float aa[3], const float bb[3], const float cc[3], return f1; } -static int quad_co(float *x, float *y, - const float v1[3], const float v2[3], const float v3[3], const float v4[3], - const float p[3], const float n[3]) +static int quad_co( + float *r_x, float *r_y, + const float v1[3], const float v2[3], const float v3[3], const float v4[3], + const float p[3], const float n[3]) { float projverts[5][3], n2[3]; float dprojverts[4][3], origin[3] = {0.0f, 0.0f, 0.0f}; @@ -340,14 +342,15 @@ static int quad_co(float *x, float *y, return 0; } - *y = quad_coord(dprojverts[1], dprojverts[0], dprojverts[2], dprojverts[3], 0, 1); - *x = quad_coord(dprojverts[2], dprojverts[1], dprojverts[3], dprojverts[0], 0, 1); + *r_y = quad_coord(dprojverts[1], dprojverts[0], dprojverts[2], dprojverts[3], 0, 1); + *r_x = quad_coord(dprojverts[2], dprojverts[1], dprojverts[3], dprojverts[0], 0, 1); return 1; } -static void mdisp_axis_from_quad(float v1[3], float v2[3], float UNUSED(v3[3]), float v4[3], - float axis_x[3], float axis_y[3]) +static void mdisp_axis_from_quad( + float v1[3], float v2[3], float UNUSED(v3[3]), float v4[3], + float axis_x[3], float axis_y[3]) { sub_v3_v3v3(axis_x, v4, v1); sub_v3_v3v3(axis_y, v2, v1); @@ -358,8 +361,9 @@ static void mdisp_axis_from_quad(float v1[3], float v2[3], float UNUSED(v3[3]), /* tl is loop to project onto, l is loop whose internal displacement, co, is being * projected. x and y are location in loop's mdisps grid of point co. */ -static bool mdisp_in_mdispquad(BMLoop *l, BMLoop *tl, float p[3], float *x, float *y, - int res, float axis_x[3], float axis_y[3]) +static bool mdisp_in_mdispquad( + BMLoop *l, BMLoop *tl, float p[3], float *x, float *y, + int res, float axis_x[3], float axis_y[3]) { float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3]; float eps = FLT_EPSILON * 4000; @@ -392,8 +396,9 @@ static bool mdisp_in_mdispquad(BMLoop *l, BMLoop *tl, float p[3], float *x, floa return 1; } -static float bm_loop_flip_equotion(float mat[2][2], float b[2], const float target_axis_x[3], const float target_axis_y[3], - const float coord[3], int i, int j) +static float bm_loop_flip_equotion( + float mat[2][2], float b[2], const float target_axis_x[3], const float target_axis_y[3], + const float coord[3], int i, int j) { mat[0][0] = target_axis_x[i]; mat[0][1] = target_axis_y[i]; @@ -405,8 +410,9 @@ static float bm_loop_flip_equotion(float mat[2][2], float b[2], const float targ return mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]; } -static void bm_loop_flip_disp(const float source_axis_x[3], const float source_axis_y[3], - const float target_axis_x[3], const float target_axis_y[3], float disp[3]) +static void bm_loop_flip_disp( + const float source_axis_x[3], const float source_axis_y[3], + const float target_axis_x[3], const float target_axis_y[3], float disp[3]) { float vx[3], vy[3], coord[3]; float n[3], vec[3]; diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index 4dc27d75a55..0abf41709a0 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -136,8 +136,9 @@ int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, cons * * Sometimes its convenient to get the iterator as an array. */ -int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, - void **array, const int len) +int BMO_iter_as_array( + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, + void **array, const int len) { int i = 0; @@ -169,9 +170,10 @@ int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam * * Caller needs to free the array. */ -void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, - /* optional args to avoid an alloc (normally stack array) */ - void **stack_array, int stack_array_size) +void *BM_iter_as_arrayN( + BMesh *bm, const char itype, void *data, int *r_len, + /* optional args to avoid an alloc (normally stack array) */ + void **stack_array, int stack_array_size) { BMIter iter; @@ -212,10 +214,11 @@ void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, } } -void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, - int *r_len, - /* optional args to avoid an alloc (normally stack array) */ - void **stack_array, int stack_array_size) +void *BMO_iter_as_arrayN( + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, + int *r_len, + /* optional args to avoid an alloc (normally stack array) */ + void **stack_array, int stack_array_size) { BMOIter iter; BMElem *ele; @@ -273,8 +276,9 @@ int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, cons * * Counts how many flagged / unflagged items are found in this element. */ -int BMO_iter_elem_count_flag(BMesh *bm, const char itype, void *data, - const short oflag, const bool value) +int BMO_iter_elem_count_flag( + BMesh *bm, const char itype, void *data, + const short oflag, const bool value) { BMIter iter; BMElemF *ele; diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index 49e511bdcb5..c4b184ef8b8 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -197,14 +197,17 @@ typedef struct BMIter { void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) ATTR_WARN_UNUSED_RESULT; int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len); -void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, - void **stack_array, int stack_array_size) ATTR_WARN_UNUSED_RESULT; -int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, - void **array, const int len); -void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, - int *r_len, - /* optional args to avoid an alloc (normally stack array) */ - void **stack_array, int stack_array_size); +void *BM_iter_as_arrayN( + BMesh *bm, const char itype, void *data, int *r_len, + void **stack_array, int stack_array_size) ATTR_WARN_UNUSED_RESULT; +int BMO_iter_as_array( + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, + void **array, const int len); +void *BMO_iter_as_arrayN( + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, + int *r_len, + /* optional args to avoid an alloc (normally stack array) */ + void **stack_array, int stack_array_size); int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value); int BMO_iter_elem_count_flag(BMesh *bm, const char itype, void *data, const short oflag, const bool value); int BM_iter_mesh_count(const char itype, BMesh *bm); diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 8aa64906019..a735f3955fc 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -626,8 +626,9 @@ void BM_mesh_select_mode_set(BMesh *bm, int selectmode) /** * counts number of elements with flag enabled/disabled */ -static int bm_mesh_flag_count(BMesh *bm, const char htype, const char hflag, - const bool respecthide, const bool test_for_enabled) +static int bm_mesh_flag_count( + BMesh *bm, const char htype, const char hflag, + const bool respecthide, const bool test_for_enabled) { BMElem *ele; BMIter iter; @@ -1013,8 +1014,9 @@ GHash *BM_select_history_map_create(BMesh *bm) return map; } -void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag, - const bool respecthide, const bool overwrite, const char hflag_test) +void BM_mesh_elem_hflag_disable_test( + BMesh *bm, const char htype, const char hflag, + const bool respecthide, const bool overwrite, const char hflag_test) { const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, @@ -1084,8 +1086,9 @@ void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hfl } } -void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hflag, - const bool respecthide, const bool overwrite, const char hflag_test) +void BM_mesh_elem_hflag_enable_test( + BMesh *bm, const char htype, const char hflag, + const bool respecthide, const bool overwrite, const char hflag_test) { const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, @@ -1139,15 +1142,17 @@ void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hfla } } -void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, - const bool respecthide) +void BM_mesh_elem_hflag_disable_all( + BMesh *bm, const char htype, const char hflag, + const bool respecthide) { /* call with 0 hflag_test */ BM_mesh_elem_hflag_disable_test(bm, htype, hflag, respecthide, false, 0); } -void BM_mesh_elem_hflag_enable_all(BMesh *bm, const char htype, const char hflag, - const bool respecthide) +void BM_mesh_elem_hflag_enable_all( + BMesh *bm, const char htype, const char hflag, + const bool respecthide) { /* call with 0 hflag_test */ BM_mesh_elem_hflag_enable_test(bm, htype, hflag, respecthide, false, 0); diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h index 15f972c6435..0d86567c06e 100644 --- a/source/blender/bmesh/intern/bmesh_marking.h +++ b/source/blender/bmesh/intern/bmesh_marking.h @@ -43,15 +43,19 @@ void BM_face_hide_set(BMFace *f, const bool hide); /* Selection code */ void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select); -void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hflag, - const bool respecthide, const bool overwrite, const char hflag_test); -void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag, - const bool respecthide, const bool overwrite, const char hflag_test); - -void BM_mesh_elem_hflag_enable_all(BMesh *bm, const char htype, const char hflag, - const bool respecthide); -void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, - const bool respecthide); +void BM_mesh_elem_hflag_enable_test( + BMesh *bm, const char htype, const char hflag, + const bool respecthide, const bool overwrite, const char hflag_test); +void BM_mesh_elem_hflag_disable_test( + BMesh *bm, const char htype, const char hflag, + const bool respecthide, const bool overwrite, const char hflag_test); + +void BM_mesh_elem_hflag_enable_all( + BMesh *bm, const char htype, const char hflag, + const bool respecthide); +void BM_mesh_elem_hflag_disable_all( + BMesh *bm, const char htype, const char hflag, + const bool respecthide); /* individual element select functions, BM_elem_select_set is a shortcut for these * that automatically detects which one to use*/ diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index ba08f9eab25..2a6c98bce2e 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -303,8 +303,9 @@ static void bm_mesh_edges_calc_vectors(BMesh *bm, float (*edgevec)[3], const flo bm->elem_index_dirty &= ~BM_EDGE; } -static void bm_mesh_verts_calc_normals(BMesh *bm, const float (*edgevec)[3], const float (*fnos)[3], - const float (*vcos)[3], float (*vnos)[3]) +static void bm_mesh_verts_calc_normals( + BMesh *bm, const float (*edgevec)[3], const float (*fnos)[3], + const float (*vcos)[3], float (*vnos)[3]) { BM_mesh_elem_index_ensure(bm, (vnos) ? (BM_EDGE | BM_VERT) : BM_EDGE); @@ -437,8 +438,9 @@ void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (* /** * Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normals_vnos */ -static void bm_mesh_edges_sharp_tag(BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float split_angle, - float (*r_lnos)[3]) +static void bm_mesh_edges_sharp_tag( + BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float split_angle, + float (*r_lnos)[3]) { BMIter eiter, viter; BMVert *v; @@ -1131,8 +1133,9 @@ finally: * These functions ensure its correct and are called more often in debug mode. */ -void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *func, - const char *msg_a, const char *msg_b) +void BM_mesh_elem_index_validate( + BMesh *bm, const char *location, const char *func, + const char *msg_a, const char *msg_b) { const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index 59feea2e2ff..b157237c7d0 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -49,8 +49,9 @@ void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag); void bmesh_edit_end(BMesh *bm, const BMOpTypeFlag type_flag); void BM_mesh_elem_index_ensure(BMesh *bm, const char hflag); -void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *func, - const char *msg_a, const char *msg_b); +void BM_mesh_elem_index_validate( + BMesh *bm, const char *location, const char *func, + const char *msg_a, const char *msg_b); #ifndef NDEBUG bool BM_mesh_elem_table_check(BMesh *bm); diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 3630bb78b8a..24d70cefb2e 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -200,8 +200,9 @@ char BM_mesh_cd_flag_from_bmesh(BMesh *bm) } /* Static function for alloc (duplicate in modifiers_bmesh.c) */ -static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml, - BMesh *bm, BMVert **vtable, BMEdge **etable) +static BMFace *bm_face_create_from_mpoly( + MPoly *mp, MLoop *ml, + BMesh *bm, BMVert **vtable, BMEdge **etable) { BMVert **verts = BLI_array_alloca(verts, mp->totloop); BMEdge **edges = BLI_array_alloca(edges, mp->totloop); @@ -221,8 +222,9 @@ static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml, * * \warning This function doesn't calculate face normals. */ -void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, - const bool calc_face_normal, const bool set_key, int act_key_nr) +void BM_mesh_bm_from_me( + BMesh *bm, Mesh *me, + const bool calc_face_normal, const bool set_key, int act_key_nr) { MVert *mvert; MEdge *medge; diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h index ab9d7a0ccf3..ce286f6c662 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.h +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h @@ -39,8 +39,9 @@ void BM_mesh_cd_flag_ensure(BMesh *bm, struct Mesh *mesh, const char cd_flag); void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag); char BM_mesh_cd_flag_from_bmesh(BMesh *bm); -void BM_mesh_bm_from_me(BMesh *bm, struct Mesh *me, - const bool calc_face_normal, const bool set_key, int act_key_nr); +void BM_mesh_bm_from_me( + BMesh *bm, struct Mesh *me, + const bool calc_face_normal, const bool set_key, int act_key_nr); void BM_mesh_bm_to_me(BMesh *bm, struct Mesh *me, bool do_tessface); #endif /* __BMESH_MESH_CONV_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 85e9ec3aa24..ab6d21de7e8 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -276,10 +276,11 @@ BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f_a, BMFace *f_b, BMEdge *e, const * if the split is successful (and the original original face will be the * other side). NULL if the split fails. */ -BMFace *BM_face_split(BMesh *bm, BMFace *f, - BMLoop *l_a, BMLoop *l_b, - BMLoop **r_l, BMEdge *example, - const bool no_double) +BMFace *BM_face_split( + BMesh *bm, BMFace *f, + BMLoop *l_a, BMLoop *l_b, + BMLoop **r_l, BMEdge *example, + const bool no_double) { const bool has_mdisp = CustomData_has_layer(&bm->ldata, CD_MDISPS); BMFace *f_new, *f_tmp; @@ -357,10 +358,11 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, * if the split is successful (and the original original face will be the * other side). NULL if the split fails. */ -BMFace *BM_face_split_n(BMesh *bm, BMFace *f, - BMLoop *l_a, BMLoop *l_b, - float cos[][3], int n, - BMLoop **r_l, BMEdge *example) +BMFace *BM_face_split_n( + BMesh *bm, BMFace *f, + BMLoop *l_a, BMLoop *l_b, + float cos[][3], int n, + BMLoop **r_l, BMEdge *example) { BMFace *f_new, *f_tmp; BMLoop *l_dummy; @@ -991,8 +993,9 @@ bool BM_face_split_edgenet( * * \returns The New Edge */ -BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac, - const bool do_del, const bool join_faces, const bool kill_degenerate_faces) +BMEdge *BM_vert_collapse_faces( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac, + const bool do_del, const bool join_faces, const bool kill_degenerate_faces) { BMEdge *e_new = NULL; BMVert *tv = BM_edge_other_vert(e_kill, v_kill); @@ -1104,8 +1107,9 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float * * \return The New Edge */ -BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, - const bool do_del, const bool kill_degenerate_faces) +BMEdge *BM_vert_collapse_edge( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, + const bool do_del, const bool kill_degenerate_faces) { /* nice example implementation but we want loops to have their customdata * accounted for */ @@ -1354,8 +1358,9 @@ bool BM_face_validate(BMFace *face, FILE *err) * * \note #BM_edge_rotate_check must have already run. */ -void BM_edge_calc_rotate(BMEdge *e, const bool ccw, - BMLoop **r_l1, BMLoop **r_l2) +void BM_edge_calc_rotate( + BMEdge *e, const bool ccw, + BMLoop **r_l1, BMLoop **r_l2) { BMVert *v1, *v2; BMFace *fa, *fb; @@ -1517,8 +1522,9 @@ bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2) return true; } -bool BM_edge_rotate_check_beauty(BMEdge *e, - BMLoop *l1, BMLoop *l2) +bool BM_edge_rotate_check_beauty( + BMEdge *e, + BMLoop *l1, BMLoop *l2) { /* Stupid check for now: * Could compare angles of surrounding edges diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h index 59aee323bba..2ef836a14a5 100644 --- a/source/blender/bmesh/intern/bmesh_mods.h +++ b/source/blender/bmesh/intern/bmesh_mods.h @@ -35,24 +35,29 @@ bool BM_disk_dissolve(BMesh *bm, BMVert *v); BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, const bool do_del); -BMFace *BM_face_split(BMesh *bm, BMFace *f, - BMLoop *l_a, BMLoop *l_b, - BMLoop **r_l, - BMEdge *example, const bool no_double); - -BMFace *BM_face_split_n(BMesh *bm, BMFace *f, - BMLoop *l_a, BMLoop *l_b, - float cos[][3], int n, - BMLoop **r_l, BMEdge *example); - -bool BM_face_split_edgenet(BMesh *bm, BMFace *f, - BMEdge **edge_net, const int edge_net_len, - BMFace ***r_face_arr, int *r_face_arr_len); - -BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac, - const bool do_del, const bool join_faces, const bool kill_degenerate_faces); -BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, - const bool do_del, const bool kill_degenerate_faces); +BMFace *BM_face_split( + BMesh *bm, BMFace *f, + BMLoop *l_a, BMLoop *l_b, + BMLoop **r_l, + BMEdge *example, const bool no_double); + +BMFace *BM_face_split_n( + BMesh *bm, BMFace *f, + BMLoop *l_a, BMLoop *l_b, + float cos[][3], int n, +BMLoop **r_l, BMEdge *example); + +bool BM_face_split_edgenet( + BMesh *bm, BMFace *f, + BMEdge **edge_net, const int edge_net_len, + BMFace ***r_face_arr, int *r_face_arr_len); + +BMEdge *BM_vert_collapse_faces( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac, + const bool do_del, const bool join_faces, const bool kill_degenerate_faces); +BMEdge *BM_vert_collapse_edge( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, + const bool do_del, const bool kill_degenerate_faces); BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent); @@ -61,13 +66,16 @@ BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr); bool BM_face_validate(BMFace *face, FILE *err); -void BM_edge_calc_rotate(BMEdge *e, const bool ccw, - BMLoop **r_l1, BMLoop **r_l2); +void BM_edge_calc_rotate( + BMEdge *e, const bool ccw, + BMLoop **r_l1, BMLoop **r_l2); bool BM_edge_rotate_check(BMEdge *e); -bool BM_edge_rotate_check_degenerate(BMEdge *e, - BMLoop *l1, BMLoop *l2); -bool BM_edge_rotate_check_beauty(BMEdge *e, - BMLoop *l1, BMLoop *l2); +bool BM_edge_rotate_check_degenerate( + BMEdge *e, + BMLoop *l1, BMLoop *l2); +bool BM_edge_rotate_check_beauty( + BMEdge *e, + BMLoop *l1, BMLoop *l2); BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag); /* flags for BM_edge_rotate */ diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index 33a956b652f..96f954f8ee7 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -273,9 +273,10 @@ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identif (op_dst)->slots_dst, slot_name_dst, \ (op_dst)->arena) -void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, - BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, - struct MemArena *arena_dst); +void _bmo_slot_copy( + BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + struct MemArena *arena_dst); /* del "context" slot values, used for operator too */ enum { @@ -335,11 +336,12 @@ void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag); -void BMO_mesh_selected_remap(BMesh *bm, - BMOpSlot *slot_vert_map, - BMOpSlot *slot_edge_map, - BMOpSlot *slot_face_map, - const bool check_select); +void BMO_mesh_selected_remap( + BMesh *bm, + BMOpSlot *slot_vert_map, + BMOpSlot *slot_edge_map, + BMOpSlot *slot_face_map, + const bool check_select); /* copies the values from another slot to the end of the output slot */ #define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \ @@ -347,53 +349,62 @@ void BMO_mesh_selected_remap(BMesh *bm, _bmo_slot_buffer_append((op_src)->slots_src, slot_name_src, \ (op_dst)->slots_dst, slot_name_dst, \ (op_dst)->arena) -void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, - BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, - struct MemArena *arena_dst); +void _bmo_slot_buffer_append( + BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + struct MemArena *arena_dst); /* puts every element of type 'type' (which is a bitmask) with tool * flag 'flag', into a slot. */ -void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag); +void BMO_slot_buffer_from_enabled_flag( + BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const short oflag); /* puts every element of type 'type' (which is a bitmask) without tool * flag 'flag', into a slot. */ -void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag); +void BMO_slot_buffer_from_disabled_flag( + BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const short oflag); /* tool-flags all elements inside an element slot array with flag flag. */ -void BMO_slot_buffer_flag_enable(BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag); +void BMO_slot_buffer_flag_enable( + BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const short oflag); /* clears tool-flag flag from all elements inside a slot array. */ -void BMO_slot_buffer_flag_disable(BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag); +void BMO_slot_buffer_flag_disable( + BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const short oflag); /* tool-flags all elements inside an element slot array with flag flag. */ -void BMO_slot_buffer_hflag_enable(BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, const bool do_flush); +void BMO_slot_buffer_hflag_enable( + BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const char hflag, const bool do_flush); /* clears tool-flag flag from all elements inside a slot array. */ -void BMO_slot_buffer_hflag_disable(BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, const bool do_flush); +void BMO_slot_buffer_hflag_disable( + BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const char hflag, const bool do_flush); /* puts every element of type 'type' (which is a bitmask) with header * flag 'flag', into a slot. note: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/ -void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag); +void BMO_slot_buffer_from_enabled_hflag( + BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const char hflag); /* puts every element of type 'type' (which is a bitmask) without * header flag 'flag', into a slot. note: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/ -void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag); +void BMO_slot_buffer_from_disabled_hflag( + BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const char hflag); void BMO_slot_buffer_from_array(BMOperator *op, BMOpSlot *slot, BMHeader **ele_buffer, int ele_buffer_len); @@ -405,19 +416,23 @@ void *BMO_slot_buffer_get_single(BMOpSlot *slot); int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, - const void *element, const void *data); +void BMO_slot_map_insert( + BMOperator *op, BMOpSlot *slot, + const void *element, const void *data); /* flags all elements in a mapping. note that the mapping must only have * bmesh elements in it.*/ -void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], - const char *slot_name, const char hflag, const short oflag); +void BMO_slot_map_to_flag( + BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const char hflag, const short oflag); -void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], - const char *slot_name, const int len); +void *BMO_slot_buffer_alloc( + BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const int len); -void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], - const char *slot_name, const char htype); +void BMO_slot_buffer_from_all( + BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const char htype); /** * This part of the API is used to iterate over element buffer or @@ -466,9 +481,10 @@ typedef struct BMOIter { void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -void *BMO_iter_new(BMOIter *iter, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char restrictmask); +void *BMO_iter_new( + BMOIter *iter, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char restrictmask); void *BMO_iter_step(BMOIter *iter); void **BMO_iter_map_value_p(BMOIter *iter); diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h index 2b78b775723..99fe6659d7d 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h +++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h @@ -69,24 +69,27 @@ BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const shor oflags[bm->stackdepth - 1].f ^= oflag; } -BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op, BMOpSlot *slot, - void *element, const int val) +BLI_INLINE void BMO_slot_map_int_insert( + BMOperator *op, BMOpSlot *slot, + void *element, const int val) { union { void *ptr; int val; } t = {NULL}; BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr)); } -BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op, BMOpSlot *slot, - void *element, const bool val) +BLI_INLINE void BMO_slot_map_bool_insert( + BMOperator *op, BMOpSlot *slot, + void *element, const bool val) { union { void *ptr; bool val; } t = {NULL}; BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr)); } -BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot, - void *element, const float val) +BLI_INLINE void BMO_slot_map_float_insert( + BMOperator *op, BMOpSlot *slot, + void *element, const float val) { union { void *ptr; float val; } t = {NULL}; BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); @@ -99,15 +102,17 @@ BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot, * do NOT use these for non-operator-api-allocated memory! instead * use BMO_slot_map_data_get and BMO_slot_map_insert, which copies the data. */ -BLI_INLINE void BMO_slot_map_ptr_insert(BMOperator *op, BMOpSlot *slot, - const void *element, void *val) +BLI_INLINE void BMO_slot_map_ptr_insert( + BMOperator *op, BMOpSlot *slot, + const void *element, void *val) { BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL); BMO_slot_map_insert(op, slot, element, val); } -BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot, - const void *element, void *val) +BLI_INLINE void BMO_slot_map_elem_insert( + BMOperator *op, BMOpSlot *slot, + const void *element, void *val) { BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM); BMO_slot_map_insert(op, slot, element, val); @@ -115,8 +120,9 @@ BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot, /* no values */ -BLI_INLINE void BMO_slot_map_empty_insert(BMOperator *op, BMOpSlot *slot, - const void *element) +BLI_INLINE void BMO_slot_map_empty_insert( + BMOperator *op, BMOpSlot *slot, + const void *element) { BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_EMPTY); BMO_slot_map_insert(op, slot, element, NULL); diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index ba154b04838..dda1f2fe30a 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -281,9 +281,10 @@ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identif * define used. * Copies data from one slot to another. */ -void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, - BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, - struct MemArena *arena_dst) +void _bmo_slot_copy( + BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + struct MemArena *arena_dst) { BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src); BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); @@ -543,8 +544,9 @@ void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam * */ -static int bmo_mesh_flag_count(BMesh *bm, const char htype, const short oflag, - const bool test_for_enabled) +static int bmo_mesh_flag_count( + BMesh *bm, const char htype, const short oflag, + const bool test_for_enabled) { const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, @@ -602,11 +604,12 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty } } -void BMO_mesh_selected_remap(BMesh *bm, - BMOpSlot *slot_vert_map, - BMOpSlot *slot_edge_map, - BMOpSlot *slot_face_map, - const bool check_select) +void BMO_mesh_selected_remap( + BMesh *bm, + BMOpSlot *slot_vert_map, + BMOpSlot *slot_edge_map, + BMOpSlot *slot_face_map, + const bool check_select) { if (bm->selected.first) { BMEditSelection *ese, *ese_next; @@ -663,8 +666,9 @@ int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na /* inserts a key/value mapping into a mapping slot. note that it copies the * value, it doesn't store a reference to it. */ -void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, - const void *element, const void *data) +void BMO_slot_map_insert( + BMOperator *op, BMOpSlot *slot, + const void *element, const void *data) { (void) op; /* Ignored in release builds. */ @@ -717,8 +721,9 @@ void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd) } #endif -void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag) +void BMO_slot_map_to_flag( + BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const short oflag) { GHashIterator gh_iter; BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); @@ -759,8 +764,9 @@ void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS] * * Copies all elements of a certain type into an operator slot. */ -void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], - const char *slot_name, const char htype) +void BMO_slot_buffer_from_all( + BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const char htype) { BMOpSlot *output = BMO_slot_get(slot_args, slot_name); int totelement = 0, i = 0; @@ -809,9 +815,10 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_ * Copies elements of a certain type, which have a certain header flag * enabled/disabled into a slot for an operator. */ -static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, - const bool test_for_enabled) +static void bmo_slot_buffer_from_hflag( + BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const char hflag, + const bool test_for_enabled) { BMOpSlot *output = BMO_slot_get(slot_args, slot_name); int totelement = 0, i = 0; @@ -872,16 +879,18 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_ } } -void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag) +void BMO_slot_buffer_from_enabled_hflag( + BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const char hflag) { bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, true); } -void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag) +void BMO_slot_buffer_from_disabled_hflag( + BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const char hflag) { bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, false); } @@ -927,9 +936,10 @@ void *BMO_slot_buffer_get_single(BMOpSlot *slot) /** * Copies the values from another slot to the end of the output slot. */ -void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, - BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, - struct MemArena *arena_dst) +void _bmo_slot_buffer_append( + BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + struct MemArena *arena_dst) { BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src); @@ -964,10 +974,11 @@ void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const cha * Copies elements of a certain type, which have a certain flag set * into an output slot for an operator. */ -static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag, - const bool test_for_enabled) +static void bmo_slot_buffer_from_flag( + BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const short oflag, + const bool test_for_enabled) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); int totelement, i = 0; @@ -1026,16 +1037,18 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, } } -void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag) +void BMO_slot_buffer_from_enabled_flag( + BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const short oflag) { bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, true); } -void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag) +void BMO_slot_buffer_from_disabled_flag( + BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const short oflag) { bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, false); } @@ -1046,9 +1059,10 @@ void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, * Header Flags elements in a slots buffer, automatically * using the selection API where appropriate. */ -void BMO_slot_buffer_hflag_enable(BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, const bool do_flush) +void BMO_slot_buffer_hflag_enable( + BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const char hflag, const bool do_flush) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMElem **data = (BMElem **)slot->data.buf; @@ -1082,9 +1096,10 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm, * Removes flags from elements in a slots buffer, automatically * using the selection API where appropriate. */ -void BMO_slot_buffer_hflag_disable(BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, const bool do_flush) +void BMO_slot_buffer_hflag_disable( + BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const char hflag, const bool do_flush) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMElem **data = (BMElem **)slot->data.buf; @@ -1116,9 +1131,10 @@ void BMO_slot_buffer_hflag_disable(BMesh *bm, * * Flags elements in a slots buffer */ -void BMO_slot_buffer_flag_enable(BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag) +void BMO_slot_buffer_flag_enable( + BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const short oflag) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMHeader **data = slot->data.p; @@ -1140,9 +1156,10 @@ void BMO_slot_buffer_flag_enable(BMesh *bm, * * Removes flags from elements in a slots buffer */ -void BMO_slot_buffer_flag_disable(BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag) +void BMO_slot_buffer_flag_disable( + BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const short oflag) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMHeader **data = (BMHeader **)slot->data.buf; @@ -1394,9 +1411,10 @@ void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char * \param restrictmask restricts the iteration to certain element types * (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating * over an element buffer (not a mapping). */ -void *BMO_iter_new(BMOIter *iter, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char restrictmask) +void *BMO_iter_new( + BMOIter *iter, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char restrictmask) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index f39fe29b596..d2ce2faf09d 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -130,14 +130,15 @@ extern const BMOpDefine *bmo_opdefines[]; extern const int bmo_opdefines_total; /*------specific operator helper functions-------*/ -void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, - const float smooth, const short smooth_falloff, const bool use_smooth_even, - const float fractal, const float along_normal, - const int numcuts, - const int seltype, const int cornertype, - const short use_single_edge, const short use_grid_fill, - const short use_only_quads, - const int seed); +void BM_mesh_esubdivide( + BMesh *bm, const char edge_hflag, + const float smooth, const short smooth_falloff, const bool use_smooth_even, + const float fractal, const float along_normal, + const int numcuts, + const int seltype, const int cornertype, + const short use_single_edge, const short use_grid_fill, + const short use_only_quads, + const int seed); #include "intern/bmesh_operator_api_inline.h" diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index bc06ba2c9b1..d2d31d6a562 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -102,8 +102,9 @@ static float bm_face_calc_poly_normal(const BMFace *f, float n[3]) * Same as #calc_poly_normal and #bm_face_calc_poly_normal * but takes an array of vertex locations. */ -static float bm_face_calc_poly_normal_vertex_cos(BMFace *f, float r_no[3], - float const (*vertexCos)[3]) +static float bm_face_calc_poly_normal_vertex_cos( + BMFace *f, float r_no[3], + float const (*vertexCos)[3]) { BMLoop *l_first = BM_FACE_FIRST_LOOP(f); BMLoop *l_iter = l_first; @@ -127,8 +128,9 @@ static float bm_face_calc_poly_normal_vertex_cos(BMFace *f, float r_no[3], /** * \brief COMPUTE POLY CENTER (BMFace) */ -static void bm_face_calc_poly_center_mean_vertex_cos(BMFace *f, float r_cent[3], - float const (*vertexCos)[3]) +static void bm_face_calc_poly_center_mean_vertex_cos( + BMFace *f, float r_cent[3], + float const (*vertexCos)[3]) { BMLoop *l_first = BM_FACE_FIRST_LOOP(f); BMLoop *l_iter = l_first; @@ -548,8 +550,9 @@ void BM_face_normal_update(BMFace *f) } /* exact same as 'BM_face_calc_normal' but accepts vertex coords */ -float BM_face_calc_normal_vcos(BMesh *bm, BMFace *f, float r_no[3], - float const (*vertexCos)[3]) +float BM_face_calc_normal_vcos( + BMesh *bm, BMFace *f, float r_no[3], + float const (*vertexCos)[3]) { BMLoop *l; @@ -607,8 +610,9 @@ float BM_face_calc_normal_subset(BMLoop *l_first, BMLoop *l_last, float r_no[3]) } /* exact same as 'BM_face_calc_normal' but accepts vertex coords */ -void BM_face_calc_center_mean_vcos(BMesh *bm, BMFace *f, float r_cent[3], - float const (*vertexCos)[3]) +void BM_face_calc_center_mean_vcos( + BMesh *bm, BMFace *f, float r_cent[3], + float const (*vertexCos)[3]) { /* must have valid index data */ BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h index 9980b59a298..582b4248c7d 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.h +++ b/source/blender/bmesh/intern/bmesh_polygon.h @@ -36,16 +36,18 @@ void BM_bmesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_loopt void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int (*r_index)[3]); float BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL(); -float BM_face_calc_normal_vcos(BMesh *bm, BMFace *f, float r_no[3], - float const (*vertexCos)[3]) ATTR_NONNULL(); +float BM_face_calc_normal_vcos( + BMesh *bm, BMFace *f, float r_no[3], + float const (*vertexCos)[3]) ATTR_NONNULL(); float BM_face_calc_normal_subset(BMLoop *l_first, BMLoop *l_last, float r_no[3]) ATTR_NONNULL(); float BM_face_calc_area(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); float BM_face_calc_perimeter(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void BM_face_calc_plane(BMFace *f, float r_plane[3]) ATTR_NONNULL(); void BM_face_calc_center_bounds(BMFace *f, float center[3]) ATTR_NONNULL(); void BM_face_calc_center_mean(BMFace *f, float center[3]) ATTR_NONNULL(); -void BM_face_calc_center_mean_vcos(BMesh *bm, BMFace *f, float r_cent[3], - float const (*vertexCos)[3]) ATTR_NONNULL(); +void BM_face_calc_center_mean_vcos( + BMesh *bm, BMFace *f, float r_cent[3], + float const (*vertexCos)[3]) ATTR_NONNULL(); void BM_face_calc_center_mean_weighted(BMFace *f, float center[3]) ATTR_NONNULL(); void BM_face_normal_update(BMFace *f) ATTR_NONNULL(); diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 4d3dd580ab3..0ed5391ed2c 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -1184,8 +1184,9 @@ BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e) * \note This is in fact quite a simple check, mainly include this function so the intent is more obvious. * We know these 2 verts will _always_ make up the loops edge */ -void BM_edge_ordered_verts_ex(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2, - const BMLoop *edge_loop) +void BM_edge_ordered_verts_ex( + const BMEdge *edge, BMVert **r_v1, BMVert **r_v2, + const BMLoop *edge_loop) { BLI_assert(edge_loop->e == edge); (void)edge; /* quiet warning in release build */ @@ -2128,9 +2129,10 @@ float BM_mesh_calc_volume(BMesh *bm, bool is_signed) * (having both set is supported too). * \return The number of groups found. */ -int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2], - BMElemFilterFunc filter_fn, void *user_data, - const char hflag_test, const char htype_step) +int BM_mesh_calc_face_groups( + BMesh *bm, int *r_groups_array, int (**r_group_index)[2], + BMElemFilterFunc filter_fn, void *user_data, + const char hflag_test, const char htype_step) { #ifdef DEBUG int group_index_len = 1; @@ -2285,9 +2287,10 @@ int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_inde * \note Unlike #BM_mesh_calc_face_groups there is no 'htype_step' argument, * since we always walk over verts. */ -int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2], - BMElemFilterFunc filter_fn, void *user_data, - const char hflag_test) +int BM_mesh_calc_edge_groups( + BMesh *bm, int *r_groups_array, int (**r_group_index)[2], + BMElemFilterFunc filter_fn, void *user_data, + const char hflag_test) { #ifdef DEBUG int group_index_len = 1; diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 6d25d9fbfec..2addcc9705d 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -142,8 +142,9 @@ BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v) ATTR_WARN_UNUSED_RESULT AT BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2) ATTR_NONNULL(); -void BM_edge_ordered_verts_ex(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2, - const BMLoop *edge_loop) ATTR_NONNULL(); +void BM_edge_ordered_verts_ex( + const BMEdge *edge, BMVert **r_v1, BMVert **r_v2, + const BMLoop *edge_loop) ATTR_NONNULL(); bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); @@ -157,12 +158,16 @@ bool BM_face_is_normal_valid(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNU float BM_mesh_calc_volume(BMesh *bm, bool is_signed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2], - BMElemFilterFunc filter_fn, void *user_data, - const char hflag_test, const char htype_step) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3); -int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2], - BMElemFilterFunc filter_fn, void *user_data, - const char hflag_test) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3); +int BM_mesh_calc_face_groups( + BMesh *bm, int *r_groups_array, int (**r_group_index)[2], + BMElemFilterFunc filter_fn, void *user_data, + const char hflag_test, const char htype_step) + ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3); +int BM_mesh_calc_edge_groups( + BMesh *bm, int *r_groups_array, int (**r_group_index)[2], + BMElemFilterFunc filter_fn, void *user_data, + const char hflag_test) + ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3); /* not really any good place to put this */ float bmesh_subd_falloff_calc(const int falloff, float val) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/bmesh/intern/bmesh_walkers.c b/source/blender/bmesh/intern/bmesh_walkers.c index 20b56632099..d16eb572540 100644 --- a/source/blender/bmesh/intern/bmesh_walkers.c +++ b/source/blender/bmesh/intern/bmesh_walkers.c @@ -74,10 +74,11 @@ void *BMW_begin(BMWalker *walker, void *start) * a given type. The elements visited are filtered * by the bitmask 'searchmask'. */ -void BMW_init(BMWalker *walker, BMesh *bm, int type, - short mask_vert, short mask_edge, short mask_face, - BMWFlag flag, - int layer) +void BMW_init( + BMWalker *walker, BMesh *bm, int type, + short mask_vert, short mask_edge, short mask_face, + BMWFlag flag, + int layer) { memset(walker, 0, sizeof(BMWalker)); diff --git a/source/blender/bmesh/intern/bmesh_walkers.h b/source/blender/bmesh/intern/bmesh_walkers.h index d551ea9fba9..e84880dc61e 100644 --- a/source/blender/bmesh/intern/bmesh_walkers.h +++ b/source/blender/bmesh/intern/bmesh_walkers.h @@ -76,10 +76,11 @@ typedef struct BMWalker { /* initialize a walker. searchmask restricts some (not all) walkers to * elements with a specific tool flag set. flags is specific to each walker.*/ -void BMW_init(struct BMWalker *walker, BMesh *bm, int type, - short mask_vert, short mask_edge, short mask_face, - BMWFlag flag, - int layer); +void BMW_init( + struct BMWalker *walker, BMesh *bm, int type, + short mask_vert, short mask_edge, short mask_face, + BMWFlag flag, + int layer); void *BMW_begin(BMWalker *walker, void *start); void *BMW_step(struct BMWalker *walker); void BMW_end(struct BMWalker *walker); diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c index b64c3aab5d7..19fe492c670 100644 --- a/source/blender/bmesh/tools/bmesh_beautify.c +++ b/source/blender/bmesh/tools/bmesh_beautify.c @@ -274,11 +274,12 @@ BLI_INLINE bool edge_in_array(const BMEdge *e, const BMEdge **edge_array, const } /* recalc an edge in the heap (surrounding geometry has changed) */ -static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr, - /* only for testing the edge is in the array */ - const BMEdge **edge_array, const int edge_array_len, +static void bm_edge_update_beauty_cost_single( + BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr, + /* only for testing the edge is in the array */ + const BMEdge **edge_array, const int edge_array_len, - const short flag, const short method) + const short flag, const short method) { if (edge_in_array(e, edge_array, edge_array_len)) { const int i = BM_elem_index_get(e); @@ -316,10 +317,11 @@ static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode * } /* we have rotated an edge, tag other edges and clear this one */ -static void bm_edge_update_beauty_cost(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr, - const BMEdge **edge_array, const int edge_array_len, - /* only for testing the edge is in the array */ - const short flag, const short method) +static void bm_edge_update_beauty_cost( + BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr, + const BMEdge **edge_array, const int edge_array_len, + /* only for testing the edge is in the array */ + const short flag, const short method) { int i; diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index a2a0f974a79..252c16e8919 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -244,8 +244,9 @@ static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert BM_elem_flag_disable(nv->v, BM_ELEM_TAG); } -static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto, - int ifrom, int jfrom, int kfrom) +static void copy_mesh_vert( + VMesh *vm, int ito, int jto, int kto, + int ifrom, int jfrom, int kfrom) { NewVert *nvto, *nvfrom; @@ -361,8 +362,9 @@ static BMFace *boundvert_rep_face(BoundVert *v) * * \note ALL face creation goes through this function, this is important to keep! */ -static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv, - BMFace **face_arr, BMFace *facerep, int mat_nr, bool do_interp) +static BMFace *bev_create_ngon( + BMesh *bm, BMVert **vert_arr, const int totv, + BMFace **face_arr, BMFace *facerep, int mat_nr, bool do_interp) { BMIter iter; BMLoop *l; @@ -402,15 +404,17 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv, return f; } -static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - BMFace *facerep, int mat_nr, bool do_interp) +static BMFace *bev_create_quad_tri( + BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, + BMFace *facerep, int mat_nr, bool do_interp) { BMVert *varr[4] = {v1, v2, v3, v4}; return bev_create_ngon(bm, varr, v4 ? 4 : 3, NULL, facerep, mat_nr, do_interp); } -static BMFace *bev_create_quad_tri_ex(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - BMFace *f1, BMFace *f2, BMFace *f3, BMFace *f4, int mat_nr) +static BMFace *bev_create_quad_tri_ex( + BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, + BMFace *f1, BMFace *f2, BMFace *f3, BMFace *f4, int mat_nr) { BMVert *varr[4] = {v1, v2, v3, v4}; BMFace *farr[4] = {f1, f2, f3, f4}; @@ -419,8 +423,9 @@ static BMFace *bev_create_quad_tri_ex(BMesh *bm, BMVert *v1, BMVert *v2, BMVert /* Is Loop layer layer_index contiguous across shared vertex of l1 and l2? */ -static bool contig_ldata_across_loops(BMesh *bm, BMLoop *l1, BMLoop *l2, - int layer_index) +static bool contig_ldata_across_loops( + BMesh *bm, BMLoop *l1, BMLoop *l2, + int layer_index) { const int offset = bm->ldata.layers[layer_index].offset; const int type = bm->ldata.layers[layer_index].type; @@ -478,7 +483,10 @@ static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f return true; } -/* Like bev_create_quad_tri, but when verts straddle an old edge. +/** + * Like #bev_create_quad_tri, but when verts straddle an old edge. + * + *
  *        e
  *        |
  *  v1+---|---+v4
@@ -487,13 +495,16 @@ static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f
  *  v2+---|---+v3
  *        |
  *    f1  |  f2
+ * 
* * Most CustomData for loops can be interpolated in their respective * faces' loops, but for UVs and other 'has_math_cd' layers, only * do this if the UVs are continuous across the edge e, otherwise pick * one side (f1, arbitrarily), and interpolate them all on that side. - * For face data, use f1 (arbitrarily) as face representative. */ -static BMFace *bev_create_quad_straddle(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, + * For face data, use f1 (arbitrarily) as face representative. + */ +static BMFace *bev_create_quad_straddle( + BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, BMFace *f1, BMFace *f2, int mat_nr, bool is_seam) { BMFace *f, *facerep; @@ -737,8 +748,9 @@ static bool offset_meet_edge(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, float meetc * already, prefer to keep the offset the same on this end. * Otherwise, pick a point between the two intersection points on emid that minimizes * the sum of squares of errors from desired offset. */ -static void offset_on_edge_between(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, - BMVert *v, float meetco[3]) +static void offset_on_edge_between( + BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, + BMVert *v, float meetco[3]) { float d, ang1, ang2, sina1, sina2, lambda; float meet1[3], meet2[3]; @@ -793,8 +805,9 @@ static void offset_on_edge_between(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, * Viewed from the vertex normal side, the CCW order of the edges is e1, emid, e2. * The offset lines may not meet exactly: the lines may be angled so that they can't meet. * In that case, pick the offset_on_edge_between. */ -static void offset_in_two_planes(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, - BMVert *v, float meetco[3]) +static void offset_in_two_planes( + BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, + BMVert *v, float meetco[3]) { float dir1[3], dir2[3], dirmid[3], norm_perp1[3], norm_perp2[3], off1a[3], off1b[3], off2a[3], off2b[3], isect2[3], @@ -1079,8 +1092,9 @@ static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f) * and B has the right side as columns - both extended into homogeneous coords. * So M = B*(Ainverse). Doing Ainverse by hand gives the code below. */ -static bool make_unit_square_map(const float va[3], const float vmid[3], const float vb[3], - float r_mat[4][4]) +static bool make_unit_square_map( + const float va[3], const float vmid[3], const float vb[3], + float r_mat[4][4]) { float vo[3], vd[3], vb_vmid[3], va_vmid[3], vddir[3]; @@ -1128,8 +1142,9 @@ static bool make_unit_square_map(const float va[3], const float vmid[3], const f * and 1/2{va+vb+vc-vd} * and Blender matrices have cols at m[i][*]. */ -static void make_unit_cube_map(const float va[3], const float vb[3], const float vc[3], - const float vd[3], float r_mat[4][4]) +static void make_unit_cube_map( + const float va[3], const float vb[3], const float vc[3], + const float vd[3], float r_mat[4][4]) { copy_v3_v3(r_mat[0], va); sub_v3_v3(r_mat[0], vb); @@ -1861,9 +1876,10 @@ static void vmesh_center(VMesh *vm, float r_cent[3]) } } -static void avg4(float co[3], - const NewVert *v0, const NewVert *v1, - const NewVert *v2, const NewVert *v3) +static void avg4( + float co[3], + const NewVert *v0, const NewVert *v1, + const NewVert *v2, const NewVert *v3) { add_v3_v3v3(co, v0->co, v1->co); add_v3_v3(co, v2->co); @@ -3755,10 +3771,11 @@ static float bevel_limit_offset(BMesh *bm, BevelParams *bp) * * \warning all tagged edges _must_ be manifold. */ -void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, - const float segments, const float profile, - const bool vertex_only, const bool use_weights, const bool limit_offset, - const struct MDeformVert *dvert, const int vertex_group, const int mat) +void BM_mesh_bevel( + BMesh *bm, const float offset, const int offset_type, + const float segments, const float profile, + const bool vertex_only, const bool use_weights, const bool limit_offset, + const struct MDeformVert *dvert, const int vertex_group, const int mat) { BMIter iter; BMVert *v, *v_next; diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h index 52d8faa5401..b4bb6c56b7d 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.h +++ b/source/blender/bmesh/tools/bmesh_bevel.h @@ -29,9 +29,10 @@ struct MDeformVert; -void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, const float segments, - const float profile, const bool vertex_only, const bool use_weights, - const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group, - const int mat); +void BM_mesh_bevel( + BMesh *bm, const float offset, const int offset_type, const float segments, + const float profile, const bool vertex_only, const bool use_weights, + const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group, + const int mat); #endif /* __BMESH_BEVEL_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h index a1b26990587..1efa829c60d 100644 --- a/source/blender/bmesh/tools/bmesh_decimate.h +++ b/source/blender/bmesh/tools/bmesh_decimate.h @@ -32,13 +32,15 @@ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, c void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool tag_only); void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations); -void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, - const BMO_Delimit delimit, - BMVert **vinput_arr, const int vinput_len, - BMEdge **einput_arr, const int einput_len, - const short oflag_out); -void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, - const BMO_Delimit delimit); +void BM_mesh_decimate_dissolve_ex( + BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, + const BMO_Delimit delimit, + BMVert **vinput_arr, const int vinput_len, + BMEdge **einput_arr, const int einput_len, + const short oflag_out); +void BM_mesh_decimate_dissolve( + BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, + const BMO_Delimit delimit); /* these weights are accumulated so too high values may reach 'inf' too quickly */ #define BM_MESH_DECIM_WEIGHT_MAX 100000.0f diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 811a144fc39..6851e013e9d 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -112,18 +112,19 @@ static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics) } -static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3], - const Quadric *vquadrics) +static void bm_decim_calc_target_co( + BMEdge *e, float optimize_co[3], + const Quadric *vquadrics) { /* compute an edge contraction target for edge 'e' * this is computed by summing it's vertices quadrics and * optimizing the result. */ Quadric q; - BLI_quadric_add_qu_ququ(&q, - &vquadrics[BM_elem_index_get(e->v1)], - &vquadrics[BM_elem_index_get(e->v2)]); - + BLI_quadric_add_qu_ququ( + &q, + &vquadrics[BM_elem_index_get(e->v1)], + &vquadrics[BM_elem_index_get(e->v2)]); if (BLI_quadric_optimize(&q, optimize_co, OPTIMIZE_EPS)) { return; /* all is good */ @@ -183,9 +184,10 @@ static bool bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_ return false; } -static void bm_decim_build_edge_cost_single(BMEdge *e, - const Quadric *vquadrics, const float *vweights, - Heap *eheap, HeapNode **eheap_table) +static void bm_decim_build_edge_cost_single( + BMEdge *e, + const Quadric *vquadrics, const float *vweights, + Heap *eheap, HeapNode **eheap_table) { const Quadric *q1, *q2; float optimize_co[3]; @@ -258,16 +260,18 @@ static void bm_decim_build_edge_cost_single(BMEdge *e, /* use this for degenerate cases - add back to the heap with an invalid cost, * this way it may be calculated again if surrounding geometry changes */ -static void bm_decim_invalid_edge_cost_single(BMEdge *e, - Heap *eheap, HeapNode **eheap_table) +static void bm_decim_invalid_edge_cost_single( + BMEdge *e, + Heap *eheap, HeapNode **eheap_table) { BLI_assert(eheap_table[BM_elem_index_get(e)] == NULL); eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, COST_INVALID, e); } -static void bm_decim_build_edge_cost(BMesh *bm, - const Quadric *vquadrics, const float *vweights, - Heap *eheap, HeapNode **eheap_table) +static void bm_decim_build_edge_cost( + BMesh *bm, + const Quadric *vquadrics, const float *vweights, + Heap *eheap, HeapNode **eheap_table) { BMIter iter; BMEdge *e; @@ -442,8 +446,9 @@ static void bm_decim_triangulate_end(BMesh *bm) /** * \param v is the target to merge into. */ -static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other, - const float customdata_fac) +static void bm_edge_collapse_loop_customdata( + BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other, + const float customdata_fac) { /* disable seam check - the seam check would have to be done per layer, its not really that important */ //#define USE_SEAM @@ -698,15 +703,16 @@ static bool bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) * \param e_clear_other let caller know what edges we remove besides \a e_clear * \param customdata_flag merge factor, scales from 0 - 1 ('v_clear' -> 'v_other') */ -static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2], +static bool bm_edge_collapse( + BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2], #ifdef USE_CUSTOMDATA - const CD_UseFlag customdata_flag, - const float customdata_fac + const CD_UseFlag customdata_flag, + const float customdata_fac #else - const CD_UseFlag UNUSED(customdata_flag), - const float UNUSED(customdata_fac) + const CD_UseFlag UNUSED(customdata_flag), + const float UNUSED(customdata_fac) #endif - ) + ) { BMVert *v_other; @@ -847,10 +853,11 @@ static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_ /* collapse e the edge, removing e->v2 */ -static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, - Quadric *vquadrics, float *vweights, - Heap *eheap, HeapNode **eheap_table, - const CD_UseFlag customdata_flag) +static void bm_decim_edge_collapse( + BMesh *bm, BMEdge *e, + Quadric *vquadrics, float *vweights, + Heap *eheap, HeapNode **eheap_table, + const CD_UseFlag customdata_flag) { int e_clear_other[2]; BMVert *v_other = e->v1; diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index 096349e8e9c..09c7b932b7a 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -98,11 +98,12 @@ fail: } -void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, - const BMO_Delimit delimit, - BMVert **vinput_arr, const int vinput_len, - BMEdge **einput_arr, const int einput_len, - const short oflag_out) +void BM_mesh_decimate_dissolve_ex( + BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, + const BMO_Delimit delimit, + BMVert **vinput_arr, const int vinput_len, + BMEdge **einput_arr, const int einput_len, + const short oflag_out) { const int eheap_table_len = do_dissolve_boundaries ? einput_len : max_ii(einput_len, vinput_len); void *_heap_table = MEM_mallocN(sizeof(HeapNode *) * eheap_table_len, __func__); @@ -316,8 +317,9 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool MEM_freeN(_heap_table); } -void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, - const BMO_Delimit delimit) +void BM_mesh_decimate_dissolve( + BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, + const BMO_Delimit delimit) { int vinput_len; int einput_len; diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c index 1328b81b746..e93ffe6b141 100644 --- a/source/blender/bmesh/tools/bmesh_edgenet.c +++ b/source/blender/bmesh/tools/bmesh_edgenet.c @@ -450,8 +450,9 @@ static LinkNode *bm_edgenet_path_calc_best( * \param use_edge_tag Only fill tagged edges. * \param face_oflag if nonzero, apply all new faces with this bmo flag. */ -void BM_mesh_edgenet(BMesh *bm, - const bool use_edge_tag, const bool use_new_face_tag) +void BM_mesh_edgenet( + BMesh *bm, + const bool use_edge_tag, const bool use_new_face_tag) { VertNetInfo *vnet_info = MEM_callocN(sizeof(*vnet_info) * (size_t)bm->totvert, __func__); BLI_mempool *edge_queue_pool = BLI_mempool_create(sizeof(LinkNode), 0, 512, BLI_MEMPOOL_NOP); diff --git a/source/blender/bmesh/tools/bmesh_edgenet.h b/source/blender/bmesh/tools/bmesh_edgenet.h index 327a7f5aa23..1ad5cadae7c 100644 --- a/source/blender/bmesh/tools/bmesh_edgenet.h +++ b/source/blender/bmesh/tools/bmesh_edgenet.h @@ -27,7 +27,8 @@ * \ingroup bmesh */ -void BM_mesh_edgenet(BMesh *bm, - const bool use_edge_tag, const bool use_new_face_tag); +void BM_mesh_edgenet( + BMesh *bm, + const bool use_edge_tag, const bool use_new_face_tag); #endif /* __BMESH_EDGENET_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c index 484eea73bbe..72c3bc90599 100644 --- a/source/blender/bmesh/tools/bmesh_region_match.c +++ b/source/blender/bmesh/tools/bmesh_region_match.c @@ -190,14 +190,16 @@ static bool ghashutil_bmelem_indexcmp(const void *a, const void *b) return (a != b); } -static GHash *ghash_bmelem_new_ex(const char *info, - const unsigned int nentries_reserve) +static GHash *ghash_bmelem_new_ex( + const char *info, + const unsigned int nentries_reserve) { return BLI_ghash_new_ex(ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve); } -static GSet *gset_bmelem_new_ex(const char *info, - const unsigned int nentries_reserve) +static GSet *gset_bmelem_new_ex( + const char *info, + const unsigned int nentries_reserve) { return BLI_gset_new_ex(ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve); } diff --git a/source/blender/bmesh/tools/bmesh_triangulate.h b/source/blender/bmesh/tools/bmesh_triangulate.h index 550109ffef9..c6a5e04dfb2 100644 --- a/source/blender/bmesh/tools/bmesh_triangulate.h +++ b/source/blender/bmesh/tools/bmesh_triangulate.h @@ -30,7 +30,8 @@ #ifndef __BMESH_TRIANGULATE_H__ #define __BMESH_TRIANGULATE_H__ -void BM_mesh_triangulate(BMesh *bm, const int quad_method, const int ngon_method, const bool tag_only, - BMOperator *op, BMOpSlot *slot_facemap_out); +void BM_mesh_triangulate( + BMesh *bm, const int quad_method, const int ngon_method, const bool tag_only, + BMOperator *op, BMOpSlot *slot_facemap_out); #endif /* __BMESH_TRIANGULATE_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_wireframe.c b/source/blender/bmesh/tools/bmesh_wireframe.c index 79fea3e5da1..87e571a49aa 100644 --- a/source/blender/bmesh/tools/bmesh_wireframe.c +++ b/source/blender/bmesh/tools/bmesh_wireframe.c @@ -55,8 +55,9 @@ static BMLoop *bm_edge_tag_faceloop(BMEdge *e) return NULL; } -static void bm_vert_boundary_tangent(BMVert *v, float r_no[3], float r_no_face[3], - BMVert **r_va_other, BMVert **r_vb_other) +static void bm_vert_boundary_tangent( + BMVert *v, float r_no[3], float r_no_face[3], + BMVert **r_va_other, BMVert **r_vb_other) { BMIter iter; BMEdge *e_iter; diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c index 84c1031a24a..a4c057acac2 100644 --- a/source/blender/python/bmesh/bmesh_py_ops_call.c +++ b/source/blender/python/bmesh/bmesh_py_ops_call.c @@ -69,9 +69,10 @@ static int bpy_bm_op_as_py_error(BMesh *bm) * \param htype Test \a value matches this type. * \param descr Description text. */ -static int bpy_slot_from_py_elem_check(BPy_BMElem *value, BMesh *bm, const char htype, - /* for error messages */ - const char *opname, const char *slot_name, const char *descr) +static int bpy_slot_from_py_elem_check( + BPy_BMElem *value, BMesh *bm, const char htype, + /* for error messages */ + const char *opname, const char *slot_name, const char *descr) { if (!BPy_BMElem_Check(value) || !(value->ele->head.htype & htype)) @@ -107,10 +108,11 @@ static int bpy_slot_from_py_elem_check(BPy_BMElem *value, BMesh *bm, const char * \param htype_bmo The type(s) supported by the target slot. * \param descr Description text. */ -static int bpy_slot_from_py_elemseq_check(BPy_BMGeneric *value, BMesh *bm, - const char htype_py, const char htype_bmo, - /* for error messages */ - const char *opname, const char *slot_name, const char *descr) +static int bpy_slot_from_py_elemseq_check( + BPy_BMGeneric *value, BMesh *bm, + const char htype_py, const char htype_bmo, + /* for error messages */ + const char *opname, const char *slot_name, const char *descr) { if (value->bm == NULL) { PyErr_Format(PyExc_TypeError, @@ -142,9 +144,10 @@ static int bpy_slot_from_py_elemseq_check(BPy_BMGeneric *value, BMesh *bm, /** * Use for giving py args to an operator. */ -static int bpy_slot_from_py(BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObject *value, - /* the are just for exception messages */ - const char *opname, const char *slot_name) +static int bpy_slot_from_py( + BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObject *value, + /* the are just for exception messages */ + const char *opname, const char *slot_name) { switch (slot->slot_type) { case BMO_OP_SLOT_BOOL: diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 0edca96404f..14fdada66bb 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -3757,10 +3757,11 @@ void bpy_bm_generic_invalidate(BPy_BMGeneric *self) * * The 'bm_r' value is assigned when empty, and used when set. */ -void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, - const char htype, - const bool do_unique_check, const bool do_bm_check, - const char *error_prefix) +void *BPy_BMElem_PySeq_As_Array( + BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, + const char htype, + const bool do_unique_check, const bool do_bm_check, + const char *error_prefix) { BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL; PyObject *seq_fast; diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h index 66059a642d1..630afcb32c0 100644 --- a/source/blender/python/bmesh/bmesh_py_types.h +++ b/source/blender/python/bmesh/bmesh_py_types.h @@ -158,10 +158,11 @@ PyObject *BPy_BMIter_CreatePyObject(BMesh *bm); PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele); /* just checks type and creates v/e/f/l */ -void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, - const char htype, - const bool do_unique_check, const bool do_bm_check, - const char *error_prefix); +void *BPy_BMElem_PySeq_As_Array( + BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, + const char htype, + const bool do_unique_check, const bool do_bm_check, + const char *error_prefix); PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len); PyObject *BPy_BMVert_Array_As_Tuple(BMesh *bm, BMVert **elem, Py_ssize_t elem_len); -- cgit v1.2.3 From 9eb191083ac79121a19ebc970575b10437f669f1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 25 Apr 2015 20:47:19 +1000 Subject: Fix neg-scaled project-paint in perspective mode --- source/blender/editors/sculpt_paint/paint_image_proj.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index d75b3f8ea3d..3ceaaff2f5d 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -1403,6 +1403,9 @@ static float project_paint_uvpixel_mask( viewDirPersp[1] = (ps->viewPos[1] - (w[0] * co1[1] + w[1] * co2[1] + w[2] * co3[1])); viewDirPersp[2] = (ps->viewPos[2] - (w[0] * co1[2] + w[1] * co2[2] + w[2] * co3[2])); normalize_v3(viewDirPersp); + if (UNLIKELY(ps->is_flip_object)) { + negate_v3(viewDirPersp); + } angle_cos = dot_v3v3(viewDirPersp, no); } @@ -3384,6 +3387,9 @@ static void proj_paint_state_vert_flags_init(ProjPaintState *ps) else { sub_v3_v3v3(viewDirPersp, ps->viewPos, mv->co); normalize_v3(viewDirPersp); + if (UNLIKELY(ps->is_flip_object)) { + negate_v3(viewDirPersp); + } if (dot_v3v3(viewDirPersp, no) <= ps->normal_angle__cos) { /* 1 vert of this face is towards us */ ps->vertFlags[a] |= PROJ_VERT_CULL; } -- cgit v1.2.3 From 01dda9a434f393fbd6787e9d1c3baf21374151e4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 25 Apr 2015 21:14:55 +1000 Subject: correct own error in recent ngon creation edit --- source/blender/bmesh/intern/bmesh_construct.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index 40fb24947d3..fb7f936318b 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -158,16 +158,18 @@ static bool bm_edges_sort_winding( } /* find first edge */ + i = 0; v_iter = v1; e_iter = e_first = v1->e; do { if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF) && (BM_edge_other_vert(e_iter, v_iter) == v2)) { + i = 1; break; } } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first); - if (e_iter == e_first) { + if (i == 0) { goto error; } -- cgit v1.2.3 From 60c5a2f2d21da2373cccebe3de025440c16b44a6 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sat, 25 Apr 2015 23:49:17 +0200 Subject: Cycles: Add Mirror ball mapping to camera panorama options The projection code was already in place, so this just exposes the option. Differential Revision: https://developer.blender.org/D1079 --- intern/cycles/blender/addon/properties.py | 1 + intern/cycles/blender/blender_camera.cpp | 3 +++ intern/cycles/kernel/kernel_projection.h | 8 ++++++++ intern/cycles/kernel/kernel_types.h | 1 + 4 files changed, 13 insertions(+) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index a86f162ae5f..875b5d384e3 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -66,6 +66,7 @@ enum_panorama_types = ( ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions"), ('FISHEYE_EQUISOLID', "Fisheye Equisolid", "Similar to most fisheye modern lens, takes sensor dimensions into consideration"), + ('MIRRORBALL', "Mirror Ball", "Uses the mirror ball mapping"), ) enum_curve_primitives = ( diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index fffc46ec9a6..3d23b5ecea8 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -148,6 +148,9 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::RenderEngine b_e case 2: bcam->panorama_type = PANORAMA_FISHEYE_EQUISOLID; break; + case 3: + bcam->panorama_type = PANORAMA_MIRRORBALL; + break; case 0: default: bcam->panorama_type = PANORAMA_EQUIRECTANGULAR; diff --git a/intern/cycles/kernel/kernel_projection.h b/intern/cycles/kernel/kernel_projection.h index bd18fd21354..62922df3286 100644 --- a/intern/cycles/kernel/kernel_projection.h +++ b/intern/cycles/kernel/kernel_projection.h @@ -163,6 +163,10 @@ ccl_device float3 mirrorball_to_direction(float u, float v) dir.x = 2.0f*u - 1.0f; dir.z = 2.0f*v - 1.0f; + + if(dir.x*dir.x + dir.z*dir.z > 1.0f) + return make_float3(0.0f, 0.0f, 0.0f); + dir.y = -sqrtf(max(1.0f - dir.x*dir.x - dir.z*dir.z, 0.0f)); /* reflection */ @@ -191,6 +195,8 @@ ccl_device float3 panorama_to_direction(KernelGlobals *kg, float u, float v) switch(kernel_data.cam.panorama_type) { case PANORAMA_EQUIRECTANGULAR: return equirectangular_range_to_direction(u, v, kernel_data.cam.equirectangular_range); + case PANORAMA_MIRRORBALL: + return mirrorball_to_direction(u, v); case PANORAMA_FISHEYE_EQUIDISTANT: return fisheye_to_direction(u, v, kernel_data.cam.fisheye_fov); case PANORAMA_FISHEYE_EQUISOLID: @@ -205,6 +211,8 @@ ccl_device float2 direction_to_panorama(KernelGlobals *kg, float3 dir) switch(kernel_data.cam.panorama_type) { case PANORAMA_EQUIRECTANGULAR: return direction_to_equirectangular_range(dir, kernel_data.cam.equirectangular_range); + case PANORAMA_MIRRORBALL: + return direction_to_mirrorball(dir); case PANORAMA_FISHEYE_EQUIDISTANT: return direction_to_fisheye(dir, kernel_data.cam.fisheye_fov); case PANORAMA_FISHEYE_EQUISOLID: diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 238b4b0bfdc..05cfb0adc71 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -426,6 +426,7 @@ enum CameraType { enum PanoramaType { PANORAMA_EQUIRECTANGULAR, + PANORAMA_MIRRORBALL, PANORAMA_FISHEYE_EQUIDISTANT, PANORAMA_FISHEYE_EQUISOLID }; -- cgit v1.2.3 From 8dd055cd47073adccb0b596384b8e642c9d0777d Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sun, 26 Apr 2015 00:06:38 +0200 Subject: Cleanup: Update Lookup table comments. --- intern/cycles/render/shader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index fba908ee447..496fd0f0cb9 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -392,9 +392,10 @@ void ShaderManager::device_update_common(Device *device, device->tex_alloc("__shader_flag", dscene->shader_flag); - /* blackbody lookup table */ + /* lookup tables */ KernelTables *ktables = &dscene->data.tables; + /* blackbody lookup table */ if(has_converter_blackbody && blackbody_table_offset == TABLE_OFFSET_INVALID) { if(blackbody_table.size() == 0) { thread_scoped_lock lock(lookup_table_mutex); -- cgit v1.2.3 From bc160d8a85e58f6bc2dd60b318bfd236e4a4a61e Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sun, 26 Apr 2015 00:42:26 +0200 Subject: Cleanup: Code style. --- intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h | 2 +- intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h | 4 ++-- intern/cycles/kernel/closure/bsdf_microfacet.h | 16 ++++++++-------- intern/cycles/kernel/osl/osl_closures.h | 8 ++++---- intern/cycles/render/camera.cpp | 4 ++-- intern/cycles/render/graph.cpp | 2 +- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h index dec09e00395..8d7d533d6f8 100644 --- a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h @@ -70,7 +70,7 @@ ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, c float out = 0.0f; if(fmaxf(sc->data0, sc->data1) <= 1e-4f) - return make_float3(0, 0, 0); + return make_float3(0.0f, 0.0f, 0.0f); if(NdotI > 0.0f && NdotO > 0.0f) { NdotI = fmaxf(NdotI, 1e-6f); diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h index 0b6ce3c7030..f1a26650078 100644 --- a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h @@ -59,7 +59,7 @@ ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderClosure *sc, co float cosHO = fabsf(dot(I, H)); if(!(fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f)) - return make_float3(0, 0, 0); + return make_float3(0.0f, 0.0f, 0.0f); float cosNHdivHO = cosNH / cosHO; cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f); @@ -80,7 +80,7 @@ ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderClosure *sc, co return make_float3(out, out, out); } - return make_float3(0, 0, 0); + return make_float3(0.0f, 0.0f, 0.0f); } ccl_device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index 32cf36abd27..ca68b1eb940 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -277,7 +277,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons float3 N = sc->N; if(m_refractive || fmaxf(alpha_x, alpha_y) <= 1e-4f) - return make_float3(0, 0, 0); + return make_float3(0.0f, 0.0f, 0.0f); float cosNO = dot(N, I); float cosNI = dot(N, omega_in); @@ -356,7 +356,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons return make_float3(out, out, out); } - return make_float3(0, 0, 0); + return make_float3(0.0f, 0.0f, 0.0f); } ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) @@ -368,13 +368,13 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con float3 N = sc->N; if(!m_refractive || fmaxf(alpha_x, alpha_y) <= 1e-4f) - return make_float3(0, 0, 0); + return make_float3(0.0f, 0.0f, 0.0f); float cosNO = dot(N, I); float cosNI = dot(N, omega_in); if(cosNO <= 0 || cosNI >= 0) - return make_float3(0, 0, 0); /* vectors on same side -- not possible */ + return make_float3(0.0f, 0.0f, 0.0f); /* vectors on same side -- not possible */ /* compute half-vector of the refraction (eq. 16) */ float3 ht = -(m_eta * omega_in + I); @@ -627,7 +627,7 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc, float3 N = sc->N; if(m_refractive || fmaxf(alpha_x, alpha_y) <= 1e-4f) - return make_float3(0, 0, 0); + return make_float3(0.0f, 0.0f, 0.0f); float cosNO = dot(N, I); float cosNI = dot(N, omega_in); @@ -709,7 +709,7 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc, return make_float3(out, out, out); } - return make_float3(0, 0, 0); + return make_float3(0.0f, 0.0f, 0.0f); } ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) @@ -721,13 +721,13 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc float3 N = sc->N; if(!m_refractive || fmaxf(alpha_x, alpha_y) <= 1e-4f) - return make_float3(0, 0, 0); + return make_float3(0.0f, 0.0f, 0.0f); float cosNO = dot(N, I); float cosNI = dot(N, omega_in); if(cosNO <= 0 || cosNI >= 0) - return make_float3(0, 0, 0); + return make_float3(0.0f, 0.0f, 0.0f); /* compute half-vector of the refraction (eq. 16) */ float3 ht = -(m_eta * omega_in + I); diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h index 5e833d738d8..ef67ef52fc0 100644 --- a/intern/cycles/kernel/osl/osl_closures.h +++ b/intern/cycles/kernel/osl/osl_closures.h @@ -147,14 +147,14 @@ public: \ \ float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const \ { \ - pdf = 0; \ - return make_float3(0, 0, 0); \ + pdf = 0.0f; \ + return make_float3(0.0f, 0.0f, 0.0f); \ } \ \ float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const \ { \ - pdf = 0; \ - return make_float3(0, 0, 0); \ + pdf = 0.0f; \ + return make_float3(0.0f, 0.0f, 0.0f); \ } \ \ int sample(const float3 &Ng, \ diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 65953a41be8..8a4eaf63414 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -162,8 +162,8 @@ void Camera::update() transform_perspective(&rastertocamera, make_float3(0, 0, 0)); } else { - dx = make_float3(0, 0, 0); - dy = make_float3(0, 0, 0); + dx = make_float3(0.0f, 0.0f, 0.0f); + dy = make_float3(0.0f, 0.0f, 0.0f); } dx = transform_direction(&cameratoworld, dx); diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index b63a7c1bc68..b36cbb5ea6f 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -33,7 +33,7 @@ ShaderInput::ShaderInput(ShaderNode *parent_, const char *name_, ShaderSocketTyp name = name_; type = type_; link = NULL; - value = make_float3(0, 0, 0); + value = make_float3(0.0f, 0.0f, 0.0f); stack_offset = SVM_STACK_INVALID; default_value = NONE; usage = USE_ALL; -- cgit v1.2.3 From 3917e9f1f23a2c45c54a02ec8f18af92ca23d597 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 26 Apr 2015 17:14:15 +1000 Subject: Macro GENERIC_TYPE_ANY map many types to one value --- source/blender/blenlib/BLI_compiler_typecheck.h | 299 ++++++++++++++++++++++++ 1 file changed, 299 insertions(+) diff --git a/source/blender/blenlib/BLI_compiler_typecheck.h b/source/blender/blenlib/BLI_compiler_typecheck.h index 652c4a954b9..b9fb3ebf47a 100644 --- a/source/blender/blenlib/BLI_compiler_typecheck.h +++ b/source/blender/blenlib/BLI_compiler_typecheck.h @@ -381,4 +381,303 @@ # define CHECK_TYPE_ANY(...) (void)0 #endif + +/** + * GENERIC_TYPE_ANY: handy macro to reuse a single expression for multiple types, eg: + * + * \code{.c} + * _Generic(value, + * GENERIC_TYPE_ANY(result_a, Foo *, Bar *, Baz *), + * GENERIC_TYPE_ANY(result_b, Spam *, Spaz *, Spot *), + * ) + * \endcode + * + * excuse ridiculously long generated args. + * \code{.py} + * for i in range(63): + * args = [(chr(ord('a') + (c % 26)) + (chr(ord('0') + (c // 26)))) for c in range(i + 1)] + * print("#define _VA_GENERIC_TYPE_ANY%d(r, %s) \\" % (i + 2, ", ".join(args))) + * print(" %s: r " % (": r, ".join(args))) + * \endcode + */ +#define _VA_GENERIC_TYPE_ANY2(r, a0) \ + a0: r +#define _VA_GENERIC_TYPE_ANY3(r, a0, b0) \ + a0: r, b0: r +#define _VA_GENERIC_TYPE_ANY4(r, a0, b0, c0) \ + a0: r, b0: r, c0: r +#define _VA_GENERIC_TYPE_ANY5(r, a0, b0, c0, d0) \ + a0: r, b0: r, c0: r, d0: r +#define _VA_GENERIC_TYPE_ANY6(r, a0, b0, c0, d0, e0) \ + a0: r, b0: r, c0: r, d0: r, e0: r +#define _VA_GENERIC_TYPE_ANY7(r, a0, b0, c0, d0, e0, f0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r +#define _VA_GENERIC_TYPE_ANY8(r, a0, b0, c0, d0, e0, f0, g0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r +#define _VA_GENERIC_TYPE_ANY9(r, a0, b0, c0, d0, e0, f0, g0, h0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r +#define _VA_GENERIC_TYPE_ANY10(r, a0, b0, c0, d0, e0, f0, g0, h0, i0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r +#define _VA_GENERIC_TYPE_ANY11(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r +#define _VA_GENERIC_TYPE_ANY12(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r +#define _VA_GENERIC_TYPE_ANY13(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r +#define _VA_GENERIC_TYPE_ANY14(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r +#define _VA_GENERIC_TYPE_ANY15(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r +#define _VA_GENERIC_TYPE_ANY16(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r +#define _VA_GENERIC_TYPE_ANY17(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r +#define _VA_GENERIC_TYPE_ANY18(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r +#define _VA_GENERIC_TYPE_ANY19(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r +#define _VA_GENERIC_TYPE_ANY20(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r +#define _VA_GENERIC_TYPE_ANY21(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r +#define _VA_GENERIC_TYPE_ANY22(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r +#define _VA_GENERIC_TYPE_ANY23(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r +#define _VA_GENERIC_TYPE_ANY24(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r +#define _VA_GENERIC_TYPE_ANY25(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r +#define _VA_GENERIC_TYPE_ANY26(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r +#define _VA_GENERIC_TYPE_ANY27(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r +#define _VA_GENERIC_TYPE_ANY28(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r +#define _VA_GENERIC_TYPE_ANY29(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r +#define _VA_GENERIC_TYPE_ANY30(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r +#define _VA_GENERIC_TYPE_ANY31(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r +#define _VA_GENERIC_TYPE_ANY32(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r +#define _VA_GENERIC_TYPE_ANY33(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r +#define _VA_GENERIC_TYPE_ANY34(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r +#define _VA_GENERIC_TYPE_ANY35(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r +#define _VA_GENERIC_TYPE_ANY36(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r +#define _VA_GENERIC_TYPE_ANY37(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r +#define _VA_GENERIC_TYPE_ANY38(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r +#define _VA_GENERIC_TYPE_ANY39(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r +#define _VA_GENERIC_TYPE_ANY40(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r +#define _VA_GENERIC_TYPE_ANY41(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r +#define _VA_GENERIC_TYPE_ANY42(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r +#define _VA_GENERIC_TYPE_ANY43(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r +#define _VA_GENERIC_TYPE_ANY44(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r +#define _VA_GENERIC_TYPE_ANY45(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r +#define _VA_GENERIC_TYPE_ANY46(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r +#define _VA_GENERIC_TYPE_ANY47(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r +#define _VA_GENERIC_TYPE_ANY48(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r +#define _VA_GENERIC_TYPE_ANY49(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r +#define _VA_GENERIC_TYPE_ANY50(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r +#define _VA_GENERIC_TYPE_ANY51(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r +#define _VA_GENERIC_TYPE_ANY52(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r +#define _VA_GENERIC_TYPE_ANY53(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r +#define _VA_GENERIC_TYPE_ANY54(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r +#define _VA_GENERIC_TYPE_ANY55(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r +#define _VA_GENERIC_TYPE_ANY56(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r +#define _VA_GENERIC_TYPE_ANY57(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r +#define _VA_GENERIC_TYPE_ANY58(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2, e2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r +#define _VA_GENERIC_TYPE_ANY59(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2, e2, f2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r +#define _VA_GENERIC_TYPE_ANY60(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r +#define _VA_GENERIC_TYPE_ANY61(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r +#define _VA_GENERIC_TYPE_ANY62(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, i2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r, i2: r +#define _VA_GENERIC_TYPE_ANY63(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, i2, j2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r, i2: r, j2: r +#define _VA_GENERIC_TYPE_ANY64(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, i2, j2, k2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r, i2: r, j2: r, k2: r + +# define GENERIC_TYPE_ANY(...) VA_NARGS_CALL_OVERLOAD(_VA_GENERIC_TYPE_ANY, __VA_ARGS__) + #endif /* __BLI_COMPILER_TYPECHECK_H__ */ -- cgit v1.2.3 From 12e7c7f674599e7eba6adfe7247ed28e6fdf348a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 26 Apr 2015 17:15:34 +1000 Subject: BMesh: BM_ELEM_CD_GET_VOID_P cast removed const --- source/blender/bmesh/bmesh_class.h | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index 120ff4997dc..10048a16590 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -256,11 +256,26 @@ enum { #define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE) #define BM_ALL_NOLOOP (BM_VERT | BM_EDGE | BM_FACE) +/* args for _Generic */ +#define _BM_GENERIC_TYPE_ELEM_NONCONST \ + void *, BMVert *, BMEdge *, BMLoop *, BMFace *, \ + BMElem *, BMElemF *, BMHeader * + +#define _BM_GENERIC_TYPE_ELEM_CONST \ + const void *, const BMVert *, const BMEdge *, const BMLoop *, const BMFace *, \ + const BMElem *, const BMElemF *, const BMHeader * + +#define BM_CHECK_TYPE_ELEM_CONST(ele) \ + CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPES_CONST) + +#define BM_CHECK_TYPE_ELEM_NONCONST(ele) \ + CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST) + #define BM_CHECK_TYPE_ELEM(ele) \ - CHECK_TYPE_ANY(ele, void *, BMFace *, BMEdge *, BMVert *, BMLoop *, BMElem *, BMElemF *, BMHeader *) + CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST, _BM_GENERIC_TYPE_ELEM_CONST) #define BM_CHECK_TYPE_ELEM_ASSIGN(ele) \ - (BM_CHECK_TYPE_ELEM(ele), CHECK_TYPE_NONCONST(ele)), ele + (BM_CHECK_TYPE_ELEM(ele)), ele /* BMHeader->hflag (char) */ enum { @@ -297,8 +312,17 @@ typedef bool (*BMElemFilterFunc)(BMElem *, void *user_data); #define BM_ELEM_CD_GET_INT(ele, offset) \ (assert(offset != -1), *((int *)((char *)(ele)->head.data + (offset)))) +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +#define BM_ELEM_CD_GET_VOID_P(ele, offset) \ + (assert(offset != -1), \ + _Generic(ele, \ + GENERIC_TYPE_ANY( POINTER_OFFSET((ele)->head.data, offset), _BM_GENERIC_TYPE_ELEM_NONCONST), \ + GENERIC_TYPE_ANY((const void *)POINTER_OFFSET((ele)->head.data, offset), _BM_GENERIC_TYPE_ELEM_CONST)) \ + ) +#else #define BM_ELEM_CD_GET_VOID_P(ele, offset) \ (assert(offset != -1), (void *)((char *)(ele)->head.data + (offset))) +#endif #define BM_ELEM_CD_SET_FLOAT(ele, offset, f) { CHECK_TYPE_NONCONST(ele); \ assert(offset != -1); *((float *)((char *)(ele)->head.data + (offset))) = (f); } (void)0 -- cgit v1.2.3 From d33314393ebb7ce68ee599fb4f3e07bcb7983759 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 26 Apr 2015 17:19:23 +1000 Subject: BMesh: use const for API calls --- source/blender/bmesh/intern/bmesh_queries.c | 32 +++++++++++++------------- source/blender/bmesh/intern/bmesh_queries.h | 20 ++++++++-------- source/blender/bmesh/operators/bmo_subdivide.c | 6 +++-- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 0ed5391ed2c..1e0b1f21381 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -501,10 +501,10 @@ bool BM_verts_in_face(BMVert **varr, int len, BMFace *f) /** * Returns whether or not a given edge is part of a given face. */ -bool BM_edge_in_face(BMEdge *e, BMFace *f) +bool BM_edge_in_face(const BMEdge *e, const BMFace *f) { if (e->l) { - BMLoop *l_iter, *l_first; + const BMLoop *l_iter, *l_first; l_iter = l_first = e->l; do { @@ -1221,7 +1221,7 @@ bool BM_loop_is_convex(const BMLoop *l) * * \return angle in radians */ -float BM_loop_calc_face_angle(BMLoop *l) +float BM_loop_calc_face_angle(const BMLoop *l) { return angle_v3v3v3(l->prev->v->co, l->v->co, @@ -1236,7 +1236,7 @@ float BM_loop_calc_face_angle(BMLoop *l) * \param l The loop to calculate the normal at * \param r_normal Resulting normal */ -void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3]) +void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) { if (normal_tri_v3(r_normal, l->prev->v->co, @@ -1258,7 +1258,7 @@ void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3]) * \param l The loop to calculate the direction at * \param r_dir Resulting direction */ -void BM_loop_calc_face_direction(BMLoop *l, float r_dir[3]) +void BM_loop_calc_face_direction(const BMLoop *l, float r_dir[3]) { float v_prev[3]; float v_next[3]; @@ -1282,7 +1282,7 @@ void BM_loop_calc_face_direction(BMLoop *l, float r_dir[3]) * \param l The loop to calculate the tangent at * \param r_tangent Resulting tangent */ -void BM_loop_calc_face_tangent(BMLoop *l, float r_tangent[3]) +void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]) { float v_prev[3]; float v_next[3]; @@ -1394,7 +1394,7 @@ void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_ta * * \returns the angle in radians */ -float BM_vert_calc_edge_angle_ex(BMVert *v, const float fallback) +float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback) { BMEdge *e1, *e2; @@ -1416,7 +1416,7 @@ float BM_vert_calc_edge_angle_ex(BMVert *v, const float fallback) } } -float BM_vert_calc_edge_angle(BMVert *v) +float BM_vert_calc_edge_angle(const BMVert *v) { return BM_vert_calc_edge_angle_ex(v, DEG2RADF(90.0f)); } @@ -1425,14 +1425,14 @@ float BM_vert_calc_edge_angle(BMVert *v) * \note this isn't optimal to run on an array of verts, * see 'solidify_add_thickness' for a function which runs on an array. */ -float BM_vert_calc_shell_factor(BMVert *v) +float BM_vert_calc_shell_factor(const BMVert *v) { BMIter iter; BMLoop *l; float accum_shell = 0.0f; float accum_angle = 0.0f; - BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { + BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) { const float face_angle = BM_loop_calc_face_angle(l); accum_shell += shell_v3v3_normalized_to_dist(v->no, l->f->no) * face_angle; accum_angle += face_angle; @@ -1447,15 +1447,15 @@ float BM_vert_calc_shell_factor(BMVert *v) } /* alternate version of #BM_vert_calc_shell_factor which only * uses 'hflag' faces, but falls back to all if none found. */ -float BM_vert_calc_shell_factor_ex(BMVert *v, const float no[3], const char hflag) +float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag) { BMIter iter; - BMLoop *l; + const BMLoop *l; float accum_shell = 0.0f; float accum_angle = 0.0f; int tot_sel = 0, tot = 0; - BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { + BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) { if (BM_elem_flag_test(l->f, hflag)) { /* <-- main difference to BM_vert_calc_shell_factor! */ const float face_angle = BM_loop_calc_face_angle(l); accum_shell += shell_v3v3_normalized_to_dist(no, l->f->no) * face_angle; @@ -1484,15 +1484,15 @@ float BM_vert_calc_shell_factor_ex(BMVert *v, const float no[3], const char hfla * \note quite an obscure function. * used in bmesh operators that have a relative scale options, */ -float BM_vert_calc_mean_tagged_edge_length(BMVert *v) +float BM_vert_calc_mean_tagged_edge_length(const BMVert *v) { BMIter iter; BMEdge *e; int tot; float length = 0.0f; - BM_ITER_ELEM_INDEX (e, &iter, v, BM_EDGES_OF_VERT, tot) { - BMVert *v_other = BM_edge_other_vert(e, v); + BM_ITER_ELEM_INDEX (e, &iter, (BMVert *)v, BM_EDGES_OF_VERT, tot) { + const BMVert *v_other = BM_edge_other_vert(e, v); if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) { length += BM_edge_calc_length(e); } diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 2addcc9705d..e4f7c78bdc1 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -31,7 +31,7 @@ bool BM_vert_in_face(BMVert *v, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNU int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool BM_verts_in_face(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_edge_in_face(BMEdge *e, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_edge_in_face(const BMEdge *e, const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); @@ -96,10 +96,10 @@ BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_W float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_loop_calc_face_angle(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3]) ATTR_NONNULL(); -void BM_loop_calc_face_direction(BMLoop *l, float r_normal[3]); -void BM_loop_calc_face_tangent(BMLoop *l, float r_tangent[3]); +float BM_loop_calc_face_angle(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL(); +void BM_loop_calc_face_direction(const BMLoop *l, float r_normal[3]); +void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]); float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); float BM_edge_calc_face_angle(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); @@ -107,11 +107,11 @@ float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback) float BM_edge_calc_face_angle_signed(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3]) ATTR_NONNULL(); -float BM_vert_calc_edge_angle(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_vert_calc_edge_angle_ex(BMVert *v, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_vert_calc_shell_factor(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_vert_calc_shell_factor_ex(BMVert *v, const float no[3], const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_vert_calc_mean_tagged_edge_length(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_vert_calc_edge_angle(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_vert_calc_shell_factor(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_vert_calc_mean_tagged_edge_length(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *BM_face_find_shortest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *BM_face_find_longest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 003c27671a5..6c30cbb023a 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -163,8 +163,10 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v_a, BMVert *v_b, BMFace return NULL; } /* calculates offset for co, based on fractal, sphere or smooth settings */ -static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params, float perc, - BMVert *vsta, BMVert *vend) +static void alter_co( + BMVert *v, BMEdge *UNUSED(e_orig), + const SubDParams *params, const float perc, + const BMVert *vsta, const BMVert *vend) { float tvec[3], fac; float *co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp); -- cgit v1.2.3 From c2f7cffd56afffcceda11813a3dcc0a93d84673a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 26 Apr 2015 18:31:54 +1000 Subject: Add inverse-square falloff to bmesh, mask & compo. --- source/blender/blenkernel/intern/mask_rasterize.c | 3 +++ source/blender/bmesh/intern/bmesh_operators.h | 1 + source/blender/bmesh/intern/bmesh_queries.c | 3 +++ source/blender/compositor/operations/COM_BlurBaseOperation.cpp | 2 ++ source/blender/makesrna/intern/rna_scene.c | 1 + 5 files changed, 10 insertions(+) diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 387d093051e..13ec970c65c 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -1360,6 +1360,9 @@ float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float x case PROP_SHARP: value_layer = value_layer * value_layer; break; + case PROP_INVSQUARE: + value_layer = value_layer * (2.0f - value_layer); + break; case PROP_LIN: default: /* nothing */ diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index d2ce2faf09d..d9961e589da 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -46,6 +46,7 @@ enum { SUBD_FALLOFF_ROOT, SUBD_FALLOFF_SHARP, SUBD_FALLOFF_LIN, + SUBD_FALLOFF_INVSQUARE = 7, /* matching PROP_INVSQUARE */ }; enum { diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 1e0b1f21381..61328a525f1 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -2419,6 +2419,9 @@ float bmesh_subd_falloff_calc(const int falloff, float val) break; case SUBD_FALLOFF_LIN: break; + case SUBD_FALLOFF_INVSQUARE: + val = val * (2.0f - val); + break; default: BLI_assert(0); break; diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp index cbf9bb211c1..07669b1a814 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp @@ -133,6 +133,8 @@ float *BlurBaseOperation::make_dist_fac_inverse(float rad, int size, int falloff case PROP_SHARP: val = val * val; break; + case PROP_INVSQUARE: + val = val * (2.0f - val); case PROP_LIN: /* fall-through */ #ifndef NDEBUG diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index f67af39d381..f671a4b29e5 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -134,6 +134,7 @@ EnumPropertyItem proportional_falloff_curve_only_items[] = { {PROP_SMOOTH, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", "Smooth falloff"}, {PROP_SPHERE, "SPHERE", ICON_SPHERECURVE, "Sphere", "Spherical falloff"}, {PROP_ROOT, "ROOT", ICON_ROOTCURVE, "Root", "Root falloff"}, + {PROP_INVSQUARE, "INVERSE_SQUARE", ICON_ROOTCURVE, "Inverse Square", "Inverse Square falloff"}, {PROP_SHARP, "SHARP", ICON_SHARPCURVE, "Sharp", "Sharp falloff"}, {PROP_LIN, "LINEAR", ICON_LINCURVE, "Linear", "Linear falloff"}, {0, NULL, 0, NULL, NULL} -- cgit v1.2.3 From 6e02f1da74a52302a79dfdaaa96d207002399c25 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 26 Apr 2015 18:35:42 +1000 Subject: BMesh: use inverse-square falloff /w smooth-subdiv Resolves ugly artifacts with multi-cut. --- source/blender/editors/mesh/editmesh_tools.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 93ebbbcf620..614963111f3 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -96,7 +96,7 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op) } BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT, - smooth, SUBD_FALLOFF_ROOT, false, + smooth, SUBD_FALLOFF_INVSQUARE, false, fractal, along_normal, cuts, SUBDIV_SELECT_ORIG, RNA_enum_get(op->ptr, "quadcorner"), -- cgit v1.2.3 From e1ca127419fce5a717215d39ecfc6fdb040bbc84 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 26 Apr 2015 19:12:20 +1000 Subject: Cleanup: subdivide smooth vertex placement --- source/blender/bmesh/operators/bmo_subdivide.c | 33 +++++++++++++------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 6c30cbb023a..6a7b0ddf7ad 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -166,9 +166,8 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v_a, BMVert *v_b, BMFace static void alter_co( BMVert *v, BMEdge *UNUSED(e_orig), const SubDParams *params, const float perc, - const BMVert *vsta, const BMVert *vend) + const BMVert *v_a, const BMVert *v_b) { - float tvec[3], fac; float *co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp); int i; @@ -180,21 +179,19 @@ static void alter_co( } else if (params->use_smooth) { /* we calculate an offset vector vec1[], to be added to *co */ - float len, nor[3], nor1[3], nor2[3], val; + float dir[3], tvec[3]; + float fac, len, val; - sub_v3_v3v3(nor, vsta->co, vend->co); - len = 0.5f * normalize_v3(nor); - - copy_v3_v3(nor1, vsta->no); - copy_v3_v3(nor2, vend->no); + sub_v3_v3v3(dir, v_a->co, v_b->co); + len = 0.5f * normalize_v3(dir); /* cosine angle */ - fac = dot_v3v3(nor, nor1); - mul_v3_v3fl(tvec, nor1, fac); + fac = dot_v3v3(dir, v_a->no); + mul_v3_v3fl(tvec, v_a->no, fac); /* cosine angle */ - fac = -dot_v3v3(nor, nor2); - madd_v3_v3fl(tvec, nor2, fac); + fac = -dot_v3v3(dir, v_b->no); + madd_v3_v3fl(tvec, v_b->no, fac); /* falloff for multi subdivide */ val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc)); @@ -210,12 +207,13 @@ static void alter_co( } if (params->use_fractal) { - const float len = len_v3v3(vsta->co, vend->co); - float normal[3], co2[3], base1[3], base2[3]; + float normal[3], co2[3], base1[3], base2[3], tvec[3]; + const float len = len_v3v3(v_a->co, v_b->co); + float fac; fac = params->fractal * len; - mid_v3_v3v3(normal, vsta->no, vend->no); + mid_v3_v3v3(normal, v_a->no, v_b->no); ortho_basis_v3v3_v3(base1, base2, normal); add_v3_v3v3(co2, v->co, params->fractal_ofs); @@ -236,9 +234,12 @@ static void alter_co( * this by getting the normals and coords for each shape key and * re-calculate the smooth value for each but this is quite involved. * for now its ok to simply apply the difference IMHO - campbell */ - sub_v3_v3v3(tvec, v->co, co); if (params->shape_info.totlayer > 1) { + float tvec[3]; + + sub_v3_v3v3(tvec, v->co, co); + /* skip the last layer since its the temp */ i = params->shape_info.totlayer - 1; co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset); -- cgit v1.2.3 From 2374cb380b83ce97db5545eb0c4f3ccd51e87d9c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 26 Apr 2015 19:19:05 +1000 Subject: BMesh: subdiv smooth, use simpler even calculation Was checking all vertices adjacent faces, now just compare the difference between normal angles. Also default to inverse-square for loopcut-subdiv falloff. --- source/blender/bmesh/operators/bmo_subdivide.c | 2 +- source/blender/editors/mesh/editmesh_loopcut.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 6a7b0ddf7ad..306cdae49fe 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -198,7 +198,7 @@ static void alter_co( val = bmesh_subd_falloff_calc(params->smooth_falloff, val); if (params->use_smooth_even) { - val *= BM_vert_calc_shell_factor(v); + val *= shell_v3v3_mid_normalized_to_dist(v_a->no, v_b->no); } mul_v3_fl(tvec, params->smooth * val * len); diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 3d93210382c..a4ea2ab3921 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -835,7 +835,7 @@ void MESH_OT_loopcut(wmOperatorType *ot) prop = RNA_def_property(ot->srna, "falloff", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, proportional_falloff_curve_only_items); - RNA_def_property_enum_default(prop, PROP_ROOT); + RNA_def_property_enum_default(prop, PROP_INVSQUARE); RNA_def_property_ui_text(prop, "Falloff", "Falloff type the feather"); RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ -- cgit v1.2.3 From 2069187a1bd9483d435b1725bd2641e3fc049f63 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 26 Apr 2015 20:32:08 +1000 Subject: Cleanup: bmesh subdivide var names were a bit cryptic, set return arg last. --- source/blender/bmesh/operators/bmo_subdivide.c | 67 ++++++++++++++------------ 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 306cdae49fe..6f3f84a3f9b 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -253,19 +253,21 @@ static void alter_co( /* assumes in the edge is the correct interpolated vertices already */ /* percent defines the interpolation, rad and flag are for special options */ /* results in new vertex with correct coordinate, vertex normal and weight group info */ -static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, BMEdge *oedge, - const SubDParams *params, float percent, - float percent2, - BMEdge **out, BMVert *vsta, BMVert *vend) +static BMVert *bm_subdivide_edge_addvert( + BMesh *bm, BMEdge *edge, BMEdge *e_orig, + const SubDParams *params, + const float factor_edge_split, const float factor_subd, + BMVert *v_a, BMVert *v_b, + BMEdge **r_edge) { - BMVert *ev; + BMVert *v_new; - ev = BM_edge_split(bm, edge, edge->v1, out, percent); + v_new = BM_edge_split(bm, edge, edge->v1, r_edge, factor_edge_split); - BMO_elem_flag_enable(bm, ev, ELE_INNER); + BMO_elem_flag_enable(bm, v_new, ELE_INNER); /* offset for smooth or sphere or fractal */ - alter_co(ev, oedge, params, percent2, vsta, vend); + alter_co(v_new, e_orig, params, factor_subd, v_a, v_b); #if 0 //BMESH_TODO /* clip if needed by mirror modifier */ @@ -282,35 +284,40 @@ static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, BMEdge *oedge, } #endif - interp_v3_v3v3(ev->no, vsta->no, vend->no, percent2); - normalize_v3(ev->no); + interp_v3_v3v3(v_new->no, v_a->no, v_b->no, factor_subd); + normalize_v3(v_new->no); - return ev; + return v_new; } -static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge, - int curpoint, int totpoint, const SubDParams *params, - BMEdge **newe, BMVert *vsta, BMVert *vend) +static BMVert *subdivide_edge_num( + BMesh *bm, BMEdge *edge, BMEdge *e_orig, + int curpoint, int totpoint, const SubDParams *params, + BMVert *v_a, BMVert *v_b, + BMEdge **r_edge) { - BMVert *ev; - float percent, percent2 = 0.0f; + BMVert *v_new; + float factor_edge_split, factor_subd; if (BMO_elem_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) { - percent = BMO_slot_map_float_get(params->slot_edge_percents, edge); + factor_edge_split = BMO_slot_map_float_get(params->slot_edge_percents, edge); + factor_subd = 0.0f; } else { - percent = 1.0f / (float)(totpoint + 1 - curpoint); - percent2 = (float)(curpoint + 1) / (float)(totpoint + 1); - + factor_edge_split = 1.0f / (float)(totpoint + 1 - curpoint); + factor_subd = (float)(curpoint + 1) / (float)(totpoint + 1); } - ev = bm_subdivide_edge_addvert(bm, edge, oedge, params, percent, - percent2, newe, vsta, vend); - return ev; + v_new = bm_subdivide_edge_addvert( + bm, edge, e_orig, params, + factor_edge_split, factor_subd, + v_a, v_b, r_edge); + return v_new; } -static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *params, - BMVert *vsta, BMVert *vend) +static void bm_subdivide_multicut( + BMesh *bm, BMEdge *edge, const SubDParams *params, + BMVert *v_a, BMVert *v_b) { BMEdge *eed = edge, *e_new, e_tmp = *edge; BMVert *v, v1_tmp = *edge->v1, v2_tmp = *edge->v2, *v1 = edge->v1, *v2 = edge->v2; @@ -320,7 +327,7 @@ static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *par e_tmp.v2 = &v2_tmp; for (i = 0; i < numcuts; i++) { - v = subdivideedgenum(bm, eed, &e_tmp, i, params->numcuts, params, &e_new, vsta, vend); + v = subdivide_edge_num(bm, eed, &e_tmp, i, params->numcuts, params, v_a, v_b, &e_new); BMO_elem_flag_enable(bm, v, SUBD_SPLIT | ELE_SPLIT); BMO_elem_flag_enable(bm, eed, SUBD_SPLIT | ELE_SPLIT); @@ -437,7 +444,7 @@ static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert * e = connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new); e_tmp = *e; - v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, &e_new, e->v1, e->v2); + v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, e->v1, e->v2, &e_new); if (i != numcuts - 1) { connect_smallest_face(bm, v_last, v, &f_new); @@ -580,8 +587,7 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts e_tmp = *e; for (a = 0; a < numcuts; a++) { - v = subdivideedgenum(bm, e, &e_tmp, a, numcuts, params, &e_new, - v1, v2); + v = subdivide_edge_num(bm, e, &e_tmp, a, numcuts, params, v1, v2, &e_new); BMESH_ASSERT(v != NULL); @@ -688,8 +694,7 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, e_tmp.v1 = &v1_tmp; e_tmp.v2 = &v2_tmp; for (j = 0; j < i; j++) { - v = subdivideedgenum(bm, e, &e_tmp, j, i, params, &e_new, - verts[a], verts[b]); + v = subdivide_edge_num(bm, e, &e_tmp, j, i, params, verts[a], verts[b], &e_new); lines[i + 1][j + 1] = v; BMO_elem_flag_enable(bm, e_new, ELE_INNER); -- cgit v1.2.3 From 3524676036c370822344f1c80b191d34644b3745 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 26 Apr 2015 21:20:25 +1000 Subject: BMesh: increase subdiv smooth strength Now 1.0 gives near spherical output --- source/blender/bmesh/operators/bmo_subdivide.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 6f3f84a3f9b..410da65f828 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -183,7 +183,7 @@ static void alter_co( float fac, len, val; sub_v3_v3v3(dir, v_a->co, v_b->co); - len = 0.5f * normalize_v3(dir); + len = M_SQRT1_2 * normalize_v3(dir); /* cosine angle */ fac = dot_v3v3(dir, v_a->no); -- cgit v1.2.3 From 5efbd2a4076af7de8d4c9256ff8f6aacbfa6b49f Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Sun, 26 Apr 2015 16:29:43 +0200 Subject: BGE : addObject in python without reference object. Making the reference argument optional for the addObject function. ``` scene.addObject("Cube") ``` This allows to keep the rotation, scale and position of the original object. To avoid layer problems with lights if the reference arguments is None, the new object have the same layer than the active layers in scene. Reviewers: lordloki, moguri, hg1, sybren Reviewed By: hg1, sybren Subscribers: agoose77 Projects: #game_engine Differential Revision: https://developer.blender.org/D1222 --- .../rst/bge_types/bge.types.KX_Scene.rst | 4 +- source/gameengine/Ketsji/KX_GameObject.h | 2 +- source/gameengine/Ketsji/KX_Light.cpp | 1 + source/gameengine/Ketsji/KX_Light.h | 2 +- source/gameengine/Ketsji/KX_Scene.cpp | 54 ++++++++++------------ 5 files changed, 30 insertions(+), 33 deletions(-) diff --git a/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst b/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst index f4846cd9265..5bd8e3a77de 100644 --- a/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst +++ b/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst @@ -143,9 +143,9 @@ base class --- :class:`PyObjectPlus` :arg object: The (name of the) object to add. :type object: :class:`KX_GameObject` or string - :arg reference: The (name of the) object which position, orientation, and scale to copy. + :arg reference: The (name of the) object which position, orientation, and scale to copy (optional), if the object to add is a light and there is not reference the light's layer will be the same that the active layer in the blender scene. :type reference: :class:`KX_GameObject` or string - :arg time: The lifetime of the added object, in frames. A time of 0 means the object will last forever. + :arg time: The lifetime of the added object, in frames. A time of 0 means the object will last forever (optional). :type time: integer :return: The newly added object. :rtype: :class:`KX_GameObject` diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 73dcae5a1a8..9b85572bec2 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -914,7 +914,7 @@ public: * Change the layer of the object (when it is added in another layer * than the original layer) */ - void + virtual void SetLayer( int l ); diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index d6b84e98aec..0dec5715588 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -108,6 +108,7 @@ void KX_LightObject::UpdateScene(KX_Scene *kxscene) void KX_LightObject::SetLayer(int layer) { + KX_GameObject::SetLayer(layer); m_lightobj->m_layer = layer; } diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index 386f8e95789..3a58584223d 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -60,7 +60,7 @@ public: RAS_ILightObject* GetLightData() { return m_lightobj;} void UpdateScene(class KX_Scene *kxscene); - void SetLayer(int layer); + virtual void SetLayer(int layer); virtual int GetGameObjectType() { return OBJ_LIGHT; } diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index ca4d017fe8c..a460d9bd392 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -835,12 +835,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) (*git)->Relink(&m_map_gameobject_to_replica); // add the object in the layer of the parent (*git)->SetLayer(groupobj->GetLayer()); - // If the object was a light, we need to update it's RAS_LightObject as well - if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) - { - KX_LightObject* lightobj = static_cast(*git); - lightobj->SetLayer(groupobj->GetLayer()); - } } // replicate crosslinks etc. between logic bricks @@ -916,18 +910,20 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, replica->GetSGNode()->AddChild(childreplicanode); } - // At this stage all the objects in the hierarchy have been duplicated, - // we can update the scenegraph, we need it for the duplication of logic - MT_Point3 newpos = referenceobj->NodeGetWorldPosition(); - replica->NodeSetLocalPosition(newpos); + if (referenceobj) { + // At this stage all the objects in the hierarchy have been duplicated, + // we can update the scenegraph, we need it for the duplication of logic + MT_Point3 newpos = referenceobj->NodeGetWorldPosition(); + replica->NodeSetLocalPosition(newpos); + + MT_Matrix3x3 newori = referenceobj->NodeGetWorldOrientation(); + replica->NodeSetLocalOrientation(newori); - MT_Matrix3x3 newori = referenceobj->NodeGetWorldOrientation(); - replica->NodeSetLocalOrientation(newori); - - // get the rootnode's scale - MT_Vector3 newscale = referenceobj->GetSGNode()->GetRootSGParent()->GetLocalScale(); - // set the replica's relative scale with the rootnode's scale - replica->NodeSetRelativeScale(newscale); + // get the rootnode's scale + MT_Vector3 newscale = referenceobj->GetSGNode()->GetRootSGParent()->GetLocalScale(); + // set the replica's relative scale with the rootnode's scale + replica->NodeSetRelativeScale(newscale); + } replica->GetSGNode()->UpdateWorldData(0); replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox()); @@ -947,13 +943,13 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, { // this will also relink the actuators in the hierarchy (*git)->Relink(&m_map_gameobject_to_replica); - // add the object in the layer of the reference object - (*git)->SetLayer(referenceobj->GetLayer()); - // If the object was a light, we need to update it's RAS_LightObject as well - if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) - { - KX_LightObject* lightobj = static_cast(*git); - lightobj->SetLayer(referenceobj->GetLayer()); + if (referenceobj) { + // add the object in the layer of the reference object + (*git)->SetLayer(referenceobj->GetLayer()); + } + else { + // We don't know what layer set, so we set all visible layers in the blender scene. + (*git)->SetLayer(m_blenderScene->lay); } } @@ -2503,23 +2499,23 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject, "addObject(object, other, time=0)\n" "Returns the added object.\n") { - PyObject *pyob, *pyreference; + PyObject *pyob, *pyreference = Py_None; KX_GameObject *ob, *reference; int time = 0; - if (!PyArg_ParseTuple(args, "OO|i:addObject", &pyob, &pyreference, &time)) + if (!PyArg_ParseTuple(args, "O|Oi:addObject", &pyob, &pyreference, &time)) return NULL; - if ( !ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, reference, time): KX_Scene (first argument)") || - !ConvertPythonToGameObject(pyreference, &reference, false, "scene.addObject(object, reference, time): KX_Scene (second argument)") ) + if (!ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, reference, time): KX_Scene (first argument)") || + !ConvertPythonToGameObject(pyreference, &reference, true, "scene.addObject(object, reference, time): KX_Scene (second argument)")) return NULL; if (!m_inactivelist->SearchValue(ob)) { PyErr_Format(PyExc_ValueError, "scene.addObject(object, reference, time): KX_Scene (first argument): object must be in an inactive layer"); return NULL; } - SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, reference, time); + SCA_IObject *replica = AddReplicaObject((SCA_IObject*)ob, reference, time); // release here because AddReplicaObject AddRef's // the object is added to the scene so we don't want python to own a reference -- cgit v1.2.3 From cf366c8b6686bae79aeccbdecdbef2472ff77923 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 27 Apr 2015 01:17:51 +1000 Subject: UI: 'View Online Manual' Shortcut D1031, implement proposal T37478 to give easy access to the online manual. Use Alt+F1 while hovering over a button/setting. --- source/blender/editors/include/UI_interface.h | 8 +++++ .../blender/editors/interface/interface_handlers.c | 35 ++-------------------- source/blender/editors/interface/interface_utils.c | 31 +++++++++++++++++++ source/blender/windowmanager/intern/wm_operators.c | 35 ++++++++++++++++++++++ 4 files changed, 77 insertions(+), 32 deletions(-) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 66b946811ea..1e0cc972ef8 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -483,6 +483,14 @@ bool UI_but_active_only(const struct bContext *C, struct ARegion *ar, uiBlock void UI_but_execute(const struct bContext *C, uiBut *but); +bool UI_but_online_manual_id( + const uiBut *but, + char *r_str, size_t maxlength) + ATTR_WARN_UNUSED_RESULT; +bool UI_but_online_manual_id_from_active( + const struct bContext *C, + char *r_str, size_t maxlength) + ATTR_WARN_UNUSED_RESULT; /* Buttons * diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 57a26ce62ec..1d71a5db350 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -6253,14 +6253,9 @@ static bool ui_but_menu(bContext *C, uiBut *but) char buf[512]; PointerRNA ptr_props; - if (but->rnapoin.data && but->rnaprop) { - BLI_snprintf(buf, sizeof(buf), "%s.%s", - RNA_struct_identifier(but->rnapoin.type), RNA_property_identifier(but->rnaprop)); - - WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual"); - RNA_string_set(&ptr_props, "doc_id", buf); - uiItemFullO(layout, "WM_OT_doc_view_manual", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"), - ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0); + if (UI_but_online_manual_id(but, buf, sizeof(buf))) { + uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"), + ICON_NONE, "WM_OT_doc_view_manual_ui_context"); WM_operator_properties_create(&ptr_props, "WM_OT_doc_view"); RNA_string_set(&ptr_props, "doc_id", buf); @@ -6274,30 +6269,6 @@ static bool ui_but_menu(bContext *C, uiBut *but) RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop)); uiItemFullO(layout, "WM_OT_doc_edit", "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0); -#endif - } - else if (but->optype) { - WM_operator_py_idname(buf, but->optype->idname); - - - WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual"); - RNA_string_set(&ptr_props, "doc_id", buf); - uiItemFullO(layout, "WM_OT_doc_view_manual", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"), - ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0); - - WM_operator_properties_create(&ptr_props, "WM_OT_doc_view"); - RNA_string_set(&ptr_props, "doc_id", buf); - uiItemFullO(layout, "WM_OT_doc_view", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"), - ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0); - - /* XXX inactive option, not for public! */ -#if 0 - WM_operator_properties_create(&ptr_props, "WM_OT_doc_edit"); - RNA_string_set(&ptr_props, "doc_id", buf); - RNA_string_set(&ptr_props, "doc_new", but->optype->description); - - uiItemFullO(layout, "WM_OT_doc_edit", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Submit Description"), - ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0); #endif } } diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 28bd637ae59..14d97dd883e 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -52,6 +52,9 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "WM_api.h" +#include "WM_types.h" + #include "interface_intern.h" @@ -309,6 +312,34 @@ int UI_calc_float_precision(int prec, double value) return prec; } +bool UI_but_online_manual_id(const uiBut *but, char *r_str, size_t maxlength) +{ + if (but->rnapoin.id.data && but->rnapoin.data && but->rnaprop) { + BLI_snprintf(r_str, maxlength, "%s.%s", RNA_struct_identifier(but->rnapoin.type), + RNA_property_identifier(but->rnaprop)); + return true; + } + else if (but->optype) { + WM_operator_py_idname(r_str, but->optype->idname); + return true; + } + + *r_str = '\0'; + return false; +} + +bool UI_but_online_manual_id_from_active(const struct bContext *C, char *r_str, size_t maxlength) +{ + uiBut *but = UI_context_active_but_get(C); + + if (but) { + return UI_but_online_manual_id(but, r_str, maxlength); + } + + *r_str = '\0'; + return false; +} + /* -------------------------------------------------------------------- */ /* Modal Button Store API */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 434e47d344e..4913b8698c0 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -4833,6 +4833,38 @@ static void WM_OT_previews_ensure(wmOperatorType *ot) ot->exec = previews_ensure_exec; } +static int doc_view_manual_ui_context_exec(bContext *C, wmOperator *UNUSED(op)) +{ + PointerRNA ptr_props; + char buf[512]; + short retval = OPERATOR_CANCELLED; + + if (UI_but_online_manual_id_from_active(C, buf, sizeof(buf))) { + WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual"); + RNA_string_set(&ptr_props, "doc_id", buf); + + retval = WM_operator_name_call_ptr( + C, WM_operatortype_find("WM_OT_doc_view_manual", false), + WM_OP_EXEC_DEFAULT, &ptr_props); + + WM_operator_properties_free(&ptr_props); + } + + return retval; +} + +static void WM_OT_doc_view_manual_ui_context(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "View Online Manual"; + ot->idname = "WM_OT_doc_view_manual_ui_context"; + ot->description = "View a context based online manual in a webbrowser"; + + /* callbacks */ + ot->poll = ED_operator_regionactive; + ot->exec = doc_view_manual_ui_context_exec; +} + /* ******************************************************* */ static void operatortype_ghash_free_cb(wmOperatorType *ot) @@ -4929,6 +4961,7 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_console_toggle); #endif WM_operatortype_append(WM_OT_previews_ensure); + WM_operatortype_append(WM_OT_doc_view_manual_ui_context); } /* circleselect-like modal operators */ @@ -5155,6 +5188,8 @@ void wm_window_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "WM_OT_window_fullscreen_toggle", F11KEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "WM_OT_quit_blender", QKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "WM_OT_doc_view_manual_ui_context", F1KEY, KM_PRESS, KM_ALT, 0); + /* debug/testing */ WM_keymap_verify_item(keymap, "WM_OT_redraw_timer", TKEY, KM_PRESS, KM_ALT | KM_CTRL, 0); WM_keymap_verify_item(keymap, "WM_OT_debug_menu", DKEY, KM_PRESS, KM_ALT | KM_CTRL, 0); -- cgit v1.2.3 From 24448e11fb4cdaaef3f1b2652e69d57bb903fcc1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 27 Apr 2015 03:34:13 +1000 Subject: Correct own error in recent sculpt changes mixed up squared nonsquared length, also remove invalid verify check. --- source/blender/blenkernel/intern/pbvh_bmesh.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index bc193b74343..02b8cdba05b 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -799,7 +799,7 @@ static void long_edge_queue_face_add( if (len_sq > eq_ctx->q->limit_len_squared) { long_edge_queue_edge_add_recursive( eq_ctx, l_iter->radial_next, l_iter, - len_sq, eq_ctx->q->limit_len_squared); + len_sq, eq_ctx->q->limit_len); } #else long_edge_queue_edge_add(eq_ctx, l_iter->e); @@ -1051,11 +1051,6 @@ static bool pbvh_bmesh_subdivide_long_edges( { bool any_subdivided = false; -#ifdef USE_EDGEQUEUE_TAG_VERIFY - pbvh_bmesh_edge_tag_verify(bvh); -#endif - - while (!BLI_heap_is_empty(eq_ctx->q->heap)) { BMVert **pair = BLI_heap_popmin(eq_ctx->q->heap); BMVert *v1 = pair[0], *v2 = pair[1]; -- cgit v1.2.3 From ddb5f962959d3ceead4137ab63b1237685198de8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 27 Apr 2015 03:35:16 +1000 Subject: Sculpt: symmetrize was leaving edge-tags dirty This is used for the edge-queue --- source/blender/editors/sculpt_paint/sculpt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 40ef8970d68..1d2f623bf9d 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -4966,6 +4966,9 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op)) sd->symmetrize_direction, 0.00001f); sculpt_dynamic_topology_triangulate(ss->bm); + /* bisect operator flags edges (keep tags clean for edge queue) */ + BM_mesh_elem_hflag_disable_all(ss->bm, BM_EDGE, BM_ELEM_TAG, false); + /* Finish undo */ BM_log_all_added(ss->bm, ss->bm_log); sculpt_undo_push_end(); -- cgit v1.2.3 From 5e1eb8cdcf6aca9ad55aa040ca914c17b717c102 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 27 Apr 2015 18:44:27 +1000 Subject: Cleanup: rename GRAB_POINTER -> GRAB_CURSOR Term pointer is overloaded already. --- release/scripts/startup/bl_operators/wm.py | 2 +- source/blender/editors/animation/anim_markers.c | 2 +- source/blender/editors/animation/anim_ops.c | 2 +- source/blender/editors/interface/view2d_ops.c | 4 ++-- source/blender/editors/mesh/editmesh_bevel.c | 2 +- source/blender/editors/mesh/editmesh_inset.c | 2 +- source/blender/editors/space_clip/clip_ops.c | 2 +- source/blender/editors/space_clip/tracking_ops.c | 4 ++-- source/blender/editors/space_image/image_ops.c | 4 ++-- source/blender/editors/space_node/node_view.c | 2 +- source/blender/editors/space_text/text_ops.c | 2 +- source/blender/editors/space_view3d/view3d_edit.c | 8 +++---- source/blender/editors/transform/transform_ops.c | 2 +- source/blender/editors/uvedit/uvedit_unwrap_ops.c | 2 +- source/blender/makesdna/DNA_windowmanager_types.h | 2 +- source/blender/makesrna/intern/rna_wm.c | 2 +- source/blender/windowmanager/WM_types.h | 27 +++++++++++++--------- .../blender/windowmanager/intern/wm_event_system.c | 4 ++-- source/blender/windowmanager/intern/wm_operators.c | 2 +- 19 files changed, 41 insertions(+), 36 deletions(-) diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 7ac9fa4a036..6e5b77b4402 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -719,7 +719,7 @@ class WM_OT_context_modal_mouse(Operator): """Adjust arbitrary values with mouse input""" bl_idname = "wm.context_modal_mouse" bl_label = "Context Modal Mouse" - bl_options = {'GRAB_POINTER', 'BLOCKING', 'UNDO', 'INTERNAL'} + bl_options = {'GRAB_CURSOR', 'BLOCKING', 'UNDO', 'INTERNAL'} data_path_iter = data_path_iter data_path_item = data_path_item diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index aa06740ed0e..45663371ae3 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -962,7 +962,7 @@ static void MARKER_OT_move(wmOperatorType *ot) ot->cancel = ed_marker_move_cancel; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; /* rna storage */ RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX); diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 47eafcbaed1..2de42933dc0 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -247,7 +247,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot) ot->poll = change_frame_poll; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR; /* rna */ ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME); diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 58b51ef8e28..816c9a93d8c 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -328,7 +328,7 @@ static void VIEW2D_OT_pan(wmOperatorType *ot) ot->cancel = view_pan_cancel; /* operator is modal */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; /* rna - must keep these in sync with the other operators */ RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX); @@ -1179,7 +1179,7 @@ static void VIEW2D_OT_zoom(wmOperatorType *ot) ot->poll = view_zoom_poll; /* operator is repeatable */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; /* rna - must keep these in sync with the other operators */ prop = RNA_def_float(ot->srna, "deltax", 0, -FLT_MAX, FLT_MAX, "Delta X", "", -FLT_MAX, FLT_MAX); diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 0e48cbcd589..1e44d7e654d 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -477,7 +477,7 @@ void MESH_OT_bevel(wmOperatorType *ot) ot->poll = ED_operator_editmesh; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING; RNA_def_enum(ot->srna, "offset_type", offset_type_items, 0, "Amount Type", "What distance Amount measures"); prop = RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Amount", "", 0.0f, 1.0f); diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c index f1c3ca30610..80d3777d057 100644 --- a/source/blender/editors/mesh/editmesh_inset.c +++ b/source/blender/editors/mesh/editmesh_inset.c @@ -499,7 +499,7 @@ void MESH_OT_inset(wmOperatorType *ot) ot->poll = ED_operator_editmesh; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING; /* properties */ RNA_def_boolean(ot->srna, "use_boundary", true, "Boundary", "Inset face boundaries"); diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 17783e1412d..1d398177d9f 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -658,7 +658,7 @@ void CLIP_OT_view_zoom(wmOperatorType *ot) ot->poll = ED_space_clip_view_clip_poll; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; /* properties */ prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Factor", diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 4521e980687..21d74638ec3 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1066,7 +1066,7 @@ void CLIP_OT_slide_marker(wmOperatorType *ot) ot->modal = slide_marker_modal; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING; /* properties */ RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX, @@ -4183,7 +4183,7 @@ void CLIP_OT_slide_plane_marker(wmOperatorType *ot) ot->modal = slide_plane_marker_modal; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING; } /********************** Insert track keyframe operator *********************/ diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 24eb1195ab1..bd44a7f403c 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -378,7 +378,7 @@ void IMAGE_OT_view_pan(wmOperatorType *ot) ot->poll = space_image_main_area_poll; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_LOCK_BYPASS; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_LOCK_BYPASS; /* properties */ RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX, @@ -594,7 +594,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot) ot->poll = space_image_main_area_poll; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_LOCK_BYPASS; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_LOCK_BYPASS; /* properties */ prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Factor", diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index dda84eb0cbf..8c5d2d82468 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -292,7 +292,7 @@ void NODE_OT_backimage_move(wmOperatorType *ot) ot->cancel = snode_bg_viewmove_cancel; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; } static int backimage_zoom_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index ad8050a50e8..fce864d975f 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -2233,7 +2233,7 @@ void TEXT_OT_scroll(wmOperatorType *ot) ot->poll = text_scroll_poll; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_INTERNAL; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_INTERNAL; /* properties */ RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 3f6f17da334..2ae638b22e4 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1312,7 +1312,7 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) ot->cancel = viewrotate_cancel; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; } /** \name NDOF Utility Functions @@ -2055,7 +2055,7 @@ void VIEW3D_OT_move(wmOperatorType *ot) ot->cancel = viewmove_cancel; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; } /* ************************ viewzoom ******************************** */ @@ -2563,7 +2563,7 @@ void VIEW3D_OT_zoom(wmOperatorType *ot) ot->cancel = viewzoom_cancel; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX); @@ -2817,7 +2817,7 @@ void VIEW3D_OT_dolly(wmOperatorType *ot) ot->cancel = viewdolly_cancel; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX); diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index e33bc19fc92..291c70bd7dc 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -488,7 +488,7 @@ static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* add temp handler */ WM_event_add_modal_handler(C, op); - op->flag |= OP_GRAB_POINTER; // XXX maybe we want this with the manipulator only? + op->flag |= OP_IS_MODAL_GRAB_CURSOR; // XXX maybe we want this with the manipulator only? return OPERATOR_RUNNING_MODAL; } } diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 793f84b05ec..f915a4b2e51 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -681,7 +681,7 @@ void UV_OT_minimize_stretch(wmOperatorType *ot) /* identifiers */ ot->name = "Minimize Stretch"; ot->idname = "UV_OT_minimize_stretch"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING; ot->description = "Reduce UV stretching by relaxing angles"; /* api callbacks */ diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 6eb2f2487b0..4aa49eea2e8 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -390,7 +390,7 @@ enum { /* wmOperator flag */ enum { - OP_GRAB_POINTER = (1 << 0), + OP_IS_MODAL_GRAB_CURSOR = (1 << 0), /* low level flag so exec() operators can tell if they were invoked, use with care. * typically this shouldn't make any difference, but it rare cases its needed (see smooth-view) */ OP_IS_INVOKE = (1 << 1), diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index f01e1d02028..d9eb14c8992 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -414,7 +414,7 @@ static EnumPropertyItem operator_flag_items[] = { {OPTYPE_UNDO, "UNDO", 0, "Undo", "Push an undo event (needed for operator redo)"}, {OPTYPE_BLOCKING, "BLOCKING", 0, "Blocking", "Block anything else from using the cursor"}, {OPTYPE_MACRO, "MACRO", 0, "Macro", "Use to check if an operator is a macro"}, - {OPTYPE_GRAB_POINTER, "GRAB_POINTER", 0, "Grab Pointer", + {OPTYPE_GRAB_CURSOR, "GRAB_CURSOR", 0, "Grab Pointer", "Use so the operator grabs the mouse focus, enables wrapping when continuous grab " "is enabled"}, {OPTYPE_PRESET, "PRESET", 0, "Preset", "Display a preset button with the operators settings"}, diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index ecc7a827bee..109ccc27d79 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -123,17 +123,22 @@ struct ImBuf; /* ************** wmOperatorType ************************ */ /* flag */ -#define OPTYPE_REGISTER 1 /* register operators in stack after finishing */ -#define OPTYPE_UNDO 2 /* do undo push after after */ -#define OPTYPE_BLOCKING 4 /* let blender grab all input from the WM (X11) */ -#define OPTYPE_MACRO 8 -#define OPTYPE_GRAB_POINTER 16 /* grabs the cursor and optionally enables continuous cursor wrapping */ -#define OPTYPE_PRESET 32 /* show preset menu */ -#define OPTYPE_INTERNAL 64 /* some operators are mainly for internal use - * and don't make sense to be accessed from the - * search menu, even if poll() returns true. - * currently only used for the search toolbox */ -#define OPTYPE_LOCK_BYPASS 128 /* Allow operator to run when interface is locked */ +enum { + OPTYPE_REGISTER = (1 << 0), /* register operators in stack after finishing */ + OPTYPE_UNDO = (1 << 1), /* do undo push after after */ + OPTYPE_BLOCKING = (1 << 2), /* let blender grab all input from the WM (X11) */ + OPTYPE_MACRO = (1 << 3), + OPTYPE_GRAB_CURSOR = (1 << 4), /* grabs the cursor and optionally enables continuous cursor wrapping */ + OPTYPE_PRESET = (1 << 5), /* show preset menu */ + + /* some operators are mainly for internal use + * and don't make sense to be accessed from the + * search menu, even if poll() returns true. + * currently only used for the search toolbox */ + OPTYPE_INTERNAL = (1 << 6), + + OPTYPE_LOCK_BYPASS = (1 << 7), /* Allow operator to run when interface is locked */ +}; /* context to call operator in for WM_operator_name_call */ /* rna_ui.c contains EnumPropertyItem's of these, keep in sync */ diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index a6d5113a03a..8c97d399385 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1085,11 +1085,11 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, if (op->opm) { wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) && - ((op->opm->flag & OP_GRAB_POINTER) || (op->opm->type->flag & OPTYPE_GRAB_POINTER)); + ((op->opm->flag & OP_IS_MODAL_GRAB_CURSOR) || (op->opm->type->flag & OPTYPE_GRAB_CURSOR)); } else { wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) && - ((op->flag & OP_GRAB_POINTER) || (ot->flag & OPTYPE_GRAB_POINTER)); + ((op->flag & OP_IS_MODAL_GRAB_CURSOR) || (ot->flag & OPTYPE_GRAB_CURSOR)); } /* exception, cont. grab in header is annoying */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 4913b8698c0..7e2ee0e3205 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -343,7 +343,7 @@ static int wm_macro_modal(bContext *C, wmOperator *op, const wmEvent *event) int bounds[4] = {-1, -1, -1, -1}; const bool wrap = ( (U.uiflag & USER_CONTINUOUS_MOUSE) && - ((op->opm->flag & OP_GRAB_POINTER) || (op->opm->type->flag & OPTYPE_GRAB_POINTER))); + ((op->opm->flag & OP_IS_MODAL_GRAB_CURSOR) || (op->opm->type->flag & OPTYPE_GRAB_CURSOR))); if (wrap) { ARegion *ar = CTX_wm_region(C); -- cgit v1.2.3 From 5df939fd15213548346558e76bd2cdc22ebe21a4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 27 Apr 2015 18:45:48 +1000 Subject: Py API: expose operator runtime flags eg from operator invoke/execute: self.options.is_grab_cursor --- source/blender/makesrna/intern/rna_wm.c | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index d9eb14c8992..ded4ea02a9b 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -511,6 +511,11 @@ static int rna_Operator_has_reports_get(PointerRNA *ptr) return (op->reports && op->reports->list.first); } +static PointerRNA rna_Operator_options_get(PointerRNA *ptr) +{ + return rna_pointer_inherit_refine(ptr, &RNA_OperatorOptions, ptr->data); +} + static PointerRNA rna_Operator_properties_get(PointerRNA *ptr) { wmOperator *op = (wmOperator *)ptr->data; @@ -1390,6 +1395,29 @@ static void rna_KeyMapItem_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi #else /* RNA_RUNTIME */ +/** + * expose ``Operator.options`` as its own type so we can control each flags use (some are read-only). + */ +static void rna_def_operator_options_runtime(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "OperatorOptions", NULL); + RNA_def_struct_ui_text(srna, "Operator Options", "Runtime options"); + RNA_def_struct_sdna(srna, "wmOperator"); + + prop = RNA_def_property(srna, "is_grab_cursor", PROP_BOOLEAN, PROP_BOOLEAN); + RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_MODAL_GRAB_CURSOR); + RNA_def_property_ui_text(prop, "Grab Cursor", "True when the cursor is grabbed"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "is_invoke", PROP_BOOLEAN, PROP_BOOLEAN); + RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_INVOKE); + RNA_def_property_ui_text(prop, "Invoke", "True when invoked (even if only the execute callbacks available)"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); +} + static void rna_def_operator(BlenderRNA *brna) { StructRNA *srna; @@ -1424,6 +1452,12 @@ static void rna_def_operator(BlenderRNA *brna) prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "UILayout"); + prop = RNA_def_property(srna, "options", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "OperatorOptions"); + RNA_def_property_pointer_funcs(prop, "rna_Operator_options_get", NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Options", "Runtime options"); + /* Registration */ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "type->idname"); @@ -2169,6 +2203,7 @@ static void rna_def_keyconfig(BlenderRNA *brna) void RNA_def_wm(BlenderRNA *brna) { rna_def_operator(brna); + rna_def_operator_options_runtime(brna); rna_def_operator_utils(brna); rna_def_operator_filelist_element(brna); rna_def_macro_operator(brna); -- cgit v1.2.3 From 3f80accfb34dd10e70380139941bcaf62702a6f8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 27 Apr 2015 18:53:45 +1000 Subject: Fix T44011: Ruler/Knife/Loop-cut fail in quad-view This is a kind of sloppy-focus, resolving long standing bug with loop-cut/knife/ruler /w quad-view. Where activating a tool would lock onto one of quad-views, especially problematic when activating from the toolbar or menus. --- source/blender/blenkernel/BKE_screen.h | 1 + source/blender/blenkernel/intern/screen.c | 17 +++++++++++ source/blender/editors/mesh/editmesh_knife.c | 12 ++++++++ source/blender/editors/mesh/editmesh_loopcut.c | 4 +++ source/blender/editors/space_view3d/view3d_ruler.c | 18 +++++++++-- source/blender/makesdna/DNA_screen_types.h | 2 ++ source/blender/makesdna/DNA_windowmanager_types.h | 10 +++++-- source/blender/makesrna/intern/rna_wm.c | 4 +++ .../blender/windowmanager/intern/wm_event_system.c | 35 +++++++++++++++++----- source/blender/windowmanager/wm_event_system.h | 1 + 10 files changed, 91 insertions(+), 13 deletions(-) diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 43499933d16..bb764540da9 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -280,6 +280,7 @@ void BKE_screen_area_free(struct ScrArea *sa); struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type); struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa); +struct ARegion *BKE_area_find_region_xy(struct ScrArea *sa, const int regiontype, int x, int y); struct ScrArea *BKE_screen_find_area_from_space(struct bScreen *sc, struct SpaceLink *sl) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2); struct ScrArea *BKE_screen_find_big_area(struct bScreen *sc, const int spacetype, const short min); struct ScrArea *BKE_screen_find_area_xy(struct bScreen *sc, const int spacetype, int x, int y); diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 3c43bfa2920..36fd598cc70 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -405,6 +405,23 @@ ARegion *BKE_area_find_region_active_win(ScrArea *sa) return NULL; } +ARegion *BKE_area_find_region_xy(ScrArea *sa, const int regiontype, int x, int y) +{ + ARegion *ar_found = NULL; + if (sa) { + ARegion *ar; + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if ((regiontype == RGN_TYPE_ANY) || (ar->regiontype == regiontype)) { + if (BLI_rcti_isect_pt(&ar->winrct, x, y)) { + ar_found = ar; + break; + } + } + } + } + return ar_found; +} + /** * \note, ideally we can get the area from the context, * there are a few places however where this isn't practical. diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index df91679b5f0..4f8839005c9 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -3051,6 +3051,8 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event) knifetool_init(C, kcd, only_select, cut_through, true); + op->flag |= OP_IS_MODAL_CURSOR_REGION; + /* add a modal handler for this operator - handles loop selection */ WM_cursor_modal_set(CTX_wm_window(C), BC_KNIFECURSOR); WM_event_add_modal_handler(C, op); @@ -3143,6 +3145,9 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_FINISHED; } + em_setup_viewcontext(C, &kcd->vc); + kcd->ar = kcd->vc.ar; + view3d_operator_needs_opengl(C); ED_view3d_init_mats_rv3d(obedit, kcd->vc.rv3d); /* needed to initialize clipping */ @@ -3302,6 +3307,13 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) } } + if (kcd->mode == MODE_DRAGGING) { + op->flag &= ~OP_IS_MODAL_CURSOR_REGION; + } + else { + op->flag |= OP_IS_MODAL_CURSOR_REGION; + } + if (do_refresh) { /* we don't really need to update mval, * but this happens to be the best way to refresh at the moment */ diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index a4ea2ab3921..c7f9522ab3f 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -553,6 +553,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) /* add a modal handler for this operator - handles loop selection */ if (is_interactive) { + op->flag |= OP_IS_MODAL_CURSOR_REGION; WM_event_add_modal_handler(C, op); } @@ -639,6 +640,9 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) bool show_cuts = false; const bool has_numinput = hasNumInput(&lcd->num); + em_setup_viewcontext(C, &lcd->vc); + lcd->ar = lcd->vc.ar; + view3d_operator_needs_opengl(C); /* using the keyboard to input the number of cuts */ diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index eba31866f54..addda0a8b66 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -187,6 +187,7 @@ typedef struct RulerInfo { /* wm state */ wmWindow *win; + ScrArea *sa; ARegion *ar; void *draw_handle_pixel; } RulerInfo; @@ -435,7 +436,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a UnitSettings *unit = &scene->unit; RulerItem *ruler_item; RulerInfo *ruler_info = arg; - RegionView3D *rv3d = ruler_info->ar->regiondata; + RegionView3D *rv3d = ar->regiondata; // ARegion *ar = ruler_info->ar; const float cap_size = 4.0f; const float bg_margin = 4.0f * U.pixelsize; @@ -798,12 +799,14 @@ static int view3d_ruler_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE op->customdata = ruler_info; ruler_info->win = win; - ruler_info->ar = ar; + ruler_info->sa = sa; ruler_info->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ruler_info_draw_pixel, ruler_info, REGION_DRAW_POST_PIXEL); view3d_ruler_header_update(sa); + op->flag |= OP_IS_MODAL_CURSOR_REGION; + WM_cursor_modal_set(win, BC_CROSSCURSOR); WM_event_add_modal_handler(C, op); @@ -829,11 +832,13 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event) RegionView3D *rv3d = ar->regiondata; /* its possible to change spaces while running the operator [#34894] */ - if (UNLIKELY(ar != CTX_wm_region(C))) { + if (UNLIKELY(sa != ruler_info->sa)) { exit_code = OPERATOR_FINISHED; goto exit; } + ruler_info->ar = ar; + switch (event->type) { case LEFTMOUSE: if (event->val == KM_RELEASE) { @@ -1019,6 +1024,13 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event) } + if (ruler_info->state == RULER_STATE_DRAG) { + op->flag &= ~OP_IS_MODAL_CURSOR_REGION; + } + else { + op->flag |= OP_IS_MODAL_CURSOR_REGION; + } + if (do_draw) { view3d_ruler_header_update(sa); diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 13365adeb58..eb76c90c0fc 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -374,6 +374,8 @@ enum { RGN_TYPE_TOOL_PROPS = 6, RGN_TYPE_PREVIEW = 7 }; +/* use for function args */ +#define RGN_TYPE_ANY -1 /* region alignment */ #define RGN_ALIGN_NONE 0 diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 4aa49eea2e8..51ed8bb6c0d 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -390,10 +390,16 @@ enum { /* wmOperator flag */ enum { - OP_IS_MODAL_GRAB_CURSOR = (1 << 0), /* low level flag so exec() operators can tell if they were invoked, use with care. * typically this shouldn't make any difference, but it rare cases its needed (see smooth-view) */ - OP_IS_INVOKE = (1 << 1), + OP_IS_INVOKE = (1 << 0), + + /* When the cursor is grabbed */ + OP_IS_MODAL_GRAB_CURSOR = (1 << 1), + + /* allow modal operators to have the region under the cursor for their context + * (the regiontype is maintained to prevent errors) */ + OP_IS_MODAL_CURSOR_REGION = (1 << 2), }; #endif /* __DNA_WINDOWMANAGER_TYPES_H__ */ diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index ded4ea02a9b..3b8ddd011c0 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -1416,6 +1416,10 @@ static void rna_def_operator_options_runtime(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_INVOKE); RNA_def_property_ui_text(prop, "Invoke", "True when invoked (even if only the execute callbacks available)"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "use_cursor_region", PROP_BOOLEAN, PROP_BOOLEAN); + RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_MODAL_CURSOR_REGION); + RNA_def_property_ui_text(prop, "Focus Region", "Enable to use the region under the cursor for modal execution"); } static void rna_def_operator(BlenderRNA *brna) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 8c97d399385..830feed2fc7 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1337,7 +1337,7 @@ void wm_event_free_handler(wmEventHandler *handler) } /* only set context when area/region is part of screen */ -static void wm_handler_op_context(bContext *C, wmEventHandler *handler) +static void wm_handler_op_context(bContext *C, wmEventHandler *handler, const wmEvent *event) { bScreen *screen = CTX_wm_screen(C); @@ -1358,10 +1358,27 @@ static void wm_handler_op_context(bContext *C, wmEventHandler *handler) } else { ARegion *ar; + wmOperator *op = handler->op ? (handler->op->opm ? handler->op->opm : handler->op) : NULL; CTX_wm_area_set(C, sa); - for (ar = sa->regionbase.first; ar; ar = ar->next) - if (ar == handler->op_region) - break; + + if (op && (op->flag & OP_IS_MODAL_CURSOR_REGION)) { + ar = BKE_area_find_region_xy(sa, handler->op_region_type, event->x, event->y); + if (ar) { + handler->op_region = ar; + } + } + else { + ar = NULL; + } + + if (ar == NULL) { + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar == handler->op_region) { + break; + } + } + } + /* XXX no warning print here, after full-area and back regions are remade */ if (ar) CTX_wm_region_set(C, ar); @@ -1379,11 +1396,12 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers) /* C is zero on freeing database, modal handlers then already were freed */ while ((handler = BLI_pophead(handlers))) { if (handler->op) { + wmWindow *win = CTX_wm_window(C); if (handler->op->type->cancel) { ScrArea *area = CTX_wm_area(C); ARegion *region = CTX_wm_region(C); - wm_handler_op_context(C, handler); + wm_handler_op_context(C, handler, win->eventstate); if (handler->op->type->flag & OPTYPE_UNDO) wm->op_undo_depth++; @@ -1397,7 +1415,7 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers) CTX_wm_region_set(C, region); } - WM_cursor_grab_disable(CTX_wm_window(C), NULL); + WM_cursor_grab_disable(win, NULL); WM_operator_free(handler->op); } else if (handler->ui_remove) { @@ -1569,7 +1587,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand ARegion *region = CTX_wm_region(C); bool dbl_click_disabled = false; - wm_handler_op_context(C, handler); + wm_handler_op_context(C, handler, event); wm_region_mouse_co(C, event); wm_event_modalkeymap(C, op, event, &dbl_click_disabled); @@ -1717,7 +1735,7 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand ED_screen_full_prevspace(C, CTX_wm_area(C)); } - wm_handler_op_context(C, handler); + wm_handler_op_context(C, handler, CTX_wm_window(C)->eventstate); /* needed for UI_popup_menu_reports */ @@ -2534,6 +2552,7 @@ wmEventHandler *WM_event_add_modal_handler(bContext *C, wmOperator *op) handler->op_area = CTX_wm_area(C); /* means frozen screen context for modal handlers! */ handler->op_region = CTX_wm_region(C); + handler->op_region_type = handler->op_region ? handler->op_region->regiontype : -1; BLI_addhead(&win->modalhandlers, handler); diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h index f89177a82ea..a097343d037 100644 --- a/source/blender/windowmanager/wm_event_system.h +++ b/source/blender/windowmanager/wm_event_system.h @@ -56,6 +56,7 @@ typedef struct wmEventHandler { wmOperator *op; /* for derived/modal handlers */ struct ScrArea *op_area; /* for derived/modal handlers */ struct ARegion *op_region; /* for derived/modal handlers */ + short op_region_type; /* for derived/modal handlers */ /* ui handler */ wmUIHandlerFunc ui_handle; /* callback receiving events */ -- cgit v1.2.3 From 9dadc8f599da94c3120f24f198c606d011a5dda2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 27 Apr 2015 21:50:38 +1000 Subject: Math Lib: add mul_v3_mat3_m4v3 --- source/blender/blenlib/BLI_math_matrix.h | 1 + source/blender/blenlib/intern/math_matrix.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 45972d03175..f7eeb1ec7a1 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -106,6 +106,7 @@ void mul_v2_m4v3(float r[2], float M[4][4], const float v[3]); void mul_v2_m2v2(float r[2], float M[2][2], const float v[2]); void mul_m2v2(float M[2][2], float v[2]); void mul_mat3_m4_v3(float M[4][4], float r[3]); +void mul_v3_mat3_m4v3(float r[3], float M[4][4], const float v[3]); void mul_m4_v4(float M[4][4], float r[4]); void mul_v4_m4v4(float r[4], float M[4][4], const float v[4]); void mul_project_m4_v3(float M[4][4], float vec[3]); diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 1b4bbafdb04..773bb419c9b 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -504,6 +504,16 @@ void mul_mat3_m4_v3(float mat[4][4], float vec[3]) vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2]; } +void mul_v3_mat3_m4v3(float r[3], float mat[4][4], const float vec[3]) +{ + const float x = vec[0]; + const float y = vec[1]; + + r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2]; + r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2]; + r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2]; +} + void mul_project_m4_v3(float mat[4][4], float vec[3]) { const float w = mul_project_m4_v3_zfac(mat, vec); -- cgit v1.2.3 From e1ed47eb5b6ec3f1501bed0b34bfa7894acee022 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 27 Apr 2015 22:43:01 +1000 Subject: Fix T44512: Cycles fails normal bake /w scale flip --- source/blender/editors/object/object_bake_api.c | 6 +----- source/blender/render/extern/include/RE_bake.h | 2 +- source/blender/render/intern/source/bake_api.c | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 578335a385b..b382fbafcfd 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -775,11 +775,7 @@ static int bake( copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat); invert_m4_m4(highpoly[i].imat, highpoly[i].obmat); - /* rotation */ - normalize_m4_m4(highpoly[i].rotmat, highpoly[i].imat); - zero_v3(highpoly[i].rotmat[3]); - if (is_negative_m4(highpoly[i].rotmat)) - negate_mat3_m4(highpoly[i].rotmat); + highpoly[i].is_flip_object = is_negative_m4(highpoly[i].ob->obmat); i++; } diff --git a/source/blender/render/extern/include/RE_bake.h b/source/blender/render/extern/include/RE_bake.h index e8a8986714d..0750ea1aa28 100644 --- a/source/blender/render/extern/include/RE_bake.h +++ b/source/blender/render/extern/include/RE_bake.h @@ -61,10 +61,10 @@ typedef struct BakeHighPolyData { struct ModifierData *tri_mod; struct Mesh *me; char restrict_flag; + bool is_flip_object; float obmat[4][4]; float imat[4][4]; - float rotmat[4][4]; } BakeHighPolyData; /* external_engine.c */ diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c index 1f7555bc5c5..bc5db5b9862 100644 --- a/source/blender/render/intern/source/bake_api.c +++ b/source/blender/render/intern/source/bake_api.c @@ -300,7 +300,7 @@ static bool cast_ray_highpoly( mul_v3_m4v3(co_high, highpoly[i].imat, co); /* rotates */ - mul_v3_m4v3(dir_high, highpoly[i].rotmat, dir); + mul_v3_mat3_m4v3(dir_high, highpoly[i].imat, dir); normalize_v3(dir_high); /* cast ray */ -- cgit v1.2.3 From b315fcb7edb7222c97facc2413d3772702533dd2 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Mon, 27 Apr 2015 10:33:18 -0300 Subject: Fix T44514 Crash under cycles rendering using F12, based on patch from Gaia Clary --- source/blender/blenkernel/intern/image.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index b9a76a125a4..d76537ab696 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -3582,10 +3582,12 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ rectz = rv->rectz; } else { - /* XXX This should never happen, yet it does - T44498 + /* XXX This should never happen, yet it does - T44498, T44514 * I'm waiting to investigate more, but meanwhile this fix * the immediate issue */ rect = NULL; + rectf = NULL; + rectz = NULL; } dither = iuser->scene->r.dither_intensity; -- cgit v1.2.3 From f809eef968c997dc00ffccd10bb0b1221d66d05a Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Mon, 27 Apr 2015 10:39:09 -0300 Subject: Muti-View: viewport crashes when empty is active camera - reported over IRC by Campbell Barton --- source/blender/editors/space_view3d/view3d_draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 520ad4f89b4..af0bd8ec761 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -3570,7 +3570,7 @@ static bool view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, if (WM_stereo3d_enabled(win, true) == false) return false; - if ((v3d->camera == NULL) || rv3d->persp != RV3D_CAMOB) + if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) return false; if (scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) { -- cgit v1.2.3 From 4a80c4faded742aeebc2852f23e210163a5759dc Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Mon, 27 Apr 2015 12:09:04 -0300 Subject: Multi-View: Code cleanup I finally put the time into understanding what was going on here. Basically RE_AcquireResultImage() produces RenderResults without RenderViews. That will be fine for now since I'm planning to refactor RenderResult soon. --- source/blender/blenkernel/intern/image.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index d76537ab696..162f45379d8 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -3569,26 +3569,26 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ if (from_render) { BLI_lock_thread(LOCK_VIEWER); *lock_r = re; + rv = NULL; + } + else { + rv = BLI_findlink(&rres.views, actview); + if (rv == NULL) + rv = rres.views.first; } - rv = BLI_findlink(&rres.views, actview); - if (rv == NULL) - rv = rres.views.first; - - if (rv != NULL) { - /* this gives active layer, composite or sequence result */ + /* this gives active layer, composite or sequence result */ + if (rv == NULL) { + rect = (unsigned int *)rres.rect32; + rectf = rres.rectf; + rectz = rres.rectz; + } + else { rect = (unsigned int *)rv->rect32; rectf = rv->rectf; rectz = rv->rectz; } - else { - /* XXX This should never happen, yet it does - T44498, T44514 - * I'm waiting to investigate more, but meanwhile this fix - * the immediate issue */ - rect = NULL; - rectf = NULL; - rectz = NULL; - } + dither = iuser->scene->r.dither_intensity; /* combined layer gets added as first layer */ -- cgit v1.2.3 From c760c0dbb3b768c54e0ac81ec318cac94503b81b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 27 Apr 2015 23:23:04 +1000 Subject: Cleanup: use mul_v3_mat3_m4v3 --- source/blender/blenkernel/intern/object.c | 3 +-- source/blender/editors/mesh/editmesh_extrude.c | 3 +-- source/blender/editors/mesh/editmesh_knife.c | 3 +-- source/blender/editors/object/object_transform.c | 6 ++---- source/blender/editors/space_view3d/drawobject.c | 3 +-- source/blender/editors/transform/transform_snap.c | 22 ++++++---------------- .../blender/render/intern/source/convertblender.c | 3 +-- source/blender/render/intern/source/shadeinput.c | 9 +++------ 8 files changed, 16 insertions(+), 36 deletions(-) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index f14f72614f4..6f373ef0576 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1769,8 +1769,7 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob) mul_m4_m4m4(ob->obmat, gob->obmat, target->obmat); if (gob->dup_group) { /* should always be true */ float tvec[3]; - copy_v3_v3(tvec, gob->dup_group->dupli_ofs); - mul_mat3_m4_v3(ob->obmat, tvec); + mul_v3_mat3_m4v3(tvec, ob->obmat, gob->dup_group->dupli_ofs); sub_v3_v3(ob->obmat[3], tvec); } BKE_object_apply_mat4(ob, ob->obmat, false, true); diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 5c7efcc40da..e8f9a76a873 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -574,8 +574,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */ /* correct the normal to be aligned on the view plane */ - copy_v3_v3(view_vec, vc.rv3d->viewinv[2]); - mul_mat3_m4_v3(vc.obedit->imat, view_vec); + mul_v3_mat3_m4v3(view_vec, vc.obedit->imat, vc.rv3d->viewinv[2]); cross_v3_v3v3(cross, nor, view_vec); cross_v3_v3v3(nor, view_vec, cross); normalize_v3(nor); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 4f8839005c9..cfd0d3fdcf5 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -2876,8 +2876,7 @@ static void knife_recalc_projmat(KnifeTool_OpData *kcd) ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, kcd->projmat); invert_m4_m4(kcd->projmat_inv, kcd->projmat); - copy_v3_v3(kcd->proj_zaxis, kcd->vc.rv3d->viewinv[2]); - mul_mat3_m4_v3(kcd->ob->imat, kcd->proj_zaxis); + mul_v3_mat3_m4v3(kcd->proj_zaxis, kcd->ob->imat, kcd->vc.rv3d->viewinv[2]); normalize_v3(kcd->proj_zaxis); kcd->is_ortho = ED_view3d_clip_range_get(kcd->vc.v3d, kcd->vc.rv3d, diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 92fe5ded4dd..340b662c0ef 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -939,8 +939,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) /* convert the offset to parent space */ BKE_object_to_mat4(ob, obmat); - copy_v3_v3(centn, cent); - mul_mat3_m4_v3(obmat, centn); /* omit translation part */ + mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */ add_v3_v3(ob->loc, centn); @@ -970,8 +969,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) ob_other->flag |= OB_DONE; DAG_id_tag_update(&ob_other->id, OB_RECALC_OB | OB_RECALC_DATA); - copy_v3_v3(centn, cent); - mul_mat3_m4_v3(ob_other->obmat, centn); /* omit translation part */ + mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */ add_v3_v3(ob_other->loc, centn); BKE_object_where_is_calc(scene, ob_other); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 24b814da44d..5b2ac50216a 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -8021,9 +8021,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* don't show smoke before simulation starts, this could be made an option in the future */ if (smd->domain->fluid && CFRA >= smd->domain->point_cache[0]->startframe) { /* get view vector */ - copy_v3_v3(viewnormal, rv3d->viewinv[2]); invert_m4_m4(ob->imat, ob->obmat); - mul_mat3_m4_v3(ob->imat, viewnormal); + mul_v3_mat3_m4v3(viewnormal, ob->imat, rv3d->viewinv[2]); normalize_v3(viewnormal); /* set dynamic boundaries to draw the volume diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index fd189e91141..e8a0f35c6b0 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -1400,11 +1400,8 @@ static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *ar invert_m4_m4(imat, obmat); - copy_v3_v3(ray_start_local, ray_start); - copy_v3_v3(ray_normal_local, ray_normal); - - mul_m4_v3(imat, ray_start_local); - mul_mat3_m4_v3(imat, ray_normal_local); + mul_v3_m4v3(ray_start_local, imat, ray_start); + mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal); if (arm->edbo) { EditBone *eBone; @@ -1762,11 +1759,8 @@ static bool snapEmpty(short snap_mode, ARegion *ar, Object *ob, float obmat[4][4 invert_m4_m4(imat, obmat); - copy_v3_v3(ray_start_local, ray_start); - copy_v3_v3(ray_normal_local, ray_normal); - - mul_m4_v3(imat, ray_start_local); - mul_mat3_m4_v3(imat, ray_normal_local); + mul_v3_m4v3(ray_start_local, imat, ray_start); + mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal); switch (snap_mode) { case SCE_SNAP_MODE_VERTEX: @@ -2111,12 +2105,8 @@ static bool peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[4][4], transpose_m3_m4(timat, imat); - copy_v3_v3(ray_start_local, ray_start); - copy_v3_v3(ray_normal_local, ray_normal); - - mul_m4_v3(imat, ray_start_local); - mul_mat3_m4_v3(imat, ray_normal_local); - + mul_v3_m4v3(ray_start_local, imat, ray_start); + mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal); /* If number of vert is more than an arbitrary limit, * test against boundbox first diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index d36ab46d145..87c886929d6 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1209,8 +1209,7 @@ static void particle_normal_ren(short ren_as, ParticleSettings *part, Render *re sd->time = 0.0f; sd->size = hasize; - copy_v3_v3(vel, state->vel); - mul_mat3_m4_v3(re->viewmat, vel); + mul_v3_mat3_m4v3(vel, re->viewmat, state->vel); normalize_v3(vel); if (part->draw & PART_DRAW_VEL_LENGTH) diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 9ea7cb62c58..5a5e67e1e43 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -423,14 +423,11 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert } if (texco & TEXCO_GLOB) { - copy_v3_v3(shi->gl, shi->co); - mul_m4_v3(R.viewinv, shi->gl); + mul_v3_m4v3(shi->gl, R.viewinv, shi->co); if (shi->osatex) { - copy_v3_v3(shi->dxgl, shi->dxco); - mul_mat3_m4_v3(R.viewinv, shi->dxgl); - copy_v3_v3(shi->dygl, shi->dyco); - mul_mat3_m4_v3(R.viewinv, shi->dygl); + mul_v3_mat3_m4v3(shi->dxgl, R.viewinv, shi->dxco); + mul_v3_mat3_m4v3(shi->dygl, R.viewinv, shi->dyco); } } -- cgit v1.2.3 From 8d8d1939fab72cee068be81dac84679cac42cee6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 28 Apr 2015 01:03:28 +1000 Subject: Cleanup: use bool for mipmap args --- source/blender/gpu/GPU_draw.h | 10 +++++----- source/blender/gpu/intern/gpu_draw.c | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 20aa4919416..845ae9d2b30 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -104,11 +104,11 @@ void GPU_render_text(struct MTFace *tface, int mode, /* Mipmap settings * - these will free textures on changes */ -void GPU_set_mipmap(int mipmap); -int GPU_get_mipmap(void); -void GPU_set_linear_mipmap(int linear); -int GPU_get_linear_mipmap(void); -void GPU_paint_set_mipmap(int mipmap); +void GPU_set_mipmap(bool mipmap); +bool GPU_get_mipmap(void); +void GPU_set_linear_mipmap(bool linear); +bool GPU_get_linear_mipmap(void); +void GPU_paint_set_mipmap(bool mipmap); /* Anisotropic filtering settings * - these will free textures on changes */ diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 7d41746659f..a31e90f0dfe 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -239,8 +239,8 @@ static struct GPUTextureState { int curtileYRep, tileYRep; Image *ima, *curima; - int domipmap, linearmipmap; - int texpaint; /* store this so that new images created while texture painting won't be set to mipmapped */ + bool domipmap, linearmipmap; + bool texpaint; /* store this so that new images created while texture painting won't be set to mipmapped */ int alphablend; float anisotropic; @@ -281,33 +281,33 @@ static void gpu_generate_mipmap(GLenum target) glDisable(target); } -void GPU_set_mipmap(int mipmap) +void GPU_set_mipmap(bool mipmap) { - if (GTS.domipmap != (mipmap != 0)) { + if (GTS.domipmap != mipmap) { GPU_free_images(); - GTS.domipmap = mipmap != 0; + GTS.domipmap = mipmap; } } -void GPU_set_linear_mipmap(int linear) +void GPU_set_linear_mipmap(bool linear) { - if (GTS.linearmipmap != (linear != 0)) { + if (GTS.linearmipmap != linear) { GPU_free_images(); - GTS.linearmipmap = linear != 0; + GTS.linearmipmap = linear; } } -int GPU_get_mipmap(void) +bool GPU_get_mipmap(void) { return GTS.domipmap && !GTS.texpaint; } -int GPU_get_linear_mipmap(void) +bool GPU_get_linear_mipmap(void) { return GTS.linearmipmap; } -static GLenum gpu_get_mipmap_filter(int mag) +static GLenum gpu_get_mipmap_filter(bool mag) { /* linearmipmap is off by default *when mipmapping is off, * use unfiltered display */ @@ -931,7 +931,7 @@ int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend) * temporary disabling/enabling mipmapping on all images for quick texture * updates with glTexSubImage2D. images that didn't change don't have to be * re-uploaded to OpenGL */ -void GPU_paint_set_mipmap(int mipmap) +void GPU_paint_set_mipmap(bool mipmap) { Image *ima; -- cgit v1.2.3 From 84db9fdf4dd3bb5e1ddd6c2884787033386ac2ca Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 28 Apr 2015 01:14:48 +1000 Subject: Fix T44464: Viewport mipmaps no longer toggle off --- source/blender/gpu/intern/gpu_draw.c | 26 ++++++++++++++-------- source/creator/creator.c | 1 + .../RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp | 15 ++++++++----- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index a31e90f0dfe..a24067fc381 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -239,8 +239,12 @@ static struct GPUTextureState { int curtileYRep, tileYRep; Image *ima, *curima; - bool domipmap, linearmipmap; - bool texpaint; /* store this so that new images created while texture painting won't be set to mipmapped */ + /* also controls min/mag filtering */ + bool domipmap; + /* only use when 'domipmap' is set */ + bool linearmipmap; + /* store this so that new images created while texture painting won't be set to mipmapped */ + bool texpaint; int alphablend; float anisotropic; @@ -292,7 +296,6 @@ void GPU_set_mipmap(bool mipmap) void GPU_set_linear_mipmap(bool linear) { if (GTS.linearmipmap != linear) { - GPU_free_images(); GTS.linearmipmap = linear; } } @@ -312,18 +315,23 @@ static GLenum gpu_get_mipmap_filter(bool mag) /* linearmipmap is off by default *when mipmapping is off, * use unfiltered display */ if (mag) { - if (GTS.linearmipmap || GTS.domipmap) + if (GTS.domipmap) return GL_LINEAR; else return GL_NEAREST; } else { - if (GTS.linearmipmap) - return GL_LINEAR_MIPMAP_LINEAR; - else if (GTS.domipmap) - return GL_LINEAR_MIPMAP_NEAREST; - else + if (GTS.domipmap) { + if (GTS.linearmipmap) { + return GL_LINEAR_MIPMAP_LINEAR; + } + else { + return GL_LINEAR_MIPMAP_NEAREST; + } + } + else { return GL_NEAREST; + } } } diff --git a/source/creator/creator.c b/source/creator/creator.c index d86ccd657d4..721e43cda4d 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1024,6 +1024,7 @@ static int set_ge_parameters(int argc, const char **argv, void *data) } /* linearMipMap */ if (STREQ(argv[a], "linearmipmap")) { + GPU_set_mipmap(1); GPU_set_linear_mipmap(1); //linearMipMap = 1; } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index f47f56541ba..95c153a7e2a 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -1074,12 +1074,17 @@ void RAS_OpenGLRasterizer::SetMipmapping(MipmapOption val) RAS_IRasterizer::MipmapOption RAS_OpenGLRasterizer::GetMipmapping() { - if (GPU_get_linear_mipmap()) - return RAS_IRasterizer::RAS_MIPMAP_LINEAR; - else if (GPU_get_mipmap()) - return RAS_IRasterizer::RAS_MIPMAP_NEAREST; - else + if (GPU_get_mipmap()) { + if (GPU_get_linear_mipmap()) { + return RAS_IRasterizer::RAS_MIPMAP_LINEAR; + } + else { + return RAS_IRasterizer::RAS_MIPMAP_NEAREST; + } + } + else { return RAS_IRasterizer::RAS_MIPMAP_NONE; + } } void RAS_OpenGLRasterizer::SetUsingOverrideShader(bool val) -- cgit v1.2.3 From 920fa0f963b8e3bd89e213ea849e09df002d2676 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 28 Apr 2015 00:10:34 +1000 Subject: Fix double-free on copied Text compiled py-code --- source/blender/blenkernel/intern/text.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 9f441b45db9..2c588739cad 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -473,6 +473,7 @@ Text *BKE_text_copy(Main *bmain, Text *ta) BLI_listbase_clear(&tan->lines); tan->curl = tan->sell = NULL; + tan->compiled = NULL; tan->nlines = ta->nlines; -- cgit v1.2.3 From 6ada7a1a0b76d7c1d1203800c0bd84c5d1dc0f86 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 27 Apr 2015 20:10:32 +0200 Subject: Usual UI messages fixes... --- source/blender/windowmanager/intern/wm_operators.c | 2 +- source/blender/windowmanager/intern/wm_stereo.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 7e2ee0e3205..dfff5b4982f 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -4858,7 +4858,7 @@ static void WM_OT_doc_view_manual_ui_context(wmOperatorType *ot) /* identifiers */ ot->name = "View Online Manual"; ot->idname = "WM_OT_doc_view_manual_ui_context"; - ot->description = "View a context based online manual in a webbrowser"; + ot->description = "View a context based online manual in a web browser"; /* callbacks */ ot->poll = ED_operator_regionactive; diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 9178bd97257..717583f69ba 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -474,7 +474,7 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) } else { BKE_report(op->reports, RPT_ERROR, - "Fail to create a window without quadbuffer support, you may experience flickering"); + "Failed to create a window without quad-buffer support, you may experience flickering"); } } else if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { @@ -493,7 +493,7 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) } else { BKE_report(op->reports, RPT_ERROR, - "Fail to create a window compatible with the time sequential display method"); + "Failed to create a window compatible with the time sequential display method"); win->stereo3d_format->display_mode = prev_display_mode; } } -- cgit v1.2.3 From 278ff15c7f3c4a91ba049b7a13ecf8a4183ebf67 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 28 Apr 2015 04:10:31 +1000 Subject: BLI_array: add permute utility function --- source/blender/blenlib/BLI_array_utils.h | 8 ++++++++ source/blender/blenlib/intern/array_utils.c | 32 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/source/blender/blenlib/BLI_array_utils.h b/source/blender/blenlib/BLI_array_utils.h index 0dd1439e58c..ff7976dc701 100644 --- a/source/blender/blenlib/BLI_array_utils.h +++ b/source/blender/blenlib/BLI_array_utils.h @@ -34,6 +34,14 @@ void _bli_array_wrap(void *arr, unsigned int arr_len, size_t arr_stride, int dir #define BLI_array_wrap(arr, arr_len, dir) \ _bli_array_wrap(arr, arr_len, sizeof(*(arr)), dir) +void _bli_array_permute( + void *arr, const unsigned int arr_len, const size_t arr_stride, + const unsigned int *index, void *arr_temp); +#define BLI_array_permute(arr, arr_len, order) \ + _bli_array_permute(arr, arr_len, sizeof(*(arr)), order, NULL) +#define BLI_array_permute_ex(arr, arr_len, index, arr_temp) \ + _bli_array_permute(arr, arr_len, sizeof(*(arr)), order, arr_temp) + int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p); #define BLI_array_findindex(arr, arr_len, p) \ _bli_array_findindex(arr, arr_len, sizeof(*(arr)), p) diff --git a/source/blender/blenlib/intern/array_utils.c b/source/blender/blenlib/intern/array_utils.c index 173effbc434..efa107ed703 100644 --- a/source/blender/blenlib/intern/array_utils.c +++ b/source/blender/blenlib/intern/array_utils.c @@ -25,6 +25,8 @@ #include #include +#include "MEM_guardedalloc.h" + #include "BLI_array_utils.h" #include "BLI_sys_types.h" @@ -69,6 +71,36 @@ void _bli_array_wrap(void *arr_v, unsigned int arr_len, size_t arr_stride, int d } } +void _bli_array_permute( + void *arr_v, const unsigned int arr_len, const size_t arr_stride, + const unsigned int *order, void *arr_temp) +{ + const size_t len = arr_len * arr_stride; + const unsigned int arr_stride_uint = arr_stride; + void *arr_orig; + unsigned int i; + + if (arr_temp == NULL) { + arr_orig = MEM_mallocN(len, __func__); + } + else { + arr_orig = arr_temp; + } + + memcpy(arr_orig, arr_v, len); + + for (i = 0; i < arr_len; i++) { + BLI_assert(order[i] < arr_len); + memcpy(POINTER_OFFSET(arr_v, arr_stride_uint * i), + POINTER_OFFSET(arr_orig, arr_stride_uint * order[i]), + arr_stride); + } + + if (arr_temp == NULL) { + MEM_freeN(arr_orig); + } +} + /** * \note Not efficient, use for error checks/asserts. */ -- cgit v1.2.3 From ae7d84dbc1936ef7ddd00f9c22d074389f97f04f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 28 Apr 2015 00:13:03 +0500 Subject: Cycles: Use native saturate function for CUDA This more a workaround for CUDA optimizer which can't optimize clamp(x, 0, 1) into a single instruction and uses 4 instructions instead. Original patch by @lockal with own modification: Don't make changes outside of the kernel. They don't make any difference anyway and term saturate() has a bit different meaning outside of kernel. This gives around 2% of speedup in Barcelona file, but in more complex shader setups with lots of math nodes with clamping speedup could be much nicer. Subscribers: dingto Projects: #cycles Differential Revision: https://developer.blender.org/D1224 --- intern/cycles/kernel/closure/bsdf_microfacet.h | 16 ++++++++-------- intern/cycles/kernel/closure/bsdf_oren_nayar.h | 2 +- intern/cycles/kernel/closure/bsdf_toon.h | 8 ++++---- intern/cycles/kernel/closure/bssrdf.h | 6 +++--- intern/cycles/kernel/geom/geom_curve.h | 4 ++-- intern/cycles/kernel/kernel_film.h | 10 +++++----- intern/cycles/kernel/kernel_globals.h | 4 ++-- intern/cycles/kernel/kernel_passes.h | 2 +- intern/cycles/kernel/svm/svm_brick.h | 2 +- intern/cycles/kernel/svm/svm_closure.h | 4 ++-- intern/cycles/kernel/svm/svm_gradient.h | 2 +- intern/cycles/kernel/svm/svm_image.h | 6 +++--- intern/cycles/kernel/svm/svm_math_util.h | 2 +- intern/cycles/kernel/svm/svm_mix.h | 8 ++++---- intern/cycles/kernel/svm/svm_musgrave.h | 2 +- intern/cycles/kernel/svm/svm_ramp.h | 2 +- intern/cycles/render/buffers.cpp | 4 ++-- intern/cycles/render/nodes.cpp | 2 +- intern/cycles/util/util_math.h | 9 +++++++++ 19 files changed, 52 insertions(+), 43 deletions(-) diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index ca68b1eb940..6a50bbed3b3 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -235,7 +235,7 @@ ccl_device_inline float3 microfacet_sample_stretched( ccl_device int bsdf_microfacet_ggx_setup(ShaderClosure *sc) { - sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */ + sc->data0 = saturate(sc->data0); /* alpha_x */ sc->data1 = sc->data0; /* alpha_y */ sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID; @@ -245,8 +245,8 @@ ccl_device int bsdf_microfacet_ggx_setup(ShaderClosure *sc) ccl_device int bsdf_microfacet_ggx_aniso_setup(ShaderClosure *sc) { - sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */ - sc->data1 = clamp(sc->data1, 0.0f, 1.0f); /* alpha_y */ + sc->data0 = saturate(sc->data0); /* alpha_x */ + sc->data1 = saturate(sc->data1); /* alpha_y */ sc->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID; @@ -255,7 +255,7 @@ ccl_device int bsdf_microfacet_ggx_aniso_setup(ShaderClosure *sc) ccl_device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc) { - sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */ + sc->data0 = saturate(sc->data0); /* alpha_x */ sc->data1 = sc->data0; /* alpha_y */ sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; @@ -588,7 +588,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure ccl_device int bsdf_microfacet_beckmann_setup(ShaderClosure *sc) { - sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */ + sc->data0 = saturate(sc->data0); /* alpha_x */ sc->data1 = sc->data0; /* alpha_y */ sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID; @@ -597,8 +597,8 @@ ccl_device int bsdf_microfacet_beckmann_setup(ShaderClosure *sc) ccl_device int bsdf_microfacet_beckmann_aniso_setup(ShaderClosure *sc) { - sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */ - sc->data1 = clamp(sc->data1, 0.0f, 1.0f); /* alpha_y */ + sc->data0 = saturate(sc->data0); /* alpha_x */ + sc->data1 = saturate(sc->data1); /* alpha_y */ sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID; return SD_BSDF|SD_BSDF_HAS_EVAL; @@ -606,7 +606,7 @@ ccl_device int bsdf_microfacet_beckmann_aniso_setup(ShaderClosure *sc) ccl_device int bsdf_microfacet_beckmann_refraction_setup(ShaderClosure *sc) { - sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */ + sc->data0 = saturate(sc->data0); /* alpha_x */ sc->data1 = sc->data0; /* alpha_y */ sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; diff --git a/intern/cycles/kernel/closure/bsdf_oren_nayar.h b/intern/cycles/kernel/closure/bsdf_oren_nayar.h index c476d4ca4e2..61b7cb11b02 100644 --- a/intern/cycles/kernel/closure/bsdf_oren_nayar.h +++ b/intern/cycles/kernel/closure/bsdf_oren_nayar.h @@ -37,7 +37,7 @@ ccl_device int bsdf_oren_nayar_setup(ShaderClosure *sc) sc->type = CLOSURE_BSDF_OREN_NAYAR_ID; - sigma = clamp(sigma, 0.0f, 1.0f); + sigma = saturate(sigma); float div = 1.0f / (M_PI_F + ((3.0f * M_PI_F - 4.0f) / 6.0f) * sigma); diff --git a/intern/cycles/kernel/closure/bsdf_toon.h b/intern/cycles/kernel/closure/bsdf_toon.h index df03942638f..e5b6ab93a64 100644 --- a/intern/cycles/kernel/closure/bsdf_toon.h +++ b/intern/cycles/kernel/closure/bsdf_toon.h @@ -40,8 +40,8 @@ CCL_NAMESPACE_BEGIN ccl_device int bsdf_diffuse_toon_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_DIFFUSE_TOON_ID; - sc->data0 = clamp(sc->data0, 0.0f, 1.0f); - sc->data1 = clamp(sc->data1, 0.0f, 1.0f); + sc->data0 = saturate(sc->data0); + sc->data1 = saturate(sc->data1); return SD_BSDF|SD_BSDF_HAS_EVAL; } @@ -120,8 +120,8 @@ ccl_device int bsdf_diffuse_toon_sample(const ShaderClosure *sc, float3 Ng, floa ccl_device int bsdf_glossy_toon_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_GLOSSY_TOON_ID; - sc->data0 = clamp(sc->data0, 0.0f, 1.0f); - sc->data1 = clamp(sc->data1, 0.0f, 1.0f); + sc->data0 = saturate(sc->data0); + sc->data1 = saturate(sc->data1); return SD_BSDF|SD_BSDF_HAS_EVAL; } diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h index b2848262001..f817dcd5f2d 100644 --- a/intern/cycles/kernel/closure/bssrdf.h +++ b/intern/cycles/kernel/closure/bssrdf.h @@ -30,8 +30,8 @@ ccl_device int bssrdf_setup(ShaderClosure *sc, ClosureType type) return flag; } else { - sc->data1 = clamp(sc->data1, 0.0f, 1.0f); /* texture blur */ - sc->T.x = clamp(sc->T.x, 0.0f, 1.0f); /* sharpness */ + sc->data1 = saturate(sc->data1); /* texture blur */ + sc->T.x = saturate(sc->T.x); /* sharpness */ sc->type = type; return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF; @@ -168,7 +168,7 @@ ccl_device float bssrdf_cubic_quintic_root_find(float xi) if(fabsf(f) < tolerance || f_ == 0.0f) break; - x = clamp(x - f/f_, 0.0f, 1.0f); + x = saturate(x - f/f_); } return x; diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h index c13858fc461..ec6c790d9f7 100644 --- a/intern/cycles/kernel/geom/geom_curve.h +++ b/intern/cycles/kernel/geom/geom_curve.h @@ -465,7 +465,7 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect continue; } w = -(p_st.x * tg.x + p_st.y * tg.y) / w; - w = clamp((float)w, 0.0f, 1.0f); + w = saturate(w); /* compute u on the curve segment */ u = i_st * (1 - w) + i_en * w; @@ -577,7 +577,7 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect } float w = (zcentre + (tg.z * correction)) * invl; - w = clamp((float)w, 0.0f, 1.0f); + w = saturate(w); /* compute u on the curve segment */ u = i_st * (1 - w) + i_en * w; diff --git a/intern/cycles/kernel/kernel_film.h b/intern/cycles/kernel/kernel_film.h index 4668b40b86d..f9e9b413898 100644 --- a/intern/cycles/kernel/kernel_film.h +++ b/intern/cycles/kernel/kernel_film.h @@ -27,7 +27,7 @@ ccl_device float4 film_map(KernelGlobals *kg, float4 irradiance, float scale) result.z = color_scene_linear_to_srgb(result.z*exposure); /* clamp since alpha might be > 1.0 due to russian roulette */ - result.w = clamp(result.w, 0.0f, 1.0f); + result.w = saturate(result.w); return result; } @@ -37,10 +37,10 @@ ccl_device uchar4 film_float_to_byte(float4 color) uchar4 result; /* simple float to byte conversion */ - result.x = (uchar)clamp(color.x*255.0f, 0.0f, 255.0f); - result.y = (uchar)clamp(color.y*255.0f, 0.0f, 255.0f); - result.z = (uchar)clamp(color.z*255.0f, 0.0f, 255.0f); - result.w = (uchar)clamp(color.w*255.0f, 0.0f, 255.0f); + result.x = (uchar)(saturate(color.x)*255.0f); + result.y = (uchar)(saturate(color.y)*255.0f); + result.z = (uchar)(saturate(color.z)*255.0f); + result.w = (uchar)(saturate(color.w)*255.0f); return result; } diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h index 0a9753baca2..be2c879adb9 100644 --- a/intern/cycles/kernel/kernel_globals.h +++ b/intern/cycles/kernel/kernel_globals.h @@ -94,7 +94,7 @@ typedef struct KernelGlobals { ccl_device float lookup_table_read(KernelGlobals *kg, float x, int offset, int size) { - x = clamp(x, 0.0f, 1.0f)*(size-1); + x = saturate(x)*(size-1); int index = min(float_to_int(x), size-1); int nindex = min(index+1, size-1); @@ -110,7 +110,7 @@ ccl_device float lookup_table_read(KernelGlobals *kg, float x, int offset, int s ccl_device float lookup_table_read_2D(KernelGlobals *kg, float x, float y, int offset, int xsize, int ysize) { - y = clamp(y, 0.0f, 1.0f)*(ysize-1); + y = saturate(y)*(ysize-1); int index = min(float_to_int(y), ysize-1); int nindex = min(index+1, ysize-1); diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index 6bb39ee485d..8910e26fcc6 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -102,7 +102,7 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl float mist_inv_depth = kernel_data.film.mist_inv_depth; float depth = camera_distance(kg, sd->P); - float mist = clamp((depth - mist_start)*mist_inv_depth, 0.0f, 1.0f); + float mist = saturate((depth - mist_start)*mist_inv_depth); /* falloff */ float mist_falloff = kernel_data.film.mist_falloff; diff --git a/intern/cycles/kernel/svm/svm_brick.h b/intern/cycles/kernel/svm/svm_brick.h index 33a2a5c7598..fcf8f47b77e 100644 --- a/intern/cycles/kernel/svm/svm_brick.h +++ b/intern/cycles/kernel/svm/svm_brick.h @@ -47,7 +47,7 @@ ccl_device_noinline float2 svm_brick(float3 p, float mortar_size, float bias, y = p.y - row_height*rownum; return make_float2( - clamp((brick_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0f, 1.0f), + saturate((brick_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias)), (x < mortar_size || y < mortar_size || x > (brick_width - mortar_size) || diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 8afdb73fb38..0d2d155f827 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -347,7 +347,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->N = N; /* sigma */ - sc->data0 = clamp(param1, 0.0f, 1.0f); + sc->data0 = saturate(param1); sc->data1 = 0.0f; sc->data2 = 0.0f; sd->flag |= bsdf_ashikhmin_velvet_setup(sc); @@ -655,7 +655,7 @@ ccl_device void svm_node_mix_closure(ShaderData *sd, float *stack, uint4 node) decode_node_uchar4(node.y, &weight_offset, &in_weight_offset, &weight1_offset, &weight2_offset); float weight = stack_load_float(stack, weight_offset); - weight = clamp(weight, 0.0f, 1.0f); + weight = saturate(weight); float in_weight = (stack_valid(in_weight_offset))? stack_load_float(stack, in_weight_offset): 1.0f; diff --git a/intern/cycles/kernel/svm/svm_gradient.h b/intern/cycles/kernel/svm/svm_gradient.h index a5e385faddc..53d7b4f812c 100644 --- a/intern/cycles/kernel/svm/svm_gradient.h +++ b/intern/cycles/kernel/svm/svm_gradient.h @@ -66,7 +66,7 @@ ccl_device void svm_node_tex_gradient(ShaderData *sd, float *stack, uint4 node) float3 co = stack_load_float3(stack, co_offset); float f = svm_gradient(co, (NodeGradientType)type); - f = clamp(f, 0.0f, 1.0f); + f = saturate(f); if(stack_valid(fac_offset)) stack_store_float(stack, fac_offset, f); diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index ccc1e3df730..08a6c01162c 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -433,17 +433,17 @@ ccl_device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float /* in case of blending, test for mixes between two textures */ if(N.z < (1.0f - limit)*(N.y + N.x)) { weight.x = N.x/(N.x + N.y); - weight.x = clamp((weight.x - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f); + weight.x = saturate((weight.x - 0.5f*(1.0f - blend))/blend); weight.y = 1.0f - weight.x; } else if(N.x < (1.0f - limit)*(N.y + N.z)) { weight.y = N.y/(N.y + N.z); - weight.y = clamp((weight.y - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f); + weight.y = saturate((weight.y - 0.5f*(1.0f - blend))/blend); weight.z = 1.0f - weight.y; } else if(N.y < (1.0f - limit)*(N.x + N.z)) { weight.x = N.x/(N.x + N.z); - weight.x = clamp((weight.x - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f); + weight.x = saturate((weight.x - 0.5f*(1.0f - blend))/blend); weight.z = 1.0f - weight.x; } else { diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h index 39cc14d5e8e..ff9e662e931 100644 --- a/intern/cycles/kernel/svm/svm_math_util.h +++ b/intern/cycles/kernel/svm/svm_math_util.h @@ -97,7 +97,7 @@ ccl_device float svm_math(NodeMath type, float Fac1, float Fac2) else if(type == NODE_MATH_ABSOLUTE) Fac = fabsf(Fac1); else if(type == NODE_MATH_CLAMP) - Fac = clamp(Fac1, 0.0f, 1.0f); + Fac = saturate(Fac1); else Fac = 0.0f; diff --git a/intern/cycles/kernel/svm/svm_mix.h b/intern/cycles/kernel/svm/svm_mix.h index b6b1966cb3b..6111214acba 100644 --- a/intern/cycles/kernel/svm/svm_mix.h +++ b/intern/cycles/kernel/svm/svm_mix.h @@ -254,16 +254,16 @@ ccl_device float3 svm_mix_clamp(float3 col) { float3 outcol = col; - outcol.x = clamp(col.x, 0.0f, 1.0f); - outcol.y = clamp(col.y, 0.0f, 1.0f); - outcol.z = clamp(col.z, 0.0f, 1.0f); + outcol.x = saturate(col.x); + outcol.y = saturate(col.y); + outcol.z = saturate(col.z); return outcol; } ccl_device float3 svm_mix(NodeMix type, float fac, float3 c1, float3 c2) { - float t = clamp(fac, 0.0f, 1.0f); + float t = saturate(fac); switch(type) { case NODE_MIX_BLEND: return svm_mix_blend(t, c1, c2); diff --git a/intern/cycles/kernel/svm/svm_musgrave.h b/intern/cycles/kernel/svm/svm_musgrave.h index 2f81ddaa74c..2a0a8e0e87d 100644 --- a/intern/cycles/kernel/svm/svm_musgrave.h +++ b/intern/cycles/kernel/svm/svm_musgrave.h @@ -168,7 +168,7 @@ ccl_device_noinline float noise_musgrave_ridged_multi_fractal(float3 p, NodeNois for(i = 1; i < float_to_int(octaves); i++) { p *= lacunarity; - weight = clamp(signal * gain, 0.0f, 1.0f); + weight = saturate(signal * gain); signal = offset - fabsf(snoise(p)); signal *= signal; signal *= weight; diff --git a/intern/cycles/kernel/svm/svm_ramp.h b/intern/cycles/kernel/svm/svm_ramp.h index 998f649a571..062ab013b1f 100644 --- a/intern/cycles/kernel/svm/svm_ramp.h +++ b/intern/cycles/kernel/svm/svm_ramp.h @@ -21,7 +21,7 @@ CCL_NAMESPACE_BEGIN ccl_device float4 rgb_ramp_lookup(KernelGlobals *kg, int offset, float f, bool interpolate) { - f = clamp(f, 0.0f, 1.0f)*(RAMP_TABLE_SIZE-1); + f = saturate(f)*(RAMP_TABLE_SIZE-1); /* clamp int as well in case of NaN */ int i = clamp(float_to_int(f), 0, RAMP_TABLE_SIZE-1); diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index 5202bf5862c..dc00da1bf88 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -187,7 +187,7 @@ bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int else if(type == PASS_MIST) { for(int i = 0; i < size; i++, in += pass_stride, pixels++) { float f = *in; - pixels[0] = clamp(f*scale_exposure, 0.0f, 1.0f); + pixels[0] = saturate(f*scale_exposure); } } #ifdef WITH_CYCLES_DEBUG @@ -298,7 +298,7 @@ bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int pixels[2] = f.z*scale_exposure; /* clamp since alpha might be > 1.0 due to russian roulette */ - pixels[3] = clamp(f.w*scale, 0.0f, 1.0f); + pixels[3] = saturate(f.w*scale); } } } diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 747bafcc904..8529855ff2e 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -3752,7 +3752,7 @@ void MathNode::compile(SVMCompiler& compiler) value1_in->value.x, value2_in->value.x); if(use_clamp) { - optimized_value = clamp(optimized_value, 0.0f, 1.0f); + optimized_value = saturate(optimized_value); } compiler.add_node(NODE_VALUE_F, __float_as_int(optimized_value), diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 6208608a233..f48625ec95d 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -175,6 +175,15 @@ ccl_device_inline float clamp(float a, float mn, float mx) #endif +#ifndef __KERNEL_CUDA__ + +ccl_device_inline float saturate(float a) +{ + return clamp(a, 0.0f, 1.0f); +} + +#endif + ccl_device_inline int float_to_int(float f) { return (int)f; -- cgit v1.2.3 From 84836e8952451228aaef6f79fbfbca9c48c8346e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 28 Apr 2015 04:30:07 +1000 Subject: Cleanup: use strict flags --- source/blender/blenlib/intern/array_utils.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/source/blender/blenlib/intern/array_utils.c b/source/blender/blenlib/intern/array_utils.c index efa107ed703..6c5dc5a7f1e 100644 --- a/source/blender/blenlib/intern/array_utils.c +++ b/source/blender/blenlib/intern/array_utils.c @@ -33,17 +33,20 @@ #include "BLI_utildefines.h" #include "BLI_alloca.h" +#include "BLI_strict_flags.h" + void _bli_array_reverse(void *arr_v, unsigned int arr_len, size_t arr_stride) { - const unsigned int arr_half_stride = (arr_len / 2) * arr_stride; + const unsigned int arr_stride_uint = (unsigned int)arr_stride; + const unsigned int arr_half_stride = (arr_len / 2) * arr_stride_uint; unsigned int i, i_end; char *arr = arr_v; char *buf = BLI_array_alloca(buf, arr_stride); - for (i = 0, i_end = (arr_len - 1) * arr_stride; + for (i = 0, i_end = (arr_len - 1) * arr_stride_uint; i < arr_half_stride; - i += arr_stride, i_end -= arr_stride) + i += arr_stride_uint, i_end -= arr_stride_uint) { memcpy(buf, &arr[i], arr_stride); memcpy(&arr[i], &arr[i_end], arr_stride); @@ -76,7 +79,7 @@ void _bli_array_permute( const unsigned int *order, void *arr_temp) { const size_t len = arr_len * arr_stride; - const unsigned int arr_stride_uint = arr_stride; + const unsigned int arr_stride_uint = (unsigned int)arr_stride; void *arr_orig; unsigned int i; -- cgit v1.2.3 From f478c2cfbd3861cfca1d1a019066d30a4410a1f7 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Tue, 28 Apr 2015 00:51:55 +0500 Subject: Cycles: Added support for light portals This patch adds support for light portals: objects that help sampling the environment light, therefore improving convergence. Using them tor other lights in a unidirectional pathtracer is virtually useless. The sampling is done with the area-preserving code already used for area lamps. MIS is used both for combination of different portals and for combining portal- and envmap-sampling. The direction of portals is considered, they aren't used if the sampling point is behind them. Reviewers: sergey, dingto, #cycles Reviewed By: dingto, #cycles Subscribers: Lapineige, nutel, jtheninja, dsisco11, januz, vitorbalbio, candreacchio, TARDISMaker, lichtwerk, ace_dragon, marcog, mib2berlin, Tunge, lopataasdf, lordodin, sergey, dingto Differential Revision: https://developer.blender.org/D1133 --- intern/cycles/blender/addon/properties.py | 6 + intern/cycles/blender/addon/ui.py | 27 +- intern/cycles/blender/blender_object.cpp | 37 ++- intern/cycles/blender/blender_sync.h | 6 +- intern/cycles/kernel/kernel_emission.h | 2 +- intern/cycles/kernel/kernel_light.h | 416 +++++++++++++++++++++++------- intern/cycles/kernel/kernel_types.h | 7 + intern/cycles/render/light.cpp | 140 +++++++--- intern/cycles/render/light.h | 2 + 9 files changed, 485 insertions(+), 158 deletions(-) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 875b5d384e3..538876a71e2 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -694,6 +694,12 @@ class CyclesLampSettings(bpy.types.PropertyGroup): "reduces noise for area lamps and sharp glossy materials", default=False, ) + cls.is_portal = BoolProperty( + name="Is Portal", + description="Use this area lamp to guide sampling of the background, " + "note that this will make the lamp invisible", + default=False, + ) @classmethod def unregister(cls): diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 74de31850ee..cdacad75221 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -743,7 +743,10 @@ class CyclesLamp_PT_preview(CyclesButtonsPanel, Panel): @classmethod def poll(cls, context): - return context.lamp and CyclesButtonsPanel.poll(context) + return context.lamp and \ + not (context.lamp.type == 'AREA' and + context.lamp.cycles.is_portal) \ + and CyclesButtonsPanel.poll(context) def draw(self, context): self.layout.template_preview(context.lamp) @@ -781,13 +784,21 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel): sub.prop(lamp, "size", text="Size X") sub.prop(lamp, "size_y", text="Size Y") - if cscene.progressive == 'BRANCHED_PATH': - col.prop(clamp, "samples") - col.prop(clamp, "max_bounces") + if not (lamp.type == 'AREA' and clamp.is_portal): + sub = col.column(align=True) + if cscene.progressive == 'BRANCHED_PATH': + sub.prop(clamp, "samples") + sub.prop(clamp, "max_bounces") col = split.column() - col.prop(clamp, "cast_shadow") - col.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance") + + sub = col.column(align=True) + sub.active = not (lamp.type == 'AREA' and clamp.is_portal) + sub.prop(clamp, "cast_shadow") + sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance") + + if lamp.type == 'AREA': + col.prop(clamp, "is_portal", text="Portal") if lamp.type == 'HEMI': layout.label(text="Not supported, interpreted as sun lamp") @@ -799,7 +810,9 @@ class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel): @classmethod def poll(cls, context): - return context.lamp and CyclesButtonsPanel.poll(context) + return context.lamp and not (context.lamp.type == 'AREA' and + context.lamp.cycles.is_portal) and \ + CyclesButtonsPanel.poll(context) def draw(self, context): layout = self.layout diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 7364a8b170a..bcc366732df 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -90,14 +90,17 @@ static uint object_ray_visibility(BL::Object b_ob) /* Light */ -void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm) +void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm, bool *use_portal) { /* test if we need to sync */ Light *light; ObjectKey key(b_parent, persistent_id, b_ob); - if(!light_map.sync(&light, b_ob, b_parent, key)) + if(!light_map.sync(&light, b_ob, b_parent, key)) { + if(light->is_portal) + *use_portal = true; return; + } BL::Lamp b_lamp(b_ob.data()); @@ -171,6 +174,14 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI light->max_bounces = get_int(clamp, "max_bounces"); + if(light->type == LIGHT_AREA) + light->is_portal = get_boolean(clamp, "is_portal"); + else + light->is_portal = false; + + if(light->is_portal) + *use_portal = true; + /* visibility */ uint visibility = object_ray_visibility(b_ob); light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0; @@ -182,7 +193,7 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI light->tag_update(scene); } -void BlenderSync::sync_background_light() +void BlenderSync::sync_background_light(bool use_portal) { BL::World b_world = b_scene.world(); @@ -191,19 +202,20 @@ void BlenderSync::sync_background_light() PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles"); bool sample_as_light = get_boolean(cworld, "sample_as_light"); - if(sample_as_light) { + if(sample_as_light || use_portal) { /* test if we need to sync */ Light *light; ObjectKey key(b_world, 0, b_world); if(light_map.sync(&light, b_world, b_world, key) || - world_recalc || - b_world.ptr.data != world_map) + world_recalc || + b_world.ptr.data != world_map) { light->type = LIGHT_BACKGROUND; light->map_resolution = get_int(cworld, "sample_map_resolution"); light->shader = scene->default_background; - + light->use_mis = sample_as_light; + int samples = get_int(cworld, "samples"); if(get_boolean(cscene, "use_square_samples")) light->samples = samples * samples; @@ -223,7 +235,7 @@ void BlenderSync::sync_background_light() /* Object */ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, - Transform& tfm, uint layer_flag, float motion_time, bool hide_tris) + Transform& tfm, uint layer_flag, float motion_time, bool hide_tris, bool *use_portal) { BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent); bool motion = motion_time != 0.0f; @@ -232,7 +244,7 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P if(object_is_light(b_ob)) { /* don't use lamps for excluded layers used as mask layer */ if(!motion && !((layer_flag & render_layer.holdout_layer) && (layer_flag & render_layer.exclude_layer))) - sync_light(b_parent, persistent_id, b_ob, tfm); + sync_light(b_parent, persistent_id, b_ob, tfm, use_portal); return NULL; } @@ -476,6 +488,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time) int dupli_settings = preview ? 1 : 2; bool cancel = false; + bool use_portal = false; for(; b_sce && !cancel; b_sce = b_sce.background_set()) { for(b_sce.object_bases.begin(b_base); b_base != b_sce.object_bases.end() && !cancel; ++b_base) { @@ -506,7 +519,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time) BL::Array persistent_id = b_dup->persistent_id(); /* sync object and mesh or light data */ - Object *object = sync_object(b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion_time, hide_tris); + Object *object = sync_object(b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion_time, hide_tris, &use_portal); /* sync possible particle data, note particle_id * starts counting at 1, first is dummy particle */ @@ -526,7 +539,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time) if(!object_render_hide(b_ob, true, true, hide_tris)) { /* object itself */ Transform tfm = get_transform(b_ob.matrix_world()); - sync_object(b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion_time, hide_tris); + sync_object(b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion_time, hide_tris, &use_portal); } } @@ -537,7 +550,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time) progress.set_sync_status(""); if(!cancel && !motion) { - sync_background_light(); + sync_background_light(use_portal); /* handle removed data and modified pointers */ if(light_map.post_sync()) diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 5fbf2c3011f..89d93e19e9f 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -86,9 +86,9 @@ private: Mesh *sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris); void sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool motion, int time_index = 0); Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, - Transform& tfm, uint layer_flag, float motion_time, bool hide_tris); - void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm); - void sync_background_light(); + Transform& tfm, uint layer_flag, float motion_time, bool hide_tris, bool *use_portal); + void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm, bool *use_portal); + void sync_background_light(bool use_portal); void sync_mesh_motion(BL::Object b_ob, Object *object, float motion_time); void sync_camera_motion(BL::Object b_ob, float motion_time); diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index d3cbc5cff06..6c5a5fac8c5 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -254,7 +254,7 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg, PathState *sta if(!(state->flag & PATH_RAY_MIS_SKIP) && res) { /* multiple importance sampling, get background light pdf for ray * direction, and compute weight with respect to BSDF pdf */ - float pdf = background_light_pdf(kg, ray->D); + float pdf = background_light_pdf(kg, ray->P, ray->D); float mis_weight = power_heuristic(state->ray_pdf, pdf); return L*mis_weight; diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 76fa754b5fa..d1b8db2c018 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -33,6 +33,98 @@ typedef struct LightSample { LightType type; /* type of light */ } LightSample; +/* Area light sampling */ + +/* Uses the following paper: + * + * Carlos Urena et al. + * An Area-Preserving Parametrization for Spherical Rectangles. + * + * https://www.solidangle.com/research/egsr2013_spherical_rectangle.pdf + * + * Note: light_p is modified when sample_coord is true. + */ +ccl_device float area_light_sample(float3 P, + float3 *light_p, + float3 axisu, float3 axisv, + float randu, float randv, + bool sample_coord) +{ + /* In our name system we're using P for the center, + * which is o in the paper. + */ + + float3 corner = *light_p - axisu * 0.5f - axisv * 0.5f; + float axisu_len, axisv_len; + /* Compute local reference system R. */ + float3 x = normalize_len(axisu, &axisu_len); + float3 y = normalize_len(axisv, &axisv_len); + float3 z = cross(x, y); + /* Compute rectangle coords in local reference system. */ + float3 dir = corner - P; + float z0 = dot(dir, z); + /* Flip 'z' to make it point against Q. */ + if(z0 > 0.0f) { + z *= -1.0f; + z0 *= -1.0f; + } + float x0 = dot(dir, x); + float y0 = dot(dir, y); + float x1 = x0 + axisu_len; + float y1 = y0 + axisv_len; + /* Create vectors to four vertices. */ + float3 v00 = make_float3(x0, y0, z0); + float3 v01 = make_float3(x0, y1, z0); + float3 v10 = make_float3(x1, y0, z0); + float3 v11 = make_float3(x1, y1, z0); + /* Compute normals to edges. */ + float3 n0 = normalize(cross(v00, v10)); + float3 n1 = normalize(cross(v10, v11)); + float3 n2 = normalize(cross(v11, v01)); + float3 n3 = normalize(cross(v01, v00)); + /* Compute internal angles (gamma_i). */ + float g0 = safe_acosf(-dot(n0, n1)); + float g1 = safe_acosf(-dot(n1, n2)); + float g2 = safe_acosf(-dot(n2, n3)); + float g3 = safe_acosf(-dot(n3, n0)); + /* Compute predefined constants. */ + float b0 = n0.z; + float b1 = n2.z; + float b0sq = b0 * b0; + float k = M_2PI_F - g2 - g3; + /* Compute solid angle from internal angles. */ + float S = g0 + g1 - k; + + if(sample_coord) { + /* Compute cu. */ + float au = randu * S + k; + float fu = (cosf(au) * b0 - b1) / sinf(au); + float cu = 1.0f / sqrtf(fu * fu + b0sq) * (fu > 0.0f ? 1.0f : -1.0f); + cu = clamp(cu, -1.0f, 1.0f); + /* Compute xu. */ + float xu = -(cu * z0) / sqrtf(1.0f - cu * cu); + xu = clamp(xu, x0, x1); + /* Compute yv. */ + float z0sq = z0 * z0; + float y0sq = y0 * y0; + float y1sq = y1 * y1; + float d = sqrtf(xu * xu + z0sq); + float h0 = y0 / sqrtf(d * d + y0sq); + float h1 = y1 / sqrtf(d * d + y1sq); + float hv = h0 + randv * (h1 - h0), hv2 = hv * hv; + float yv = (hv2 < 1.0f - 1e-6f) ? (hv * d) / sqrtf(1.0f - hv2) : y1; + + /* Transform (xu, yv, z0) to world coords. */ + *light_p = P + xu * x + yv * y + z0 * z; + } + + /* return pdf */ + if(S != 0.0f) + return 1.0f / S; + else + return 0.0f; +} + /* Background Light */ #ifdef __BACKGROUND_MIS__ @@ -46,7 +138,7 @@ ccl_device_noinline #else ccl_device #endif -float3 background_light_sample(KernelGlobals *kg, float randu, float randv, float *pdf) +float3 background_map_sample(KernelGlobals *kg, float randu, float randv, float *pdf) { /* for the following, the CDF values are actually a pair of floats, with the * function value as X and the actual CDF as Y. The last entry's function @@ -116,10 +208,8 @@ float3 background_light_sample(KernelGlobals *kg, float randu, float randv, floa else *pdf = (cdf_u.x * cdf_v.x)/(M_2PI_F * M_PI_F * sin_theta * denom); - *pdf *= kernel_data.integrator.pdf_lights; - /* compute direction */ - return -equirectangular_to_direction(u, v); + return equirectangular_to_direction(u, v); } /* TODO(sergey): Same as above, after the release we should consider using @@ -130,7 +220,7 @@ ccl_device_noinline #else ccl_device #endif -float background_light_pdf(KernelGlobals *kg, float3 direction) +float background_map_pdf(KernelGlobals *kg, float3 direction) { float2 uv = direction_to_equirectangular(direction); int res = kernel_data.integrator.pdf_background_res; @@ -156,9 +246,228 @@ float background_light_pdf(KernelGlobals *kg, float3 direction) float2 cdf_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * (res + 1) + index_u); float2 cdf_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v); - float pdf = (cdf_u.x * cdf_v.x)/(M_2PI_F * M_PI_F * sin_theta * denom); + return (cdf_u.x * cdf_v.x)/(M_2PI_F * M_PI_F * sin_theta * denom); +} + +ccl_device float background_portal_pdf(KernelGlobals *kg, + float3 P, + float3 direction, + int ignore_portal, + bool *is_possible) +{ + float portal_pdf = 0.0f; + if(is_possible) + *is_possible = false; + + for(int p = 0; p < kernel_data.integrator.num_portals; p++) { + if(p == ignore_portal) + continue; + + /* TODO(sergey): Consider moving portal data fetch to a + * dedicated function. + */ + float4 data0 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 0); + float4 data3 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 3); + + float3 lightpos = make_float3(data0.y, data0.z, data0.w); + float3 dir = make_float3(data3.y, data3.z, data3.w); + + if(dot(dir, P - lightpos) <= 1e-5f) { + /* P is on the wrong side or too close. */ + continue; + } + + if(is_possible) { + /* There's a portal that could be sampled from this position. */ + *is_possible = true; + } + + float t = -(dot(P, dir) - dot(lightpos, dir)) / dot(direction, dir); + if(t <= 1e-5f) { + /* Either behind the portal or too close. */ + continue; + } + + float4 data1 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 1); + float4 data2 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 2); + + float3 axisu = make_float3(data1.y, data1.z, data1.w); + float3 axisv = make_float3(data2.y, data2.z, data2.w); + + float3 hit = P + t*direction; + float3 inplane = hit - lightpos; + /* Skip if the the ray doesn't pass through portal. */ + if(fabsf(dot(inplane, axisu) / dot(axisu, axisu)) > 0.5f) + continue; + if(fabsf(dot(inplane, axisv) / dot(axisv, axisv)) > 0.5f) + continue; + + portal_pdf += area_light_sample(P, &lightpos, axisu, axisv, 0.0f, 0.0f, false); + } + + return kernel_data.integrator.num_portals? portal_pdf / kernel_data.integrator.num_portals: 0.0f; +} + +ccl_device int background_num_possible_portals(KernelGlobals *kg, float3 P) +{ + int num_possible_portals = 0; + for(int p = 0; p < kernel_data.integrator.num_portals; p++) { + float4 data0 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 0); + float4 data3 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 3); + float3 lightpos = make_float3(data0.y, data0.z, data0.w); + float3 dir = make_float3(data3.y, data3.z, data3.w); + + /* Check whether portal is on the right side. */ + if(dot(dir, P - lightpos) > 1e-5f) + num_possible_portals++; + } + return num_possible_portals; +} + +ccl_device float3 background_portal_sample(KernelGlobals *kg, + float3 P, + float randu, + float randv, + int num_possible, + int *sampled_portal, + float *pdf) +{ + /* Pick a portal, then re-normalize randv. */ + randv *= num_possible; + int portal = (int)randv; + randv -= portal; + + /* TODO(sergey): Some smarter way of finding portal to sample + * is welcome. + */ + for(int p = 0; p < kernel_data.integrator.num_portals; p++) { + /* Search for the sampled portal. */ + float4 data0 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 0); + float4 data3 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 3); + float3 lightpos = make_float3(data0.y, data0.z, data0.w); + float3 dir = make_float3(data3.y, data3.z, data3.w); + + /* Check whether portal is on the right side. */ + if(dot(dir, P - lightpos) <= 1e-5f) + continue; + + if(portal == 0) { + /* p is the portal to be sampled. */ + float4 data1 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 1); + float4 data2 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 2); + float3 axisu = make_float3(data1.y, data1.z, data1.w); + float3 axisv = make_float3(data2.y, data2.z, data2.w); + + float3 lightPoint = lightpos; + + *pdf = area_light_sample(P, &lightPoint, + axisu, axisv, + randu, randv, + true); + + *pdf /= num_possible; + *sampled_portal = p; + return normalize(lightPoint - P); + } + + portal--; + } + + return make_float3(0.0f, 0.0f, 0.0f); +} + +ccl_device float3 background_light_sample(KernelGlobals *kg, float3 P, float randu, float randv, float *pdf) +{ + /* Probability of sampling portals instead of the map. */ + float portal_sampling_pdf = kernel_data.integrator.portal_pdf; + + /* Check if there are portals in the scene which we can sample. */ + if(portal_sampling_pdf > 0.0f) { + int num_portals = background_num_possible_portals(kg, P); + if(num_portals > 0) { + if(portal_sampling_pdf == 1.0f || randu < portal_sampling_pdf) { + if(portal_sampling_pdf < 1.0f) { + randu /= portal_sampling_pdf; + } + int portal; + float3 D = background_portal_sample(kg, P, randu, randv, num_portals, &portal, pdf); + if(num_portals > 1) { + /* Ignore the chosen portal, its pdf is already included. */ + *pdf += background_portal_pdf(kg, P, D, portal, NULL); + } + /* We could also have sampled the map, so combine with MIS. */ + if(portal_sampling_pdf < 1.0f) { + float cdf_pdf = background_map_pdf(kg, D); + *pdf = (portal_sampling_pdf * (*pdf) + + (1.0f - portal_sampling_pdf) * cdf_pdf); + } + return D; + } else { + /* Sample map, but with nonzero portal_sampling_pdf for MIS. */ + randu = (randu - portal_sampling_pdf) / (1.0f - portal_sampling_pdf); + } + } else { + /* We can't sample a portal. + * Check if we can sample the map instead. + */ + if(portal_sampling_pdf == 1.0f) { + /* Use uniform as a fallback if we can't sample the map. */ + *pdf = 1.0f / M_4PI_F; + return sample_uniform_sphere(randu, randv); + } + else { + portal_sampling_pdf = 0.0f; + } + } + } + + float3 D = background_map_sample(kg, randu, randv, pdf); + /* Use MIS if portals could be sampled as well. */ + if(portal_sampling_pdf > 0.0f) { + float portal_pdf = background_portal_pdf(kg, P, D, -1, NULL); + *pdf = (portal_sampling_pdf * portal_pdf + + (1.0f - portal_sampling_pdf) * (*pdf)); + } + return D; +} - return pdf * kernel_data.integrator.pdf_lights; +ccl_device float background_light_pdf(KernelGlobals *kg, float3 P, float3 direction) +{ + /* Probability of sampling portals instead of the map. */ + float portal_sampling_pdf = kernel_data.integrator.portal_pdf; + + if(portal_sampling_pdf > 0.0f) { + bool is_possible; + float portal_pdf = background_portal_pdf(kg, P, direction, -1, &is_possible); + if(portal_pdf == 0.0f) { + if(portal_sampling_pdf == 1.0f) { + /* If there are no possible portals at this point, + * the fallback sampling would have been used. + * Otherwise, the direction would not be sampled at all => pdf = 0 + */ + return is_possible? 0.0f: kernel_data.integrator.pdf_lights / M_4PI_F; + } + else { + /* We can only sample the map. */ + return background_map_pdf(kg, direction) * kernel_data.integrator.pdf_lights; + } + } else { + if(portal_sampling_pdf == 1.0f) { + /* We can only sample portals. */ + return portal_pdf * kernel_data.integrator.pdf_lights; + } + else { + /* We can sample both, so combine with MIS. */ + return (background_map_pdf(kg, direction) * (1.0f - portal_sampling_pdf) + + portal_pdf * portal_sampling_pdf) * kernel_data.integrator.pdf_lights; + } + } + } + + /* No portals in the scene, so must sample the map. + * At least one of them is always possible if we have a LIGHT_BACKGROUND. + */ + return background_map_pdf(kg, direction) * kernel_data.integrator.pdf_lights; } #endif @@ -184,96 +493,6 @@ ccl_device float3 sphere_light_sample(float3 P, float3 center, float radius, flo return disk_light_sample(normalize(P - center), randu, randv)*radius; } -/* Uses the following paper: - * - * Carlos Urena et al. - * An Area-Preserving Parametrization for Spherical Rectangles. - * - * https://www.solidangle.com/research/egsr2013_spherical_rectangle.pdf - * - * Note: light_p is modified when sample_coord is true. - */ -ccl_device float area_light_sample(float3 P, - float3 *light_p, - float3 axisu, float3 axisv, - float randu, float randv, - bool sample_coord) -{ - /* In our name system we're using P for the center, - * which is o in the paper. - */ - - float3 corner = *light_p - axisu * 0.5f - axisv * 0.5f; - float axisu_len, axisv_len; - /* Compute local reference system R. */ - float3 x = normalize_len(axisu, &axisu_len); - float3 y = normalize_len(axisv, &axisv_len); - float3 z = cross(x, y); - /* Compute rectangle coords in local reference system. */ - float3 dir = corner - P; - float z0 = dot(dir, z); - /* Flip 'z' to make it point against Q. */ - if(z0 > 0.0f) { - z *= -1.0f; - z0 *= -1.0f; - } - float x0 = dot(dir, x); - float y0 = dot(dir, y); - float x1 = x0 + axisu_len; - float y1 = y0 + axisv_len; - /* Create vectors to four vertices. */ - float3 v00 = make_float3(x0, y0, z0); - float3 v01 = make_float3(x0, y1, z0); - float3 v10 = make_float3(x1, y0, z0); - float3 v11 = make_float3(x1, y1, z0); - /* Compute normals to edges. */ - float3 n0 = normalize(cross(v00, v10)); - float3 n1 = normalize(cross(v10, v11)); - float3 n2 = normalize(cross(v11, v01)); - float3 n3 = normalize(cross(v01, v00)); - /* Compute internal angles (gamma_i). */ - float g0 = safe_acosf(-dot(n0, n1)); - float g1 = safe_acosf(-dot(n1, n2)); - float g2 = safe_acosf(-dot(n2, n3)); - float g3 = safe_acosf(-dot(n3, n0)); - /* Compute predefined constants. */ - float b0 = n0.z; - float b1 = n2.z; - float b0sq = b0 * b0; - float k = M_2PI_F - g2 - g3; - /* Compute solid angle from internal angles. */ - float S = g0 + g1 - k; - - if(sample_coord) { - /* Compute cu. */ - float au = randu * S + k; - float fu = (cosf(au) * b0 - b1) / sinf(au); - float cu = 1.0f / sqrtf(fu * fu + b0sq) * (fu > 0.0f ? 1.0f : -1.0f); - cu = clamp(cu, -1.0f, 1.0f); - /* Compute xu. */ - float xu = -(cu * z0) / sqrtf(1.0f - cu * cu); - xu = clamp(xu, x0, x1); - /* Compute yv. */ - float z0sq = z0 * z0; - float y0sq = y0 * y0; - float y1sq = y1 * y1; - float d = sqrtf(xu * xu + z0sq); - float h0 = y0 / sqrtf(d * d + y0sq); - float h1 = y1 / sqrtf(d * d + y1sq); - float hv = h0 + randv * (h1 - h0), hv2 = hv * hv; - float yv = (hv2 < 1.0f - 1e-6f) ? (hv * d) / sqrtf(1.0f - hv2) : y1; - - /* Transform (xu, yv, z0) to world coords. */ - *light_p = P + xu * x + yv * y + z0 * z; - } - - /* return pdf */ - if(S != 0.0f) - return 1.0f / S; - else - return 0.0f; -} - ccl_device float spot_light_attenuation(float4 data1, float4 data2, LightSample *ls) { float3 dir = make_float3(data2.y, data2.z, data2.w); @@ -344,13 +563,14 @@ ccl_device void lamp_light_sample(KernelGlobals *kg, int lamp, #ifdef __BACKGROUND_MIS__ else if(type == LIGHT_BACKGROUND) { /* infinite area light (e.g. light dome or env light) */ - float3 D = background_light_sample(kg, randu, randv, &ls->pdf); + float3 D = -background_light_sample(kg, P, randu, randv, &ls->pdf); ls->P = D; ls->Ng = D; ls->D = -D; ls->t = FLT_MAX; ls->eval_fac = 1.0f; + ls->pdf *= kernel_data.integrator.pdf_lights; } #endif else { diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 05cfb0adc71..f4f2e22edaa 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -896,6 +896,11 @@ typedef struct KernelIntegrator { float inv_pdf_lights; int pdf_background_res; + /* light portals */ + float portal_pdf; + int num_portals; + int portal_offset; + /* bounces */ int min_bounce; int max_bounce; @@ -948,6 +953,8 @@ typedef struct KernelIntegrator { int volume_max_steps; float volume_step_size; int volume_samples; + + int pad; } KernelIntegrator; typedef struct KernelBVH { diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 91e45aea17a..817e1f5806c 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -129,6 +129,8 @@ Light::Light() shader = 0; samples = 1; max_bounces = 1024; + + is_portal = false; } void Light::tag_update(Scene *scene) @@ -153,10 +155,17 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen progress.set_status("Updating Lights", "Computing distribution"); /* count */ - size_t num_lights = scene->lights.size(); + size_t num_lights = 0; size_t num_background_lights = 0; size_t num_triangles = 0; + bool background_mis = false; + + foreach(Light *light, scene->lights) { + if(!light->is_portal) + num_lights++; + } + foreach(Object *object, scene->objects) { Mesh *mesh = object->mesh; bool have_emission = false; @@ -287,22 +296,29 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen float trianglearea = totarea; /* point lights */ - float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f; + float lightarea = (totarea > 0.0f) ? totarea / num_lights : 1.0f; bool use_lamp_mis = false; - for(int i = 0; i < scene->lights.size(); i++, offset++) { - Light *light = scene->lights[i]; + int light_index = 0; + foreach(Light *light, scene->lights) { + if(light->is_portal) + continue; distribution[offset].x = totarea; - distribution[offset].y = __int_as_float(~(int)i); + distribution[offset].y = __int_as_float(~light_index); distribution[offset].z = 1.0f; distribution[offset].w = light->size; totarea += lightarea; if(light->size > 0.0f && light->use_mis) use_lamp_mis = true; - if(light->type == LIGHT_BACKGROUND) + if(light->type == LIGHT_BACKGROUND) { num_background_lights++; + background_mis = light->use_mis; + } + + light_index++; + offset++; } /* normalize cumulative distribution functions */ @@ -364,6 +380,18 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen /* CDF */ device->tex_alloc("__light_distribution", dscene->light_distribution); + + /* Portals */ + if(num_background_lights > 0 && light_index != scene->lights.size()) { + kintegrator->portal_offset = light_index; + kintegrator->num_portals = scene->lights.size() - light_index; + kintegrator->portal_pdf = background_mis? 0.5f: 1.0f; + } + else { + kintegrator->num_portals = 0; + kintegrator->portal_offset = 0; + kintegrator->portal_pdf = 0.0f; + } } else { dscene->light_distribution.clear(); @@ -374,6 +402,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen kintegrator->pdf_lights = 0.0f; kintegrator->inv_pdf_lights = 0.0f; kintegrator->use_lamp_mis = false; + kintegrator->num_portals = 0; + kintegrator->portal_offset = 0; + kintegrator->portal_pdf = 0.0f; + kfilm->pass_shadow_scale = 1.0f; } } @@ -515,8 +547,8 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE); - if(!device->info.advanced_shading) { - /* remove unsupported light */ + /* remove background light? */ + if(!(device->info.advanced_shading)) { foreach(Light *light, scene->lights) { if(light->type == LIGHT_BACKGROUND) { scene->lights.erase(std::remove(scene->lights.begin(), scene->lights.end(), light), scene->lights.end()); @@ -525,10 +557,14 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce } } - for(size_t i = 0; i < scene->lights.size(); i++) { - Light *light = scene->lights[i]; + int light_index = 0; + + foreach(Light *light, scene->lights) { + if(light->is_portal) + continue; + float3 co = light->co; - int shader_id = scene->shader_manager->get_shader_id(scene->lights[i]->shader); + int shader_id = scene->shader_manager->get_shader_id(light->shader); float samples = __int_as_float(light->samples); float max_bounces = __int_as_float(light->max_bounces); @@ -561,11 +597,11 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce if(light->use_mis && radius > 0.0f) shader_id |= SHADER_USE_MIS; - light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); - light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f); - light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); - light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f); + light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); + light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f); + light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); + light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f); } else if(light->type == LIGHT_DISTANT) { shader_id &= ~SHADER_AREA_LIGHT; @@ -582,11 +618,11 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce if(light->use_mis && area > 0.0f) shader_id |= SHADER_USE_MIS; - light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z); - light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea); - light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); - light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f); + light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z); + light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea); + light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); + light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f); } else if(light->type == LIGHT_BACKGROUND) { uint visibility = scene->background->visibility; @@ -611,11 +647,11 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce use_light_visibility = true; } - light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), 0.0f, 0.0f, 0.0f); - light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f); - light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); - light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f); + light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), 0.0f, 0.0f, 0.0f); + light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f); + light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); + light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f); } else if(light->type == LIGHT_AREA) { float3 axisu = light->axisu*(light->sizeu*light->size); @@ -629,11 +665,11 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce if(light->use_mis && area > 0.0f) shader_id |= SHADER_USE_MIS; - light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); - light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z); - light_data[i*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z); - light_data[i*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z); - light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f); + light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); + light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z); + light_data[light_index*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z); + light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z); + light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f); } else if(light->type == LIGHT_SPOT) { shader_id &= ~SHADER_AREA_LIGHT; @@ -649,14 +685,44 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce if(light->use_mis && radius > 0.0f) shader_id |= SHADER_USE_MIS; - light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); - light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle); - light_data[i*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z); - light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); - light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f); + light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); + light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle); + light_data[light_index*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z); + light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); + light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f); } + + light_index++; } - + + /* TODO(sergey): Consider moving portals update to their own function + * keeping this one more manageable. + */ + foreach(Light *light, scene->lights) { + if(!light->is_portal) + continue; + assert(light->type == LIGHT_AREA); + + float3 co = light->co; + float3 axisu = light->axisu*(light->sizeu*light->size); + float3 axisv = light->axisv*(light->sizev*light->size); + float area = len(axisu)*len(axisv); + float invarea = (area > 0.0f) ? 1.0f / area : 1.0f; + float3 dir = light->dir; + + dir = safe_normalize(dir); + + light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); + light_data[light_index*LIGHT_SIZE + 1] = make_float4(area, axisu.x, axisu.y, axisu.z); + light_data[light_index*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z); + light_data[light_index*LIGHT_SIZE + 3] = make_float4(-1, dir.x, dir.y, dir.z); + light_data[light_index*LIGHT_SIZE + 4] = make_float4(-1, 0.0f, 0.0f, 0.0f); + + light_index++; + } + + assert(light_index == scene->lights.size()); + device->tex_alloc("__light_data", dscene->light_data); } diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h index 1f8eac6a97f..824d99aeb93 100644 --- a/intern/cycles/render/light.h +++ b/intern/cycles/render/light.h @@ -56,6 +56,8 @@ public: bool use_transmission; bool use_scatter; + bool is_portal; + int shader; int samples; int max_bounces; -- cgit v1.2.3 From a4965249ec035953249abd2bdc47a86c764f4040 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 28 Apr 2015 06:54:17 +1000 Subject: Math Lib: add range_vn_u --- source/blender/blenlib/BLI_math_vector.h | 1 + source/blender/blenlib/intern/math_vector.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 9c8a9f54379..82a2b9c9ab2 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -314,6 +314,7 @@ double len_squared_vn(const float *array, const int size) ATTR_WARN_UNUSED_RESUL float normalize_vn_vn(float *array_tar, const float *array_src, const int size); float normalize_vn(float *array_tar, const int size); void range_vn_i(int *array_tar, const int size, const int start); +void range_vn_u(unsigned int *array_tar, const int size, const unsigned int start); void range_vn_fl(float *array_tar, const int size, const float start, const float step); void negate_vn(float *array_tar, const int size); void negate_vn_vn(float *array_tar, const float *array_src, const int size); diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index e9909cef29d..8f536bfe75c 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -897,6 +897,16 @@ void range_vn_i(int *array_tar, const int size, const int start) } } +void range_vn_u(unsigned int *array_tar, const int size, const unsigned int start) +{ + unsigned int *array_pt = array_tar + (size - 1); + unsigned int j = start + (unsigned int)(size - 1); + int i = size; + while (i--) { + *(array_pt--) = j--; + } +} + void range_vn_fl(float *array_tar, const int size, const float start, const float step) { float *array_pt = array_tar + (size - 1); -- cgit v1.2.3 From 58a2b10a65872b2e4a3654a54a83e6f94bf4e229 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Mon, 27 Apr 2015 23:12:53 +0200 Subject: Cycles: Initialize portal variable directly, so we can avoid the one NULL check. --- intern/cycles/kernel/kernel_light.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index d1b8db2c018..704fb49efc9 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -256,8 +256,6 @@ ccl_device float background_portal_pdf(KernelGlobals *kg, bool *is_possible) { float portal_pdf = 0.0f; - if(is_possible) - *is_possible = false; for(int p = 0; p < kernel_data.integrator.num_portals; p++) { if(p == ignore_portal) @@ -437,7 +435,7 @@ ccl_device float background_light_pdf(KernelGlobals *kg, float3 P, float3 direct float portal_sampling_pdf = kernel_data.integrator.portal_pdf; if(portal_sampling_pdf > 0.0f) { - bool is_possible; + bool is_possible = false; float portal_pdf = background_portal_pdf(kg, P, direction, -1, &is_possible); if(portal_pdf == 0.0f) { if(portal_sampling_pdf == 1.0f) { -- cgit v1.2.3 From 4288ab16e5c83bd0763d8ee580731d9ea7eacde1 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Tue, 28 Apr 2015 07:24:56 +1000 Subject: Add material slot reorder buttons --- .../scripts/startup/bl_ui/properties_material.py | 13 +++- source/blender/blenkernel/BKE_curve.h | 1 + source/blender/blenkernel/BKE_material.h | 1 + source/blender/blenkernel/BKE_mesh.h | 1 + source/blender/blenkernel/intern/curve.c | 48 +++++++++++++++ source/blender/blenkernel/intern/material.c | 32 ++++++++++ source/blender/blenkernel/intern/mesh.c | 30 ++++++++++ source/blender/editors/render/render_intern.h | 1 + source/blender/editors/render/render_ops.c | 1 + source/blender/editors/render/render_shading.c | 70 +++++++++++++++++++++- 10 files changed, 196 insertions(+), 2 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py index cea0c9aef95..79199400b63 100644 --- a/release/scripts/startup/bl_ui/properties_material.py +++ b/release/scripts/startup/bl_ui/properties_material.py @@ -123,11 +123,16 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel): ob = context.object slot = context.material_slot space = context.space_data + is_sortable = (len(ob.material_slots) > 1) if ob: + rows = 1 + if is_sortable: + rows = 4 + row = layout.row() - row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=1) + row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows) col = row.column(align=True) col.operator("object.material_slot_add", icon='ZOOMIN', text="") @@ -135,6 +140,12 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel): col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="") + if is_sortable: + col.separator() + + col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP' + col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN' + if ob.mode == 'EDIT': row = layout.row(align=True) row.operator("object.material_slot_assign", text="Assign") diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index ec3c0447269..98c85415812 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -90,6 +90,7 @@ void BKE_curve_translate(struct Curve *cu, float offset[3], const bool do_keys); void BKE_curve_material_index_remove(struct Curve *cu, int index); void BKE_curve_material_index_clear(struct Curve *cu); int BKE_curve_material_index_validate(struct Curve *cu); +void BKE_curve_material_remap(struct Curve *cu,const unsigned int *remap, unsigned int remap_len); ListBase *BKE_curve_nurbs_get(struct Curve *cu); diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 56393727d28..0cfa1aeecb5 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -50,6 +50,7 @@ void BKE_material_free_ex(struct Material *ma, bool do_id_user); void test_object_materials(struct Main *bmain, struct ID *id); void BKE_material_resize_object(struct Object *ob, const short totcol, bool do_id_user); void init_material(struct Material *ma); +void BKE_material_remap_object(struct Object *ob, const unsigned int *remap); struct Material *BKE_material_add(struct Main *bmain, const char *name); struct Material *BKE_material_copy(struct Material *ma); struct Material *localize_material(struct Material *ma); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index c0d8902eb71..ebf4384d5a7 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -108,6 +108,7 @@ void BKE_mesh_to_curve_nurblist(struct DerivedMesh *dm, struct ListBase *nurblis void BKE_mesh_to_curve(struct Scene *scene, struct Object *ob); void BKE_mesh_material_index_remove(struct Mesh *me, short index); void BKE_mesh_material_index_clear(struct Mesh *me); +void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len); void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth); const char *BKE_mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 5fcdc9c2e78..cd59e30a406 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -4492,6 +4492,54 @@ int BKE_curve_material_index_validate(Curve *cu) } } +void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int remap_len) +{ + const int curvetype = BKE_curve_type_get(cu); + const short remap_len_short = (short)remap_len; + +#define MAT_NR_REMAP(n) \ + if (n < remap_len_short) { \ + BLI_assert(n >= 0 && remap[n] < remap_len_short); \ + n = remap[n]; \ + } ((void)0) + + if (curvetype == OB_FONT) { + struct CharInfo *strinfo; + int charinfo_len, i; + + if (cu->editfont) { + EditFont *ef = cu->editfont; + strinfo = ef->textbufinfo; + charinfo_len = ef->len; + } + else { + strinfo = cu->strinfo; + charinfo_len = cu->len_wchar; + } + + for (i = 0; i <= charinfo_len; i++) { + if (strinfo[i].mat_nr > 0) { + strinfo[i].mat_nr -= 1; + MAT_NR_REMAP(strinfo[i].mat_nr); + strinfo[i].mat_nr += 1; + } + } + } + else { + Nurb *nu; + ListBase *nurbs = BKE_curve_editNurbs_get(cu); + + if (nurbs) { + for (nu = nurbs->first; nu; nu = nu->next) { + MAT_NR_REMAP(nu->mat_nr); + } + } + } + +#undef MAT_NR_REMAP + +} + void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect) { r_rect->xmin = cu->xof + tb->x; diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index c7e6b3ba1b3..8932ac1f4c6 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -53,6 +53,7 @@ #include "BLI_listbase.h" #include "BLI_utildefines.h" #include "BLI_string.h" +#include "BLI_array_utils.h" #include "BKE_animsys.h" #include "BKE_displist.h" @@ -66,6 +67,8 @@ #include "BKE_scene.h" #include "BKE_node.h" #include "BKE_curve.h" +#include "BKE_editmesh.h" +#include "BKE_font.h" #include "GPU_material.h" @@ -922,6 +925,35 @@ void assign_material(Object *ob, Material *ma, short act, int assign_type) test_object_materials(G.main, ob->data); } + +void BKE_material_remap_object(Object *ob, const unsigned int *remap) +{ + Material ***matar = give_matarar(ob); + const short *totcol_p = give_totcolp(ob); + + BLI_array_permute(ob->mat, ob->totcol, remap); + + if (ob->matbits) { + BLI_array_permute(ob->matbits, ob->totcol, remap); + } + + if(matar) { + BLI_array_permute(*matar, *totcol_p, remap); + } + + if (ob->type == OB_MESH) { + BKE_mesh_material_remap(ob->data, remap, ob->totcol); + } + else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { + BKE_curve_material_remap(ob->data, remap, ob->totcol); + } + else { + /* add support for this object data! */ + BLI_assert(matar == NULL); + } +} + + /* XXX - this calls many more update calls per object then are needed, could be optimized */ void assign_matarar(struct Object *ob, struct Material ***matar, short totcol) { diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 87325a7ff47..12379bedb36 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1773,6 +1773,36 @@ void BKE_mesh_material_index_clear(Mesh *me) } } +void BKE_mesh_material_remap(Mesh *me, const unsigned int *remap, unsigned int remap_len) +{ + const short remap_len_short = (short)remap_len; + +#define MAT_NR_REMAP(n) \ + if (n < remap_len_short) { \ + BLI_assert(n >= 0 && remap[n] < remap_len_short); \ + n = remap[n]; \ + } ((void)0) + + if (me->edit_btmesh) { + BMEditMesh *em = me->edit_btmesh; + BMIter iter; + BMFace *efa; + + BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) { + MAT_NR_REMAP(efa->mat_nr); + } + } + else { + int i; + for (i = 0; i < me->totpoly; i++) { + MAT_NR_REMAP(me->mpoly[i].mat_nr); + } + } + +#undef MAT_NR_REMAP + +} + void BKE_mesh_smooth_flag_set(Object *meshOb, int enableSmooth) { Mesh *me = meshOb->data; diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h index 5c6744b0248..54429f9f066 100644 --- a/source/blender/editors/render/render_intern.h +++ b/source/blender/editors/render/render_intern.h @@ -44,6 +44,7 @@ void OBJECT_OT_material_slot_assign(struct wmOperatorType *ot); void OBJECT_OT_material_slot_select(struct wmOperatorType *ot); void OBJECT_OT_material_slot_deselect(struct wmOperatorType *ot); void OBJECT_OT_material_slot_copy(struct wmOperatorType *ot); +void OBJECT_OT_material_slot_move(struct wmOperatorType *ot); void MATERIAL_OT_new(struct wmOperatorType *ot); void TEXTURE_OT_new(struct wmOperatorType *ot); diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c index 6aaad98f946..f98083f7e74 100644 --- a/source/blender/editors/render/render_ops.c +++ b/source/blender/editors/render/render_ops.c @@ -47,6 +47,7 @@ void ED_operatortypes_render(void) WM_operatortype_append(OBJECT_OT_material_slot_select); WM_operatortype_append(OBJECT_OT_material_slot_deselect); WM_operatortype_append(OBJECT_OT_material_slot_copy); + WM_operatortype_append(OBJECT_OT_material_slot_move); WM_operatortype_append(MATERIAL_OT_new); WM_operatortype_append(TEXTURE_OT_new); diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 3de21536148..88f522a2615 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -41,8 +41,9 @@ #include "DNA_space_types.h" #include "DNA_world_types.h" -#include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_math_vector.h" #include "BLF_translation.h" @@ -381,6 +382,73 @@ void OBJECT_OT_material_slot_copy(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } +static int material_slot_move_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_context(C); + + unsigned int *slot_remap; + int index_pair[2]; + + int dir = RNA_enum_get(op->ptr, "direction"); + + if (!ob || ob->totcol < 2) { + return OPERATOR_CANCELLED; + } + + /* up */ + if (dir == 1 && ob->actcol > 1) { + index_pair[0] = ob->actcol - 2; + index_pair[1] = ob->actcol - 1; + ob->actcol--; + } + /* down */ + else if (dir == -1 && ob->actcol < ob->totcol) { + index_pair[0] = ob->actcol - 1; + index_pair[1] = ob->actcol - 0; + ob->actcol++; + } + else { + return OPERATOR_CANCELLED; + } + + slot_remap = MEM_mallocN(sizeof(unsigned int) * ob->totcol, __func__); + + range_vn_u(slot_remap, ob->totcol, 0); + + slot_remap[index_pair[0]] = index_pair[1]; + slot_remap[index_pair[1]] = index_pair[0]; + + BKE_material_remap_object(ob, slot_remap); + + MEM_freeN(slot_remap); + + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW | ND_DATA, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_material_slot_move(wmOperatorType *ot) +{ + static EnumPropertyItem material_slot_move[] = { + {1, "UP", 0, "Up", ""}, + {-1, "DOWN", 0, "Down", ""}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "Move Material"; + ot->idname = "OBJECT_OT_material_slot_move"; + ot->description = "Move the active material up/down in the list"; + + /* api callbacks */ + ot->exec = material_slot_move_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "direction", material_slot_move, 0, "Direction", "Direction to move, UP or DOWN"); +} + /********************** new material operator *********************/ static int new_material_exec(bContext *C, wmOperator *UNUSED(op)) -- cgit v1.2.3 From 7e36c280c2b268822862169c5493d4d6adaa818e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 28 Apr 2015 16:47:31 +1000 Subject: Cleanup: redundant checks --- source/blender/bmesh/intern/bmesh_core.c | 4 +--- source/blender/bmesh/tools/bmesh_edgesplit.c | 11 ----------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 743dc8502d7..7d6743e7598 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -2174,9 +2174,7 @@ void bmesh_vert_separate( * if you are tidying up code - campbell */ STACK_INIT(stack, v_edgetot); BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - if (l->v == v) { - STACK_PUSH(stack, (BMEdge *)l); - } + STACK_PUSH(stack, (BMEdge *)l); } while ((l = (BMLoop *)(STACK_POP(stack)))) { if ((i = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&visithash, (uintptr_t)l->e)))) { diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c index 947b77675d8..c01b4880d7a 100644 --- a/source/blender/bmesh/tools/bmesh_edgesplit.c +++ b/source/blender/bmesh/tools/bmesh_edgesplit.c @@ -168,17 +168,6 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con } } - if (use_verts) { - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e->v1, BM_ELEM_TAG) == false) { - BM_elem_flag_disable(e->v1, BM_ELEM_TAG); - } - if (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == false) { - BM_elem_flag_disable(e->v2, BM_ELEM_TAG); - } - } - } - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_TAG)) { unsigned int i; -- cgit v1.2.3 From 5c6ec169ccb257a0f1d7f0aafa83f3d5ff866ba1 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Tue, 28 Apr 2015 10:52:19 +0200 Subject: Added missing update tag to recalculate data after permutating materials --- source/blender/editors/render/render_shading.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 88f522a2615..617364c7e74 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -422,6 +422,7 @@ static int material_slot_move_exec(bContext *C, wmOperator *op) MEM_freeN(slot_remap); + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW | ND_DATA, ob); return OPERATOR_FINISHED; -- cgit v1.2.3 From 2edb342ffad63aa6ff37b852a0d40366254639ff Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 28 Apr 2015 18:48:41 +1000 Subject: Fix for Clang type check --- source/blender/bmesh/bmesh_class.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index 10048a16590..ada0fabd28e 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -263,7 +263,9 @@ enum { #define _BM_GENERIC_TYPE_ELEM_CONST \ const void *, const BMVert *, const BMEdge *, const BMLoop *, const BMFace *, \ - const BMElem *, const BMElemF *, const BMHeader * + const BMElem *, const BMElemF *, const BMHeader *, \ + void * const, BMVert * const, BMEdge * const, BMLoop * const, BMFace * const, \ + BMElem * const, BMElemF * const, BMHeader * const #define BM_CHECK_TYPE_ELEM_CONST(ele) \ CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPES_CONST) -- cgit v1.2.3 From eee666583fe0d863a9243d0a650a5d1b63d010b2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 28 Apr 2015 18:37:28 +1000 Subject: Use gnu89 for GCC GCC5 defaults to gnu11, which we may switch to later but disable for now to prevent accidental use. --- CMakeLists.txt | 6 ++++++ build_files/scons/config/linux-config.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bdaefb0d590..4724e101603 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1156,6 +1156,12 @@ if(UNIX AND NOT APPLE) # GNU Compiler if(CMAKE_COMPILER_IS_GNUCC) set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") + + if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "5.0") + # GCC5 uses gnu11, until we update, force c89 + # though some c11 features can still be used. + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu89") + endif() # CLang is the same as GCC for now. elseif(CMAKE_C_COMPILER_ID MATCHES "Clang") set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") diff --git a/build_files/scons/config/linux-config.py b/build_files/scons/config/linux-config.py index 455dd23cdb3..c3f0c434081 100644 --- a/build_files/scons/config/linux-config.py +++ b/build_files/scons/config/linux-config.py @@ -230,7 +230,7 @@ WITH_BF_FREESTYLE = True CC = 'gcc' CXX = 'g++' -CCFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing','-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64','-D_LARGEFILE64_SOURCE'] +CCFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing', '-std=gnu89', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64','-D_LARGEFILE64_SOURCE'] CXXFLAGS = [] CPPFLAGS = [] -- cgit v1.2.3 From d920b8e075ed949bd21297bb3baa4a8cb22428c9 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 28 Apr 2015 11:12:47 +0200 Subject: Fix T44530 UV islands fail on subsurf after mirror modifier. Caused by own commit that changed island detection code. In the case of modifiers we don't want to take winding information into account, but left the code since there are use cases (like painting) which could use this. --- source/blender/blenkernel/BKE_mesh_mapping.h | 2 +- source/blender/blenkernel/intern/mesh_mapping.c | 7 +++++-- source/blender/blenkernel/intern/subsurf_ccg.c | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h index da44c989146..dcf5d2ed78d 100644 --- a/source/blender/blenkernel/BKE_mesh_mapping.h +++ b/source/blender/blenkernel/BKE_mesh_mapping.h @@ -102,7 +102,7 @@ typedef struct MeshElemMap { /* mapping */ UvVertMap *BKE_mesh_uv_vert_map_create( struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv, - unsigned int totpoly, unsigned int totvert, int selected, float *limit); + unsigned int totpoly, unsigned int totvert, int selected, float *limit, bool use_winding); UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v); void BKE_mesh_uv_vert_map_free(UvVertMap *vmap); diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index ebdbd3aac8a..cc5006efacb 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -55,7 +55,7 @@ * but for now this replaces it because its unused. */ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv, - unsigned int totpoly, unsigned int totvert, int selected, float *limit) + unsigned int totpoly, unsigned int totvert, int selected, float *limit, bool use_winding) { UvVertMap *vmap; UvMapVert *buf; @@ -109,7 +109,10 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, buf++; } - winding[a] = cross_poly_v2((const float (*)[2])tf_uv, (unsigned int)nverts) > 0; + if (use_winding) + winding[a] = cross_poly_v2((const float (*)[2])tf_uv, (unsigned int)nverts) > 0; + else + winding[a] = 0; } } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index a4e0eaaa324..f81d5825120 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -300,7 +300,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */ limit[0] = limit[1] = STD_UV_CONNECT_LIMIT; - vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, 0, limit); + vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, 0, limit, false); if (!vmap) return 0; -- cgit v1.2.3 From 5e423775da5c85a0340d7acd302f6d3cbaa6b159 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Tue, 28 Apr 2015 11:11:39 +0200 Subject: Cleanup: Move Cycles volume stack update for subsurface into kernel_volume.h. --- intern/cycles/kernel/kernel_path.h | 29 ++--------------------------- intern/cycles/kernel/kernel_volume.h | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 9b9495644dd..cca7e897a7e 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -364,31 +364,6 @@ ccl_device void kernel_branched_path_ao(KernelGlobals *kg, ShaderData *sd, PathR #ifdef __SUBSURFACE__ -#ifdef __VOLUME__ -ccl_device void kernel_path_subsurface_update_volume_stack(KernelGlobals *kg, - Ray *ray, - VolumeStack *stack) -{ - kernel_assert(kernel_data.integrator.use_volumes); - - Ray volume_ray = *ray; - Intersection isect; - int step = 0; - while(step < VOLUME_STACK_SIZE && - scene_intersect_volume(kg, &volume_ray, &isect)) - { - ShaderData sd; - shader_setup_from_ray(kg, &sd, &isect, &volume_ray, 0, 0); - kernel_volume_stack_enter_exit(kg, &sd, stack); - - /* Move ray forward. */ - volume_ray.P = ray_offset(sd.P, -sd.Ng); - volume_ray.t -= sd.ray_length; - ++step; - } -} -#endif - ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, PathState *state, RNG *rng, Ray *ray, float3 *throughput) { float bssrdf_probability; @@ -433,7 +408,7 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd volume_ray.D = normalize_len(hit_ray.P - volume_ray.P, &volume_ray.t); - kernel_path_subsurface_update_volume_stack( + kernel_volume_stack_update_for_subsurface( kg, &volume_ray, hit_state.volume_stack); @@ -832,7 +807,7 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, volume_ray.D = normalize_len(P - volume_ray.P, &volume_ray.t); - kernel_path_subsurface_update_volume_stack( + kernel_volume_stack_update_for_subsurface( kg, &volume_ray, hit_state.volume_stack); diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index 5e34b7ee85e..3d3d871a702 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -1097,4 +1097,29 @@ ccl_device void kernel_volume_stack_enter_exit(KernelGlobals *kg, ShaderData *sd } } +#ifdef __SUBSURFACE__ +ccl_device void kernel_volume_stack_update_for_subsurface(KernelGlobals *kg, + Ray *ray, + VolumeStack *stack) +{ + kernel_assert(kernel_data.integrator.use_volumes); + + Ray volume_ray = *ray; + Intersection isect; + int step = 0; + while(step < VOLUME_STACK_SIZE && + scene_intersect_volume(kg, &volume_ray, &isect)) + { + ShaderData sd; + shader_setup_from_ray(kg, &sd, &isect, &volume_ray, 0, 0); + kernel_volume_stack_enter_exit(kg, &sd, stack); + + /* Move ray forward. */ + volume_ray.P = ray_offset(sd.P, -sd.Ng); + volume_ray.t -= sd.ray_length; + ++step; + } +} +#endif + CCL_NAMESPACE_END -- cgit v1.2.3 From 1f9fe0626fc0f6de449b62d88763faf8290e93b5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 28 Apr 2015 21:14:46 +1000 Subject: BLI_utildefines: add MEMSET_STRUCT_OFS macro --- source/blender/blenlib/BLI_utildefines.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 2ddc8faa8b1..d817aa95c74 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -493,8 +493,11 @@ extern "C" { #define OFFSETOF_STRUCT(_struct, _member) \ ((((char *)&((_struct)->_member)) - ((char *)(_struct))) + sizeof((_struct)->_member)) -/* memcpy, skipping the first part of a struct, - * ensures 'struct_dst' isn't const and that the offset can be computed at compile time */ +/** + * memcpy helper, skipping the first part of a struct, + * ensures 'struct_dst' isn't const and the offset can be computed at compile time. + * This isn't inclusive, the value of \a member isn't copied. + */ #define MEMCPY_STRUCT_OFS(struct_dst, struct_src, member) { \ CHECK_TYPE_NONCONST(struct_dst); \ ((void)(struct_dst == struct_src), \ @@ -503,6 +506,13 @@ extern "C" { sizeof(*(struct_dst)) - OFFSETOF_STRUCT(struct_dst, member))); \ } (void)0 +#define MEMSET_STRUCT_OFS(struct_var, value, member) { \ + CHECK_TYPE_NONCONST(struct_var); \ + memset((char *)(struct_var) + OFFSETOF_STRUCT(struct_var, member), \ + value, \ + sizeof(*(struct_var)) - OFFSETOF_STRUCT(struct_var, member)); \ +} (void)0 + /* Warning-free macros for storing ints in pointers. Use these _only_ * for storing an int in a pointer, not a pointer in an int (64bit)! */ #define SET_INT_IN_POINTER(i) ((void *)(intptr_t)(i)) -- cgit v1.2.3 From 43616918f3ee3a6ad867f0175ff973f6809e5047 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 28 Apr 2015 21:17:48 +1000 Subject: Cleanup: const correctness --- source/blender/bmesh/intern/bmesh_interp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index f8306d22ba7..169af6f62c3 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -459,8 +459,8 @@ static void bm_loop_interp_mdisps(BMesh *bm, BMLoop *l_dst, const BMFace *f_src) /* if no disps data allocate a new grid, the size of the first grid in f_src. */ if (!md_dst->totdisp) { - MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset); - + const MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset); + md_dst->totdisp = md_src->totdisp; md_dst->level = md_src->level; if (md_dst->totdisp) { -- cgit v1.2.3 From e2d60d180ed8a318b48833a07e1d17a788fa9a38 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 28 Apr 2015 23:34:40 +1000 Subject: Project Paint: Add symmetry support - Access from symmetry panel (as with sculpt) - Supports multiple axis at once. - Supports all brush types including clone. --- .../scripts/startup/bl_ui/space_view3d_toolbar.py | 19 + source/blender/editors/include/ED_view3d.h | 1 + .../editors/sculpt_paint/paint_image_proj.c | 507 ++++++++++++++------- .../blender/editors/space_view3d/view3d_project.c | 8 + 4 files changed, 373 insertions(+), 162 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index d5f64a7dd0a..51dd8b05f93 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -1698,6 +1698,25 @@ class VIEW3D_PT_tools_imagepaint_external(Panel, View3DPaintPanel): col.operator("paint.project_image", text="Apply Camera Image") +class VIEW3D_PT_tools_imagepaint_symmetry(Panel, View3DPaintPanel): + bl_category = "Tools" + bl_context = "imagepaint" + bl_label = "Symmetry" + bl_options = {'DEFAULT_CLOSED'} + + def draw(self, context): + layout = self.layout + + toolsettings = context.tool_settings + ipaint = toolsettings.image_paint + + col = layout.column(align=True) + row = col.row(align=True) + row.prop(ipaint, "use_symmetry_x", text="X", toggle=True) + row.prop(ipaint, "use_symmetry_y", text="Y", toggle=True) + row.prop(ipaint, "use_symmetry_z", text="Z", toggle=True) + + class VIEW3D_PT_tools_projectpaint(View3DPaintPanel, Panel): bl_category = "Options" bl_context = "imagepaint" diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index ab270f657a4..be4204e7cb7 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -219,6 +219,7 @@ void ED_view3d_win_to_vector(const struct ARegion *ar, const float mval[2], floa bool ED_view3d_win_to_segment(const struct ARegion *ar, struct View3D *v3d, const float mval[2], float r_ray_start[3], float r_ray_end[3], const bool do_clip); void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]); +void ED_view3d_ob_project_mat_get_from_obmat(const struct RegionView3D *rv3d, float obmat[4][4], float pmat[4][4]); void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, const float y, const float z); /* end */ diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 3ceaaff2f5d..698b62bf259 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -43,6 +43,7 @@ #include "BLI_blenlib.h" #include "BLI_linklist.h" #include "BLI_math.h" +#include "BLI_math_bits.h" #include "BLI_math_color_blend.h" #include "BLI_memarena.h" #include "BLI_threads.h" @@ -196,6 +197,29 @@ typedef struct ProjPaintImage { bool touch; } ProjPaintImage; +/** + * Handle for stroke (operator customdata) + */ +typedef struct ProjStrokeHandle { + /* Support for painting from multiple views at once, + * currently used to impliment summetry painting, + * we can assume at least the first is set while painting. */ + struct ProjPaintState *ps_views[8]; + int ps_views_tot; + int symmetry_flags; + + int orig_brush_size; + + bool need_redraw; + + /* trick to bypass regular paint and allow clone picking */ + bool is_clone_cursor_pick; + + /* In ProjPaintState, only here for convenience */ + Scene *scene; + Brush *brush; +} ProjStrokeHandle; + /* Main projection painting struct passed to all projection painting functions */ typedef struct ProjPaintState { View3D *v3d; @@ -211,24 +235,14 @@ typedef struct ProjPaintState { Brush *brush; short tool, blend, mode; - int orig_brush_size; + float brush_size; Object *ob; + /* for symmetry, we need to store modified object matrix */ + float obmat[4][4]; + float obmat_imat[4][4]; /* end similarities with ImagePaintState */ - DerivedMesh *dm; - int dm_totface; - int dm_totedge; - int dm_totvert; - int dm_release; - - MVert *dm_mvert; - MEdge *dm_medge; - MFace *dm_mface; - MTFace **dm_mtface; - MTFace **dm_mtface_clone; /* other UV map, use for cloning between layers */ - MTFace *dm_mtface_stencil; - Image *stencil_ima; Image *canvas_ima; Image *clone_ima; @@ -239,24 +253,16 @@ typedef struct ProjPaintState { LinkNode **bucketRect; /* screen sized 2D array, each pixel has a linked list of ProjPixel's */ LinkNode **bucketFaces; /* bucketRect aligned array linkList of faces overlapping each bucket */ unsigned char *bucketFlags; /* store if the bucks have been initialized */ -#ifndef PROJ_DEBUG_NOSEAMBLEED - char *faceSeamFlags; /* store info about faces, if they are initialized etc*/ - char *faceWindingFlags; /* save the winding of the face in uv space, helps as an extra validation step for seam detection */ - float (*faceSeamUVs)[4][2]; /* expanded UVs for faces to use as seams */ - LinkNode **vertFaces; /* Only needed for when seam_bleed_px is enabled, use to find UV seams */ -#endif + char *vertFlags; /* store options per vert, now only store if the vert is pointing away from the view */ int buckets_x; /* The size of the bucket grid, the grid span's screenMin/screenMax so you can paint outsize the screen or with 2 brushes at once */ int buckets_y; - ProjPaintImage *projImages; - int pixel_sizeof; /* result of project_paint_pixel_sizeof(), constant per stroke */ int image_tot; /* size of projectImages array */ float (*screenCoords)[4]; /* verts projected into floating point screen space */ - float *cavities; /* cavity amount for vertices */ float screenMin[2]; /* 2D bounds for mesh verts on the screen's plane (screenspace) */ float screenMax[2]; float screen_width; /* Calculated from screenMin & screenMax */ @@ -308,13 +314,51 @@ typedef struct ProjPaintState { int bucketMax[2]; int context_bucket_x, context_bucket_y; /* must lock threads while accessing these */ - /* redraw */ - bool need_redraw; - struct CurveMapping *cavity_curve; BlurKernel *blurkernel; + + + /* -------------------------------------------------------------------- */ + /* Vars shared between multiple views (keep last) */ + /** + * This data is owned by ``ProjStrokeHandle.ps_views[0]``, + * all other views re-use the data. + */ + +#define PROJ_PAINT_STATE_SHARED_MEMCPY(ps_dst, ps_src) \ + MEMCPY_STRUCT_OFS(ps_dst, ps_src, is_shared_user) + +#define PROJ_PAINT_STATE_SHARED_CLEAR(ps) \ + MEMSET_STRUCT_OFS(ps, 0, is_shared_user) + + bool is_shared_user; + + ProjPaintImage *projImages; + float *cavities; /* cavity amount for vertices */ + +#ifndef PROJ_DEBUG_NOSEAMBLEED + char *faceSeamFlags; /* store info about faces, if they are initialized etc*/ + char *faceWindingFlags; /* save the winding of the face in uv space, helps as an extra validation step for seam detection */ + float (*faceSeamUVs)[4][2]; /* expanded UVs for faces to use as seams */ + LinkNode **vertFaces; /* Only needed for when seam_bleed_px is enabled, use to find UV seams */ +#endif + SpinLock *tile_lock; + + DerivedMesh *dm; + int dm_totface; + int dm_totedge; + int dm_totvert; + int dm_release; + + MVert *dm_mvert; + MEdge *dm_medge; + MFace *dm_mface; + MTFace *dm_mtface_stencil; + + MTFace **dm_mtface; + MTFace **dm_mtface_clone; /* other UV map, use for cloning between layers */ } ProjPaintState; typedef union pixelPointer { @@ -3110,7 +3154,8 @@ static void proj_paint_state_non_cddm_init(ProjPaintState *ps) } } -static void proj_paint_state_viewport_init(ProjPaintState *ps) +static void proj_paint_state_viewport_init( + ProjPaintState *ps, const char symmetry_flag) { float mat[3][3]; float viewmat[4][4]; @@ -3120,7 +3165,19 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps) ps->viewDir[1] = 0.0f; ps->viewDir[2] = 1.0f; - invert_m4_m4(ps->ob->imat, ps->ob->obmat); + copy_m4_m4(ps->obmat, ps->ob->obmat); + + if (symmetry_flag) { + int i; + for (i = 0; i < 3; i++) { + if ((symmetry_flag >> i) & 1) { + negate_v3(ps->obmat[i]); + ps->is_flip_object = !ps->is_flip_object; + } + } + } + + invert_m4_m4(ps->obmat_imat, ps->obmat); if (ELEM(ps->source, PROJ_SRC_VIEW, PROJ_SRC_VIEW_FILL)) { /* normal drawing */ @@ -3130,7 +3187,7 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps) copy_m4_m4(viewmat, ps->rv3d->viewmat); copy_m4_m4(viewinv, ps->rv3d->viewinv); - ED_view3d_ob_project_mat_get(ps->rv3d, ps->ob, ps->projectMat); + ED_view3d_ob_project_mat_get_from_obmat(ps->rv3d, ps->obmat, ps->projectMat); ps->is_ortho = ED_view3d_clip_range_get(ps->v3d, ps->rv3d, &ps->clipsta, &ps->clipend, true); } @@ -3183,16 +3240,15 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps) } /* same as #ED_view3d_ob_project_mat_get */ - mul_m4_m4m4(vmat, viewmat, ps->ob->obmat); + mul_m4_m4m4(vmat, viewmat, ps->obmat); mul_m4_m4m4(ps->projectMat, winmat, vmat); } /* viewDir - object relative */ - invert_m4_m4(ps->ob->imat, ps->ob->obmat); copy_m3_m4(mat, viewinv); mul_m3_v3(mat, ps->viewDir); - copy_m3_m4(mat, ps->ob->imat); + copy_m3_m4(mat, ps->obmat_imat); mul_m3_v3(mat, ps->viewDir); normalize_v3(ps->viewDir); @@ -3202,9 +3258,9 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps) /* viewPos - object relative */ copy_v3_v3(ps->viewPos, viewinv[3]); - copy_m3_m4(mat, ps->ob->imat); + copy_m3_m4(mat, ps->obmat_imat); mul_m3_v3(mat, ps->viewPos); - add_v3_v3(ps->viewPos, ps->ob->imat[3]); + add_v3_v3(ps->viewPos, ps->obmat_imat[3]); } static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int diameter) @@ -3351,12 +3407,14 @@ static void proj_paint_state_thread_init(ProjPaintState *ps, const bool reset_th if (reset_threads) ps->thread_tot = 1; - if (ps->thread_tot > 1) { - ps->tile_lock = MEM_mallocN(sizeof(SpinLock), "projpaint_tile_lock"); - BLI_spin_init(ps->tile_lock); - } + if (ps->is_shared_user == false) { + if (ps->thread_tot > 1) { + ps->tile_lock = MEM_mallocN(sizeof(SpinLock), "projpaint_tile_lock"); + BLI_spin_init(ps->tile_lock); + } - image_undo_init_locks(); + image_undo_init_locks(); + } for (a = 0; a < ps->thread_tot; a++) { ps->arena_mt[a] = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "project paint arena"); @@ -3714,7 +3772,8 @@ static void project_paint_prepare_all_faces( ProjPaintState *ps, MemArena *arena, const ProjPaintFaceLookup *face_lookup, ProjPaintLayerClone *layer_clone, - MTFace *tf_base) + MTFace *tf_base, + const bool is_multi_view) { /* Image Vars - keep track of images we have used */ LinkNode *image_LinkList = NULL; @@ -3773,20 +3832,21 @@ static void project_paint_prepare_all_faces( ProjPaintFaceCoSS coSS; proj_paint_face_coSS_init(ps, mf, &coSS); - if (project_paint_flt_max_cull(ps, &coSS)) { - continue; - } + if (is_multi_view == false) { + if (project_paint_flt_max_cull(ps, &coSS)) { + continue; + } #ifdef PROJ_DEBUG_WINCLIP - if (project_paint_winclip(ps, mf, &coSS)) { - continue; - } + if (project_paint_winclip(ps, mf, &coSS)) { + continue; + } #endif //PROJ_DEBUG_WINCLIP - - if (project_paint_backface_cull(ps, mf, &coSS)) { - continue; + if (project_paint_backface_cull(ps, mf, &coSS)) { + continue; + } } if (tpage_last != tpage) { @@ -3811,14 +3871,18 @@ static void project_paint_prepare_all_faces( } /* build an array of images we use*/ - project_paint_build_proj_ima(ps, arena, image_LinkList); + if (ps->is_shared_user == false) { + project_paint_build_proj_ima(ps, arena, image_LinkList); + } /* we have built the array, discard the linked list */ BLI_linklist_free(image_LinkList, NULL); } /* run once per stroke before projection painting */ -static void project_paint_begin(ProjPaintState *ps) +static void project_paint_begin( + ProjPaintState *ps, + const bool is_multi_view, const char symmetry_flag) { ProjPaintLayerClone layer_clone; ProjPaintFaceLookup face_lookup; @@ -3839,8 +3903,10 @@ static void project_paint_begin(ProjPaintState *ps) ps->is_flip_object = (ps->ob->transflag & OB_NEG_SCALE) != 0; /* paint onto the derived mesh */ - if (!proj_paint_state_dm_init(ps)) { - return; + if (ps->is_shared_user == false) { + if (!proj_paint_state_dm_init(ps)) { + return; + } } proj_paint_face_lookup_init(ps, &face_lookup); @@ -3862,11 +3928,13 @@ static void project_paint_begin(ProjPaintState *ps) } /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */ - proj_paint_state_non_cddm_init(ps); + if (ps->is_shared_user == false) { + proj_paint_state_non_cddm_init(ps); - proj_paint_state_cavity_init(ps); + proj_paint_state_cavity_init(ps); + } - proj_paint_state_viewport_init(ps); + proj_paint_state_viewport_init(ps, symmetry_flag); /* calculate vert screen coords * run this early so we can calculate the x/y resolution of our bucket rect */ @@ -3895,7 +3963,9 @@ static void project_paint_begin(ProjPaintState *ps) ps->bucketFlags = MEM_callocN(sizeof(char) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces"); #ifndef PROJ_DEBUG_NOSEAMBLEED - proj_paint_state_seam_bleed_init(ps); + if (ps->is_shared_user == false) { + proj_paint_state_seam_bleed_init(ps); + } #endif proj_paint_state_thread_init(ps, reset_threads); @@ -3903,7 +3973,7 @@ static void project_paint_begin(ProjPaintState *ps) proj_paint_state_vert_flags_init(ps); - project_paint_prepare_all_faces(ps, arena, &face_lookup, &layer_clone, tf_base); + project_paint_prepare_all_faces(ps, arena, &face_lookup, &layer_clone, tf_base, is_multi_view); } static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2]) @@ -3912,7 +3982,7 @@ static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2]) if (ps->tool == PAINT_TOOL_CLONE) { float projCo[4]; copy_v3_v3(projCo, ED_view3d_cursor3d_get(ps->scene, ps->v3d)); - mul_m4_v3(ps->ob->imat, projCo); + mul_m4_v3(ps->obmat_imat, projCo); projCo[3] = 1.0f; mul_m4_v4(ps->projectMat, projCo); @@ -3924,14 +3994,16 @@ static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2]) static void project_paint_end(ProjPaintState *ps) { int a; - ProjPaintImage *projIma; image_undo_remove_masks(); /* dereference used image buffers */ - for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) { - BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL); - DAG_id_tag_update(&projIma->ima->id, 0); + if (ps->is_shared_user == false) { + ProjPaintImage *projIma; + for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) { + BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL); + DAG_id_tag_update(&projIma->ima->id, 0); + } } BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL); @@ -3940,68 +4012,81 @@ static void project_paint_end(ProjPaintState *ps) MEM_freeN(ps->bucketRect); MEM_freeN(ps->bucketFaces); MEM_freeN(ps->bucketFlags); - MEM_freeN(ps->dm_mtface); - if (ps->do_layer_clone) - MEM_freeN(ps->dm_mtface_clone); - if (ps->thread_tot > 1) { - BLI_spin_end(ps->tile_lock); - MEM_freeN((void *)ps->tile_lock); - } - image_undo_end_locks(); + + if (ps->is_shared_user == false) { + + /* must be set for non-shared */ + BLI_assert(ps->dm_mtface || ps->is_shared_user); + if (ps->dm_mtface) + MEM_freeN(ps->dm_mtface); + + if (ps->do_layer_clone) + MEM_freeN(ps->dm_mtface_clone); + if (ps->thread_tot > 1) { + BLI_spin_end(ps->tile_lock); + MEM_freeN((void *)ps->tile_lock); + } + + image_undo_end_locks(); #ifndef PROJ_DEBUG_NOSEAMBLEED - if (ps->seam_bleed_px > 0.0f) { - MEM_freeN(ps->vertFaces); - MEM_freeN(ps->faceSeamFlags); - MEM_freeN(ps->faceWindingFlags); - MEM_freeN(ps->faceSeamUVs); - } + if (ps->seam_bleed_px > 0.0f) { + MEM_freeN(ps->vertFaces); + MEM_freeN(ps->faceSeamFlags); + MEM_freeN(ps->faceWindingFlags); + MEM_freeN(ps->faceSeamUVs); + } #endif + if (ps->do_mask_cavity) { + MEM_freeN(ps->cavities); + } + + /* copy for subsurf/multires, so throw away */ + if (ps->dm->type != DM_TYPE_CDDM) { + if (ps->dm_mvert) MEM_freeN(ps->dm_mvert); + if (ps->dm_mface) MEM_freeN(ps->dm_mface); + /* looks like these don't need copying */ +#if 0 + if (ps->dm_mtface) MEM_freeN(ps->dm_mtface); + if (ps->dm_mtface_clone) MEM_freeN(ps->dm_mtface_clone); + if (ps->dm_mtface_stencil) MEM_freeN(ps->dm_mtface_stencil); +#endif + } + + if (ps->dm_release) + ps->dm->release(ps->dm); + } + if (ps->blurkernel) { paint_delete_blur_kernel(ps->blurkernel); MEM_freeN(ps->blurkernel); } - if (ps->do_mask_cavity) { - MEM_freeN(ps->cavities); - } - if (ps->vertFlags) MEM_freeN(ps->vertFlags); for (a = 0; a < ps->thread_tot; a++) { BLI_memarena_free(ps->arena_mt[a]); } +} - /* copy for subsurf/multires, so throw away */ - if (ps->dm->type != DM_TYPE_CDDM) { - if (ps->dm_mvert) MEM_freeN(ps->dm_mvert); - if (ps->dm_mface) MEM_freeN(ps->dm_mface); - /* looks like these don't need copying */ -#if 0 - if (ps->dm_mtface) MEM_freeN(ps->dm_mtface); - if (ps->dm_mtface_clone) MEM_freeN(ps->dm_mtface_clone); - if (ps->dm_mtface_stencil) MEM_freeN(ps->dm_mtface_stencil); -#endif - } +/* 1 = an undo, -1 is a redo. */ +static void partial_redraw_single_init(ImagePaintPartialRedraw *pr) +{ + pr->x1 = 10000000; + pr->y1 = 10000000; + + pr->x2 = -1; + pr->y2 = -1; - if (ps->dm_release) - ps->dm->release(ps->dm); + pr->enabled = 1; } -/* 1 = an undo, -1 is a redo. */ static void partial_redraw_array_init(ImagePaintPartialRedraw *pr) { int tot = PROJ_BOUNDBOX_SQUARED; while (tot--) { - pr->x1 = 10000000; - pr->y1 = 10000000; - - pr->x2 = -1; - pr->y2 = -1; - - pr->enabled = 1; - + partial_redraw_single_init(pr); pr++; } } @@ -4045,6 +4130,8 @@ static bool project_image_refresh_tagged(ProjPaintState *ps) imapaint_image_update(NULL, projIma->ima, projIma->ibuf, true); redraw = 1; } + + partial_redraw_single_init(pr); } projIma->touch = 0; /* clear for reuse */ @@ -4884,7 +4971,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po } ups->average_stroke_counter++; - mul_m4_v3(ps->ob->obmat, world); + mul_m4_v3(ps->obmat, world); add_v3_v3(ups->average_stroke_accum, world); ups->last_stroke_valid = true; } @@ -4894,33 +4981,21 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po } -void paint_proj_stroke(const bContext *C, void *pps, const float prev_pos[2], const float pos[2], const bool eraser, float pressure, float distance, float size) +static void paint_proj_stroke_ps( + const bContext *UNUSED(C), void *ps_handle_p, const float prev_pos[2], const float pos[2], + const bool eraser, float pressure, float distance, float size, + /* extra view */ + ProjPaintState *ps + ) { - ProjPaintState *ps = pps; + ProjStrokeHandle *ps_handle = ps_handle_p; Brush *brush = ps->brush; Scene *scene = ps->scene; - int a; ps->brush_size = size; ps->blend = brush->blend; if (eraser) ps->blend = IMB_BLEND_ERASE_ALPHA; - - /* clone gets special treatment here to avoid going through image initialization */ - if (ps->tool == PAINT_TOOL_CLONE && ps->mode == BRUSH_STROKE_INVERT) { - View3D *v3d = ps->v3d; - float *cursor = ED_view3d_cursor3d_get(scene, v3d); - int mval_i[2] = {(int)pos[0], (int)pos[1]}; - - view3d_operator_needs_opengl(C); - - if (!ED_view3d_autodist(scene, ps->ar, v3d, mval_i, cursor, false, NULL)) - return; - - ED_region_tag_redraw(ps->ar); - - return; - } /* handle gradient and inverted stroke color here */ if (ps->tool == PAINT_TOOL_DRAW) { @@ -4941,14 +5016,42 @@ void paint_proj_stroke(const bContext *C, void *pps, const float prev_pos[2], co } } - /* continue adding to existing partial redraw rects until redraw */ - if (!ps->need_redraw) { - for (a = 0; a < ps->image_tot; a++) - partial_redraw_array_init(ps->projImages[a].partRedrawRect); + if (project_paint_op(ps, prev_pos, pos)) { + ps_handle->need_redraw = true; + project_image_refresh_tagged(ps); + } +} + + +void paint_proj_stroke( + const bContext *C, void *ps_handle_p, const float prev_pos[2], const float pos[2], + const bool eraser, float pressure, float distance, float size) +{ + int i; + ProjStrokeHandle *ps_handle = ps_handle_p; + + /* clone gets special treatment here to avoid going through image initialization */ + if (ps_handle->is_clone_cursor_pick) { + Scene *scene = ps_handle->scene; + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + float *cursor = ED_view3d_cursor3d_get(scene, v3d); + int mval_i[2] = {(int)pos[0], (int)pos[1]}; + + view3d_operator_needs_opengl(C); + + if (!ED_view3d_autodist(scene, ar, v3d, mval_i, cursor, false, NULL)) + return; + + ED_region_tag_redraw(ar); + + return; } - if (project_paint_op(ps, prev_pos, pos)) - ps->need_redraw = true; + for (i = 0; i < ps_handle->ps_views_tot; i++) { + ProjPaintState *ps = ps_handle->ps_views[i]; + paint_proj_stroke_ps(C, ps_handle_p, prev_pos, pos, eraser, pressure, distance, size, ps); + } } @@ -5058,51 +5161,116 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int mode) { - ProjPaintState *ps = MEM_callocN(sizeof(ProjPaintState), "ProjectionPaintState"); + ProjStrokeHandle *ps_handle; + Scene *scene = CTX_data_scene(C); + ToolSettings *settings = scene->toolsettings; + int i; + bool is_multi_view; + char symmetry_flag_views[ARRAY_SIZE(ps_handle->ps_views)] = {0}; - project_state_init(C, ob, ps, mode); + ps_handle = MEM_callocN(sizeof(ProjStrokeHandle), "ProjStrokeHandle"); + ps_handle->scene = scene; + ps_handle->brush = BKE_paint_brush(&settings->imapaint.paint); - if (ps->tool == PAINT_TOOL_CLONE && mode == BRUSH_STROKE_INVERT) { + /* bypass regular stroke logic */ + if ((ps_handle->brush->imagepaint_tool == PAINT_TOOL_CLONE) && + (mode == BRUSH_STROKE_INVERT)) + { view3d_operator_needs_opengl(C); - return ps; + ps_handle->is_clone_cursor_pick = true; + return ps_handle; } - paint_brush_init_tex(ps->brush); + ps_handle->orig_brush_size = BKE_brush_size_get(scene, ps_handle->brush); - ps->source = (ps->tool == PAINT_TOOL_FILL) ? PROJ_SRC_VIEW_FILL : PROJ_SRC_VIEW; + ps_handle->symmetry_flags = settings->imapaint.paint.symmetry_flags & PAINT_SYMM_AXIS_ALL; + ps_handle->ps_views_tot = 1 + (pow_i(2, count_bits_i(ps_handle->symmetry_flags)) - 1); + is_multi_view = (ps_handle->ps_views_tot != 1); - if (ps->ob == NULL || !(ps->ob->lay & ps->v3d->lay)) { - MEM_freeN(ps); - return NULL; + for (i = 0; i < ps_handle->ps_views_tot; i++) { + ProjPaintState *ps = MEM_callocN(sizeof(ProjPaintState), "ProjectionPaintState"); + ps_handle->ps_views[i] = ps; } - ps->orig_brush_size = BKE_brush_size_get(ps->scene, ps->brush); + if (ps_handle->symmetry_flags) { + int index = 0; + + int x = 0; + do { + int y = 0; + do { + int z = 0; + do { + symmetry_flag_views[index++] = ( + (x ? PAINT_SYMM_X : 0) | + (y ? PAINT_SYMM_Y : 0) | + (z ? PAINT_SYMM_Z : 0)); + BLI_assert(index <= ps_handle->ps_views_tot); + } while ((z++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_Z)); + } while ((y++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_Y)); + } while ((x++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_X)); + BLI_assert(index == ps_handle->ps_views_tot); + } + + for (i = 0; i < ps_handle->ps_views_tot; i++) { + ProjPaintState *ps = ps_handle->ps_views[i]; + + project_state_init(C, ob, ps, mode); + + if (ps->ob == NULL || !(ps->ob->lay & ps->v3d->lay)) { + ps_handle->ps_views_tot = i + 1; + goto fail; + } + } /* Don't allow brush size below 2 */ - if (BKE_brush_size_get(ps->scene, ps->brush) < 2) - BKE_brush_size_set(ps->scene, ps->brush, 2 * U.pixelsize); + if (BKE_brush_size_get(scene, ps_handle->brush) < 2) + BKE_brush_size_set(scene, ps_handle->brush, 2 * U.pixelsize); /* allocate and initialize spatial data structures */ - project_paint_begin(ps); - if (ps->dm == NULL) { - MEM_freeN(ps); - return NULL; + for (i = 0; i < ps_handle->ps_views_tot; i++) { + ProjPaintState *ps = ps_handle->ps_views[i]; + + ps->source = (ps->tool == PAINT_TOOL_FILL) ? PROJ_SRC_VIEW_FILL : PROJ_SRC_VIEW; + project_image_refresh_tagged(ps); + + /* re-use! */ + if (i != 0) { + ps->is_shared_user = true; + PROJ_PAINT_STATE_SHARED_MEMCPY(ps, ps_handle->ps_views[0]); + } + + project_paint_begin(ps, is_multi_view, symmetry_flag_views[i]); + + paint_proj_begin_clone(ps, mouse); + + if (ps->dm == NULL) { + goto fail; + return NULL; + } } - paint_proj_begin_clone(ps, mouse); + paint_brush_init_tex(ps_handle->brush); + + return ps_handle; + - return ps; +fail: + for (i = 0; i < ps_handle->ps_views_tot; i++) { + ProjPaintState *ps = ps_handle->ps_views[i]; + MEM_freeN(ps); + } + MEM_freeN(ps_handle); + return NULL; } -void paint_proj_redraw(const bContext *C, void *pps, bool final) +void paint_proj_redraw(const bContext *C, void *ps_handle_p, bool final) { - ProjPaintState *ps = pps; + ProjStrokeHandle *ps_handle = ps_handle_p; - if (ps->need_redraw) { - project_image_refresh_tagged(ps); - - ps->need_redraw = false; + if (ps_handle->need_redraw) { + ps_handle->need_redraw = false; } else if (!final) { return; @@ -5117,19 +5285,34 @@ void paint_proj_redraw(const bContext *C, void *pps, bool final) } } -void paint_proj_stroke_done(void *pps) +void paint_proj_stroke_done(void *ps_handle_p) { - ProjPaintState *ps = pps; - if (ps->tool == PAINT_TOOL_CLONE && ps->mode == BRUSH_STROKE_INVERT) { - MEM_freeN(ps); + ProjStrokeHandle *ps_handle = ps_handle_p; + Scene *scene = ps_handle->scene; + int i; + + if (ps_handle->is_clone_cursor_pick) { + MEM_freeN(ps_handle); return; } - BKE_brush_size_set(ps->scene, ps->brush, ps->orig_brush_size); - paint_brush_exit_tex(ps->brush); + for (i = 1; i < ps_handle->ps_views_tot; i++) { + PROJ_PAINT_STATE_SHARED_CLEAR(ps_handle->ps_views[i]); + } + + BKE_brush_size_set(scene, ps_handle->brush, ps_handle->orig_brush_size); + + paint_brush_exit_tex(ps_handle->brush); + + for (i = 0; i < ps_handle->ps_views_tot; i++) { + ProjPaintState *ps; + ps = ps_handle->ps_views[i]; + project_paint_end(ps); + MEM_freeN(ps); + + } - project_paint_end(ps); - MEM_freeN(ps); + MEM_freeN(ps_handle); } /* use project paint to re-apply an image */ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) @@ -5209,7 +5392,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) ED_image_undo_restore, ED_image_undo_free, NULL); /* allocate and initialize spatial data structures */ - project_paint_begin(&ps); + project_paint_begin(&ps, false, 0); if (ps.dm == NULL) { BKE_brush_size_set(scene, ps.brush, orig_brush_size); diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index 74e3fde0eec..ba0626c58ea 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -605,6 +605,14 @@ void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, Object *ob, float pm mul_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat); } +void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, float obmat[4][4], float pmat[4][4]) +{ + float vmat[4][4]; + + mul_m4_m4m4(vmat, (float (*)[4])rv3d->viewmat, obmat); + mul_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat); +} + /** * Uses window coordinates (x,y) and depth component z to find a point in * modelspace */ -- cgit v1.2.3 From f8c383472a68ae1fdfc5b98c63fb1cd27c49e690 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 28 Apr 2015 15:41:44 +0200 Subject: Fix T44516 grid lines obscuring selection outline. Was changed to draw after meshes without depth mask to make grid not contribute to compositing effects. Now only draw it like this when we do compositing (unfortunately can't have both). --- source/blender/editors/space_view3d/view3d_draw.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index af0bd8ec761..a8cfd9955c2 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -472,7 +472,7 @@ float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) return v3d->grid * ED_scene_grid_scale(scene, grid_unit); } -static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) +static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth) { float grid, grid_scale; unsigned char col_grid[3]; @@ -484,7 +484,8 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit); grid = gridlines * grid_scale; - glDepthMask(GL_FALSE); + if (!write_depth) + glDepthMask(GL_FALSE); UI_GetThemeColor3ubv(TH_GRID, col_grid); @@ -2726,7 +2727,7 @@ static void view3d_draw_objects( const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0; const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO); /* only draw grids after in solid modes, else it hovers over mesh wires */ - const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE); + const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE) && fx; bool do_composite_xray = false; bool xrayclear = true; @@ -2775,8 +2776,8 @@ static void view3d_draw_objects( glMatrixMode(GL_MODELVIEW); glLoadMatrixf(rv3d->viewmat); } - else { - drawfloor(scene, v3d, grid_unit); + else if (!draw_grids_after){ + drawfloor(scene, v3d, grid_unit, true); } } @@ -2854,7 +2855,7 @@ static void view3d_draw_objects( /* perspective floor goes last to use scene depth and avoid writing to depth buffer */ if (draw_grids_after) { - drawfloor(scene, v3d, grid_unit); + drawfloor(scene, v3d, grid_unit, false); } /* must be before xray draw which clears the depth buffer */ -- cgit v1.2.3 From 57a107c7bc81dd952acf5908441a1e860b099bc8 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 28 Apr 2015 14:15:27 +0200 Subject: Minor cleanup in comments. --- source/blender/blenkernel/intern/mesh_mapping.c | 33 +++++++++++++++---------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index cc5006efacb..37b4c5fcf8f 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -180,8 +180,6 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap) } /** - - * Generates a map where the key is the vertex and the value is a list * of polys or loops that use that vertex as a corner. The lists are allocated * from one memory pool. @@ -254,9 +252,10 @@ void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, int **r_mem, mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, true); } -/* Generates a map where the key is the vertex and the value is a list - * of edges that use that vertex as an endpoint. The lists are allocated - * from one memory pool. */ +/** + * Generates a map where the key is the vertex and the value is a list of edges that use that vertex as an endpoint. + * The lists are allocated from one memory pool. + */ void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map, int **r_mem, const MEdge *medge, int totvert, int totedge) { @@ -296,6 +295,10 @@ void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map, int **r_mem, *r_mem = indices; } +/** + * Generates a map where the key is the edge and the value is a list of polygons that use that edge. + * The lists are allocated from one memory pool. + */ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int **r_mem, const MEdge *UNUSED(medge), const int totedge, const MPoly *mpoly, const int totpoly, @@ -403,7 +406,8 @@ void BKE_mesh_origindex_map_create(MeshElemMap **r_map, int **r_mem, * Used currently for UVs and 'smooth groups'. * \{ */ -/** Callback deciding whether the given poly/loop/edge define an island boundary or not. +/** + * Callback deciding whether the given poly/loop/edge define an island boundary or not. */ typedef bool (*MeshRemap_CheckIslandBoundary)( const struct MPoly *mpoly, const struct MLoop *mloop, const struct MEdge *medge, @@ -586,8 +590,7 @@ static void poly_edge_loop_islands_calc( } static bool poly_is_island_boundary_smooth_cb( - const MPoly *mp, const MLoop *UNUSED(ml), const MEdge *me, - const int nbr_egde_users) + const MPoly *mp, const MLoop *UNUSED(ml), const MEdge *me, const int nbr_egde_users) { /* Edge is sharp if its poly is sharp, or edge itself is sharp, or edge is not used by exactly two polygons. */ return (!(mp->flag & ME_SMOOTH) || (me->flag & ME_SHARP) || (nbr_egde_users != 2)); @@ -719,17 +722,21 @@ void BKE_mesh_loop_islands_add( * not sure we want that at all! */ static bool mesh_check_island_boundary_uv( - const MPoly *UNUSED(mp), const MLoop *UNUSED(ml), const MEdge *me, - const int UNUSED(nbr_egde_users)) + const MPoly *UNUSED(mp), const MLoop *UNUSED(ml), const MEdge *me, const int UNUSED(nbr_egde_users)) { /* Edge is UV boundary if tagged as seam. */ return (me->flag & ME_SEAM) != 0; } /** - * \note all this could be optimized... - * Not sure it would be worth the more complex code, though, those loops - * are supposed to be really quick to do... + * Calculate UV islands. + * + * \note Currently we only consider edges tagges as seams as UV boundaries. This has the advantages of simplicity, + * and being valid/common to all UV maps. However, it means actual UV islands whithout matching UV seams + * will not be handled correctly... + * + * \note All this could be optimized... + * Not sure it would be worth the more complex code, though, those loops are supposed to be really quick to do... */ bool BKE_mesh_calc_islands_loop_poly_uv( MVert *UNUSED(verts), const int UNUSED(totvert), -- cgit v1.2.3 From 34abe82205995d6dab316e1c17b81f72358e7341 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 28 Apr 2015 15:57:11 +0200 Subject: Fix T44522: loop remapping between meshes when using 'nearest vert, best matching normal' modes would fail on coplanar faces (or smooth verts). Loop remapping is really a tricky topic... For now, we enhance a bit more our Frankenfunc by using distance between dest and source polygons as fallback in case we have too much similar normals... Probably not a perfect solution, but should be robust enough I hope. One core question remains open though: do we want to stick to 'use only seams to detect UV islands'? This makes things much simpler, but will obviously fail in case of actual islands without matching seams. :/ --- source/blender/blenkernel/intern/mesh_remap.c | 69 ++++++++++++++++++++------- 1 file changed, 52 insertions(+), 17 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c index aca72614094..94fe9f993d3 100644 --- a/source/blender/blenkernel/intern/mesh_remap.c +++ b/source/blender/blenkernel/intern/mesh_remap.c @@ -977,6 +977,8 @@ void BKE_mesh_remap_calc_loops_from_dm( float (*poly_nors_dst)[3] = NULL; float (*loop_nors_dst)[3] = NULL; + float (*poly_cents_src)[3] = NULL; + MeshElemMap *vert_to_loop_map_src = NULL; int *vert_to_loop_map_src_buff = NULL; MeshElemMap *vert_to_poly_map_src = NULL; @@ -1012,6 +1014,8 @@ void BKE_mesh_remap_calc_loops_from_dm( int *indices_interp = NULL; float *weights_interp = NULL; + MLoop *ml_src, *ml_dst; + MPoly *mp_src, *mp_dst; int tindex, pidx_dst, lidx_dst, plidx_dst, pidx_src, lidx_src, plidx_src; IslandResult **islands_res; @@ -1089,11 +1093,13 @@ void BKE_mesh_remap_calc_loops_from_dm( edges_src, num_edges_src, polys_src, num_polys_src, loops_src, num_loops_src); if (use_from_vert) { loop_to_poly_map_src = MEM_mallocN(sizeof(*loop_to_poly_map_src) * (size_t)num_loops_src, __func__); - for (pidx_src = 0; pidx_src < num_polys_src; pidx_src++) { - MPoly *mp = &polys_src[pidx_src]; - for (plidx_src = 0, lidx_src = mp->loopstart; plidx_src < mp->totloop; plidx_src++, lidx_src++) { + poly_cents_src = MEM_mallocN(sizeof(*poly_cents_src) * (size_t)num_polys_src, __func__); + for (pidx_src = 0, mp_src = polys_src; pidx_src < num_polys_src; pidx_src++, mp_src++) { + ml_src = &loops_src[mp_src->loopstart]; + for (plidx_src = 0, lidx_src = mp_src->loopstart; plidx_src < mp_src->totloop; plidx_src++, lidx_src++) { loop_to_poly_map_src[lidx_src] = pidx_src; } + BKE_mesh_calc_poly_center(mp_src, ml_src, verts_src, poly_cents_src[pidx_src]); } } @@ -1155,7 +1161,7 @@ void BKE_mesh_remap_calc_loops_from_dm( int num_verts_active = 0; BLI_BITMAP_SET_ALL(verts_active, false, (size_t)num_verts_src); for (i = 0; i < isld->count; i++) { - MPoly *mp_src = &polys_src[isld->indices[i]]; + mp_src = &polys_src[isld->indices[i]]; for (lidx_src = mp_src->loopstart; lidx_src < mp_src->loopstart + mp_src->totloop; lidx_src++) { BLI_BITMAP_ENABLE(verts_active, loops_src[lidx_src].v); num_verts_active++; @@ -1199,7 +1205,7 @@ void BKE_mesh_remap_calc_loops_from_dm( int num_faces_active = 0; BLI_BITMAP_SET_ALL(faces_active, false, (size_t)num_faces_src); for (i = 0; i < num_faces_src; i++) { - MPoly *mp_src = &polys_src[tessface_to_poly_map_src[i]]; + mp_src = &polys_src[tessface_to_poly_map_src[i]]; if (island_store.items_to_islands[mp_src->loopstart] == tindex) { BLI_BITMAP_ENABLE(faces_active, i); num_faces_active++; @@ -1233,10 +1239,14 @@ void BKE_mesh_remap_calc_loops_from_dm( islands_res[tindex] = MEM_mallocN(sizeof(**islands_res) * islands_res_buff_size, __func__); } - for (pidx_dst = 0; pidx_dst < numpolys_dst; pidx_dst++) { - MPoly *mp_dst = &polys_dst[pidx_dst]; + for (pidx_dst = 0, mp_dst = polys_dst; pidx_dst < numpolys_dst; pidx_dst++, mp_dst++) { float (*pnor_dst)[3] = &poly_nors_dst[pidx_dst]; + /* Only in use_from_vert case, we may need polys' centers as fallback in case we cannot decide which + * corner to use from normals only. */ + float pcent_dst[3]; + bool pcent_dst_valid = false; + if ((size_t)mp_dst->totloop > islands_res_buff_size) { islands_res_buff_size = (size_t)mp_dst->totloop; for (tindex = 0; tindex < num_trees; tindex++) { @@ -1246,8 +1256,8 @@ void BKE_mesh_remap_calc_loops_from_dm( for (tindex = 0; tindex < num_trees; tindex++) { BVHTreeFromMesh *tdata = &treedata[tindex]; - MLoop *ml_dst = &loops_dst[mp_dst->loopstart]; + ml_dst = &loops_dst[mp_dst->loopstart]; for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++, ml_dst++) { if (use_from_vert) { float tmp_co[3]; @@ -1263,6 +1273,7 @@ void BKE_mesh_remap_calc_loops_from_dm( float (*nor_dst)[3]; float (*nors_src)[3]; float best_nor_dot = -2.0f; + float best_sqdist_fallback = FLT_MAX; int best_index_src = -1; if (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) { @@ -1279,16 +1290,38 @@ void BKE_mesh_remap_calc_loops_from_dm( for (i = vert_to_refelem_map_src[nearest.index].count; i--;) { const int index_src = vert_to_refelem_map_src[nearest.index].indices[i]; const float dot = dot_v3v3(nors_src[index_src], *nor_dst); - if (dot > best_nor_dot) { - best_nor_dot = dot; - best_index_src = index_src; + + if (dot > best_nor_dot - 1e-6f) { + /* We need something as fallback decision in case dest normal matches several + * source normals (see T44522), using distance between polys' centers here. */ + float *pcent_src; + float sqdist; + + pidx_src = (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) ? + loop_to_poly_map_src[index_src] : index_src; + mp_src = &polys_src[pidx_src]; + ml_src = &loops_src[mp_src->loopstart]; + + if (!pcent_dst_valid) { + BKE_mesh_calc_poly_center( + mp_dst, &loops_dst[mp_dst->loopstart], verts_dst, pcent_dst); + pcent_dst_valid = true; + } + pcent_src = poly_cents_src[pidx_src]; + sqdist = len_squared_v3v3(pcent_dst, pcent_src); + + if ((dot > best_nor_dot + 1e-6f) || (sqdist < best_sqdist_fallback)) { + best_nor_dot = dot; + best_sqdist_fallback = sqdist; + best_index_src = index_src; + } } } if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) { /* Our best_index_src is a poly one for now! * Have to find its loop matching our closest vertex. */ - MPoly *mp_src = &polys_src[best_index_src]; - MLoop *ml_src = &loops_src[mp_src->loopstart]; + mp_src = &polys_src[best_index_src]; + ml_src = &loops_src[mp_src->loopstart]; for (plidx_src = 0; plidx_src < mp_src->totloop; plidx_src++, ml_src++) { if ((int)ml_src->v == nearest.index) { best_index_src = plidx_src + mp_src->loopstart; @@ -1488,12 +1521,11 @@ void BKE_mesh_remap_calc_loops_from_dm( if (last_valid_pidx_isld_src != -1) { /* Find a new valid loop in that new poly (nearest one for now). * Note we could be much more subtle here, again that's for later... */ - MPoly *mp_src; - MLoop *ml_src, *ml_dst = &loops_dst[lidx_dst]; int j; float best_dist_sq = FLT_MAX; float tmp_co[3]; + ml_dst = &loops_dst[lidx_dst]; copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co); /* We do our transform here, since we may do several raycast/nearest queries. */ @@ -1532,10 +1564,10 @@ void BKE_mesh_remap_calc_loops_from_dm( /* Else, we use source poly, indices stored in islands_res are those of polygons. */ pidx_src = isld_res->index_src; if (pidx_src >= 0) { - MPoly *mp_src = &polys_src[pidx_src]; float *hit_co = isld_res->hit_point; int best_loop_index_src; + mp_src = &polys_src[pidx_src]; /* If prev and curr poly are the same, no need to do anything more!!! */ if (!ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) { int pidx_isld_src, pidx_isld_src_prev; @@ -1575,11 +1607,11 @@ void BKE_mesh_remap_calc_loops_from_dm( if (last_valid_pidx_isld_src != -1) { /* Find a new valid loop in that new poly (nearest point on poly for now). * Note we could be much more subtle here, again that's for later... */ - MLoop *ml_dst = &loops_dst[lidx_dst]; float best_dist_sq = FLT_MAX; float tmp_co[3]; int j; + ml_dst = &loops_dst[lidx_dst]; copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co); /* We do our transform here, since we may do several raycast/nearest queries. */ @@ -1710,6 +1742,9 @@ void BKE_mesh_remap_calc_loops_from_dm( if (loop_to_poly_map_src) { MEM_freeN(loop_to_poly_map_src); } + if (poly_cents_src) { + MEM_freeN(poly_cents_src); + } if (vcos_interp) { MEM_freeN(vcos_interp); } -- cgit v1.2.3 From be228d33f165b10327b06ae77bb21ab1a437a16a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Apr 2015 00:19:34 +1000 Subject: Curves: don't use 'charidx' for regular curves Code attempted to sync them with materials, but its not needed (and wasn't reliable). --- source/blender/blenkernel/intern/curve.c | 9 --------- source/blender/blenloader/intern/readfile.c | 2 +- source/blender/editors/render/render_shading.c | 2 +- source/blender/makesdna/DNA_curve_types.h | 1 + 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index cd59e30a406..30ceaea89b8 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -4422,9 +4422,6 @@ void BKE_curve_material_index_remove(Curve *cu, int index) for (nu = cu->nurb.first; nu; nu = nu->next) { if (nu->mat_nr && nu->mat_nr >= index) { nu->mat_nr--; - if (curvetype == OB_CURVE) { - nu->charidx--; - } } } } @@ -4446,9 +4443,6 @@ void BKE_curve_material_index_clear(Curve *cu) for (nu = cu->nurb.first; nu; nu = nu->next) { nu->mat_nr = 0; - if (curvetype == OB_CURVE) { - nu->charidx = 0; - } } } } @@ -4475,9 +4469,6 @@ int BKE_curve_material_index_validate(Curve *cu) for (nu = cu->nurb.first; nu; nu = nu->next) { if (nu->mat_nr > max_idx) { nu->mat_nr = 0; - if (curvetype == OB_CURVE) { - nu->charidx = 0; - } is_valid = false; } } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 060b5e97dde..6d9d7ad073f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3532,7 +3532,7 @@ static void direct_link_curve(FileData *fd, Curve *cu) nu->bp = newdataadr(fd, nu->bp); nu->knotsu = newdataadr(fd, nu->knotsu); nu->knotsv = newdataadr(fd, nu->knotsv); - if (cu->vfont == NULL) nu->charidx= nu->mat_nr; + if (cu->vfont == NULL) nu->charidx = 0; if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) { switch_endian_knots(nu); diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 617364c7e74..3b8b874a462 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -203,7 +203,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op)) if (nurbs) { for (nu = nurbs->first; nu; nu = nu->next) if (isNurbsel(nu)) - nu->mat_nr = nu->charidx = ob->actcol - 1; + nu->mat_nr = ob->actcol - 1; } } else if (ob->type == OB_FONT) { diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 205ed7e7380..40c028c3aa1 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -157,6 +157,7 @@ typedef struct Nurb { short tilt_interp; /* KEY_LINEAR, KEY_CARDINAL, KEY_BSPLINE */ short radius_interp; + /* only used for dynamically generated Nurbs created from OB_FONT's */ int charidx; } Nurb; -- cgit v1.2.3 From 7615498e6dfe2902e265f49c2d1605fe81dcf99c Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 28 Apr 2015 17:18:32 +0200 Subject: Alleviate somewhat the issue of T44505 Issue is zfighting with wire of mesh when parts of the mesh are close together. We can make this slightly better by reducing the offset, however this offset is calculated pre-perspective division and can vary greatly with distance. Correct approach would be using polygon offset, however we draw mesh wireframes as lines, (not polygons with polygon mode line) so this approach will not work. Alternatively, we could set an offset in a shader, however we don't have code for that either. --- source/blender/editors/screen/glutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 6001534e88d..618d6906b76 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -1008,7 +1008,7 @@ void bglPolygonOffset(float viewdist, float dist) /* dist is from camera to center point */ if (winmat[15] > 0.5f) offs = 0.00001f * dist * viewdist; // ortho tweaking - else offs = 0.0005f * dist; // should be clipping value or so... + else offs = 0.0001f * dist; // should be clipping value or so... winmat[14] -= offs; offset += offs; -- cgit v1.2.3 From 7851534541b02a05b8b647be01c726373185f758 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Apr 2015 01:36:14 +1000 Subject: disable ARRAY_SIZE fixed length check for Clang --- source/blender/blenlib/BLI_utildefines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index d817aa95c74..8f2f906ed17 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -435,7 +435,7 @@ extern "C" { } (void)0 /* assuming a static array */ -#if defined(__GNUC__) && !defined(__cplusplus) +#if defined(__GNUC__) && !defined(__cplusplus) && !defined(__clang__) # define ARRAY_SIZE(arr) \ ((sizeof(struct {int isnt_array : ((const void *)&(arr) == &(arr)[0]);}) * 0) + \ (sizeof(arr) / sizeof(*(arr)))) -- cgit v1.2.3 From 85ae4b87afa80527a36d3bd3164a9df6544f0c3b Mon Sep 17 00:00:00 2001 From: Tamito Kajiyama Date: Tue, 28 Apr 2015 23:18:32 +0900 Subject: Fix T44404: freestyle crashes blender. The reported crash case seems to be caused by freeing compiled Python objects in a thread. Now this issue is avoided by allocating a buffer to store a Python script and using BPY_string_exec() to run the script. This makes it unnecessary to repeatedly create and destroy Text data blocks. Many thanks to Campbell Barton for his help on the bug fix. --- .../freestyle/intern/application/Controller.cpp | 6 +++++ .../freestyle/intern/application/Controller.h | 1 + .../intern/blender_interface/BlenderStyleModule.h | 29 +++++++++++++++++++++- .../intern/blender_interface/FRS_freestyle.cpp | 29 ++++++---------------- .../freestyle/intern/system/PythonInterpreter.h | 22 ++++++++++++++++ 5 files changed, 65 insertions(+), 22 deletions(-) diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp index add7420b89a..5cd2e16847d 100644 --- a/source/blender/freestyle/intern/application/Controller.cpp +++ b/source/blender/freestyle/intern/application/Controller.cpp @@ -927,6 +927,12 @@ void Controller::InsertStyleModule(unsigned index, const char *iFileName) _Canvas->InsertStyleModule(index, sm); } +void Controller::InsertStyleModule(unsigned index, const char *iName, const char *iBuffer) +{ + StyleModule *sm = new BufferedStyleModule(iBuffer, iName, _inter); + _Canvas->InsertStyleModule(index, sm); +} + void Controller::InsertStyleModule(unsigned index, const char *iName, struct Text *iText) { StyleModule *sm = new BlenderStyleModule(iText, iName, _inter); diff --git a/source/blender/freestyle/intern/application/Controller.h b/source/blender/freestyle/intern/application/Controller.h index 9fe57d92cf4..a09964a4e79 100644 --- a/source/blender/freestyle/intern/application/Controller.h +++ b/source/blender/freestyle/intern/application/Controller.h @@ -90,6 +90,7 @@ public: Render *RenderStrokes(Render *re, bool render); void SwapStyleModules(unsigned i1, unsigned i2); void InsertStyleModule(unsigned index, const char *iFileName); + void InsertStyleModule(unsigned index, const char *iName, const char *iBuffer); void InsertStyleModule(unsigned index, const char *iName, struct Text *iText); void AddStyleModule(const char *iFileName); void RemoveStyleModule(unsigned index); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h index 2bc43798878..1d73125f627 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h +++ b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h @@ -36,6 +36,34 @@ struct Text; namespace Freestyle { +class BufferedStyleModule : public StyleModule +{ +public: + BufferedStyleModule(const string& buffer, const string& file_name, Interpreter *inter) : StyleModule(file_name, inter) + { + _buffer = buffer; + } + + virtual ~BufferedStyleModule() + { + } + +protected: + virtual int interpret() + { + PythonInterpreter *py_inter = dynamic_cast(_inter); + BLI_assert(py_inter != 0); + return py_inter->interpretString(_buffer, getFileName()); + } + +private: + string _buffer; + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BufferedStyleModule") +#endif +}; + class BlenderStyleModule : public StyleModule { public: @@ -62,7 +90,6 @@ private: #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BlenderStyleModule") #endif - }; } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 6b102410aa6..8a7753eda92 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -211,16 +211,12 @@ static char *escape_quotes(char *name) return s; } -static Text *create_lineset_handler(Main *bmain, char *layer_name, char *lineset_name) +static char * create_lineset_handler(char *layer_name, char *lineset_name) { + char *fmt = "__import__('parameter_editor').process('%s', '%s')\n"; char *s1 = escape_quotes(layer_name); char *s2 = escape_quotes(lineset_name); - Text *text = BKE_text_add(bmain, lineset_name); - BKE_text_write(text, "import parameter_editor; parameter_editor.process('"); - BKE_text_write(text, s1); - BKE_text_write(text, "', '"); - BKE_text_write(text, s2); - BKE_text_write(text, "')\n"); + char *text = BLI_sprintfN(fmt, s1, s2); MEM_freeN(s1); MEM_freeN(s2); return text; @@ -293,7 +289,7 @@ static bool test_edge_type_conditions(struct edge_type_condition *conditions, return true; } -static void prepare(Main *bmain, Render *re, SceneRenderLayer *srl) +static void prepare(Render *re, SceneRenderLayer *srl) { // load mesh re->i.infostr = "Freestyle: Mesh loading"; @@ -369,9 +365,10 @@ static void prepare(Main *bmain, Render *re, SceneRenderLayer *srl) cout << " " << layer_count+1 << ": " << lineset->name << " - " << (lineset->linestyle ? (lineset->linestyle->id.name + 2) : "") << endl; } - Text *text = create_lineset_handler(bmain, srl->name, lineset->name); - controller->InsertStyleModule(layer_count, lineset->name, text); + char *buffer = create_lineset_handler(srl->name, lineset->name); + controller->InsertStyleModule(layer_count, lineset->name, buffer); controller->toggleLayer(layer_count, true); + MEM_freeN(buffer); if (!(lineset->selection & FREESTYLE_SEL_EDGE_TYPES) || !lineset->edge_types) { ++use_ridges_and_valleys; ++use_suggestive_contours; @@ -584,9 +581,7 @@ void FRS_init_stroke_rendering(Render *re) Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render) { - Main *freestyle_bmain = re->freestyle_bmain; Render *freestyle_render = NULL; - Text *text, *next_text; if (!render) return controller->RenderStrokes(re, false); @@ -607,7 +602,7 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render) // - add style modules // - set parameters // - compute view map - prepare(freestyle_bmain, re, srl); + prepare(re, srl); if (re->test_break(re->tbh)) { controller->CloseFile(); @@ -635,14 +630,6 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render) } } - // Free temp main (currently only text blocks are stored there) - for (text = (Text *)freestyle_bmain->text.first; text; text = next_text) { - next_text = (Text *) text->id.next; - - BKE_text_unlink(freestyle_bmain, text); - BKE_libblock_free(freestyle_bmain, text); - } - return freestyle_render; } diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.h b/source/blender/freestyle/intern/system/PythonInterpreter.h index 60193590944..ddb79b2df0b 100644 --- a/source/blender/freestyle/intern/system/PythonInterpreter.h +++ b/source/blender/freestyle/intern/system/PythonInterpreter.h @@ -51,6 +51,8 @@ extern "C" { #include "BKE_text.h" #include "BPY_extern.h" + +#include "bpy_util.h" } namespace Freestyle { @@ -105,6 +107,26 @@ public: return 0; } + int interpretString(const string& str, const string& name) + { + ReportList *reports = CTX_wm_reports(_context); + + BKE_reports_clear(reports); + + if (BPY_string_exec(_context, str.c_str()) != 0) { + BPy_errors_to_report(reports); + cerr << "\nError executing Python script from PythonInterpreter::interpretString" << endl; + cerr << "Name: " << name << endl; + cerr << "Errors: " << endl; + BKE_reports_print(reports, RPT_ERROR); + return 1; + } + + BKE_reports_clear(reports); + + return 0; + } + int interpretText(struct Text *text, const string& name) { ReportList *reports = CTX_wm_reports(_context); -- cgit v1.2.3 From 859ac8fbc6eaaa303b04839538b590a5a240f857 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 28 Apr 2015 20:41:37 +0200 Subject: Fix ortho part of T44505 In this case we can calculate an offset without worrying about perspective correction. Unfortunately if looking from a camera we still have depth issues here. There's no really general case that can fix this so I'm leaving this as is. --- source/blender/editors/screen/glutil.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 618d6906b76..1ab03bfb7ef 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -991,7 +991,7 @@ void bgl_get_mats(bglMats *mats) /** * \note \a viewdist is only for ortho at the moment. */ -void bglPolygonOffset(float viewdist, float dist) +void bglPolygonOffset(float viewdist, float dist) { static float winmat[16], offset = 0.0; @@ -1007,7 +1007,16 @@ void bglPolygonOffset(float viewdist, float dist) /* dist is from camera to center point */ - if (winmat[15] > 0.5f) offs = 0.00001f * dist * viewdist; // ortho tweaking + if (winmat[15] > 0.5f) { + int depthbits, i, depthmax = 1; + glGetIntegerv(GL_DEPTH_BITS, &depthbits); + + for (i = 1; i < depthbits; i++) { + depthmax = (depthmax << 1) + 1; + } + offs = (-1.0 / winmat[10]) * dist / (double) depthmax; + //offs = 0.00001f * dist * viewdist; // ortho tweaking + } else offs = 0.0001f * dist; // should be clipping value or so... winmat[14] -= offs; -- cgit v1.2.3 From d2ac3abbc2f9c66f5912b92768765ea326f800c5 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Apr 2015 00:23:52 +0500 Subject: Compilation error fixes for strict compiler flags --- source/blender/editors/screen/glutil.c | 2 +- source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 1ab03bfb7ef..f29ba785180 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -991,7 +991,7 @@ void bgl_get_mats(bglMats *mats) /** * \note \a viewdist is only for ortho at the moment. */ -void bglPolygonOffset(float viewdist, float dist) +void bglPolygonOffset(float UNUSED(viewdist), float dist) { static float winmat[16], offset = 0.0; diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 8a7753eda92..291ed98f905 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -213,7 +213,7 @@ static char *escape_quotes(char *name) static char * create_lineset_handler(char *layer_name, char *lineset_name) { - char *fmt = "__import__('parameter_editor').process('%s', '%s')\n"; + const char *fmt = "__import__('parameter_editor').process('%s', '%s')\n"; char *s1 = escape_quotes(layer_name); char *s2 = escape_quotes(lineset_name); char *text = BLI_sprintfN(fmt, s1, s2); -- cgit v1.2.3 From e0ae6939242ed5a50f9904b87a059b4edf9aeabf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Apr 2015 05:30:30 +1000 Subject: Store bit-depth for reuse, replace loop with shift --- source/blender/editors/screen/glutil.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index f29ba785180..ca0047b202a 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -1008,16 +1008,22 @@ void bglPolygonOffset(float UNUSED(viewdist), float dist) /* dist is from camera to center point */ if (winmat[15] > 0.5f) { - int depthbits, i, depthmax = 1; - glGetIntegerv(GL_DEPTH_BITS, &depthbits); - - for (i = 1; i < depthbits; i++) { - depthmax = (depthmax << 1) + 1; +#if 0 + offs = 0.00001f * dist * viewdist; // ortho tweaking +#else + static float depth_fac = 0.0f; + if (depth_fac == 0.0f) { + int depthbits; + glGetIntegerv(GL_DEPTH_BITS, &depthbits); + depth_fac = 1.0f / (float)(depthbits - 1); } - offs = (-1.0 / winmat[10]) * dist / (double) depthmax; - //offs = 0.00001f * dist * viewdist; // ortho tweaking + offs = (-1.0 / winmat[10]) * dist * depth_fac; +#endif + } + else { + /* should be clipping value or so... */ + offs = 0.0001f * dist; } - else offs = 0.0001f * dist; // should be clipping value or so... winmat[14] -= offs; offset += offs; -- cgit v1.2.3 From cbb601346a6401192298b34255f7f3c981078293 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Apr 2015 05:36:39 +1000 Subject: Error in last commit --- source/blender/editors/screen/glutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index ca0047b202a..2a0e13bccbc 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -1015,7 +1015,7 @@ void bglPolygonOffset(float UNUSED(viewdist), float dist) if (depth_fac == 0.0f) { int depthbits; glGetIntegerv(GL_DEPTH_BITS, &depthbits); - depth_fac = 1.0f / (float)(depthbits - 1); + depth_fac = 1.0f / (float)((1 << depthbits) - 1); } offs = (-1.0 / winmat[10]) * dist * depth_fac; #endif -- cgit v1.2.3 From f9d23b82fe4461ccab40124b8a4cdb4735fbedd3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Apr 2015 06:08:45 +1000 Subject: Rewind fix for T44505 (leave in ifdef'd) This makes selection fail in simple cases, default cube subdiv 10x for eg. --- source/blender/editors/screen/glutil.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 2a0e13bccbc..a478a1f1b84 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -991,7 +991,7 @@ void bgl_get_mats(bglMats *mats) /** * \note \a viewdist is only for ortho at the moment. */ -void bglPolygonOffset(float UNUSED(viewdist), float dist) +void bglPolygonOffset(float viewdist, float dist) { static float winmat[16], offset = 0.0; @@ -1008,7 +1008,7 @@ void bglPolygonOffset(float UNUSED(viewdist), float dist) /* dist is from camera to center point */ if (winmat[15] > 0.5f) { -#if 0 +#if 1 offs = 0.00001f * dist * viewdist; // ortho tweaking #else static float depth_fac = 0.0f; @@ -1018,6 +1018,8 @@ void bglPolygonOffset(float UNUSED(viewdist), float dist) depth_fac = 1.0f / (float)((1 << depthbits) - 1); } offs = (-1.0 / winmat[10]) * dist * depth_fac; + + UNUSED_VARS(viewdist); #endif } else { -- cgit v1.2.3 From f8540d7fd5a47bc9d1d676d5aaaa0de379c71637 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Tue, 28 Apr 2015 17:36:44 -0300 Subject: RenderResult should have a valid view whenever possible --- source/blender/render/intern/include/render_result.h | 1 + source/blender/render/intern/source/pipeline.c | 1 + source/blender/render/intern/source/render_result.c | 20 +++++++++++--------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h index e7a2cbf99cd..f031be9e9c9 100644 --- a/source/blender/render/intern/include/render_result.h +++ b/source/blender/render/intern/include/render_result.h @@ -60,6 +60,7 @@ struct RenderResult *render_result_new_full_sample(struct Render *re, struct RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty); +void render_result_view_new(struct RenderResult *rr, const char *viewname); void render_result_views_new(struct RenderResult *rr, struct RenderData *rd); /* Merge */ diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 7b5692fbdb6..7206c21de9e 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -747,6 +747,7 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, re->result = MEM_callocN(sizeof(RenderResult), "new render result"); re->result->rectx = re->rectx; re->result->recty = re->recty; + render_result_view_new(re->result, "new temporary view"); } if (re->r.scemode & R_VIEWPORT_PREVIEW) diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 0d3720a9eca..0bd4284746d 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -911,10 +911,16 @@ RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace return rr; } +void render_result_view_new(RenderResult *rr, const char *viewname) +{ + RenderView *rv = MEM_callocN(sizeof(RenderView), "new render view"); + BLI_addtail(&rr->views, rv); + BLI_strncpy(rv->name, viewname, sizeof(rv->name)); +} + void render_result_views_new(RenderResult *rr, RenderData *rd) { SceneRenderView *srv; - RenderView *rv; /* clear previously existing views - for sequencer */ render_result_views_free(rr); @@ -922,19 +928,15 @@ void render_result_views_new(RenderResult *rr, RenderData *rd) /* check renderdata for amount of views */ if ((rd->scemode & R_MULTIVIEW)) { for (srv = rd->views.first; srv; srv = srv->next) { - if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) continue; - - rv = MEM_callocN(sizeof(RenderView), "new render view"); - BLI_addtail(&rr->views, rv); - - BLI_strncpy(rv->name, srv->name, sizeof(rv->name)); + if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) + continue; + render_result_view_new(rr, srv->name); } } /* we always need at least one view */ if (BLI_listbase_count_ex(&rr->views, 1) == 0) { - rv = MEM_callocN(sizeof(RenderView), "new render view"); - BLI_addtail(&rr->views, rv); + render_result_view_new(rr, "new render view"); } } -- cgit v1.2.3 From f4d7f5216fe45a171bb92add0446dc7409c7b542 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Apr 2015 13:47:47 +0500 Subject: Buildbot: Fix typo in error message --- build_files/buildbot/slave_compile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py index cbe345e764c..8353bb8331c 100644 --- a/build_files/buildbot/slave_compile.py +++ b/build_files/buildbot/slave_compile.py @@ -140,7 +140,7 @@ else: retcode = subprocess.call(cur_scons_cmd + scons_options) if retcode != 0: - print('Error building rules wuth config ' + config) + print('Error building rules with config ' + config) sys.exit(retcode) sys.exit(0) -- cgit v1.2.3 From 029bd44bbd0fc6c1c59c6cb37f9e70c4dd23f91d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Apr 2015 13:57:02 +0500 Subject: SCons: Fix wrong flags usage after recent stdc89 changes CCFLAGS are used for both C and C++ compilers and one is better not to pass C-related flags to C++ compiler. C-compiler flags are to be passed via CFLAGS variable. --- build_files/scons/config/linux-config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build_files/scons/config/linux-config.py b/build_files/scons/config/linux-config.py index c3f0c434081..63531200d7c 100644 --- a/build_files/scons/config/linux-config.py +++ b/build_files/scons/config/linux-config.py @@ -230,7 +230,8 @@ WITH_BF_FREESTYLE = True CC = 'gcc' CXX = 'g++' -CCFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing', '-std=gnu89', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64','-D_LARGEFILE64_SOURCE'] +CCFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64','-D_LARGEFILE64_SOURCE'] +CFLAGS = ['-std=gnu89'] CXXFLAGS = [] CPPFLAGS = [] -- cgit v1.2.3 From e37373d96e6784d08e3f6091733cff06923f5aae Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 29 Apr 2015 11:19:23 +0200 Subject: Revert commit with perspective depth offset, makes simple cases such as loopcuts on cube have zfighting. --- source/blender/editors/screen/glutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index a478a1f1b84..c7421aa0c16 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -1024,7 +1024,7 @@ void bglPolygonOffset(float viewdist, float dist) } else { /* should be clipping value or so... */ - offs = 0.0001f * dist; + offs = 0.0005f * dist; } winmat[14] -= offs; -- cgit v1.2.3 From 615414fa364f8772b1a1bee04ec9372ef73baee1 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Apr 2015 14:29:42 +0500 Subject: SCons: Ignore .svn folder when installing site-packages --- build_files/scons/tools/Blender.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py index e751be3ebc5..6e7417c76ec 100644 --- a/build_files/scons/tools/Blender.py +++ b/build_files/scons/tools/Blender.py @@ -670,6 +670,8 @@ def WinPyBundle(target=None, source=None, env=None): py_dir += '/release/site-packages' # grr, we have to do one by one because the dir exists for f in os.listdir(py_dir): + if f == '.svn': + continue fn_src = os.path.join(py_dir, f) fn_dst = os.path.join(py_target, f) -- cgit v1.2.3 From 728d4f296f79674accf2284543bd408fc4682df7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Apr 2015 19:39:58 +1000 Subject: Cleanup: headers --- source/blender/editors/transform/transform.c | 1 + source/blender/editors/transform/transform.h | 5 +---- source/blender/editors/transform/transform_ops.c | 1 + 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index a7b984fc76a..3cf0c53d564 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -54,6 +54,7 @@ #include "BLI_memarena.h" #include "BKE_nla.h" +#include "BKE_editmesh.h" #include "BKE_editmesh_bvh.h" #include "BKE_context.h" #include "BKE_constraint.h" diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 1971c88ae2e..f5a9b3d6ae0 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -39,9 +39,6 @@ #include "DNA_listBase.h" -#include "BLI_smallhash.h" -#include "BKE_editmesh.h" - /* ************************** Types ***************************** */ struct TransInfo; @@ -261,7 +258,7 @@ typedef struct EdgeSlideData { typedef struct TransDataVertSlideVert { /* TransDataGenericSlideVert */ - BMVert *v; + struct BMVert *v; struct LinkNode **cd_loop_groups; float co_orig_3d[3]; /* end generic */ diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 291c70bd7dc..8e0b3d708e2 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -38,6 +38,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_report.h" +#include "BKE_editmesh.h" #include "RNA_access.h" #include "RNA_define.h" -- cgit v1.2.3 From e1ecd39f0ee2ce1139045c83b8f5e415c346570f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Apr 2015 10:25:59 +1000 Subject: BMesh: avoid over-counting vert-edges --- source/blender/bmesh/intern/bmesh_core.c | 6 ++---- source/blender/bmesh/intern/bmesh_structure.c | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 7d6743e7598..16a9ecb56c9 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1687,7 +1687,7 @@ BMEdge *bmesh_jekv( BMEdge *e_old; BMVert *v_old, *tv; BMLoop *l_kill; - int len, radlen = 0, i; + int radlen = 0, i; bool halt = false; #ifndef NDEBUG bool edok; @@ -1698,10 +1698,8 @@ BMEdge *bmesh_jekv( if (BM_vert_in_edge(e_kill, v_kill) == 0) { return NULL; } - - len = bmesh_disk_count(v_kill); - if (len == 2) { + if (bmesh_disk_count_ex(v_kill, 3) == 2) { #ifndef NDEBUG int valence1, valence2; BMLoop *l; diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c index cf56c3b4b83..5d2eed8c753 100644 --- a/source/blender/bmesh/intern/bmesh_structure.c +++ b/source/blender/bmesh/intern/bmesh_structure.c @@ -228,7 +228,7 @@ bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) if (!BM_vert_in_edge(e, v)) return false; - if (bmesh_disk_count(v) != len || len == 0) + if (bmesh_disk_count_ex(v, len + 1) != len || len == 0) return false; e_iter = e; -- cgit v1.2.3 From 179ffefce5abd786531b8825634d6179d5634322 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Apr 2015 12:25:20 +1000 Subject: BMesh: replace smallhash flag for checking doubles --- source/blender/bmesh/intern/bmesh_core.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 16a9ecb56c9..a370f2be805 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1989,27 +1989,38 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b) BLI_assert(BM_edge_exists(v_a, v_b) == false); if (v_a->e && v_b->e) { - SmallHash visit; BMEdge *e, *e_first; - BLI_smallhash_init(&visit); +#define VERT_VISIT _FLAG_WALK + /* tag 'v_a' */ e = e_first = v_a->e; do { BMVert *v_other = BM_edge_other_vert(e, v_a); - BLI_smallhash_insert(&visit, (uintptr_t)v_other, NULL); + BLI_assert(!BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)); + BM_ELEM_API_FLAG_ENABLE(v_other, VERT_VISIT); } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first); + /* check 'v_b' connects to 'v_a' edges */ e = e_first = v_b->e; do { BMVert *v_other = BM_edge_other_vert(e, v_b); - if (BLI_smallhash_haskey(&visit, (uintptr_t)v_other)) { + if (BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)) { is_double = true; break; } } while ((e = BM_DISK_EDGE_NEXT(e, v_b)) != e_first); - BLI_smallhash_release(&visit); + /* cleanup */ + e = e_first = v_a->e; + do { + BMVert *v_other = BM_edge_other_vert(e, v_a); + BLI_assert(BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)); + BM_ELEM_API_FLAG_DISABLE(v_other, VERT_VISIT); + } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first); + +#undef VERT_VISIT + } return is_double; -- cgit v1.2.3 From 65a95926600027814ef01ce5beaf711d3f41be55 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Apr 2015 12:48:06 +1000 Subject: BMesh: optimize edge split Avoid hashing edges when splitting into fans, Instead, walk & split fans until they're all done, gives approx 40% speedup. --- source/blender/bmesh/intern/bmesh_core.c | 214 +++++++++++++++++-------------- 1 file changed, 116 insertions(+), 98 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index a370f2be805..ee34a749d93 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -31,7 +31,7 @@ #include "BLI_math_vector.h" #include "BLI_array.h" #include "BLI_alloca.h" -#include "BLI_smallhash.h" +#include "BLI_linklist_stack.h" #include "BLI_stackdefines.h" #include "BLF_translation.h" @@ -2095,126 +2095,131 @@ void bmesh_vert_separate( BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, const bool copy_select) { - const int v_edgetot = BM_vert_face_count(v); - BMEdge **stack = BLI_array_alloca(stack, v_edgetot); - STACK_DECLARE(stack); + int v_edges_num = 0; - SmallHash visithash; - BMVert **verts = NULL; - BMIter eiter, liter; - BMLoop *l; - BMEdge *e; - int i, maxindex; - BMLoop *l_new; + /* Detailed notes on array use since this is stack memory, we have to be careful */ - BLI_smallhash_init_ex(&visithash, v_edgetot); + /* newly created vertices, only use when 'r_vout' is set + * (total size will be number of fans) */ + BLI_SMALLSTACK_DECLARE(verts_new, BMVert *); + /* fill with edges from the face-fan, clearing on completion + * (total size will be max fan edge count) */ + BLI_SMALLSTACK_DECLARE(edges, BMEdge *); + /* temp store edges to walk over when filling 'edges', + * (total size will be max radial edges of any edge) */ + BLI_SMALLSTACK_DECLARE(edges_search, BMEdge *); - STACK_INIT(stack, v_edgetot); + /* number of resulting verts, include self */ + int verts_num = 1; + /* track the total number of edges handled, so we know when we've found the last fan */ + int edges_found = 0; - maxindex = 0; - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - if (BLI_smallhash_haskey(&visithash, (uintptr_t)e)) { - continue; - } +#define EDGE_VISIT _FLAG_WALK + + /* count and flag at once */ + if (v->e) { + BMEdge *e_first, *e_iter; + e_iter = e_first = v->e; + do { + v_edges_num += 1; + BLI_assert(!BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT)); + BM_ELEM_API_FLAG_ENABLE(e_iter, EDGE_VISIT); + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + } + + while (true) { /* Considering only edges and faces incident on vertex v, walk * the edges & faces and assign an index to each connected set */ - BLI_smallhash_insert(&visithash, (uintptr_t)e, SET_INT_IN_POINTER(maxindex)); + + BMEdge *e = v->e; + BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT); + do { + BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)); + BLI_SMALLSTACK_PUSH(edges, e); + edges_found += 1; + if (e->l) { BMLoop *l_iter, *l_first; l_iter = l_first = e->l; do { - l_new = (l_iter->v == v) ? l_iter->prev : l_iter->next; - BLI_assert(BM_vert_in_edge(l_new->e, v)); - if (!BLI_smallhash_haskey(&visithash, (uintptr_t)l_new->e)) { - BLI_smallhash_insert(&visithash, (uintptr_t)l_new->e, SET_INT_IN_POINTER(maxindex)); - STACK_PUSH(stack, l_new->e); + BMLoop *l_adjacent = (l_iter->v == v) ? l_iter->prev : l_iter->next; + BLI_assert(BM_vert_in_edge(l_adjacent->e, v)); + if (BM_ELEM_API_FLAG_TEST(l_adjacent->e, EDGE_VISIT)) { + BM_ELEM_API_FLAG_DISABLE(l_adjacent->e, EDGE_VISIT); + BLI_SMALLSTACK_PUSH(edges_search, l_adjacent->e); } } while ((l_iter = l_iter->radial_next) != l_first); } - } while ((e = STACK_POP(stack))); + } while ((e = BLI_SMALLSTACK_POP(edges_search))); - maxindex++; - } + /* now we have all edges connected to 'v->e' */ - /* Make enough verts to split v for each group */ - if (r_vout != NULL) { - verts = MEM_callocN(sizeof(BMVert *) * maxindex, __func__); - } - else { - verts = BLI_array_alloca(verts, maxindex); - } + BLI_assert(edges_found <= v_edges_num); - verts[0] = v; - for (i = 1; i < maxindex; i++) { - verts[i] = BM_vert_create(bm, v->co, v, BM_CREATE_NOP); - if (copy_select) { - BM_elem_select_copy(bm, bm, verts[i], v); + if (edges_found == v_edges_num) { + /* We're done! The remaining edges in 'edges' form the last fan, + * which can be left as is. + * if 'edges' were alloc'd it'd be freed here. */ + break; } - } + else { + BMVert *v_new; - /* Replace v with the new verts in each group */ -#if 0 - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - /* call first since its faster then a hash lookup */ - if (l->v != v) { - continue; - } - i = GET_INT_FROM_POINTER(BLI_ghash_lookup(visithash, l->e)); - if (i == 0) { - continue; - } + v_new = BM_vert_create(bm, v->co, v, BM_CREATE_NOP); + if (copy_select) { + BM_elem_select_copy(bm, bm, v_new, v); + } - /* Loops here should always refer to an edge that has v as an - * endpoint. For each appearance of this vert in a face, there - * will actually be two iterations: one for the loop heading - * towards vertex v, and another for the loop heading out from - * vertex v. Only need to swap the vertex on one of those times, - * on the outgoing loop. */ + while ((e = BLI_SMALLSTACK_POP(edges))) { - /* XXX - because this clobbers the iterator, this *whole* block is commented, see below */ - l->v = verts[i]; - } -#else - /* note: this is the same as the commented code above *except* that it doesn't break iterator - * by modifying data it loops over [#30632], this re-uses the 'stack' variable which is a bit - * bad practice but save alloc'ing a new array - note, the comment above is useful, keep it - * if you are tidying up code - campbell */ - STACK_INIT(stack, v_edgetot); - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - STACK_PUSH(stack, (BMEdge *)l); - } - while ((l = (BMLoop *)(STACK_POP(stack)))) { - if ((i = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&visithash, (uintptr_t)l->e)))) { - l->v = verts[i]; - } - } -#endif + /* swap out loops */ + if (e->l) { + BMLoop *l_iter, *l_first; + l_iter = l_first = e->l; + do { + if (l_iter->v == v) { + l_iter->v = v_new; + } + } while ((l_iter = l_iter->radial_next) != l_first); + } - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - i = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&visithash, (uintptr_t)e)); - if (i == 0) { - continue; - } + /* swap out edges */ + BLI_assert(e->v1 == v || e->v2 == v); + bmesh_disk_edge_remove(e, v); + bmesh_edge_swapverts(e, v, v_new); + bmesh_disk_edge_append(e, v_new); + } - BLI_assert(e->v1 == v || e->v2 == v); - bmesh_disk_edge_remove(e, v); - bmesh_edge_swapverts(e, v, verts[i]); - bmesh_disk_edge_append(e, verts[i]); + if (r_vout) { + BLI_SMALLSTACK_PUSH(verts_new, v_new); + } + verts_num += 1; + } } - BLI_smallhash_release(&visithash); +#undef EDGE_VISIT - for (i = 0; i < maxindex; i++) { - BM_CHECK_ELEMENT(verts[i]); - } + /* flags are clean now, handle return values */ if (r_vout_len != NULL) { - *r_vout_len = maxindex; + *r_vout_len = verts_num; } if (r_vout != NULL) { + BMVert **verts; + int i; + + verts = MEM_mallocN(sizeof(BMVert *) * verts_num, __func__); + verts[0] = v; + + for (i = 1; i < verts_num; i++) { + verts[i] = BLI_SMALLSTACK_POP(verts_new); + BLI_assert(verts[i] != NULL); + } + BLI_assert(BLI_SMALLSTACK_POP(verts_new) == NULL); + *r_vout = verts; } } @@ -2341,26 +2346,39 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep) int len, i; BMVert *v_new = NULL; BMVert *v_sep = l_sep->v; + BMEdge *e_iter; /* peel the face from the edge radials on both sides of the * loop vert, disconnecting the face from its fan */ bmesh_edge_separate(bm, l_sep->e, l_sep, false); bmesh_edge_separate(bm, l_sep->prev->e, l_sep->prev, false); - if (bmesh_disk_count(v_sep) == 2) { - /* If there are still only two edges out of v_sep, then - * this whole URMV was just a no-op, so exit now. */ + /* do inline, below */ +#if 0 + if (BM_vert_edge_count_is_equal(v_sep, 2)) { return v_sep; } +#endif - /* Update the disk start, so that v->e points to an edge - * not touching the split loop. This is so that BM_vert_split - * will leave the original v_sep on some *other* fan (not the - * one-face fan that holds the unglue face). */ - while (v_sep->e == l_sep->e || v_sep->e == l_sep->prev->e) { - v_sep->e = bmesh_disk_edge_next(v_sep->e, v_sep); + /* Search for an edge unattached to this loop */ + e_iter = v_sep->e; + while (!ELEM(e_iter, l_sep->e, l_sep->prev->e)) { + e_iter = bmesh_disk_edge_next(e_iter, v_sep); + + /* We've come back around to the initial edge, all touch this loop. + * If there are still only two edges out of v_sep, + * then this whole URMV was just a no-op, so exit now. */ + if (e_iter == v_sep->e) { + BLI_assert(BM_vert_edge_count_is_equal(v_sep, 2)); + return v_sep; + } } + /* Update the disk start, so that v->e points to an edge touching the split loop. + * This is so that BM_vert_split will leave the original v_sep on some *other* fan + * (not the one-face fan that holds the unglue face). */ + v_sep->e = e_iter; + /* Split all fans connected to the vert, duplicating it for * each fans. */ bmesh_vert_separate(bm, v_sep, &vtar, &len, false); -- cgit v1.2.3 From 620cc762dbcab37afba5ac069035649290f6182a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Apr 2015 14:51:50 +0500 Subject: Buildbot: Attempt to fix cudakernels target screwing up autotest cache --- build_files/buildbot/slave_compile.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py index 8353bb8331c..7b3f848a198 100644 --- a/build_files/buildbot/slave_compile.py +++ b/build_files/buildbot/slave_compile.py @@ -116,6 +116,8 @@ else: if config.find('player') != -1: scons_options.append('BF_BUILDDIR=%s_player' % (build_dir)) + elif config.find('cuda') != -1: + scons_options.append('BF_BUILDDIR=%s_cuda' % (build_dir)) else: scons_options.append('BF_BUILDDIR=%s' % (build_dir)) -- cgit v1.2.3 From 7232157357a9905ed611fbcfbe6990b1275311b6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Apr 2015 20:16:40 +1000 Subject: Correct comment --- source/blender/bmesh/intern/bmesh_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index ee34a749d93..558d41c12be 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -2130,7 +2130,7 @@ void bmesh_vert_separate( while (true) { /* Considering only edges and faces incident on vertex v, walk - * the edges & faces and assign an index to each connected set */ + * the edges & collect in the 'edges' list for splitting */ BMEdge *e = v->e; BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT); -- cgit v1.2.3 From 734fb30bda1d3b0b444b1f627f156598961ca8ca Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 29 Apr 2015 12:30:25 +0200 Subject: Use size_t to calculate size of tiles for rendering --- source/blender/render/intern/source/render_result.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 0bd4284746d..f3a8dfde299 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -486,7 +486,7 @@ static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int const size_t view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name)); const char *typestr = name_from_passtype(passtype, -1); RenderPass *rpass = MEM_callocN(sizeof(RenderPass), typestr); - int rectsize = rr->rectx * rr->recty * channels; + size_t rectsize = rr->rectx * rr->recty * channels; BLI_addtail(&rl->passes, rpass); rpass->passtype = passtype; -- cgit v1.2.3 From 2e91bcfb9d5384bf14c5f405998aa8637b0fc918 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Apr 2015 15:29:42 +0500 Subject: Fix T44544: Cached BVH is broken since BVH leaf split Still need to solve issues with reading old cache with new builds. --- intern/cycles/bvh/bvh.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index d1c3feed963..0d9412a5712 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -107,6 +107,7 @@ bool BVH::cache_read(CacheData& key) if(!(value.read(pack.root_index) && value.read(pack.SAH) && value.read(pack.nodes) && + value.read(pack.leaf_nodes) && value.read(pack.object_node) && value.read(pack.tri_woop) && value.read(pack.prim_type) && @@ -118,6 +119,7 @@ bool BVH::cache_read(CacheData& key) pack.root_index = 0; pack.SAH = 0.0f; pack.nodes.clear(); + pack.leaf_nodes.clear(); pack.object_node.clear(); pack.tri_woop.clear(); pack.prim_type.clear(); @@ -140,6 +142,7 @@ void BVH::cache_write(CacheData& key) value.add(pack.SAH); value.add(pack.nodes); + value.add(pack.leaf_nodes); value.add(pack.object_node); value.add(pack.tri_woop); value.add(pack.prim_type); -- cgit v1.2.3 From d6b28bbb1d61f059ec28156fb275393ee3389d57 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Apr 2015 15:48:49 +0500 Subject: Cycles: Fix crashes when loading cache created with pre-leaf split builds --- intern/cycles/util/util_cache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/util/util_cache.h b/intern/cycles/util/util_cache.h index 9d001a6f1ff..343fa36817d 100644 --- a/intern/cycles/util/util_cache.h +++ b/intern/cycles/util/util_cache.h @@ -105,7 +105,7 @@ public: return false; } - if(!size) + if((size == 0) || (size % sizeof(T)) != 0) return false; data.resize(size/sizeof(T)); -- cgit v1.2.3 From 3acc1ba49c95786841608c0b516a7fd0879bad76 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Apr 2015 23:54:32 +1000 Subject: Add macro BLI_SMALLSTACK_AS_TABLE Use for edge-split (a little less overhead compare to popping each item). --- source/blender/blenlib/BLI_linklist_stack.h | 10 ++++++++++ source/blender/bmesh/intern/bmesh_core.c | 12 +++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h index 9ac233a8fa4..a4b8f77bfa6 100644 --- a/source/blender/blenlib/BLI_linklist_stack.h +++ b/source/blender/blenlib/BLI_linklist_stack.h @@ -168,6 +168,16 @@ #define BLI_SMALLSTACK_IS_EMPTY(var) \ ((_BLI_SMALLSTACK_CAST(var) _##var##_stack) == NULL) +/* fill in a lookup table */ +#define BLI_SMALLSTACK_AS_TABLE(var, data) \ +{ \ + LinkNode *_##var##_iter; \ + unsigned int i; \ + for (_##var##_iter = _##var##_stack, i = 0; _##var##_iter; _##var##_iter = _##var##_iter->next, i++) { \ + (data)[i] = _BLI_SMALLSTACK_CAST(var) (_##var##_iter->link); \ + } \ +} ((void)0) + /* loop over stack members last-added-first */ #define BLI_SMALLSTACK_ITER_BEGIN(var, item) \ { \ diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 558d41c12be..3266ee0394d 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -2209,18 +2209,12 @@ void bmesh_vert_separate( if (r_vout != NULL) { BMVert **verts; - int i; verts = MEM_mallocN(sizeof(BMVert *) * verts_num, __func__); - verts[0] = v; - - for (i = 1; i < verts_num; i++) { - verts[i] = BLI_SMALLSTACK_POP(verts_new); - BLI_assert(verts[i] != NULL); - } - BLI_assert(BLI_SMALLSTACK_POP(verts_new) == NULL); - *r_vout = verts; + + verts[0] = v; + BLI_SMALLSTACK_AS_TABLE(verts_new, &verts[1]); } } -- cgit v1.2.3 From b033736eb7ea65d47bc3cb13605df176c490efe1 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Wed, 29 Apr 2015 11:18:18 -0300 Subject: Multi-View: new util functions RE_RenderViewGetById() and RE_RenderViewGetByName() Both functions try to find a valid RenderView and if they can't they fallback to the first RenderView of the RenderResult --- .../compositor/operations/COM_CompositorOperation.cpp | 2 +- source/blender/render/extern/include/RE_pipeline.h | 2 ++ source/blender/render/intern/source/pipeline.c | 8 +++----- source/blender/render/intern/source/render_result.c | 16 ++++++++++++++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp index eacbdf91be2..76f74c144f6 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.cpp +++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp @@ -82,7 +82,7 @@ void CompositorOperation::deinitExecution() RenderResult *rr = RE_AcquireResultWrite(re); if (rr) { - RenderView *rv = (RenderView *)BLI_findstring(&rr->views, this->m_viewName, offsetof(RenderView, name)); + RenderView *rv = RE_RenderViewGetByName(rr, this->m_viewName); if (rv->rectf != NULL) { MEM_freeN(rv->rectf); diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 39e17c28162..2c3ad74c7e3 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -354,6 +354,8 @@ bool RE_allow_render_generic_object(struct Object *ob); bool RE_HasFakeLayer(RenderResult *res); bool RE_RenderResult_is_stereo(RenderResult *res); +struct RenderView *RE_RenderViewGetById(struct RenderResult *res, const int view_id); +struct RenderView *RE_RenderViewGetByName(struct RenderResult *res, const char *viewname); float *RE_RenderViewGetRectf(struct RenderResult *rr, const int view_id); float *RE_RenderViewGetRectz(struct RenderResult *rr, const int view_id); int *RE_RenderViewGetRect32(struct RenderResult *rr, const int view_id); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 7206c21de9e..c26a74f18c5 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -395,9 +395,7 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id) rr->recty = re->result->recty; /* actview view */ - rv = BLI_findlink(&re->result->views, view_id); - if (rv == NULL) - rv = (RenderView *)re->result->views.first; + rv = RE_RenderViewGetById(re->result, view_id); rr->rectf = rv ? rv->rectf : NULL; rr->rectz = rv ? rv->rectz : NULL; @@ -2287,7 +2285,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) /* store the final result */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - rv = BLI_findlink(&re->result->views, nr); + rv = RE_RenderViewGetById(re->result, nr); if (rv->rectf) MEM_freeN(rv->rectf); rv->rectf = rectf; @@ -2571,7 +2569,7 @@ static void do_render_seq(Render *re) BLI_rw_mutex_unlock(&re->resultmutex); for (view_id = 0; view_id < tot_views; view_id++) { - RenderView *rv = BLI_findlink(&rr->views, view_id); + RenderView *rv = RE_RenderViewGetById(rr, view_id); BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if (ibuf_arr[view_id]) { diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index f3a8dfde299..1668b11bd20 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -1507,7 +1507,7 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd, const int vi void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBuf *ibuf, const int view_id) { - RenderView *rv = BLI_findlink(&rr->views, view_id); + RenderView *rv = RE_RenderViewGetById(rr, view_id); if (ibuf->rect_float) { if (!rv->rectf) @@ -1536,7 +1536,7 @@ void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBu void render_result_rect_fill_zero(RenderResult *rr, const int view_id) { - RenderView *rv = BLI_findlink(&rr->views, view_id); + RenderView *rv = RE_RenderViewGetById(rr, view_id); if (rv->rectf) memset(rv->rectf, 0, 4 * sizeof(float) * rr->rectx * rr->recty); @@ -1592,6 +1592,18 @@ bool RE_RenderResult_is_stereo(RenderResult *res) return true; } +RenderView *RE_RenderViewGetById(RenderResult *res, const int view_id) +{ + RenderView *rv = BLI_findlink(&res->views, view_id); + return rv ? rv : res->views.first; +} + +RenderView *RE_RenderViewGetByName(RenderResult *res, const char *viewname) +{ + RenderView *rv = BLI_findstring(&res->views, viewname, offsetof(RenderView, name)); + return rv ? rv : res->views.first; +} + void RE_RenderViewSetRectf(RenderResult *res, const int view_id, float *rect) { RenderView *rv = BLI_findlink(&res->views, view_id); -- cgit v1.2.3 From 18ba32df37aa84d0a7c884bd1945772df0d9c59f Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 29 Apr 2015 16:28:20 +0200 Subject: Don't check against scene notifier twice --- source/blender/windowmanager/intern/wm_event_system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 830feed2fc7..e2b8598b4fe 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -293,7 +293,7 @@ void wm_event_do_notifiers(bContext *C) do_anim = true; } } - if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_SCENE, NC_WM)) { + if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_WM)) { ED_info_stats_clear(win->screen->scene); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL); } -- cgit v1.2.3 From 3e6a66b9dee4e0b034a1de83fbd242191858a7df Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Wed, 29 Apr 2015 11:26:30 -0300 Subject: Multi-View cleanup: using RenderResult->rect* only for temporary RenderResults Originally I wanted to get rid of RenderResult->rect* entirely, but it's convenient to have for temporary structs. This patch makes sure they are used only when really needed, which should help clearing the code out. (they are needed when using RE_AcquireResultImage() - which produces a RenderResult with no RenderView) Reviewers: sergey Differential Revision: https://developer.blender.org/D1270 --- source/blender/blenkernel/intern/image.c | 2 +- source/blender/editors/render/render_internal.c | 10 ++- source/blender/editors/render/render_opengl.c | 6 +- source/blender/editors/render/render_preview.c | 9 ++- source/blender/editors/space_image/image_buttons.c | 5 +- source/blender/render/extern/include/RE_pipeline.h | 9 +-- source/blender/render/intern/source/pipeline.c | 25 ++++--- .../blender/render/intern/source/render_result.c | 76 ++++------------------ 8 files changed, 52 insertions(+), 90 deletions(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 162f45379d8..eceb5c4ff20 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -3554,7 +3554,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ } else if (ima->renders[ima->render_slot]) { rres = *(ima->renders[ima->render_slot]); - rres.have_combined = RE_RenderViewGetRectf(&rres, actview) != NULL; + rres.have_combined = ((RenderView *)rres.views.first)->rectf != NULL; } else memset(&rres, 0, sizeof(RenderResult)); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 2f279122ae4..2ba1e615a9e 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -189,11 +189,15 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu */ /* TODO(sergey): Need to check has_combined here? */ if (iuser->passtype == SCE_PASS_COMBINED) { + RenderView *rv; size_t view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname); + rv = RE_RenderViewGetById(rr, view_id); + /* find current float rect for display, first case is after composite... still weak */ - rectf = RE_RenderViewGetRectf(rr, view_id); - if (rectf == NULL) { - if (RE_RenderViewGetRect32(rr, view_id)) { + if (rv->rectf) + rectf = rv->rectf; + else { + if (rv->rect32) { /* special case, currently only happens with sequencer rendering, * which updates the whole frame, so we can only mark display buffer * as invalid here (sergey) diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 164f5f4bfd7..7fbdf9dc66b 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -248,7 +248,7 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) Object *camera = NULL; ImBuf *ibuf; float winmat[4][4]; - float *rectf = RE_RenderViewGetRectf(rr, oglrender->view_id); + float *rectf = RE_RenderViewGetById(rr, oglrender->view_id)->rectf; int sizex = oglrender->sizex; int sizey = oglrender->sizey; const short view_context = (v3d != NULL); @@ -446,8 +446,8 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) if (rect) { int profile_to; - float *rectf = RE_RenderViewGetRectf(rr, oglrender->view_id); - + float *rectf = RE_RenderViewGetById(rr, oglrender->view_id)->rectf; + if (BKE_scene_check_color_management_enabled(scene)) profile_to = IB_PROFILE_LINEAR_RGB; else diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index e6fbfda3067..2c353c13334 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -525,6 +525,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, rcti *newrect) { Render *re; + RenderView *rv; RenderResult rres; char name[32]; int offx = 0; @@ -549,10 +550,12 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, /* test if something rendered ok */ re = RE_GetRender(name); + RE_AcquireResultImageViews(re, &rres); + /* material preview only needs monoscopy (view 0) */ - RE_AcquireResultImage(re, &rres, 0); + rv = RE_RenderViewGetById(&rres, 0); - if (rres.rectf) { + if (rv->rectf) { if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) { @@ -577,7 +580,7 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, } } - RE_ReleaseResultImage(re); + RE_ReleaseResultImageViews(re, &rres); return ok; } diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 1c668c33597..e52eea248ed 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -312,10 +312,11 @@ static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void * static const char *ui_imageuser_layer_fake_name(RenderResult *rr) { - if (RE_RenderViewGetRectf(rr, 0)) { + RenderView *rv = RE_RenderViewGetById(rr, 0); + if (rv->rectf) { return IFACE_("Composite"); } - else if (RE_RenderViewGetRect32(rr, 0)) { + else if (rv->rect32) { return IFACE_("Sequence"); } else { diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 2c3ad74c7e3..2df4cde2b27 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -138,6 +138,9 @@ typedef struct RenderResult { int rectx, recty; short crop, sample_nr; + /* the following rect32, rectf and rectz buffers are for temporary storage only, for RenderResult structs + * created in #RE_AcquireResultImage - which do not have RenderView */ + /* optional, 32 bits version of picture, used for ogl render and image curves */ int *rect32; /* if this exists, a copy of one of layers, or result of composited layers */ @@ -353,14 +356,8 @@ bool RE_allow_render_generic_object(struct Object *ob); bool RE_HasFakeLayer(RenderResult *res); bool RE_RenderResult_is_stereo(RenderResult *res); - struct RenderView *RE_RenderViewGetById(struct RenderResult *res, const int view_id); struct RenderView *RE_RenderViewGetByName(struct RenderResult *res, const char *viewname); -float *RE_RenderViewGetRectf(struct RenderResult *rr, const int view_id); -float *RE_RenderViewGetRectz(struct RenderResult *rr, const int view_id); -int *RE_RenderViewGetRect32(struct RenderResult *rr, const int view_id); -void RE_RenderViewSetRectf(struct RenderResult *res, const int view_id, float *rect); -void RE_RenderViewSetRectz(struct RenderResult *res, const int view_id, float *rect); #endif /* __RE_PIPELINE_H__ */ diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index c26a74f18c5..a4089002ba5 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -380,6 +380,8 @@ void RE_ReleaseResultImageViews(Render *re, RenderResult *rr) } /* fill provided result struct with what's currently active or done */ +/* this RenderResult struct is the only exception to the rule of a RenderResult */ +/* always having at least one RenderView */ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id) { memset(rr, 0, sizeof(RenderResult)); @@ -397,14 +399,14 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id) /* actview view */ rv = RE_RenderViewGetById(re->result, view_id); - rr->rectf = rv ? rv->rectf : NULL; - rr->rectz = rv ? rv->rectz : NULL; - rr->rect32 = rv ? rv->rect32 : NULL; + rr->rectf = rv->rectf; + rr->rectz = rv->rectz; + rr->rect32 = rv->rect32; /* active layer */ rl = render_get_active_layer(re, re->result); - if (rl && rv) { + if (rl) { if (rv->rectf == NULL) rr->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rv->name); @@ -412,7 +414,7 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id) rr->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rv->name); } - rr->have_combined = rv ? (rv->rectf != NULL) : false; + rr->have_combined = (rv->rectf != NULL); rr->layers = re->result->layers; rr->views = re->result->views; @@ -434,9 +436,9 @@ void RE_ResultGet32(Render *re, unsigned int *rect) RenderResult rres; const size_t view_id = BKE_scene_multiview_view_id_get(&re->r, re->viewname); - RE_AcquireResultImage(re, &rres, view_id); - render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings, 0); - RE_ReleaseResultImage(re); + RE_AcquireResultImageViews(re, &rres); + render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings, view_id); + RE_ReleaseResultImageViews(re, &rres); } /* caller is responsible for allocating rect in correct size! */ @@ -768,11 +770,14 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, static void render_result_rescale(Render *re) { RenderResult *result = re->result; + RenderView *rv; int x, y; float scale_x, scale_y; float *src_rectf; - src_rectf = result->rectf; + rv = RE_RenderViewGetById(result, 0); + src_rectf = rv->rectf; + if (src_rectf == NULL) { RenderLayer *rl = render_get_active_layer(re, re->result); if (rl != NULL) { @@ -790,7 +795,7 @@ static void render_result_rescale(Render *re) ""); if (re->result != NULL) { - dst_rectf = re->result->rectf; + dst_rectf = RE_RenderViewGetById(re->result, 0)->rectf; if (dst_rectf == NULL) { RenderLayer *rl; rl = render_get_active_layer(re, re->result); diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 1668b11bd20..c8ca1105417 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -1465,12 +1465,13 @@ bool render_result_exr_file_cache_read(Render *re) ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd, const int view_id) { ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0); - + RenderView *rv = RE_RenderViewGetById(rr, view_id); + /* if not exists, BKE_imbuf_write makes one */ - ibuf->rect = (unsigned int *) RE_RenderViewGetRect32(rr, view_id); - ibuf->rect_float = RE_RenderViewGetRectf(rr, view_id); - ibuf->zbuf_float = RE_RenderViewGetRectz(rr, view_id); - + ibuf->rect = (unsigned int *) rv->rect32; + ibuf->rect_float = rv->rectf; + ibuf->zbuf_float = rv->rectz; + /* float factor for random dither, imbuf takes care of it */ ibuf->dither = rd->dither_intensity; @@ -1528,10 +1529,6 @@ void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBu /* Same things as above, old rectf can hang around from previous render. */ MEM_SAFE_FREE(rv->rectf); } - - /* clean up non-view buffers */ - MEM_SAFE_FREE(rr->rect32); - MEM_SAFE_FREE(rr->rectf); } void render_result_rect_fill_zero(RenderResult *rr, const int view_id) @@ -1550,15 +1547,13 @@ void render_result_rect_get_pixels(RenderResult *rr, unsigned int *rect, int rec const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, const int view_id) { - if (rr->rect32) { - int *rect32 = RE_RenderViewGetRect32(rr, view_id); - memcpy(rect, (rect32 ? rect32 : rr->rect32), sizeof(int) * rr->rectx * rr->recty); - } - else if (rr->rectf) { - float *rectf = RE_RenderViewGetRectf(rr, view_id); - IMB_display_buffer_transform_apply((unsigned char *) rect, (rectf ? rectf : rr->rectf), rr->rectx, rr->recty, 4, + RenderView *rv = RE_RenderViewGetById(rr, view_id); + + if (rv->rect32) + memcpy(rect, rv->rect32, sizeof(int) * rr->rectx * rr->recty); + else if (rv->rectf) + IMB_display_buffer_transform_apply((unsigned char *) rect, rv->rectf, rr->rectx, rr->recty, 4, view_settings, display_settings, true); - } else /* else fill with black */ memset(rect, 0, sizeof(int) * rectx * recty); @@ -1595,56 +1590,13 @@ bool RE_RenderResult_is_stereo(RenderResult *res) RenderView *RE_RenderViewGetById(RenderResult *res, const int view_id) { RenderView *rv = BLI_findlink(&res->views, view_id); + BLI_assert(res->views.first); return rv ? rv : res->views.first; } RenderView *RE_RenderViewGetByName(RenderResult *res, const char *viewname) { RenderView *rv = BLI_findstring(&res->views, viewname, offsetof(RenderView, name)); + BLI_assert(res->views.first); return rv ? rv : res->views.first; } - -void RE_RenderViewSetRectf(RenderResult *res, const int view_id, float *rect) -{ - RenderView *rv = BLI_findlink(&res->views, view_id); - if (rv) { - rv->rectf = rect; - } -} - -void RE_RenderViewSetRectz(RenderResult *res, const int view_id, float *rect) -{ - RenderView *rv = BLI_findlink(&res->views, view_id); - if (rv) { - rv->rectz = rect; - } -} - -float *RE_RenderViewGetRectz(RenderResult *res, const int view_id) -{ - RenderView *rv = BLI_findlink(&res->views, view_id); - if (rv) { - return rv->rectz; - } - return res->rectz; -} - -float *RE_RenderViewGetRectf(RenderResult *res, const int view_id) -{ - RenderView *rv = BLI_findlink(&res->views, view_id); - if (rv) { - return rv->rectf; - } - return res->rectf; -} - -int *RE_RenderViewGetRect32(RenderResult *res, const int view_id) -{ - RenderView *rv = BLI_findlink(&res->views, view_id); - if (rv) { - return rv->rect32; - } - return res->rect32; -} - - -- cgit v1.2.3 From 78956b6a83f2b5b3011fcfee7715b563c4c8b1bd Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 29 Apr 2015 17:14:40 +0200 Subject: Fix T44542: 'extend selection' editmode tool would select hidden elements. --- source/blender/bmesh/operators/bmo_utils.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index da1991a187d..964d0b1dfc6 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -208,7 +208,7 @@ static void bmo_region_extend_expand( BMEdge *e; BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - if (!BMO_elem_flag_test(bm, e, SEL_ORIG)) { + if (!BMO_elem_flag_test(bm, e, SEL_ORIG) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { found = true; break; } @@ -221,7 +221,7 @@ static void bmo_region_extend_expand( BMEdge *e; BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - if (!BMO_elem_flag_test(bm, e, SEL_FLAG)) { + if (!BMO_elem_flag_test(bm, e, SEL_FLAG) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { BMO_elem_flag_enable(bm, e, SEL_FLAG); BMO_elem_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG); } @@ -232,7 +232,7 @@ static void bmo_region_extend_expand( BMFace *f; BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) { - if (!BMO_elem_flag_test(bm, f, SEL_FLAG)) { + if (!BMO_elem_flag_test(bm, f, SEL_FLAG) && !BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { bmo_face_flag_set_flush(bm, f, SEL_FLAG, true); } } @@ -243,7 +243,7 @@ static void bmo_region_extend_expand( BMEdge *e; BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { if (BM_edge_is_wire(e)) { - if (!BMO_elem_flag_test(bm, e, SEL_FLAG)) { + if (!BMO_elem_flag_test(bm, e, SEL_FLAG) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { BMO_elem_flag_enable(bm, e, SEL_FLAG); BMO_elem_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG); } @@ -267,7 +267,9 @@ static void bmo_region_extend_expand( BMFace *f_other; BM_ITER_ELEM (f_other, &fiter, l->e, BM_FACES_OF_EDGE) { - if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG)) { + if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG) && + !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN)) + { BMO_elem_flag_enable(bm, f_other, SEL_FLAG); } } @@ -277,7 +279,9 @@ static void bmo_region_extend_expand( BMFace *f_other; BM_ITER_ELEM (f_other, &fiter, l->v, BM_FACES_OF_VERT) { - if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG)) { + if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG) && + !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN)) + { BMO_elem_flag_enable(bm, f_other, SEL_FLAG); } } -- cgit v1.2.3 From 611bbc696afe58d2ab1b92c2a7578233606aefab Mon Sep 17 00:00:00 2001 From: Ines Almeida Date: Wed, 29 Apr 2015 16:22:04 +0100 Subject: cleanup for uiTemplateIconView --- .../blender/editors/interface/interface_templates.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index d333ab9f4c1..66de859b453 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1641,10 +1641,7 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem) /* arg_litem is malloced, can be freed by parent button */ cb = *((RNAUpdateCb *)arg_litem); - - /* unused */ - // icon = RNA_property_enum_get(&cb.ptr, cb.prop); - + block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); UI_block_flag_enable(block, UI_BLOCK_LOOP); @@ -1682,12 +1679,13 @@ void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname) EnumPropertyItem *items; uiBlock *block; uiBut *but; -// rctf rect; /* UNUSED */ int value, icon = ICON_NONE, tot_items; bool free_items; - - if (!prop || RNA_property_type(prop) != PROP_ENUM) + + if (!prop || RNA_property_type(prop) != PROP_ENUM) { + RNA_warning("property of type Enum not found: %s.%s", RNA_struct_identifier(ptr->type), propname); return; + } block = uiLayoutAbsoluteBlock(layout); @@ -1698,15 +1696,9 @@ void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname) cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); cb->ptr = *ptr; cb->prop = prop; - -// rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X; -// rect.ymin = 0; rect.ymax = 10.0f * UI_UNIT_X; - + but = uiDefBlockButN(block, ui_icon_view_menu_cb, MEM_dupallocN(cb), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); - -// but = uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, icon, 0, 0, BLI_rctf_size_x(&rect), BLI_rctf_size_y(&rect), ptr, prop, -1, 0, icon, -1, -1, NULL); - but->icon = icon; UI_but_flag_enable(but, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); -- cgit v1.2.3 From 091832c955992ecd8fff6d88028075775e4b4e8e Mon Sep 17 00:00:00 2001 From: Ines Almeida Date: Wed, 29 Apr 2015 16:25:54 +0100 Subject: fix for double call to update callback in uiTemplateIconView --- source/blender/editors/interface/interface_templates.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 66de859b453..8d2ee04a2e9 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1697,14 +1697,11 @@ void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname) cb->ptr = *ptr; cb->prop = prop; - but = uiDefBlockButN(block, ui_icon_view_menu_cb, MEM_dupallocN(cb), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); + but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); but->icon = icon; UI_but_flag_enable(but, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); - - UI_but_funcN_set(but, rna_update_cb, MEM_dupallocN(cb), NULL); - - MEM_freeN(cb); + if (free_items) { MEM_freeN(items); } -- cgit v1.2.3 From 0dbc9060a69e4d64a01a6fefdabb78acc32fab95 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 29 Apr 2015 17:46:03 +0200 Subject: Cleanup: make grumpy asan happy and do not use `new []` to allocate data freed by `free()`. Probably nothing crucial, but asan build would crash on that stupid glitch... Annoying. --- source/blender/imbuf/intern/dds/DirectDrawSurface.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index 15c8d86d61c..6bf82776afe 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -60,6 +60,7 @@ #include #include // printf +#include // malloc #include // sqrt #include @@ -1147,7 +1148,7 @@ void* DirectDrawSurface::readData(uint &rsize) uint size = stream.size - header_size; rsize = size; - unsigned char *data = new unsigned char[size]; + unsigned char *data = (unsigned char *)malloc(sizeof(*data) * size); stream.seek(header_size); mem_read(stream, data, size); -- cgit v1.2.3 From d04ba6d56245e28c70b56c5458dc9f16b6c0e278 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Apr 2015 21:47:30 +0500 Subject: Remove unused stubs Noticed by TristanPorteries in IRC. --- source/blenderplayer/bad_level_call_stubs/stubs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index f8a42159c27..08d01a9c79e 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -227,8 +227,6 @@ struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name) void RE_init_texture_rng() RET_NONE void RE_exit_texture_rng() RET_NONE -float *RE_RenderViewGetRectf(struct RenderResult *rr, int view_id) {STUB_ASSERT(0); return (float *) NULL;} -float *RE_RenderViewGetRectz(struct RenderResult *rr, int view_id) {STUB_ASSERT(0); return (float *) NULL;} bool RE_layers_have_name(struct RenderResult *result) {STUB_ASSERT(0); return 0;} void RE_engine_active_view_set(struct RenderEngine *engine, const char *viewname) {STUB_ASSERT(0);} void RE_engine_get_camera_model_matrix(struct RenderEngine *engine, struct Object *camera, float *r_modelmat) {STUB_ASSERT(0);} -- cgit v1.2.3 From 5782126d41a9ea7c12896752996fc21fd5be8e7b Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 29 Apr 2015 18:49:38 +0200 Subject: Make sure integer calculation uses large precision --- source/blender/render/intern/source/render_result.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index c8ca1105417..2baf445466c 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -486,7 +486,7 @@ static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int const size_t view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name)); const char *typestr = name_from_passtype(passtype, -1); RenderPass *rpass = MEM_callocN(sizeof(RenderPass), typestr); - size_t rectsize = rr->rectx * rr->recty * channels; + size_t rectsize = ((size_t)rr->rectx) * ((size_t)rr->recty) * ((size_t)channels); BLI_addtail(&rl->passes, rpass); rpass->passtype = passtype; -- cgit v1.2.3 From 3878180a6fa3db7aaec7bb6efb4fbfdff04306f6 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 29 Apr 2015 19:38:19 +0200 Subject: Fix typo using interp_v3_v3v3 over float[2] variables... Found by asan! ;) --- source/blender/editors/mesh/editmesh_select.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index be3cb1c5fe1..4ce493def5b 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -559,7 +559,7 @@ static void find_nearest_edge__doClosest( copy_v2_v2(screen_co, screen_co_b); } else { - interp_v3_v3v3(screen_co, screen_co_a, screen_co_b, fac); + interp_v2_v2v2(screen_co, screen_co_a, screen_co_b, fac); } dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co); -- cgit v1.2.3 From ce32aae80c5c00ec33a86528a93809c66f819c5c Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Wed, 29 Apr 2015 20:07:38 +0200 Subject: OSX: fix T44533, system_bookmarks not showing utf standard ( umlauts etc. ) --- source/blender/editors/space_file/fsmenu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index c6ee6875403..fdf7b458865 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -565,7 +565,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle); - if (pathString == NULL || !CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingASCII)) + if (pathString == NULL || !CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingUTF8)) continue; /* Exclude "all my files" as it makes no sense in blender fileselector */ -- cgit v1.2.3 From 3de45ee7fe451ab4267b824a569a2173660d2575 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Apr 2015 23:44:57 +0500 Subject: Fix T44132: Crash after open EXR format Was own mistake on adding Alpha socket for Combined pass. --- source/blender/compositor/nodes/COM_ImageNode.cpp | 73 ++++++++++------------ .../nodes/composite/nodes/node_composite_image.c | 2 +- 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp index fdd75033aea..572e63a2ced 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cpp +++ b/source/blender/compositor/nodes/COM_ImageNode.cpp @@ -79,7 +79,6 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo int numberOfOutputs = this->getNumberOfOutputSockets(); bool outputStraightAlpha = (editorNode->custom1 & CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT) != 0; BKE_image_user_frame_calc(imageuser, context.getFramenumber(), 0); - NodeOperation *combined_operation = NULL; /* force a load, we assume iuser index will be set OK anyway */ if (image && image->type == IMA_TYPE_MULTILAYER) { bool is_multilayer_ok = false; @@ -124,44 +123,40 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo } } - if (STREQ(bnodeSocket->identifier, "Alpha")) { - BLI_assert(combined_operation != NULL); - NodeOutput *outputSocket = this->getOutputSocket(index); - SeparateChannelOperation *separate_operation; - separate_operation = new SeparateChannelOperation(); - separate_operation->setChannel(3); - converter.addOperation(separate_operation); - converter.addLink(combined_operation->getOutputSocket(), separate_operation->getInputSocket(0)); - converter.mapOutputSocket(outputSocket, separate_operation->getOutputSocket()); - operation = separate_operation; - } - else { - if (rpass) { - switch (rpass->channels) { - case 1: - operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, - rpass->passtype, view, COM_DT_VALUE); - break; - /* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */ - /* XXX any way to detect actual vector images? */ - case 3: - operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, - rpass->passtype, view, COM_DT_VECTOR); - break; - case 4: - operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, - rpass->passtype, view, COM_DT_COLOR); - break; - default: - /* dummy operation is added below */ - break; - } - if (index == 0 && operation) { - converter.addPreview(operation->getOutputSocket()); - } - if (STREQ(rpass->chan_id, "RGBA")) { - combined_operation = operation; - } + if (rpass) { + switch (rpass->channels) { + case 1: + operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, + rpass->passtype, view, COM_DT_VALUE); + break; + /* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */ + /* XXX any way to detect actual vector images? */ + case 3: + operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, + rpass->passtype, view, COM_DT_VECTOR); + break; + case 4: + operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, + rpass->passtype, view, COM_DT_COLOR); + break; + default: + /* dummy operation is added below */ + break; + } + if (index == 0 && operation) { + converter.addPreview(operation->getOutputSocket()); + } + if (rpass->passtype == SCE_PASS_COMBINED) { + BLI_assert(operation != NULL); + BLI_assert(index < numberOfOutputs - 1); + NodeOutput *outputSocket = this->getOutputSocket(index + 1); + SeparateChannelOperation *separate_operation; + separate_operation = new SeparateChannelOperation(); + separate_operation->setChannel(3); + converter.addOperation(separate_operation); + converter.addLink(operation->getOutputSocket(), separate_operation->getInputSocket(0)); + converter.mapOutputSocket(outputSocket, separate_operation->getOutputSocket()); + index++; } } diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 23d47065f59..19e93447608 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -190,7 +190,7 @@ static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, sockdata->pass_index = index; sockdata->pass_flag = rpass->passtype; - if (STREQ(rpass->chan_id, "RGBA")) { + if (rpass->passtype == SCE_PASS_COMBINED) { sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, SOCK_FLOAT, PROP_NONE, "Alpha", "Alpha"); sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); sock->storage = sockdata; -- cgit v1.2.3 From 054aa61f3c9af0997cbb0ecf89f73227723a24cd Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 29 Apr 2015 21:25:34 +0200 Subject: File browser - change thumbnails size with a slider We can now scale from 32px up to 256px (default has been upgraded to 128px). Thumbnails are now generated as 'large', i.e. 256px. Previews are scaled up if necessary, unlike icons (for folders or files without preview images). Note that .blend thumbnails themselves remain in 128px for now (they are embeded in .blend files, not quite sure we want to make them four times bigger...). Patch by DMS (Yaron Dames), with final edits by myself. Reviewers: mont29 Subscribers: Severin, mont29 Differential Revision: https://developer.blender.org/D1260 --- release/scripts/startup/bl_ui/space_filebrowser.py | 4 ++++ source/blender/blenloader/intern/versioning_270.c | 24 ++++++++++++++++++++++ source/blender/editors/space_file/file_draw.c | 16 +++++++++------ source/blender/editors/space_file/filelist.c | 2 +- source/blender/editors/space_file/filesel.c | 6 ++++-- source/blender/imbuf/intern/thumbs.c | 5 +++++ source/blender/makesdna/DNA_space_types.h | 1 + source/blender/makesrna/intern/rna_space.c | 6 ++++++ 8 files changed, 55 insertions(+), 9 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py index 8acf8cfaef3..5da660fcb5f 100644 --- a/release/scripts/startup/bl_ui/space_filebrowser.py +++ b/release/scripts/startup/bl_ui/space_filebrowser.py @@ -53,6 +53,10 @@ class FILEBROWSER_HT_header(Header): # can be None when save/reload with a file selector open if params: layout.prop(params, "display_type", expand=True, text="") + + if params.display_type == 'FILE_IMGDISPLAY': + layout.prop(params, "thumbnails_size") + layout.prop(params, "sort_method", expand=True, text="") layout.prop(params, "show_hidden", text="", icon='FILE_HIDDEN') diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index c8862870b92..2343ba06e75 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -799,4 +799,28 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } + + if (!MAIN_VERSION_ATLEAST(main, 274, 6)) { + bScreen *screen; + + if (!DNA_struct_elem_find(fd->filesdna, "FileSelectParams", "int", "thumbnails_size")) { + for (screen = main->screen.first; screen; screen = screen->id.next) { + ScrArea *sa; + + for (sa = screen->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; + + for (sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_FILE) { + SpaceFile *sfile = (SpaceFile *)sl; + + if (sfile->params) { + sfile->params->thumbnails_size = 128; + } + } + } + } + } + } + } } diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 9763efbc7b5..d5b9c169192 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -329,6 +329,7 @@ static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int float fx, fy; float dx, dy; int xco, yco; + float ui_imbx, ui_imby; float scaledx, scaledy; float scale; int ex, ey; @@ -336,23 +337,26 @@ static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int BLI_assert(imb != NULL); - if ((imb->x * UI_DPI_FAC > layout->prv_w) || - (imb->y * UI_DPI_FAC > layout->prv_h)) + ui_imbx = imb->x * UI_DPI_FAC; + ui_imby = imb->y * UI_DPI_FAC; + /* Unlike thumbnails, icons are not scaled up. */ + if (((ui_imbx > layout->prv_w) || (ui_imby > layout->prv_h)) || + (!is_icon && ((ui_imbx < layout->prv_w) || (ui_imby < layout->prv_h)))) { if (imb->x > imb->y) { scaledx = (float)layout->prv_w; - scaledy = ( (float)imb->y / (float)imb->x) * layout->prv_w; + scaledy = ((float)imb->y / (float)imb->x) * layout->prv_w; scale = scaledx / imb->x; } else { scaledy = (float)layout->prv_h; - scaledx = ( (float)imb->x / (float)imb->y) * layout->prv_h; + scaledx = ((float)imb->x / (float)imb->y) * layout->prv_h; scale = scaledy / imb->y; } } else { - scaledx = (float)imb->x * UI_DPI_FAC; - scaledy = (float)imb->y * UI_DPI_FAC; + scaledx = ui_imbx; + scaledy = ui_imby; scale = UI_DPI_FAC; } diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 87e6183f4f8..2853ee9c053 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -1349,7 +1349,7 @@ static void thumbnails_startjob(void *tjv, short *stop, short *do_update, float else if (limg->flags & FILE_TYPE_FTFONT) { source = THB_SOURCE_FONT; } - limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, source); + limg->img = IMB_thumb_manage(limg->path, THB_LARGE, source); *do_update = true; PIL_sleep_ms(10); limg = limg->next; diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 6858f536e92..d89e55cb55f 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -102,6 +102,8 @@ short ED_fileselect_set_params(SpaceFile *sfile) /* set path to most recently opened .blend */ BLI_split_dirfile(G.main->name, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file)); sfile->params->filter_glob[0] = '\0'; + /* set the default thumbnails size */ + sfile->params->thumbnails_size = 128; } params = sfile->params; @@ -527,8 +529,8 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar) layout->textheight = textheight; if (params->display == FILE_IMGDISPLAY) { - layout->prv_w = 4.8f * UI_UNIT_X; - layout->prv_h = 4.8f * UI_UNIT_Y; + layout->prv_w = ((float)params->thumbnails_size / 20.0f) * UI_UNIT_X; + layout->prv_h = ((float)params->thumbnails_size / 20.0f) * UI_UNIT_Y; layout->tile_border_x = 0.3f * UI_UNIT_X; layout->tile_border_y = 0.3f * UI_UNIT_X; layout->prv_border_x = 0.3f * UI_UNIT_X; diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 2318553eecc..a608aa0db34 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -283,9 +283,14 @@ static bool thumbpath_from_uri(const char *uri, char *path, const int path_len, void IMB_thumb_makedirs(void) { char tpath[FILE_MAX]; +#if 0 /* UNUSED */ if (get_thumb_dir(tpath, THB_NORMAL)) { BLI_dir_create_recursive(tpath); } +#endif + if (get_thumb_dir(tpath, THB_LARGE)) { + BLI_dir_create_recursive(tpath); + } if (get_thumb_dir(tpath, THB_FAIL)) { BLI_dir_create_recursive(tpath); } diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 09651bdbf3a..78121035371 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -590,6 +590,7 @@ typedef struct FileSelectParams { int active_file; int sel_first; int sel_last; + int thumbnails_size; /* short */ short type; /* XXXXX for now store type here, should be moved to the operator */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index fd03840b145..eade210f90d 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -3788,6 +3788,12 @@ static void rna_def_fileselect_params(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Name Filter", "Filter by name, supports '*' wildcard"); RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL); + + prop = RNA_def_property(srna, "thumbnails_size", PROP_INT, PROP_PIXEL); + RNA_def_property_int_sdna(prop, NULL, "thumbnails_size"); + RNA_def_property_range(prop, 32, 256); + RNA_def_property_ui_text(prop, "Thumbnails Size", "Change the size of the thumbnails"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } static void rna_def_filemenu_entry(BlenderRNA *brna) -- cgit v1.2.3 From 3856d439db2d4c4f39ed5a06f185ff3d27e126a9 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Wed, 29 Apr 2015 16:35:19 -0300 Subject: Fix filename has "new render view" suffix reported by Jason van Gumster (Fweeb) Bug introduced in f8540d7fd5a47bc9d1d676d5aaaa0de379c71637 --- source/blender/render/intern/source/render_result.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 2baf445466c..4b5c6e54406 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -936,7 +936,7 @@ void render_result_views_new(RenderResult *rr, RenderData *rd) /* we always need at least one view */ if (BLI_listbase_count_ex(&rr->views, 1) == 0) { - render_result_view_new(rr, "new render view"); + render_result_view_new(rr, ""); } } -- cgit v1.2.3 From e5f3193df30edbdcbc7111c1e3b9ccf7aa6ddfe2 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 30 Apr 2015 01:07:38 +0500 Subject: Cycles: Fix wrong order in object flags calculations Object flags are depending on bounding box which is only available after mesh synchronization. This was broken since 7fd4c44 which happened quite close to the release and oddly enough was not sopped by anyone. Render test is coming for this. Was spotted by Thomas Dinges while working on another patch. --- intern/cycles/render/scene.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 71741c0dfd1..19d715d834b 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -180,13 +180,13 @@ void Scene::device_update(Device *device_, Progress& progress) if(progress.get_cancel() || device->have_error()) return; - progress.set_status("Updating Objects Flags"); - object_manager->device_update_flags(device, &dscene, this, progress); + progress.set_status("Updating Meshes"); + mesh_manager->device_update(device, &dscene, this, progress); if(progress.get_cancel() || device->have_error()) return; - progress.set_status("Updating Meshes"); - mesh_manager->device_update(device, &dscene, this, progress); + progress.set_status("Updating Objects Flags"); + object_manager->device_update_flags(device, &dscene, this, progress); if(progress.get_cancel() || device->have_error()) return; -- cgit v1.2.3 From 7aab5c6ca99c04447dc57645d781e9e445be8616 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 30 Apr 2015 01:20:17 +0500 Subject: Cycles: Fix wrong termination criteria in SSS volume stack update Another issue spotted with Thomas. --- intern/cycles/kernel/kernel_volume.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index 3d3d871a702..32c7e4eef09 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -1107,8 +1107,8 @@ ccl_device void kernel_volume_stack_update_for_subsurface(KernelGlobals *kg, Ray volume_ray = *ray; Intersection isect; int step = 0; - while(step < VOLUME_STACK_SIZE && - scene_intersect_volume(kg, &volume_ray, &isect)) + while(step < 2 * VOLUME_STACK_SIZE && + scene_intersect_volume(kg, &volume_ray, &isect)) { ShaderData sd; shader_setup_from_ray(kg, &sd, &isect, &volume_ray, 0, 0); -- cgit v1.2.3 From 67fcb04bbfbaccbcae73846613862f3a9d63e3d6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 30 Apr 2015 01:45:20 +1000 Subject: BMesh: minor change to swap-vert api - assert if the verts not in the edge (all callers assume success) - rename to bmesh_disk_vert_swap - swap src/dst arg order. --- source/blender/bmesh/intern/bmesh_core.c | 8 ++++---- source/blender/bmesh/intern/bmesh_structure.c | 16 ++++++++-------- source/blender/bmesh/intern/bmesh_structure.h | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 3266ee0394d..c92acfd039e 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1512,7 +1512,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) bmesh_disk_edge_remove(e, tv); /* swap out tv for v_new in e */ - bmesh_edge_swapverts(e, tv, v_new); + bmesh_disk_vert_swap(e, v_new, tv); /* add e to v_new's disk cycle */ bmesh_disk_edge_append(e, v_new); @@ -1729,7 +1729,7 @@ BMEdge *bmesh_jekv( /* remove e_old from v_kill's disk cycle */ bmesh_disk_edge_remove(e_old, v_kill); /* relink e_old->v_kill to be e_old->tv */ - bmesh_edge_swapverts(e_old, v_kill, tv); + bmesh_disk_vert_swap(e_old, tv, v_kill); /* append e_old to tv's disk cycle */ bmesh_disk_edge_append(e_old, tv); /* remove e_kill from tv's disk cycle */ @@ -2066,7 +2066,7 @@ bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) /* disk */ bmesh_disk_edge_remove(e, v); - bmesh_edge_swapverts(e, v, v_target); + bmesh_disk_vert_swap(e, v_target, v); bmesh_disk_edge_append(e, v_target); BLI_assert(e->v1 != e->v2); } @@ -2188,7 +2188,7 @@ void bmesh_vert_separate( /* swap out edges */ BLI_assert(e->v1 == v || e->v2 == v); bmesh_disk_edge_remove(e, v); - bmesh_edge_swapverts(e, v, v_new); + bmesh_disk_vert_swap(e, v_new, v); bmesh_disk_edge_append(e, v_new); } diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c index 5d2eed8c753..3b1dd7e96be 100644 --- a/source/blender/bmesh/intern/bmesh_structure.c +++ b/source/blender/bmesh/intern/bmesh_structure.c @@ -40,19 +40,19 @@ * MISC utility functions. */ -bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new) +void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) { - if (e->v1 == v_orig) { - e->v1 = v_new; + if (e->v1 == v_src) { + e->v1 = v_dst; e->v1_disk_link.next = e->v1_disk_link.prev = NULL; - return true; } - else if (e->v2 == v_orig) { - e->v2 = v_new; + else if (e->v2 == v_src) { + e->v2 = v_dst; e->v2_disk_link.next = e->v2_disk_link.prev = NULL; - return true; } - return false; + else { + BLI_assert(0); + } } /** diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h index 4a6247d7165..b5ffd9eb67a 100644 --- a/source/blender/bmesh/intern/bmesh_structure.h +++ b/source/blender/bmesh/intern/bmesh_structure.h @@ -70,7 +70,7 @@ BMLoop *bmesh_radial_faceloop_find_vert(const BMFace *f, const BMVert *v) ATTR_W bool bmesh_radial_validate(int radlen, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); /* EDGE UTILITIES */ -bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new) ATTR_NONNULL(); +void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL(); BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -- cgit v1.2.3 From 26541b7488be08ce998960e5edbbe0dcee2698c3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 30 Apr 2015 02:25:32 +1000 Subject: BMesh: refactor edge-vert swapping into API call --- source/blender/bmesh/intern/bmesh_core.c | 37 ++------------------------- source/blender/bmesh/intern/bmesh_structure.c | 26 +++++++++++++++++++ source/blender/bmesh/intern/bmesh_structure.h | 1 + 3 files changed, 29 insertions(+), 35 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index c92acfd039e..76b54a45a6b 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -2050,24 +2050,7 @@ bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) /* move all the edges from v's disk to vtarget's disk */ while ((e = v->e)) { - - /* loop */ - BMLoop *l_first; - if ((l_first = e->l)) { - BMLoop *l_iter = l_first; - do { - if (l_iter->v == v) { - l_iter->v = v_target; - } - /* else if (l_iter->prev->v == v) {...} - * (this case will be handled by a different edge) */ - } while ((l_iter = l_iter->radial_next) != l_first); - } - - /* disk */ - bmesh_disk_edge_remove(e, v); - bmesh_disk_vert_swap(e, v_target, v); - bmesh_disk_edge_append(e, v_target); + bmesh_edge_vert_swap(e, v_target, v); BLI_assert(e->v1 != e->v2); } @@ -2173,23 +2156,7 @@ void bmesh_vert_separate( } while ((e = BLI_SMALLSTACK_POP(edges))) { - - /* swap out loops */ - if (e->l) { - BMLoop *l_iter, *l_first; - l_iter = l_first = e->l; - do { - if (l_iter->v == v) { - l_iter->v = v_new; - } - } while ((l_iter = l_iter->radial_next) != l_first); - } - - /* swap out edges */ - BLI_assert(e->v1 == v || e->v2 == v); - bmesh_disk_edge_remove(e, v); - bmesh_disk_vert_swap(e, v_new, v); - bmesh_disk_edge_append(e, v_new); + bmesh_edge_vert_swap(e, v_new, v); } if (r_vout) { diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c index 3b1dd7e96be..30ab693beb7 100644 --- a/source/blender/bmesh/intern/bmesh_structure.c +++ b/source/blender/bmesh/intern/bmesh_structure.c @@ -55,6 +55,32 @@ void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) } } +/** + * Handles all connected data, use with care. + * + * Assumes caller has setup correct state before the swap is done. + */ +void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) +{ + /* swap out loops */ + if (e->l) { + BMLoop *l_iter, *l_first; + l_iter = l_first = e->l; + do { + if (l_iter->v == v_src) { + l_iter->v = v_dst; + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + + /* swap out edges */ + BLI_assert(e->v1 == v_src || e->v2 == v_src); + bmesh_disk_edge_remove(e, v_src); + bmesh_disk_vert_swap(e, v_dst, v_src); + bmesh_disk_edge_append(e, v_dst); + BLI_assert(e->v1 != e->v2); +} + /** * \section bm_cycles BMesh Cycles * (this is somewhat outdate, though bits of its API are still used) - joeedh diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h index b5ffd9eb67a..9d9fb7f2c68 100644 --- a/source/blender/bmesh/intern/bmesh_structure.h +++ b/source/blender/bmesh/intern/bmesh_structure.h @@ -71,6 +71,7 @@ bool bmesh_radial_validate(int radlen, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATT /* EDGE UTILITIES */ void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL(); +void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL(); BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -- cgit v1.2.3 From 53662bcaf1c158a083faf48b1748787a9b2e6909 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 30 Apr 2015 02:37:21 +1000 Subject: BMesh: simplify/optimize loop splitting logic To split off a single loop, was splitting all fans off the vertex, then merging back together (except for one). Now simply splits off one loop. --- source/blender/bmesh/intern/bmesh_core.c | 57 ++++++++++---------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 76b54a45a6b..abeecf596ba 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -2303,11 +2303,11 @@ void bmesh_edge_separate( */ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep) { - BMVert **vtar; - int len, i; BMVert *v_new = NULL; BMVert *v_sep = l_sep->v; BMEdge *e_iter; + BMEdge *edges[2]; + int i; /* peel the face from the edge radials on both sides of the * loop vert, disconnecting the face from its fan */ @@ -2335,49 +2335,26 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep) } } - /* Update the disk start, so that v->e points to an edge touching the split loop. - * This is so that BM_vert_split will leave the original v_sep on some *other* fan - * (not the one-face fan that holds the unglue face). */ - v_sep->e = e_iter; - - /* Split all fans connected to the vert, duplicating it for - * each fans. */ - bmesh_vert_separate(bm, v_sep, &vtar, &len, false); + v_sep->e = l_sep->e; - /* There should have been at least two fans cut apart here, - * otherwise the early exit would have kicked in. */ - BLI_assert(len >= 2); + v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP); - v_new = l_sep->v; + edges[0] = l_sep->e; + edges[1] = l_sep->prev->e; - /* Desired result here is that a new vert should always be - * created for the unglue face. This is so we can glue any - * extras back into the original vert. */ - BLI_assert(v_new != v_sep); - BLI_assert(v_sep == vtar[0]); - - /* If there are more than two verts as a result, glue together - * all the verts except the one this URMV intended to create */ - if (len > 2) { - for (i = 0; i < len; i++) { - if (vtar[i] == v_new) { - break; - } - } - - if (i != len) { - /* Swap the single vert that was needed for the - * unglue into the last array slot */ - SWAP(BMVert *, vtar[i], vtar[len - 1]); - - /* And then glue the rest back together */ - for (i = 1; i < len - 1; i++) { - BM_vert_splice(bm, vtar[i], vtar[0]); - } - } + for (i = 0; i < ARRAY_SIZE(edges); i++) { + BMEdge *e = edges[i]; + bmesh_edge_vert_swap(e, v_new, v_sep); } - MEM_freeN(vtar); + BLI_assert(v_sep != l_sep->v); + BLI_assert(v_sep->e != l_sep->v->e); + + BM_CHECK_ELEMENT(l_sep); + BM_CHECK_ELEMENT(v_sep); + BM_CHECK_ELEMENT(edges[0]); + BM_CHECK_ELEMENT(edges[1]); + BM_CHECK_ELEMENT(v_new); return v_new; } -- cgit v1.2.3 From 3ef27ec807bc89eed5b3a10ae9041c607ff4eacb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 30 Apr 2015 05:52:48 +1000 Subject: BMesh: add BM_face_loop_separate_multi New utility function to handle splitting off multiple loops from a face at once. --- source/blender/bmesh/intern/bmesh_core.c | 145 +++++++++++++++++++++++++++++++ source/blender/bmesh/intern/bmesh_core.h | 2 + source/blender/bmesh/intern/bmesh_mods.c | 6 ++ source/blender/bmesh/intern/bmesh_mods.h | 2 + 4 files changed, 155 insertions(+) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index abeecf596ba..81cc9727965 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -2359,6 +2359,151 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep) return v_new; } +/** + * A version of #bmesh_urmv_loop that disconnects multiple loops at once. + * + * Handles the task of finding fans boundaris. + */ +BMVert *bmesh_urmv_loop_multi( + BMesh *bm, BMLoop **larr, int larr_len) +{ + BMVert *v_sep = larr[0]->v; + BMVert *v_new; + int i; + bool is_mixed_any = false; + + BLI_SMALLSTACK_DECLARE(edges, BMEdge *); + +#define LOOP_VISIT _FLAG_WALK +#define EDGE_VISIT _FLAG_WALK + + for (i = 0; i < larr_len; i++) { + BMLoop *l_sep = larr[i]; + + /* all must be from the same vert! */ + BLI_assert(v_sep == l_sep->v); + + BLI_assert(!BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT)); + BM_ELEM_API_FLAG_ENABLE(l_sep, LOOP_VISIT); + + /* weak! but it makes it simpler to check for edges to split + * while doing a radial loop (where loops may be adjacent) */ + BM_ELEM_API_FLAG_ENABLE(l_sep->next, LOOP_VISIT); + BM_ELEM_API_FLAG_ENABLE(l_sep->prev, LOOP_VISIT); + } + + for (i = 0; i < larr_len; i++) { + BMLoop *l_sep = larr[i]; + + BMLoop *loop_pair[2] = {l_sep, l_sep->prev}; + int j; + for (j = 0; j < ARRAY_SIZE(loop_pair); j++) { + BMEdge *e = loop_pair[j]->e; + if (!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)) { + BMLoop *l_iter, *l_first; + bool is_mixed = false; + + BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT); + + l_iter = l_first = e->l; + do { + if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) { + is_mixed = true; + is_mixed_any = true; + break; + } + } while ((l_iter = l_iter->radial_next) != l_first); + + if (is_mixed) { + /* ensure the first loop is one we don't own so we can do a quick check below + * on the edge's loop-flag to see if the edge is mixed or not. */ + e->l = l_iter; + } + BLI_SMALLSTACK_PUSH(edges, e); + } + } + } + + if (is_mixed_any == false) { + /* all loops in 'larr' are the soul owners of their edges. + * nothing to split away from, this is a no-op */ + v_new = v_sep; + } + else { + BMEdge *e; + + BLI_assert(!BLI_SMALLSTACK_IS_EMPTY(edges)); + + v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP); + while ((e = BLI_SMALLSTACK_POP(edges))) { + BMLoop *l_iter, *l_first, *l_next; + BMEdge *e_new; + + /* disable so copied edge isn't left dirty (loop edges are cleared last too) */ + BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT); + + if (!BM_ELEM_API_FLAG_TEST(e->l, LOOP_VISIT)) { + /* edge has some loops owned by us, some owned by other loops */ + BMVert *e_new_v_pair[2]; + + if (e->v1 == v_sep) { + e_new_v_pair[0] = v_new; + e_new_v_pair[1] = e->v2; + } + else { + BLI_assert(v_sep == e->v2); + e_new_v_pair[0] = e->v1; + e_new_v_pair[1] = v_new; + } + + e_new = BM_edge_create(bm, UNPACK2(e_new_v_pair), e, BM_CREATE_NOP); + + /* now moved all loops from 'larr' to this newly created edge */ + l_iter = l_first = e->l; + do { + l_next = l_iter->radial_next; + if (BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) { + bmesh_radial_loop_remove(l_iter, e); + bmesh_radial_append(e_new, l_iter); + l_iter->e = e_new; + } + } while ((l_iter = l_next) != l_first); + } + else { + /* we own the edge entirely, replace the vert */ + bmesh_disk_edge_remove(e, v_sep); + bmesh_disk_vert_swap(e, v_new, v_sep); + bmesh_disk_edge_append(e, v_new); + } + + /* loop vert is handled last! */ + } + } + + for (i = 0; i < larr_len; i++) { + BMLoop *l_sep = larr[i]; + + l_sep->v = v_new; + + BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT)); + BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->prev, LOOP_VISIT)); + BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->next, LOOP_VISIT)); + BM_ELEM_API_FLAG_DISABLE(l_sep, LOOP_VISIT); + BM_ELEM_API_FLAG_DISABLE(l_sep->prev, LOOP_VISIT); + BM_ELEM_API_FLAG_DISABLE(l_sep->next, LOOP_VISIT); + + + BM_ELEM_API_FLAG_DISABLE(l_sep->prev->e, EDGE_VISIT); + BM_ELEM_API_FLAG_DISABLE(l_sep->e, EDGE_VISIT); + } + +#undef LOOP_VISIT +#undef EDGE_VISIT + + return v_new; +} + + /** * \brief Unglue Region Make Vert (URMV) * diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index 55bc6a62a88..85dd1de0ef5 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -99,6 +99,8 @@ BMEdge *bmesh_jekv( BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e); BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep); BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep); +BMVert *bmesh_urmv_loop_multi( + BMesh *bm, BMLoop **larr, int larr_len); void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b); diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index ab6d21de7e8..5891876c22c 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -1650,3 +1650,9 @@ BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *sl) { return bmesh_urmv_loop(bm, sl); } + +BMVert *BM_face_loop_separate_multi( + BMesh *bm, BMLoop **larr, int larr_len) +{ + return bmesh_urmv_loop_multi(bm, larr, larr_len); +} diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h index 2ef836a14a5..1b826b1e0b2 100644 --- a/source/blender/bmesh/intern/bmesh_mods.h +++ b/source/blender/bmesh/intern/bmesh_mods.h @@ -89,5 +89,7 @@ enum { BMVert *BM_face_vert_separate(BMesh *bm, BMFace *sf, BMVert *sv); BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *sl); +BMVert *BM_face_loop_separate_multi( + BMesh *bm, BMLoop **larr, int larr_len); #endif /* __BMESH_MODS_H__ */ -- cgit v1.2.3 From 99811c283efaa8f5bc13b81bb5cc42761c42a8a0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 30 Apr 2015 06:23:01 +1000 Subject: BMesh: use BM_face_loop_separate_multi for rip Resolves bug over-splitting non-manifold connected edges. --- source/blender/editors/mesh/editmesh_rip.c | 74 +++++++++++++++--------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 45e16ceff7b..f5d22eac641 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -734,20 +734,42 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve /* unlike edge split, for single vertex split we only use the operator in one of the cases * but both allocate fill */ - /* rip two adjacent edges */ - if (BM_edge_is_boundary(e2) || BM_vert_face_count_is_equal(v, 2)) { - /* Don't run the edge split operator in this case */ + { BMVert *v_rip; + BMLoop *larr[2]; + int larr_len = 0; + + /* rip two adjacent edges */ + if (BM_edge_is_boundary(e2) || BM_vert_face_count_is_equal(v, 2)) { + /* Don't run the edge split operator in this case */ - l = BM_edge_vert_share_loop(e2->l, v); + l = BM_edge_vert_share_loop(e2->l, v); + larr[larr_len] = l; + larr_len++; - /* only tag for face-fill (we don't call the operator) */ - if (BM_edge_is_boundary(e2)) { - BM_elem_flag_enable(e2, BM_ELEM_TAG); + /* only tag for face-fill (we don't call the operator) */ + if (BM_edge_is_boundary(e2)) { + BM_elem_flag_enable(e2, BM_ELEM_TAG); + } + else { + BM_elem_flag_enable(l->e, BM_ELEM_TAG); + BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG); + } } else { - BM_elem_flag_enable(l->e, BM_ELEM_TAG); - BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG); + if (BM_edge_is_manifold(e2)) { + BMLoop *l_iter, *l_first; + + l_iter = l_first = e2->l; + do { + larr[larr_len] = BM_edge_vert_share_loop(l_iter, v); + BM_elem_flag_enable(larr[larr_len]->e, BM_ELEM_TAG); + larr_len++; + } while ((l_iter = l_iter->radial_next) != l_first); + } + else { + /* looks like there are no split edges, we could just return/report-error? - Campbell */ + } } /* keep directly before edgesplit */ @@ -755,13 +777,12 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm); } -#if 0 - v_rip = BM_face_vert_separate(bm, l->f, v); -#else - v_rip = BM_face_loop_separate(bm, l); -#endif - - BLI_assert(v_rip); + if (larr_len) { + v_rip = BM_face_loop_separate_multi(bm, larr, larr_len); + } + else { + v_rip = NULL; + } if (v_rip) { BM_vert_select_set(bm, v_rip, true); @@ -771,27 +792,6 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve return OPERATOR_CANCELLED; } } - else { - if (BM_edge_is_manifold(e2)) { - l = e2->l; - e = BM_loop_other_edge_loop(l, v)->e; - BM_elem_flag_enable(e, BM_ELEM_TAG); - - l = e2->l->radial_next; - e = BM_loop_other_edge_loop(l, v)->e; - BM_elem_flag_enable(e, BM_ELEM_TAG); - } - else { - /* looks like there are no split edges, we could just return/report-error? - Campbell */ - } - - /* keep directly before edgesplit */ - if (do_fill) { - fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm); - } - - BM_mesh_edgesplit(em->bm, true, true, true); - } { /* --- select which vert --- */ -- cgit v1.2.3 From e9dcb068c749bc9e73450a4feb491551ede58c07 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 30 Apr 2015 07:22:18 +1000 Subject: Fix T44484: Edge-split corrupts mesh Splitting non-manifold edges could produce duplicate edges. --- source/blender/bmesh/operators/bmo_split_edges.c | 2 +- source/blender/bmesh/tools/bmesh_edgesplit.c | 43 ++++++++++++++++++++++-- source/blender/bmesh/tools/bmesh_edgesplit.h | 5 ++- source/blender/bmesh/tools/bmesh_intersect.c | 2 +- source/blender/editors/mesh/editmesh_rip.c | 2 +- source/blender/modifiers/intern/MOD_edgesplit.c | 2 +- 6 files changed, 48 insertions(+), 8 deletions(-) diff --git a/source/blender/bmesh/operators/bmo_split_edges.c b/source/blender/bmesh/operators/bmo_split_edges.c index eb7946caff0..ca2088339cf 100644 --- a/source/blender/bmesh/operators/bmo_split_edges.c +++ b/source/blender/bmesh/operators/bmo_split_edges.c @@ -48,7 +48,7 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) } /* this is where everything happens */ - BM_mesh_edgesplit(bm, use_verts, true, false); + BM_mesh_edgesplit(bm, use_verts, true, true, false); BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_INTERNAL_TAG); } diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c index c01b4880d7a..30ba07c2d8f 100644 --- a/source/blender/bmesh/tools/bmesh_edgesplit.c +++ b/source/blender/bmesh/tools/bmesh_edgesplit.c @@ -42,7 +42,7 @@ * un-tag edges not connected to other tagged edges, * unless they are on a boundary */ -static void bm_edgesplit_validate_seams(BMesh *bm) +static void bm_edgesplit_validate_seams(BMesh *bm, const bool use_non_manifold) { BMIter iter; BMEdge *e; @@ -72,6 +72,11 @@ static void bm_edgesplit_validate_seams(BMesh *bm) * the edge its self can't be split */ BM_elem_flag_disable(e, BM_ELEM_TAG); } + else if ((use_non_manifold == false) && + (BM_edge_is_manifold(e) == false)) + { + BM_elem_flag_disable(e, BM_ELEM_TAG); + } } /* single marked edges unconnected to any other marked edges @@ -98,7 +103,16 @@ static void bm_edgesplit_validate_seams(BMesh *bm) MEM_freeN(vtouch); } -void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, const bool copy_select) +/** + * \param use_verts Use flagged verts instead of edges. + * \param use_non_manifold Split non-manifold edges (a little slower, must check for doubles). + * \param tag_only Only split tagged edges. + * \param copy_select Copy selection history. + */ +void BM_mesh_edgesplit( + BMesh *bm, + const bool use_verts, const bool use_non_manifold, + const bool tag_only, const bool copy_select) { BMIter iter; BMEdge *e; @@ -142,7 +156,7 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con } } - bm_edgesplit_validate_seams(bm); + bm_edgesplit_validate_seams(bm, use_non_manifold); BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_TAG)) { @@ -204,6 +218,29 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con } } + if (use_non_manifold) { + /* if we split non-manifold, double edge may remain */ + BMEdge *e_next; + BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + BMEdge *e_other; + if ((e_other = BM_edge_find_double(e))) { + BM_edge_splice(bm, e, e_other); + } + } + } + } + else { +#ifndef NDEBUG + /* ensure we don't have any double edges! */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + BLI_assert(BM_edge_find_double(e) == NULL); + } + } +#endif + } + if (use_ese) { BLI_ghash_free(ese_gh, NULL, NULL); } diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.h b/source/blender/bmesh/tools/bmesh_edgesplit.h index bd66f6a9e2f..531af964a99 100644 --- a/source/blender/bmesh/tools/bmesh_edgesplit.h +++ b/source/blender/bmesh/tools/bmesh_edgesplit.h @@ -27,6 +27,9 @@ * \ingroup bmesh */ -void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, const bool copy_select); +void BM_mesh_edgesplit( + BMesh *bm, + const bool use_verts, const bool use_non_manifold, + const bool tag_only, const bool copy_select); #endif /* __BMESH_EDGESPLIT_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c index ceb6ded5a43..76a289feaaa 100644 --- a/source/blender/bmesh/tools/bmesh_intersect.c +++ b/source/blender/bmesh/tools/bmesh_intersect.c @@ -1283,7 +1283,7 @@ bool BM_mesh_intersect( BM_elem_flag_enable(e, BM_ELEM_TAG); } - BM_mesh_edgesplit(bm, false, true, false); + BM_mesh_edgesplit(bm, false, false, true, false); } #else (void)use_separate; diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index f5d22eac641..7bd072ac6cb 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -941,7 +941,7 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, const wmEvent *eve fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm); } - BM_mesh_edgesplit(em->bm, true, true, true); + BM_mesh_edgesplit(em->bm, true, true, true, true); /* note: the output of the bmesh operator is ignored, since we built * the contiguous loop pairs to split already, its possible that some diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index fa29921b325..2e6360c3ded 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -91,7 +91,7 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd) } } - BM_mesh_edgesplit(bm, false, true, false); + BM_mesh_edgesplit(bm, false, false, true, false); /* BM_mesh_validate(bm); */ /* for troubleshooting */ -- cgit v1.2.3 From b3def11f5b751ead0bc8bcf100ff4ab3f2b10981 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Wed, 29 Apr 2015 23:21:05 +0200 Subject: Cycles: Record all possible volume intersections for SSS and camera checks This replaces sequential ray moving followed with scene intersection with single BVH traversal, which gives us all possible intersections. Only implemented for CPU, due to qsort and a bigger memory usage on GPU which we rather avoid. GPU still uses the regular bvh volume intersection code, while CPU now uses the new code. This improves render performance for scenes with: a) Camera inside volume mesh b) SSS mesh intersecting a volume mesh/domain In simple volume files (not much geometry) performance is roughly the same (slightly faster). In files with a lot of geometry, the performance increase is larger. bmps.blend with a volume shader and camera inside the mesh, it renders ~10% faster here. Patch by Sergey and myself. Differential Revision: https://developer.blender.org/D1264 --- intern/cycles/kernel/CMakeLists.txt | 2 + intern/cycles/kernel/geom/geom_bvh.h | 76 ++++ intern/cycles/kernel/geom/geom_bvh_volume_all.h | 454 +++++++++++++++++++++++ intern/cycles/kernel/geom/geom_qbvh_volume_all.h | 446 ++++++++++++++++++++++ intern/cycles/kernel/kernel_shadow.h | 15 +- intern/cycles/kernel/kernel_types.h | 1 + intern/cycles/kernel/kernel_volume.h | 63 ++++ 7 files changed, 1043 insertions(+), 14 deletions(-) create mode 100644 intern/cycles/kernel/geom/geom_bvh_volume_all.h create mode 100644 intern/cycles/kernel/geom/geom_qbvh_volume_all.h diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index fd690234bc1..83b3450fc1c 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -119,6 +119,7 @@ set(SRC_GEOM_HEADERS geom/geom_bvh_subsurface.h geom/geom_bvh_traversal.h geom/geom_bvh_volume.h + geom/geom_bvh_volume_all.h geom/geom_curve.h geom/geom_motion_curve.h geom/geom_motion_triangle.h @@ -129,6 +130,7 @@ set(SRC_GEOM_HEADERS geom/geom_qbvh_subsurface.h geom/geom_qbvh_traversal.h geom/geom_qbvh_volume.h + geom/geom_qbvh_volume_all.h geom/geom_triangle.h geom/geom_triangle_intersect.h geom/geom_volume.h diff --git a/intern/cycles/kernel/geom/geom_bvh.h b/intern/cycles/kernel/geom/geom_bvh.h index c0eefcd9c7f..c2610c7d92c 100644 --- a/intern/cycles/kernel/geom/geom_bvh.h +++ b/intern/cycles/kernel/geom/geom_bvh.h @@ -179,6 +179,38 @@ CCL_NAMESPACE_BEGIN #include "geom_bvh_volume.h" #endif +/* Record all BVH intersection for volumes */ + +#if defined(__VOLUME_RECORD_ALL__) +#define BVH_FUNCTION_NAME bvh_intersect_volume_all +#define BVH_FUNCTION_FEATURES 0 +#include "geom_bvh_volume_all.h" +#endif + +#if defined(__VOLUME_RECORD_ALL__) && defined(__INSTANCING__) +#define BVH_FUNCTION_NAME bvh_intersect_volume_all_instancing +#define BVH_FUNCTION_FEATURES BVH_INSTANCING +#include "geom_bvh_volume_all.h" +#endif + +#if defined(__VOLUME_RECORD_ALL__) && defined(__HAIR__) +#define BVH_FUNCTION_NAME bvh_intersect_volume_all_hair +#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH +#include "geom_bvh_volume_all.h" +#endif + +#if defined(__VOLUME_RECORD_ALL__) && defined(__OBJECT_MOTION__) +#define BVH_FUNCTION_NAME bvh_intersect_volume_all_motion +#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION +#include "geom_bvh_volume_all.h" +#endif + +#if defined(__VOLUME_RECORD_ALL__) && defined(__HAIR__) && defined(__OBJECT_MOTION__) +#define BVH_FUNCTION_NAME bvh_intersect_volume_all_hair_motion +#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH|BVH_MOTION +#include "geom_bvh_volume_all.h" +#endif + #undef BVH_FEATURE #undef BVH_NAME_JOIN #undef BVH_NAME_EVAL @@ -330,6 +362,37 @@ ccl_device_intersect bool scene_intersect_volume(KernelGlobals *kg, } #endif +#ifdef __VOLUME_RECORD_ALL__ +ccl_device_intersect uint scene_intersect_volume_all(KernelGlobals *kg, + const Ray *ray, + Intersection *isect, + const uint max_hits) +{ +#ifdef __OBJECT_MOTION__ + if(kernel_data.bvh.have_motion) { +#ifdef __HAIR__ + if(kernel_data.bvh.have_curves) + return bvh_intersect_volume_all_hair_motion(kg, ray, isect, max_hits); +#endif /* __HAIR__ */ + + return bvh_intersect_volume_all_motion(kg, ray, isect, max_hits); + } +#endif /* __OBJECT_MOTION__ */ + +#ifdef __HAIR__ + if(kernel_data.bvh.have_curves) + return bvh_intersect_volume_all_hair(kg, ray, isect, max_hits); +#endif /* __HAIR__ */ + +#ifdef __INSTANCING__ + if(kernel_data.bvh.have_instancing) + return bvh_intersect_volume_all_instancing(kg, ray, isect, max_hits); +#endif /* __INSTANCING__ */ + + return bvh_intersect_volume_all(kg, ray, isect, max_hits); +} +#endif + /* Ray offset to avoid self intersection. * @@ -384,5 +447,18 @@ ccl_device_inline float3 ray_offset(float3 P, float3 Ng) #endif } +ccl_device int intersections_compare(const void *a, const void *b) +{ + const Intersection *isect_a = (const Intersection*)a; + const Intersection *isect_b = (const Intersection*)b; + + if(isect_a->t < isect_b->t) + return -1; + else if(isect_a->t > isect_b->t) + return 1; + else + return 0; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/geom/geom_bvh_volume_all.h b/intern/cycles/kernel/geom/geom_bvh_volume_all.h new file mode 100644 index 00000000000..b6db36f4b17 --- /dev/null +++ b/intern/cycles/kernel/geom/geom_bvh_volume_all.h @@ -0,0 +1,454 @@ +/* + * Adapted from code Copyright 2009-2010 NVIDIA Corporation, + * and code copyright 2009-2012 Intel Corporation + * + * Modifications Copyright 2011-2014, Blender Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef __QBVH__ +#include "geom_qbvh_volume_all.h" +#endif + +/* This is a template BVH traversal function for volumes, where + * various features can be enabled/disabled. This way we can compile optimized + * versions for each case without new features slowing things down. + * + * BVH_INSTANCING: object instancing + * BVH_HAIR: hair curve rendering + * BVH_MOTION: motion blur rendering + * + */ + +ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, + const Ray *ray, + Intersection *isect_array, + const uint max_hits) +{ + /* todo: + * - test if pushing distance on the stack helps (for non shadow rays) + * - separate version for shadow rays + * - likely and unlikely for if() statements + * - test restrict attribute for pointers + */ + + /* traversal stack in CUDA thread-local memory */ + int traversalStack[BVH_STACK_SIZE]; + traversalStack[0] = ENTRYPOINT_SENTINEL; + + /* traversal variables in registers */ + int stackPtr = 0; + int nodeAddr = kernel_data.bvh.root; + + /* ray parameters in registers */ + const float tmax = ray->t; + float3 P = ray->P; + float3 dir = bvh_clamp_direction(ray->D); + float3 idir = bvh_inverse_direction(dir); + int object = OBJECT_NONE; + float isect_t = tmax; + + const uint visibility = PATH_RAY_ALL_VISIBILITY; + +#if BVH_FEATURE(BVH_MOTION) + Transform ob_tfm; +#endif + +#if BVH_FEATURE(BVH_INSTANCING) + int num_hits_in_instance = 0; +#endif + + uint num_hits = 0; + isect_array->t = tmax; + +#if defined(__KERNEL_SSE2__) + const shuffle_swap_t shuf_identity = shuffle_swap_identity(); + const shuffle_swap_t shuf_swap = shuffle_swap_swap(); + + const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000)); + ssef Psplat[3], idirsplat[3]; + shuffle_swap_t shufflexyz[3]; + + Psplat[0] = ssef(P.x); + Psplat[1] = ssef(P.y); + Psplat[2] = ssef(P.z); + + ssef tsplat(0.0f, 0.0f, -isect_t, -isect_t); + + gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); +#endif + + IsectPrecalc isect_precalc; + triangle_intersect_precalc(dir, &isect_precalc); + + /* traversal loop */ + do { + do { + /* traverse internal nodes */ + while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) { + bool traverseChild0, traverseChild1; + int nodeAddrChild1; + +#if !defined(__KERNEL_SSE2__) + /* Intersect two child bounding boxes, non-SSE version */ + float t = isect_array->t; + + /* fetch node data */ + float4 node0 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0); + float4 node1 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+1); + float4 node2 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+2); + float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+3); + + /* intersect ray against child nodes */ + NO_EXTENDED_PRECISION float c0lox = (node0.x - P.x) * idir.x; + NO_EXTENDED_PRECISION float c0hix = (node0.z - P.x) * idir.x; + NO_EXTENDED_PRECISION float c0loy = (node1.x - P.y) * idir.y; + NO_EXTENDED_PRECISION float c0hiy = (node1.z - P.y) * idir.y; + NO_EXTENDED_PRECISION float c0loz = (node2.x - P.z) * idir.z; + NO_EXTENDED_PRECISION float c0hiz = (node2.z - P.z) * idir.z; + NO_EXTENDED_PRECISION float c0min = max4(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f); + NO_EXTENDED_PRECISION float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t); + + NO_EXTENDED_PRECISION float c1lox = (node0.y - P.x) * idir.x; + NO_EXTENDED_PRECISION float c1hix = (node0.w - P.x) * idir.x; + NO_EXTENDED_PRECISION float c1loy = (node1.y - P.y) * idir.y; + NO_EXTENDED_PRECISION float c1hiy = (node1.w - P.y) * idir.y; + NO_EXTENDED_PRECISION float c1loz = (node2.y - P.z) * idir.z; + NO_EXTENDED_PRECISION float c1hiz = (node2.w - P.z) * idir.z; + NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f); + NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t); + + /* decide which nodes to traverse next */ + traverseChild0 = (c0max >= c0min); + traverseChild1 = (c1max >= c1min); + +#else // __KERNEL_SSE2__ + /* Intersect two child bounding boxes, SSE3 version adapted from Embree */ + + /* fetch node data */ + const ssef *bvh_nodes = (ssef*)kg->__bvh_nodes.data + nodeAddr*BVH_NODE_SIZE; + const float4 cnodes = ((float4*)bvh_nodes)[3]; + + /* intersect ray against child nodes */ + const ssef tminmaxx = (shuffle_swap(bvh_nodes[0], shufflexyz[0]) - Psplat[0]) * idirsplat[0]; + const ssef tminmaxy = (shuffle_swap(bvh_nodes[1], shufflexyz[1]) - Psplat[1]) * idirsplat[1]; + const ssef tminmaxz = (shuffle_swap(bvh_nodes[2], shufflexyz[2]) - Psplat[2]) * idirsplat[2]; + + /* calculate { c0min, c1min, -c0max, -c1max} */ + ssef minmax = max(max(tminmaxx, tminmaxy), max(tminmaxz, tsplat)); + const ssef tminmax = minmax ^ pn; + + const sseb lrhit = tminmax <= shuffle<2, 3, 0, 1>(tminmax); + + /* decide which nodes to traverse next */ + traverseChild0 = (movemask(lrhit) & 1); + traverseChild1 = (movemask(lrhit) & 2); +#endif // __KERNEL_SSE2__ + + nodeAddr = __float_as_int(cnodes.x); + nodeAddrChild1 = __float_as_int(cnodes.y); + + if(traverseChild0 && traverseChild1) { + /* both children were intersected, push the farther one */ +#if !defined(__KERNEL_SSE2__) + bool closestChild1 = (c1min < c0min); +#else + bool closestChild1 = tminmax[1] < tminmax[0]; +#endif + + if(closestChild1) { + int tmp = nodeAddr; + nodeAddr = nodeAddrChild1; + nodeAddrChild1 = tmp; + } + + ++stackPtr; + kernel_assert(stackPtr < BVH_STACK_SIZE); + traversalStack[stackPtr] = nodeAddrChild1; + } + else { + /* one child was intersected */ + if(traverseChild1) { + nodeAddr = nodeAddrChild1; + } + else if(!traverseChild0) { + /* neither child was intersected */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } + } + } + + /* if node is leaf, fetch triangle list */ + if(nodeAddr < 0) { + float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE); + int primAddr = __float_as_int(leaf.x); + +#if BVH_FEATURE(BVH_INSTANCING) + if(primAddr >= 0) { +#endif + const int primAddr2 = __float_as_int(leaf.y); + const uint type = __float_as_int(leaf.w); + bool hit; + + /* pop */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + + /* primitive intersection */ + switch(type & PRIMITIVE_ALL) { + case PRIMITIVE_TRIANGLE: { + /* intersect ray against primitive */ + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* only primitives from volume object */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + int object_flag = kernel_tex_fetch(__object_flag, tri_object); + if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { + continue; + } + hit = triangle_intersect(kg, &isect_precalc, isect_array, P, visibility, object, primAddr); + if(hit) { + /* Move on to next entry in intersections array. */ + isect_array++; + num_hits++; +#if BVH_FEATURE(BVH_INSTANCING) + num_hits_in_instance++; +#endif + isect_array->t = isect_t; + if(num_hits == max_hits) { +#if BVH_FEATURE(BVH_INSTANCING) +#if BVH_FEATURE(BVH_MOTION) + float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir)); +#else + Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); + float t_fac = len(transform_direction(&tfm, 1.0f/idir)); +#endif + for(int i = 0; i < num_hits_in_instance; i++) { + (isect_array-i-1)->t *= t_fac; + } +#endif /* BVH_FEATURE(BVH_INSTANCING) */ + return num_hits; + } + } + } + break; + } +#if BVH_FEATURE(BVH_MOTION) + case PRIMITIVE_MOTION_TRIANGLE: { + /* intersect ray against primitive */ + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* only primitives from volume object */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + int object_flag = kernel_tex_fetch(__object_flag, tri_object); + if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { + continue; + } + hit = motion_triangle_intersect(kg, isect_array, P, dir, ray->time, visibility, object, primAddr); + if(hit) { + /* Move on to next entry in intersections array. */ + isect_array++; + num_hits++; +#if BVH_FEATURE(BVH_INSTANCING) + num_hits_in_instance++; +#endif + isect_array->t = isect_t; + if(num_hits == max_hits) { +#if BVH_FEATURE(BVH_INSTANCING) +# if BVH_FEATURE(BVH_MOTION) + float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir)); +# else + Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); + float t_fac = len(transform_direction(&tfm, 1.0f/idir)); +#endif + for(int i = 0; i < num_hits_in_instance; i++) { + (isect_array-i-1)->t *= t_fac; + } +#endif /* BVH_FEATURE(BVH_INSTANCING) */ + return num_hits; + } + } + } + break; + } +#endif +#if BVH_FEATURE(BVH_HAIR) + case PRIMITIVE_CURVE: + case PRIMITIVE_MOTION_CURVE: { + /* intersect ray against primitive */ + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* only primitives from volume object */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + int object_flag = kernel_tex_fetch(__object_flag, tri_object); + if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { + continue; + } + if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) + hit = bvh_cardinal_curve_intersect(kg, isect_array, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); + else + hit = bvh_curve_intersect(kg, isect_array, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); + if(hit) { + /* Move on to next entry in intersections array. */ + isect_array++; + num_hits++; +#if BVH_FEATURE(BVH_INSTANCING) + num_hits_in_instance++; +#endif + isect_array->t = isect_t; + if(num_hits == max_hits) { +#if BVH_FEATURE(BVH_INSTANCING) +# if BVH_FEATURE(BVH_MOTION) + float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir)); +# else + Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); + float t_fac = len(transform_direction(&tfm, 1.0f/idir)); +#endif + for(int i = 0; i < num_hits_in_instance; i++) { + (isect_array-i-1)->t *= t_fac; + } +#endif /* BVH_FEATURE(BVH_INSTANCING) */ + return num_hits; + } + } + } + break; + } +#endif + default: { + break; + } + } + } +#if BVH_FEATURE(BVH_INSTANCING) + else { + /* instance push */ + object = kernel_tex_fetch(__prim_object, -primAddr-1); + int object_flag = kernel_tex_fetch(__object_flag, object); + + if(object_flag & SD_OBJECT_HAS_VOLUME) { + +#if BVH_FEATURE(BVH_MOTION) + bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm); +#else + bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t); +#endif + + triangle_intersect_precalc(dir, &isect_precalc); + num_hits_in_instance = 0; + isect_array->t = isect_t; + +#if defined(__KERNEL_SSE2__) + Psplat[0] = ssef(P.x); + Psplat[1] = ssef(P.y); + Psplat[2] = ssef(P.z); + + tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t); + + gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); +#endif + + ++stackPtr; + kernel_assert(stackPtr < BVH_STACK_SIZE); + traversalStack[stackPtr] = ENTRYPOINT_SENTINEL; + + nodeAddr = kernel_tex_fetch(__object_node, object); + } + else { + /* pop */ + object = OBJECT_NONE; + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } + } + } +#endif /* FEATURE(BVH_INSTANCING) */ + } while(nodeAddr != ENTRYPOINT_SENTINEL); + +#if BVH_FEATURE(BVH_INSTANCING) + if(stackPtr >= 0) { + kernel_assert(object != OBJECT_NONE); + + if(num_hits_in_instance) { + float t_fac; +#if BVH_FEATURE(BVH_MOTION) + bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_tfm); +#else + bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac); +#endif + triangle_intersect_precalc(dir, &isect_precalc); + /* Scale isect->t to adjust for instancing. */ + for(int i = 0; i < num_hits_in_instance; i++) { + (isect_array-i-1)->t *= t_fac; + } + } + else { + float ignore_t = FLT_MAX; +#if BVH_FEATURE(BVH_MOTION) + bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &ignore_t, &ob_tfm); +#else + bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t); +#endif + triangle_intersect_precalc(dir, &isect_precalc); + } + + isect_t = tmax; + isect_array->t = isect_t; + +#if defined(__KERNEL_SSE2__) + Psplat[0] = ssef(P.x); + Psplat[1] = ssef(P.y); + Psplat[2] = ssef(P.z); + + tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t); + + gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); +#endif + + object = OBJECT_NONE; + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } +#endif /* FEATURE(BVH_MOTION) */ + } while(nodeAddr != ENTRYPOINT_SENTINEL); + + return num_hits; +} + +ccl_device_inline uint BVH_FUNCTION_NAME(KernelGlobals *kg, + const Ray *ray, + Intersection *isect_array, + const uint max_hits) +{ +#ifdef __QBVH__ + if(kernel_data.bvh.use_qbvh) { + return BVH_FUNCTION_FULL_NAME(QBVH)(kg, + ray, + isect_array, + max_hits); + } + else +#endif + { + kernel_assert(kernel_data.bvh.use_qbvh == false); + return BVH_FUNCTION_FULL_NAME(BVH)(kg, + ray, + isect_array, + max_hits); + } +} + +#undef BVH_FUNCTION_NAME +#undef BVH_FUNCTION_FEATURES diff --git a/intern/cycles/kernel/geom/geom_qbvh_volume_all.h b/intern/cycles/kernel/geom/geom_qbvh_volume_all.h new file mode 100644 index 00000000000..d5131919944 --- /dev/null +++ b/intern/cycles/kernel/geom/geom_qbvh_volume_all.h @@ -0,0 +1,446 @@ +/* + * Adapted from code Copyright 2009-2010 NVIDIA Corporation, + * and code copyright 2009-2012 Intel Corporation + * + * Modifications Copyright 2011-2014, Blender Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This is a template BVH traversal function for volumes, where + * various features can be enabled/disabled. This way we can compile optimized + * versions for each case without new features slowing things down. + * + * BVH_INSTANCING: object instancing + * BVH_HAIR: hair curve rendering + * BVH_MOTION: motion blur rendering + * + */ + +ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, + const Ray *ray, + Intersection *isect_array, + const uint max_hits) +{ + /* TODO(sergey): + * - Test if pushing distance on the stack helps. + * - Likely and unlikely for if() statements. + * - Test restrict attribute for pointers. + */ + + /* Traversal stack in CUDA thread-local memory. */ + QBVHStackItem traversalStack[BVH_QSTACK_SIZE]; + traversalStack[0].addr = ENTRYPOINT_SENTINEL; + + /* Traversal variables in registers. */ + int stackPtr = 0; + int nodeAddr = kernel_data.bvh.root; + + /* Ray parameters in registers. */ + const float tmax = ray->t; + float3 P = ray->P; + float3 dir = bvh_clamp_direction(ray->D); + float3 idir = bvh_inverse_direction(dir); + int object = OBJECT_NONE; + float isect_t = tmax; + + const uint visibility = PATH_RAY_ALL_VISIBILITY; + +#if BVH_FEATURE(BVH_MOTION) + Transform ob_tfm; +#endif + +#ifndef __KERNEL_SSE41__ + if(!isfinite(P.x)) { + return false; + } +#endif + +#if BVH_FEATURE(BVH_INSTANCING) + int num_hits_in_instance = 0; +#endif + + uint num_hits = 0; + isect_array->t = tmax; + + ssef tnear(0.0f), tfar(isect_t); + sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z)); + +#ifdef __KERNEL_AVX2__ + float3 P_idir = P*idir; + sse3f P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z); +#else + sse3f org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); +#endif + + /* Offsets to select the side that becomes the lower or upper bound. */ + int near_x, near_y, near_z; + int far_x, far_y, far_z; + + if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; } + if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; } + if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; } + + IsectPrecalc isect_precalc; + triangle_intersect_precalc(dir, &isect_precalc); + + /* Traversal loop. */ + do { + do { + /* Traverse internal nodes. */ + while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) { + ssef dist; + int traverseChild = qbvh_node_intersect(kg, + tnear, + tfar, +#ifdef __KERNEL_AVX2__ + P_idir4, +#else + org, +#endif + idir4, + near_x, near_y, near_z, + far_x, far_y, far_z, + nodeAddr, + &dist); + + if(traverseChild != 0) { + float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6); + + /* One child is hit, continue with that child. */ + int r = __bscf(traverseChild); + if(traverseChild == 0) { + nodeAddr = __float_as_int(cnodes[r]); + continue; + } + + /* Two children are hit, push far child, and continue with + * closer child. + */ + int c0 = __float_as_int(cnodes[r]); + float d0 = ((float*)&dist)[r]; + r = __bscf(traverseChild); + int c1 = __float_as_int(cnodes[r]); + float d1 = ((float*)&dist)[r]; + if(traverseChild == 0) { + if(d1 < d0) { + nodeAddr = c1; + ++stackPtr; + kernel_assert(stackPtr < BVH_QSTACK_SIZE); + traversalStack[stackPtr].addr = c0; + traversalStack[stackPtr].dist = d0; + continue; + } + else { + nodeAddr = c0; + ++stackPtr; + kernel_assert(stackPtr < BVH_QSTACK_SIZE); + traversalStack[stackPtr].addr = c1; + traversalStack[stackPtr].dist = d1; + continue; + } + } + + /* Here starts the slow path for 3 or 4 hit children. We push + * all nodes onto the stack to sort them there. + */ + ++stackPtr; + kernel_assert(stackPtr < BVH_QSTACK_SIZE); + traversalStack[stackPtr].addr = c1; + traversalStack[stackPtr].dist = d1; + ++stackPtr; + kernel_assert(stackPtr < BVH_QSTACK_SIZE); + traversalStack[stackPtr].addr = c0; + traversalStack[stackPtr].dist = d0; + + /* Three children are hit, push all onto stack and sort 3 + * stack items, continue with closest child. + */ + r = __bscf(traverseChild); + int c2 = __float_as_int(cnodes[r]); + float d2 = ((float*)&dist)[r]; + if(traverseChild == 0) { + ++stackPtr; + kernel_assert(stackPtr < BVH_QSTACK_SIZE); + traversalStack[stackPtr].addr = c2; + traversalStack[stackPtr].dist = d2; + qbvh_stack_sort(&traversalStack[stackPtr], + &traversalStack[stackPtr - 1], + &traversalStack[stackPtr - 2]); + nodeAddr = traversalStack[stackPtr].addr; + --stackPtr; + continue; + } + + /* Four children are hit, push all onto stack and sort 4 + * stack items, continue with closest child. + */ + r = __bscf(traverseChild); + int c3 = __float_as_int(cnodes[r]); + float d3 = ((float*)&dist)[r]; + ++stackPtr; + kernel_assert(stackPtr < BVH_QSTACK_SIZE); + traversalStack[stackPtr].addr = c3; + traversalStack[stackPtr].dist = d3; + ++stackPtr; + kernel_assert(stackPtr < BVH_QSTACK_SIZE); + traversalStack[stackPtr].addr = c2; + traversalStack[stackPtr].dist = d2; + qbvh_stack_sort(&traversalStack[stackPtr], + &traversalStack[stackPtr - 1], + &traversalStack[stackPtr - 2], + &traversalStack[stackPtr - 3]); + } + + nodeAddr = traversalStack[stackPtr].addr; + --stackPtr; + } + + /* If node is leaf, fetch triangle list. */ + if(nodeAddr < 0) { + float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE); + int primAddr = __float_as_int(leaf.x); + +#if BVH_FEATURE(BVH_INSTANCING) + if(primAddr >= 0) { +#endif + int primAddr2 = __float_as_int(leaf.y); + const uint type = __float_as_int(leaf.w); + const uint p_type = type & PRIMITIVE_ALL; + bool hit; + + /* Pop. */ + nodeAddr = traversalStack[stackPtr].addr; + --stackPtr; + + /* Primitive intersection. */ + switch(p_type) { + case PRIMITIVE_TRIANGLE: { + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* Only primitives from volume object. */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + int object_flag = kernel_tex_fetch(__object_flag, tri_object); + if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { + continue; + } + /* Intersect ray against primitive. */ + hit = triangle_intersect(kg, &isect_precalc, isect_array, P, visibility, object, primAddr); + if(hit) { + /* Move on to next entry in intersections array. */ + isect_array++; + num_hits++; +#if BVH_FEATURE(BVH_INSTANCING) + num_hits_in_instance++; +#endif + isect_array->t = isect_t; + if(num_hits == max_hits) { +#if BVH_FEATURE(BVH_INSTANCING) +#if BVH_FEATURE(BVH_MOTION) + float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir)); +#else + Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); + float t_fac = len(transform_direction(&tfm, 1.0f/idir)); +#endif + for(int i = 0; i < num_hits_in_instance; i++) { + (isect_array-i-1)->t *= t_fac; + } +#endif /* BVH_FEATURE(BVH_INSTANCING) */ + return num_hits; + } + } + } + break; + } +#if BVH_FEATURE(BVH_MOTION) + case PRIMITIVE_MOTION_TRIANGLE: { + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* Only primitives from volume object. */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + int object_flag = kernel_tex_fetch(__object_flag, tri_object); + if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { + continue; + } + /* Intersect ray against primitive. */ + hit = motion_triangle_intersect(kg, isect_array, P, dir, ray->time, visibility, object, primAddr); + if(hit) { + /* Move on to next entry in intersections array. */ + isect_array++; + num_hits++; +#if BVH_FEATURE(BVH_INSTANCING) + num_hits_in_instance++; +#endif + isect_array->t = isect_t; + if(num_hits == max_hits) { +#if BVH_FEATURE(BVH_INSTANCING) +# if BVH_FEATURE(BVH_MOTION) + float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir)); +# else + Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); + float t_fac = len(transform_direction(&tfm, 1.0f/idir)); +#endif + for(int i = 0; i < num_hits_in_instance; i++) { + (isect_array-i-1)->t *= t_fac; + } +#endif /* BVH_FEATURE(BVH_INSTANCING) */ + return num_hits; + } + } + } + break; + } +#endif +#if BVH_FEATURE(BVH_HAIR) + case PRIMITIVE_CURVE: + case PRIMITIVE_MOTION_CURVE: { + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* Only primitives from volume object. */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + int object_flag = kernel_tex_fetch(__object_flag, tri_object); + if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { + continue; + } + /* Intersect ray against primitive. */ + if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) + hit = bvh_cardinal_curve_intersect(kg, isect_array, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); + else + hit = bvh_curve_intersect(kg, isect_array, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); + if(hit) { + /* Move on to next entry in intersections array. */ + isect_array++; + num_hits++; +#if BVH_FEATURE(BVH_INSTANCING) + num_hits_in_instance++; +#endif + isect_array->t = isect_t; + if(num_hits == max_hits) { +#if BVH_FEATURE(BVH_INSTANCING) +# if BVH_FEATURE(BVH_MOTION) + float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir)); +# else + Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); + float t_fac = len(transform_direction(&tfm, 1.0f/idir)); +#endif + for(int i = 0; i < num_hits_in_instance; i++) { + (isect_array-i-1)->t *= t_fac; + } +#endif /* BVH_FEATURE(BVH_INSTANCING) */ + return num_hits; + } + } + } + break; + } +#endif + } + } +#if BVH_FEATURE(BVH_INSTANCING) + else { + /* Instance push. */ + object = kernel_tex_fetch(__prim_object, -primAddr-1); + int object_flag = kernel_tex_fetch(__object_flag, object); + + if(object_flag & SD_OBJECT_HAS_VOLUME) { + +#if BVH_FEATURE(BVH_MOTION) + bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm); +#else + bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t); +#endif + + if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; } + if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; } + if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; } + tfar = ssef(isect_t); + idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z)); +#ifdef __KERNEL_AVX2__ + P_idir = P*idir; + P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z); +#else + org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); +#endif + triangle_intersect_precalc(dir, &isect_precalc); + num_hits_in_instance = 0; + isect_array->t = isect_t; + + ++stackPtr; + kernel_assert(stackPtr < BVH_QSTACK_SIZE); + traversalStack[stackPtr].addr = ENTRYPOINT_SENTINEL; + + nodeAddr = kernel_tex_fetch(__object_node, object); + } + else { + /* Pop. */ + object = OBJECT_NONE; + nodeAddr = traversalStack[stackPtr].addr; + --stackPtr; + } + } + } +#endif /* FEATURE(BVH_INSTANCING) */ + } while(nodeAddr != ENTRYPOINT_SENTINEL); + +#if BVH_FEATURE(BVH_INSTANCING) + if(stackPtr >= 0) { + kernel_assert(object != OBJECT_NONE); + + /* Instance pop. */ + if(num_hits_in_instance) { + float t_fac; +#if BVH_FEATURE(BVH_MOTION) + bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_tfm); +#else + bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac); +#endif + triangle_intersect_precalc(dir, &isect_precalc); + /* Scale isect->t to adjust for instancing. */ + for(int i = 0; i < num_hits_in_instance; i++) { + (isect_array-i-1)->t *= t_fac; + } + } + else { + float ignore_t = FLT_MAX; +#if BVH_FEATURE(BVH_MOTION) + bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &ignore_t, &ob_tfm); +#else + bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t); +#endif + triangle_intersect_precalc(dir, &isect_precalc); + } + + if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; } + if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; } + if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; } + tfar = ssef(isect_t); + idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z)); +#ifdef __KERNEL_AVX2__ + P_idir = P*idir; + P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z); +#else + org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); +#endif + triangle_intersect_precalc(dir, &isect_precalc); + isect_t = tmax; + isect_array->t = isect_t; + + object = OBJECT_NONE; + nodeAddr = traversalStack[stackPtr].addr; + --stackPtr; + } +#endif /* FEATURE(BVH_INSTANCING) */ + } while(nodeAddr != ENTRYPOINT_SENTINEL); + + return num_hits; +} diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h index 8923fcebee5..d7c4fa02bcf 100644 --- a/intern/cycles/kernel/kernel_shadow.h +++ b/intern/cycles/kernel/kernel_shadow.h @@ -39,19 +39,6 @@ CCL_NAMESPACE_BEGIN * This is CPU only because of qsort, and malloc or high stack space usage to * record all these intersections. */ -ccl_device_noinline int shadow_intersections_compare(const void *a, const void *b) -{ - const Intersection *isect_a = (const Intersection*)a; - const Intersection *isect_b = (const Intersection*)b; - - if(isect_a->t < isect_b->t) - return -1; - else if(isect_a->t > isect_b->t) - return 1; - else - return 0; -} - #define STACK_MAX_HITS 64 ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, float3 *shadow) @@ -95,7 +82,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray * PathState ps = *state; #endif - qsort(hits, num_hits, sizeof(Intersection), shadow_intersections_compare); + qsort(hits, num_hits, sizeof(Intersection), intersections_compare); for(int hit = 0; hit < num_hits; hit++, isect++) { /* adjust intersection distance for moving ray forward */ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index f4f2e22edaa..b948f7de2f4 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -72,6 +72,7 @@ CCL_NAMESPACE_BEGIN #define __VOLUME_DECOUPLED__ #define __VOLUME_SCATTER__ #define __SHADOW_RECORD_ALL__ +#define __VOLUME_RECORD_ALL__ #endif #ifdef __KERNEL_CUDA__ diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index 32c7e4eef09..e06568457c6 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -993,6 +993,48 @@ ccl_device void kernel_volume_stack_init(KernelGlobals *kg, volume_ray.t = FLT_MAX; int stack_index = 0, enclosed_index = 0; + +#ifdef __VOLUME_RECORD_ALL__ + Intersection hits[2*VOLUME_STACK_SIZE]; + uint num_hits = scene_intersect_volume_all(kg, + &volume_ray, + hits, + 2*VOLUME_STACK_SIZE); + if(num_hits > 0) { + int enclosed_volumes[VOLUME_STACK_SIZE]; + Intersection *isect = hits; + + qsort(hits, num_hits, sizeof(Intersection), intersections_compare); + + for(uint hit = 0; hit < num_hits; ++hit, ++isect) { + ShaderData sd; + shader_setup_from_ray(kg, &sd, isect, &volume_ray, 0, 0); + if(sd.flag & SD_BACKFACING) { + /* If ray exited the volume and never entered to that volume + * it means that camera is inside such a volume. + */ + bool is_enclosed = false; + for(int i = 0; i < enclosed_index; ++i) { + if(enclosed_volumes[i] == sd.object) { + is_enclosed = true; + break; + } + } + if(is_enclosed == false) { + stack[stack_index].object = sd.object; + stack[stack_index].shader = sd.shader; + ++stack_index; + } + } + else { + /* If ray from camera enters the volume, this volume shouldn't + * be added to the stack on exit. + */ + enclosed_volumes[enclosed_index++] = sd.object; + } + } + } +#else int enclosed_volumes[VOLUME_STACK_SIZE]; int step = 0; @@ -1035,6 +1077,7 @@ ccl_device void kernel_volume_stack_init(KernelGlobals *kg, volume_ray.P = ray_offset(sd.P, -sd.Ng); ++step; } +#endif /* stack_index of 0 means quick checks outside of the kernel gave false * positive, nothing to worry about, just we've wasted quite a few of * ticks just to come into conclusion that camera is in the air. @@ -1105,6 +1148,25 @@ ccl_device void kernel_volume_stack_update_for_subsurface(KernelGlobals *kg, kernel_assert(kernel_data.integrator.use_volumes); Ray volume_ray = *ray; + +#ifdef __VOLUME_RECORD_ALL__ + Intersection hits[2*VOLUME_STACK_SIZE]; + uint num_hits = scene_intersect_volume_all(kg, + &volume_ray, + hits, + 2*VOLUME_STACK_SIZE); + if(num_hits > 0) { + Intersection *isect = hits; + + qsort(hits, num_hits, sizeof(Intersection), intersections_compare); + + for(uint hit = 0; hit < num_hits; ++hit, ++isect) { + ShaderData sd; + shader_setup_from_ray(kg, &sd, isect, &volume_ray, 0, 0); + kernel_volume_stack_enter_exit(kg, &sd, stack); + } + } +#else Intersection isect; int step = 0; while(step < 2 * VOLUME_STACK_SIZE && @@ -1119,6 +1181,7 @@ ccl_device void kernel_volume_stack_update_for_subsurface(KernelGlobals *kg, volume_ray.t -= sd.ray_length; ++step; } +#endif } #endif -- cgit v1.2.3 From 4eab0e72b380163f1b2e65e4d0efae30c1cdd916 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Wed, 29 Apr 2015 23:56:46 +0200 Subject: Cleanup: Update some comments and add ToDo. --- intern/cycles/kernel/geom/geom_bvh.h | 69 ++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_bvh.h b/intern/cycles/kernel/geom/geom_bvh.h index c2610c7d92c..2e8e27c709d 100644 --- a/intern/cycles/kernel/geom/geom_bvh.h +++ b/intern/cycles/kernel/geom/geom_bvh.h @@ -115,39 +115,7 @@ CCL_NAMESPACE_BEGIN #include "geom_bvh_subsurface.h" #endif -/* Record all BVH intersection for shadows */ - -#if defined(__SHADOW_RECORD_ALL__) -#define BVH_FUNCTION_NAME bvh_intersect_shadow_all -#define BVH_FUNCTION_FEATURES 0 -#include "geom_bvh_shadow.h" -#endif - -#if defined(__SHADOW_RECORD_ALL__) && defined(__INSTANCING__) -#define BVH_FUNCTION_NAME bvh_intersect_shadow_all_instancing -#define BVH_FUNCTION_FEATURES BVH_INSTANCING -#include "geom_bvh_shadow.h" -#endif - -#if defined(__SHADOW_RECORD_ALL__) && defined(__HAIR__) -#define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair -#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR -#include "geom_bvh_shadow.h" -#endif - -#if defined(__SHADOW_RECORD_ALL__) && defined(__OBJECT_MOTION__) -#define BVH_FUNCTION_NAME bvh_intersect_shadow_all_motion -#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION -#include "geom_bvh_shadow.h" -#endif - -#if defined(__SHADOW_RECORD_ALL__) && defined(__HAIR__) && defined(__OBJECT_MOTION__) -#define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair_motion -#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_MOTION -#include "geom_bvh_shadow.h" -#endif - -/* Camera inside Volume BVH intersection */ +/* Volume BVH traversal */ #if defined(__VOLUME__) #define BVH_FUNCTION_NAME bvh_intersect_volume @@ -179,7 +147,39 @@ CCL_NAMESPACE_BEGIN #include "geom_bvh_volume.h" #endif -/* Record all BVH intersection for volumes */ +/* Record all intersections - Shadow BVH traversal */ + +#if defined(__SHADOW_RECORD_ALL__) +#define BVH_FUNCTION_NAME bvh_intersect_shadow_all +#define BVH_FUNCTION_FEATURES 0 +#include "geom_bvh_shadow.h" +#endif + +#if defined(__SHADOW_RECORD_ALL__) && defined(__INSTANCING__) +#define BVH_FUNCTION_NAME bvh_intersect_shadow_all_instancing +#define BVH_FUNCTION_FEATURES BVH_INSTANCING +#include "geom_bvh_shadow.h" +#endif + +#if defined(__SHADOW_RECORD_ALL__) && defined(__HAIR__) +#define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair +#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR +#include "geom_bvh_shadow.h" +#endif + +#if defined(__SHADOW_RECORD_ALL__) && defined(__OBJECT_MOTION__) +#define BVH_FUNCTION_NAME bvh_intersect_shadow_all_motion +#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION +#include "geom_bvh_shadow.h" +#endif + +#if defined(__SHADOW_RECORD_ALL__) && defined(__HAIR__) && defined(__OBJECT_MOTION__) +#define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair_motion +#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_MOTION +#include "geom_bvh_shadow.h" +#endif + +/* Record all intersections - Volume BVH traversal */ #if defined(__VOLUME_RECORD_ALL__) #define BVH_FUNCTION_NAME bvh_intersect_volume_all @@ -447,6 +447,7 @@ ccl_device_inline float3 ray_offset(float3 P, float3 Ng) #endif } +/* ToDo: Move to another file? */ ccl_device int intersections_compare(const void *a, const void *b) { const Intersection *isect_a = (const Intersection*)a; -- cgit v1.2.3 From b640700597e4a331ee45f9a8850953e8e08cfd93 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 30 Apr 2015 08:07:15 +1000 Subject: Cleanup: style --- source/blender/blenkernel/BKE_curve.h | 2 +- source/blender/blenkernel/BKE_pbvh.h | 5 +++-- source/blender/blenkernel/intern/material.c | 2 +- source/blender/blenkernel/intern/pbvh.c | 4 +++- source/blender/editors/sculpt_paint/paint_intern.h | 2 +- source/blender/editors/sculpt_paint/paint_stroke.c | 2 +- source/blender/editors/space_view3d/view3d_draw.c | 2 +- source/blender/gpu/GPU_debug.h | 2 +- source/blender/imbuf/intern/IMB_filetype.h | 2 +- 9 files changed, 13 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 98c85415812..9de13ce9240 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -90,7 +90,7 @@ void BKE_curve_translate(struct Curve *cu, float offset[3], const bool do_keys); void BKE_curve_material_index_remove(struct Curve *cu, int index); void BKE_curve_material_index_clear(struct Curve *cu); int BKE_curve_material_index_validate(struct Curve *cu); -void BKE_curve_material_remap(struct Curve *cu,const unsigned int *remap, unsigned int remap_len); +void BKE_curve_material_remap(struct Curve *cu, const unsigned int *remap, unsigned int remap_len); ListBase *BKE_curve_nurbs_get(struct Curve *cu); diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 03ad1765f8d..1df633cc966 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -104,8 +104,9 @@ bool BKE_pbvh_bmesh_node_raycast_detail( /* for orthographic cameras, project the far away ray segment points to the root node so * we can have better precision. */ -void BKE_pbvh_raycast_project_ray_root(PBVH *bvh, bool original, float ray_start[3], - float ray_end[3], float ray_normal[3]); +void BKE_pbvh_raycast_project_ray_root( + PBVH *bvh, bool original, + float ray_start[3], float ray_end[3], float ray_normal[3]); /* Drawing */ diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 8932ac1f4c6..eaaf1319167 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -937,7 +937,7 @@ void BKE_material_remap_object(Object *ob, const unsigned int *remap) BLI_array_permute(ob->matbits, ob->totcol, remap); } - if(matar) { + if (matar) { BLI_array_permute(*matar, *totcol_p, remap); } diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index fdda72e4f7d..bcbf3b8e77b 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1612,7 +1612,9 @@ bool BKE_pbvh_node_raycast( return hit; } -void BKE_pbvh_raycast_project_ray_root (PBVH *bvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3]) +void BKE_pbvh_raycast_project_ray_root( + PBVH *bvh, bool original, + float ray_start[3], float ray_end[3], float ray_normal[3]) { if (bvh->nodes) { float rootmin_start, rootmin_end; diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 77059a22de7..05a5bf9f7b8 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -160,7 +160,7 @@ void paint_2d_redraw(const bContext *C, void *ps, bool final); void paint_2d_stroke_done(void *ps); void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], const bool eraser, float pressure, float distance, float size); void paint_2d_bucket_fill(const struct bContext *C, const float color[3], struct Brush *br, const float mouse_init[2], void *ps); -void paint_2d_gradient_fill (const struct bContext *C, struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps); +void paint_2d_gradient_fill(const struct bContext *C, struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps); void *paint_proj_new_stroke(struct bContext *C, struct Object *ob, const float mouse[2], int mode); void paint_proj_stroke(const struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2], const bool eraser, float pressure, float distance, float size); void paint_proj_redraw(const struct bContext *C, void *pps, bool final); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index f5a65be880e..f0963cae1ce 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -1015,7 +1015,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str return false; } -static void paint_stroke_line_constrain (PaintStroke *stroke, float mouse[2]) +static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2]) { if (stroke->constrain_line) { float line[2]; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index a8cfd9955c2..7c403806f05 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2776,7 +2776,7 @@ static void view3d_draw_objects( glMatrixMode(GL_MODELVIEW); glLoadMatrixf(rv3d->viewmat); } - else if (!draw_grids_after){ + else if (!draw_grids_after) { drawfloor(scene, v3d, grid_unit, true); } } diff --git a/source/blender/gpu/GPU_debug.h b/source/blender/gpu/GPU_debug.h index a74c0e7c67b..f89df2b54aa 100644 --- a/source/blender/gpu/GPU_debug.h +++ b/source/blender/gpu/GPU_debug.h @@ -63,7 +63,7 @@ void gpu_assert_no_gl_errors(const char *file, int line, const char *str); #ifdef WITH_GPU_DEBUG /* inserts a debug marker message for the debug context messaging system */ -void gpu_string_marker (size_t size, const char *str); +void gpu_string_marker(size_t size, const char *str); # define GPU_STRING_MARKER(size, str) gpu_string_marker((size), (str)) #else /* WITH_GPU_DEBUG */ diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h index 9327c15c415..0e6438fb729 100644 --- a/source/blender/imbuf/intern/IMB_filetype.h +++ b/source/blender/imbuf/intern/IMB_filetype.h @@ -88,7 +88,7 @@ int imb_savejp2(struct ImBuf *ibuf, const char *name, int flags); /* jpeg */ int imb_is_a_jpeg(unsigned char *mem); int imb_savejpeg(struct ImBuf *ibuf, const char *name, int flags); -struct ImBuf *imb_load_jpeg (unsigned char *buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *imb_load_jpeg(unsigned char *buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE]); /* bmp */ int imb_is_a_bmp(unsigned char *buf); -- cgit v1.2.3 From 0ecce09288c4141e1cfb65f81a53f19b6d726049 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 30 Apr 2015 08:18:32 +1000 Subject: Correct missing break --- source/blender/compositor/operations/COM_BlurBaseOperation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp index 07669b1a814..ce42de7a149 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp @@ -135,6 +135,7 @@ float *BlurBaseOperation::make_dist_fac_inverse(float rad, int size, int falloff break; case PROP_INVSQUARE: val = val * (2.0f - val); + break; case PROP_LIN: /* fall-through */ #ifndef NDEBUG -- cgit v1.2.3 From f553aba69f02e69ce218dbfbd99da3b998760c16 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 30 Apr 2015 09:55:54 +1000 Subject: Correct docstring --- source/blender/python/bmesh/bmesh_py_utils.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index 0dd6ee7d51a..8c9f4c4a42c 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -670,7 +670,7 @@ PyDoc_STRVAR(bpy_bm_utils_face_vert_separate_doc, " :type face: :class:`bmesh.types.BMFace`\n" " :arg vert: A vertex in the face to separate.\n" " :type vert: :class:`bmesh.types.BMVert`\n" -" :return vert: The newly created vertex or None of failure.\n" +" :return vert: The newly created vertex or None on failure.\n" " :rtype vert: :class:`bmesh.types.BMVert`\n" "\n" " .. note::\n" @@ -749,9 +749,9 @@ PyDoc_STRVAR(bpy_bm_utils_loop_separate_doc, "\n" " Rip a vertex in a face away and add a new vertex.\n" "\n" -" :arg loop: The to separate.\n" -" :type loop: :class:`bmesh.types.BMFace`\n" -" :return vert: The newly created vertex or None of failure.\n" +" :arg loop: The loop to separate.\n" +" :type loop: :class:`bmesh.types.BMLoop`\n" +" :return vert: The newly created vertex or None on failure.\n" " :rtype vert: :class:`bmesh.types.BMVert`\n" ); static PyObject *bpy_bm_utils_loop_separate(PyObject *UNUSED(self), BPy_BMLoop *value) -- cgit v1.2.3 From 1721d47106aec81406a2714816b202c2a89a9467 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 30 Apr 2015 12:55:52 +0500 Subject: CMake: Solve compilation error from path with a space --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4724e101603..9c7308e1fc2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1127,7 +1127,7 @@ if(UNIX AND NOT APPLE) if(WITH_LLVM OR WITH_SDL_DYNLOAD) # Fix for conflict with Mesa llvmpipe - set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Wl,--version-script=${CMAKE_SOURCE_DIR}/source/creator/blender.map") + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Wl,--version-script='${CMAKE_SOURCE_DIR}/source/creator/blender.map'") endif() # OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed -- cgit v1.2.3 From aa4c97faa3666a9417782e598464d0ad2f66dee5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 30 Apr 2015 18:45:47 +1000 Subject: View3D: expose size as a distance in units also note that size/rotation doesn't work for camera views. see T44511 --- source/blender/makesrna/intern/rna_space.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index eade210f90d..4f54a6f07dc 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -1348,6 +1348,19 @@ static void rna_BackgroundImage_opacity_set(PointerRNA *ptr, float value) bgpic->blend = 1.0f - value; } +/* radius internally (expose as a distance value) */ +static float rna_BackgroundImage_size_get(PointerRNA *ptr) +{ + BGpic *bgpic = ptr->data; + return bgpic->size * 2.0f; +} + +static void rna_BackgroundImage_size_set(PointerRNA *ptr, float value) +{ + BGpic *bgpic = ptr->data; + bgpic->size = value * 0.5f; +} + static BGpic *rna_BackgroundImage_new(View3D *v3d) { BGpic *bgpic = ED_view3D_background_image_new(v3d); @@ -2108,15 +2121,16 @@ static void rna_def_background_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Y Offset", "Offset image vertically from the world origin"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "size"); - RNA_def_property_ui_text(prop, "Size", "Scaling factor for the background image"); + RNA_def_property_float_funcs(prop, "rna_BackgroundImage_size_get", "rna_BackgroundImage_size_set", NULL); + RNA_def_property_ui_text(prop, "Size", "Size of the background image (ortho view only)"); RNA_def_property_range(prop, 0.0, FLT_MAX); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_EULER); RNA_def_property_float_sdna(prop, NULL, "rotation"); - RNA_def_property_ui_text(prop, "Rotation", "Rotation for the background image"); + RNA_def_property_ui_text(prop, "Rotation", "Rotation for the background image (ortho view only)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "use_flip_x", PROP_BOOLEAN, PROP_NONE); -- cgit v1.2.3 From 41d817f15da2bfb0423612d6ba1d464e8a983bb9 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 30 Apr 2015 14:21:32 +0500 Subject: Fix T44548: Cycles Tube Mapping off / not compatible with BI Was a typo in original implementation, probably a result of some code reshuffle happened for optimization reasons. --- intern/cycles/util/util_math.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index f48625ec95d..2262f8fdbb7 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -1472,7 +1472,7 @@ ccl_device_inline float2 map_to_tube(const float3 co) len = sqrtf(co.x * co.x + co.y * co.y); if(len > 0.0f) { u = (1.0f - (atan2f(co.x / len, co.y / len) / M_PI_F)) * 0.5f; - v = (co.x + 1.0f) * 0.5f; + v = (co.z + 1.0f) * 0.5f; } else { u = v = 0.0f; -- cgit v1.2.3 From 4bcc7a2ec6bf6937778a2227c7f938c50a0fafe5 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 30 Apr 2015 14:52:59 +0500 Subject: Fix T44556: Crash on the World Properties > Preview Issue was caused by de-referencing NULL pointer, rres did not have any views because nothing was rendered yet. Needs more closer look about where else such a de-reference could happen. --- source/blender/editors/render/render_preview.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 2c353c13334..b9aa6ac6e72 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -532,6 +532,7 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, int newx = BLI_rcti_size_x(rect); int newy = BLI_rcti_size_y(rect); bool ok = false; + bool has_rectf = false; if (!split || first) sprintf(name, "Preview %p", (void *)sa); else sprintf(name, "SecondPreview %p", (void *)sa); @@ -551,11 +552,14 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, re = RE_GetRender(name); RE_AcquireResultImageViews(re, &rres); + /* TODO(sergey): Is there a cleaner way to do this? */ + if (!BLI_listbase_is_empty(&rres.views)) { + /* material preview only needs monoscopy (view 0) */ + rv = RE_RenderViewGetById(&rres, 0); + has_rectf = rv->rectf != NULL; + } - /* material preview only needs monoscopy (view 0) */ - rv = RE_RenderViewGetById(&rres, 0); - - if (rv->rectf) { + if (has_rectf) { if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) { -- cgit v1.2.3 From 290997538590d54387602a37879ad4cffbc311da Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 30 Apr 2015 12:10:58 +0200 Subject: Fix T44541 aka gigapixel image render support in blender. Moral of the story: Make sure that size_t is used whenever pointer arithmetic is involved. For images, that basically means whenever any squared dimensions are involved. Casting an operand to size_t early in the operation is usually sufficient to force the entire operation to size_t. There might still be places lurking where we don't support this correctly. This has been tested with render pipeline, quite a few image functions (meaning we can paint on such images now, albeit somewhat slowly ;) ) and export to jpeg. Too many places in code to check so I guess we'll be handling cases as they come. Don't try this at home unless you have an immense ammount of RAM. First GPixel render of suzanne in the multiverse can be found here: http://download.blender.org/demo/test/suzanne-billion-pixel.jpg Can be viewed from blender (takes about 3.3 GB after loading but may take more during loading so 8GB might be more safe to try this). --- source/blender/editors/screen/glutil.c | 16 ++--- source/blender/imbuf/intern/allocimbuf.c | 4 +- source/blender/imbuf/intern/colormanagement.c | 20 +++--- source/blender/imbuf/intern/divers.c | 82 +++++++++++----------- source/blender/imbuf/intern/imageprocess.c | 4 +- source/blender/imbuf/intern/rectop.c | 18 ++--- .../blender/render/intern/source/render_result.c | 11 +-- 7 files changed, 78 insertions(+), 77 deletions(-) diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index c7421aa0c16..8a8b61e09fe 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -579,25 +579,25 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, continue; if (type == GL_FLOAT) { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]); /* add an extra border of pixels so linear looks ok at edges of full image. */ if (subpart_w < tex_w) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); if (subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); if (subpart_w < tex_w && subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]); if (subpart_w < tex_w) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); if (subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); if (subpart_w < tex_w && subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); } glEnable(GL_TEXTURE_2D); diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index b28d19e3e15..18c3aeb8942 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -465,10 +465,10 @@ ImBuf *IMB_dupImBuf(ImBuf *ibuf1) if (ibuf2 == NULL) return NULL; if (flags & IB_rect) - memcpy(ibuf2->rect, ibuf1->rect, x * y * sizeof(int)); + memcpy(ibuf2->rect, ibuf1->rect, ((size_t)x) * y * sizeof(int)); if (flags & IB_rectfloat) - memcpy(ibuf2->rect_float, ibuf1->rect_float, ibuf1->channels * x * y * sizeof(float)); + memcpy(ibuf2->rect_float, ibuf1->rect_float, ((size_t)ibuf1->channels) * x * y * sizeof(float)); if (ibuf1->encodedbuffer) { ibuf2->encodedbuffersize = ibuf1->encodedbuffersize; diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 20baa1614c9..d6fdcad0819 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1306,8 +1306,8 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l float dither = ibuf->dither; bool is_data = (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) != 0; - int offset = channels * start_line * ibuf->x; - int display_buffer_byte_offset = DISPLAY_BUFFER_CHANNELS * start_line * ibuf->x; + size_t offset = ((size_t)channels) * start_line * ibuf->x; + size_t display_buffer_byte_offset = ((size_t)DISPLAY_BUFFER_CHANNELS) * start_line * ibuf->x; memset(handle, 0, sizeof(DisplayBufferThread)); @@ -1344,7 +1344,7 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle, int channels = handle->channels; int width = handle->width; - int buffer_size = channels * width * height; + size_t buffer_size = ((size_t)channels) * width * height; bool is_data = handle->is_data; bool is_data_display = handle->cm_processor->is_data_result; @@ -1357,11 +1357,11 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle, float *fp; unsigned char *cp; - int i; + size_t i; /* first convert byte buffer to float, keep in image space */ for (i = 0, fp = linear_buffer, cp = byte_buffer; - i < width * height; + i < ((size_t)width) * height; i++, fp += channels, cp += channels) { if (channels == 3) { @@ -1440,7 +1440,7 @@ static void *do_display_buffer_apply_thread(void *handle_v) } else { bool is_straight_alpha, predivide; - float *linear_buffer = MEM_mallocN(channels * width * height * sizeof(float), + float *linear_buffer = MEM_mallocN(((size_t)channels) * width * height * sizeof(float), "color conversion linear buffer"); display_buffer_apply_get_linear_buffer(handle, height, linear_buffer, &is_straight_alpha); @@ -1467,14 +1467,14 @@ static void *do_display_buffer_apply_thread(void *handle_v) } if (display_buffer) { - memcpy(display_buffer, linear_buffer, width * height * channels * sizeof(float)); + memcpy(display_buffer, linear_buffer, ((size_t)width) * height * channels * sizeof(float)); if (is_straight_alpha && channels == 4) { - int i; + size_t i; float *fp; for (i = 0, fp = display_buffer; - i < width * height; + i < ((size_t)width) * height; i++, fp += channels) { straight_to_premul_v4(fp); @@ -2959,7 +2959,7 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { - float *pixel = buffer + channels * (y * width + x); + float *pixel = buffer + channels * (((size_t)y) * width + x); curve_mapping_apply_pixel(cm_processor->curve_mapping, pixel, channels); } diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 3417fe2fc1d..455b78bce4d 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -184,16 +184,16 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, if (channels_from == 1) { /* single channel input */ - const float *from = rect_from + stride_from * y; - uchar *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from++, to += 4) to[0] = to[1] = to[2] = to[3] = FTOCHAR(from[0]); } else if (channels_from == 3) { /* RGB input */ - const float *from = rect_from + stride_from * y * 3; - uchar *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 3; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { /* no color space conversion */ @@ -221,8 +221,8 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, } else if (channels_from == 4) { /* RGBA input */ - const float *from = rect_from + stride_from * y * 4; - uchar *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 4; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { float straight[4]; @@ -334,8 +334,8 @@ void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from, if (channels_from == 1) { /* single channel input */ - const float *from = rect_from + stride_from * y; - uchar *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from++, to += 4) if (*mask++ == FILTER_MASK_USED) @@ -343,8 +343,8 @@ void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from, } else if (channels_from == 3) { /* RGB input */ - const float *from = rect_from + stride_from * y * 3; - uchar *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 3; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from += 3, to += 4) { if (*mask++ == FILTER_MASK_USED) { @@ -355,8 +355,8 @@ void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from, } else if (channels_from == 4) { /* RGBA input */ - const float *from = rect_from + stride_from * y * 4; - uchar *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 4; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; float straight[4]; @@ -408,7 +408,7 @@ void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from, /* RGBA input */ for (y = 0; y < height; y++) { const uchar *from = rect_from + stride_from * y * 4; - float *to = rect_to + stride_to * y * 4; + float *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { /* no color space conversion */ @@ -460,8 +460,8 @@ void IMB_buffer_float_from_float(float *rect_to, const float *rect_from, if (channels_from == 1) { /* single channel input */ for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y; - float *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y; + float *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from++, to += 4) to[0] = to[1] = to[2] = to[3] = from[0]; @@ -470,8 +470,8 @@ void IMB_buffer_float_from_float(float *rect_to, const float *rect_from, else if (channels_from == 3) { /* RGB input */ for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y * 3; - float *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 3; + float *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { /* no color space conversion */ @@ -499,12 +499,12 @@ void IMB_buffer_float_from_float(float *rect_to, const float *rect_from, else if (channels_from == 4) { /* RGBA input */ for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y * 4; - float *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 4; + float *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { /* same profile, copy */ - memcpy(to, from, sizeof(float) * 4 * width); + memcpy(to, from, sizeof(float) * ((size_t)4) * width); } else if (profile_to == IB_PROFILE_LINEAR_RGB) { /* convert to sRGB to linear */ @@ -541,8 +541,8 @@ void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, in if (channels_from == 1) { /* single channel input */ for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y; - float *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y; + float *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from++, to += 4) if (*mask++ == FILTER_MASK_USED) @@ -552,8 +552,8 @@ void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, in else if (channels_from == 3) { /* RGB input */ for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y * 3; - float *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 3; + float *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from += 3, to += 4) { if (*mask++ == FILTER_MASK_USED) { @@ -566,8 +566,8 @@ void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, in else if (channels_from == 4) { /* RGBA input */ for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y * 4; - float *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 4; + float *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from += 4, to += 4) if (*mask++ == FILTER_MASK_USED) @@ -590,8 +590,8 @@ void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from, /* always RGBA input */ for (y = 0; y < height; y++) { - const uchar *from = rect_from + stride_from * y * 4; - uchar *to = rect_to + stride_to * y * 4; + const uchar *from = rect_from + ((size_t)stride_from) * y * 4; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { /* same profile, copy */ @@ -690,8 +690,8 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w imb_addrectImBuf(ibuf); /* do conversion */ - rect_float = ibuf->rect_float + (x + y * ibuf->x) * ibuf->channels; - rect_byte = (uchar *)ibuf->rect + (x + y * ibuf->x) * 4; + rect_float = ibuf->rect_float + (x + ((size_t)y) * ibuf->x) * ibuf->channels; + rect_byte = (uchar *)ibuf->rect + (x + ((size_t)y) * ibuf->x) * 4; if (is_data) { /* exception for non-color data, just copy float */ @@ -734,9 +734,9 @@ void IMB_float_from_rect(ImBuf *ibuf) */ rect_float = ibuf->rect_float; if (rect_float == NULL) { - int size; + size_t size; - size = ibuf->x * ibuf->y; + size = ((size_t)ibuf->x) * ibuf->y; size = size * 4 * sizeof(float); ibuf->channels = 4; @@ -771,22 +771,22 @@ void IMB_color_to_bw(ImBuf *ibuf) { float *rct_fl = ibuf->rect_float; uchar *rct = (uchar *)ibuf->rect; - int i; + size_t i; if (rct_fl) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rct_fl += 4) + for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct_fl += 4) rct_fl[0] = rct_fl[1] = rct_fl[2] = IMB_colormanagement_get_luminance(rct_fl); } if (rct) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rct += 4) + for (i = ((size_t)ibuf->x * ibuf->y); i > 0; i--, rct += 4) rct[0] = rct[1] = rct[2] = IMB_colormanagement_get_luminance_byte(rct); } } void IMB_buffer_float_clamp(float *buf, int width, int height) { - int i, total = width * height * 4; + size_t i, total = ((size_t)width) * height * 4; for (i = 0; i < total; i++) { buf[i] = min_ff(1.0, buf[i]); } @@ -794,7 +794,7 @@ void IMB_buffer_float_clamp(float *buf, int width, int height) void IMB_buffer_float_unpremultiply(float *buf, int width, int height) { - int total = width * height; + size_t total = ((size_t)width) * height; float *fp = buf; while (total--) { premul_to_straight_v4(fp); @@ -804,7 +804,7 @@ void IMB_buffer_float_unpremultiply(float *buf, int width, int height) void IMB_buffer_float_premultiply(float *buf, int width, int height) { - int total = width * height; + size_t total = ((size_t)width) * height; float *fp = buf; while (total--) { straight_to_premul_v4(fp); @@ -816,14 +816,14 @@ void IMB_buffer_float_premultiply(float *buf, int width, int height) void IMB_saturation(ImBuf *ibuf, float sat) { - int i; + size_t i; unsigned char *rct = (unsigned char *)ibuf->rect; float *rct_fl = ibuf->rect_float; float hsv[3]; if (rct) { float rgb[3]; - for (i = ibuf->x * ibuf->y; i > 0; i--, rct += 4) { + for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct += 4) { rgb_uchar_to_float(rgb, rct); rgb_to_hsv_v(rgb, hsv); hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb + 1, rgb + 2); @@ -832,7 +832,7 @@ void IMB_saturation(ImBuf *ibuf, float sat) } if (rct_fl) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rct_fl += 4) { + for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct_fl += 4) { rgb_to_hsv_v(rct_fl, hsv); hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rct_fl, rct_fl + 1, rct_fl + 2); } diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index 8234b01992b..90219461772 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -343,7 +343,7 @@ void IMB_processor_apply_threaded(int buffer_lines, int handle_size, void *init_ void IMB_alpha_under_color_float(float *rect_float, int x, int y, float backcol[3]) { - int a = x * y; + size_t a = ((size_t)x) * y; float *fp = rect_float; while (a--) { @@ -366,7 +366,7 @@ void IMB_alpha_under_color_float(float *rect_float, int x, int y, float backcol[ void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, float backcol[3]) { - int a = x * y; + size_t a = ((size_t)x) * y; unsigned char *cp = rect; while (a--) { diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index 4001b681ad9..c7b347cb20c 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -322,30 +322,30 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask, do_float = (sbuf && sbuf->rect_float && dbuf->rect_float && obuf->rect_float); if (do_char) { - drect = dbuf->rect + desty * dbuf->x + destx; - orect = obuf->rect + origy * obuf->x + origx; + drect = dbuf->rect + ((size_t)desty) * dbuf->x + destx; + orect = obuf->rect + ((size_t)origy) * obuf->x + origx; } if (do_float) { - drectf = dbuf->rect_float + (desty * dbuf->x + destx) * 4; - orectf = obuf->rect_float + (origy * obuf->x + origx) * 4; + drectf = dbuf->rect_float + (((size_t)desty) * dbuf->x + destx) * 4; + orectf = obuf->rect_float + (((size_t)origy) * obuf->x + origx) * 4; } if (dmaskrect) - dmaskrect += origy * obuf->x + origx; + dmaskrect += ((size_t)origy) * obuf->x + origx; destskip = dbuf->x; origskip = obuf->x; if (sbuf) { - if (do_char) srect = sbuf->rect + srcy * sbuf->x + srcx; - if (do_float) srectf = sbuf->rect_float + (srcy * sbuf->x + srcx) * 4; + if (do_char) srect = sbuf->rect + ((size_t)srcy) * sbuf->x + srcx; + if (do_float) srectf = sbuf->rect_float + (((size_t)srcy) * sbuf->x + srcx) * 4; srcskip = sbuf->x; if (cmaskrect) - cmaskrect += srcy * sbuf->x + srcx; + cmaskrect += ((size_t)srcy) * sbuf->x + srcx; if (texmaskrect) - texmaskrect += srcy * sbuf->x + srcx; + texmaskrect += ((size_t)srcy) * sbuf->x + srcx; } else { srect = drect; diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 4b5c6e54406..019484f7ed2 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -486,7 +486,7 @@ static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int const size_t view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name)); const char *typestr = name_from_passtype(passtype, -1); RenderPass *rpass = MEM_callocN(sizeof(RenderPass), typestr); - size_t rectsize = ((size_t)rr->rectx) * ((size_t)rr->recty) * ((size_t)channels); + size_t rectsize = ((size_t)rr->rectx) * rr->recty * channels; BLI_addtail(&rl->passes, rpass); rpass->passtype = passtype; @@ -944,22 +944,23 @@ void render_result_views_new(RenderResult *rr, RenderData *rd) static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize) { - int y, ofs, copylen, tilex, tiley; + int y, tilex, tiley; + size_t ofs, copylen; copylen = tilex = rrpart->rectx; tiley = rrpart->recty; if (rrpart->crop) { /* filters add pixel extra */ - tile += pixsize * (rrpart->crop + rrpart->crop * tilex); + tile += pixsize * (rrpart->crop + ((size_t)rrpart->crop) * tilex); copylen = tilex - 2 * rrpart->crop; tiley -= 2 * rrpart->crop; - ofs = (rrpart->tilerect.ymin + rrpart->crop) * rr->rectx + (rrpart->tilerect.xmin + rrpart->crop); + ofs = (((size_t)rrpart->tilerect.ymin) + rrpart->crop) * rr->rectx + (rrpart->tilerect.xmin + rrpart->crop); target += pixsize * ofs; } else { - ofs = (rrpart->tilerect.ymin * rr->rectx + rrpart->tilerect.xmin); + ofs = (((size_t)rrpart->tilerect.ymin) * rr->rectx + rrpart->tilerect.xmin); target += pixsize * ofs; } -- cgit v1.2.3 From 16794f908fe3f1df46096df100e007049991d89e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 30 Apr 2015 15:46:09 +0500 Subject: Cycles: Fix possible uninitialized XML read state which might cause crashes --- intern/cycles/app/cycles_xml.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 2b99dfe6feb..382574696c4 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -55,6 +55,16 @@ struct XMLReadState { string base; /* base path to current file*/ float dicing_rate; /* current dicing rate */ Mesh::DisplacementMethod displacement_method; + + XMLReadState() + : scene(NULL), + smooth(false), + shader(0), + dicing_rate(0.0f), + displacement_method(Mesh::DISPLACE_BUMP) + { + tfm = transform_identity(); + } }; /* Attribute Reading */ -- cgit v1.2.3 From debcd6b2177938feef619e0b2d65e1dbf00cfef8 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 30 Apr 2015 22:43:48 +1200 Subject: Fix T44558 - "Clear Keyframes" complains when operating on an array property and it had deleted the action in the process --- source/blender/editors/animation/keyframing.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 64ced437142..08b1889aff6 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1884,8 +1884,19 @@ static int clear_key_button_exec(bContext *C, wmOperator *op) else length = 1; - for (a = 0; a < length; a++) + for (a = 0; a < length; a++) { + AnimData *adt = BKE_animdata_from_id(ptr.id.data); + success += clear_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, 0); + + /* T44558 - Stop if there's no animdata anymore + * This is needed if only the first item in an array is keyed, + * and we're clearing for the whole array + */ + if (ELEM(NULL, adt, adt->action)) { + break; + } + } MEM_freeN(path); } -- cgit v1.2.3 From 7369c4f4d50ee02d8ad574bbb1a3320626e1bed3 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 30 Apr 2015 22:50:31 +1200 Subject: Code Cleanup: Simplify Clear Keyframes operator's code On second thought, the previous commit was just adding additional complexity which wasn't needed, as the operator was wasting effort by doing this looping itself. --- source/blender/editors/animation/keyframing.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 08b1889aff6..4e1e9320a37 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1865,7 +1865,7 @@ static int clear_key_button_exec(bContext *C, wmOperator *op) PropertyRNA *prop = NULL; char *path; short success = 0; - int a, index, length; + int index; const bool all = RNA_boolean_get(op->ptr, "all"); /* try to insert keyframe using property retrieved from UI */ @@ -1876,28 +1876,11 @@ static int clear_key_button_exec(bContext *C, wmOperator *op) if (path) { if (all) { - length = RNA_property_array_length(&ptr, prop); - - if (length) index = 0; - else length = 1; - } - else - length = 1; - - for (a = 0; a < length; a++) { - AnimData *adt = BKE_animdata_from_id(ptr.id.data); - - success += clear_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, 0); - - /* T44558 - Stop if there's no animdata anymore - * This is needed if only the first item in an array is keyed, - * and we're clearing for the whole array - */ - if (ELEM(NULL, adt, adt->action)) { - break; - } + /* -1 indicates operating on the entire array (or the property itself otherwise) */ + index = -1; } + success += clear_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, 0); MEM_freeN(path); } else if (G.debug & G_DEBUG) -- cgit v1.2.3 From 04b23af02d89f765ff580dc188747598e6babb1a Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 30 Apr 2015 22:58:53 +1200 Subject: Code Cleanup: Simplified insert_keyframe_button and delete_keyframe_button As a followup for the previous commit, do the same thing for the insert/delete keyframe button operators as is done for the clear keyframes op. There really isn't much need/reason for conducting the looping there, as those functions natively handle this themselves already. --- source/blender/editors/animation/keyframing.c | 29 +++++++++------------------ 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 4e1e9320a37..092408d7de5 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1696,7 +1696,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) char *path; float cfra = (float)CFRA; short success = 0; - int a, index, length; + int index; const bool all = RNA_boolean_get(op->ptr, "all"); short flag = 0; @@ -1715,7 +1715,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) NlaStrip *strip = (NlaStrip *)ptr.data; FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), flag); - success += insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0); + success = insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0); } else { /* standard properties */ @@ -1723,16 +1723,11 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) if (path) { if (all) { - length = RNA_property_array_length(&ptr, prop); - - if (length) index = 0; - else length = 1; + /* -1 indicates operating on the entire array (or the property itself otherwise) */ + index = -1; } - else - length = 1; - for (a = 0; a < length; a++) - success += insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, cfra, flag); + success = insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, cfra, flag); MEM_freeN(path); } @@ -1795,7 +1790,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op) char *path; float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap short success = 0; - int a, index, length; + int index; const bool all = RNA_boolean_get(op->ptr, "all"); /* try to insert keyframe using property retrieved from UI */ @@ -1806,17 +1801,11 @@ static int delete_key_button_exec(bContext *C, wmOperator *op) if (path) { if (all) { - length = RNA_property_array_length(&ptr, prop); - - if (length) index = 0; - else length = 1; + /* -1 indicates operating on the entire array (or the property itself otherwise) */ + index = -1; } - else - length = 1; - - for (a = 0; a < length; a++) - success += delete_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, cfra, 0); + success = delete_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, cfra, 0); MEM_freeN(path); } else if (G.debug & G_DEBUG) -- cgit v1.2.3 From 2d491b84151ad3cf3050f0526d187aa664873c8f Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 30 Apr 2015 13:52:25 +0200 Subject: Minor tweaks to make fill and invert support gpixel operations --- source/blender/editors/include/ED_paint.h | 2 +- source/blender/editors/sculpt_paint/paint_image.c | 8 ++--- .../blender/editors/sculpt_paint/paint_image_2d.c | 36 +++++++++++----------- .../editors/sculpt_paint/paint_image_proj.c | 4 +-- source/blender/editors/sculpt_paint/paint_intern.h | 2 +- source/blender/editors/space_image/image_ops.c | 8 ++--- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/source/blender/editors/include/ED_paint.h b/source/blender/editors/include/ED_paint.h index 822dab61a06..e46f4b966c0 100644 --- a/source/blender/editors/include/ED_paint.h +++ b/source/blender/editors/include/ED_paint.h @@ -58,7 +58,7 @@ void ED_undo_paint_push_end(int type); void ED_image_undo_restore(struct bContext *C, struct ListBase *lb); void ED_image_undo_free(struct ListBase *lb); void ED_imapaint_clear_partial_redraw(void); -void ED_imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h); +void ED_imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h, bool find_old); void ED_imapaint_bucket_fill(struct bContext *C, float color[3], struct wmOperator *op); #endif /* __ED_PAINT_H__ */ diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 7992767072a..346be5b336e 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -215,7 +215,7 @@ void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsi return NULL; } -void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **mask, bool **valid, bool proj) +void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **mask, bool **valid, bool proj, bool find_prev) { ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE); UndoImageTile *tile; @@ -226,7 +226,7 @@ void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, /* check if tile is already pushed */ /* in projective painting we keep accounting of tiles, so if we need one pushed, just push! */ - if (!proj) { + if (find_prev) { data = image_undo_find_tile(ima, ibuf, x_tile, y_tile, mask, true); if (data) return data; @@ -445,7 +445,7 @@ void imapaint_region_tiles(ImBuf *ibuf, int x, int y, int w, int h, int *tx, int *ty = (y >> IMAPAINT_TILE_BITS); } -void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h) +void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h, bool find_old) { ImBuf *tmpibuf = NULL; int tilex, tiley, tilew, tileh, tx, ty; @@ -474,7 +474,7 @@ void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int for (ty = tiley; ty <= tileh; ty++) for (tx = tilex; tx <= tilew; tx++) - image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty, NULL, NULL, false); + image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty, NULL, NULL, false, find_old); ibuf->userflags |= IB_BITMAPDIRTY; diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index eff604658d9..f0c47794534 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -1049,7 +1049,7 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsign for (a = 0; a < tot; a++) { ED_imapaint_dirty_region(s->image, s->canvas, region[a].destx, region[a].desty, - region[a].width, region[a].height); + region[a].width, region[a].height, true); if (s->do_masking) { /* masking, find original pixels tiles from undo buffer to composite over */ @@ -1329,12 +1329,12 @@ static void paint_2d_fill_add_pixel_float( const int x_px, const int y_px, ImBuf *ibuf, BLI_Stack *stack, BLI_bitmap *touched, const float color[4], float threshold_sq) { - int coordinate; + size_t coordinate; if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0) return; - coordinate = y_px * ibuf->x + x_px; + coordinate = ((size_t)y_px) * ibuf->x + x_px; if (!BLI_BITMAP_TEST(touched, coordinate)) { if (compare_len_squared_v3v3(ibuf->rect_float + 4 * coordinate, color, threshold_sq)) { @@ -1386,21 +1386,21 @@ void paint_2d_bucket_fill( if (!mouse_init || !br) { /* first case, no image UV, fill the whole image */ - ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y); + ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false); if (do_float) { for (x_px = 0; x_px < ibuf->x; x_px++) { for (y_px = 0; y_px < ibuf->y; y_px++) { - blend_color_mix_float(ibuf->rect_float + 4 * (y_px * ibuf->x + x_px), - ibuf->rect_float + 4 * (y_px * ibuf->x + x_px), color_f); + blend_color_mix_float(ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px), + ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px), color_f); } } } else { for (x_px = 0; x_px < ibuf->x; x_px++) { for (y_px = 0; y_px < ibuf->y; y_px++) { - blend_color_mix_byte((unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px), - (unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px), (unsigned char *)&color_b); + blend_color_mix_byte((unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px), + (unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px), (unsigned char *)&color_b); } } } @@ -1410,7 +1410,7 @@ void paint_2d_bucket_fill( * value is within the brush fill threshold from the fill color */ BLI_Stack *stack; BLI_bitmap *touched; - int coordinate; + size_t coordinate; int width = ibuf->x; float image_init[2]; int minx = ibuf->x, miny = ibuf->y, maxx = 0, maxy = 0; @@ -1428,12 +1428,12 @@ void paint_2d_bucket_fill( } /* change image invalidation method later */ - ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y); + ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false); - stack = BLI_stack_new(sizeof(int), __func__); - touched = BLI_BITMAP_NEW(ibuf->x * ibuf->y, "bucket_fill_bitmap"); + stack = BLI_stack_new(sizeof(size_t), __func__); + touched = BLI_BITMAP_NEW(((size_t)ibuf->x) * ibuf->y, "bucket_fill_bitmap"); - coordinate = (y_px * ibuf->x + x_px); + coordinate = (((size_t)y_px) * ibuf->x + x_px); if (do_float) { copy_v4_v4(pixel_color, ibuf->rect_float + 4 * coordinate); @@ -1566,7 +1566,7 @@ void paint_2d_gradient_fill( do_float = (ibuf->rect_float != NULL); /* this will be substituted by something else when selection is available */ - ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y); + ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false); if (do_float) { for (x_px = 0; x_px < ibuf->x; x_px++) { @@ -1590,8 +1590,8 @@ void paint_2d_gradient_fill( /* convert to premultiplied */ mul_v3_fl(color_f, color_f[3]); color_f[3] *= br->alpha; - IMB_blend_color_float(ibuf->rect_float + 4 * (y_px * ibuf->x + x_px), - ibuf->rect_float + 4 * (y_px * ibuf->x + x_px), + IMB_blend_color_float(ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px), + ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px), color_f, br->blend); } } @@ -1619,8 +1619,8 @@ void paint_2d_gradient_fill( linearrgb_to_srgb_v3_v3(color_f, color_f); rgba_float_to_uchar((unsigned char *)&color_b, color_f); ((unsigned char *)&color_b)[3] *= br->alpha; - IMB_blend_color_byte((unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px), - (unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px), + IMB_blend_color_byte((unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px), + (unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px), (unsigned char *)&color_b, br->blend); } } diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 698b62bf259..b74dcb73acd 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -1501,10 +1501,10 @@ static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty) if (generate_tile) { volatile void *undorect; if (tinf->masked) { - undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, &pjIma->maskRect[tile_index], &pjIma->valid[tile_index], true); + undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, &pjIma->maskRect[tile_index], &pjIma->valid[tile_index], true, false); } else { - undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, NULL, &pjIma->valid[tile_index], true); + undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, NULL, &pjIma->valid[tile_index], true, false); } pjIma->ibuf->userflags |= IB_BITMAPDIRTY; diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 05a5bf9f7b8..fd7e053fea3 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -145,7 +145,7 @@ typedef struct ImagePaintPartialRedraw { int image_texture_paint_poll(struct bContext *C); void *image_undo_find_tile(struct Image *ima, struct ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask, bool validate); -void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **, bool **valid, bool proj); +void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **, bool **valid, bool proj, bool find_prev); void image_undo_remove_masks(void); void image_undo_init_locks(void); void image_undo_end_locks(void); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index bd44a7f403c..75e6f77ba49 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -2406,7 +2406,7 @@ static int image_invert_exec(bContext *C, wmOperator *op) const bool b = RNA_boolean_get(op->ptr, "invert_b"); const bool a = RNA_boolean_get(op->ptr, "invert_a"); - int i; + size_t i; if (ibuf == NULL) /* TODO: this should actually never happen, but does for render-results -> cleanup */ return OPERATOR_CANCELLED; @@ -2417,13 +2417,13 @@ static int image_invert_exec(bContext *C, wmOperator *op) /* not strictly needed, because we only imapaint_dirty_region to invalidate all tiles * but better do this right in case someone copies this for a tool that uses partial redraw better */ ED_imapaint_clear_partial_redraw(); - ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y); + ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false); } /* TODO: make this into an IMB_invert_channels(ibuf,r,g,b,a) method!? */ if (ibuf->rect_float) { float *fp = (float *) ibuf->rect_float; - for (i = ibuf->x * ibuf->y; i > 0; i--, fp += 4) { + for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, fp += 4) { if (r) fp[0] = 1.0f - fp[0]; if (g) fp[1] = 1.0f - fp[1]; if (b) fp[2] = 1.0f - fp[2]; @@ -2437,7 +2437,7 @@ static int image_invert_exec(bContext *C, wmOperator *op) else if (ibuf->rect) { char *cp = (char *) ibuf->rect; - for (i = ibuf->x * ibuf->y; i > 0; i--, cp += 4) { + for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, cp += 4) { if (r) cp[0] = 255 - cp[0]; if (g) cp[1] = 255 - cp[1]; if (b) cp[2] = 255 - cp[2]; -- cgit v1.2.3 From d1c98520f7b792d5f2f1f2d1eb51d08d172e2e22 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 30 Apr 2015 14:24:05 +0200 Subject: Missed this last commit --- source/blender/editors/sculpt_paint/paint_image_2d.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index f0c47794534..1ad700b2964 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -1306,12 +1306,12 @@ static void paint_2d_fill_add_pixel_byte( const int x_px, const int y_px, ImBuf *ibuf, BLI_Stack *stack, BLI_bitmap *touched, const float color[4], float threshold_sq) { - int coordinate; + size_t coordinate; if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0) return; - coordinate = y_px * ibuf->x + x_px; + coordinate = ((size_t)y_px) * ibuf->x + x_px; if (!BLI_BITMAP_TEST(touched, coordinate)) { float color_f[4]; -- cgit v1.2.3 From f271d85b865cb5e82b50a29f91d2cabbbede6a9a Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 30 Apr 2015 14:04:41 +0200 Subject: Fix T44439: outliner's treestore could keep invalid ID pointers, could crash on undo due to invalid mem access. We cannot nuke treestore in readfile's `blo_lib_link_screen_restore()`, because this will destroy all UI-state data (like opened/closed items, etc.). Since we cannot know for sure whether an ID pointer from tselem->id is valid here, we have to ensure they are never invalid, i.e. to always set them to NULL when we delete them. To do so, this commit uses a similar approach as what already exists for ID references in WM notifiers - it extends `free_notifier_reference_cb()` to also nullify those IDs in all outliners. Note that some ID types are not used(shown) by outliner currently, so `TREESTORE_ID_TYPE` macro was added, that checks whether an ID is possibly used by outliner. Avoids a few searches in whole tree whene deleting some IDs. Reviewers: campbellbarton, sergey Maniphest Tasks: T44439 Differential Revision: https://developer.blender.org/D1272 --- source/blender/editors/include/ED_outliner.h | 36 ++++++++++++++++++++++ .../blender/editors/space_outliner/outliner_edit.c | 36 ++++++++++++++++++++++ .../editors/space_outliner/outliner_intern.h | 4 +++ .../blender/editors/space_outliner/outliner_tree.c | 5 +++ .../blender/windowmanager/intern/wm_event_system.c | 19 ++++++++++++ 5 files changed, 100 insertions(+) create mode 100644 source/blender/editors/include/ED_outliner.h diff --git a/source/blender/editors/include/ED_outliner.h b/source/blender/editors/include/ED_outliner.h new file mode 100644 index 00000000000..af4af8e2f5d --- /dev/null +++ b/source/blender/editors/include/ED_outliner.h @@ -0,0 +1,36 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015, Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ED_outliner.h + * \ingroup editors + */ + +#ifndef __ED_OUTLINER_H__ +#define __ED_OUTLINER_H__ + +struct ID; +struct SpaceOops; + +/* Used to check whether a given texture context is valid in current context. */ +void ED_outliner_id_unref(struct SpaceOops *so, const struct ID *id); + +#endif /* __ED_OUTLINER_H__ */ diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 798dae2cef3..058b8c4de5a 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -39,20 +39,24 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_mempool.h" #include "BLF_translation.h" #include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_depsgraph.h" +#include "BKE_global.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_outliner_treehash.h" #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_material.h" #include "BKE_group.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_screen.h" #include "ED_keyframing.h" @@ -1952,3 +1956,35 @@ void OUTLINER_OT_group_link(wmOperatorType *ot) /* properties */ RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object"); } + +/******** Utils to clear any ref to freed ID... **********/ + +void ED_outliner_id_unref(SpaceOops *so, const ID *id) +{ + /* Some early out checks. */ + if (!TREESTORE_ID_TYPE(id)) { + return; /* ID type is not used by outilner... */ + } + + if (so->search_tse.id == id) { + so->search_tse.id = NULL; + } + + if (so->treestore) { + TreeStoreElem *tselem; + BLI_mempool_iter iter; + bool changed = false; + + BLI_mempool_iternew(so->treestore, &iter); + while ((tselem = BLI_mempool_iterstep(&iter))) { + if (tselem->id == id) { + tselem->id = NULL; + changed = true; + } + } + if (so->treehash && changed) { + /* rebuild hash table, because it depends on ids too */ + BKE_outliner_treehash_rebuild_from_treestore(so->treehash, so->treestore); + } + } +} diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index b4b73a11a14..38672ef14dd 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -57,6 +57,10 @@ typedef struct TreeElement { PointerRNA rnaptr; // RNA Pointer } TreeElement; +#define TREESTORE_ID_TYPE(_id) \ + (ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \ + ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS)) + /* TreeElement->flag */ #define TE_ACTIVE 1 #define TE_ICONROW 2 diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 17a6e952ee1..4b07c400220 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -855,6 +855,11 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i return NULL; } + if (type == 0) { + /* Zero type means real ID, ensure we do not get non-outliner ID types here... */ + BLI_assert(TREESTORE_ID_TYPE(id)); + } + te = MEM_callocN(sizeof(TreeElement), "tree elem"); /* add to the visual tree */ BLI_addtail(lb, te); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index e2b8598b4fe..c883b37f6c5 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -63,6 +63,7 @@ #include "ED_fileselect.h" #include "ED_info.h" +#include "ED_outliner.h" #include "ED_screen.h" #include "ED_view3d.h" #include "ED_util.h" @@ -217,6 +218,8 @@ void WM_main_remove_notifier_reference(const void *reference) { Main *bmain = G.main; wmWindowManager *wm = bmain->wm.first; + bScreen *sc; + if (wm) { wmNotifier *note, *note_next; @@ -230,6 +233,22 @@ void WM_main_remove_notifier_reference(const void *reference) } } } + + for (sc = bmain->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_OUTLINER) { + SpaceOops *so = (SpaceOops *)sl; + + ED_outliner_id_unref(so, (ID *)reference); + } + } + } + } } static void wm_notifier_clear(wmNotifier *note) -- cgit v1.2.3 From 5dd63a977f358653ec8f06056b288d8bd59fd9e2 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 30 Apr 2015 15:06:10 +0200 Subject: Fix opengl rendering always looking through camera Actually check if we have a camera and looking through it before rendering in multiview. --- source/blender/editors/space_view3d/view3d_draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 7c403806f05..c5fccc8aded 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -3168,7 +3168,7 @@ void ED_view3d_draw_offscreen( } /* setup view matrices before fx or unbinding the offscreen buffers will cause issues */ - if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL)) + if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera) view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname); else view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat); -- cgit v1.2.3 From 69ef1a3a83f47dbcc25d05c8a87f73fbfcd0667d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 1 May 2015 00:57:12 +1000 Subject: Py/RNA: support to load and remove sounds --- source/blender/makesrna/intern/rna_main_api.c | 37 ++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 59c3befad9e..168f23ceaa1 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -61,6 +61,7 @@ #include "BKE_image.h" #include "BKE_texture.h" #include "BKE_scene.h" +#include "BKE_sound.h" #include "BKE_text.h" #include "BKE_action.h" #include "BKE_group.h" @@ -87,6 +88,7 @@ #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_speaker_types.h" +#include "DNA_sound_types.h" #include "DNA_text_types.h" #include "DNA_texture_types.h" #include "DNA_group_types.h" @@ -548,6 +550,25 @@ static void rna_Main_speakers_remove(Main *bmain, ReportList *reports, PointerRN } } +static bSound *rna_Main_sounds_load(Main *bmain, const char *name) +{ + bSound *sound = BKE_sound_new_file(bmain, name); + id_us_min(&sound->id); + return sound; +} +static void rna_Main_sounds_remove(Main *bmain, ReportList *reports, PointerRNA *sound_ptr) +{ + Speaker *sound = sound_ptr->data; + if (ID_REAL_USERS(sound) <= 0) { + BKE_libblock_free(bmain, sound); + RNA_POINTER_INVALIDATE(sound_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Sound '%s' must have zero users to be removed, found %d", + sound->id.name + 2, ID_REAL_USERS(sound)); + } +} + static Text *rna_Main_texts_new(Main *bmain, const char *name) { return BKE_text_add(bmain, name); @@ -1585,7 +1606,21 @@ void RNA_def_main_sounds(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_struct_sdna(srna, "Main"); RNA_def_struct_ui_text(srna, "Main Sounds", "Collection of sounds"); - /* TODO, 'load' */ + /* load func */ + func = RNA_def_function(srna, "load", "rna_Main_sounds_load"); + RNA_def_function_ui_description(func, "Add a new sound to the main database from a file"); + parm = RNA_def_string_file_path(func, "filepath", "Path", FILE_MAX, "", "path for the datablock"); + RNA_def_property_flag(parm, PROP_REQUIRED); + /* return type */ + parm = RNA_def_pointer(func, "sound", "Sound", "", "New text datablock"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_Main_sounds_remove"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Remove a sound from the current blendfile"); + parm = RNA_def_pointer(func, "sound", "Sound", "", "Sound to remove"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_sounds_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); -- cgit v1.2.3 From 179fff94e8a1977af95fe30f98f1a2b81699089a Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 30 Apr 2015 10:22:47 -0300 Subject: Revert "Fix T44556: Crash on the World Properties > Preview" This reverts commit 4bcc7a2ec6bf6937778a2227c7f938c50a0fafe5. --- source/blender/editors/render/render_preview.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index b9aa6ac6e72..2c353c13334 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -532,7 +532,6 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, int newx = BLI_rcti_size_x(rect); int newy = BLI_rcti_size_y(rect); bool ok = false; - bool has_rectf = false; if (!split || first) sprintf(name, "Preview %p", (void *)sa); else sprintf(name, "SecondPreview %p", (void *)sa); @@ -552,14 +551,11 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, re = RE_GetRender(name); RE_AcquireResultImageViews(re, &rres); - /* TODO(sergey): Is there a cleaner way to do this? */ - if (!BLI_listbase_is_empty(&rres.views)) { - /* material preview only needs monoscopy (view 0) */ - rv = RE_RenderViewGetById(&rres, 0); - has_rectf = rv->rectf != NULL; - } - if (has_rectf) { + /* material preview only needs monoscopy (view 0) */ + rv = RE_RenderViewGetById(&rres, 0); + + if (rv->rectf) { if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) { -- cgit v1.2.3 From 078e589263df3aa815052196e4d87ff97e156086 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 30 Apr 2015 12:11:48 -0300 Subject: Better fix for T44556: Crash on the World Properties > Preview --- source/blender/editors/render/render_preview.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 2c353c13334..5534073c290 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -550,6 +550,9 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, /* test if something rendered ok */ re = RE_GetRender(name); + if (re == NULL) + return; + RE_AcquireResultImageViews(re, &rres); /* material preview only needs monoscopy (view 0) */ -- cgit v1.2.3 From 3a9726783f388b13b29510089affa9b9d85b0a22 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 1 May 2015 01:03:55 +1000 Subject: RNA defaults test Alternative to T32894, simple test which creates new data and compares with RNA defaults. Can be used to keep the values in sync without having to maintain a large set of defines. --- tests/python/bl_rna_defaults.py | 117 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 tests/python/bl_rna_defaults.py diff --git a/tests/python/bl_rna_defaults.py b/tests/python/bl_rna_defaults.py new file mode 100644 index 00000000000..1d6f82b06c2 --- /dev/null +++ b/tests/python/bl_rna_defaults.py @@ -0,0 +1,117 @@ +# Apache License, Version 2.0 + +# ./blender.bin --background -noaudio --factory-startup --python tests/python/bl_rna_defaults.py + +import bpy + +DUMMY_NAME = "Untitled" +DUMMY_PATH = __file__ +GLOBALS = { + "error_num": 0, + } + + +def validate_defaults(test_id, o): + + def warning(prop_id, val_real, val_default): + print("Error %s: '%s.%s' is:%r, expected:%r" % + (test_id, o.__class__.__name__, prop_id, val_real, val_default)) + GLOBALS["error_num"] += 1 + + properties = type(o).bl_rna.properties.items() + for prop_id, prop in properties: + if prop_id == "rna_type": + continue + prop_type = prop.type + if prop_type in {'STRING', 'COLLECTION'}: + continue + + if prop_type == 'POINTER': + # traverse down pointers if they're set + val_real = getattr(o, prop_id) + if (val_real is not None) and (not isinstance(val_real, bpy.types.ID)): + validate_defaults("%s.%s" % (test_id, prop_id), val_real) + elif prop_type in {'INT', 'BOOL'}: + array_length = prop.array_length + if array_length == 0: + val_real = getattr(o, prop_id) + val_default = prop.default + if val_real != val_default: + warning(prop_id, val_real, val_default) + else: + pass # TODO, array defaults + elif prop_type == 'FLOAT': + array_length = prop.array_length + if array_length == 0: + val_real = getattr(o, prop_id) + val_default = prop.default + if val_real != val_default: + warning(prop_id, val_real, val_default) + else: + pass # TODO, array defaults + elif prop_type == 'ENUM': + val_real = getattr(o, prop_id) + if prop.is_enum_flag: + val_default = prop.default_flag + else: + val_default = prop.default + if val_real != val_default: + warning(prop_id, val_real, val_default) + + # print(prop_id, prop_type) + + +def _test_id_gen(data_attr, args_create=(DUMMY_NAME,), create_method="new"): + def test_gen(test_id): + id_collection = getattr(bpy.data, data_attr) + create_fn = getattr(id_collection, create_method) + o = create_fn(*args_create) + o.user_clear() + validate_defaults(test_id, o) + id_collection.remove(o) + return test_gen + + +test_Action = _test_id_gen("actions") +test_Armature = _test_id_gen("armatures") +test_Camera = _test_id_gen("cameras") +test_Group = _test_id_gen("groups") +test_Lattice = _test_id_gen("lattices") +test_LineStyle = _test_id_gen("linestyles") +test_Mask = _test_id_gen("masks") +test_Material = _test_id_gen("materials") +test_Mesh = _test_id_gen("meshes") +test_MetaBall = _test_id_gen("metaballs") +test_MovieClip = _test_id_gen("movieclips", args_create=(DUMMY_PATH,), create_method="load") +test_Object = _test_id_gen("objects", args_create=(DUMMY_NAME, None)) +test_Palette = _test_id_gen("palettes") +test_Particle = _test_id_gen("particles") +test_Scene = _test_id_gen("scenes") +test_Sound = _test_id_gen("sounds", args_create=(DUMMY_PATH,), create_method="load") +test_Speaker = _test_id_gen("speakers") +test_Text = _test_id_gen("texts") +test_VectorFont = _test_id_gen("fonts", args_create=("",), create_method="load") +test_World = _test_id_gen("worlds") + +ns = globals() +for t in bpy.data.curves.bl_rna.functions["new"].parameters["type"].enum_items.keys(): + ns["test_Curve_%s" % t] = _test_id_gen("curves", args_create=(DUMMY_NAME, t)) +for t in bpy.data.lamps.bl_rna.functions["new"].parameters["type"].enum_items.keys(): + ns["test_Lamp_%s" % t] = _test_id_gen("lamps", args_create=(DUMMY_NAME, t)) +# types are a dynamic enum, have to hard-code. +for t in "ShaderNodeTree", "CompositorNodeTree", "TextureNodeTree": + ns["test_NodeGroup_%s" % t] = _test_id_gen("node_groups", args_create=(DUMMY_NAME, t)) +for t in bpy.data.textures.bl_rna.functions["new"].parameters["type"].enum_items.keys(): + ns["test_Texture_%s" % t] = _test_id_gen("textures", args_create=(DUMMY_NAME, t)) +del ns + + +def main(): + for fn_id, fn_val in sorted(globals().items()): + if fn_id.startswith("test_") and callable(fn_val): + fn_val(fn_id) + + print("Error (total): %d" % GLOBALS["error_num"]) + +if __name__ == "__main__": + main() -- cgit v1.2.3 From 5ced6cb2bc52a50365e4bc4003994c39cdcb895f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 1 May 2015 01:36:36 +1000 Subject: Correct warning --- source/blender/editors/render/render_preview.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 5534073c290..65d4c2301a9 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -551,7 +551,7 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, re = RE_GetRender(name); if (re == NULL) - return; + return false; RE_AcquireResultImageViews(re, &rres); -- cgit v1.2.3 From 4d6584ba6a22d4c06cb5e5ecce38dded1247da3f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 1 May 2015 01:49:58 +1000 Subject: UI: use enum for thumbnail size --- release/scripts/startup/bl_ui/space_filebrowser.py | 2 +- source/blender/blenloader/intern/versioning_270.c | 4 ++-- source/blender/editors/space_file/filesel.c | 6 +++--- source/blender/makesdna/DNA_space_types.h | 3 ++- source/blender/makesrna/intern/rna_space.c | 14 +++++++++++--- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py index 5da660fcb5f..bcf0495d00f 100644 --- a/release/scripts/startup/bl_ui/space_filebrowser.py +++ b/release/scripts/startup/bl_ui/space_filebrowser.py @@ -55,7 +55,7 @@ class FILEBROWSER_HT_header(Header): layout.prop(params, "display_type", expand=True, text="") if params.display_type == 'FILE_IMGDISPLAY': - layout.prop(params, "thumbnails_size") + layout.prop(params, "thumbnail_size", text="") layout.prop(params, "sort_method", expand=True, text="") diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 2343ba06e75..4daf93916c9 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -803,7 +803,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) if (!MAIN_VERSION_ATLEAST(main, 274, 6)) { bScreen *screen; - if (!DNA_struct_elem_find(fd->filesdna, "FileSelectParams", "int", "thumbnails_size")) { + if (!DNA_struct_elem_find(fd->filesdna, "FileSelectParams", "int", "thumbnail_size")) { for (screen = main->screen.first; screen; screen = screen->id.next) { ScrArea *sa; @@ -815,7 +815,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) SpaceFile *sfile = (SpaceFile *)sl; if (sfile->params) { - sfile->params->thumbnails_size = 128; + sfile->params->thumbnail_size = 128; } } } diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index d89e55cb55f..82409c9ecb4 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -103,7 +103,7 @@ short ED_fileselect_set_params(SpaceFile *sfile) BLI_split_dirfile(G.main->name, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file)); sfile->params->filter_glob[0] = '\0'; /* set the default thumbnails size */ - sfile->params->thumbnails_size = 128; + sfile->params->thumbnail_size = 128; } params = sfile->params; @@ -529,8 +529,8 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar) layout->textheight = textheight; if (params->display == FILE_IMGDISPLAY) { - layout->prv_w = ((float)params->thumbnails_size / 20.0f) * UI_UNIT_X; - layout->prv_h = ((float)params->thumbnails_size / 20.0f) * UI_UNIT_Y; + layout->prv_w = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_X; + layout->prv_h = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_Y; layout->tile_border_x = 0.3f * UI_UNIT_X; layout->tile_border_y = 0.3f * UI_UNIT_X; layout->prv_border_x = 0.3f * UI_UNIT_X; diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 78121035371..075995c2924 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -590,7 +590,8 @@ typedef struct FileSelectParams { int active_file; int sel_first; int sel_last; - int thumbnails_size; + unsigned short thumbnail_size; + short pad; /* short */ short type; /* XXXXX for now store type here, should be moved to the operator */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 4f54a6f07dc..b02c69c54ef 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -3698,6 +3698,14 @@ static void rna_def_fileselect_params(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem thumbnail_size_items[] = { + {32, "TINY", 0, "Tiny", ""}, + {64, "SMALL", 0, "Small", ""}, + {128, "NORMAL", 0, "Normal", ""}, + {256, "LARGE", 0, "Large", ""}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "FileSelectParams", NULL); RNA_def_struct_ui_text(srna, "File Select Parameters", "File Select Parameters"); @@ -3803,9 +3811,9 @@ static void rna_def_fileselect_params(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL); - prop = RNA_def_property(srna, "thumbnails_size", PROP_INT, PROP_PIXEL); - RNA_def_property_int_sdna(prop, NULL, "thumbnails_size"); - RNA_def_property_range(prop, 32, 256); + prop = RNA_def_property(srna, "thumbnail_size", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "thumbnail_size"); + RNA_def_property_enum_items(prop, thumbnail_size_items); RNA_def_property_ui_text(prop, "Thumbnails Size", "Change the size of the thumbnails"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } -- cgit v1.2.3 From cdabf7e3535fe5c88f9e475459210e5121bc58f7 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 30 Apr 2015 20:58:34 +0200 Subject: Data transfer - Loop Islands Hell Fixes. This commit fixes several issues: * island_store->items_to_islands_num was reset each time we added a new island, this is stupid! Harmless too, though, afaikt. * partial verts bvhtree (with several islands) was hugely over-allocated... * we would 'leak' in neighbor islands when geometry itself was contiguous. * best_nor_dot was used incorrectly, leading to smaller weights for better matching normal! All those fixes are related to T44522 (through personal communications with reporter). --- source/blender/blenkernel/intern/mesh_mapping.c | 1 - source/blender/blenkernel/intern/mesh_remap.c | 28 +++++++++++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index 37b4c5fcf8f..e4a85eb399b 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -687,7 +687,6 @@ void BKE_mesh_loop_islands_add( const size_t curr_num_islands = (size_t)island_store->islands_num; int i = item_num; - island_store->items_to_islands_num = item_num; while (i--) { island_store->items_to_islands[items_indices[i]] = curr_island_idx; } diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c index 94fe9f993d3..f3e2f395002 100644 --- a/source/blender/blenkernel/intern/mesh_remap.c +++ b/source/blender/blenkernel/intern/mesh_remap.c @@ -1163,8 +1163,11 @@ void BKE_mesh_remap_calc_loops_from_dm( for (i = 0; i < isld->count; i++) { mp_src = &polys_src[isld->indices[i]]; for (lidx_src = mp_src->loopstart; lidx_src < mp_src->loopstart + mp_src->totloop; lidx_src++) { - BLI_BITMAP_ENABLE(verts_active, loops_src[lidx_src].v); - num_verts_active++; + const unsigned int vidx_src = loops_src[lidx_src].v; + if (!BLI_BITMAP_TEST(verts_active, vidx_src)) { + BLI_BITMAP_ENABLE(verts_active, loops_src[lidx_src].v); + num_verts_active++; + } } } /* verts 'ownership' is transfered to treedata here, which will handle its freeing. */ @@ -1211,7 +1214,7 @@ void BKE_mesh_remap_calc_loops_from_dm( num_faces_active++; } } - /* verts 'ownership' is transfered to treedata here, which will handle its freeing. */ + /* verts and faces 'ownership' is transfered to treedata here, which will handle its freeing. */ bvhtree_from_mesh_faces_ex( &treedata[tindex], verts_src, verts_allocated_src, faces_src, num_faces_src, faces_allocated_src, @@ -1291,14 +1294,26 @@ void BKE_mesh_remap_calc_loops_from_dm( const int index_src = vert_to_refelem_map_src[nearest.index].indices[i]; const float dot = dot_v3v3(nors_src[index_src], *nor_dst); + pidx_src = (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) ? + loop_to_poly_map_src[index_src] : index_src; + /* WARNING! This is not the *real* lidx_src in case of POLYNOR, we only use it + * to check we stay on current island (all loops from a given poly are + * on same island!). */ + lidx_src = (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) ? + index_src : polys_src[pidx_src].loopstart; + + /* A same vert may be at the boundary of several islands! Hence, we have to ensure + * poly/loop we are currently considering *belongs* to current island! */ + if (island_store.items_to_islands[lidx_src] != tindex) { + continue; + } + if (dot > best_nor_dot - 1e-6f) { /* We need something as fallback decision in case dest normal matches several * source normals (see T44522), using distance between polys' centers here. */ float *pcent_src; float sqdist; - pidx_src = (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) ? - loop_to_poly_map_src[index_src] : index_src; mp_src = &polys_src[pidx_src]; ml_src = &loops_src[mp_src->loopstart]; @@ -1329,7 +1344,8 @@ void BKE_mesh_remap_calc_loops_from_dm( } } } - islands_res[tindex][plidx_dst].factor = hit_dist ? (1.0f / (hit_dist * best_nor_dot)) : 1e18f; + best_nor_dot = (best_nor_dot + 1.0f) * 0.5f; + islands_res[tindex][plidx_dst].factor = hit_dist ? (1.0f / hit_dist * best_nor_dot) : 1e18f; islands_res[tindex][plidx_dst].hit_dist = hit_dist; islands_res[tindex][plidx_dst].index_src = best_index_src; } -- cgit v1.2.3 From a8221060624f576be015ac3be02a245c6a36e5ee Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 1 May 2015 05:45:41 +1000 Subject: Cleanup: typos --- source/blender/editors/space_clip/space_clip.c | 2 +- source/blender/editors/space_clip/tracking_ops.c | 2 +- source/blender/editors/space_clip/tracking_select.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index fc2c0d3d45c..5ba82f7f71f 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -206,7 +206,7 @@ static void clip_scopes_tag_refresh(ScrArea *sa) if (sc->mode != SC_MODE_TRACKING) return; - /* only while proeprties are visible */ + /* only while properties are visible */ for (ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->regiontype == RGN_TYPE_UI && ar->flag & RGN_FLAG_HIDDEN) return; diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 21d74638ec3..538c1a4e5ea 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1879,7 +1879,7 @@ void CLIP_OT_clear_track_path(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* proeprties */ + /* properties */ RNA_def_enum(ot->srna, "action", clear_path_actions, TRACK_CLEAR_REMAINED, "Action", "Clear action to execute"); RNA_def_boolean(ot->srna, "clear_active", 0, "Clear Active", "Clear active track only instead of all selected tracks"); } diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c index 0b29c253f3a..8a2bf17c667 100644 --- a/source/blender/editors/space_clip/tracking_select.c +++ b/source/blender/editors/space_clip/tracking_select.c @@ -997,6 +997,6 @@ void CLIP_OT_select_grouped(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* proeprties */ + /* properties */ RNA_def_enum(ot->srna, "group", select_group_items, TRACK_CLEAR_REMAINED, "Action", "Clear action to execute"); } -- cgit v1.2.3 From 6111da36297dd9d40878c5805dac4b7659ee6ecd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 1 May 2015 06:18:04 +1000 Subject: BMesh: add bmesh_disk_vert_replace --- source/blender/bmesh/intern/bmesh_core.c | 21 ++++----------------- source/blender/bmesh/intern/bmesh_structure.c | 12 +++++++++--- source/blender/bmesh/intern/bmesh_structure.h | 1 + 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 81cc9727965..87f700ac731 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1508,14 +1508,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) bmesh_disk_edge_remove(e_new, tv); bmesh_disk_edge_remove(e_new, v_new); - /* remove e from tv's disk cycle */ - bmesh_disk_edge_remove(e, tv); - - /* swap out tv for v_new in e */ - bmesh_disk_vert_swap(e, v_new, tv); - - /* add e to v_new's disk cycle */ - bmesh_disk_edge_append(e, v_new); + bmesh_disk_vert_replace(e, v_new, tv); /* add e_new to v_new's disk cycle */ bmesh_disk_edge_append(e_new, v_new); @@ -1726,12 +1719,8 @@ BMEdge *bmesh_jekv( e_splice = BM_edge_exists(tv, v_old); } - /* remove e_old from v_kill's disk cycle */ - bmesh_disk_edge_remove(e_old, v_kill); - /* relink e_old->v_kill to be e_old->tv */ - bmesh_disk_vert_swap(e_old, tv, v_kill); - /* append e_old to tv's disk cycle */ - bmesh_disk_edge_append(e_old, tv); + bmesh_disk_vert_replace(e_old, tv, v_kill); + /* remove e_kill from tv's disk cycle */ bmesh_disk_edge_remove(e_kill, tv); @@ -2471,9 +2460,7 @@ BMVert *bmesh_urmv_loop_multi( } else { /* we own the edge entirely, replace the vert */ - bmesh_disk_edge_remove(e, v_sep); - bmesh_disk_vert_swap(e, v_new, v_sep); - bmesh_disk_edge_append(e, v_new); + bmesh_disk_vert_replace(e, v_new, v_sep); } /* loop vert is handled last! */ diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c index 30ab693beb7..5bc36cefad2 100644 --- a/source/blender/bmesh/intern/bmesh_structure.c +++ b/source/blender/bmesh/intern/bmesh_structure.c @@ -74,10 +74,15 @@ void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) } /* swap out edges */ + bmesh_disk_vert_replace(e, v_dst, v_src); +} + +void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src) +{ BLI_assert(e->v1 == v_src || e->v2 == v_src); - bmesh_disk_edge_remove(e, v_src); - bmesh_disk_vert_swap(e, v_dst, v_src); - bmesh_disk_edge_append(e, v_dst); + bmesh_disk_edge_remove(e, v_src); /* remove e from tv's disk cycle */ + bmesh_disk_vert_swap(e, v_dst, v_src); /* swap out tv for v_new in e */ + bmesh_disk_edge_append(e, v_dst); /* add e to v_dst's disk cycle */ BLI_assert(e->v1 != e->v2); } @@ -114,6 +119,7 @@ void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) * the disk cycle has no problems dealing with non-manifold conditions involving faces. * * Functions relating to this cycle: + * - #bmesh_disk_vert_replace * - #bmesh_disk_edge_append * - #bmesh_disk_edge_remove * - #bmesh_disk_edge_next diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h index 9d9fb7f2c68..07f94796bb2 100644 --- a/source/blender/bmesh/intern/bmesh_structure.h +++ b/source/blender/bmesh/intern/bmesh_structure.h @@ -72,6 +72,7 @@ bool bmesh_radial_validate(int radlen, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATT /* EDGE UTILITIES */ void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL(); void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL(); +void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL(); BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -- cgit v1.2.3 From f8bdd8e6a8ea5bef16789c5d61cbb9f4ff239945 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 1 May 2015 06:51:16 +1000 Subject: BMesh: correct bmesh_edge_vert_swap Missed swapping out loops. --- source/blender/bmesh/intern/bmesh_structure.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c index 5bc36cefad2..cb302139a4c 100644 --- a/source/blender/bmesh/intern/bmesh_structure.c +++ b/source/blender/bmesh/intern/bmesh_structure.c @@ -70,6 +70,12 @@ void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) if (l_iter->v == v_src) { l_iter->v = v_dst; } + else if (l_iter->next->v == v_src) { + l_iter->next->v = v_dst; + } + else { + BLI_assert(l_iter->prev->v != v_src); + } } while ((l_iter = l_iter->radial_next) != l_first); } -- cgit v1.2.3 From be0dcd4e3429dcbaaf4f2884695e883438fd0b95 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 1 May 2015 12:42:10 +1200 Subject: Fix T43867: Clicking outside the viewport exits now Grease Pencil "Continous Draw" mode When working with a pen only, it was previously impossible to exit Grease Pencil draw mode (when continous drawing was enabled). Now, clicking outside the drawing region (e.g. in the timeline, properties editor, or the header/properties/toolshelf regions) where you are drawing will exit this mode. Some corner cases to be aware of: * When Region Overlap is enabled, clicking on the overlapping panels still exits draw mode (even though you can see behind the buttons) * In the Nodes Editor, clicking on a node (while in drawmode) will still draw a dot/stroke. But, you can still exit drawmode by clicking on any of the panels (properties/toolshelf/header) mentioned earlier * To cope with cases where the operator is launched from the toolshelf, the code now sets a new "active region" when the first stroke is performed (based on what region is under the cursor at the time of that stroke), overwriting the setting that got stored when invoking the operator (i.e. the toolshelf). This change doesn't have any real user-visible effects, other than making it possible for this fix to actually work without breaking that use case. --- source/blender/editors/gpencil/gpencil_paint.c | 88 +++++++++++++++++++++----- 1 file changed, 73 insertions(+), 15 deletions(-) diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 778f98d212e..bcce5cc8fab 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -48,6 +48,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_report.h" +#include "BKE_screen.h" #include "BKE_tracking.h" #include "DNA_object_types.h" @@ -1030,6 +1031,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) /* set current area * - must verify that region data is 3D-view (and not something else) */ + /* CAUTION: If this is the "toolbar", then this will change on the first stroke */ p->sa = curarea; p->ar = ar; @@ -1938,25 +1940,81 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else if (event->val == KM_PRESS) { - /* Switch paintmode (temporarily if need be) based on which button was used - * NOTE: This is to make it more convenient to erase strokes when using drawing sessions + bool in_bounds = false; + + /* Check if we're outside the bounds of the active region + * NOTE: An exception here is that if launched from the toolbar, + * whatever region we're now in should become the new region */ - if (event->type == LEFTMOUSE) { - /* restore drawmode to default */ - p->paintmode = RNA_enum_get(op->ptr, "mode"); + if ((p->ar) && (p->ar->regiontype == RGN_TYPE_TOOLS)) { + /* Change to whatever region is now under the mouse */ + ARegion *current_region = BKE_area_find_region_xy(p->sa, RGN_TYPE_ANY, event->x, event->y); + + printf("found alternative region %p (old was %p) - at %d %d (sa: %d %d -> %d %d)\n", + current_region, p->ar, event->x, event->y, + p->sa->totrct.xmin, p->sa->totrct.ymin, p->sa->totrct.xmax, p->sa->totrct.ymax); + + if (current_region) { + /* Assume that since we found the cursor in here, it is in bounds + * and that this should be the region that we begin drawing in + */ + p->ar = current_region; + in_bounds = true; + } + else { + /* Out of bounds, or invalid in some other way */ + p->status = GP_STATUS_ERROR; + estate = OPERATOR_CANCELLED; + + if (G.debug & G_DEBUG) + printf("%s: Region under cursor is out of bounds, so cannot be drawn on\n", __func__); + } } - else if (event->type == RIGHTMOUSE) { - /* turn on eraser */ - p->paintmode = GP_PAINTMODE_ERASER; + else if (p->ar) { + rcti region_rect; + + /* Perform bounds check using */ + ED_region_visible_rect(p->ar, ®ion_rect); + in_bounds = BLI_rcti_isect_pt_v(®ion_rect, event->mval); } - - gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER); - - /* not painting, so start stroke (this should be mouse-button down) */ - p = gpencil_stroke_begin(C, op); - - if (p->status == GP_STATUS_ERROR) { + else { + /* No region */ + p->status = GP_STATUS_ERROR; estate = OPERATOR_CANCELLED; + + if (G.debug & G_DEBUG) + printf("%s: No active region found in GP Paint session data\n", __func__); + } + + if (in_bounds) { + /* Switch paintmode (temporarily if need be) based on which button was used + * NOTE: This is to make it more convenient to erase strokes when using drawing sessions + */ + if (event->type == LEFTMOUSE) { + /* restore drawmode to default */ + p->paintmode = RNA_enum_get(op->ptr, "mode"); + } + else if (event->type == RIGHTMOUSE) { + /* turn on eraser */ + p->paintmode = GP_PAINTMODE_ERASER; + } + + gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER); + + /* not painting, so start stroke (this should be mouse-button down) */ + p = gpencil_stroke_begin(C, op); + + if (p->status == GP_STATUS_ERROR) { + estate = OPERATOR_CANCELLED; + } + } + else if (p->status != GP_STATUS_ERROR) { + /* User clicked outside bounds of window while idling, so exit paintmode + * NOTE: Don't eter this case if an error occurred while finding the + * region (as above) + */ + p->status = GP_STATUS_DONE; + estate = OPERATOR_FINISHED; } } else { -- cgit v1.2.3 From 94d80c8ca4739ff8bbc406157812b52a74286370 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 1 May 2015 12:42:40 +1200 Subject: Left some debug prints in here... --- source/blender/editors/gpencil/gpencil_paint.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index bcce5cc8fab..767ef7d16d7 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1950,9 +1950,11 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* Change to whatever region is now under the mouse */ ARegion *current_region = BKE_area_find_region_xy(p->sa, RGN_TYPE_ANY, event->x, event->y); - printf("found alternative region %p (old was %p) - at %d %d (sa: %d %d -> %d %d)\n", - current_region, p->ar, event->x, event->y, - p->sa->totrct.xmin, p->sa->totrct.ymin, p->sa->totrct.xmax, p->sa->totrct.ymax); + if (G.debug & G_DEBUG) { + printf("found alternative region %p (old was %p) - at %d %d (sa: %d %d -> %d %d)\n", + current_region, p->ar, event->x, event->y, + p->sa->totrct.xmin, p->sa->totrct.ymin, p->sa->totrct.xmax, p->sa->totrct.ymax); + } if (current_region) { /* Assume that since we found the cursor in here, it is in bounds -- cgit v1.2.3 From 28ea3f5b94175edcfd27612cf56d69106879d9a4 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 1 May 2015 12:06:05 +0200 Subject: Fix T44565 World background artifacts when world shader is void (or compilation fails). --- source/blender/editors/space_view3d/view3d_draw.c | 24 +++++++++++++++++++++-- source/blender/gpu/GPU_material.h | 2 +- source/blender/gpu/intern/gpu_material.c | 4 ++-- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index c5fccc8aded..da628c32341 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2940,21 +2940,41 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar) if (glsl) { RegionView3D *rv3d = ar->regiondata; GPUMaterial *gpumat = GPU_material_world(scene, scene->world); + bool material_not_bound; /* calculate full shader for background */ GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0)); + material_not_bound = !GPU_material_bound(gpumat); + + if (material_not_bound) { + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + } + glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); glShadeModel(GL_SMOOTH); - glBegin(GL_QUADS); + glBegin(GL_TRIANGLE_STRIP); glVertex3f(-1.0, -1.0, 1.0); glVertex3f(1.0, -1.0, 1.0); - glVertex3f(1.0, 1.0, 1.0); glVertex3f(-1.0, 1.0, 1.0); + glVertex3f(1.0, 1.0, 1.0); glEnd(); glShadeModel(GL_FLAT); + if (material_not_bound) { + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + } + GPU_material_unbind(gpumat); glDepthFunc(GL_LEQUAL); diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index b61bdf969cc..7bb044a1ae3 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -186,7 +186,7 @@ bool GPU_lamp_override_visible(GPULamp *lamp, struct SceneRenderLayer *srl, stru void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock); void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale); void GPU_material_unbind(GPUMaterial *material); -int GPU_material_bound(GPUMaterial *material); +bool GPU_material_bound(GPUMaterial *material); struct Scene *GPU_material_scene(GPUMaterial *material); GPUMatType GPU_Material_get_type(GPUMaterial *material); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 4d46ef3af7b..12672b5f5af 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -102,7 +102,6 @@ struct GPUMaterial { /* for binding the material */ GPUPass *pass; GPUVertexAttribs attribs; - int bound; int builtins; int alpha, obcolalpha; int dynproperty; @@ -114,6 +113,7 @@ struct GPUMaterial { int cameratexcofacloc; ListBase lamps; + bool bound; }; struct GPULamp { @@ -400,7 +400,7 @@ void GPU_material_unbind(GPUMaterial *material) } } -int GPU_material_bound(GPUMaterial *material) +bool GPU_material_bound(GPUMaterial *material) { return material->bound; } -- cgit v1.2.3 From 535e75ea90f31d1d231e39dfdb14634563484679 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 1 May 2015 14:27:44 +0200 Subject: Use mono font for metadata --- source/blender/editors/screen/area.c | 49 ++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 4518aad1a5c..0bd05b8c9e8 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2088,7 +2088,7 @@ BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index, int off return (IMB_metadata_get_field(ibuf, meta_data_list[index], r_str + offset, MAX_METADATA_STR - offset) && r_str[0]); } -static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool is_top, float factor) +static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool is_top) { char temp_str[MAX_METADATA_STR]; int line_width; @@ -2096,6 +2096,7 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i short i; int len; const float height = BLF_height_max(fontid); + const float vertical_offset = height + (0.1f * U.widget_unit); if (is_top) { for (i = 0; i < 4; i++) { @@ -2105,7 +2106,7 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]); if (metadata_is_valid(ibuf, temp_str, 0, len)) { BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit), - rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y), 0.0f); + rect.ymax - vertical_offset, 0.0f); BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); do_newline = true; } @@ -2114,21 +2115,21 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i if (metadata_is_valid(ibuf, temp_str, 1, len)) { line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); BLF_position(fontid, rect.xmax - line_width - (0.2f * U.widget_unit), - rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y), 0.0f); + rect.ymax - vertical_offset, 0.0f); BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); do_newline = true; } if (do_newline) - ofs_y += (height + (0.2f * U.widget_unit)); + ofs_y += vertical_offset; } else if (i == 1) { len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]); if (metadata_is_valid(ibuf, temp_str, i + 1, len)) { BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit), - rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y) - ofs_y, 0.0f); + rect.ymax - vertical_offset - ofs_y, 0.0f); BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); - ofs_y += (height + (0.2f * U.widget_unit)); + ofs_y += vertical_offset; } } else { @@ -2136,9 +2137,9 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i if (metadata_is_valid(ibuf, temp_str, i + 1, len)) { line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); BLF_position(fontid, rect.xmax - line_width - (0.2f * U.widget_unit), - rect.ymax - factor * (1.5f * U.widget_unit - UI_UNIT_Y) - ofs_y, 0.0f); + rect.ymax - vertical_offset - ofs_y, 0.0f); BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); - ofs_y += (height + (0.2f * U.widget_unit)); + ofs_y += vertical_offset; } } } @@ -2148,9 +2149,8 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool i for (i = 5; i < 10; i++) { len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i]); if (metadata_is_valid(ibuf, temp_str, i, len)) { - const int line_height = height; BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit) + ofs_x, - rect.ymin - line_height + factor * (U.widget_unit), 0.0f); + rect.ymin + (0.3f * U.widget_unit), 0.0f); BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); ofs_x += BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX) + UI_UNIT_X; @@ -2163,7 +2163,7 @@ static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top) { char str[MAX_METADATA_STR]; short i, count = 0; - const float height = BLF_height_max(fontid) + 0.2f * U.widget_unit; + const float height = BLF_height_max(fontid) + 0.1f * U.widget_unit; if (is_top) { if (metadata_is_valid(ibuf, str, 0, 0) || metadata_is_valid(ibuf, str, 1, 0)) { @@ -2184,7 +2184,7 @@ static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top) } if (count) { - return (height * count + (0.2f * U.widget_unit)); + return (height * count + (0.1f * U.widget_unit)); } return 0; @@ -2194,11 +2194,10 @@ static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top) void ED_region_image_metadata_draw(ARegion *ar, ImBuf *ibuf, float zoomx, float zoomy) { - uiStyle *style = UI_style_get_dpi(); - int fontid = style->widget.uifont_id; float box_y; rcti rect; int x, y; + uiStyle *style = UI_style_get_dpi(); if (!ibuf->metadata) return; @@ -2212,12 +2211,12 @@ void ED_region_image_metadata_draw(ARegion *ar, ImBuf *ibuf, float zoomx, float glTranslatef(x, y, 0.0f); glScalef(zoomx, zoomy, 1.0f); - BLF_size(fontid, style->widgetlabel.points, U.dpi * zoomy); + BLF_size(blf_mono_font, style->widgetlabel.points * zoomy * 1.5f, U.dpi); /* *** upper box*** */ /* get needed box height */ - box_y = metadata_box_height_get(ibuf, fontid, true); + box_y = metadata_box_height_get(ibuf, blf_mono_font, true); if (box_y) { UI_ThemeColor(TH_METADATA_BG); @@ -2227,19 +2226,19 @@ void ED_region_image_metadata_draw(ARegion *ar, ImBuf *ibuf, float zoomx, float /* draw top box */ glRecti(rect.xmin, rect.ymin, rect.xmax, rect.ymax); - BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - BLF_enable(fontid, BLF_CLIPPING); + BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + BLF_enable(blf_mono_font, BLF_CLIPPING); UI_ThemeColor(TH_METADATA_TEXT); - metadata_draw_imbuf(ibuf, rect, fontid, true, zoomy); + metadata_draw_imbuf(ibuf, rect, blf_mono_font, true); - BLF_disable(fontid, BLF_CLIPPING); + BLF_disable(blf_mono_font, BLF_CLIPPING); } /* *** lower box*** */ - box_y = metadata_box_height_get(ibuf, fontid, false); + box_y = metadata_box_height_get(ibuf, blf_mono_font, false); if (box_y) { UI_ThemeColor(TH_METADATA_BG); @@ -2249,13 +2248,13 @@ void ED_region_image_metadata_draw(ARegion *ar, ImBuf *ibuf, float zoomx, float /* draw top box */ glRecti(rect.xmin, rect.ymin, rect.xmax, rect.ymax); - BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - BLF_enable(fontid, BLF_CLIPPING); + BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + BLF_enable(blf_mono_font, BLF_CLIPPING); UI_ThemeColor(TH_METADATA_TEXT); - metadata_draw_imbuf(ibuf, rect, fontid, false, zoomy); + metadata_draw_imbuf(ibuf, rect, blf_mono_font, false); - BLF_disable(fontid, BLF_CLIPPING); + BLF_disable(blf_mono_font, BLF_CLIPPING); } glPopMatrix(); -- cgit v1.2.3 From f84135ee655fa38b0a1347ef1e3139d938790a65 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 1 May 2015 16:11:55 +0200 Subject: Fix T44577: writing tessellated cddata when we should not... Own mistake in rBf75c89b3f42ffac51603e6e53459f9d94a8782cc... --- source/blender/blenloader/intern/writefile.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 39096abf5fa..285c50a4049 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2008,7 +2008,9 @@ static void write_meshes(WriteData *wd, ListBase *idbase) * If we do not do that, we can get crash by buffer-overflow on reading, see T44461. */ CustomData_copy(&old_mesh->vdata, &mesh->vdata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totvert); CustomData_copy(&old_mesh->edata, &mesh->edata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totedge); +#ifndef USE_BMESH_SAVE_WITHOUT_MFACE /* Do not copy org fdata in this case!!! */ CustomData_copy(&old_mesh->fdata, &mesh->fdata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totface); +#endif CustomData_copy(&old_mesh->ldata, &mesh->ldata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totloop); CustomData_copy(&old_mesh->pdata, &mesh->pdata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totpoly); @@ -2030,7 +2032,9 @@ static void write_meshes(WriteData *wd, ListBase *idbase) CustomData_free(&mesh->vdata, mesh->totvert); CustomData_free(&mesh->edata, mesh->totedge); +#ifndef USE_BMESH_SAVE_WITHOUT_MFACE CustomData_free(&mesh->fdata, mesh->totface); +#endif CustomData_free(&mesh->ldata, mesh->totloop); CustomData_free(&mesh->pdata, mesh->totpoly); -- cgit v1.2.3 From 74d31279cd90df312de2078d3323ddcb857e2bbf Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 1 May 2015 17:10:39 +0200 Subject: Fix T44560: Merge Collapse tool - UVs operator panel option ignored with Collapse but not with other merge types. Was missing parameter for collapse bmesh operator... --- source/blender/bmesh/intern/bmesh_opdefines.c | 1 + source/blender/bmesh/operators/bmo_dissolve.c | 2 +- source/blender/bmesh/operators/bmo_removedoubles.c | 7 +++++-- source/blender/editors/mesh/editmesh_tools.c | 6 ++---- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index d0679b9919a..2ba65f5a1e7 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -359,6 +359,7 @@ static BMOpDefine bmo_collapse_def = { "collapse", /* slots_in */ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"uvs", BMO_OP_SLOT_BOOL}, /* also collapse UVs and such */ {{'\0'}}, }, {{{'\0'}}}, /* no output */ diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index ecb41363761..ac0466a74d2 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -494,7 +494,7 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op) static void bm_mesh_edge_collapse_flagged(BMesh *bm, const int flag, const short oflag) { - BMO_op_callf(bm, flag, "collapse edges=%fe", oflag); + BMO_op_callf(bm, flag, "collapse edges=%fe uvs=%b", oflag, true); } void bmo_dissolve_degenerate_exec(BMesh *bm, BMOperator *op) diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index 871bee64c19..73b6268e78b 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -380,8 +380,11 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) float min[3], max[3], center[3]; unsigned int i, tot; BMOpSlot *slot_targetmap; - - BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges"); + + if (BMO_slot_bool_get(op->slots_in, "uvs")) { + BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges"); + } + BMO_op_init(bm, &weldop, op->flag, "weld_verts"); slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap"); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 614963111f3..54acf4abf7c 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -492,7 +492,7 @@ static int edbm_collapse_edge_exec(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); - if (!EDBM_op_callf(em, op, "collapse edges=%he", BM_ELEM_SELECT)) + if (!EDBM_op_callf(em, op, "collapse edges=%he uvs=%b", BM_ELEM_SELECT, true)) return OPERATOR_CANCELLED; EDBM_update_generic(em, true, true); @@ -2049,9 +2049,7 @@ static int edbm_merge_exec(bContext *C, wmOperator *op) ok = merge_firstlast(em, true, uvs, op); break; case 5: - ok = true; - if (!EDBM_op_callf(em, op, "collapse edges=%he", BM_ELEM_SELECT)) - ok = false; + ok = EDBM_op_callf(em, op, "collapse edges=%he uvs=%b", BM_ELEM_SELECT, uvs); break; default: BLI_assert(0); -- cgit v1.2.3 From d3c45535529603a90e47343d088df1dec750c81d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 1 May 2015 19:17:14 +0200 Subject: Fix a couple of harmless compiler warnings. --- source/blender/bmesh/operators/bmo_connect_concave.c | 4 ++-- source/blender/bmesh/tools/bmesh_intersect.c | 4 +--- source/blender/editors/sculpt_paint/paint_image_proj.c | 2 +- source/blender/gpu/intern/gpu_debug.c | 1 + 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/source/blender/bmesh/operators/bmo_connect_concave.c b/source/blender/bmesh/operators/bmo_connect_concave.c index a00f65bd10f..107aead6994 100644 --- a/source/blender/bmesh/operators/bmo_connect_concave.c +++ b/source/blender/bmesh/operators/bmo_connect_concave.c @@ -79,8 +79,8 @@ static bool bm_face_split_by_concave( struct Heap *pf_heap, struct EdgeHash *pf_ehash) { const int f_base_len = f_base->len; - int faces_array_tot = f_base->len - 3; - int edges_array_tot = f_base->len - 3; + int faces_array_tot = f_base_len - 3; + int edges_array_tot = f_base_len - 3; BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot); BMEdge **edges_array = BLI_array_alloca(edges_array, edges_array_tot); const int quad_method = 0, ngon_method = 0; /* beauty */ diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c index 76a289feaaa..b11a22b5854 100644 --- a/source/blender/bmesh/tools/bmesh_intersect.c +++ b/source/blender/bmesh/tools/bmesh_intersect.c @@ -1267,10 +1267,8 @@ bool BM_mesh_intersect( face_edges_split(bm, f, e_ls_base); } } -#else - (void)totface_orig; #endif /* USE_NET */ - + (void)totface_orig; #ifdef USE_SEPARATE if (use_separate) { diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index b74dcb73acd..4085f13999d 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -3886,7 +3886,7 @@ static void project_paint_begin( { ProjPaintLayerClone layer_clone; ProjPaintFaceLookup face_lookup; - MTFace *tf_base; + MTFace *tf_base = NULL; MemArena *arena; /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */ diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c index a0dde9c8f3b..7bcc51aef31 100644 --- a/source/blender/gpu/intern/gpu_debug.c +++ b/source/blender/gpu/intern/gpu_debug.c @@ -356,6 +356,7 @@ void gpu_assert_no_gl_errors(const char* file, int line, const char* str) GLboolean gl_ok = gpu_report_gl_errors(file, line, str); BLI_assert(gl_ok); + (void) gl_ok; } } -- cgit v1.2.3 From 4e40bdd02cd97ff61a62512e548686aad0d91a4d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 1 May 2015 15:52:53 +0200 Subject: Fix T44433: print "unknown" rather than "1970-01-01" when .blend date is unknown. --- source/blender/blenloader/intern/readfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 6d9d7ad073f..2aaa84bc056 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7805,12 +7805,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main) if (G.debug & G_DEBUG) { char build_commit_datetime[32]; time_t temp_time = main->build_commit_timestamp; - struct tm *tm = gmtime(&temp_time); + struct tm *tm = (temp_time) ? gmtime(&temp_time) : NULL; if (LIKELY(tm)) { strftime(build_commit_datetime, sizeof(build_commit_datetime), "%Y-%m-%d %H:%M", tm); } else { - BLI_strncpy(build_commit_datetime, "date-unknown", sizeof(build_commit_datetime)); + BLI_strncpy(build_commit_datetime, "unknown", sizeof(build_commit_datetime)); } printf("read file %s\n Version %d sub %d date %s hash %s\n", -- cgit v1.2.3 From bf7098a93f5a8b45e94795a99c8fb8942b3ac1c6 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 1 May 2015 16:03:45 +0200 Subject: Auto pack: don't show "No new files have been packed" on every .blend file save. --- source/blender/blenkernel/BKE_packedFile.h | 2 +- source/blender/blenkernel/intern/packedFile.c | 10 +++++----- source/blender/editors/space_info/info_ops.c | 4 ++-- source/blender/windowmanager/intern/wm_files.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h index 8fab44121de..a2397922061 100644 --- a/source/blender/blenkernel/BKE_packedFile.h +++ b/source/blender/blenkernel/BKE_packedFile.h @@ -48,7 +48,7 @@ struct PackedFile *dupPackedFile(const struct PackedFile *pf_src); struct PackedFile *newPackedFile(struct ReportList *reports, const char *filename, const char *relabase); struct PackedFile *newPackedFileMemory(void *mem, int memlen); -void packAll(struct Main *bmain, struct ReportList *reports); +void packAll(struct Main *bmain, struct ReportList *reports, bool verbose); void packLibraries(struct Main *bmain, struct ReportList *reports); /* unpack */ diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 61e39d0ad47..68212521617 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -224,7 +224,7 @@ PackedFile *newPackedFile(ReportList *reports, const char *filename, const char } /* no libraries for now */ -void packAll(Main *bmain, ReportList *reports) +void packAll(Main *bmain, ReportList *reports, bool verbose) { Image *ima; VFont *vfont; @@ -237,7 +237,7 @@ void packAll(Main *bmain, ReportList *reports) BKE_image_packfiles(reports, ima, ID_BLEND_PATH(bmain, &ima->id)); tot ++; } - else if (BKE_image_is_animated(ima)) { + else if (BKE_image_is_animated(ima) && verbose) { BKE_reportf(reports, RPT_WARNING, "Image '%s' skipped, movies and image sequences not supported", ima->id.name + 2); } @@ -258,10 +258,10 @@ void packAll(Main *bmain, ReportList *reports) } } - if (tot == 0) - BKE_report(reports, RPT_INFO, "No new files have been packed"); - else + if (tot > 0) BKE_reportf(reports, RPT_INFO, "Packed %d files", tot); + else if (verbose) + BKE_report(reports, RPT_INFO, "No new files have been packed"); } diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index 240d8baa6f2..a1f90f16bbf 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -134,7 +134,7 @@ static int autopack_toggle_exec(bContext *C, wmOperator *op) G.fileflags &= ~G_AUTOPACK; } else { - packAll(bmain, op->reports); + packAll(bmain, op->reports, true); G.fileflags |= G_AUTOPACK; } @@ -161,7 +161,7 @@ static int pack_all_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - packAll(bmain, op->reports); + packAll(bmain, op->reports, true); G.fileflags |= G_AUTOPACK; return OPERATOR_FINISHED; diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index df0d27bc43e..a3cbb2b6eec 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -951,7 +951,7 @@ int wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList * /* operator now handles overwrite checks */ if (G.fileflags & G_AUTOPACK) { - packAll(G.main, reports); + packAll(G.main, reports, false); } /* don't forget not to return without! */ -- cgit v1.2.3 From b6caefdaa9f90159b6c058ef245cc9b8d4a110fa Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 1 May 2015 16:19:06 +0200 Subject: Fix T43711: dual quaternion deform bug with shearing in deform matrix. This also increases the tolerances in is_orthogonal / is_orthonormal functions, which were much too low for practical purposes. --- source/blender/blenlib/intern/math_matrix.c | 8 ++++---- source/blender/blenlib/intern/math_rotation.c | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 773bb419c9b..081c555ed6f 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -1159,7 +1159,7 @@ bool is_orthogonal_m3(float m[3][3]) for (i = 0; i < 3; i++) { for (j = 0; j < i; j++) { - if (fabsf(dot_v3v3(m[i], m[j])) > 1.5f * FLT_EPSILON) + if (fabsf(dot_v3v3(m[i], m[j])) > 1e-5f) return false; } } @@ -1173,7 +1173,7 @@ bool is_orthogonal_m4(float m[4][4]) for (i = 0; i < 4; i++) { for (j = 0; j < i; j++) { - if (fabsf(dot_v4v4(m[i], m[j])) > 1.5f * FLT_EPSILON) + if (fabsf(dot_v4v4(m[i], m[j])) > 1e-5f) return false; } @@ -1188,7 +1188,7 @@ bool is_orthonormal_m3(float m[3][3]) int i; for (i = 0; i < 3; i++) - if (fabsf(dot_v3v3(m[i], m[i]) - 1) > 1.5f * FLT_EPSILON) + if (fabsf(dot_v3v3(m[i], m[i]) - 1) > 1e-5f) return false; return true; @@ -1203,7 +1203,7 @@ bool is_orthonormal_m4(float m[4][4]) int i; for (i = 0; i < 4; i++) - if (fabsf(dot_v4v4(m[i], m[i]) - 1) > 1.5f * FLT_EPSILON) + if (fabsf(dot_v4v4(m[i], m[i]) - 1) > 1e-5f) return false; return true; diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 1f0d68b09b2..5f039e89e89 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -1616,7 +1616,7 @@ void eulO_to_gimbal_axis(float gmat[3][3], const float eul[3], const short order void mat4_to_dquat(DualQuat *dq, float basemat[4][4], float mat[4][4]) { - float *t, *q, dscale[3], scale[3], basequat[4]; + float *t, *q, dscale[3], scale[3], basequat[4], mat3[3][3]; float baseRS[4][4], baseinv[4][4], baseR[4][4], baseRinv[4][4]; float R[4][4], S[4][4]; @@ -1629,7 +1629,9 @@ void mat4_to_dquat(DualQuat *dq, float basemat[4][4], float mat[4][4]) dscale[1] = scale[1] - 1.0f; dscale[2] = scale[2] - 1.0f; - if ((determinant_m4(mat) < 0.0f) || len_v3(dscale) > 1e-4f) { + copy_m3_m4(mat3, mat); + + if (!is_orthonormal_m3(mat3) || (determinant_m4(mat) < 0.0f) || len_v3(dscale) > 1e-4f) { /* extract R and S */ float tmp[4][4]; -- cgit v1.2.3 From 86f80c481cc1de4ddc722cd83913d2643c03474b Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 1 May 2015 19:14:28 +0200 Subject: Fix T44353, Fix T43981: random particle distribution overlaps if number is greater than 256. --- source/blender/blenkernel/intern/particle_distribute.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 1429d3b1cdc..4a2540e385b 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -668,6 +668,8 @@ static void exec_distribute_parent(TaskPool *UNUSED(pool), void *taskdata, int U ParticleSystem *psys= task->ctx->sim.psys; ParticleData *pa; int p; + + BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->begin); pa= psys->particles + task->begin; switch (psys->part->from) { -- cgit v1.2.3 From 23abcc0636135c83cfb91782f7030ea41482e147 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Fri, 1 May 2015 21:09:21 +0200 Subject: OSX: remove collada from fading out 32bit buildbot --- build_files/buildbot/config/user-config-mac-i386.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build_files/buildbot/config/user-config-mac-i386.py b/build_files/buildbot/config/user-config-mac-i386.py index ab93628c78d..c1beefcf83d 100644 --- a/build_files/buildbot/config/user-config-mac-i386.py +++ b/build_files/buildbot/config/user-config-mac-i386.py @@ -5,3 +5,5 @@ WITH_BF_CYCLES_CUDA_BINARIES = True WITH_BF_CYCLES_OSL = False # OSL never worked on OSX 32bit ! +WITH_BF_COLLADA = False # we drop 32bit, newest collada is only x86_64 ! + -- cgit v1.2.3 From bd6e1e6ad7c8856070152991ea62e917ddbd974f Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 1 May 2015 21:18:08 +0200 Subject: Updated install_deps' Collada to 3335ac164e68b2512a40914b14c74db260e6ff7d. --- build_files/build_environment/install_deps.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index 1c78858ac59..ea60eb39e0b 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -510,7 +510,7 @@ OSL_SOURCE_REPO_UID="22ee5ea298fd215430dfbd160b5aefd507f06db0" OSL_SOURCE_REPO_BRANCH="blender-fixes" OPENCOLLADA_SOURCE=( "https://github.com/KhronosGroup/OpenCOLLADA.git" ) -OPENCOLLADA_REPO_UID="18da7f4109a8eafaa290a33f5550501cc4c8bae8" +OPENCOLLADA_REPO_UID="3335ac164e68b2512a40914b14c74db260e6ff7d" FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" ) @@ -1537,7 +1537,7 @@ clean_OpenCOLLADA() { compile_OpenCOLLADA() { # To be changed each time we make edits that would modify the compiled results! - opencollada_magic=8 + opencollada_magic=9 _init_opencollada # Clean install if needed! -- cgit v1.2.3 From b50c6e3f6f9f50a6e8e5e84844f00eca07ef8ec9 Mon Sep 17 00:00:00 2001 From: Daniel Salazar Date: Fri, 1 May 2015 16:17:23 -0600 Subject: Object Align Operator: Make it use modifiers in high quality bounding box calculation --- release/scripts/startup/bl_operators/object_align.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py index e843209da3c..916a9f66915 100644 --- a/release/scripts/startup/bl_operators/object_align.py +++ b/release/scripts/startup/bl_operators/object_align.py @@ -70,7 +70,9 @@ def GlobalBB_HQ(obj): # Initialize the variables with the last vertex - verts = obj.data.vertices + me = obj.to_mesh(scene=bpy.context.scene, apply_modifiers=True, settings='PREVIEW') + verts = me.vertices + bpy.data.meshes.remove(me) val = matrix_world * verts[-1].co -- cgit v1.2.3 From 5e1c729882c242be56730f45f5828c0238b8c818 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 1 May 2015 19:16:58 +1000 Subject: Cleanup: use function attrs for BMesh inline funcs --- source/blender/bmesh/intern/bmesh_inline.h | 3 +++ source/blender/bmesh/intern/bmesh_iterators_inline.h | 3 +++ .../blender/bmesh/intern/bmesh_operator_api_inline.h | 19 +++++++++++++++++++ source/blender/bmesh/intern/bmesh_queries_inline.h | 10 ++++++++++ source/blender/bmesh/intern/bmesh_structure_inline.h | 5 +++++ 5 files changed, 40 insertions(+) diff --git a/source/blender/bmesh/intern/bmesh_inline.h b/source/blender/bmesh/intern/bmesh_inline.h index 96b2cd396a2..4b55060875b 100644 --- a/source/blender/bmesh/intern/bmesh_inline.h +++ b/source/blender/bmesh/intern/bmesh_inline.h @@ -39,11 +39,13 @@ #define BM_elem_flag_merge( ele_a, ele_b) _bm_elem_flag_merge (&(ele_a)->head, &(ele_b)->head) #define BM_elem_flag_merge_into(ele, ele_a, ele_b)_bm_elem_flag_merge_into (&(ele)->head, &(ele_a)->head, &(ele_b)->head) +ATTR_WARN_UNUSED_RESULT BLI_INLINE char _bm_elem_flag_test(const BMHeader *head, const char hflag) { return head->hflag & hflag; } +ATTR_WARN_UNUSED_RESULT BLI_INLINE bool _bm_elem_flag_test_bool(const BMHeader *head, const char hflag) { return (head->hflag & hflag) != 0; @@ -116,6 +118,7 @@ BLI_INLINE void _bm_elem_index_set(BMHeader *head, const int index) head->index = index; } +ATTR_WARN_UNUSED_RESULT BLI_INLINE int _bm_elem_index_get(const BMHeader *head) { return head->index; diff --git a/source/blender/bmesh/intern/bmesh_iterators_inline.h b/source/blender/bmesh/intern/bmesh_iterators_inline.h index d3e18b97acb..e68440021e6 100644 --- a/source/blender/bmesh/intern/bmesh_iterators_inline.h +++ b/source/blender/bmesh/intern/bmesh_iterators_inline.h @@ -37,6 +37,7 @@ * * Calls an iterators step function to return the next element. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE void *BM_iter_step(BMIter *iter) { return iter->step(iter); @@ -50,6 +51,7 @@ BLI_INLINE void *BM_iter_step(BMIter *iter) * it with the appropriate function pointers based * upon its type. */ +ATTR_NONNULL(1) BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *data) { /* int argtype; */ @@ -169,6 +171,7 @@ BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *da * to return the first element of the iterator. * */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE void *BM_iter_new(BMIter *iter, BMesh *bm, const char itype, void *data) { if (LIKELY(BM_iter_init(iter, bm, itype, data))) { diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h index 99fe6659d7d..4f995e08b9c 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h +++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h @@ -38,37 +38,44 @@ * ghash or a mapping slot to do it. */ /* flags 15 and 16 (1 << 14 and 1 << 15) are reserved for bmesh api use */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE short _bmo_elem_flag_test(BMesh *bm, BMFlagLayer *oflags, const short oflag) { return oflags[bm->stackdepth - 1].f & oflag; } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE bool _bmo_elem_flag_test_bool(BMesh *bm, BMFlagLayer *oflags, const short oflag) { return (oflags[bm->stackdepth - 1].f & oflag) != 0; } +ATTR_NONNULL(1, 2) BLI_INLINE void _bmo_elem_flag_enable(BMesh *bm, BMFlagLayer *oflags, const short oflag) { oflags[bm->stackdepth - 1].f |= oflag; } +ATTR_NONNULL(1, 2) BLI_INLINE void _bmo_elem_flag_disable(BMesh *bm, BMFlagLayer *oflags, const short oflag) { oflags[bm->stackdepth - 1].f &= (short)~oflag; } +ATTR_NONNULL(1, 2) BLI_INLINE void _bmo_elem_flag_set(BMesh *bm, BMFlagLayer *oflags, const short oflag, int val) { if (val) oflags[bm->stackdepth - 1].f |= oflag; else oflags[bm->stackdepth - 1].f &= (short)~oflag; } +ATTR_NONNULL(1, 2) BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const short oflag) { oflags[bm->stackdepth - 1].f ^= oflag; } +ATTR_NONNULL(1, 2) BLI_INLINE void BMO_slot_map_int_insert( BMOperator *op, BMOpSlot *slot, void *element, const int val) @@ -78,6 +85,7 @@ BLI_INLINE void BMO_slot_map_int_insert( BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr)); } +ATTR_NONNULL(1, 2) BLI_INLINE void BMO_slot_map_bool_insert( BMOperator *op, BMOpSlot *slot, void *element, const bool val) @@ -87,6 +95,7 @@ BLI_INLINE void BMO_slot_map_bool_insert( BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr)); } +ATTR_NONNULL(1, 2) BLI_INLINE void BMO_slot_map_float_insert( BMOperator *op, BMOpSlot *slot, void *element, const float val) @@ -102,6 +111,7 @@ BLI_INLINE void BMO_slot_map_float_insert( * do NOT use these for non-operator-api-allocated memory! instead * use BMO_slot_map_data_get and BMO_slot_map_insert, which copies the data. */ +ATTR_NONNULL(1, 2) BLI_INLINE void BMO_slot_map_ptr_insert( BMOperator *op, BMOpSlot *slot, const void *element, void *val) @@ -110,6 +120,7 @@ BLI_INLINE void BMO_slot_map_ptr_insert( BMO_slot_map_insert(op, slot, element, val); } +ATTR_NONNULL(1, 2) BLI_INLINE void BMO_slot_map_elem_insert( BMOperator *op, BMOpSlot *slot, const void *element, void *val) @@ -120,6 +131,7 @@ BLI_INLINE void BMO_slot_map_elem_insert( /* no values */ +ATTR_NONNULL(1, 2) BLI_INLINE void BMO_slot_map_empty_insert( BMOperator *op, BMOpSlot *slot, const void *element) @@ -128,18 +140,21 @@ BLI_INLINE void BMO_slot_map_empty_insert( BMO_slot_map_insert(op, slot, element, NULL); } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BMO_slot_map_contains(BMOpSlot *slot, const void *element) { BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); return BLI_ghash_haskey(slot->data.ghash, element); } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE void **BMO_slot_map_data_get(BMOpSlot *slot, const void *element) { return BLI_ghash_lookup_p(slot->data.ghash, element); } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element) { void **data; @@ -154,6 +169,7 @@ BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element) } } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) { void **data; @@ -168,6 +184,7 @@ BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) } } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element) { void **data; @@ -182,6 +199,7 @@ BLI_INLINE bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element) } } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element) { void **val = BMO_slot_map_data_get(slot, element); @@ -191,6 +209,7 @@ BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element) return NULL; } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE void *BMO_slot_map_elem_get(BMOpSlot *slot, const void *element) { void **val = (void **) BMO_slot_map_data_get(slot, element); diff --git a/source/blender/bmesh/intern/bmesh_queries_inline.h b/source/blender/bmesh/intern/bmesh_queries_inline.h index 1ca56beb746..430ba10fb42 100644 --- a/source/blender/bmesh/intern/bmesh_queries_inline.h +++ b/source/blender/bmesh/intern/bmesh_queries_inline.h @@ -30,6 +30,7 @@ * Returns whether or not a given vertex is * is part of a given edge. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) { return (ELEM(v, e->v1, e->v2)); @@ -38,6 +39,7 @@ BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) /** * Returns whether or not a given edge is part of a given loop. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) { return (l->e == e || l->prev->e == e); @@ -47,6 +49,7 @@ BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) * Returns whether or not two vertices are in * a given edge */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3) BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdge *e) { return ((e->v1 == v1 && e->v2 == v2) || @@ -57,6 +60,7 @@ BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdg * Given a edge and one of its vertices, returns * the other vertex. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v) { if (e->v1 == v) { @@ -72,6 +76,7 @@ BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v) * Tests whether or not the edge is part of a wire. * (ie: has no faces attached to it) */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) { return (e->l == NULL); @@ -83,6 +88,7 @@ BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) */ #if 1 /* fast path for checking manifold */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) { const BMLoop *l = e->l; @@ -100,6 +106,7 @@ BLI_INLINE int BM_edge_is_manifold(BMEdge *e) * Tests that the edge is manifold and * that both its faces point the same way. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) { const BMLoop *l = e->l; @@ -115,6 +122,7 @@ BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) */ #if 1 /* fast path for checking boundary */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) { const BMLoop *l = e->l; @@ -130,6 +138,7 @@ BLI_INLINE int BM_edge_is_boundary(BMEdge *e) /** * Tests whether one loop is next to another within the same face. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) { BLI_assert(l_a->f == l_b->f); @@ -140,6 +149,7 @@ BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) /** * Check if we have a single wire edge user. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_vert_is_wire_endpoint(const BMVert *v) { const BMEdge *e = v->e; diff --git a/source/blender/bmesh/intern/bmesh_structure_inline.h b/source/blender/bmesh/intern/bmesh_structure_inline.h index 5b7e890f5ea..64292194ae7 100644 --- a/source/blender/bmesh/intern/bmesh_structure_inline.h +++ b/source/blender/bmesh/intern/bmesh_structure_inline.h @@ -27,6 +27,7 @@ #ifndef __BMESH_STRUCTURE_INLINE_H__ #define __BMESH_STRUCTURE_INLINE_H__ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(const BMEdge *e, const BMVert *v) { BLI_assert(BM_vert_in_edge(e, v)); @@ -40,6 +41,7 @@ BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(const BMEdge *e, const BMV * * \return Pointer to the next edge in the disk cycle for the vertex v. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v) { if (v == e->v1) @@ -49,6 +51,7 @@ BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v) return NULL; } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v) { if (v == e->v1) @@ -58,11 +61,13 @@ BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v) return NULL; } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) { return BM_DISK_EDGE_NEXT(e, v); } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v) { return BM_DISK_EDGE_PREV(e, v); -- cgit v1.2.3 From a5869945c69c818bf53a3043c4bf41060464963e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 1 May 2015 19:30:41 +1000 Subject: Cleanup: bmesh src/dst order in API args --- source/blender/bmesh/intern/bmesh_core.c | 50 +++++++++++----------- source/blender/bmesh/intern/bmesh_core.h | 4 +- source/blender/bmesh/operators/bmo_inset.c | 2 +- .../blender/bmesh/tools/bmesh_decimate_collapse.c | 10 ++--- source/blender/bmesh/tools/bmesh_edgesplit.c | 2 +- source/blender/bmesh/tools/bmesh_intersect.c | 4 +- source/blender/editors/mesh/editmesh_rip.c | 2 +- source/blender/python/bmesh/bmesh_py_utils.c | 2 +- 8 files changed, 39 insertions(+), 37 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 87f700ac731..38849b71ae8 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1804,7 +1804,7 @@ BMEdge *bmesh_jekv( if (check_edge_double) { if (e_splice) { /* removes e_splice */ - BM_edge_splice(bm, e_splice, e_old); + BM_edge_splice(bm, e_old, e_splice); } } @@ -2018,7 +2018,8 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b) /** * \brief Splice Vert * - * Merges two verts into one (\a v into \a vtarget). + * Merges two verts into one + * (\a v_src into \a v_dst, removing \a v_src). * * \return Success * @@ -2026,28 +2027,28 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b) * where \a v and \a vtarget are connected by an edge * (assert checks for this case). */ -bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) +bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src) { BMEdge *e; /* verts already spliced */ - if (v == v_target) { + if (v_src == v_dst) { return false; } - BLI_assert(BM_vert_pair_share_face_check(v, v_target) == false); + BLI_assert(BM_vert_pair_share_face_check(v_src, v_dst) == false); - /* move all the edges from v's disk to vtarget's disk */ - while ((e = v->e)) { - bmesh_edge_vert_swap(e, v_target, v); + /* move all the edges from 'v_src' disk to 'v_dst' */ + while ((e = v_src->e)) { + bmesh_edge_vert_swap(e, v_dst, v_src); BLI_assert(e->v1 != e->v2); } - BM_CHECK_ELEMENT(v); - BM_CHECK_ELEMENT(v_target); + BM_CHECK_ELEMENT(v_src); + BM_CHECK_ELEMENT(v_dst); - /* v is unused now, and can be killed */ - BM_vert_kill(bm, v); + /* 'v_src' is unused now, and can be killed */ + BM_vert_kill(bm, v_src); return true; } @@ -2197,16 +2198,17 @@ void BM_vert_separate( * \brief Splice Edge * * Splice two unique edges which share the same two vertices into one edge. + * (\a e_src into \a e_dst, removing e_src). * * \return Success * * \note Edges must already have the same vertices. */ -bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target) +bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src) { BMLoop *l; - if (!BM_vert_in_edge(e, e_target->v1) || !BM_vert_in_edge(e, e_target->v2)) { + if (!BM_vert_in_edge(e_src, e_dst->v1) || !BM_vert_in_edge(e_src, e_dst->v2)) { /* not the same vertices can't splice */ /* the caller should really make sure this doesn't happen ever @@ -2216,21 +2218,21 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target) return false; } - while (e->l) { - l = e->l; - BLI_assert(BM_vert_in_edge(e_target, l->v)); - BLI_assert(BM_vert_in_edge(e_target, l->next->v)); - bmesh_radial_loop_remove(l, e); - bmesh_radial_append(e_target, l); + while (e_src->l) { + l = e_src->l; + BLI_assert(BM_vert_in_edge(e_dst, l->v)); + BLI_assert(BM_vert_in_edge(e_dst, l->next->v)); + bmesh_radial_loop_remove(l, e_src); + bmesh_radial_append(e_dst, l); } - BLI_assert(bmesh_radial_length(e->l) == 0); + BLI_assert(bmesh_radial_length(e_src->l) == 0); - BM_CHECK_ELEMENT(e); - BM_CHECK_ELEMENT(e_target); + BM_CHECK_ELEMENT(e_src); + BM_CHECK_ELEMENT(e_dst); /* removes from disks too */ - BM_edge_kill(bm, e); + BM_edge_kill(bm, e_src); return true; } diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index 85dd1de0ef5..452ed07dcd0 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -65,8 +65,8 @@ void BM_vert_kill(BMesh *bm, BMVert *v); void bmesh_edge_separate( BMesh *bm, BMEdge *e, BMLoop *l_sep, const bool copy_select); -bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target); -bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target); +bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src); +bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src); bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b); void bmesh_vert_separate( diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index 27e140eb990..3d899bdef28 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -974,7 +974,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op) v_glue = v_split; } else { - BM_vert_splice(bm, v_split, v_glue); + BM_vert_splice(bm, v_glue, v_split); } } } diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 6851e013e9d..47c41c44d81 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -788,12 +788,12 @@ static bool bm_edge_collapse( BM_edge_kill(bm, e_clear); v_other->head.hflag |= v_clear->head.hflag; - BM_vert_splice(bm, v_clear, v_other); + BM_vert_splice(bm, v_other, v_clear); e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag; e_b_other[1]->head.hflag |= e_b_other[0]->head.hflag; - BM_edge_splice(bm, e_a_other[0], e_a_other[1]); - BM_edge_splice(bm, e_b_other[0], e_b_other[1]); + BM_edge_splice(bm, e_a_other[1], e_a_other[0]); + BM_edge_splice(bm, e_b_other[1], e_b_other[0]); // BM_mesh_validate(bm); @@ -837,10 +837,10 @@ static bool bm_edge_collapse( BM_edge_kill(bm, e_clear); v_other->head.hflag |= v_clear->head.hflag; - BM_vert_splice(bm, v_clear, v_other); + BM_vert_splice(bm, v_other, v_clear); e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag; - BM_edge_splice(bm, e_a_other[0], e_a_other[1]); + BM_edge_splice(bm, e_a_other[1], e_a_other[0]); // BM_mesh_validate(bm); diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c index 30ba07c2d8f..50be4e21f24 100644 --- a/source/blender/bmesh/tools/bmesh_edgesplit.c +++ b/source/blender/bmesh/tools/bmesh_edgesplit.c @@ -225,7 +225,7 @@ void BM_mesh_edgesplit( if (BM_elem_flag_test(e, BM_ELEM_TAG)) { BMEdge *e_other; if ((e_other = BM_edge_find_double(e))) { - BM_edge_splice(bm, e, e_other); + BM_edge_splice(bm, e_other, e); } } } diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c index b11a22b5854..98ebd2e854b 100644 --- a/source/blender/bmesh/tools/bmesh_intersect.c +++ b/source/blender/bmesh/tools/bmesh_intersect.c @@ -1006,7 +1006,7 @@ bool BM_mesh_intersect( !BM_vert_splice_check_double(v_prev, vi) && !BM_vert_pair_share_face_check(v_prev, vi)) { - BM_vert_splice(bm, v_prev, vi); + BM_vert_splice(bm, vi, v_prev); } else { copy_v3_v3(v_prev->co, vi->co); @@ -1228,7 +1228,7 @@ bool BM_mesh_intersect( if (!BM_edge_exists(UNPACK2(splice_ls[i])) && !BM_vert_splice_check_double(UNPACK2(splice_ls[i]))) { - BM_vert_splice(bm, UNPACK2(splice_ls[i])); + BM_vert_splice(bm, splice_ls[i][1], splice_ls[i][0]); } } } diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 7bd072ac6cb..05bd677ba6f 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -715,7 +715,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve } for (i = 2; i < vout_len; i++) { - BM_vert_splice(bm, vout[i], vout[1]); + BM_vert_splice(bm, vout[1], vout[i]); } } diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index 8c9f4c4a42c..f810a64119b 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -253,7 +253,7 @@ static PyObject *bpy_bm_utils_vert_splice(PyObject *UNUSED(self), PyObject *args } /* should always succeed */ - ok = BM_vert_splice(bm, py_vert->v, py_vert_target->v); + ok = BM_vert_splice(bm, py_vert_target->v, py_vert->v); BLI_assert(ok == true); UNUSED_VARS_NDEBUG(ok); -- cgit v1.2.3 From c276cfb3c078152327bf38751172d2379a5c7c46 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 2 May 2015 15:52:27 +1000 Subject: BMesh: return error on mesh validate --- source/blender/bmesh/intern/bmesh_mesh_validate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/bmesh/intern/bmesh_mesh_validate.c b/source/blender/bmesh/intern/bmesh_mesh_validate.c index 494da3b889b..478194735f3 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_validate.c +++ b/source/blender/bmesh/intern/bmesh_mesh_validate.c @@ -195,7 +195,7 @@ bool BM_mesh_validate(BMesh *bm) ERRMSG("Finished - errors %d", errtot); - return true; + return (errtot == 0); } -- cgit v1.2.3 From f283b959e7d4ebd3fc2cddc480d2f08cef662caf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 2 May 2015 16:04:02 +1000 Subject: BMesh: BM_vert_separate double edge fix Splitting edges could give duplicates. --- source/blender/bmesh/intern/bmesh_core.c | 123 +++++++++++++++++++++++++-- source/blender/bmesh/intern/bmesh_core.h | 7 +- source/blender/python/bmesh/bmesh_py_utils.c | 2 +- 3 files changed, 123 insertions(+), 9 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 38849b71ae8..7083642f225 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -2053,6 +2053,16 @@ bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src) return true; } + +/** \name BM_vert_separate, bmesh_vert_separate and friends + * \{ */ + +/* BM_edge_face_count(e) >= 1 */ +BLI_INLINE bool bm_edge_supports_separate(const BMEdge *e) +{ + return (e->l && e->l->radial_next != e->l); +} + /** * \brief Separate Vert * @@ -2175,25 +2185,126 @@ void bmesh_vert_separate( } } +/** + * Utility function for #BM_vert_separate + * + * Takes a list of edges, which have been split from their original. + * + * Any edges which failed to split off in #bmesh_vert_separate will be merged back into the original edge. + * + * \param edges_seperate + * A list-of-lists, each list is from a single original edge (the first edge is the original), + * Check for duplicates (not just with the first) but between all. + * This is O(n2) but radial edges are very rarely >2 and almost never >~10. + * + * \note typically its best to avoid createing the data in the first place, + * but inspecting all loops connectivity is quite involved. + * + * \note this function looks like it could become slow, + * but in common cases its only going to iterate a few times. + */ +static void bmesh_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separate) +{ + do { + LinkNode *n_orig = edges_separate->link; + do { + BMEdge *e_orig = n_orig->link; + LinkNode *n_step = n_orig->next; + LinkNode *n_prev = n_orig; + do { + BMEdge *e = n_step->link; + BLI_assert(e != e_orig); + if ((e->v1 == e_orig->v1) && (e->v2 == e_orig->v2)) { + BM_edge_splice(bm, e_orig, e); + n_prev->next = n_step->next; + n_step = n_prev; + } + } while ((n_prev = n_step), + (n_step = n_step->next)); + + } while ((n_orig = n_orig->next) && n_orig->next); + } while ((edges_separate = edges_separate->next)); +} + /** * High level function which wraps both #bmesh_vert_separate and #bmesh_edge_separate */ void BM_vert_separate( - BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, - BMEdge **e_in, int e_in_len) + BMesh *bm, BMVert *v, + BMEdge **e_in, int e_in_len, + const bool copy_select, + BMVert ***r_vout, int *r_vout_len) { + LinkNode *edges_separate = NULL; int i; for (i = 0; i < e_in_len; i++) { BMEdge *e = e_in[i]; - if (e->l && BM_vert_in_edge(e, v)) { - bmesh_edge_separate(bm, e, e->l, false); + if (bm_edge_supports_separate(e)) { + LinkNode *edges_orig = NULL; + do { + BMLoop *l_sep = e->l; + bmesh_edge_separate(bm, e, l_sep, copy_select); + BLI_linklist_prepend_alloca(&edges_orig, l_sep->e); + BLI_assert(e != l_sep->e); + } while (bm_edge_supports_separate(e)); + BLI_linklist_prepend_alloca(&edges_orig, e); + BLI_linklist_prepend_alloca(&edges_separate, edges_orig); } } - bmesh_vert_separate(bm, v, r_vout, r_vout_len, false); + bmesh_vert_separate(bm, v, r_vout, r_vout_len, copy_select); + + if (edges_separate) { + bmesh_vert_separate__cleanup(bm, edges_separate); + } +} + + +/** + * A version of #BM_vert_separate which takes a flag. + */ +void BM_vert_separate_hflag( + BMesh *bm, BMVert *v, + const char hflag, + const bool copy_select, + BMVert ***r_vout, int *r_vout_len) +{ + LinkNode *edges_separate = NULL; + BMEdge *e_iter, *e_first; + + e_iter = e_first = v->e; + do { + if (BM_elem_flag_test(e_iter, hflag)) { + BMEdge *e = e_iter; + if (bm_edge_supports_separate(e)) { + LinkNode *edges_orig = NULL; + do { + BMLoop *l_sep = e->l; + bmesh_edge_separate(bm, e, l_sep, copy_select); + /* trick to avoid looping over seperated edges */ + if (edges_separate == NULL && edges_orig == NULL) { + e_first = l_sep->e; + } + BLI_linklist_prepend_alloca(&edges_orig, l_sep->e); + BLI_assert(e != l_sep->e); + } while (bm_edge_supports_separate(e)); + BLI_linklist_prepend_alloca(&edges_orig, e); + BLI_linklist_prepend_alloca(&edges_separate, edges_orig); + } + } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first); + + bmesh_vert_separate(bm, v, r_vout, r_vout_len, copy_select); + + if (edges_separate) { + bmesh_vert_separate__cleanup(bm, edges_separate); + } } +/** \} */ + + /** * \brief Splice Edge * @@ -2261,7 +2372,7 @@ void bmesh_edge_separate( BLI_assert(e->l); if (BM_edge_is_boundary(e)) { - /* no cut required */ + BLI_assert(0); /* no cut required */ return; } diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index 452ed07dcd0..54656fc8e16 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -77,8 +77,11 @@ bool bmesh_loop_reverse(BMesh *bm, BMFace *f); BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del); void BM_vert_separate( - BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, - BMEdge **e_in, int e_in_len); + BMesh *bm, BMVert *v, BMEdge **e_in, int e_in_len, const bool copy_select, + BMVert ***r_vout, int *r_vout_len); +void BM_vert_separate_hflag( + BMesh *bm, BMVert *v, const char hflag, const bool copy_select, + BMVert ***r_vout, int *r_vout_len); /* EULER API - For modifying structure */ BMFace *bmesh_sfme( diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index f810a64119b..b7890926a85 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -307,7 +307,7 @@ static PyObject *bpy_bm_utils_vert_separate(PyObject *UNUSED(self), PyObject *ar return NULL; } - BM_vert_separate(bm, py_vert->v, &elem, &elem_len, edge_array, edge_array_len); + BM_vert_separate(bm, py_vert->v, edge_array, edge_array_len, false, &elem, &elem_len); /* return collected verts */ ret = BPy_BMVert_Array_As_Tuple(bm, elem, elem_len); MEM_freeN(elem); -- cgit v1.2.3 From 53d08ec50634e88eb67339333f9c13cfae03f85d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 2 May 2015 16:05:32 +1000 Subject: BMesh: BM_mesh_edgesplit Did quite a few checks not to tag bad splits (which wasn't working perfectly) Instead rely on BM_vert_separate not to create invalid geometry. --- source/blender/bmesh/operators/bmo_split_edges.c | 2 +- source/blender/bmesh/tools/bmesh_edgesplit.c | 117 ++--------------------- source/blender/bmesh/tools/bmesh_edgesplit.h | 2 +- source/blender/bmesh/tools/bmesh_intersect.c | 2 +- source/blender/editors/mesh/editmesh_rip.c | 2 +- source/blender/modifiers/intern/MOD_edgesplit.c | 2 +- 6 files changed, 13 insertions(+), 114 deletions(-) diff --git a/source/blender/bmesh/operators/bmo_split_edges.c b/source/blender/bmesh/operators/bmo_split_edges.c index ca2088339cf..eb7946caff0 100644 --- a/source/blender/bmesh/operators/bmo_split_edges.c +++ b/source/blender/bmesh/operators/bmo_split_edges.c @@ -48,7 +48,7 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) } /* this is where everything happens */ - BM_mesh_edgesplit(bm, use_verts, true, true, false); + BM_mesh_edgesplit(bm, use_verts, true, false); BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_INTERNAL_TAG); } diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c index 50be4e21f24..74b1660080b 100644 --- a/source/blender/bmesh/tools/bmesh_edgesplit.c +++ b/source/blender/bmesh/tools/bmesh_edgesplit.c @@ -35,74 +35,6 @@ #include "bmesh_edgesplit.h" /* own include */ - -/** - * Remove the BM_ELEM_TAG flag for edges we cant split - * - * un-tag edges not connected to other tagged edges, - * unless they are on a boundary - */ -static void bm_edgesplit_validate_seams(BMesh *bm, const bool use_non_manifold) -{ - BMIter iter; - BMEdge *e; - - unsigned char *vtouch; - - BM_mesh_elem_index_ensure(bm, BM_VERT); - - vtouch = MEM_callocN(sizeof(char) * bm->totvert, __func__); - - /* tag all boundary verts so as not to untag an edge which is inbetween only 2 faces [] */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - - /* unrelated to flag assignment in this function - since this is the - * only place we loop over all edges, disable tag */ - BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG); - - if (e->l == NULL) { - BM_elem_flag_disable(e, BM_ELEM_TAG); - } - else if (BM_edge_is_boundary(e)) { - unsigned char *vt; - vt = &vtouch[BM_elem_index_get(e->v1)]; if (*vt < 2) (*vt)++; - vt = &vtouch[BM_elem_index_get(e->v2)]; if (*vt < 2) (*vt)++; - - /* while the boundary verts need to be tagged, - * the edge its self can't be split */ - BM_elem_flag_disable(e, BM_ELEM_TAG); - } - else if ((use_non_manifold == false) && - (BM_edge_is_manifold(e) == false)) - { - BM_elem_flag_disable(e, BM_ELEM_TAG); - } - } - - /* single marked edges unconnected to any other marked edges - * are illegal, go through and unmark them */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - /* lame, but we don't want the count to exceed 255, - * so just count to 2, its all we need */ - unsigned char *vt; - vt = &vtouch[BM_elem_index_get(e->v1)]; if (*vt < 2) (*vt)++; - vt = &vtouch[BM_elem_index_get(e->v2)]; if (*vt < 2) (*vt)++; - } - } - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - if (vtouch[BM_elem_index_get(e->v1)] == 1 && - vtouch[BM_elem_index_get(e->v2)] == 1) - { - BM_elem_flag_disable(e, BM_ELEM_TAG); - } - } - } - - MEM_freeN(vtouch); -} - /** * \param use_verts Use flagged verts instead of edges. * \param use_non_manifold Split non-manifold edges (a little slower, must check for doubles). @@ -111,7 +43,7 @@ static void bm_edgesplit_validate_seams(BMesh *bm, const bool use_non_manifold) */ void BM_mesh_edgesplit( BMesh *bm, - const bool use_verts, const bool use_non_manifold, + const bool use_verts, const bool tag_only, const bool copy_select) { BMIter iter; @@ -156,27 +88,8 @@ void BM_mesh_edgesplit( } } - bm_edgesplit_validate_seams(bm, use_non_manifold); - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - /* this flag gets copied so we can be sure duplicate edges get it too (important) */ - BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG); - - /* keep splitting until each loop has its own edge */ - while (!BM_edge_is_boundary(e)) { - BMLoop *l_sep = e->l; - bmesh_edge_separate(bm, e, l_sep, copy_select); - BLI_assert(l_sep->e != e); - - if (use_ese) { - BMEditSelection *ese = BLI_ghash_lookup(ese_gh, e); - if (UNLIKELY(ese)) { - BM_select_history_store_after_notest(bm, ese, l_sep->e); - } - } - } - BM_elem_flag_enable(e->v1, BM_ELEM_TAG); BM_elem_flag_enable(e->v2, BM_ELEM_TAG); } @@ -194,7 +107,7 @@ void BM_mesh_edgesplit( BMVert **vtar; int vtar_len; - bmesh_vert_separate(bm, v, &vtar, &vtar_len, copy_select); + BM_vert_separate_hflag(bm, v, BM_ELEM_TAG, copy_select, &vtar, &vtar_len); /* first value is always in 'v' */ if (vtar_len > 1) { @@ -211,35 +124,21 @@ void BM_mesh_edgesplit( MEM_freeN(vtar); } else { - bmesh_vert_separate(bm, v, NULL, NULL, copy_select); + BM_vert_separate_hflag(bm, v, BM_ELEM_TAG, copy_select, NULL, NULL); } } } } } - if (use_non_manifold) { - /* if we split non-manifold, double edge may remain */ - BMEdge *e_next; - BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - BMEdge *e_other; - if ((e_other = BM_edge_find_double(e))) { - BM_edge_splice(bm, e_other, e); - } - } - } - } - else { #ifndef NDEBUG - /* ensure we don't have any double edges! */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - BLI_assert(BM_edge_find_double(e) == NULL); - } + /* ensure we don't have any double edges! */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + BLI_assert(BM_edge_find_double(e) == NULL); } -#endif } +#endif if (use_ese) { BLI_ghash_free(ese_gh, NULL, NULL); diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.h b/source/blender/bmesh/tools/bmesh_edgesplit.h index 531af964a99..26040077f43 100644 --- a/source/blender/bmesh/tools/bmesh_edgesplit.h +++ b/source/blender/bmesh/tools/bmesh_edgesplit.h @@ -29,7 +29,7 @@ void BM_mesh_edgesplit( BMesh *bm, - const bool use_verts, const bool use_non_manifold, + const bool use_verts, const bool tag_only, const bool copy_select); #endif /* __BMESH_EDGESPLIT_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c index 98ebd2e854b..fc12bce8563 100644 --- a/source/blender/bmesh/tools/bmesh_intersect.c +++ b/source/blender/bmesh/tools/bmesh_intersect.c @@ -1281,7 +1281,7 @@ bool BM_mesh_intersect( BM_elem_flag_enable(e, BM_ELEM_TAG); } - BM_mesh_edgesplit(bm, false, false, true, false); + BM_mesh_edgesplit(bm, false, true, false); } #else (void)use_separate; diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 05bd677ba6f..cc462bb75a8 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -941,7 +941,7 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, const wmEvent *eve fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm); } - BM_mesh_edgesplit(em->bm, true, true, true, true); + BM_mesh_edgesplit(em->bm, true, true, true); /* note: the output of the bmesh operator is ignored, since we built * the contiguous loop pairs to split already, its possible that some diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index 2e6360c3ded..fa29921b325 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -91,7 +91,7 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd) } } - BM_mesh_edgesplit(bm, false, false, true, false); + BM_mesh_edgesplit(bm, false, true, false); /* BM_mesh_validate(bm); */ /* for troubleshooting */ -- cgit v1.2.3 From 929c9de3dc79f2b8c488ec9ff2138701dfa17175 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sat, 2 May 2015 10:38:51 +0200 Subject: Turn bpy.utils into a package, so that we can easily add submodules to it. --- release/scripts/modules/bpy/utils.py | 699 -------------------------- release/scripts/modules/bpy/utils/__init__.py | 699 ++++++++++++++++++++++++++ 2 files changed, 699 insertions(+), 699 deletions(-) delete mode 100644 release/scripts/modules/bpy/utils.py create mode 100644 release/scripts/modules/bpy/utils/__init__.py diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py deleted file mode 100644 index 5f235ae3958..00000000000 --- a/release/scripts/modules/bpy/utils.py +++ /dev/null @@ -1,699 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -# - -""" -This module contains utility functions specific to blender but -not associated with blenders internal data. -""" - -__all__ = ( - "blend_paths", - "escape_identifier", - "keyconfig_set", - "load_scripts", - "modules_from_path", - "preset_find", - "preset_paths", - "refresh_script_paths", - "register_class", - "register_module", - "register_manual_map", - "unregister_manual_map", - "make_rna_paths", - "manual_map", - "resource_path", - "script_path_user", - "script_path_pref", - "script_paths", - "smpte_from_frame", - "smpte_from_seconds", - "units", - "unregister_class", - "unregister_module", - "user_resource", - ) - -from _bpy import ( - escape_identifier, - register_class, - unregister_class, - blend_paths, - resource_path, - ) -from _bpy import script_paths as _bpy_script_paths -from _bpy import user_resource as _user_resource -from _bpy import _utils_units as units - -import bpy as _bpy -import os as _os -import sys as _sys - -import addon_utils as _addon_utils - -_user_preferences = _bpy.context.user_preferences -_script_module_dirs = "startup", "modules" - - -def _test_import(module_name, loaded_modules): - use_time = _bpy.app.debug_python - - if module_name in loaded_modules: - return None - if "." in module_name: - print("Ignoring '%s', can't import files containing " - "multiple periods" % module_name) - return None - - if use_time: - import time - t = time.time() - - try: - mod = __import__(module_name) - except: - import traceback - traceback.print_exc() - return None - - if use_time: - print("time %s %.4f" % (module_name, time.time() - t)) - - loaded_modules.add(mod.__name__) # should match mod.__name__ too - return mod - - -def _sys_path_ensure(path): - if path not in _sys.path: # reloading would add twice - _sys.path.insert(0, path) - - -def modules_from_path(path, loaded_modules): - """ - Load all modules in a path and return them as a list. - - :arg path: this path is scanned for scripts and packages. - :type path: string - :arg loaded_modules: already loaded module names, files matching these - names will be ignored. - :type loaded_modules: set - :return: all loaded modules. - :rtype: list - """ - modules = [] - - for mod_name, mod_path in _bpy.path.module_names(path): - mod = _test_import(mod_name, loaded_modules) - if mod: - modules.append(mod) - - return modules - - -_global_loaded_modules = [] # store loaded module names for reloading. -import bpy_types as _bpy_types # keep for comparisons, never ever reload this. - - -def load_scripts(reload_scripts=False, refresh_scripts=False): - """ - Load scripts and run each modules register function. - - :arg reload_scripts: Causes all scripts to have their unregister method - called before loading. - :type reload_scripts: bool - :arg refresh_scripts: only load scripts which are not already loaded - as modules. - :type refresh_scripts: bool - """ - use_time = _bpy.app.debug_python - - if use_time: - import time - t_main = time.time() - - loaded_modules = set() - - if refresh_scripts: - original_modules = _sys.modules.values() - - if reload_scripts: - _bpy_types.TypeMap.clear() - - # just unload, don't change user defaults, this means we can sync - # to reload. note that they will only actually reload of the - # modification time changes. This `won't` work for packages so... - # its not perfect. - for module_name in [ext.module for ext in _user_preferences.addons]: - _addon_utils.disable(module_name, default_set=False) - - def register_module_call(mod): - register = getattr(mod, "register", None) - if register: - try: - register() - except: - import traceback - traceback.print_exc() - else: - print("\nWarning! '%s' has no register function, " - "this is now a requirement for registerable scripts" % - mod.__file__) - - def unregister_module_call(mod): - unregister = getattr(mod, "unregister", None) - if unregister: - try: - unregister() - except: - import traceback - traceback.print_exc() - - def test_reload(mod): - import importlib - # reloading this causes internal errors - # because the classes from this module are stored internally - # possibly to refresh internal references too but for now, best not to. - if mod == _bpy_types: - return mod - - try: - return importlib.reload(mod) - except: - import traceback - traceback.print_exc() - - def test_register(mod): - - if refresh_scripts and mod in original_modules: - return - - if reload_scripts and mod: - print("Reloading:", mod) - mod = test_reload(mod) - - if mod: - register_module_call(mod) - _global_loaded_modules.append(mod.__name__) - - if reload_scripts: - - # module names -> modules - _global_loaded_modules[:] = [_sys.modules[mod_name] - for mod_name in _global_loaded_modules] - - # loop over and unload all scripts - _global_loaded_modules.reverse() - for mod in _global_loaded_modules: - unregister_module_call(mod) - - for mod in _global_loaded_modules: - test_reload(mod) - - del _global_loaded_modules[:] - - from bpy_restrict_state import RestrictBlend - - with RestrictBlend(): - for base_path in script_paths(): - for path_subdir in _script_module_dirs: - path = _os.path.join(base_path, path_subdir) - if _os.path.isdir(path): - _sys_path_ensure(path) - - # only add this to sys.modules, don't run - if path_subdir == "modules": - continue - - for mod in modules_from_path(path, loaded_modules): - test_register(mod) - - # deal with addons separately - _initialize = getattr(_addon_utils, "_initialize", None) - if _initialize is not None: - # first time, use fast-path - _initialize() - del _addon_utils._initialize - else: - _addon_utils.reset_all(reload_scripts) - del _initialize - - # run the active integration preset - filepath = preset_find(_user_preferences.inputs.active_keyconfig, - "keyconfig") - - if filepath: - keyconfig_set(filepath) - - if reload_scripts: - import gc - print("gc.collect() -> %d" % gc.collect()) - - if use_time: - print("Python Script Load Time %.4f" % (time.time() - t_main)) - - -# base scripts -_scripts = _os.path.join(_os.path.dirname(__file__), - _os.path.pardir, - _os.path.pardir, - ) -_scripts = (_os.path.normpath(_scripts), ) - - -def script_path_user(): - """returns the env var and falls back to home dir or None""" - path = _user_resource('SCRIPTS') - return _os.path.normpath(path) if path else None - - -def script_path_pref(): - """returns the user preference or None""" - path = _user_preferences.filepaths.script_directory - return _os.path.normpath(path) if path else None - - -def script_paths(subdir=None, user_pref=True, check_all=False): - """ - Returns a list of valid script paths. - - :arg subdir: Optional subdir. - :type subdir: string - :arg user_pref: Include the user preference script path. - :type user_pref: bool - :arg check_all: Include local, user and system paths rather just the paths - blender uses. - :type check_all: bool - :return: script paths. - :rtype: list - """ - scripts = list(_scripts) - - if check_all: - # all possible paths - base_paths = tuple(_os.path.join(resource_path(res), "scripts") - for res in ('LOCAL', 'USER', 'SYSTEM')) - else: - # only paths blender uses - base_paths = _bpy_script_paths() - - for path in base_paths + (script_path_user(), script_path_pref()): - if path: - path = _os.path.normpath(path) - if path not in scripts and _os.path.isdir(path): - scripts.append(path) - - if subdir is None: - return scripts - - scripts_subdir = [] - for path in scripts: - path_subdir = _os.path.join(path, subdir) - if _os.path.isdir(path_subdir): - scripts_subdir.append(path_subdir) - - return scripts_subdir - - -def refresh_script_paths(): - """ - Run this after creating new script paths to update sys.path - """ - - for base_path in script_paths(): - for path_subdir in _script_module_dirs: - path = _os.path.join(base_path, path_subdir) - if _os.path.isdir(path): - _sys_path_ensure(path) - - for path in _addon_utils.paths(): - _sys_path_ensure(path) - path = _os.path.join(path, "modules") - if _os.path.isdir(path): - _sys_path_ensure(path) - - -def preset_paths(subdir): - """ - Returns a list of paths for a specific preset. - - :arg subdir: preset subdirectory (must not be an absolute path). - :type subdir: string - :return: script paths. - :rtype: list - """ - dirs = [] - for path in script_paths("presets", check_all=True): - directory = _os.path.join(path, subdir) - if not directory.startswith(path): - raise Exception("invalid subdir given %r" % subdir) - elif _os.path.isdir(directory): - dirs.append(directory) - - # Find addons preset paths - for path in _addon_utils.paths(): - directory = _os.path.join(path, "presets", subdir) - if _os.path.isdir(directory): - dirs.append(directory) - - return dirs - - -def smpte_from_seconds(time, fps=None): - """ - Returns an SMPTE formatted string from the time in seconds: "HH:MM:SS:FF". - - If the *fps* is not given the current scene is used. - """ - import math - - if fps is None: - fps = _bpy.context.scene.render.fps - - hours = minutes = seconds = frames = 0 - - if time < 0: - time = - time - neg = "-" - else: - neg = "" - - if time >= 3600.0: # hours - hours = int(time / 3600.0) - time = time % 3600.0 - if time >= 60.0: # minutes - minutes = int(time / 60.0) - time = time % 60.0 - - seconds = int(time) - frames = int(round(math.floor(((time - seconds) * fps)))) - - return "%s%02d:%02d:%02d:%02d" % (neg, hours, minutes, seconds, frames) - - -def smpte_from_frame(frame, fps=None, fps_base=None): - """ - Returns an SMPTE formatted string from the frame: "HH:MM:SS:FF". - - If *fps* and *fps_base* are not given the current scene is used. - - :arg time: time in seconds. - :type time: number or timedelta object - :return: the frame. - :rtype: float - """ - - if fps is None: - fps = _bpy.context.scene.render.fps - - if fps_base is None: - fps_base = _bpy.context.scene.render.fps_base - - return smpte_from_seconds((frame * fps_base) / fps, fps) - - -def time_from_frame(frame, fps=None, fps_base=None): - """ - Returns the time from a frame number . - - If *fps* and *fps_base* are not given the current scene is used. - - :arg frame: number. - :type frame: the frame number - :return: the time in seconds. - :rtype: datetime.timedelta - """ - - if fps is None: - fps = _bpy.context.scene.render.fps - - if fps_base is None: - fps_base = _bpy.context.scene.render.fps_base - - from datetime import timedelta - - return timedelta(0, (frame * fps_base) / fps) - - -def time_to_frame(time, fps=None, fps_base=None): - """ - Returns a float frame number from a time given in seconds or - as a datetime.timedelta object. - - If *fps* and *fps_base* are not given the current scene is used. - - :arg time: time in seconds. - :type time: number or a datetime.timedelta object - :return: the frame. - :rtype: float - """ - - if fps is None: - fps = _bpy.context.scene.render.fps - - if fps_base is None: - fps_base = _bpy.context.scene.render.fps_base - - from datetime import timedelta - - if isinstance(time, timedelta): - time = time.total_seconds() - - return (time / fps_base) * fps - - -def preset_find(name, preset_path, display_name=False, ext=".py"): - if not name: - return None - - for directory in preset_paths(preset_path): - - if display_name: - filename = "" - for fn in _os.listdir(directory): - if fn.endswith(ext) and name == _bpy.path.display_name(fn): - filename = fn - break - else: - filename = name + ext - - if filename: - filepath = _os.path.join(directory, filename) - if _os.path.exists(filepath): - return filepath - - -def keyconfig_set(filepath, report=None): - from os.path import basename, splitext - from itertools import chain - - if _bpy.app.debug_python: - print("loading preset:", filepath) - - keyconfigs = _bpy.context.window_manager.keyconfigs - - keyconfigs_old = keyconfigs[:] - - try: - error_msg = "" - with open(filepath, 'r', encoding='utf-8') as keyfile: - exec(compile(keyfile.read(), filepath, "exec"), - {"__file__": filepath}) - except: - import traceback - error_msg = traceback.format_exc() - - if error_msg: - if report is not None: - report({'ERROR'}, error_msg) - print(error_msg) - - kc_new = next(chain(iter(kc for kc in keyconfigs - if kc not in keyconfigs_old), (None,))) - if kc_new is None: - if report is not None: - report({'ERROR'}, "Failed to load keymap %r" % filepath) - return False - else: - kc_new.name = "" - - # remove duplicates - name = splitext(basename(filepath))[0] - while True: - kc_dupe = keyconfigs.get(name) - if kc_dupe: - keyconfigs.remove(kc_dupe) - else: - break - - kc_new.name = name - keyconfigs.active = kc_new - return True - - -def user_resource(resource_type, path="", create=False): - """ - Return a user resource path (normally from the users home directory). - - :arg type: Resource type in ['DATAFILES', 'CONFIG', 'SCRIPTS', 'AUTOSAVE']. - :type type: string - :arg subdir: Optional subdirectory. - :type subdir: string - :arg create: Treat the path as a directory and create - it if its not existing. - :type create: boolean - :return: a path. - :rtype: string - """ - - target_path = _user_resource(resource_type, path) - - if create: - # should always be true. - if target_path: - # create path if not existing. - if not _os.path.exists(target_path): - try: - _os.makedirs(target_path) - except: - import traceback - traceback.print_exc() - target_path = "" - elif not _os.path.isdir(target_path): - print("Path %r found but isn't a directory!" % target_path) - target_path = "" - - return target_path - - -def _bpy_module_classes(module, is_registered=False): - typemap_list = _bpy_types.TypeMap.get(module, ()) - i = 0 - while i < len(typemap_list): - cls_weakref = typemap_list[i] - cls = cls_weakref() - - if cls is None: - del typemap_list[i] - else: - if is_registered == cls.is_registered: - yield cls - i += 1 - - -def register_module(module, verbose=False): - if verbose: - print("bpy.utils.register_module(%r): ..." % module) - cls = None - for cls in _bpy_module_classes(module, is_registered=False): - if verbose: - print(" %r" % cls) - try: - register_class(cls) - except: - print("bpy.utils.register_module(): " - "failed to registering class %r" % cls) - import traceback - traceback.print_exc() - if verbose: - print("done.\n") - if cls is None: - raise Exception("register_module(%r): defines no classes" % module) - - -def unregister_module(module, verbose=False): - if verbose: - print("bpy.utils.unregister_module(%r): ..." % module) - for cls in _bpy_module_classes(module, is_registered=True): - if verbose: - print(" %r" % cls) - try: - unregister_class(cls) - except: - print("bpy.utils.unregister_module(): " - "failed to unregistering class %r" % cls) - import traceback - traceback.print_exc() - if verbose: - print("done.\n") - - -# ----------------------------------------------------------------------------- -# Manual lookups, each function has to return a basepath and a sequence -# of... - -# we start with the built-in default mapping -def _blender_default_map(): - import sys - import rna_wiki_reference as ref_mod - ret = (ref_mod.url_manual_prefix, ref_mod.url_manual_mapping) - # avoid storing in memory - del sys.modules["rna_wiki_reference"] - return ret - -# hooks for doc lookups -_manual_map = [_blender_default_map] - - -def register_manual_map(manual_hook): - _manual_map.append(manual_hook) - - -def unregister_manual_map(manual_hook): - _manual_map.remove(manual_hook) - - -def manual_map(): - # reverse so default is called last - for cb in reversed(_manual_map): - try: - prefix, url_manual_mapping = cb() - except: - print("Error calling %r" % cb) - import traceback - traceback.print_exc() - continue - - yield prefix, url_manual_mapping - - -# Build an RNA path from struct/property/enum names. -def make_rna_paths(struct_name, prop_name, enum_name): - """ - Create RNA "paths" from given names. - - :arg struct_name: Name of a RNA struct (like e.g. "Scene"). - :type struct_name: string - :arg prop_name: Name of a RNA struct's property. - :type prop_name: string - :arg enum_name: Name of a RNA enum identifier. - :type enum_name: string - :return: A triple of three "RNA paths" - (most_complete_path, "struct.prop", "struct.prop:'enum'"). - If no enum_name is given, the third element will always be void. - :rtype: tuple of strings - """ - src = src_rna = src_enum = "" - if struct_name: - if prop_name: - src = src_rna = ".".join((struct_name, prop_name)) - if enum_name: - src = src_enum = "%s:'%s'" % (src_rna, enum_name) - else: - src = src_rna = struct_name - return src, src_rna, src_enum diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py new file mode 100644 index 00000000000..5f235ae3958 --- /dev/null +++ b/release/scripts/modules/bpy/utils/__init__.py @@ -0,0 +1,699 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# + +""" +This module contains utility functions specific to blender but +not associated with blenders internal data. +""" + +__all__ = ( + "blend_paths", + "escape_identifier", + "keyconfig_set", + "load_scripts", + "modules_from_path", + "preset_find", + "preset_paths", + "refresh_script_paths", + "register_class", + "register_module", + "register_manual_map", + "unregister_manual_map", + "make_rna_paths", + "manual_map", + "resource_path", + "script_path_user", + "script_path_pref", + "script_paths", + "smpte_from_frame", + "smpte_from_seconds", + "units", + "unregister_class", + "unregister_module", + "user_resource", + ) + +from _bpy import ( + escape_identifier, + register_class, + unregister_class, + blend_paths, + resource_path, + ) +from _bpy import script_paths as _bpy_script_paths +from _bpy import user_resource as _user_resource +from _bpy import _utils_units as units + +import bpy as _bpy +import os as _os +import sys as _sys + +import addon_utils as _addon_utils + +_user_preferences = _bpy.context.user_preferences +_script_module_dirs = "startup", "modules" + + +def _test_import(module_name, loaded_modules): + use_time = _bpy.app.debug_python + + if module_name in loaded_modules: + return None + if "." in module_name: + print("Ignoring '%s', can't import files containing " + "multiple periods" % module_name) + return None + + if use_time: + import time + t = time.time() + + try: + mod = __import__(module_name) + except: + import traceback + traceback.print_exc() + return None + + if use_time: + print("time %s %.4f" % (module_name, time.time() - t)) + + loaded_modules.add(mod.__name__) # should match mod.__name__ too + return mod + + +def _sys_path_ensure(path): + if path not in _sys.path: # reloading would add twice + _sys.path.insert(0, path) + + +def modules_from_path(path, loaded_modules): + """ + Load all modules in a path and return them as a list. + + :arg path: this path is scanned for scripts and packages. + :type path: string + :arg loaded_modules: already loaded module names, files matching these + names will be ignored. + :type loaded_modules: set + :return: all loaded modules. + :rtype: list + """ + modules = [] + + for mod_name, mod_path in _bpy.path.module_names(path): + mod = _test_import(mod_name, loaded_modules) + if mod: + modules.append(mod) + + return modules + + +_global_loaded_modules = [] # store loaded module names for reloading. +import bpy_types as _bpy_types # keep for comparisons, never ever reload this. + + +def load_scripts(reload_scripts=False, refresh_scripts=False): + """ + Load scripts and run each modules register function. + + :arg reload_scripts: Causes all scripts to have their unregister method + called before loading. + :type reload_scripts: bool + :arg refresh_scripts: only load scripts which are not already loaded + as modules. + :type refresh_scripts: bool + """ + use_time = _bpy.app.debug_python + + if use_time: + import time + t_main = time.time() + + loaded_modules = set() + + if refresh_scripts: + original_modules = _sys.modules.values() + + if reload_scripts: + _bpy_types.TypeMap.clear() + + # just unload, don't change user defaults, this means we can sync + # to reload. note that they will only actually reload of the + # modification time changes. This `won't` work for packages so... + # its not perfect. + for module_name in [ext.module for ext in _user_preferences.addons]: + _addon_utils.disable(module_name, default_set=False) + + def register_module_call(mod): + register = getattr(mod, "register", None) + if register: + try: + register() + except: + import traceback + traceback.print_exc() + else: + print("\nWarning! '%s' has no register function, " + "this is now a requirement for registerable scripts" % + mod.__file__) + + def unregister_module_call(mod): + unregister = getattr(mod, "unregister", None) + if unregister: + try: + unregister() + except: + import traceback + traceback.print_exc() + + def test_reload(mod): + import importlib + # reloading this causes internal errors + # because the classes from this module are stored internally + # possibly to refresh internal references too but for now, best not to. + if mod == _bpy_types: + return mod + + try: + return importlib.reload(mod) + except: + import traceback + traceback.print_exc() + + def test_register(mod): + + if refresh_scripts and mod in original_modules: + return + + if reload_scripts and mod: + print("Reloading:", mod) + mod = test_reload(mod) + + if mod: + register_module_call(mod) + _global_loaded_modules.append(mod.__name__) + + if reload_scripts: + + # module names -> modules + _global_loaded_modules[:] = [_sys.modules[mod_name] + for mod_name in _global_loaded_modules] + + # loop over and unload all scripts + _global_loaded_modules.reverse() + for mod in _global_loaded_modules: + unregister_module_call(mod) + + for mod in _global_loaded_modules: + test_reload(mod) + + del _global_loaded_modules[:] + + from bpy_restrict_state import RestrictBlend + + with RestrictBlend(): + for base_path in script_paths(): + for path_subdir in _script_module_dirs: + path = _os.path.join(base_path, path_subdir) + if _os.path.isdir(path): + _sys_path_ensure(path) + + # only add this to sys.modules, don't run + if path_subdir == "modules": + continue + + for mod in modules_from_path(path, loaded_modules): + test_register(mod) + + # deal with addons separately + _initialize = getattr(_addon_utils, "_initialize", None) + if _initialize is not None: + # first time, use fast-path + _initialize() + del _addon_utils._initialize + else: + _addon_utils.reset_all(reload_scripts) + del _initialize + + # run the active integration preset + filepath = preset_find(_user_preferences.inputs.active_keyconfig, + "keyconfig") + + if filepath: + keyconfig_set(filepath) + + if reload_scripts: + import gc + print("gc.collect() -> %d" % gc.collect()) + + if use_time: + print("Python Script Load Time %.4f" % (time.time() - t_main)) + + +# base scripts +_scripts = _os.path.join(_os.path.dirname(__file__), + _os.path.pardir, + _os.path.pardir, + ) +_scripts = (_os.path.normpath(_scripts), ) + + +def script_path_user(): + """returns the env var and falls back to home dir or None""" + path = _user_resource('SCRIPTS') + return _os.path.normpath(path) if path else None + + +def script_path_pref(): + """returns the user preference or None""" + path = _user_preferences.filepaths.script_directory + return _os.path.normpath(path) if path else None + + +def script_paths(subdir=None, user_pref=True, check_all=False): + """ + Returns a list of valid script paths. + + :arg subdir: Optional subdir. + :type subdir: string + :arg user_pref: Include the user preference script path. + :type user_pref: bool + :arg check_all: Include local, user and system paths rather just the paths + blender uses. + :type check_all: bool + :return: script paths. + :rtype: list + """ + scripts = list(_scripts) + + if check_all: + # all possible paths + base_paths = tuple(_os.path.join(resource_path(res), "scripts") + for res in ('LOCAL', 'USER', 'SYSTEM')) + else: + # only paths blender uses + base_paths = _bpy_script_paths() + + for path in base_paths + (script_path_user(), script_path_pref()): + if path: + path = _os.path.normpath(path) + if path not in scripts and _os.path.isdir(path): + scripts.append(path) + + if subdir is None: + return scripts + + scripts_subdir = [] + for path in scripts: + path_subdir = _os.path.join(path, subdir) + if _os.path.isdir(path_subdir): + scripts_subdir.append(path_subdir) + + return scripts_subdir + + +def refresh_script_paths(): + """ + Run this after creating new script paths to update sys.path + """ + + for base_path in script_paths(): + for path_subdir in _script_module_dirs: + path = _os.path.join(base_path, path_subdir) + if _os.path.isdir(path): + _sys_path_ensure(path) + + for path in _addon_utils.paths(): + _sys_path_ensure(path) + path = _os.path.join(path, "modules") + if _os.path.isdir(path): + _sys_path_ensure(path) + + +def preset_paths(subdir): + """ + Returns a list of paths for a specific preset. + + :arg subdir: preset subdirectory (must not be an absolute path). + :type subdir: string + :return: script paths. + :rtype: list + """ + dirs = [] + for path in script_paths("presets", check_all=True): + directory = _os.path.join(path, subdir) + if not directory.startswith(path): + raise Exception("invalid subdir given %r" % subdir) + elif _os.path.isdir(directory): + dirs.append(directory) + + # Find addons preset paths + for path in _addon_utils.paths(): + directory = _os.path.join(path, "presets", subdir) + if _os.path.isdir(directory): + dirs.append(directory) + + return dirs + + +def smpte_from_seconds(time, fps=None): + """ + Returns an SMPTE formatted string from the time in seconds: "HH:MM:SS:FF". + + If the *fps* is not given the current scene is used. + """ + import math + + if fps is None: + fps = _bpy.context.scene.render.fps + + hours = minutes = seconds = frames = 0 + + if time < 0: + time = - time + neg = "-" + else: + neg = "" + + if time >= 3600.0: # hours + hours = int(time / 3600.0) + time = time % 3600.0 + if time >= 60.0: # minutes + minutes = int(time / 60.0) + time = time % 60.0 + + seconds = int(time) + frames = int(round(math.floor(((time - seconds) * fps)))) + + return "%s%02d:%02d:%02d:%02d" % (neg, hours, minutes, seconds, frames) + + +def smpte_from_frame(frame, fps=None, fps_base=None): + """ + Returns an SMPTE formatted string from the frame: "HH:MM:SS:FF". + + If *fps* and *fps_base* are not given the current scene is used. + + :arg time: time in seconds. + :type time: number or timedelta object + :return: the frame. + :rtype: float + """ + + if fps is None: + fps = _bpy.context.scene.render.fps + + if fps_base is None: + fps_base = _bpy.context.scene.render.fps_base + + return smpte_from_seconds((frame * fps_base) / fps, fps) + + +def time_from_frame(frame, fps=None, fps_base=None): + """ + Returns the time from a frame number . + + If *fps* and *fps_base* are not given the current scene is used. + + :arg frame: number. + :type frame: the frame number + :return: the time in seconds. + :rtype: datetime.timedelta + """ + + if fps is None: + fps = _bpy.context.scene.render.fps + + if fps_base is None: + fps_base = _bpy.context.scene.render.fps_base + + from datetime import timedelta + + return timedelta(0, (frame * fps_base) / fps) + + +def time_to_frame(time, fps=None, fps_base=None): + """ + Returns a float frame number from a time given in seconds or + as a datetime.timedelta object. + + If *fps* and *fps_base* are not given the current scene is used. + + :arg time: time in seconds. + :type time: number or a datetime.timedelta object + :return: the frame. + :rtype: float + """ + + if fps is None: + fps = _bpy.context.scene.render.fps + + if fps_base is None: + fps_base = _bpy.context.scene.render.fps_base + + from datetime import timedelta + + if isinstance(time, timedelta): + time = time.total_seconds() + + return (time / fps_base) * fps + + +def preset_find(name, preset_path, display_name=False, ext=".py"): + if not name: + return None + + for directory in preset_paths(preset_path): + + if display_name: + filename = "" + for fn in _os.listdir(directory): + if fn.endswith(ext) and name == _bpy.path.display_name(fn): + filename = fn + break + else: + filename = name + ext + + if filename: + filepath = _os.path.join(directory, filename) + if _os.path.exists(filepath): + return filepath + + +def keyconfig_set(filepath, report=None): + from os.path import basename, splitext + from itertools import chain + + if _bpy.app.debug_python: + print("loading preset:", filepath) + + keyconfigs = _bpy.context.window_manager.keyconfigs + + keyconfigs_old = keyconfigs[:] + + try: + error_msg = "" + with open(filepath, 'r', encoding='utf-8') as keyfile: + exec(compile(keyfile.read(), filepath, "exec"), + {"__file__": filepath}) + except: + import traceback + error_msg = traceback.format_exc() + + if error_msg: + if report is not None: + report({'ERROR'}, error_msg) + print(error_msg) + + kc_new = next(chain(iter(kc for kc in keyconfigs + if kc not in keyconfigs_old), (None,))) + if kc_new is None: + if report is not None: + report({'ERROR'}, "Failed to load keymap %r" % filepath) + return False + else: + kc_new.name = "" + + # remove duplicates + name = splitext(basename(filepath))[0] + while True: + kc_dupe = keyconfigs.get(name) + if kc_dupe: + keyconfigs.remove(kc_dupe) + else: + break + + kc_new.name = name + keyconfigs.active = kc_new + return True + + +def user_resource(resource_type, path="", create=False): + """ + Return a user resource path (normally from the users home directory). + + :arg type: Resource type in ['DATAFILES', 'CONFIG', 'SCRIPTS', 'AUTOSAVE']. + :type type: string + :arg subdir: Optional subdirectory. + :type subdir: string + :arg create: Treat the path as a directory and create + it if its not existing. + :type create: boolean + :return: a path. + :rtype: string + """ + + target_path = _user_resource(resource_type, path) + + if create: + # should always be true. + if target_path: + # create path if not existing. + if not _os.path.exists(target_path): + try: + _os.makedirs(target_path) + except: + import traceback + traceback.print_exc() + target_path = "" + elif not _os.path.isdir(target_path): + print("Path %r found but isn't a directory!" % target_path) + target_path = "" + + return target_path + + +def _bpy_module_classes(module, is_registered=False): + typemap_list = _bpy_types.TypeMap.get(module, ()) + i = 0 + while i < len(typemap_list): + cls_weakref = typemap_list[i] + cls = cls_weakref() + + if cls is None: + del typemap_list[i] + else: + if is_registered == cls.is_registered: + yield cls + i += 1 + + +def register_module(module, verbose=False): + if verbose: + print("bpy.utils.register_module(%r): ..." % module) + cls = None + for cls in _bpy_module_classes(module, is_registered=False): + if verbose: + print(" %r" % cls) + try: + register_class(cls) + except: + print("bpy.utils.register_module(): " + "failed to registering class %r" % cls) + import traceback + traceback.print_exc() + if verbose: + print("done.\n") + if cls is None: + raise Exception("register_module(%r): defines no classes" % module) + + +def unregister_module(module, verbose=False): + if verbose: + print("bpy.utils.unregister_module(%r): ..." % module) + for cls in _bpy_module_classes(module, is_registered=True): + if verbose: + print(" %r" % cls) + try: + unregister_class(cls) + except: + print("bpy.utils.unregister_module(): " + "failed to unregistering class %r" % cls) + import traceback + traceback.print_exc() + if verbose: + print("done.\n") + + +# ----------------------------------------------------------------------------- +# Manual lookups, each function has to return a basepath and a sequence +# of... + +# we start with the built-in default mapping +def _blender_default_map(): + import sys + import rna_wiki_reference as ref_mod + ret = (ref_mod.url_manual_prefix, ref_mod.url_manual_mapping) + # avoid storing in memory + del sys.modules["rna_wiki_reference"] + return ret + +# hooks for doc lookups +_manual_map = [_blender_default_map] + + +def register_manual_map(manual_hook): + _manual_map.append(manual_hook) + + +def unregister_manual_map(manual_hook): + _manual_map.remove(manual_hook) + + +def manual_map(): + # reverse so default is called last + for cb in reversed(_manual_map): + try: + prefix, url_manual_mapping = cb() + except: + print("Error calling %r" % cb) + import traceback + traceback.print_exc() + continue + + yield prefix, url_manual_mapping + + +# Build an RNA path from struct/property/enum names. +def make_rna_paths(struct_name, prop_name, enum_name): + """ + Create RNA "paths" from given names. + + :arg struct_name: Name of a RNA struct (like e.g. "Scene"). + :type struct_name: string + :arg prop_name: Name of a RNA struct's property. + :type prop_name: string + :arg enum_name: Name of a RNA enum identifier. + :type enum_name: string + :return: A triple of three "RNA paths" + (most_complete_path, "struct.prop", "struct.prop:'enum'"). + If no enum_name is given, the third element will always be void. + :rtype: tuple of strings + """ + src = src_rna = src_enum = "" + if struct_name: + if prop_name: + src = src_rna = ".".join((struct_name, prop_name)) + if enum_name: + src = src_enum = "%s:'%s'" % (src_rna, enum_name) + else: + src = src_rna = struct_name + return src, src_rna, src_enum -- cgit v1.2.3 From ca15ffb8ad8c25a18ac63eb096aa2c3aaaed7ea2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 2 May 2015 22:11:29 +1000 Subject: CMake: use ld.gold linker when available Gives noticeable speedup linking blender --- CMakeLists.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c7308e1fc2..44f6b2f8752 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1162,6 +1162,19 @@ if(UNIX AND NOT APPLE) # though some c11 features can still be used. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu89") endif() + + # use ld.gold linker if available, could make optional + execute_process( + COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version + ERROR_QUIET OUTPUT_VARIABLE LD_VERSION) + if ("${LD_VERSION}" MATCHES "GNU gold") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=gold") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold") + else () + message(WARNING "GNU gold linker isn't available, using the default system linker.") + endif () + unset(LD_VERSION) + # CLang is the same as GCC for now. elseif(CMAKE_C_COMPILER_ID MATCHES "Clang") set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") -- cgit v1.2.3 From 2c72edc7f1983fceea9e07ea368e1608b9c51d03 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sat, 2 May 2015 16:49:12 +0200 Subject: Fix T44586: Viet language problem for Blender Interface We were missing many of the complex diacritics combinations in latin extended additional code block... Alawyas a pleasure to edit this font... :| --- release/datafiles/fonts/droidsans.ttf.gz | Bin 2451240 -> 2466802 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/release/datafiles/fonts/droidsans.ttf.gz b/release/datafiles/fonts/droidsans.ttf.gz index a73566ce57c..a685c590795 100644 Binary files a/release/datafiles/fonts/droidsans.ttf.gz and b/release/datafiles/fonts/droidsans.ttf.gz differ -- cgit v1.2.3 From 8e4ac2d229fff53ed7bd7dee638fc0f004c1e12c Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Sat, 2 May 2015 18:02:19 +0200 Subject: Fix ghash assert during BGE libload. The assert message was caused by the multi call of BLO_library_append_begin in KX_BlenderSceneConverter::LinkBlendFile. --- .../Converter/KX_BlenderSceneConverter.cpp | 23 +++++++++++----------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 4f251a66ccf..c5add2df3d4 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -922,14 +922,9 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFilePath(const char *filepa return LinkBlendFile(bpy_openlib, filepath, group, scene_merge, err_str, options); } -static void load_datablocks(Main *main_newlib, BlendHandle *bpy_openlib, const char *path, int idcode) +static void load_datablocks(Main *main_tmp, BlendHandle *bpy_openlib, const char *path, int idcode) { - Main *main_tmp= NULL; /* created only for linking, then freed */ LinkNode *names = NULL; - short flag= 0; /* don't need any special options */ - - /* here appending/linking starts */ - main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); int totnames_dummy; names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode, &totnames_dummy); @@ -942,8 +937,6 @@ static void load_datablocks(Main *main_newlib, BlendHandle *bpy_openlib, const c i++; } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ - - BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag); } KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) @@ -981,17 +974,23 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl main_newlib = BKE_main_new(); BKE_reports_init(&reports, RPT_STORE); - load_datablocks(main_newlib, bpy_openlib, path, idcode); + short flag = 0; /* don't need any special options */ + /* created only for linking, then freed */ + Main *main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); + + load_datablocks(main_tmp, bpy_openlib, path, idcode); if (idcode==ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) { - load_datablocks(main_newlib, bpy_openlib, path, ID_TXT); + load_datablocks(main_tmp, bpy_openlib, path, ID_TXT); } /* now do another round of linking for Scenes so all actions are properly loaded */ if (idcode==ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { - load_datablocks(main_newlib, bpy_openlib, path, ID_AC); + load_datablocks(main_tmp, bpy_openlib, path, ID_AC); } - + + BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag); + BLO_blendhandle_close(bpy_openlib); BKE_reports_clear(&reports); -- cgit v1.2.3 From c826566ce341cfa6bb02c733a5c70e26542bee9e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 3 May 2015 03:28:43 +1000 Subject: Sound now returns even if file fails to load With various codecs its hard to ensure a sound will load or not. --- source/blender/blenkernel/intern/sequencer.c | 2 +- source/blender/blenkernel/intern/sound.c | 19 +------------------ source/blender/editors/sound/sound_ops.c | 4 +++- source/blender/makesrna/intern/rna_sequencer_api.c | 3 ++- 4 files changed, 7 insertions(+), 21 deletions(-) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index f370570750f..d1893513a4f 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -4974,7 +4974,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad sound = BKE_sound_new_file(bmain, seq_load->path); /* handles relative paths */ - if (sound == NULL || sound->playback_handle == NULL) { + if (sound->playback_handle == NULL) { #if 0 if (op) BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 6a831d23aea..30c17773f7d 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -66,7 +66,7 @@ static int sound_cfra; bSound *BKE_sound_new_file(struct Main *bmain, const char *filename) { - bSound *sound = NULL; + bSound *sound; char str[FILE_MAX]; const char *path; @@ -89,11 +89,6 @@ bSound *BKE_sound_new_file(struct Main *bmain, const char *filename) BKE_sound_load(bmain, sound); - if (!sound->playback_handle) { - BKE_libblock_free(bmain, sound); - sound = NULL; - } - return sound; } @@ -246,12 +241,6 @@ bSound *BKE_sound_new_buffer(struct Main *bmain, bSound *source) sound_load(bmain, sound); - if (!sound->playback_handle) - { - BKE_libblock_free(bmain, sound); - sound = NULL; - } - return sound; } @@ -272,12 +261,6 @@ bSound *BKE_sound_new_limiter(struct Main *bmain, bSound *source, float start, f sound_load(bmain, sound); - if (!sound->playback_handle) - { - BKE_libblock_free(bmain, sound); - sound = NULL; - } - return sound; } #endif diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index bce9a375091..8a3b48125d0 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -51,6 +51,7 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BKE_report.h" +#include "BKE_library.h" #include "BKE_packedFile.h" #include "BKE_scene.h" #include "BKE_sound.h" @@ -105,8 +106,9 @@ static int sound_open_exec(bContext *C, wmOperator *op) if (!op->customdata) sound_open_init(C, op); - if (sound == NULL || sound->playback_handle == NULL) { + if (sound->playback_handle == NULL) { if (op->customdata) MEM_freeN(op->customdata); + BKE_libblock_free(bmain, sound); BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); return OPERATOR_CANCELLED; } diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index 881688281f3..44169fa641e 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -232,7 +232,8 @@ static Sequence *rna_Sequences_new_sound(ID *id, Editing *ed, Main *bmain, Repor bSound *sound = BKE_sound_new_file(bmain, file); - if (sound == NULL || sound->playback_handle == NULL) { + if (sound->playback_handle == NULL) { + BKE_libblock_free(bmain, sound); BKE_report(reports, RPT_ERROR, "Sequences.new_sound: unable to open sound file"); return NULL; } -- cgit v1.2.3 From de031b7c89cc5c5dd079d407ebd3a690b1c4b567 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 2 May 2015 17:12:32 +1000 Subject: BMesh: replace radial count with simple checks --- source/blender/bmesh/intern/bmesh_core.c | 3 ++- source/blender/bmesh/intern/bmesh_queries.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 7083642f225..06bd6229119 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1053,8 +1053,9 @@ static bool disk_is_flagged(BMVert *v, const char api_flag) return false; } - if (bmesh_radial_length(l) == 1) + if (BM_edge_is_boundary(l->e)) { return false; + } do { if (!BM_ELEM_API_FLAG_TEST(l->f, api_flag)) diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 61328a525f1..296bde9eb33 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -877,7 +877,7 @@ bool BM_vert_is_manifold(const BMVert *v) /* loose edge or edge shared by more than two faces, * edges with 1 face user are OK, otherwise we could * use BM_edge_is_manifold() here */ - if (e->l == NULL || bmesh_radial_length(e->l) > 2) { + if (e->l == NULL || (e->l != e->l->radial_next->radial_next)) { return false; } len++; -- cgit v1.2.3 From bd5e578804d9debe0c8450d196b1960ee66dbaa9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 3 May 2015 04:40:02 +1000 Subject: BMesh: rework BM_vert_is_manifold (simplify logic) - simplify boundary handling (walk from boundary - no need to reset walking) - early exit when the vert has >2 boundaries - use BM_vert_step_fan_loop to walk the fan --- source/blender/bmesh/intern/bmesh_queries.c | 73 +++++++++++++++-------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 296bde9eb33..ece4d782a84 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -861,9 +861,9 @@ bool BM_vert_is_wire(const BMVert *v) */ bool BM_vert_is_manifold(const BMVert *v) { - BMEdge *e, *e_old; - BMLoop *l; - int len, count, flag; + BMEdge *e_iter, *e_first, *e_prev; + BMLoop *l_iter, *l_first; + int edge_num = 0, loop_num = 0, loop_num_region = 0, boundary_num = 0; if (v->e == NULL) { /* loose vert */ @@ -871,51 +871,52 @@ bool BM_vert_is_manifold(const BMVert *v) } /* count edges while looking for non-manifold edges */ - len = 0; - e_old = e = v->e; + e_first = e_iter = v->e; + l_first = e_iter->l ? e_iter->l : NULL; do { /* loose edge or edge shared by more than two faces, * edges with 1 face user are OK, otherwise we could * use BM_edge_is_manifold() here */ - if (e->l == NULL || (e->l != e->l->radial_next->radial_next)) { + if (e_iter->l == NULL || (e_iter->l != e_iter->l->radial_next->radial_next)) { return false; } - len++; - } while ((e = bmesh_disk_edge_next(e, v)) != e_old); - - count = 1; - flag = 1; - e = NULL; - e_old = v->e; - l = e_old->l; - while (e != e_old) { - l = (l->v == v) ? l->prev : l->next; - e = l->e; - count++; /* count the edges */ - - if (flag && l->radial_next == l) { - /* we've hit the edge of an open mesh, reset once */ - flag = 0; - count = 1; - e_old = e; - e = NULL; - l = e_old->l; + + /* count radial loops */ + if (e_iter->l->v == v) { + loop_num += 1; } - else if (l->radial_next == l) { - /* break the loop */ - e = e_old; + + if (!BM_edge_is_boundary(e_iter)) { + /* non boundary check opposite loop */ + if (e_iter->l->radial_next->v == v) { + loop_num += 1; + } } else { - l = l->radial_next; + /* start at the boundary */ + l_first = e_iter->l; + boundary_num += 1; + /* >2 boundaries cant be manifold */ + if (boundary_num == 3) { + return false; + } } - } - if (count < len) { - /* vert shared by multiple regions */ - return false; - } + edge_num += 1; + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - return true; + e_first = l_first->e; + l_first = (l_first->v == v) ? l_first : l_first->next; + BLI_assert(l_first->v == v); + + l_iter = l_first; + e_prev = e_first; + + do { + loop_num_region += 1; + } while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL)); + + return (loop_num == loop_num_region); } /** -- cgit v1.2.3 From 4fca12e0faf77671473e3a0207a7fe383bc7cb73 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Sat, 2 May 2015 19:46:27 +0200 Subject: Fix rna default value in BGE UI. --- source/blender/blenkernel/intern/scene.c | 2 +- source/blender/makesrna/intern/rna_object.c | 11 ++++++++++ source/blender/makesrna/intern/rna_scene.c | 34 +++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 07e2a186444..5b34504184a 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -680,7 +680,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->gm.recastData.cellsize = 0.3f; sce->gm.recastData.cellheight = 0.2f; - sce->gm.recastData.agentmaxslope = M_PI / 2; + sce->gm.recastData.agentmaxslope = M_PI_4; sce->gm.recastData.agentmaxclimb = 0.9f; sce->gm.recastData.agentheight = 2.0f; sce->gm.recastData.agentradius = 0.6f; diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index e2df903ac95..92f8ad62924 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1686,6 +1686,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "physics_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "body_type"); RNA_def_property_enum_items(prop, body_type_items); + RNA_def_property_enum_default(prop, OB_BODY_TYPE_STATIC); RNA_def_property_enum_funcs(prop, "rna_GameObjectSettings_physics_type_get", "rna_GameObjectSettings_physics_type_set", NULL); RNA_def_property_ui_text(prop, "Physics Type", "Select the type of physical representation"); @@ -1705,12 +1706,14 @@ static void rna_def_object_game_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.01, 10000.0); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Mass", "Mass of the object"); prop = RNA_def_property(srna, "radius", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH); RNA_def_property_float_sdna(prop, NULL, "inertia"); RNA_def_property_range(prop, 0.01f, FLT_MAX); RNA_def_property_ui_range(prop, 0.01f, 10.0f, 1, 3); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Radius", "Radius of bounding sphere and material physics"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); @@ -1721,11 +1724,13 @@ static void rna_def_object_game_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "damping", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "damping"); RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_float_default(prop, 0.04f); RNA_def_property_ui_text(prop, "Damping", "General movement damping"); prop = RNA_def_property(srna, "rotation_damping", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rdamping"); RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_float_default(prop, 0.1f); RNA_def_property_ui_text(prop, "Rotation Damping", "General rotation damping"); prop = RNA_def_property(srna, "velocity_min", PROP_FLOAT, PROP_NONE); @@ -1742,16 +1747,19 @@ static void rna_def_object_game_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "step_height", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "step_height"); RNA_def_property_range(prop, 0.01, 1.0); + RNA_def_property_float_default(prop, 0.15f); RNA_def_property_ui_text(prop, "Step Height", "Maximum height of steps the character can run over"); prop = RNA_def_property(srna, "jump_speed", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "jump_speed"); RNA_def_property_range(prop, 0.0, 1000.0); + RNA_def_property_float_default(prop, 10.0f); RNA_def_property_ui_text(prop, "Jump Force", "Upward velocity applied to the character when jumping"); prop = RNA_def_property(srna, "fall_speed", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "fall_speed"); RNA_def_property_range(prop, 0.0, 1000.0); + RNA_def_property_float_default(prop, 55.0f); RNA_def_property_ui_text(prop, "Fall Speed Max", "Maximum speed at which the character will fall"); /* Collision Masks */ @@ -1812,6 +1820,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "form_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "formfactor"); RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_float_default(prop, 0.4f); RNA_def_property_ui_text(prop, "Form Factor", "Form factor scales the inertia tensor"); prop = RNA_def_property(srna, "use_anisotropic_friction", PROP_BOOLEAN, PROP_NONE); @@ -1844,6 +1853,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "collision_margin", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH); RNA_def_property_float_sdna(prop, NULL, "margin"); RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_float_default(prop, 0.04f); RNA_def_property_ui_text(prop, "Collision Margin", "Extra margin around object for collision detection, small amount required " "for stability"); @@ -1859,6 +1869,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "obstacle_radius", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH); RNA_def_property_float_sdna(prop, NULL, "obstacleRad"); RNA_def_property_range(prop, 0.0, 1000.0); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Obstacle Radius", "Radius of object representation in obstacle simulation"); /* state */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index f671a4b29e5..78e19d2a40d 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -3488,36 +3488,42 @@ static void rna_def_scene_game_recast_data(BlenderRNA *brna) prop = RNA_def_property(srna, "cell_size", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "cellsize"); RNA_def_property_ui_range(prop, 0.1, 1, 1, 2); + RNA_def_property_float_default(prop, 0.3f); RNA_def_property_ui_text(prop, "Cell Size", "Rasterized cell size"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "cell_height", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "cellheight"); RNA_def_property_ui_range(prop, 0.1, 1, 1, 2); + RNA_def_property_float_default(prop, 0.2f); RNA_def_property_ui_text(prop, "Cell Height", "Rasterized cell height"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "agent_height", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "agentheight"); RNA_def_property_ui_range(prop, 0.1, 5, 1, 2); + RNA_def_property_float_default(prop, 2.0f); RNA_def_property_ui_text(prop, "Agent Height", "Minimum height where the agent can still walk"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "agent_radius", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "agentradius"); RNA_def_property_ui_range(prop, 0.1, 5, 1, 2); + RNA_def_property_float_default(prop, 0.6f); RNA_def_property_ui_text(prop, "Agent Radius", "Radius of the agent"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "climb_max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "agentmaxclimb"); RNA_def_property_ui_range(prop, 0.1, 5, 1, 2); + RNA_def_property_float_default(prop, 0.9f); RNA_def_property_ui_text(prop, "Max Climb", "Maximum height between grid cells the agent can climb"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "slope_max", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "agentmaxslope"); RNA_def_property_range(prop, 0, M_PI_2); + RNA_def_property_float_default(prop, M_PI_4); RNA_def_property_ui_text(prop, "Max Slope", "Maximum walkable slope angle"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3525,42 +3531,49 @@ static void rna_def_scene_game_recast_data(BlenderRNA *brna) prop = RNA_def_property(srna, "region_min_size", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "regionminsize"); RNA_def_property_ui_range(prop, 0, 150, 1, 2); + RNA_def_property_float_default(prop, 8.0f); RNA_def_property_ui_text(prop, "Min Region Size", "Minimum regions size (smaller regions will be deleted)"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "region_merge_size", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "regionmergesize"); RNA_def_property_ui_range(prop, 0, 150, 1, 2); + RNA_def_property_float_default(prop, 20.0f); RNA_def_property_ui_text(prop, "Merged Region Size", "Minimum regions size (smaller regions will be merged)"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "edge_max_len", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "edgemaxlen"); RNA_def_property_ui_range(prop, 0, 50, 1, 2); + RNA_def_property_float_default(prop, 12.0f); RNA_def_property_ui_text(prop, "Max Edge Length", "Maximum contour edge length"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "edge_max_error", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "edgemaxerror"); RNA_def_property_ui_range(prop, 0.1, 3.0, 1, 2); + RNA_def_property_float_default(prop, 1.3f); RNA_def_property_ui_text(prop, "Max Edge Error", "Maximum distance error from contour to cells"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "verts_per_poly", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "vertsperpoly"); RNA_def_property_ui_range(prop, 3, 12, 1, -1); + RNA_def_property_int_default(prop, 6); RNA_def_property_ui_text(prop, "Verts Per Poly", "Max number of vertices per polygon"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "sample_dist", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "detailsampledist"); RNA_def_property_ui_range(prop, 0.0, 16.0, 1, 2); + RNA_def_property_float_default(prop, 6.0f); RNA_def_property_ui_text(prop, "Sample Distance", "Detail mesh sample spacing"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "sample_max_error", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "detailsamplemaxerror"); RNA_def_property_ui_range(prop, 0.0, 16.0, 1, 2); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Max Sample Error", "Detail mesh simplification max sample error"); RNA_def_property_update(prop, NC_SCENE, NULL); } @@ -3772,12 +3785,14 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "resolution_x", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "xplay"); RNA_def_property_range(prop, 4, 10000); + RNA_def_property_int_default(prop, 640); RNA_def_property_ui_text(prop, "Resolution X", "Number of horizontal pixels in the screen"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "resolution_y", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "yplay"); RNA_def_property_range(prop, 4, 10000); + RNA_def_property_int_default(prop, 480); RNA_def_property_ui_text(prop, "Resolution Y", "Number of vertical pixels in the screen"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3794,12 +3809,14 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "depth", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "depth"); RNA_def_property_range(prop, 8, 32); + RNA_def_property_int_default(prop, 32); RNA_def_property_ui_text(prop, "Bits", "Display bit depth of full screen display"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "exit_key", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "exitkey"); RNA_def_property_enum_items(prop, event_type_items); + RNA_def_property_enum_default(prop, ESCKEY); RNA_def_property_enum_funcs(prop, NULL, "rna_GameSettings_exit_key_set", NULL); RNA_def_property_ui_text(prop, "Exit Key", "The key that exits the Game Engine"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3814,6 +3831,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "frequency", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "freqplay"); RNA_def_property_range(prop, 4, 2000); + RNA_def_property_int_default(prop, 60); RNA_def_property_ui_text(prop, "Freq", "Display clock frequency of fullscreen display"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3851,12 +3869,14 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "stereo_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "stereomode"); RNA_def_property_enum_items(prop, stereo_modes_items); + RNA_def_property_enum_default(prop, STEREO_ANAGLYPH); RNA_def_property_ui_text(prop, "Stereo Mode", "Stereographic techniques"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "stereo_eye_separation", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "eyeseparation"); RNA_def_property_range(prop, 0.01, 5.0); + RNA_def_property_float_default(prop, 0.1f); RNA_def_property_ui_text(prop, "Eye Separation", "Set the distance between the eyes - the camera focal distance/30 should be fine"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3871,18 +3891,21 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "dome_tessellation", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "dome.res"); RNA_def_property_ui_range(prop, 1, 8, 1, 1); + RNA_def_property_int_default(prop, 4); RNA_def_property_ui_text(prop, "Tessellation", "Tessellation level - check the generated mesh in wireframe mode"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "dome_buffer_resolution", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "dome.resbuf"); RNA_def_property_ui_range(prop, 0.1, 1.0, 0.1, 2); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Buffer Resolution", "Buffer Resolution - decrease it to increase speed"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "dome_angle", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "dome.angle"); RNA_def_property_ui_range(prop, 90, 250, 1, 1); + RNA_def_property_int_default(prop, 180); RNA_def_property_ui_text(prop, "Angle", "Field of View of the Dome - it only works in mode Fisheye and Truncated"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3903,6 +3926,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "physics_engine", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "physicsEngine"); RNA_def_property_enum_items(prop, physics_engine_items); + RNA_def_property_enum_default(prop, WOPHY_BULLET); RNA_def_property_ui_text(prop, "Physics Engine", "Physics engine used for physics simulation in the game engine"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3910,6 +3934,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "gravity"); RNA_def_property_ui_range(prop, 0.0, 25.0, 1, 2); RNA_def_property_range(prop, 0.0, 10000.0); + RNA_def_property_float_default(prop, 9.8f); RNA_def_property_ui_text(prop, "Physics Gravity", "Gravitational constant used for physics simulation in the game engine"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3917,6 +3942,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "occlusion_culling_resolution", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "occlusionRes"); RNA_def_property_range(prop, 128.0, 1024.0); + RNA_def_property_int_default(prop, 128); RNA_def_property_ui_text(prop, "Occlusion Resolution", "Size of the occlusion buffer, use higher value for better precision (slower)"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3925,6 +3951,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "ticrate"); RNA_def_property_ui_range(prop, 1, 60, 1, 1); RNA_def_property_range(prop, 1, 10000); + RNA_def_property_int_default(prop, 60); RNA_def_property_ui_text(prop, "Frames Per Second", "Nominal number of game frames per second " "(physics fixed timestep = 1/fps, independently of actual frame rate)"); @@ -3934,6 +3961,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "maxlogicstep"); RNA_def_property_range(prop, 1, 10000); RNA_def_property_ui_range(prop, 1, 50, 1, 1); + RNA_def_property_int_default(prop, 5); RNA_def_property_ui_text(prop, "Max Logic Steps", "Maximum number of logic frame per game frame if graphics slows down the game, " "higher value allows better synchronization with physics"); @@ -3943,6 +3971,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "maxphystep"); RNA_def_property_range(prop, 1, 10000); RNA_def_property_ui_range(prop, 1, 50, 1, 1); + RNA_def_property_int_default(prop, 5); RNA_def_property_ui_text(prop, "Max Physics Steps", "Maximum number of physics step per game frame if graphics slows down the game, " "higher value allows physics to keep up with realtime"); @@ -3952,6 +3981,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "physubstep"); RNA_def_property_range(prop, 1, 50); RNA_def_property_ui_range(prop, 1, 5, 1, 1); + RNA_def_property_int_default(prop, 1); RNA_def_property_ui_text(prop, "Physics Sub Steps", "Number of simulation substep per physic timestep, " "higher value give better physics precision"); @@ -3961,6 +3991,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "lineardeactthreshold"); RNA_def_property_ui_range(prop, 0.001, 10000.0, 2, 3); RNA_def_property_range(prop, 0.001, 10000.0); + RNA_def_property_float_default(prop, 0.8f); RNA_def_property_ui_text(prop, "Deactivation Linear Threshold", "Linear velocity that an object must be below before the deactivation timer can start"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3969,6 +4000,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "angulardeactthreshold"); RNA_def_property_ui_range(prop, 0.001, 10000.0, 2, 3); RNA_def_property_range(prop, 0.001, 10000.0); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Deactivation Angular Threshold", "Angular velocity that an object must be below before the deactivation timer can start"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -4112,6 +4144,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "level_height", PROP_FLOAT, PROP_ACCELERATION); RNA_def_property_float_sdna(prop, NULL, "levelHeight"); RNA_def_property_range(prop, 0.0f, 200.0f); + RNA_def_property_float_default(prop, 2.0f); RNA_def_property_ui_text(prop, "Level height", "Max difference in heights of obstacles to enable their interaction"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -4140,6 +4173,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "scehysteresis"); RNA_def_property_range(prop, 0, 100); RNA_def_property_ui_range(prop, 0, 100, 10, 1); + RNA_def_property_int_default(prop, 10); RNA_def_property_ui_text(prop, "Hysteresis %", "Minimum distance change required to transition to the previous level of detail"); RNA_def_property_update(prop, NC_SCENE, NULL); -- cgit v1.2.3 From 33cc5ed49517c170d348d8f35988421402201054 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 3 May 2015 05:20:36 +1000 Subject: Cleanup: redundant vars --- source/blender/bmesh/intern/bmesh_queries.c | 4 +--- source/blender/editors/mesh/editmesh_rip.c | 5 ++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index ece4d782a84..031fc68e66f 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -863,7 +863,7 @@ bool BM_vert_is_manifold(const BMVert *v) { BMEdge *e_iter, *e_first, *e_prev; BMLoop *l_iter, *l_first; - int edge_num = 0, loop_num = 0, loop_num_region = 0, boundary_num = 0; + int loop_num = 0, loop_num_region = 0, boundary_num = 0; if (v->e == NULL) { /* loose vert */ @@ -901,8 +901,6 @@ bool BM_vert_is_manifold(const BMVert *v) return false; } } - - edge_num += 1; } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); e_first = l_first->e; diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index cc462bb75a8..e9fc12f3252 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -570,12 +570,11 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve if (v->e) { /* find closest edge to mouse cursor */ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { - const bool is_boundary = BM_edge_is_boundary(e); /* consider wire as boundary for this purpose, * otherwise we can't a face away from a wire edge */ - totboundary_edge += (is_boundary != 0 || BM_edge_is_wire(e)); + totboundary_edge += (BM_edge_is_boundary(e) || BM_edge_is_wire(e)); if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - if (is_boundary == false && BM_edge_is_manifold(e)) { + if (BM_edge_is_manifold(e)) { d = edbm_rip_edgedist_squared(ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT); if ((e2 == NULL) || (d < dist_sq)) { dist_sq = d; -- cgit v1.2.3 From dd48ddd605708a64adb5d78307451ffca0cc1ad3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 3 May 2015 06:15:24 +1000 Subject: BMesh: utility to split isolated loop regions --- source/blender/bmesh/intern/bmesh_core.c | 40 ++++++++++++++++++++++++++++++++ source/blender/bmesh/intern/bmesh_core.h | 1 + 2 files changed, 41 insertions(+) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 06bd6229119..2a69edd47b0 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -2604,6 +2604,46 @@ BMVert *bmesh_urmv_loop_multi( return v_new; } +static void bmesh_edge_vert_swap__recursive(BMEdge *e, BMVert *v_dst, BMVert *v_src) +{ + BMLoop *l_iter, *l_first; + + BLI_assert(ELEM(v_src, e->v1, e->v2)); + bmesh_disk_vert_replace(e, v_dst, v_src); + + l_iter = l_first = e->l; + do { + if (l_iter->v == v_src) { + l_iter->v = v_dst; + if (BM_vert_in_edge(l_iter->prev->e, v_src)) { + bmesh_edge_vert_swap__recursive(l_iter->prev->e, v_dst, v_src); + } + } + else if (l_iter->next->v == v_src) { + l_iter->next->v = v_dst; + if (BM_vert_in_edge(l_iter->next->e, v_src)) { + bmesh_edge_vert_swap__recursive(l_iter->next->e, v_dst, v_src); + } + } + else { + BLI_assert(l_iter->prev->v != v_src); + } + } while ((l_iter = l_iter->radial_next) != l_first); +} + +/** + * This function assumes l_sep is apart of a larger fan which has already been + * isolated by calling bmesh_edge_separate to segragate it radially. + */ +BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep) +{ + BMVert *v_new = BM_vert_create(bm, l_sep->v->co, l_sep->v, BM_CREATE_NOP); + /* passing either 'l_sep->e', 'l_sep->prev->e' will work */ + bmesh_edge_vert_swap__recursive(l_sep->e, v_new, l_sep->v); + BLI_assert(l_sep->v == v_new); + return v_new; +} + /** * \brief Unglue Region Make Vert (URMV) diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index 54656fc8e16..2b100eb7b8d 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -104,6 +104,7 @@ BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep); BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep); BMVert *bmesh_urmv_loop_multi( BMesh *bm, BMLoop **larr, int larr_len); +BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep); void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b); -- cgit v1.2.3 From 6bc8a3f8d3b47c1b8be0ede8293334448ea6bf3f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 3 May 2015 06:15:51 +1000 Subject: BMesh: rip-tool can now split off isolated fans Useful since there wasn't a good way to do this previously. --- source/blender/editors/mesh/editmesh_rip.c | 31 ++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index e9fc12f3252..abd88ae65aa 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -559,9 +559,10 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve } } - /* this should be impossible, but sanity checks are a good thing */ - if (!v) + /* (v == NULL) should be impossible */ + if ((v == NULL) || (v->e == NULL)) { return OPERATOR_CANCELLED; + } is_wire = BM_vert_is_wire(v); @@ -621,6 +622,32 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve } } + if (e2) { + /* Try to split off a non-manifold fan (when we have multiple disconnected fans) */ + + /* note: we're lazy here and first split then check there are any faces remaining, + * this isn't good practice, however its less hassle then checking for multiple-disconnected regions */ + BMLoop *l_sep = e2->l->v == v ? e2->l : e2->l->next; + BMVert *v_new; + BLI_assert(l_sep->v == v); + v_new = bmesh_urmv_loop_region(bm, l_sep); + if (BM_vert_find_first_loop(v)) { + BM_vert_select_set(bm, v, false); + BM_select_history_remove(bm, v); + + BM_vert_select_set(bm, v_new, true); + if (ese.ele) { + BM_select_history_store(bm, v_new); + } + + return OPERATOR_FINISHED; + } + else { + /* rewind */ + BM_vert_splice(bm, v, v_new); + } + } + /* should we go ahead with edge rip or do we need to do special case, split off vertex?: * split off vertex if... * - we cant find an edge - this means we are ripping a faces vert that is connected to other -- cgit v1.2.3 From 9715d4c778a7229783e19a339fd823a944c76359 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Fri, 1 May 2015 12:15:55 +0200 Subject: Added name attribute to instance_geometry nodes (request for Second Life) --- source/blender/collada/SceneExporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index b2d9aed579b..ac8ac2b9867 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -150,7 +150,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) if (!instance_controller_created) { COLLADASW::InstanceGeometry instGeom(mSW); instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation))); - + instGeom.setName(translate_id(id_name(ob))); InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), ob, this->export_settings->active_uv_only); instGeom.add(); -- cgit v1.2.3 From 472b3c582820d32ac39be91a6a884ed09285fe4f Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 3 May 2015 11:55:58 +0200 Subject: We do need to transform lnors in BKE_mesh_transform(), much handy for scripts. --- source/blender/blenkernel/intern/mesh.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 12379bedb36..e66a4d48fc8 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1920,6 +1920,7 @@ void BKE_mesh_transform(Mesh *me, float mat[4][4], bool do_keys) { int i; MVert *mvert = me->mvert; + float (*lnors)[3] = CustomData_get_layer(&me->ldata, CD_NORMAL); for (i = 0; i < me->totvert; i++, mvert++) mul_m4_v3(mat, mvert->co); @@ -1934,7 +1935,17 @@ void BKE_mesh_transform(Mesh *me, float mat[4][4], bool do_keys) } } - /* don't update normals, caller can do this explicitly */ + /* don't update normals, caller can do this explicitly. + * We do update loop normals though, those may not be auto-generated (see e.g. STL import script)! */ + if (lnors) { + float m3[3][3]; + + copy_m3_m4(m3, mat); + normalize_m3(m3); + for (i = 0; i < me->totloop; i++, lnors++) { + mul_m3_v3(m3, *lnors); + } + } } void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys) -- cgit v1.2.3 From 3a808270df31ea438e7ca912b8035920ad24cd4a Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 3 May 2015 15:09:48 +0200 Subject: Fix T44589: No way to add a skin data layer manualy. There are several ways to end up with an object with skin modifier, but no skin data on the geometry. So we need an operator to add it by hands. Also tweaked a bit UI of this modifier. --- .../startup/bl_ui/properties_data_modifier.py | 10 +++--- source/blender/editors/mesh/mesh_data.c | 41 +++++++++++++++++++++- source/blender/editors/mesh/mesh_intern.h | 1 + source/blender/editors/mesh/mesh_ops.c | 1 + 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index 1186992b13e..d6d4e03df39 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -1131,13 +1131,15 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): self.vertex_weight_mask(layout, ob, md) def SKIN(self, layout, ob, md): - layout.operator("object.skin_armature_create", text="Create Armature") + row = layout.row() + row.operator("object.skin_armature_create", text="Create Armature") + row.operator("mesh.customdata_skin_add") layout.separator() - col = layout.column(align=True) - col.prop(md, "branch_smoothing") - col.prop(md, "use_smooth_shade") + row = layout.row(align=True) + row.prop(md, "branch_smoothing") + row.prop(md, "use_smooth_shade") split = layout.split() diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 86991d7dfeb..1d0cd6a2934 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -804,7 +804,7 @@ void MESH_OT_customdata_clear_mask(wmOperatorType *ot) } /* Clear Skin */ -static int mesh_customdata_clear_skin_poll(bContext *C) +static bool mesh_customdata_skin_has(bContext *C) { Object *ob = ED_object_context(C); @@ -819,6 +819,45 @@ static int mesh_customdata_clear_skin_poll(bContext *C) } return false; } + +static int mesh_customdata_skin_add_poll(bContext *C) +{ + return !mesh_customdata_skin_has(C); +} + +static int mesh_customdata_skin_add_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = ED_object_context(C); + Mesh *me = ob->data; + + BKE_mesh_ensure_skin_customdata(me); + + DAG_id_tag_update(&me->id, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); + + return OPERATOR_FINISHED; +} + +void MESH_OT_customdata_skin_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Skin Data"; + ot->idname = "MESH_OT_customdata_skin_add"; + ot->description = "Add a vertex skin layer"; + + /* api callbacks */ + ot->exec = mesh_customdata_skin_add_exec; + ot->poll = mesh_customdata_skin_add_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int mesh_customdata_clear_skin_poll(bContext *C) +{ + return mesh_customdata_skin_has(C); +} + static int mesh_customdata_clear_skin_exec(bContext *C, wmOperator *UNUSED(op)) { return mesh_customdata_clear_exec__internal(C, BM_VERT, CD_MVERT_SKIN); diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index c7355120a57..de7d0f32f6f 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -233,6 +233,7 @@ void MESH_OT_vertex_color_add(struct wmOperatorType *ot); void MESH_OT_vertex_color_remove(struct wmOperatorType *ot); /* no create_mask yet */ void MESH_OT_customdata_clear_mask(struct wmOperatorType *ot); +void MESH_OT_customdata_skin_add(struct wmOperatorType *ot); void MESH_OT_customdata_clear_skin(struct wmOperatorType *ot); void MESH_OT_customdata_custom_splitnormals_add(struct wmOperatorType *ot); void MESH_OT_customdata_custom_splitnormals_clear(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 2855af063c0..31d3f019585 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -152,6 +152,7 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_vertex_color_add); WM_operatortype_append(MESH_OT_vertex_color_remove); WM_operatortype_append(MESH_OT_customdata_clear_mask); + WM_operatortype_append(MESH_OT_customdata_skin_add); WM_operatortype_append(MESH_OT_customdata_clear_skin); WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_add); WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_clear); -- cgit v1.2.3 From 944e0bd7b5e1d94f8206b4e516c8ff59e8a4899a Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 3 May 2015 15:18:27 +0200 Subject: Cleanup: rename clear_skin & clear_mask operators to skin_clear and mask_clear. So that they match all other op names around - and sensible logic as well. --- .../scripts/startup/bl_ui/properties_data_mesh.py | 4 ++-- source/blender/editors/mesh/mesh_data.c | 24 +++++++++++----------- source/blender/editors/mesh/mesh_intern.h | 4 ++-- source/blender/editors/mesh/mesh_ops.c | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index e2b0121cdbe..5416735494b 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -369,8 +369,8 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel): me = context.mesh col = layout.column() - col.operator("mesh.customdata_clear_mask", icon='X') - col.operator("mesh.customdata_clear_skin", icon='X') + col.operator("mesh.customdata_mask_clear", icon='X') + col.operator("mesh.customdata_skin_clear", icon='X') if me.has_custom_normals: col.operator("mesh.customdata_custom_splitnormals_clear", icon='X') diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 1d0cd6a2934..f497cd7a1aa 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -748,7 +748,7 @@ static int mesh_customdata_clear_exec__internal(bContext *C, } /* Clear Mask */ -static int mesh_customdata_clear_mask_poll(bContext *C) +static int mesh_customdata_mask_clear_poll(bContext *C) { Object *ob = ED_object_context(C); if (ob && ob->type == OB_MESH) { @@ -772,7 +772,7 @@ static int mesh_customdata_clear_mask_poll(bContext *C) } return false; } -static int mesh_customdata_clear_mask_exec(bContext *C, wmOperator *UNUSED(op)) +static int mesh_customdata_mask_clear_exec(bContext *C, wmOperator *UNUSED(op)) { int ret_a = mesh_customdata_clear_exec__internal(C, BM_VERT, CD_PAINT_MASK); int ret_b = mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_GRID_PAINT_MASK); @@ -787,17 +787,17 @@ static int mesh_customdata_clear_mask_exec(bContext *C, wmOperator *UNUSED(op)) } } -void MESH_OT_customdata_clear_mask(wmOperatorType *ot) +void MESH_OT_customdata_mask_clear(wmOperatorType *ot) { /* identifiers */ ot->name = "Clear Sculpt-Mask Data"; - ot->idname = "MESH_OT_customdata_clear_mask"; + ot->idname = "MESH_OT_customdata_mask_clear"; ot->description = "Clear vertex sculpt masking data from the mesh"; /* api callbacks */ - ot->exec = mesh_customdata_clear_mask_exec; - ot->poll = mesh_customdata_clear_mask_poll; + ot->exec = mesh_customdata_mask_clear_exec; + ot->poll = mesh_customdata_mask_clear_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -853,26 +853,26 @@ void MESH_OT_customdata_skin_add(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -static int mesh_customdata_clear_skin_poll(bContext *C) +static int mesh_customdata_skin_clear_poll(bContext *C) { return mesh_customdata_skin_has(C); } -static int mesh_customdata_clear_skin_exec(bContext *C, wmOperator *UNUSED(op)) +static int mesh_customdata_skin_clear_exec(bContext *C, wmOperator *UNUSED(op)) { return mesh_customdata_clear_exec__internal(C, BM_VERT, CD_MVERT_SKIN); } -void MESH_OT_customdata_clear_skin(wmOperatorType *ot) +void MESH_OT_customdata_skin_clear(wmOperatorType *ot) { /* identifiers */ ot->name = "Clear Skin Data"; - ot->idname = "MESH_OT_customdata_clear_skin"; + ot->idname = "MESH_OT_customdata_skin_clear"; ot->description = "Clear vertex skin layer"; /* api callbacks */ - ot->exec = mesh_customdata_clear_skin_exec; - ot->poll = mesh_customdata_clear_skin_poll; + ot->exec = mesh_customdata_skin_clear_exec; + ot->poll = mesh_customdata_skin_clear_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index de7d0f32f6f..9226146bc51 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -232,9 +232,9 @@ void MESH_OT_uv_texture_remove(struct wmOperatorType *ot); void MESH_OT_vertex_color_add(struct wmOperatorType *ot); void MESH_OT_vertex_color_remove(struct wmOperatorType *ot); /* no create_mask yet */ -void MESH_OT_customdata_clear_mask(struct wmOperatorType *ot); +void MESH_OT_customdata_mask_clear(struct wmOperatorType *ot); void MESH_OT_customdata_skin_add(struct wmOperatorType *ot); -void MESH_OT_customdata_clear_skin(struct wmOperatorType *ot); +void MESH_OT_customdata_skin_clear(struct wmOperatorType *ot); void MESH_OT_customdata_custom_splitnormals_add(struct wmOperatorType *ot); void MESH_OT_customdata_custom_splitnormals_clear(struct wmOperatorType *ot); void MESH_OT_drop_named_image(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 31d3f019585..197df48d688 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -151,9 +151,9 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_uv_texture_remove); WM_operatortype_append(MESH_OT_vertex_color_add); WM_operatortype_append(MESH_OT_vertex_color_remove); - WM_operatortype_append(MESH_OT_customdata_clear_mask); + WM_operatortype_append(MESH_OT_customdata_mask_clear); WM_operatortype_append(MESH_OT_customdata_skin_add); - WM_operatortype_append(MESH_OT_customdata_clear_skin); + WM_operatortype_append(MESH_OT_customdata_skin_clear); WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_add); WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_clear); WM_operatortype_append(MESH_OT_drop_named_image); -- cgit v1.2.3 From 2775eaf01a87c68f2e092152429774017276b2f9 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 3 May 2015 15:06:17 +0200 Subject: Fix T41893: inconsistent color management on sculpt texture nodes previews. --- source/blender/nodes/texture/node_texture_tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index 93ce469c150..3482227f044 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -337,7 +337,7 @@ int ntreeTexExecTree( data.osatex = osatex; data.target = texres; data.do_preview = preview; - data.do_manage = (shi) ? shi->do_manage : 0; + data.do_manage = (shi) ? shi->do_manage : true; data.thread = thread; data.which_output = which_output; data.cfra = cfra; -- cgit v1.2.3 From 6159f9a55a4edc61c11dbe1b6167fbefd17b6fb9 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 3 May 2015 15:36:47 +0200 Subject: Fix T41739: 3D view solid draw mode missing some material node updates. --- source/blender/makesrna/intern/rna_nodetree.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index da77b9ee6ea..f1b12963c6a 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -2258,8 +2258,13 @@ static void rna_NodeSocketStandard_value_update(struct bContext *C, PointerRNA * nodeFindNode(ntree, sock, &node, NULL); } - if (node) + if (node) { nodeSynchronizeID(node, true); + + /* extra update for sockets that get synced to material */ + if (node->id && ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT)) + WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, node->id); + } } -- cgit v1.2.3 From dced56f02a42481de167dd45542adf6dae2d039d Mon Sep 17 00:00:00 2001 From: Krzysztof Recko Date: Sun, 3 May 2015 16:01:07 +0200 Subject: Fix T44185, Fix T44090: hair texture density working unreliable. "Unexisting" particles must be freed after the unexist flag has been set, which was no longer the case after 78c491e62a5. Reviewers: brecht Differential Revision: https://developer.blender.org/D1213 --- source/blender/blenkernel/intern/particle_system.c | 24 +++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 5a263e24fc4..2576c4576cd 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -559,17 +559,24 @@ static void initialize_all_particles(ParticleSimulationData *sim) ParticleSystem *psys = sim->psys; PARTICLE_P; + LOOP_PARTICLES { + initialize_particle(sim, pa); + } +} + +static void free_unexisting_particles(ParticleSimulationData *sim) +{ + ParticleSystem *psys = sim->psys; + PARTICLE_P; + psys->totunexist = 0; LOOP_PARTICLES { - if ((pa->flag & PARS_UNEXIST)==0) - initialize_particle(sim, pa); - - if (pa->flag & PARS_UNEXIST) + if (pa->flag & PARS_UNEXIST) { psys->totunexist++; + } } - /* Free unexisting particles. */ if (psys->totpart && psys->totunexist == psys->totpart) { if (psys->particles->boid) MEM_freeN(psys->particles->boid); @@ -3790,6 +3797,7 @@ static void system_step(ParticleSimulationData *sim, float cfra) initialize_all_particles(sim); /* reset only just created particles (on startframe all particles are recreated) */ reset_all_particles(sim, 0.0, cfra, oldtotpart); + free_unexisting_particles(sim); if (psys->fluid_springs) { MEM_freeN(psys->fluid_springs); @@ -4136,6 +4144,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) { PARTICLE_P; float disp = psys_get_current_display_percentage(psys); + bool free_unexisting = false; /* Particles without dynamics haven't been reset yet because they don't use pointcache */ if (psys->recalc & PSYS_RECALC_RESET) @@ -4145,6 +4154,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) free_keyed_keys(psys); distribute_particles(&sim, part->from); initialize_all_particles(&sim); + free_unexisting = true; /* flag for possible explode modifiers after this system */ sim.psmd->flag |= eParticleSystemFlag_Pars; @@ -4163,6 +4173,10 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) pa->flag &= ~PARS_NO_DISP; } + /* free unexisting after reseting particles */ + if (free_unexisting) + free_unexisting_particles(&sim); + if (part->phystype == PART_PHYS_KEYED) { psys_count_keyed_targets(&sim); set_keyed_keys(&sim); -- cgit v1.2.3 From d33b564f9178d324349d3a21eef4d6bf9dde1f1b Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 3 May 2015 16:51:16 +0200 Subject: Fix T44591: Set PBone Group operator did not handled predifined group index in its invoke func. --- source/blender/editors/armature/pose_group.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source/blender/editors/armature/pose_group.c b/source/blender/editors/armature/pose_group.c index 413a74d24b5..4d9df06f33f 100644 --- a/source/blender/editors/armature/pose_group.c +++ b/source/blender/editors/armature/pose_group.c @@ -130,6 +130,7 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U { Object *ob = ED_pose_object_from_context(C); bPose *pose; + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type"); uiPopupMenu *pup; uiLayout *layout; @@ -140,6 +141,17 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U if (ELEM(NULL, ob, ob->pose)) return OPERATOR_CANCELLED; pose = ob->pose; + + /* If group index is set, try to use it! */ + if (RNA_property_is_set(op->ptr, prop)) { + const int num_groups = BLI_listbase_count(&pose->agroups); + const int group = RNA_property_int_get(op->ptr, prop); + + /* just use the active group index, and call the exec callback for the calling operator */ + if (group > 0 && group <= num_groups) { + return op->type->exec(C, op); + } + } /* if there's no active group (or active is invalid), create a new menu to find it */ if (pose->active_group <= 0) { -- cgit v1.2.3 From ee7538613a18cc9cdfcd4413bc9dfd15a12e7e2f Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Sun, 3 May 2015 17:52:54 +0200 Subject: Rigidbody: Fix viewport update when changing collision shape in toolbar --- source/blender/editors/physics/rigidbody_object.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c index 9b4f128ef86..c8b944f7d2a 100644 --- a/source/blender/editors/physics/rigidbody_object.c +++ b/source/blender/editors/physics/rigidbody_object.c @@ -348,6 +348,7 @@ static int rigidbody_objects_shape_change_exec(bContext *C, wmOperator *op) if (changed) { /* send updates */ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* done */ return OPERATOR_FINISHED; -- cgit v1.2.3 From dbee63457273f09d9977f0bb0235b4c7b53c8eb0 Mon Sep 17 00:00:00 2001 From: Tamito Kajiyama Date: Sun, 8 Mar 2015 16:47:30 +0900 Subject: Fix typos. --- source/blender/blenkernel/intern/text.c | 2 +- source/blender/python/bmesh/bmesh_py_api.c | 2 +- source/blender/python/mathutils/mathutils_geometry.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 2c588739cad..1966d5af7d1 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -652,7 +652,7 @@ void BKE_text_unlink(Main *bmain, Text *text) } } - /* Freestyle (while looping oer the scene) */ + /* Freestyle (while looping over the scene) */ for (srl = sce->r.layers.first; srl; srl = srl->next) { for (module = srl->freestyleConfig.modules.first; module; module = module->next) { if (module->script == text) diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c index bc14e1ac3a6..f74737ba8f4 100644 --- a/source/blender/python/bmesh/bmesh_py_api.c +++ b/source/blender/python/bmesh/bmesh_py_api.c @@ -108,7 +108,7 @@ PyDoc_STRVAR(bpy_bm_update_edit_mesh_doc, " :type mesh: :class:`bpy.types.Mesh`\n" " :arg tessface: Option to recalculate n-gon tessellation.\n" " :type tessface: boolean\n" -" :arg destructive: Use when grometry has been added or removed.\n" +" :arg destructive: Use when geometry has been added or removed.\n" " :type destructive: boolean\n" ); static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args, PyObject *kw) diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index bb4080decef..ae5c058406f 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -850,7 +850,7 @@ PyDoc_STRVAR(M_Geometry_intersect_point_quad_2d_doc, "\n" " Takes 5 vectors (using only the x and y coordinates): one is the point and the next 4 define the quad, \n" " only the x and y are used from the vectors. Returns 1 if the point is within the quad, otherwise 0.\n" -" Works only with convex quads without singular edges." +" Works only with convex quads without singular edges.\n" "\n" " :arg pt: Point\n" " :type pt: :class:`mathutils.Vector`\n" -- cgit v1.2.3 From 62b13c6d070ac5be86c6ff64cb2b32066f64a0db Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Sun, 3 May 2015 19:12:45 +0200 Subject: BGE: Fix: Activate collision mask/group in UI. --- release/scripts/startup/bl_ui/properties_game.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py index 616c5fdb854..33b19eb0752 100644 --- a/release/scripts/startup/bl_ui/properties_game.py +++ b/release/scripts/startup/bl_ui/properties_game.py @@ -213,11 +213,13 @@ class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, Panel): layout = self.layout game = context.active_object.game - layout.active = game.use_collision_bounds + split = layout.split() + split.active = game.use_collision_bounds - layout.prop(game, "collision_bounds_type", text="Bounds") + col = split.column() + col.prop(game, "collision_bounds_type", text="Bounds") - row = layout.row() + row = col.row() row.prop(game, "collision_margin", text="Margin", slider=True) sub = row.row() -- cgit v1.2.3 From 4e7ef3f5cd8cd96545c3250a93bf856174ee54e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Mon, 4 May 2015 12:04:09 +0800 Subject: BGE: Added 'ghost' arg to KX_GameObject.suspendDynamics() method The implementation of this 'ghost' argument already existed in the C++ source, but wasn't exposed to Python yet. --- doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst | 12 ++++++++++-- source/gameengine/Ketsji/KX_GameObject.cpp | 12 +++++++++--- source/gameengine/Ketsji/KX_GameObject.h | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst index 7b2f68b019c..672df3728a9 100644 --- a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst +++ b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst @@ -84,6 +84,8 @@ base class --- :class:`SCA_IObject` :type: boolean + .. seealso:: :py:meth:`suspendDynamics` and :py:meth:`restoreDynamics` allow you to change the state. + .. attribute:: linearDamping The object's linear damping, also known as translational damping. Can be set simultaneously with angular damping using the :py:meth:`setDamping` method. @@ -671,13 +673,19 @@ base class --- :class:`SCA_IObject` :arg angular_damping: Angular ("rotational") damping factor. :type angular_damping: float ∈ [0, 1] - .. method:: suspendDynamics() + .. method:: suspendDynamics([ghost]) Suspends physics for this object. + :arg ghost: When set to `True`, collisions with the object will be ignored, similar to the "ghost" checkbox in + Blender. When `False` (the default), the object becomes static but still collide with other objects. + :type ghost: bool + + .. seealso:: :py:attr:`isSuspendDynamics` allows you to inspect whether the object is in a suspended state. + .. method:: restoreDynamics() - Resumes physics for this object. + Resumes physics for this object. Also reinstates collisions; the object will no longer be a ghost. .. note:: diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index e464883016e..44d9bfa0cf4 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1907,7 +1907,7 @@ PyMethodDef KX_GameObject::Methods[] = { {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS}, {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS}, {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O}, - {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS}, + {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics, METH_VARARGS}, {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS}, {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS}, {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS}, @@ -3318,10 +3318,16 @@ PyObject *KX_GameObject::PyApplyImpulse(PyObject *args) -PyObject *KX_GameObject::PySuspendDynamics() +PyObject *KX_GameObject::PySuspendDynamics(PyObject *args) { + bool ghost = false; + + if (!PyArg_ParseTuple(args, "|b", &ghost)) + return NULL; + if (GetPhysicsController()) - GetPhysicsController()->SuspendDynamics(); + GetPhysicsController()->SuspendDynamics(ghost); + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 9b85572bec2..9c081b449ec 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -1005,7 +1005,7 @@ public: KX_PYMETHOD_O(KX_GameObject,SetState); KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect); KX_PYMETHOD_O(KX_GameObject,GetAxisVect); - KX_PYMETHOD_NOARGS(KX_GameObject,SuspendDynamics); + KX_PYMETHOD_VARARGS(KX_GameObject,SuspendDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,RestoreDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,EnableRigidBody); KX_PYMETHOD_NOARGS(KX_GameObject,DisableRigidBody); -- cgit v1.2.3 From fdc5f9c0a81bba0be6bab5120cdfc955d63265d5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 May 2015 12:25:33 +1000 Subject: Add name argument to data creation API calls Was adding then renaming, unnecessarily. --- source/blender/blenkernel/BKE_image.h | 2 +- source/blender/blenkernel/BKE_object.h | 17 +++++-- source/blender/blenkernel/intern/image.c | 8 +++- source/blender/blenkernel/intern/object.c | 52 ++++++++++++---------- source/blender/blenloader/intern/readfile.c | 1 - source/blender/collada/collada_utils.cpp | 2 +- source/blender/editors/curve/editcurve_add.c | 18 ++------ source/blender/editors/curve/editfont.c | 2 +- source/blender/editors/include/ED_object.h | 6 ++- source/blender/editors/mesh/editmesh_add.c | 5 +-- source/blender/editors/mesh/mesh_navmesh.c | 3 +- source/blender/editors/object/object_add.c | 40 ++++++++--------- source/blender/editors/object/object_constraint.c | 2 +- source/blender/editors/object/object_hook.c | 5 ++- source/blender/editors/object/object_modifier.c | 4 +- source/blender/editors/object/object_relations.c | 6 +-- .../editors/sculpt_paint/paint_image_proj.c | 4 +- .../editors/space_outliner/outliner_tools.c | 3 +- 18 files changed, 91 insertions(+), 89 deletions(-) diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index abfe0e98acf..155f26d9bd9 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -177,7 +177,7 @@ struct Image *BKE_image_load_exists(const char *filepath); struct Image *BKE_image_add_generated( struct Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4], const bool stereo3d); /* adds image from imbuf, owns imbuf */ -struct Image *BKE_image_add_from_imbuf(struct ImBuf *ibuf); +struct Image *BKE_image_add_from_imbuf(struct ImBuf *ibuf, const char *name); /* for reload, refresh, pack */ void BKE_image_init_imageuser(struct Image *ima, struct ImageUser *iuser); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 0ddc9b0b256..0e0c779c033 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -33,6 +33,8 @@ extern "C" { #endif +#include "BLI_compiler_attrs.h" + struct Base; struct EvaluationContext; struct Scene; @@ -82,9 +84,18 @@ bool BKE_object_is_in_editmode(struct Object *ob); bool BKE_object_is_in_editmode_vgroup(struct Object *ob); bool BKE_object_is_in_wpaint_select_vert(struct Object *ob); -struct Object *BKE_object_add_only_object(struct Main *bmain, int type, const char *name); -struct Object *BKE_object_add(struct Main *bmain, struct Scene *scene, int type); -void *BKE_object_obdata_add_from_type(struct Main *bmain, int type); +struct Object *BKE_object_add_only_object( + struct Main *bmain, + int type, const char *name) + ATTR_NONNULL(1) ATTR_RETURNS_NONNULL; +struct Object *BKE_object_add( + struct Main *bmain, struct Scene *scene, + int type, const char *name) + ATTR_NONNULL(1, 2) ATTR_RETURNS_NONNULL; +void *BKE_object_obdata_add_from_type( + struct Main *bmain, + int type, const char *name) + ATTR_NONNULL(1); void BKE_object_lod_add(struct Object *ob); void BKE_object_lod_sort(struct Object *ob); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index eceb5c4ff20..b714e8b7eac 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -883,12 +883,16 @@ Image *BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int hei /* Create an image image from ibuf. The refcount of ibuf is increased, * caller should take care to drop its reference by calling * IMB_freeImBuf if needed. */ -Image *BKE_image_add_from_imbuf(ImBuf *ibuf) +Image *BKE_image_add_from_imbuf(ImBuf *ibuf, const char *name) { /* on save, type is changed to FILE in editsima.c */ Image *ima; - ima = image_alloc(G.main, BLI_path_basename(ibuf->name), IMA_SRC_FILE, IMA_TYPE_IMAGE); + if (name == NULL) { + name = BLI_path_basename(ibuf->name); + } + + ima = image_alloc(G.main, name, IMA_SRC_FILE, IMA_TYPE_IMAGE); if (ima) { BLI_strncpy(ima->name, ibuf->name, FILE_MAX); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 6f373ef0576..034c0833b9c 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -938,26 +938,6 @@ bool BKE_object_exists_check(Object *obtest) /* *************************************************** */ -void *BKE_object_obdata_add_from_type(Main *bmain, int type) -{ - switch (type) { - case OB_MESH: return BKE_mesh_add(bmain, "Mesh"); - case OB_CURVE: return BKE_curve_add(bmain, "Curve", OB_CURVE); - case OB_SURF: return BKE_curve_add(bmain, "Surf", OB_SURF); - case OB_FONT: return BKE_curve_add(bmain, "Text", OB_FONT); - case OB_MBALL: return BKE_mball_add(bmain, "Meta"); - case OB_CAMERA: return BKE_camera_add(bmain, "Camera"); - case OB_LAMP: return BKE_lamp_add(bmain, "Lamp"); - case OB_LATTICE: return BKE_lattice_add(bmain, "Lattice"); - case OB_ARMATURE: return BKE_armature_add(bmain, "Armature"); - case OB_SPEAKER: return BKE_speaker_add(bmain, "Speaker"); - case OB_EMPTY: return NULL; - default: - printf("BKE_object_obdata_add_from_type: Internal error, bad type: %d\n", type); - return NULL; - } -} - static const char *get_obdata_defname(int type) { switch (type) { @@ -978,6 +958,30 @@ static const char *get_obdata_defname(int type) } } +void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name) +{ + if (name == NULL) { + name = get_obdata_defname(type); + } + + switch (type) { + case OB_MESH: return BKE_mesh_add(bmain, name); + case OB_CURVE: return BKE_curve_add(bmain, name, OB_CURVE); + case OB_SURF: return BKE_curve_add(bmain, name, OB_SURF); + case OB_FONT: return BKE_curve_add(bmain, name, OB_FONT); + case OB_MBALL: return BKE_mball_add(bmain, name); + case OB_CAMERA: return BKE_camera_add(bmain, name); + case OB_LAMP: return BKE_lamp_add(bmain, name); + case OB_LATTICE: return BKE_lattice_add(bmain, name); + case OB_ARMATURE: return BKE_armature_add(bmain, name); + case OB_SPEAKER: return BKE_speaker_add(bmain, name); + case OB_EMPTY: return NULL; + default: + printf("%s: Internal error, bad type: %d\n", __func__, type); + return NULL; + } +} + /* more general add: creates minimum required data, but without vertices etc. */ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name) { @@ -1063,16 +1067,16 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name) /* general add: to scene, with layer from area and default name */ /* creates minimum required data, but without vertices etc. */ -Object *BKE_object_add(Main *bmain, Scene *scene, int type) +Object *BKE_object_add( + Main *bmain, Scene *scene, + int type, const char *name) { Object *ob; Base *base; - char name[MAX_ID_NAME]; - BLI_strncpy(name, get_obdata_defname(type), sizeof(name)); ob = BKE_object_add_only_object(bmain, type, name); - ob->data = BKE_object_obdata_add_from_type(bmain, type); + ob->data = BKE_object_obdata_add_from_type(bmain, type, name); ob->lay = scene->lay; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 2aaa84bc056..d8d56e4cfd8 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -9241,7 +9241,6 @@ static void give_base_to_groups(Main *mainvar, Scene *scene) /* assign the group */ ob->dup_group = group; ob->transflag |= OB_DUPLIGROUP; - rename_id(&ob->id, group->id.name + 2); copy_v3_v3(ob->loc, scene->cursor); } } diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index f15efa89ea6..d3813e2fb7a 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -131,7 +131,7 @@ Object *bc_add_object(Scene *scene, int type, const char *name) { Object *ob = BKE_object_add_only_object(G.main, type, name); - ob->data = BKE_object_obdata_add_from_type(G.main, type); + ob->data = BKE_object_obdata_add_from_type(G.main, type, name); ob->lay = scene->lay; DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c index d319adca388..555a53ae532 100644 --- a/source/blender/editors/curve/editcurve_add.c +++ b/source/blender/editors/curve/editcurve_add.c @@ -488,9 +488,10 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) if (!isSurf) { /* adding curve */ if (obedit == NULL || obedit->type != OB_CURVE) { + const char *name = get_curve_defname(type); Curve *cu; - obedit = ED_object_add_type(C, OB_CURVE, loc, rot, true, layer); + obedit = ED_object_add_type(C, OB_CURVE, name, loc, rot, true, layer); newob = true; cu = (Curve *)obedit->data; @@ -505,7 +506,8 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) } else { /* adding surface */ if (obedit == NULL || obedit->type != OB_SURF) { - obedit = ED_object_add_type(C, OB_SURF, loc, rot, true, layer); + const char *name = get_surf_defname(type); + obedit = ED_object_add_type(C, OB_SURF, name, loc, rot, true, layer); newob = true; } else { @@ -513,18 +515,6 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) } } - /* rename here, the undo stack checks name for valid undo pushes */ - if (newob) { - if (obedit->type == OB_CURVE) { - rename_id((ID *)obedit, get_curve_defname(type)); - rename_id((ID *)obedit->data, get_curve_defname(type)); - } - else { - rename_id((ID *)obedit, get_surf_defname(type)); - rename_id((ID *)obedit->data, get_surf_defname(type)); - } - } - /* ED_object_add_type doesnt do an undo, is needed for redo operator on primitive */ if (newob && enter_editmode) ED_undo_push(C, "Enter Editmode"); diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 303aa2ccded..7eaa9afd814 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -526,7 +526,7 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const int a; float rot[3] = {0.f, 0.f, 0.f}; - obedit = BKE_object_add(bmain, scene, OB_FONT); + obedit = BKE_object_add(bmain, scene, OB_FONT, NULL); base = scene->basact; /* seems to assume view align ? TODO - look into this, could be an operator option */ diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 3b7157bd465..c52174c8f2d 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -138,8 +138,10 @@ bool ED_object_add_generic_get_opts(struct bContext *C, struct wmOperator *op, c bool *enter_editmode, unsigned int *layer, bool *is_view_aligned); struct Object *ED_object_add_type( - struct bContext *C, int type, const float loc[3], const float rot[3], - bool enter_editmode, unsigned int layer) ATTR_RETURNS_NONNULL; + struct bContext *C, + int type, const char *name, const float loc[3], const float rot[3], + bool enter_editmode, unsigned int layer) + ATTR_NONNULL(1) ATTR_RETURNS_NONNULL; void ED_object_single_users(struct Main *bmain, struct Scene *scene, const bool full, const bool copy_groups); void ED_object_single_user(struct Main *bmain, struct Scene *scene, struct Object *ob); diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 6ce5e8a304b..c67ee41703a 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -62,10 +62,7 @@ static Object *make_prim_init(bContext *C, const char *idname, *was_editmode = false; if (obedit == NULL || obedit->type != OB_MESH) { - obedit = ED_object_add_type(C, OB_MESH, loc, rot, false, layer); - - rename_id((ID *)obedit, idname); - rename_id((ID *)obedit->data, idname); + obedit = ED_object_add_type(C, OB_MESH, idname, loc, rot, false, layer); /* create editmode */ ED_object_editmode_enter(C, EM_DO_UNDO | EM_IGNORE_LAYER); /* rare cases the active layer is messed up */ diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c index 440ab14dacd..0d9f6f2a0be 100644 --- a/source/blender/editors/mesh/mesh_navmesh.c +++ b/source/blender/editors/mesh/mesh_navmesh.c @@ -325,7 +325,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, if (createob) { /* create new object */ - obedit = ED_object_add_type(C, OB_MESH, co, rot, false, lay); + obedit = ED_object_add_type(C, OB_MESH, "Navmesh", co, rot, false, lay); } else { obedit = base->object; @@ -429,7 +429,6 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, obedit->gameflag &= ~OB_COLLISION; obedit->gameflag |= OB_NAVMESH; obedit->body_type = OB_BODY_TYPE_NAVMESH; - rename_id((ID *)obedit, "Navmesh"); } BKE_mesh_ensure_navmesh(obedit->data); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 37faa7ba664..27d77f0635e 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -394,8 +394,11 @@ bool ED_object_add_generic_get_opts(bContext *C, wmOperator *op, const char view /* For object add primitive operators. * Do not call undo push in this function (users of this function have to). */ -Object *ED_object_add_type(bContext *C, int type, const float loc[3], const float rot[3], - bool enter_editmode, unsigned int layer) +Object *ED_object_add_type( + bContext *C, + int type, const char *name, + const float loc[3], const float rot[3], + bool enter_editmode, unsigned int layer) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -406,7 +409,7 @@ Object *ED_object_add_type(bContext *C, int type, const float loc[3], const floa ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */ /* deselects all, sets scene->basact */ - ob = BKE_object_add(bmain, scene, type); + ob = BKE_object_add(bmain, scene, type, name); BASACT->lay = ob->lay = layer; /* editor level activate, notifiers */ ED_base_object_activate(C, BASACT); @@ -447,7 +450,7 @@ static int object_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; radius = RNA_float_get(op->ptr, "radius"); - ob = ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), loc, rot, enter_editmode, layer); + ob = ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), NULL, loc, rot, enter_editmode, layer); if (ob->type == OB_LATTICE) { /* lattice is a special case! @@ -504,9 +507,9 @@ static int effector_add_exec(bContext *C, wmOperator *op) if (type == PFIELD_GUIDE) { Curve *cu; - ob = ED_object_add_type(C, OB_CURVE, loc, rot, false, layer); + const char *name = CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "CurveGuide"); + ob = ED_object_add_type(C, OB_CURVE, name, loc, rot, false, layer); - rename_id(&ob->id, CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "CurveGuide")); cu = ob->data; cu->flag |= CU_PATH | CU_3D; ED_object_editmode_enter(C, 0); @@ -516,9 +519,9 @@ static int effector_add_exec(bContext *C, wmOperator *op) ED_object_editmode_exit(C, EM_FREEDATA); } else { - ob = ED_object_add_type(C, OB_EMPTY, loc, rot, false, layer); + const char *name = CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "Field"); + ob = ED_object_add_type(C, OB_EMPTY, name, loc, rot, false, layer); BKE_object_obdata_size_init(ob, dia); - rename_id(&ob->id, CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "Field")); if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX)) ob->empty_drawtype = OB_SINGLE_ARROW; } @@ -569,7 +572,7 @@ static int object_camera_add_exec(bContext *C, wmOperator *op) if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; - ob = ED_object_add_type(C, OB_CAMERA, loc, rot, false, layer); + ob = ED_object_add_type(C, OB_CAMERA, NULL, loc, rot, false, layer); if (v3d) { if (v3d->camera == NULL) @@ -626,7 +629,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; if (obedit == NULL || obedit->type != OB_MBALL) { - obedit = ED_object_add_type(C, OB_MBALL, loc, rot, true, layer); + obedit = ED_object_add_type(C, OB_MBALL, NULL, loc, rot, true, layer); newob = true; } else { @@ -685,7 +688,7 @@ static int object_add_text_exec(bContext *C, wmOperator *op) if (obedit && obedit->type == OB_FONT) return OPERATOR_CANCELLED; - obedit = ED_object_add_type(C, OB_FONT, loc, rot, enter_editmode, layer); + obedit = ED_object_add_type(C, OB_FONT, NULL, loc, rot, enter_editmode, layer); BKE_object_obdata_size_init(obedit, RNA_float_get(op->ptr, "radius")); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); @@ -729,7 +732,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; if ((obedit == NULL) || (obedit->type != OB_ARMATURE)) { - obedit = ED_object_add_type(C, OB_ARMATURE, loc, rot, true, layer); + obedit = ED_object_add_type(C, OB_ARMATURE, NULL, loc, rot, true, layer); ED_object_editmode_enter(C, 0); newob = true; } @@ -786,7 +789,7 @@ static int object_empty_add_exec(bContext *C, wmOperator *op) if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL)) return OPERATOR_CANCELLED; - ob = ED_object_add_type(C, OB_EMPTY, loc, rot, false, layer); + ob = ED_object_add_type(C, OB_EMPTY, NULL, loc, rot, false, layer); BKE_object_empty_draw_type_set(ob, type); BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius")); @@ -846,7 +849,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv if (!ED_object_add_generic_get_opts(C, op, 'Z', NULL, rot, NULL, &layer, NULL)) return OPERATOR_CANCELLED; - ob = ED_object_add_type(C, OB_EMPTY, NULL, rot, false, layer); + ob = ED_object_add_type(C, OB_EMPTY, NULL, NULL, rot, false, layer); /* add under the mouse */ ED_object_location_from_view(C, ob->loc); @@ -916,13 +919,11 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op) if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL)) return OPERATOR_CANCELLED; - ob = ED_object_add_type(C, OB_LAMP, loc, rot, false, layer); + ob = ED_object_add_type(C, OB_LAMP, get_lamp_defname(type), loc, rot, false, layer); BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius")); la = (Lamp *)ob->data; la->type = type; - rename_id(&ob->id, get_lamp_defname(type)); - rename_id(&la->id, get_lamp_defname(type)); if (BKE_scene_use_new_shading_nodes(scene)) { ED_node_shader_default(C, &la->id); @@ -988,8 +989,7 @@ static int group_instance_add_exec(bContext *C, wmOperator *op) if (group) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Object *ob = ED_object_add_type(C, OB_EMPTY, loc, rot, false, layer); - rename_id(&ob->id, group->id.name + 2); + Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, loc, rot, false, layer); ob->dup_group = group; ob->transflag |= OB_DUPLIGROUP; id_lib_extern(&group->id); @@ -1044,7 +1044,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL)) return OPERATOR_CANCELLED; - ob = ED_object_add_type(C, OB_SPEAKER, loc, rot, false, layer); + ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, layer); /* to make it easier to start using this immediately in NLA, a default sound clip is created * ready to be moved around to retime the sound and/or make new sound clips diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index d459dd417c7..f214741467f 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -1662,7 +1662,7 @@ static short get_new_constraint_target(bContext *C, int con_type, Object **tar_o Object *obt; /* add new target object */ - obt = BKE_object_add(bmain, scene, OB_EMPTY); + obt = BKE_object_add(bmain, scene, OB_EMPTY, NULL); /* set layers OK */ newbase = BASACT; diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 1d764ced524..8797b75a801 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -448,11 +448,12 @@ static Object *add_hook_object_new(Main *bmain, Scene *scene, Object *obedit) Base *base, *basedit; Object *ob; - ob = BKE_object_add(bmain, scene, OB_EMPTY); + ob = BKE_object_add(bmain, scene, OB_EMPTY, NULL); basedit = BKE_scene_base_find(scene, obedit); - base = BKE_scene_base_find(scene, ob); + base = scene->basact; base->lay = ob->lay = obedit->lay; + BLI_assert(scene->basact->object == ob); /* icky, BKE_object_add sets new base as active. * so set it back to the original edit object */ diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index ac5ec1976ab..1cee54c33fa 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -459,7 +459,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene * if (totvert == 0) return 0; /* add new mesh */ - obn = BKE_object_add(bmain, scene, OB_MESH); + obn = BKE_object_add(bmain, scene, OB_MESH, NULL); me = obn->data; me->totvert = totvert; @@ -1704,7 +1704,7 @@ static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, Object * NULL, me->totvert); - arm_ob = BKE_object_add(bmain, scene, OB_ARMATURE); + arm_ob = BKE_object_add(bmain, scene, OB_ARMATURE, NULL); BKE_object_transform_copy(arm_ob, skin_ob); arm = arm_ob->data; arm->layer = 1; diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 2d981594524..19648c291f7 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -342,12 +342,10 @@ static int make_proxy_exec(bContext *C, wmOperator *op) Base *newbase, *oldbase = BASACT; char name[MAX_ID_NAME + 4]; - /* Add new object for the proxy */ - newob = BKE_object_add(bmain, scene, OB_EMPTY); - BLI_snprintf(name, sizeof(name), "%s_proxy", ((ID *)(gob ? gob : ob))->name + 2); - rename_id(&newob->id, name); + /* Add new object for the proxy */ + newob = BKE_object_add(bmain, scene, OB_EMPTY, name); /* set layers OK */ newbase = BASACT; /* BKE_object_add sets active... */ diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 4085f13999d..70127d0d425 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -5474,7 +5474,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - image = BKE_image_add_from_imbuf(ibuf); + image = BKE_image_add_from_imbuf(ibuf, "image_view"); /* Drop reference to ibuf so that the image owns it */ IMB_freeImBuf(ibuf); @@ -5504,8 +5504,6 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) array[2] = is_ortho ? 1.0f : 0.0f; IDP_AddToGroup(idgroup, view_data); - - rename_id(&image->id, "image_view"); } return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 4c4378e004e..66863b8061b 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -427,8 +427,7 @@ static void group_instance_cb(bContext *C, Scene *scene, TreeElement *UNUSED(te) { Group *group = (Group *)tselem->id; - Object *ob = ED_object_add_type(C, OB_EMPTY, scene->cursor, NULL, false, scene->layact); - rename_id(&ob->id, group->id.name + 2); + Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, scene->cursor, NULL, false, scene->layact); ob->dup_group = group; ob->transflag |= OB_DUPLIGROUP; id_lib_extern(&group->id); -- cgit v1.2.3 From 8515be8a739b2ce88f7eb8f46d8a46df15d25231 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 May 2015 15:55:52 +1000 Subject: Remove redundant outliner lookup freeing objects --- source/blender/blenkernel/intern/object.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 034c0833b9c..111aa84e688 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -809,16 +809,7 @@ void BKE_object_unlink(Object *ob) } } else if (sl->spacetype == SPACE_OUTLINER) { - SpaceOops *so = (SpaceOops *)sl; - - if (so->treestore) { - TreeStoreElem *tselem; - BLI_mempool_iter iter; - BLI_mempool_iternew(so->treestore, &iter); - while ((tselem = BLI_mempool_iterstep(&iter))) { - if (tselem->id == (ID *)ob) tselem->id = NULL; - } - } + /* now handled by WM_main_remove_editor_id_reference */ } else if (sl->spacetype == SPACE_BUTS) { SpaceButs *sbuts = (SpaceButs *)sl; -- cgit v1.2.3 From da8a62adcedecf1a7f7f21f47c2ad8153649b423 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 May 2015 12:29:38 +1000 Subject: Cleanup: naming for callback wrappers --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/BKE_library.h | 4 ++-- source/blender/blenkernel/intern/blender.c | 2 +- source/blender/blenkernel/intern/library.c | 4 ++-- source/blender/windowmanager/intern/wm_init_exit.c | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 081553826f4..80332c08fc2 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -87,7 +87,7 @@ void BKE_userdef_free(void); void BKE_userdef_state(void); /* set this callback when a UI is running */ -void set_blender_test_break_cb(void (*func)(void)); +void BKE_blender_callback_test_break_set(void (*func)(void)); int blender_test_break(void); #define BKE_UNDO_STR_MAX 64 diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index e88a4e88209..f00bd0754a3 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -107,8 +107,8 @@ void BKE_library_make_local(struct Main *bmain, struct Library *lib, bool untagg struct ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -void set_free_windowmanager_cb(void (*func)(struct bContext *, struct wmWindowManager *)); -void set_free_notifier_reference_cb(void (*func)(const void *)); +void BKE_library_callback_free_window_manager_set(void (*func)(struct bContext *, struct wmWindowManager *)); +void BKE_library_callback_free_notifier_reference_set(void (*func)(const void *)); /* use when "" is given to new_id() */ #define ID_FALLBACK_NAME N_("Untitled") diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 2085fefdb93..37bd9c5db5c 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -623,7 +623,7 @@ int BKE_write_file_userdef(const char *filepath, ReportList *reports) static void (*blender_test_break_cb)(void) = NULL; -void set_blender_test_break_cb(void (*func)(void)) +void BKE_blender_callback_test_break_set(void (*func)(void)) { blender_test_break_cb = func; } diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 2cee08a821b..ccc373b6eb4 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -865,14 +865,14 @@ static void BKE_library_free(Library *lib) static void (*free_windowmanager_cb)(bContext *, wmWindowManager *) = NULL; -void set_free_windowmanager_cb(void (*func)(bContext *C, wmWindowManager *) ) +void BKE_library_callback_free_window_manager_set(void (*func)(bContext *C, wmWindowManager *) ) { free_windowmanager_cb = func; } static void (*free_notifier_reference_cb)(const void *) = NULL; -void set_free_notifier_reference_cb(void (*func)(const void *) ) +void BKE_library_callback_free_notifier_reference_set(void (*func)(const void *) ) { free_notifier_reference_cb = func; } diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 71a025f3660..add09aa4c1f 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -149,9 +149,9 @@ void WM_init(bContext *C, int argc, const char **argv) WM_menutype_init(); WM_uilisttype_init(); - set_free_windowmanager_cb(wm_close_and_free); /* library.c */ - set_free_notifier_reference_cb(WM_main_remove_notifier_reference); /* library.c */ - set_blender_test_break_cb(wm_window_testbreak); /* blender.c */ + BKE_library_callback_free_window_manager_set(wm_close_and_free); /* library.c */ + BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference); /* library.c */ + BKE_blender_callback_test_break_set(wm_window_testbreak); /* blender.c */ DAG_editors_update_cb(ED_render_id_flush_update, ED_render_scene_update); /* depsgraph.c */ ED_spacetypes_init(); /* editors/space_api/spacetype.c */ -- cgit v1.2.3 From 8d5e57748a777a76dbbe85d432d7d8364775713a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 May 2015 12:40:38 +1000 Subject: Cleanup: WM_main_remove_notifier_reference Assumed the `reference` pointer is an ID, currently true, but may not always be. Add a callback specifically for this purpose since cleaning up notifiers and space-types are different operations. --- source/blender/blenkernel/BKE_library.h | 1 + source/blender/blenkernel/intern/library.c | 13 ++++++++++++- source/blender/windowmanager/WM_api.h | 1 + source/blender/windowmanager/intern/wm_event_system.c | 9 +++++++-- source/blender/windowmanager/intern/wm_init_exit.c | 1 + 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index f00bd0754a3..6ecc955e26c 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -109,6 +109,7 @@ struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_ void BKE_library_callback_free_window_manager_set(void (*func)(struct bContext *, struct wmWindowManager *)); void BKE_library_callback_free_notifier_reference_set(void (*func)(const void *)); +void BKE_library_callback_free_editor_id_reference_set(void (*func)(const struct ID *)); /* use when "" is given to new_id() */ #define ID_FALLBACK_NAME N_("Untitled") diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index ccc373b6eb4..42856e82062 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -877,6 +877,12 @@ void BKE_library_callback_free_notifier_reference_set(void (*func)(const void *) free_notifier_reference_cb = func; } +static void (*free_editor_id_reference_cb)(const ID *) = NULL; + +void BKE_library_callback_free_editor_id_reference_set(void (*func)(const ID *)) +{ + free_editor_id_reference_cb = func; +} static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata) { @@ -1034,8 +1040,13 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user) /* avoid notifying on removed data */ BKE_main_lock(bmain); - if (free_notifier_reference_cb) + if (free_notifier_reference_cb) { free_notifier_reference_cb(id); + } + + if (free_editor_id_reference_cb) { + free_editor_id_reference_cb(id); + } BLI_remlink(lb, id); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index dbeea80ba82..d4148a56dd2 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -175,6 +175,7 @@ bool WM_modal_tweak_exit(const struct wmEvent *event, int tweak_event); void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference); void WM_main_add_notifier(unsigned int type, void *reference); void WM_main_remove_notifier_reference(const void *reference); +void WM_main_remove_editor_id_reference(const struct ID *id); /* reports */ void WM_report(const struct bContext *C, ReportType type, const char *message); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index c883b37f6c5..f054c5a43c1 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -218,7 +218,6 @@ void WM_main_remove_notifier_reference(const void *reference) { Main *bmain = G.main; wmWindowManager *wm = bmain->wm.first; - bScreen *sc; if (wm) { wmNotifier *note, *note_next; @@ -233,6 +232,12 @@ void WM_main_remove_notifier_reference(const void *reference) } } } +} + +void WM_main_remove_editor_id_reference(const ID *id) +{ + Main *bmain = G.main; + bScreen *sc; for (sc = bmain->screen.first; sc; sc = sc->id.next) { ScrArea *sa; @@ -244,7 +249,7 @@ void WM_main_remove_notifier_reference(const void *reference) if (sl->spacetype == SPACE_OUTLINER) { SpaceOops *so = (SpaceOops *)sl; - ED_outliner_id_unref(so, (ID *)reference); + ED_outliner_id_unref(so, id); } } } diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index add09aa4c1f..7ca82c0c03a 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -151,6 +151,7 @@ void WM_init(bContext *C, int argc, const char **argv) BKE_library_callback_free_window_manager_set(wm_close_and_free); /* library.c */ BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference); /* library.c */ + BKE_library_callback_free_editor_id_reference_set(WM_main_remove_editor_id_reference); /* library.c */ BKE_blender_callback_test_break_set(wm_window_testbreak); /* blender.c */ DAG_editors_update_cb(ED_render_id_flush_update, ED_render_scene_update); /* depsgraph.c */ -- cgit v1.2.3 From 77e6a001a96b7eb3b2b1c2216a48c85c1b6906e0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 May 2015 15:07:24 +1000 Subject: Fix T44376: Buttons context, invalid data access Removing a scene from the buttons window would crash from a Python operator. --- source/blender/blenkernel/BKE_screen.h | 3 +++ source/blender/blenkernel/intern/scene.c | 3 +++ source/blender/blenkernel/intern/screen.c | 13 +++++++++++ source/blender/editors/include/ED_buttons.h | 2 ++ source/blender/editors/include/ED_screen.h | 1 - source/blender/editors/include/ED_util.h | 2 ++ .../editors/space_buttons/buttons_context.c | 26 ++++++++++++++++++++++ source/blender/editors/util/ed_util.c | 21 +++++++++++++++++ source/blender/windowmanager/intern/wm_init_exit.c | 1 + 9 files changed, 71 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index bb764540da9..c584051708b 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -273,6 +273,9 @@ void BKE_spacedata_freelist(ListBase *lb); void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2); void BKE_spacedata_draw_locks(int set); +void BKE_spacedata_callback_id_unref_set(void (*func)(struct SpaceLink *sl, const struct ID *)); +void BKE_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id); + /* area/regions */ struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar); void BKE_area_region_free(struct SpaceType *st, struct ARegion *ar); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 5b34504184a..c24649556fc 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -82,6 +82,7 @@ #include "BKE_paint.h" #include "BKE_rigidbody.h" #include "BKE_scene.h" +#include "BKE_screen.h" #include "BKE_sequencer.h" #include "BKE_sound.h" #include "BKE_unit.h" @@ -823,6 +824,8 @@ static void scene_unlink_space_buts(SpaceButs *sbuts, Scene *sce) if (sbuts->pinid == &sce->id) { sbuts->pinid = NULL; } + + BKE_spacedata_id_unref((SpaceLink *)sbuts, &sce->id); } void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce) diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 36fd598cc70..840e1f99f84 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -272,6 +272,19 @@ void BKE_spacedata_draw_locks(int set) } } +static void (*spacedata_id_unref_cb)(struct SpaceLink *sl, const struct ID *id) = NULL; + +void BKE_spacedata_callback_id_unref_set(void (*func)(struct SpaceLink *sl, const struct ID *)) +{ + spacedata_id_unref_cb = func; +} + +void BKE_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id) +{ + if (spacedata_id_unref_cb) { + spacedata_id_unref_cb(sl, id); + } +} /* not region itself */ void BKE_area_region_free(SpaceType *st, ARegion *ar) diff --git a/source/blender/editors/include/ED_buttons.h b/source/blender/editors/include/ED_buttons.h index 64c16605dec..9a987d7618c 100644 --- a/source/blender/editors/include/ED_buttons.h +++ b/source/blender/editors/include/ED_buttons.h @@ -37,4 +37,6 @@ bool ED_texture_context_check_particles(const struct bContext *C); bool ED_texture_context_check_linestyle(const struct bContext *C); bool ED_texture_context_check_others(const struct bContext *C); +void ED_buttons_id_unref(struct SpaceButs *sbuts, const struct ID *id); + #endif /* __ED_BUTTONS_H__ */ diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 5b0b4642644..8de9a7f5f88 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -76,7 +76,6 @@ void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect); void ED_spacetypes_keymap(struct wmKeyConfig *keyconf); int ED_area_header_switchbutton(const struct bContext *C, struct uiBlock *block, int yco); - /* areas */ void ED_area_initialize(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *sa); void ED_area_exit(struct bContext *C, struct ScrArea *sa); diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index 9556c601d1f..496ce7f2c60 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -42,6 +42,8 @@ void ED_editors_exit(struct bContext *C); bool ED_editors_flush_edits(const struct bContext *C, bool for_render); +void ED_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id); + /* ************** Undo ************************ */ /* undo.c */ diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 73091e7f261..b00a2c54ff9 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -59,6 +59,7 @@ #include "RNA_access.h" +#include "ED_buttons.h" #include "ED_armature.h" #include "ED_screen.h" #include "ED_physics.h" @@ -1179,3 +1180,28 @@ ID *buttons_context_id_path(const bContext *C) return NULL; } + +void ED_buttons_id_unref(SpaceButs *sbuts, const ID *id) +{ + if (sbuts->path) { + ButsContextPath *path = sbuts->path; + int i; + + for (i = 0; i < path->len; i++) { + if (path->ptr[i].id.data == id) { + break; + } + } + + if (i == path->len) { + /* pass */ + } + else if (i == 0) { + MEM_SAFE_FREE(sbuts->path); + } + else { + memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i)); + path->len = i; + } + } +} diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 438eb1f3864..d162becfe98 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -38,6 +38,7 @@ #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_screen_types.h" +#include "DNA_space_types.h" #include "DNA_scene_types.h" #include "DNA_packedFile_types.h" @@ -58,9 +59,11 @@ #include "BKE_paint.h" #include "ED_armature.h" +#include "ED_buttons.h" #include "ED_image.h" #include "ED_mesh.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_paint.h" #include "ED_space_api.h" #include "ED_util.h" @@ -318,3 +321,21 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info glEnd(); setlinestyle(0); } + +/** + * Use to free ID references within runtime data (stored outside of DNA) + * + * \note Typically notifiers take care of this, + * but there are times we have to free references immediately, see: T44376 + */ +void ED_spacedata_id_unref(struct SpaceLink *sl, const ID *id) +{ + switch (sl->spacetype) { + case SPACE_OUTLINER: + ED_outliner_id_unref((SpaceOops *)sl, id); + break; + case SPACE_BUTS: + ED_buttons_id_unref((SpaceButs *)sl, id); + break; + } +} diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 7ca82c0c03a..b5c267e8a39 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -153,6 +153,7 @@ void WM_init(bContext *C, int argc, const char **argv) BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference); /* library.c */ BKE_library_callback_free_editor_id_reference_set(WM_main_remove_editor_id_reference); /* library.c */ BKE_blender_callback_test_break_set(wm_window_testbreak); /* blender.c */ + BKE_spacedata_callback_id_unref_set(ED_spacedata_id_unref); /* screen.c */ DAG_editors_update_cb(ED_render_id_flush_update, ED_render_scene_update); /* depsgraph.c */ ED_spacetypes_init(); /* editors/space_api/spacetype.c */ -- cgit v1.2.3 From c9e5e81064d4ce4863d113ea5dc3773500f01d7d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 May 2015 16:12:12 +1000 Subject: Button Space: clear pin flag when NULL'ing pointer --- source/blender/blenkernel/intern/scene.c | 1 + source/blender/blenloader/intern/readfile.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index c24649556fc..495b3516c0d 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -823,6 +823,7 @@ static void scene_unlink_space_buts(SpaceButs *sbuts, Scene *sce) { if (sbuts->pinid == &sce->id) { sbuts->pinid = NULL; + sbuts->flag &= ~SB_PIN_CONTEXT; } BKE_spacedata_id_unref((SpaceLink *)sbuts, &sce->id); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index d8d56e4cfd8..4efb61a7efc 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5975,6 +5975,9 @@ static void lib_link_screen(FileData *fd, Main *main) else if (sl->spacetype == SPACE_BUTS) { SpaceButs *sbuts = (SpaceButs *)sl; sbuts->pinid = newlibadr(fd, sc->id.lib, sbuts->pinid); + if (sbuts->pinid == NULL) { + sbuts->flag &= ~SB_PIN_CONTEXT; + } } else if (sl->spacetype == SPACE_FILE) { ; @@ -6304,6 +6307,9 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc else if (sl->spacetype == SPACE_BUTS) { SpaceButs *sbuts = (SpaceButs *)sl; sbuts->pinid = restore_pointer_by_name(newmain, sbuts->pinid, USER_IGNORE); + if (sbuts->pinid == NULL) { + sbuts->flag &= ~SB_PIN_CONTEXT; + } /* TODO: restore path pointers: T40046 * (complicated because this contains data pointers too, not just ID)*/ -- cgit v1.2.3 From 74dc4e87a6df2826f26eb94eaff8fe02a3911c24 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 May 2015 18:02:56 +1000 Subject: Fix Buttons context, invalid object data access Another instance of T44376. Crash where the Python context would access a stale pointer to the active object. --- source/blender/blenkernel/intern/object.c | 20 ++------- source/blender/blenkernel/intern/scene.c | 49 ++-------------------- source/blender/editors/include/ED_node.h | 2 + .../editors/space_buttons/buttons_context.c | 5 +++ source/blender/editors/space_node/node_edit.c | 28 +++++++++++++ source/blender/editors/util/ed_util.c | 5 +++ .../blender/windowmanager/intern/wm_event_system.c | 6 +-- 7 files changed, 47 insertions(+), 68 deletions(-) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 111aa84e688..bd0b7275174 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -808,25 +808,11 @@ void BKE_object_unlink(Object *ob) } } } - else if (sl->spacetype == SPACE_OUTLINER) { +#if 0 + else if (ELEM(sl->spacetype, SPACE_OUTLINER, SPACE_BUTS, SPACE_NODE)) { /* now handled by WM_main_remove_editor_id_reference */ } - else if (sl->spacetype == SPACE_BUTS) { - SpaceButs *sbuts = (SpaceButs *)sl; - - if (sbuts->pinid == (ID *)ob) { - sbuts->flag &= ~SB_PIN_CONTEXT; - sbuts->pinid = NULL; - } - } - else if (sl->spacetype == SPACE_NODE) { - SpaceNode *snode = (SpaceNode *)sl; - - if (snode->from == (ID *)ob) { - snode->flag &= ~SNODE_PIN; - snode->from = NULL; - } - } +#endif } sa = sa->next; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 495b3516c0d..052308bfac8 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -799,36 +799,6 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name) return NULL; } -static void scene_unlink_space_node(SpaceNode *snode, Scene *sce) -{ - if (snode->id == &sce->id) { - /* nasty DNA logic for SpaceNode: - * ideally should be handled by editor code, but would be bad level call - */ - bNodeTreePath *path, *path_next; - for (path = snode->treepath.first; path; path = path_next) { - path_next = path->next; - MEM_freeN(path); - } - BLI_listbase_clear(&snode->treepath); - - snode->id = NULL; - snode->from = NULL; - snode->nodetree = NULL; - snode->edittree = NULL; - } -} - -static void scene_unlink_space_buts(SpaceButs *sbuts, Scene *sce) -{ - if (sbuts->pinid == &sce->id) { - sbuts->pinid = NULL; - sbuts->flag &= ~SB_PIN_CONTEXT; - } - - BKE_spacedata_id_unref((SpaceLink *)sbuts, &sce->id); -} - void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce) { Scene *sce1; @@ -853,24 +823,11 @@ void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce) /* all screens */ for (screen = bmain->screen.first; screen; screen = screen->id.next) { - ScrArea *area; - - if (screen->scene == sce) + if (screen->scene == sce) { screen->scene = newsce; - - for (area = screen->areabase.first; area; area = area->next) { - SpaceLink *space_link; - for (space_link = area->spacedata.first; space_link; space_link = space_link->next) { - switch (space_link->spacetype) { - case SPACE_NODE: - scene_unlink_space_node((SpaceNode *)space_link, sce); - break; - case SPACE_BUTS: - scene_unlink_space_buts((SpaceButs *)space_link, sce); - break; - } - } } + + /* editors are handled by WM_main_remove_editor_id_reference */ } BKE_libblock_free(bmain, sce); diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index b02ebeb650b..1445308c485 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -103,6 +103,8 @@ void ED_node_set_active(struct Main *bmain, struct bNodeTree *ntree, struct bNod void ED_node_composite_job(const struct bContext *C, struct bNodeTree *nodetree, struct Scene *scene_owner); +void ED_node_id_unref(struct SpaceNode *snode, const ID *id); + /* node_ops.c */ void ED_operatormacros_node(void); diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index b00a2c54ff9..bc42f1dd5bb 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -1183,6 +1183,11 @@ ID *buttons_context_id_path(const bContext *C) void ED_buttons_id_unref(SpaceButs *sbuts, const ID *id) { + if (sbuts->pinid == id) { + sbuts->pinid = NULL; + sbuts->flag &= ~SB_PIN_CONTEXT; + } + if (sbuts->path) { ButsContextPath *path = sbuts->path; int i; diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 360087d77c7..ffd51bcc44e 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -740,6 +740,34 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) } } +void ED_node_id_unref(SpaceNode *snode, const ID *id) +{ + if (GS(id->name) == ID_SCE) { + if (snode->id == id) { + /* nasty DNA logic for SpaceNode: + * ideally should be handled by editor code, but would be bad level call + */ + bNodeTreePath *path, *path_next; + for (path = snode->treepath.first; path; path = path_next) { + path_next = path->next; + MEM_freeN(path); + } + BLI_listbase_clear(&snode->treepath); + + snode->id = NULL; + snode->from = NULL; + snode->nodetree = NULL; + snode->edittree = NULL; + } + } + else if (GS(id->name) == ID_OB) { + if (snode->from == id) { + snode->flag &= ~SNODE_PIN; + snode->from = NULL; + } + } +} + void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree)) { /* XXX This does not work due to layout functions relying on node->block, diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index d162becfe98..433c7603f35 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -62,6 +62,7 @@ #include "ED_buttons.h" #include "ED_image.h" #include "ED_mesh.h" +#include "ED_node.h" #include "ED_object.h" #include "ED_outliner.h" #include "ED_paint.h" @@ -330,6 +331,7 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info */ void ED_spacedata_id_unref(struct SpaceLink *sl, const ID *id) { + switch (sl->spacetype) { case SPACE_OUTLINER: ED_outliner_id_unref((SpaceOops *)sl, id); @@ -337,5 +339,8 @@ void ED_spacedata_id_unref(struct SpaceLink *sl, const ID *id) case SPACE_BUTS: ED_buttons_id_unref((SpaceButs *)sl, id); break; + case SPACE_NODE: + ED_node_id_unref((SpaceNode *)sl, id); + break; } } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index f054c5a43c1..69bee8bab80 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -246,11 +246,7 @@ void WM_main_remove_editor_id_reference(const ID *id) SpaceLink *sl; for (sl = sa->spacedata.first; sl; sl = sl->next) { - if (sl->spacetype == SPACE_OUTLINER) { - SpaceOops *so = (SpaceOops *)sl; - - ED_outliner_id_unref(so, id); - } + ED_spacedata_id_unref(sl, id); } } } -- cgit v1.2.3 From 4edc9d50fddd7119dd664d48ecb1086c7baf1e37 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 May 2015 18:32:47 +1000 Subject: Correct own error in recent quad-view ruler fix --- source/blender/editors/space_view3d/view3d_ruler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index addda0a8b66..98b1e846c70 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -188,8 +188,8 @@ typedef struct RulerInfo { /* wm state */ wmWindow *win; ScrArea *sa; - ARegion *ar; void *draw_handle_pixel; + ARegion *ar; /* re-assigned every modal update */ } RulerInfo; /* -------------------------------------------------------------------- */ @@ -828,7 +828,7 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event) int exit_code = OPERATOR_RUNNING_MODAL; RulerInfo *ruler_info = op->customdata; ScrArea *sa = CTX_wm_area(C); - ARegion *ar = ruler_info->ar; + ARegion *ar = CTX_wm_region(C); RegionView3D *rv3d = ar->regiondata; /* its possible to change spaces while running the operator [#34894] */ -- cgit v1.2.3 From 7a8170e9c17780ea0751cceefee2331d7d04aedb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 May 2015 18:33:37 +1000 Subject: CMake: Only consider it INFO is ld.gold is missing --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 44f6b2f8752..ea1ca3d37b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1171,7 +1171,7 @@ if(UNIX AND NOT APPLE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=gold") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold") else () - message(WARNING "GNU gold linker isn't available, using the default system linker.") + message(INFO "GNU gold linker isn't available, using the default system linker.") endif () unset(LD_VERSION) -- cgit v1.2.3 From c46f40e9e28c84405ae81d506f90e8d51b75fa0f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 4 May 2015 13:51:51 +0500 Subject: Freestyle: Compilation error fix after recent changes in BKE_object_add() --- .../freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index 0e8f6222c8c..1ddc311b1ae 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -126,7 +126,7 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str BKE_scene_set_background(freestyle_bmain, freestyle_scene); // Camera - Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, OB_CAMERA); + Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, OB_CAMERA, NULL); Camera *camera = (Camera *)object_camera->data; camera->type = CAM_ORTHO; -- cgit v1.2.3 From 4e1c27f646493931d4c45f348160cd0bc92ce680 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 May 2015 19:11:08 +1000 Subject: Fix T29029: Grease pencil fails in Quad View --- source/blender/editors/gpencil/gpencil_paint.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 767ef7d16d7..e902f9552b5 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1254,6 +1254,7 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode) /* when drawing in the camera view, in 2D space, set the subrect */ + p->subrect = NULL; if (!(p->gpd->flag & GP_DATA_VIEWALIGN)) { if (p->sa->spacetype == SPACE_VIEW3D) { View3D *v3d = p->sa->spacedata.first; @@ -1779,6 +1780,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event else { /* toolbar invoked - don't start drawing yet... */ /* printf("\tGP - hotkey invoked... waiting for click-drag\n"); */ + op->flag |= OP_IS_MODAL_CURSOR_REGION; } WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); @@ -1816,8 +1818,10 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) if (gp_session_initdata(C, p)) gp_paint_initstroke(p, p->paintmode); - if (p->status != GP_STATUS_ERROR) + if (p->status != GP_STATUS_ERROR) { p->status = GP_STATUS_PAINTING; + op->flag &= ~OP_IS_MODAL_CURSOR_REGION; + } return op->customdata; } @@ -1833,6 +1837,7 @@ static void gpencil_stroke_end(wmOperator *op) gp_session_cleanup(p); p->status = GP_STATUS_IDLING; + op->flag |= OP_IS_MODAL_CURSOR_REGION; p->gpd = NULL; p->gpl = NULL; @@ -1858,6 +1863,11 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) * in 3D space. */ + if (p->status == GP_STATUS_IDLING) { + ARegion *ar = CTX_wm_region(C); + p->ar = ar; + } + /* we don't pass on key events, GP is used with key-modifiers - prevents Dkey to insert drivers */ if (ISKEYBOARD(event->type)) { if (ELEM(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY, ZKEY)) { @@ -2021,6 +2031,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } else { p->status = GP_STATUS_IDLING; + op->flag |= OP_IS_MODAL_CURSOR_REGION; } } -- cgit v1.2.3 From 23a79c42b5efce2c0d1aa27bd01751380ca9fb41 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 4 May 2015 14:38:46 +0500 Subject: BGE Player: Fix compilation error after cleanup commit da8a62a --- source/gameengine/GamePlayer/ghost/GPG_ghost.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index a4c9472df2f..9e5b1464ac0 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -519,7 +519,7 @@ int main(int argc, char** argv) BKE_sound_init_once(); - set_free_windowmanager_cb(wm_free); + BKE_library_callback_free_window_manager_set(wm_free); /* if running blenderplayer the last argument can't be parsed since it has to be the filename. else it is bundled */ isBlenderPlayer = !BLO_is_a_runtime(argv[0]); -- cgit v1.2.3 From 711e2f71a80923e0b1d5acc0b6634c0b326238b6 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 4 May 2015 12:17:49 +0200 Subject: Support displaying metadata for images in sequencer preview windows (not backdrop) --- release/scripts/startup/bl_ui/space_sequencer.py | 1 + source/blender/blenkernel/intern/sequencer.c | 9 +++++-- source/blender/editors/include/ED_screen.h | 2 +- source/blender/editors/screen/area.c | 17 +++++------- source/blender/editors/space_image/image_draw.c | 11 ++++++-- .../editors/space_sequencer/sequencer_draw.c | 30 +++++++++++++--------- source/blender/makesdna/DNA_space_types.h | 1 + source/blender/makesrna/intern/rna_space.c | 5 ++++ source/blender/makesrna/intern/rna_userdef.c | 12 +++++++++ 9 files changed, 61 insertions(+), 27 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 3aed000223c..0d512b263ac 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -207,6 +207,7 @@ class SEQUENCER_MT_view(Menu): if is_preview: if st.display_mode == 'IMAGE': layout.prop(st, "show_safe_areas") + layout.prop(st, "show_metadata") elif st.display_mode == 'WAVEFORM': layout.prop(st, "show_separate_color") diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index d1893513a4f..f31d30bed35 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -2423,6 +2423,7 @@ static ImBuf *input_preprocess(const SeqRenderData *context, Sequence *seq, floa IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy); sequencer_imbuf_assign_spaces(scene, i); + IMB_metadata_copy(i, ibuf); IMB_freeImBuf(ibuf); ibuf = i; @@ -2474,6 +2475,7 @@ static ImBuf *input_preprocess(const SeqRenderData *context, Sequence *seq, floa ImBuf *ibuf_new = BKE_sequence_modifier_apply_stack(context, seq, ibuf, cfra); if (ibuf_new != ibuf) { + IMB_metadata_copy(ibuf_new, ibuf); IMB_freeImBuf(ibuf); ibuf = ibuf_new; } @@ -2496,6 +2498,7 @@ static ImBuf *copy_from_ibuf_still(const SeqRenderData *context, Sequence *seq, if (ibuf) { rval = IMB_dupImBuf(ibuf); + IMB_metadata_copy(rval, ibuf); IMB_freeImBuf(ibuf); } @@ -2509,9 +2512,11 @@ static void copy_to_ibuf_still(const SeqRenderData *context, Sequence *seq, floa /* we have to store a copy, since the passed ibuf * could be preprocessed afterwards (thereby silently * changing the cached image... */ - ibuf = IMB_dupImBuf(ibuf); + ImBuf *oibuf = ibuf; + ibuf = IMB_dupImBuf(oibuf); if (ibuf) { + IMB_metadata_copy(ibuf, oibuf); sequencer_imbuf_assign_spaces(context->scene, ibuf); } @@ -2721,7 +2726,7 @@ static ImBuf *seq_render_image_strip(const SeqRenderData *context, Sequence *seq BLI_path_abs(name, G.main->name); } - flag = IB_rect; + flag = IB_rect | IB_metadata; if (seq->alpha_mode == SEQ_ALPHA_PREMUL) flag |= IB_alphamode_premul; diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 8de9a7f5f88..7f6679b827b 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -66,7 +66,7 @@ void ED_region_header_init(struct ARegion *ar); void ED_region_header(const struct bContext *C, struct ARegion *ar); void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar); void ED_region_info_draw(struct ARegion *ar, const char *text, int block, float fill_color[4]); -void ED_region_image_metadata_draw(struct ARegion *ar, struct ImBuf *ibuf, float zoomx, float zoomy); +void ED_region_image_metadata_draw(int x, int y, struct ImBuf *ibuf, rctf frame, float zoomx, float zoomy); void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy); float ED_region_blend_factor(struct ARegion *ar); void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 0bd05b8c9e8..89b6d3b4f73 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2088,7 +2088,7 @@ BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index, int off return (IMB_metadata_get_field(ibuf, meta_data_list[index], r_str + offset, MAX_METADATA_STR - offset) && r_str[0]); } -static void metadata_draw_imbuf(ImBuf *ibuf, rcti rect, int fontid, const bool is_top) +static void metadata_draw_imbuf(ImBuf *ibuf, rctf rect, int fontid, const bool is_top) { char temp_str[MAX_METADATA_STR]; int line_width; @@ -2192,19 +2192,16 @@ static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top) #undef MAX_METADATA_STR -void ED_region_image_metadata_draw(ARegion *ar, ImBuf *ibuf, float zoomx, float zoomy) +void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, rctf frame, float zoomx, float zoomy) { float box_y; - rcti rect; - int x, y; + rctf rect; uiStyle *style = UI_style_get_dpi(); if (!ibuf->metadata) return; /* find window pixel coordinates of origin */ - UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y); - glPushMatrix(); /* offset and zoom using ogl */ @@ -2222,9 +2219,9 @@ void ED_region_image_metadata_draw(ARegion *ar, ImBuf *ibuf, float zoomx, float UI_ThemeColor(TH_METADATA_BG); /* set up rect */ - BLI_rcti_init(&rect, 0, ibuf->x, ibuf->y, ibuf->y + box_y); + BLI_rctf_init(&rect, frame.xmin, frame.xmax, frame.ymax, frame.ymax + box_y); /* draw top box */ - glRecti(rect.xmin, rect.ymin, rect.xmax, rect.ymax); + glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax); BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax); BLF_enable(blf_mono_font, BLF_CLIPPING); @@ -2244,9 +2241,9 @@ void ED_region_image_metadata_draw(ARegion *ar, ImBuf *ibuf, float zoomx, float UI_ThemeColor(TH_METADATA_BG); /* set up box rect */ - BLI_rcti_init(&rect, 0, ibuf->x, -box_y, 0); + BLI_rctf_init(&rect, frame.xmin, frame.xmax, frame.ymin - box_y, frame.ymin); /* draw top box */ - glRecti(rect.xmin, rect.ymin, rect.xmax, rect.ymax); + glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax); BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax); BLF_enable(blf_mono_font, BLF_CLIPPING); diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 04e874bbae1..36419ccd10d 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -848,8 +848,15 @@ void draw_image_main(const bContext *C, ARegion *ar) else draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy); - if (sima->flag & SI_DRAW_METADATA) - ED_region_image_metadata_draw(ar, ibuf, zoomx, zoomy); + if (sima->flag & SI_DRAW_METADATA) { + int x, y; + rctf frame; + + BLI_rctf_init(&frame, 0.0f, ibuf->x, 0.0f, ibuf->y); + UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y); + + ED_region_image_metadata_draw(x, y, ibuf, frame, zoomx, zoomy); + } } ED_space_image_release_buffer(sima, ibuf, lock); diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index abe2e866a75..0c811ca1af7 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -63,6 +63,7 @@ #include "ED_markers.h" #include "ED_mask.h" #include "ED_sequencer.h" +#include "ED_screen.h" #include "ED_space_api.h" #include "UI_interface.h" @@ -1068,6 +1069,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq bool glsl_used = false; const bool draw_gpencil = ((sseq->flag & SEQ_SHOW_GPENCIL) && sseq->gpd); const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + bool draw_metadata = false; if (G.is_rendering == false && (scene->r.seq_flag & R_SEQ_GL_PREV) == 0) { /* stop all running jobs, except screen one. currently previews frustrate Render @@ -1303,10 +1305,12 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq } } else if (draw_backdrop) { - float aspect = BLI_rcti_size_x(&ar->winrct) / (float)BLI_rcti_size_y(&ar->winrct); + float aspect; float image_aspect = viewrect[0] / viewrect[1]; float imagex, imagey; - + + aspect = BLI_rcti_size_x(&ar->winrct) / (float)BLI_rcti_size_y(&ar->winrct); + if (aspect >= image_aspect) { imagex = image_aspect / aspect; imagey = 1.0f; @@ -1315,28 +1319,22 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq imagex = 1.0f; imagey = aspect / image_aspect; } - + glTexCoord2f(0.0f, 0.0f); glVertex2f(-imagex, -imagey); glTexCoord2f(0.0f, 1.0f); glVertex2f(-imagex, imagey); glTexCoord2f(1.0f, 1.0f); glVertex2f(imagex, imagey); glTexCoord2f(1.0f, 0.0f); glVertex2f(imagex, -imagey); } else { + draw_metadata = ((sseq->flag & SEQ_SHOW_METADATA) != 0); + glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin); glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax); glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax); glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin); } glEnd(); - - if (draw_backdrop) { - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - - } - + glBindTexture(GL_TEXTURE_2D, last_texid); glDisable(GL_TEXTURE_2D); if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) @@ -1352,7 +1350,15 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq if (!scope) IMB_freeImBuf(ibuf); + if (draw_metadata) { + ED_region_image_metadata_draw(0.0, 0.0, ibuf, v2d->tot, 1.0, 1.0); + } + if (draw_backdrop) { + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); return; } diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 075995c2924..d6785da7486 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -534,6 +534,7 @@ typedef enum eSpaceSeq_Flag { SEQ_ALL_WAVEFORMS = (1 << 7), /* draw all waveforms */ SEQ_NO_WAVEFORMS = (1 << 8), /* draw no waveforms */ SEQ_SHOW_SAFE_CENTER = (1 << 9), + SEQ_SHOW_METADATA = (1 << 10), } eSpaceSeq_Flag; /* sseq->view */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index b02c69c54ef..2b7ed3dc057 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -3074,6 +3074,11 @@ static void rna_def_space_sequencer(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Center-Cut Safe Areas", "Show safe areas to fit content in a different aspect ratio"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); + prop = RNA_def_property(srna, "show_metadata", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_METADATA); + RNA_def_property_ui_text(prop, "Show Metadata", "Show metadata of first visible strip"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); + prop = RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SEQ_DRAWFRAMES); RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 58f355bdf52..a441f2f57dc 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2500,6 +2500,18 @@ static void rna_def_userdef_theme_space_seq(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Preview Background", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "metadatabg", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "metadatabg"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Metadata Background", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "metadatatext", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "metadatatext"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Metadata Text", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); } static void rna_def_userdef_theme_space_action(BlenderRNA *brna) -- cgit v1.2.3 From b07c2961fac3a461c4bc42115dc05d87df4b7143 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 4 May 2015 12:30:26 +0200 Subject: Don't scale metadata font with zoom - makes strings not consistently adhere to the string length --- source/blender/editors/screen/area.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 89b6d3b4f73..a0ab8de0101 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2208,7 +2208,7 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, rctf frame, float glTranslatef(x, y, 0.0f); glScalef(zoomx, zoomy, 1.0f); - BLF_size(blf_mono_font, style->widgetlabel.points * zoomy * 1.5f, U.dpi); + BLF_size(blf_mono_font, style->widgetlabel.points * 1.5f, U.dpi); /* *** upper box*** */ -- cgit v1.2.3 From 046388830ac854b4ff4a6bdf6e8107c550884992 Mon Sep 17 00:00:00 2001 From: Tamito Kajiyama Date: Mon, 4 May 2015 15:45:32 +0900 Subject: Freestyle: Fix for line style ID datablocks not copied when fully copying a scene. --- source/blender/blenkernel/intern/scene.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 052308bfac8..887bcbeb3fc 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -75,6 +75,7 @@ #include "BKE_idprop.h" #include "BKE_image.h" #include "BKE_library.h" +#include "BKE_linestyle.h" #include "BKE_main.h" #include "BKE_mask.h" #include "BKE_node.h" @@ -155,6 +156,7 @@ Scene *BKE_scene_copy(Scene *sce, int type) { Scene *scen; SceneRenderLayer *srl, *new_srl; + FreestyleLineSet *lineset; ToolSettings *ts; Base *base, *obase; @@ -238,6 +240,14 @@ Scene *BKE_scene_copy(Scene *sce, int type) new_srl = scen->r.layers.first; for (srl = sce->r.layers.first; srl; srl = srl->next) { BKE_freestyle_config_copy(&new_srl->freestyleConfig, &srl->freestyleConfig); + if (type == SCE_COPY_FULL) { + for (lineset = new_srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { + if (lineset->linestyle) { + id_us_plus((ID *)lineset->linestyle); + lineset->linestyle = BKE_linestyle_copy(G.main, lineset->linestyle); + } + } + } new_srl = new_srl->next; } } -- cgit v1.2.3 From 93055b1c2293ca0e4db35641193b778f48d7aff5 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 4 May 2015 12:52:58 +0200 Subject: Fix metadata display in sequencer lost after doing a preprocess transform. IMB_makeSingleUser makes a copy and destroys metadata. I am not sure if this is the safest way to make a single user ImBuf (setting the refcount to 0 is simpler and there's less, but no zero, risk of dangling pointers) but I will leave this as is for now in case there is an actual need for a copy here. The alternative approach should be tested at some point. --- source/blender/blenkernel/intern/sequencer.c | 2 ++ source/blender/imbuf/intern/allocimbuf.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index f31d30bed35..bb48023de56 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -3588,6 +3588,8 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seq out = seq_render_strip_stack_apply_effect(context, seq, cfra, ibuf1, ibuf2); + IMB_metadata_copy(out, ibuf2); + IMB_freeImBuf(ibuf1); IMB_freeImBuf(ibuf2); } diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index 18c3aeb8942..79f869968d3 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -210,6 +210,8 @@ ImBuf *IMB_makeSingleUser(ImBuf *ibuf) rval = IMB_dupImBuf(ibuf); + IMB_metadata_copy(rval, ibuf); + IMB_freeImBuf(ibuf); return rval; -- cgit v1.2.3 From 8d5eeab473110ee102b68fedfe74b4404f7cc07f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 4 May 2015 20:25:59 +1000 Subject: Skin Modifier: Add missing operator stack pop --- source/blender/modifiers/intern/MOD_skin.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index bd16fd07044..02515360f3a 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -1783,6 +1783,9 @@ static BMesh *build_skin(SkinNode *skin_nodes, skin_output_connections(&so, skin_nodes, medge, totedge); hull_merge_triangles(&so, smd); + bmesh_edit_end(so.bm, 0); + BMO_pop(so.bm); + return so.bm; } -- cgit v1.2.3 From abd68c6e45a67ff682f13000d1ae2f8b79edea22 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 May 2015 20:36:43 +1000 Subject: Fix T42893: Skin Modifier, changes randomly toggling editmode Own regression, previously it would do a full mesh normal calculation for each isolated shape (could hang on meshes with many loose parts). However the normals are needed, instead of doing a full calculation, just set normals on new faces. Thanks to Brecht for finding cause! --- source/blender/modifiers/intern/MOD_skin.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 02515360f3a..155c76638f9 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -249,6 +249,7 @@ static bool build_hull(SkinOutput *so, Frame **frames, int totframe) /* Apply face attributes to hull output */ BMO_ITER (f, &oiter, op.slots_out, "geom.out", BM_FACE) { + BM_face_normal_update(f); if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING) BM_elem_flag_enable(f, BM_ELEM_SMOOTH); f->mat_nr = so->mat_nr; @@ -960,6 +961,7 @@ static void add_poly(SkinOutput *so, BLI_assert(v1 && v2 && v3); f = BM_face_create_verts(so->bm, verts, v4 ? 4 : 3, NULL, BM_CREATE_NO_DOUBLE, true); + BM_face_normal_update(f); if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING) BM_elem_flag_enable(f, BM_ELEM_SMOOTH); f->mat_nr = so->mat_nr; @@ -1421,6 +1423,9 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd) if (adj[0]->len == 3 && adj[1]->len == 3) { BMVert *quad[4]; + BLI_assert(BM_face_is_normal_valid(adj[0])); + BLI_assert(BM_face_is_normal_valid(adj[1])); + /* Construct quad using the two triangles adjacent to * the edge */ quad_from_tris(e, adj, quad); -- cgit v1.2.3 From 7e3ee2d15dc3e11b4b2be778eb600653c8561523 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 May 2015 20:59:34 +1000 Subject: Skin Modifier: remove redundant edge-calculation --- source/blender/modifiers/intern/MOD_skin.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 155c76638f9..50b1404a8e5 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -1852,7 +1852,6 @@ static DerivedMesh *base_skin(DerivedMesh *origdm, result = CDDM_from_bmesh(bm, false); BM_mesh_free(bm); - CDDM_calc_edges(result); result->dirty |= DM_DIRTY_NORMALS; skin_set_orig_indices(result); -- cgit v1.2.3 From b7d0ff0ad6f9ab8cb10c727b6db293204c79636f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 4 May 2015 16:26:28 +0500 Subject: Separate scene simplification into viewport and render This way it is possible to have viewport simplification bumped all the way up, making viewport really responsive but still have final render to use highest subdivision possible. Reviewers: lukastoenne, campbellbarton, dingto Reviewed By: campbellbarton, dingto Subscribers: dingto, nutel, eyecandy, venomgfx Differential Revision: https://developer.blender.org/D1273 --- intern/cycles/blender/addon/ui.py | 13 ++++++++--- release/scripts/startup/bl_ui/properties_scene.py | 7 ++++-- source/blender/blenkernel/BKE_scene.h | 4 ++-- source/blender/blenkernel/intern/multires.c | 4 ++-- source/blender/blenkernel/intern/particle_system.c | 2 +- source/blender/blenkernel/intern/scene.c | 26 +++++++++++++++------- source/blender/blenkernel/intern/subsurf_ccg.c | 6 ++--- source/blender/blenloader/intern/versioning_270.c | 8 +++++++ source/blender/makesdna/DNA_scene_types.h | 4 +++- source/blender/makesrna/intern/rna_scene.c | 11 +++++++++ source/blender/modifiers/intern/MOD_subsurf.c | 2 +- 11 files changed, 64 insertions(+), 23 deletions(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index cdacad75221..0407e87c842 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1409,10 +1409,17 @@ class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel): rd = context.scene.render layout.active = rd.use_simplify + split = layout.split() - row = layout.row() - row.prop(rd, "simplify_subdivision", text="Subdivision") - row.prop(rd, "simplify_child_particles", text="Child Particles") + col = split.column() + col.label(text="Viewport:") + col.prop(rd, "simplify_subdivision", text="Subdivision") + col.prop(rd, "simplify_child_particles", text="Child Particles") + + col = split.column() + col.label(text="Render:") + col.prop(rd, "simplify_subdivision_render", text="Subdivision") + col.prop(rd, "simplify_child_particles_render", text="Child Particles") def draw_device(self, context): diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py index b4c4ed6ceae..dafe0af5eb9 100644 --- a/release/scripts/startup/bl_ui/properties_scene.py +++ b/release/scripts/startup/bl_ui/properties_scene.py @@ -392,14 +392,17 @@ class SCENE_PT_simplify(SceneButtonsPanel, Panel): split = layout.split() col = split.column() + col.label(text="Viewport:") col.prop(rd, "simplify_subdivision", text="Subdivision") col.prop(rd, "simplify_child_particles", text="Child Particles") - col.prop(rd, "use_simplify_triangulate") - col = split.column() + col.label(text="Render:") + col.prop(rd, "simplify_subdivision_render", text="Subdivision") + col.prop(rd, "simplify_child_particles_render", text="Child Particles") col.prop(rd, "simplify_shadow_samples", text="Shadow Samples") col.prop(rd, "simplify_ao_sss", text="AO and SSS") + col.prop(rd, "use_simplify_triangulate") class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel): diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 79778d504a5..75a5e919bad 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -127,8 +127,8 @@ struct SceneRenderView *BKE_scene_add_render_view(struct Scene *sce, const char bool BKE_scene_remove_render_view(struct Scene *scene, struct SceneRenderView *srv); /* render profile */ -int get_render_subsurf_level(const struct RenderData *r, int level); -int get_render_child_particle_number(const struct RenderData *r, int num); +int get_render_subsurf_level(const struct RenderData *r, int level, bool for_render); +int get_render_child_particle_number(const struct RenderData *r, int num, bool for_render); int get_render_shadow_samples(const struct RenderData *r, int samples); float get_render_aosss_error(const struct RenderData *r, float error); diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 4ac96405fbf..e4bf05c2b5b 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -340,13 +340,13 @@ static int multires_get_level(Object *ob, MultiresModifierData *mmd, bool render, bool ignore_simplify) { if (render) - return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->renderlvl) : mmd->renderlvl; + return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->renderlvl, true) : mmd->renderlvl; else if (ob->mode == OB_MODE_SCULPT) return mmd->sculptlvl; else if (ignore_simplify) return mmd->lvl; else - return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->lvl) : mmd->lvl; + return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->lvl, false) : mmd->lvl; } void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, int lvl) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 2576c4576cd..4bc46a476a5 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -297,7 +297,7 @@ int psys_get_child_number(Scene *scene, ParticleSystem *psys) else nbr= psys->part->child_nbr; - return get_render_child_particle_number(&scene->r, nbr); + return get_render_child_particle_number(&scene->r, nbr, psys->renderdata != NULL); } int psys_get_tot_child(Scene *scene, ParticleSystem *psys) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 887bcbeb3fc..575a42ed690 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1939,20 +1939,30 @@ bool BKE_scene_remove_render_view(Scene *scene, SceneRenderView *srv) /* render simplification */ -int get_render_subsurf_level(const RenderData *r, int lvl) +int get_render_subsurf_level(const RenderData *r, int lvl, bool for_render) { - if (r->mode & R_SIMPLIFY) - return min_ii(r->simplify_subsurf, lvl); - else + if (r->mode & R_SIMPLIFY) { + if (for_render) + return min_ii(r->simplify_subsurf_render, lvl); + else + return min_ii(r->simplify_subsurf, lvl); + } + else { return lvl; + } } -int get_render_child_particle_number(const RenderData *r, int num) +int get_render_child_particle_number(const RenderData *r, int num, bool for_render) { - if (r->mode & R_SIMPLIFY) - return (int)(r->simplify_particles * num); - else + if (r->mode & R_SIMPLIFY) { + if (for_render) + return (int)(r->simplify_particles_render * num); + else + return (int)(r->simplify_particles * num); + } + else { return num; + } } int get_render_shadow_samples(const RenderData *r, int samples) diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index f81d5825120..2b05a6c8fc5 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -3828,7 +3828,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( /* note: editmode calculation can only run once per * modifier stack evaluation (uses freed cache) [#36299] */ if (flags & SUBSURF_FOR_EDIT_MODE) { - int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels) : smd->levels; + int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels, false) : smd->levels; smd->emCache = _getSubSurf(smd->emCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS); ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple); @@ -3840,7 +3840,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( else if (flags & SUBSURF_USE_RENDER_PARAMS) { /* Do not use cache in render mode. */ CCGSubSurf *ss; - int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->renderLevels) : smd->renderLevels; + int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->renderLevels, true) : smd->renderLevels; if (levels == 0) return dm; @@ -3856,7 +3856,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( } else { int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental); - int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels) : smd->levels; + int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels, false) : smd->levels; CCGSubSurf *ss; /* It is quite possible there is a much better place to do this. It diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 4daf93916c9..df985448ccd 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -822,5 +822,13 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } + + if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "short", "simplify_subsurf_render")) { + Scene *scene; + for (scene = main->scene.first; scene != NULL; scene = scene->id.next) { + scene->r.simplify_subsurf_render = scene->r.simplify_subsurf; + scene->r.simplify_particles_render = scene->r.simplify_particles; + } + } } } diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index ca2edb5eb90..ff2a7468832 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -657,8 +657,10 @@ typedef struct RenderData { /* render simplify */ int simplify_flag; short simplify_subsurf; - short simplify_shadowsamples; + short simplify_subsurf_render; + short simplify_shadowsamples, pad9; float simplify_particles; + float simplify_particles_render; float simplify_aosss; /* cineon */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 78e19d2a40d..d7dfa827493 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -5821,6 +5821,17 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Simplify Child Particles", "Global child particles percentage"); RNA_def_property_update(prop, 0, "rna_Scene_simplify_update"); + prop = RNA_def_property(srna, "simplify_subdivision_render", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "simplify_subsurf_render"); + RNA_def_property_ui_range(prop, 0, 6, 1, -1); + RNA_def_property_ui_text(prop, "Simplify Subdivision", "Global maximum subdivision level during rendering"); + RNA_def_property_update(prop, 0, "rna_Scene_simplify_update"); + + prop = RNA_def_property(srna, "simplify_child_particles_render", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "simplify_particles_render"); + RNA_def_property_ui_text(prop, "Simplify Child Particles", "Global child particles percentage during rendering"); + RNA_def_property_update(prop, 0, "rna_Scene_simplify_update"); + prop = RNA_def_property(srna, "simplify_shadow_samples", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "simplify_shadowsamples"); RNA_def_property_ui_range(prop, 1, 16, 1, -1); diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index f17858264f8..7ada058d883 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -88,7 +88,7 @@ static bool isDisabled(ModifierData *md, int useRenderParams) SubsurfModifierData *smd = (SubsurfModifierData *) md; int levels = (useRenderParams) ? smd->renderLevels : smd->levels; - return get_render_subsurf_level(&md->scene->r, levels) == 0; + return get_render_subsurf_level(&md->scene->r, levels, useRenderParams != 0) == 0; } static DerivedMesh *applyModifier(ModifierData *md, Object *ob, -- cgit v1.2.3 From be30070d869906f6fd12fc0ca8dd24b85f6e33b6 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Mon, 4 May 2015 13:32:28 +0200 Subject: BGE: Cleanup KX_BlenderSceneConverter.cpp This commit is a little cleanup for whitspaces, braces, spaces around operators and useless keywords struct/class. Reviewers:sybren --- .../Converter/KX_BlenderSceneConverter.cpp | 606 +++++++++------------ 1 file changed, 254 insertions(+), 352 deletions(-) diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index c5add2df3d4..1a489c301e2 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -117,11 +117,9 @@ typedef struct ThreadInfo { } ThreadInfo; KX_BlenderSceneConverter::KX_BlenderSceneConverter( - struct Main* maggie, - class KX_KetsjiEngine* engine - ) - : m_maggie(maggie), - /*m_maggie_dyn(NULL),*/ + Main *maggie, + KX_KetsjiEngine *engine) + :m_maggie(maggie), m_ketsjiEngine(engine), m_alwaysUseExpandFraming(false), m_usemat(false), @@ -134,13 +132,11 @@ KX_BlenderSceneConverter::KX_BlenderSceneConverter( pthread_mutex_init(&m_threadinfo->merge_lock, NULL); } - KX_BlenderSceneConverter::~KX_BlenderSceneConverter() { // clears meshes, and hashmaps from blender to gameengine data - int i; // delete sumoshapes - + if (m_threadinfo) { vector::iterator pit = m_threadinfo->threads.begin(); while (pit != m_threadinfo->threads.end()) { @@ -153,104 +149,83 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter() } int numAdtLists = m_map_blender_to_gameAdtList.size(); - for (i=0; i >::iterator itw = m_worldinfos.begin(); + vector >::iterator itw = m_worldinfos.begin(); while (itw != m_worldinfos.end()) { delete (*itw).second; itw++; } m_worldinfos.clear(); - vector >::iterator itp = m_polymaterials.begin(); + vector >::iterator itp = m_polymaterials.begin(); while (itp != m_polymaterials.end()) { - //m_polymat_cache.erase((*itp).second->GetBlenderMaterial()); delete (*itp).second; itp++; } m_polymaterials.clear(); // delete after RAS_IPolyMaterial - vector >::iterator itmat = m_materials.begin(); + vector >::iterator itmat = m_materials.begin(); while (itmat != m_materials.end()) { - //m_mat_cache.erase((*itmat).second->material); delete (*itmat).second; itmat++; } m_materials.clear(); - - vector >::iterator itm = m_meshobjects.begin(); + vector >::iterator itm = m_meshobjects.begin(); while (itm != m_meshobjects.end()) { delete (*itm).second; itm++; } m_meshobjects.clear(); - /* free any data that was dynamically loaded */ - while (m_DynamicMaggie.size() != 0) - { + while (m_DynamicMaggie.size() != 0) { FreeBlendFile(m_DynamicMaggie[0]); } m_DynamicMaggie.clear(); } -void KX_BlenderSceneConverter::SetNewFileName(const STR_String& filename) +void KX_BlenderSceneConverter::SetNewFileName(const STR_String &filename) { m_newfilename = filename; } - - bool KX_BlenderSceneConverter::TryAndLoadNewFile() { bool result = false; - // find the file -/* if () - { - result = true; - } - // if not, clear the newfilename - else - { - m_newfilename = ""; - } -*/ return result; } -Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name) +Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String &name) { Scene *sce; /** * Find the specified scene by name, or NULL if nothing matches. */ - if ((sce= (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2))) + if ((sce = (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2))) return sce; - for (vector::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) { - Main *main= *it; + for (vector
::iterator it=m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) { + Main *main = *it; if ((sce= (Scene *)BLI_findstring(&main->scene, name.ReadPtr(), offsetof(ID, name) + 2))) return sce; } return NULL; - } -void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, - class RAS_IRasterizer* rendertools, - class RAS_ICanvas* canvas, - bool libloading) +void KX_BlenderSceneConverter::ConvertScene(KX_Scene *destinationscene, RAS_IRasterizer *rendertools, + RAS_ICanvas *canvas, bool libloading) { //find out which physics engine Scene *blenderscene = destinationscene->GetBlenderScene(); @@ -266,13 +241,12 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, // when doing threaded conversion, so it's disabled for now. // SG_SetActiveStage(SG_STAGE_CONVERTER); - switch (blenderscene->gm.physicsEngine) - { + switch (blenderscene->gm.physicsEngine) { #ifdef WITH_BULLET case WOPHY_BULLET: { SYS_SystemHandle syshandle = SYS_GetSystem(); /*unused*/ - int visualizePhysics = SYS_GetCommandLineInt(syshandle,"show_physics",0); + int visualizePhysics = SYS_GetCommandLineInt(syshandle, "show_physics", 0); phy_env = CcdPhysicsEnvironment::Create(blenderscene, visualizePhysics); physics_engine = UseBullet; @@ -291,7 +265,8 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, destinationscene->SetPhysicsEnvironment(phy_env); - BL_ConvertBlenderObjects(m_maggie, + BL_ConvertBlenderObjects( + m_maggie, destinationscene, m_ketsjiEngine, physics_engine, @@ -299,8 +274,7 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, canvas, this, m_alwaysUseExpandFraming, - libloading - ); + libloading); //These lookup are not needed during game m_map_blender_to_gameactuator.clear(); @@ -326,30 +300,32 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) // delete the scene first as it will stop the use of entities delete scene; // delete the entities of this scene - vector >::iterator worldit; + vector >::iterator worldit; size = m_worldinfos.size(); - for (i=0, worldit=m_worldinfos.begin(); i >::iterator polymit; + vector >::iterator polymit; size = m_polymaterials.size(); - for (i=0, polymit=m_polymaterials.begin(); iGetBlenderMaterial()); delete (*polymit).second; *polymit = m_polymaterials.back(); m_polymaterials.pop_back(); size--; - } else { + } + else { i++; polymit++; } @@ -357,16 +333,17 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) m_polymat_cache.erase(scene); - vector >::iterator matit; + vector >::iterator matit; size = m_materials.size(); - for (i=0, matit=m_materials.begin(); imaterial); delete (*matit).second; *matit = m_materials.back(); m_materials.pop_back(); size--; - } else { + } + else { i++; matit++; } @@ -374,15 +351,16 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) m_mat_cache.erase(scene); - vector >::iterator meshit; + vector >::iterator meshit; size = m_meshobjects.size(); - for (i=0, meshit=m_meshobjects.begin(); i >::iterator it; + vector >::iterator it; for (it = m_materials.begin(); it != m_materials.end(); ++it) if (it->second == mat) return; - m_materials.push_back(pair(m_currentScene,mat)); + m_materials.push_back(pair (m_currentScene, mat)); } - - -void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming( - bool to_what) +void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming(bool to_what) { m_alwaysUseExpandFraming= to_what; } - - -void KX_BlenderSceneConverter::RegisterGameObject( - KX_GameObject *gameobject, - struct Object *for_blenderobject) +void KX_BlenderSceneConverter::RegisterGameObject(KX_GameObject *gameobject, Object *for_blenderobject) { /* only maintained while converting, freed during game runtime */ - m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject),gameobject); + m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject), gameobject); } /* only need to run this during conversion since * m_map_blender_to_gameobject is freed after conversion */ -void KX_BlenderSceneConverter::UnregisterGameObject( - KX_GameObject *gameobject) +void KX_BlenderSceneConverter::UnregisterGameObject(KX_GameObject *gameobject) { - struct Object *bobp= gameobject->GetBlenderObject(); + Object *bobp = gameobject->GetBlenderObject(); if (bobp) { CHashedPtr bptr(bobp); - KX_GameObject **gobp= m_map_blender_to_gameobject[bptr]; - if (gobp && *gobp == gameobject) - { + KX_GameObject **gobp = m_map_blender_to_gameobject[bptr]; + if (gobp && *gobp == gameobject) { // also maintain m_map_blender_to_gameobject if the gameobject // being removed is matching the blender object m_map_blender_to_gameobject.remove(bptr); @@ -469,47 +438,41 @@ void KX_BlenderSceneConverter::UnregisterGameObject( } } -KX_GameObject *KX_BlenderSceneConverter::FindGameObject( - struct Object *for_blenderobject) +KX_GameObject *KX_BlenderSceneConverter::FindGameObject(Object *for_blenderobject) { - KX_GameObject **obp= m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)]; - - return obp?*obp:NULL; + KX_GameObject **obp = m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)]; + + return obp ? *obp : NULL; } -void KX_BlenderSceneConverter::RegisterGameMesh( - RAS_MeshObject *gamemesh, - struct Mesh *for_blendermesh) +void KX_BlenderSceneConverter::RegisterGameMesh(RAS_MeshObject *gamemesh, Mesh *for_blendermesh) { if (for_blendermesh) { /* dynamically loaded meshes we don't want to keep lookups for */ m_map_mesh_to_gamemesh.insert(CHashedPtr(for_blendermesh),gamemesh); } - m_meshobjects.push_back(pair(m_currentScene,gamemesh)); + m_meshobjects.push_back(pair (m_currentScene,gamemesh)); } - - -RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh( - struct Mesh *for_blendermesh/*, - unsigned int onlayer*/) +RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(Mesh *for_blendermesh) { - RAS_MeshObject** meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)]; - - if (meshp/* && onlayer==(*meshp)->GetLightLayer()*/) { + RAS_MeshObject **meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)]; + + if (meshp) { return *meshp; - } else { + } + else { return NULL; } -} +} void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat) { // First make sure we don't register the material twice - vector >::iterator it; + vector >::iterator it; for (it = m_polymaterials.begin(); it != m_polymaterials.end(); ++it) if (it->second == polymat) return; - m_polymaterials.push_back(pair(m_currentScene,polymat)); + m_polymaterials.push_back(pair (m_currentScene, polymat)); } void KX_BlenderSceneConverter::CachePolyMaterial(KX_Scene *scene, Material *mat, RAS_IPolyMaterial *polymat) @@ -518,94 +481,82 @@ void KX_BlenderSceneConverter::CachePolyMaterial(KX_Scene *scene, Material *mat, m_polymat_cache[scene][mat] = polymat; } -RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(KX_Scene *scene, struct Material *mat) +RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(KX_Scene *scene, Material *mat) { return (m_use_mat_cache) ? m_polymat_cache[scene][mat] : NULL; } -void KX_BlenderSceneConverter::CacheBlenderMaterial(KX_Scene *scene, struct Material *mat, BL_Material *blmat) +void KX_BlenderSceneConverter::CacheBlenderMaterial(KX_Scene *scene, Material *mat, BL_Material *blmat) { if (m_use_mat_cache && mat) m_mat_cache[scene][mat] = blmat; } - -BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(KX_Scene *scene, struct Material *mat) +BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(KX_Scene *scene, Material *mat) { return (m_use_mat_cache) ? m_mat_cache[scene][mat] : NULL; } - -void KX_BlenderSceneConverter::RegisterInterpolatorList(BL_InterpolatorList *actList, struct bAction *for_act) +void KX_BlenderSceneConverter::RegisterInterpolatorList(BL_InterpolatorList *actList, bAction *for_act) { m_map_blender_to_gameAdtList.insert(CHashedPtr(for_act), actList); } -BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(struct bAction *for_act) +BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(bAction *for_act) { BL_InterpolatorList **listp = m_map_blender_to_gameAdtList[CHashedPtr(for_act)]; - return listp?*listp:NULL; + return listp ? *listp : NULL; } - -void KX_BlenderSceneConverter::RegisterGameActuator(SCA_IActuator *act, struct bActuator *for_actuator) +void KX_BlenderSceneConverter::RegisterGameActuator(SCA_IActuator *act, bActuator *for_actuator) { m_map_blender_to_gameactuator.insert(CHashedPtr(for_actuator), act); } -SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(struct bActuator *for_actuator) +SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(bActuator *for_actuator) { SCA_IActuator **actp = m_map_blender_to_gameactuator[CHashedPtr(for_actuator)]; - return actp?*actp:NULL; + return actp ? *actp : NULL; } - -void KX_BlenderSceneConverter::RegisterGameController(SCA_IController *cont, struct bController *for_controller) +void KX_BlenderSceneConverter::RegisterGameController(SCA_IController *cont, bController *for_controller) { m_map_blender_to_gamecontroller.insert(CHashedPtr(for_controller), cont); } -SCA_IController *KX_BlenderSceneConverter::FindGameController(struct bController *for_controller) +SCA_IController *KX_BlenderSceneConverter::FindGameController(bController *for_controller) { SCA_IController **contp = m_map_blender_to_gamecontroller[CHashedPtr(for_controller)]; - return contp?*contp:NULL; + return contp ? *contp : NULL; } - - void KX_BlenderSceneConverter::RegisterWorldInfo(KX_WorldInfo *worldinfo) { - m_worldinfos.push_back(pair(m_currentScene,worldinfo)); + m_worldinfos.push_back(pair (m_currentScene, worldinfo)); } -void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo) +void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo) { //TODO this entire function is deprecated, written for 2.4x //the functionality should be rewritten, currently it does nothing - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; - for (i=0;iat(i); - //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); - CListValue* parentList = scene->GetRootParentList(); + for (i = 0; i < numScenes; i++) { + KX_Scene *scene = scenes->at(i); + CListValue *parentList = scene->GetRootParentList(); int numObjects = parentList->GetCount(); int g; - for (g=0;gGetValue(g); + for (g = 0; g < numObjects; g++) { + KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); if (gameObj->IsRecordAnimation()) { - - Object* blenderObject = gameObj->GetBlenderObject(); - if (blenderObject) - { + Object *blenderObject = gameObj->GetBlenderObject(); + if (blenderObject) { #if 0 //erase existing ipo's Ipo* ipo = blenderObject->ipo;//findIpoForName(blenderObject->id.name+2); - if (ipo) - { //clear the curve data + if (ipo) { //clear the curve data if (clearIpo) {//rcruiz IpoCurve *icu1; @@ -630,64 +581,52 @@ void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo) localDel_ipoCurve( tmpicu ); } } - } else - { ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB); + } + else { + ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB); blenderObject->ipo = ipo; - } #endif } } - } - - } - - - } -void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo() +void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo() { //TODO the functionality should be rewritten } - - ///this generates ipo curves for position, rotation, allowing to use game physics in animation -void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) +// this generates ipo curves for position, rotation, allowing to use game physics in animation +void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) { - - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; - for (i=0;iat(i); + for (i = 0; i < numScenes; i++) { + KX_Scene *scene = scenes->at(i); //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); - CListValue* parentList = scene->GetObjectList(); + CListValue *parentList = scene->GetObjectList(); int numObjects = parentList->GetCount(); int g; - for (g=0;gGetValue(g); - Object* blenderObject = gameObj->GetBlenderObject(); - if (blenderObject && blenderObject->parent==NULL && gameObj->IsRecordAnimation()) { - - if (blenderObject->adt==NULL) + for (g = 0; g < numObjects; g++) { + KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); + Object *blenderObject = gameObj->GetBlenderObject(); + if (blenderObject && blenderObject->parent == NULL && gameObj->IsRecordAnimation()) { + if (blenderObject->adt == NULL) BKE_animdata_add_id(&blenderObject->id); - if (blenderObject->adt) - { - const MT_Point3& position = gameObj->NodeGetWorldPosition(); + if (blenderObject->adt) { + const MT_Point3 &position = gameObj->NodeGetWorldPosition(); //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); - const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation(); + const MT_Matrix3x3 &orn = gameObj->NodeGetWorldOrientation(); position.getValue(blenderObject->loc); float tmat[3][3]; - for (int r=0;r<3;r++) - for (int c=0;c<3;c++) + for (int r = 0; r < 3; r++) + for (int c = 0; c < 3; c++) tmat[r][c] = (float)orn[c][r]; mat3_to_compatible_eul(blenderObject->rot, blenderObject->rot, tmat); @@ -772,27 +711,22 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) } } - -void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() +void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() { - - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; - for (i=0;iat(i); + for (i = 0; i < numScenes; i++) { + KX_Scene *scene = scenes->at(i); //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); - CListValue* parentList = scene->GetRootParentList(); + CListValue *parentList = scene->GetRootParentList(); int numObjects = parentList->GetCount(); int g; - for (g=0;gGetValue(g); + for (g = 0; g < numObjects; g++) { + KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); if (gameObj->IsRecordAnimation()) { - Object* blenderObject = gameObj->GetBlenderObject(); - if (blenderObject && blenderObject->adt) - { + Object *blenderObject = gameObj->GetBlenderObject(); + if (blenderObject && blenderObject->adt) { bAction *act = verify_adt_action(&blenderObject->id, false); FCurve *fcu; @@ -832,14 +766,14 @@ PyObject *KX_BlenderSceneConverter::GetPyNamespace() } #endif -vector &KX_BlenderSceneConverter::GetMainDynamic() +vector
&KX_BlenderSceneConverter::GetMainDynamic() { return m_DynamicMaggie; } -Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path) +Main *KX_BlenderSceneConverter::GetMainDynamicPath(const char *path) { - for (vector::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) + for (vector
::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) if (BLI_path_cmp((*it)->name, path) == 0) return *it; @@ -848,22 +782,21 @@ Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path) void KX_BlenderSceneConverter::MergeAsyncLoads() { - vector *merge_scenes; + vector *merge_scenes; - vector::iterator mit; - vector::iterator sit; + vector::iterator mit; + vector::iterator sit; pthread_mutex_lock(&m_threadinfo->merge_lock); - for (mit=m_mergequeue.begin(); mit!=m_mergequeue.end(); ++mit) { - merge_scenes = (vector*)(*mit)->GetData(); + for (mit = m_mergequeue.begin(); mit != m_mergequeue.end(); ++mit) { + merge_scenes = (vector *)(*mit)->GetData(); for (sit=merge_scenes->begin(); sit!=merge_scenes->end(); ++sit) { (*mit)->GetMergeScene()->MergeScene(*sit); delete (*sit); } - delete merge_scenes; (*mit)->SetData(NULL); @@ -885,17 +818,17 @@ void KX_BlenderSceneConverter::AddScenesToMergeQueue(KX_LibLoadStatus *status) static void *async_convert(void *ptr) { KX_Scene *new_scene = NULL; - KX_LibLoadStatus *status = (KX_LibLoadStatus*)ptr; - vector *scenes = (vector*)status->GetData(); - vector *merge_scenes = new vector(); // Deleted in MergeAsyncLoads + KX_LibLoadStatus *status = (KX_LibLoadStatus *)ptr; + vector *scenes = (vector *)status->GetData(); + vector *merge_scenes = new vector(); // Deleted in MergeAsyncLoads - for (unsigned int i=0; isize(); ++i) { + for (unsigned int i = 0; i < scenes->size(); ++i) { new_scene = status->GetEngine()->CreateScene((*scenes)[i], true); if (new_scene) merge_scenes->push_back(new_scene); - status->AddProgress((1.f/scenes->size())*0.9f); // We'll call conversion 90% and merging 10% for now + status->AddProgress((1.0f / scenes->size()) * 0.9f); // We'll call conversion 90% and merging 10% for now } delete scenes; @@ -927,13 +860,13 @@ static void load_datablocks(Main *main_tmp, BlendHandle *bpy_openlib, const char LinkNode *names = NULL; int totnames_dummy; - names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode, &totnames_dummy); + names = BLO_blendhandle_get_datablock_names(bpy_openlib, idcode, &totnames_dummy); - int i=0; - LinkNode *n= names; + int i = 0; + LinkNode *n = names; while (n) { BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, idcode); - n= (LinkNode *)n->next; + n = (LinkNode *)n->next; i++; } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ @@ -949,25 +882,25 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl // TIMEIT_START(bge_link_blend_file); KX_LibLoadStatus *status; - + /* only scene and mesh supported right now */ - if (idcode!=ID_SCE && idcode!=ID_ME &&idcode!=ID_AC) { + if (idcode != ID_SCE && idcode != ID_ME && idcode != ID_AC) { snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group); - *err_str= err_local; + *err_str = err_local; BLO_blendhandle_close(bpy_openlib); return NULL; } if (GetMainDynamicPath(path)) { snprintf(err_local, sizeof(err_local), "blend file already open \"%s\"\n", path); - *err_str= err_local; + *err_str = err_local; BLO_blendhandle_close(bpy_openlib); return NULL; } - if (bpy_openlib==NULL) { + if (bpy_openlib == NULL) { snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path); - *err_str= err_local; + *err_str = err_local; return NULL; } @@ -980,12 +913,12 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl load_datablocks(main_tmp, bpy_openlib, path, idcode); - if (idcode==ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) { + if (idcode == ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) { load_datablocks(main_tmp, bpy_openlib, path, ID_TXT); } /* now do another round of linking for Scenes so all actions are properly loaded */ - if (idcode==ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { + if (idcode == ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { load_datablocks(main_tmp, bpy_openlib, path, ID_AC); } @@ -1003,42 +936,43 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl status = new KX_LibLoadStatus(this, m_ketsjiEngine, scene_merge, path); - if (idcode==ID_ME) { + if (idcode == ID_ME) { /* Convert all new meshes into BGE meshes */ - ID* mesh; + ID *mesh; - for (mesh= (ID *)main_newlib->mesh.first; mesh; mesh= (ID *)mesh->next ) { + for (mesh = (ID *)main_newlib->mesh.first; mesh; mesh = (ID *)mesh->next ) { if (options & LIB_LOAD_VERBOSE) - printf("MeshName: %s\n", mesh->name+2); + printf("MeshName: %s\n", mesh->name + 2); RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this, false); // For now only use the libloading option for scenes, which need to handle materials/shaders - scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj); + scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj); } } - else if (idcode==ID_AC) { + else if (idcode == ID_AC) { /* Convert all actions */ ID *action; - for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) { + for (action= (ID *)main_newlib->action.first; action; action = (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) - printf("ActionName: %s\n", action->name+2); - scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action); + printf("ActionName: %s\n", action->name + 2); + scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action); } } - else if (idcode==ID_SCE) { + else if (idcode == ID_SCE) { /* Merge all new linked in scene into the existing one */ ID *scene; // scenes gets deleted by the thread when it's done using it (look in async_convert()) - vector *scenes = (options & LIB_LOAD_ASYNC) ? new vector() : NULL; + vector *scenes = (options & LIB_LOAD_ASYNC) ? new vector() : NULL; - for (scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) { + for (scene = (ID *)main_newlib->scene.first; scene; scene = (ID *)scene->next ) { if (options & LIB_LOAD_VERBOSE) - printf("SceneName: %s\n", scene->name+2); + printf("SceneName: %s\n", scene->name + 2); if (options & LIB_LOAD_ASYNC) { - scenes->push_back((Scene*)scene); - } else { + scenes->push_back((Scene *)scene); + } + else { /* merge into the base scene */ - KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene, true); + KX_Scene* other = m_ketsjiEngine->CreateScene((Scene *)scene, true); scene_merge->MergeScene(other); // RemoveScene(other); // Don't run this, it frees the entire scene converter data, just delete the scene @@ -1049,7 +983,7 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl if (options & LIB_LOAD_ASYNC) { pthread_t id; status->SetData(scenes); - pthread_create(&id, NULL, &async_convert, (void*)status); + pthread_create(&id, NULL, &async_convert, (void *)status); m_threadinfo->threads.push_back(id); } @@ -1063,17 +997,16 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl if (options & LIB_LOAD_LOAD_ACTIONS) { ID *action; - for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) { + for (action = (ID *)main_newlib->action.first; action; action = (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) - printf("ActionName: %s\n", action->name+2); - scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action); + printf("ActionName: %s\n", action->name + 2); + scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action); } } } if (!(options & LIB_LOAD_ASYNC)) status->Finish(); - // TIMEIT_END(bge_link_blend_file); @@ -1083,22 +1016,22 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl /* Note m_map_*** are all ok and don't need to be freed * most are temp and NewRemoveObject frees m_map_gameobject_to_blender */ -bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) +bool KX_BlenderSceneConverter::FreeBlendFile(Main *maggie) { - int maggie_index= -1; - int i=0; + int maggie_index = -1; + int i = 0; - if (maggie==NULL) + if (maggie == NULL) return false; /* tag all false except the one we remove */ - for (vector::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) { - Main *main= *it; + for (vector
::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) { + Main *main = *it; if (main != maggie) { BKE_main_id_tag_all(main, false); } else { - maggie_index= i; + maggie_index = i; } i++; } @@ -1110,15 +1043,12 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) m_DynamicMaggie.erase(m_DynamicMaggie.begin() + maggie_index); BKE_main_id_tag_all(maggie, true); - /* free all tagged objects */ - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); - - for (int scene_idx=0;scene_idxat(scene_idx); + for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) { + KX_Scene *scene = scenes->at(scene_idx); if (IS_TAGGED(scene->GetBlenderScene())) { m_ketsjiEngine->RemoveScene(scene->GetName()); m_mat_cache.erase(scene); @@ -1127,16 +1057,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) numScenes--; } else { - /* in case the mesh might be refered to later */ { - CTR_Map &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap(); + CTR_Map &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap(); - for (int i=0; iGetMesh())) - { + for (int i = 0; i < mapStringToMeshes.size(); i++) { + RAS_MeshObject *meshobj = (RAS_MeshObject *) *mapStringToMeshes.at(i); + if (meshobj && IS_TAGGED(meshobj->GetMesh())) { STR_HashedString mn = meshobj->GetName(); mapStringToMeshes.remove(mn); m_map_mesh_to_gamemesh.remove(CHashedPtr(meshobj->GetMesh())); @@ -1147,15 +1074,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) /* Now unregister actions */ { - CTR_Map &mapStringToActions = scene->GetLogicManager()->GetActionMap(); + CTR_Map &mapStringToActions = scene->GetLogicManager()->GetActionMap(); - for (int i=0; iname+2; + if (IS_TAGGED(action)) { + STR_HashedString an = action->name + 2; mapStringToActions.remove(an); i--; } @@ -1165,16 +1090,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) //scene->FreeTagged(); /* removed tagged objects and meshes*/ CListValue *obj_lists[] = {scene->GetObjectList(), scene->GetInactiveList(), NULL}; - for (int ob_ls_idx=0; obj_lists[ob_ls_idx]; ob_ls_idx++) - { - CListValue *obs= obj_lists[ob_ls_idx]; - RAS_MeshObject* mesh; + for (int ob_ls_idx = 0; obj_lists[ob_ls_idx]; ob_ls_idx++) { + CListValue *obs = obj_lists[ob_ls_idx]; + RAS_MeshObject *mesh; - for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++) - { - KX_GameObject* gameobj = (KX_GameObject*)obs->GetValue(ob_idx); + for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++) { + KX_GameObject *gameobj = (KX_GameObject*)obs->GetValue(ob_idx); if (IS_TAGGED(gameobj->GetBlenderObject())) { - int size_before = obs->GetCount(); /* Eventually calls RemoveNodeDestructObject @@ -1189,9 +1111,9 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) } else { /* free the mesh, we could be referecing a linked one! */ - int mesh_index= gameobj->GetMeshCount(); + int mesh_index = gameobj->GetMeshCount(); while (mesh_index--) { - mesh= gameobj->GetMesh(mesh_index); + mesh = gameobj->GetMesh(mesh_index); if (IS_TAGGED(mesh->GetMesh())) { gameobj->RemoveMeshes(); /* XXX - slack, should only remove meshes that are library items but mostly objects only have 1 mesh */ break; @@ -1209,11 +1131,9 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) } /* make sure action actuators are not referencing tagged actions */ - for (unsigned int act_idx=0; act_idxGetActuators().size(); act_idx++) - { - if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION)) - { - BL_ActionActuator *act = (BL_ActionActuator*)gameobj->GetActuators()[act_idx]; + for (unsigned int act_idx = 0; act_idx < gameobj->GetActuators().size(); act_idx++) { + if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION)) { + BL_ActionActuator *act = (BL_ActionActuator *)gameobj->GetActuators()[act_idx]; if (IS_TAGGED(act->GetAction())) act->SetAction(NULL); } @@ -1224,7 +1144,6 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) } } - int size; // delete the entities of this scene @@ -1247,24 +1166,24 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) /* Worlds don't reference original blender data so we need to make a set from them */ - typedef std::set KX_WorldInfoSet; + typedef std::set KX_WorldInfoSet; KX_WorldInfoSet worldset; - for (int scene_idx=0;scene_idxat(scene_idx); + for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) { + KX_Scene *scene = scenes->at(scene_idx); if (scene->GetWorldInfo()) - worldset.insert( scene->GetWorldInfo() ); + worldset.insert(scene->GetWorldInfo()); } - vector >::iterator worldit; + vector >::iterator worldit; size = m_worldinfos.size(); - for (i=0, worldit=m_worldinfos.begin(); i >::iterator polymit; + vector >::iterator polymit; size = m_polymaterials.size(); + for (i = 0, polymit = m_polymaterials.begin(); i < size; ) { + RAS_IPolyMaterial *mat = (*polymit).second; + Material *bmat = NULL; - - for (i=0, polymit=m_polymaterials.begin(); i(mat); - bmat= bl_mat->GetBlenderMaterial(); + KX_BlenderMaterial *bl_mat = static_cast(mat); + bmat = bl_mat->GetBlenderMaterial(); if (IS_TAGGED(bmat)) { /* only remove from bucket */ @@ -1296,63 +1210,53 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) polymit++; } - - - for (i=0, polymit=m_polymaterials.begin(); i(mat); - bmat= bl_mat->GetBlenderMaterial(); - - if (bmat) { - //printf("FOUND MAT '%s' !!! ", ((ID*)bmat)->name+2); - } - else { - //printf("LOST MAT !!!"); - } + bmat = bl_mat->GetBlenderMaterial(); if (IS_TAGGED(bmat)) { delete (*polymit).second; *polymit = m_polymaterials.back(); m_polymaterials.pop_back(); size--; - //printf("tagged !\n"); } else { i++; polymit++; - //printf("(un)tagged !\n"); } } - vector >::iterator matit; + vector >::iterator matit; size = m_materials.size(); - for (i=0, matit=m_materials.begin(); imaterial)) { delete (*matit).second; *matit = m_materials.back(); m_materials.pop_back(); size--; - } else { + } + else { i++; matit++; } } - vector >::iterator meshit; + vector >::iterator meshit; RAS_BucketManager::BucketList::iterator bit; list::iterator msit; RAS_BucketManager::BucketList buckets; size = m_meshobjects.size(); - for (i=0, meshit=m_meshobjects.begin(); iGetMesh())) { // Before deleting the mesh object, make sure the rasterizer is // no longer referencing it. buckets = meshit->first->GetBucketManager()->GetSolidBuckets(); - for (bit=buckets.begin(); bit!=buckets.end(); bit++) { + for (bit = buckets.begin(); bit != buckets.end(); bit++) { msit = (*bit)->msBegin(); while (msit != (*bit)->msEnd()) { @@ -1365,7 +1269,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) // And now the alpha buckets buckets = meshit->first->GetBucketManager()->GetAlphaBuckets(); - for (bit=buckets.begin(); bit!=buckets.end(); bit++) { + for (bit = buckets.begin(); bit != buckets.end(); bit++) { msit = (*bit)->msBegin(); while (msit != (*bit)->msEnd()) { @@ -1381,7 +1285,8 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) *meshit = m_meshobjects.back(); m_meshobjects.pop_back(); size--; - } else { + } + else { i++; meshit++; } @@ -1408,24 +1313,23 @@ bool KX_BlenderSceneConverter::FreeBlendFile(const char *path) bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from) { - { - vector >::iterator itp = m_worldinfos.begin(); + vector >::iterator itp = m_worldinfos.begin(); while (itp != m_worldinfos.end()) { - if ((*itp).first==from) - (*itp).first= to; + if ((*itp).first == from) + (*itp).first = to; itp++; } } { - vector >::iterator itp = m_polymaterials.begin(); + vector >::iterator itp = m_polymaterials.begin(); while (itp != m_polymaterials.end()) { - if ((*itp).first==from) { - (*itp).first= to; + if ((*itp).first == from) { + (*itp).first = to; /* also switch internal data */ - RAS_IPolyMaterial*mat= (*itp).second; + RAS_IPolyMaterial *mat = (*itp).second; mat->Replace_IScene(to); } itp++; @@ -1433,29 +1337,29 @@ bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from) } { - vector >::iterator itp = m_meshobjects.begin(); + vector >::iterator itp = m_meshobjects.begin(); while (itp != m_meshobjects.end()) { - if ((*itp).first==from) - (*itp).first= to; + if ((*itp).first == from) + (*itp).first = to; itp++; } } { - vector >::iterator itp = m_materials.begin(); + vector >::iterator itp = m_materials.begin(); while (itp != m_materials.end()) { - if ((*itp).first==from) - (*itp).first= to; + if ((*itp).first == from) + (*itp).first = to; itp++; } } - + return true; } /* This function merges a mesh from the current scene into another main * it does not convert */ -RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, Main *maggie, const char *name) +RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene *kx_scene, Main *maggie, const char *name) { /* Find a mesh in the current main */ ID *me= static_cast(BLI_findstring(&m_maggie->mesh, name, offsetof(ID, name) + 2)); @@ -1463,7 +1367,7 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, if (me == NULL) { // The mesh wasn't in the current main, try any dynamic (i.e., LibLoaded) ones - vector::iterator it; + vector
::iterator it; for (it = GetMainDynamic().begin(); it != GetMainDynamic().end(); it++) { me = static_cast(BLI_findstring(&(*it)->mesh, name, offsetof(ID, name) + 2)); @@ -1473,12 +1377,12 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, break; } } - - if (me==NULL) { + + if (me == NULL) { printf("Could not be found \"%s\"\n", name); return NULL; } - + /* Watch this!, if its used in the original scene can cause big troubles */ if (me->us > 0) { #ifdef DEBUG @@ -1490,34 +1394,32 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, BLI_remlink(&from_maggie->mesh, me); /* even if we made the copy it needs to be removed */ BLI_addtail(&maggie->mesh, me); - /* Must copy the materials this uses else we cant free them */ { - Mesh *mesh= (Mesh *)me; - + Mesh *mesh = (Mesh *)me; + /* ensure all materials are tagged */ - for (int i=0; itotcol; i++) + for (int i = 0; i < mesh->totcol; i++) { if (mesh->mat[i]) mesh->mat[i]->id.flag &= ~LIB_DOIT; - - for (int i=0; itotcol; i++) - { - Material *mat_old= mesh->mat[i]; - + } + + for (int i = 0; i < mesh->totcol; i++) { + Material *mat_old = mesh->mat[i]; + /* if its tagged its a replaced material */ - if (mat_old && (mat_old->id.flag & LIB_DOIT)==0) - { - Material *mat_old= mesh->mat[i]; - Material *mat_new= BKE_material_copy( mat_old ); - + if (mat_old && (mat_old->id.flag & LIB_DOIT) == 0) { + Material *mat_old = mesh->mat[i]; + Material *mat_new = BKE_material_copy(mat_old); + mat_new->id.flag |= LIB_DOIT; mat_old->id.us--; - + BLI_remlink(&G.main->mat, mat_new); // BKE_material_copy uses G.main, and there is no BKE_material_copy_ex BLI_addtail(&maggie->mat, mat_new); - + mesh->mat[i] = mat_new; - + /* the same material may be used twice */ for (int j = i + 1; j < mesh->totcol; j++) { if (mesh->mat[j] == mat_old) { -- cgit v1.2.3 From 5a8629c0d7da6cfb4b696f1787111c9492e03aba Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 4 May 2015 13:53:07 +0200 Subject: Different drawing for object centers. Code here did depth test always and depth range 0.0. There is no real reason for object centers to write and get tested against depth buffer in this case, just disable the depth test instead ;) Helps with blurry object centers in depth of field mode too (centers wrote depth 0 and were always blurry) --- source/blender/editors/space_view3d/drawobject.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 5b2ac50216a..de2b5a39313 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -735,11 +735,7 @@ static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f; float verts[CIRCLE_RESOL][3]; - /* using gldepthfunc guarantees that it does write z values, - * but not checks for it, so centers remain visible independent order of drawing */ - if (v3d->zbuf) glDepthFunc(GL_ALWAYS); - /* write to near buffer always */ - glDepthRange(0.0, 0.0); + if (v3d->zbuf) glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); if (special_color) { @@ -769,10 +765,9 @@ static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], /* finish up */ glDisableClientState(GL_VERTEX_ARRAY); - glDepthRange(0.0, 1.0); glDisable(GL_BLEND); - if (v3d->zbuf) glDepthFunc(GL_LEQUAL); + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } /* *********** text drawing for object/particles/armature ************* */ -- cgit v1.2.3 From e560bbe1d584871ffda3569ac3b4ac1129389e6e Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 4 May 2015 14:28:52 +0200 Subject: Fix possible crash with datatransfer operator when source object was hidden. Mismatch in poll and exec funcs when getting active (source) object... --- source/blender/editors/object/object_data_transfer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index b39e8470a95..a7802b6a411 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -325,7 +325,7 @@ static bool data_transfer_exec_is_object_valid( static int data_transfer_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Object *ob_src = CTX_data_active_object(C); + Object *ob_src = ED_object_active_context(C); ListBase ctx_objects; CollectionPointerLink *ctx_ob_dst; @@ -419,7 +419,7 @@ static int data_transfer_exec(bContext *C, wmOperator *op) /* Note this context poll is only really partial, it cannot check for all possible invalid cases. */ static int data_transfer_poll(bContext *C) { - Object *ob = ED_object_context(C); + Object *ob = ED_object_active_context(C); ID *data = (ob) ? ob->data : NULL; return (ob && ob->type == OB_MESH && data); } -- cgit v1.2.3 From 66f96e555c19e2572df5a0056c5b3ea8f861f40f Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Mon, 4 May 2015 14:29:38 +0200 Subject: Cycles: Fix copy / paste mistake in XML reader. --- intern/cycles/app/cycles_xml.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 382574696c4..b47f20b22a9 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -647,10 +647,10 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug snode = new SeparateHSVNode(); } else if(string_iequals(node.name(), "combine_xyz")) { - snode = new CombineHSVNode(); + snode = new CombineXYZNode(); } else if(string_iequals(node.name(), "separate_xyz")) { - snode = new SeparateHSVNode(); + snode = new SeparateXYZNode(); } else if(string_iequals(node.name(), "hsv")) { snode = new HSVNode(); -- cgit v1.2.3 From c19f3ea1b263f52add0604f94fde63bb54214dfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20T=C3=B6nne?= Date: Mon, 4 May 2015 14:30:46 +0200 Subject: Fixed comment. --- source/blender/blenlib/intern/math_matrix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 081c555ed6f..1360c735805 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -2261,7 +2261,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) void pseudoinverse_m4_m4(float Ainv[4][4], float A_[4][4], float epsilon) { - /* compute moon-penrose pseudo inverse of matrix, singular values + /* compute Moore-Penrose pseudo inverse of matrix, singular values * below epsilon are ignored for stability (truncated SVD) */ float A[4][4], V[4][4], W[4], Wm[4][4], U[4][4]; int i; -- cgit v1.2.3 From 73c090fe81fcc6f0966681171377412d0b4d1da4 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 4 May 2015 14:34:44 +0200 Subject: Fix T44594 disable depth of field in wireframe/bounding box modes. We don't supply depth information in those modes so supporting the effects does not really make sense --- source/blender/editors/space_view3d/view3d_draw.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index da628c32341..57b417ef1d7 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -3729,7 +3729,7 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3 #endif /* framebuffer fx needed, we need to draw offscreen first */ - if (v3d->fx_settings.fx_flag) { + if (v3d->fx_settings.fx_flag && v3d->drawtype >= OB_SOLID) { GPUFXSettings fx_settings; BKE_screen_gpu_fx_validate(&v3d->fx_settings); fx_settings = v3d->fx_settings; @@ -3742,9 +3742,6 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3 fx_settings.dof = NULL; } - if (v3d->drawtype < OB_SOLID) - fx_settings.ssao = NULL; - do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings); } -- cgit v1.2.3 From 9ff91acadbe99b414165ec6604374641001c0a98 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 4 May 2015 14:38:02 +0200 Subject: Follow up to previous commit, remove depth of field from UI in wireframe/boundbox mode. --- release/scripts/startup/bl_ui/space_view3d.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 07631f37339..59fc3692e13 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -3022,11 +3022,10 @@ class VIEW3D_PT_view3d_shading(Panel): fx_settings = view.fx_settings - sub = col.column() - sub.active = view.region_3d.view_perspective == 'CAMERA' - sub.prop(fx_settings, "use_dof") - if view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}: + sub = col.column() + sub.active = view.region_3d.view_perspective == 'CAMERA' + sub.prop(fx_settings, "use_dof") col.prop(fx_settings, "use_ssao", text="Ambient Occlusion") if fx_settings.use_ssao: ssao_settings = fx_settings.ssao -- cgit v1.2.3 From 52b9d83417f7ef64b01b3a66af45e9a7dd760de5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 May 2015 22:26:38 +1000 Subject: Fix T44592: Zero scale on an axis, zeros all --- source/blender/blenlib/intern/math_matrix.c | 39 ++++++----------------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 1360c735805..a9afed7a63d 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -1475,39 +1475,14 @@ float mat4_to_scale(float mat[4][4]) void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3]) { - float mat3_n[3][3]; /* mat3 -> normalized, 3x3 */ - float imat3_n[3][3]; /* mat3 -> normalized & inverted, 3x3 */ - - /* rotation & scale are linked, we need to create the mat's - * for these together since they are related. */ - - /* so scale doesn't interfere with rotation [#24291] */ - /* note: this is a workaround for negative matrix not working for rotation conversion, FIXME */ - normalize_m3_m3(mat3_n, mat3); - if (is_negative_m3(mat3)) { - negate_m3(mat3_n); - } - - /* rotation */ /* keep rot as a 3x3 matrix, the caller can convert into a quat or euler */ - copy_m3_m3(rot, mat3_n); - - /* scale */ - /* note: mat4_to_size(ob->size, mat) fails for negative scale */ - invert_m3_m3(imat3_n, mat3_n); - - /* better not edit mat3 */ -#if 0 - mul_m3_m3m3(mat3, imat3_n, mat3); - - size[0] = mat3[0][0]; - size[1] = mat3[1][1]; - size[2] = mat3[2][2]; -#else - size[0] = dot_m3_v3_row_x(imat3_n, mat3[0]); - size[1] = dot_m3_v3_row_y(imat3_n, mat3[1]); - size[2] = dot_m3_v3_row_z(imat3_n, mat3[2]); -#endif + size[0] = normalize_v3_v3(rot[0], mat3[0]); + size[1] = normalize_v3_v3(rot[1], mat3[1]); + size[2] = normalize_v3_v3(rot[2], mat3[2]); + if (UNLIKELY(is_negative_m3(rot))) { + negate_m3(rot); + negate_v3(size); + } } void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[4][4]) -- cgit v1.2.3 From 68fe630735ea6a474e0a303f90cfb72c4e29b973 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 May 2015 23:48:10 +1000 Subject: Fix eyedropper with quad-view --- .../blender/editors/interface/interface_eyedropper.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index 80b01b69647..44e06bab4ab 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -176,8 +176,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int if (sa) { if (sa->spacetype == SPACE_IMAGE) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); + if (ar) { SpaceImage *sima = sa->spacedata.first; int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; @@ -188,8 +188,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int } } else if (sa->spacetype == SPACE_NODE) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); + if (ar) { SpaceNode *snode = sa->spacedata.first; int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; @@ -200,8 +200,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int } } else if (sa->spacetype == SPACE_CLIP) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); + if (ar) { SpaceClip *sc = sa->spacedata.first; int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; @@ -484,8 +484,8 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int if (sa) { if (sa->spacetype == SPACE_VIEW3D) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); + if (ar) { const int mval[2] = { mx - ar->winrct.xmin, my - ar->winrct.ymin}; @@ -767,8 +767,8 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, if (sa) { if (sa->spacetype == SPACE_VIEW3D) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); + if (ar) { View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; /* weak, we could pass in some reference point */ -- cgit v1.2.3 From 1227e5c3d1ee20e9af57984a261b1d51d48c0263 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 4 May 2015 16:57:17 +0200 Subject: Fix T44503 full sample does not display any preview any more. The fix exposes another error not fixed in this commit, escaping the render will not flush the full sample render result correctly. --- source/blender/blenkernel/intern/image.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index b714e8b7eac..5169559d80b 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -3623,6 +3623,15 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ if (rpass) { channels = rpass->channels; rectf = rpass->rect; + + if (!rectf) { + /* Happens when Save Buffers is enabled. + * Use display buffer stored in the render layer. + */ + rect = (unsigned int *) rl->display_buffer; + byte_buffer_in_display_space = true; + } + dither = 0.0f; /* don't dither passes */ } -- cgit v1.2.3 From fd5090ab41f82b1e12e8e773b6088bf5a536acea Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 May 2015 01:05:09 +1000 Subject: UI: button snap (ctrl) was rounding down --- .../blender/editors/interface/interface_handlers.c | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 1d71a5db350..3d8a56c976c 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -365,7 +365,7 @@ static void ui_color_snap_hue(const enum eSnapType snap, float *r_hue) { const float snap_increment = (snap == SNAP_ON_SMALL) ? 24 : 12; BLI_assert(snap != SNAP_OFF); - *r_hue = floorf(0.5f + ((*r_hue) * snap_increment)) / snap_increment; + *r_hue = roundf((*r_hue) * snap_increment) / snap_increment; } /* assumes event type is MOUSEPAN */ @@ -3502,14 +3502,14 @@ static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, floa } if (snap == SNAP_ON) { - if (softrange < 2.10f) tempf = 0.1f * floorf(10.0f * tempf); - else if (softrange < 21.0f) tempf = floorf(tempf); - else tempf = 10.0f * floorf(tempf / 10.0f); + if (softrange < 2.10f) tempf = roundf(tempf * 10.0f) * 0.1f; + else if (softrange < 21.0f) tempf = roundf(tempf); + else tempf = roundf(tempf * 0.1f) * 10.0f; } else if (snap == SNAP_ON_SMALL) { - if (softrange < 2.10f) tempf = 0.01f * floorf(100.0f * tempf); - else if (softrange < 21.0f) tempf = 0.1f * floorf(10.0f * tempf); - else tempf = floor(tempf); + if (softrange < 2.10f) tempf = roundf(tempf * 100.0f) * 0.01f; + else if (softrange < 21.0f) tempf = roundf(tempf * 10.0f) * 0.1f; + else tempf = roundf(tempf); } else { BLI_assert(0); @@ -3660,7 +3660,7 @@ static bool ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, if (!is_float) { - temp = floorf(tempf + 0.5f); + temp = iroundf(tempf); temp = ui_numedit_apply_snap(temp, softmin, softmax, snap); @@ -3933,7 +3933,7 @@ static bool ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, tempf = softmin + f * softrange; - temp = floorf(tempf + 0.5f); + temp = iroundf(tempf); if (snap) { if (tempf == softmin || tempf == softmax) { @@ -3943,14 +3943,14 @@ static bool ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, if (shift) { if (tempf == softmin || tempf == softmax) {} - else if (softmax - softmin < 2.10f) tempf = 0.01f * floorf(100.0f * tempf); - else if (softmax - softmin < 21.0f) tempf = 0.1f * floorf(10.0f * tempf); - else tempf = floorf(tempf); + else if (softrange < 2.10f) tempf = roundf(tempf * 100.0f) * 0.01f; + else if (softrange < 21.0f) tempf = roundf(tempf * 10.0f) * 0.1f; + else tempf = roundf(tempf); } else { - if (softmax - softmin < 2.10f) tempf = 0.1f * floorf(10.0f * tempf); - else if (softmax - softmin < 21.0f) tempf = floorf(tempf); - else tempf = 10.0f * floorf(tempf / 10.0f); + if (softrange < 2.10f) tempf = roundf(tempf * 10.0f) * 0.1f; + else if (softrange < 21.0f) tempf = roundf(tempf); + else tempf = roundf(tempf * 0.1f) * 10.0f; } } else { @@ -3960,7 +3960,7 @@ static bool ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, } if (!ui_but_is_float(but)) { - lvalue = floor(data->value + 0.5); + lvalue = round(data->value); CLAMP(temp, softmin, softmax); @@ -4434,7 +4434,7 @@ static bool ui_numedit_but_UNITVEC(uiBut *but, uiHandleButtonData *data, * do this in "angle" space - this gives increments of same size */ for (i = 0; i < 3; i++) { angle = asinf(fp[i]); - angle_snap = floorf(0.5f + (angle / snap_steps_angle)) * snap_steps_angle; + angle_snap = roundf((angle / snap_steps_angle)) * snap_steps_angle; fp[i] = sinf(angle_snap); } normalize_v3(fp); @@ -5360,8 +5360,8 @@ static bool ui_numedit_but_CURVE(uiBlock *block, uiBut *but, uiHandleButtonData cmp[a].x += fx; cmp[a].y += fy; if (snap) { - cmp[a].x = 0.125f * floorf(0.5f + 8.0f * cmp[a].x); - cmp[a].y = 0.125f * floorf(0.5f + 8.0f * cmp[a].y); + cmp[a].x = 0.125f * roundf(8.0f * cmp[a].x); + cmp[a].y = 0.125f * roundf(8.0f * cmp[a].y); } if (cmp[a].x != origx || cmp[a].y != origy) moved_point = true; -- cgit v1.2.3 From 1b8069bdd921a2807f156682aec540f2acc37e3c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 May 2015 01:20:40 +1000 Subject: UI: location/scale were snapping to 10s In practice this isn't useful (for scale especially). For float buttons with a very large range, don't attempt to match the snap to the range. --- source/blender/editors/interface/interface_handlers.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 3d8a56c976c..7ed02c9e83e 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3501,6 +3501,16 @@ static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, floa softrange /= fac; } + /* workaround, too high snapping values */ + /* snapping by 10's for float buttons is quite annoying (location, scale...), + * but allow for rotations */ + if ((softrange > 2100.0f)) { + int unit_type = UI_but_unit_type_get(but); + if (!ELEM(unit_type, PROP_UNIT_ROTATION)) { + softrange = 20.0f; + } + } + if (snap == SNAP_ON) { if (softrange < 2.10f) tempf = roundf(tempf * 10.0f) * 0.1f; else if (softrange < 21.0f) tempf = roundf(tempf); -- cgit v1.2.3 From e10ecb6494e99e5880a1bad296464a2475feac8e Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 4 May 2015 18:00:29 +0200 Subject: Revert "Different drawing for object centers." This reverts commit 5a8629c0d7da6cfb4b696f1787111c9492e03aba. It does not really work that well since objects can draw in front of selection circles now. --- source/blender/editors/space_view3d/drawobject.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index de2b5a39313..5b2ac50216a 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -735,7 +735,11 @@ static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f; float verts[CIRCLE_RESOL][3]; - if (v3d->zbuf) glDisable(GL_DEPTH_TEST); + /* using gldepthfunc guarantees that it does write z values, + * but not checks for it, so centers remain visible independent order of drawing */ + if (v3d->zbuf) glDepthFunc(GL_ALWAYS); + /* write to near buffer always */ + glDepthRange(0.0, 0.0); glEnable(GL_BLEND); if (special_color) { @@ -765,9 +769,10 @@ static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], /* finish up */ glDisableClientState(GL_VERTEX_ARRAY); + glDepthRange(0.0, 1.0); glDisable(GL_BLEND); - if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + if (v3d->zbuf) glDepthFunc(GL_LEQUAL); } /* *********** text drawing for object/particles/armature ************* */ -- cgit v1.2.3 From cc81b58277dcea68587d3ff2f4a3ee8a6b28c074 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 4 May 2015 21:12:28 +0200 Subject: Cleanup: deduplicate code. FileBrowser had its own 'shorten_string' func, when we have a full fledge one in interface_widget code... --- source/blender/editors/include/UI_interface.h | 5 +++ .../blender/editors/interface/interface_widgets.c | 15 ++++--- source/blender/editors/space_file/file_draw.c | 2 +- source/blender/editors/space_file/file_intern.h | 1 - source/blender/editors/space_file/filesel.c | 52 ---------------------- 5 files changed, 14 insertions(+), 61 deletions(-) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 1e0cc972ef8..01fd19c14e9 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -319,6 +319,11 @@ void UI_draw_safe_areas( #define UI_SCROLL_NO_OUTLINE (1 << 2) void UI_draw_widget_scroll(struct uiWidgetColors *wcol, const struct rcti *rect, const struct rcti *slider, int state); +/* Shortening string helper. */ +float UI_text_clip_middle_ex( + struct uiFontStyle *fstyle, char *str, float okwidth, const float minwidth, + const size_t max_len, const char *rpart_sep); + /* Callbacks * * UI_block_func_handle_set/ButmFunc are for handling events through a callback. diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 08bd2d3360c..cc7f975b275 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -965,8 +965,9 @@ static void ui_text_clip_right_ex(uiFontStyle *fstyle, char *str, const size_t m * If rpart_sep is not Null, the part of str starting to first occurrence of rpart_sep is preserved at all cost (useful * for strings with shortcuts, like 'AVeryLongFooBarLabelForMenuEntry|Ctrl O' -> 'AVeryLong...MenuEntry|Ctrl O'). */ -static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, float okwidth, const float minwidth, - const size_t max_len, const char *rpart_sep) +float UI_text_clip_middle_ex( + uiFontStyle *fstyle, char *str, float okwidth, const float minwidth, + const size_t max_len, const char *rpart_sep) { float strwidth; @@ -1066,7 +1067,7 @@ static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, float okwidt } /** - * Wrapper around ui_text_clip_middle_ex. + * Wrapper around UI_text_clip_middle_ex. */ static void ui_text_clip_middle(uiFontStyle *fstyle, uiBut *but, const rcti *rect) { @@ -1077,7 +1078,7 @@ static void ui_text_clip_middle(uiFontStyle *fstyle, uiBut *but, const rcti *rec const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f; but->ofs = 0; - but->strwidth = ui_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, NULL); + but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, NULL); } /** @@ -1093,7 +1094,7 @@ static void ui_text_clip_middle_protect_right(uiFontStyle *fstyle, uiBut *but, c const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f; but->ofs = 0; - but->strwidth = ui_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, rsep); + but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, rsep); } /** @@ -4065,7 +4066,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic const float minwidth = (float)(UI_DPI_ICON_SIZE); BLI_strncpy(drawstr, name, sizeof(drawstr)); - ui_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, NULL); + UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, NULL); glColor4ubv((unsigned char *)wt->wcol.text); UI_fontstyle_draw(fstyle, rect, drawstr); @@ -4140,7 +4141,7 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int const float minwidth = (float)(UI_DPI_ICON_SIZE); BLI_strncpy(drawstr, name, sizeof(drawstr)); - ui_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, NULL); + UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, NULL); glColor4ubv((unsigned char *)wt->wcol.text); UI_fontstyle_draw(fstyle, &trect, drawstr); diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index d5b9c169192..3553a0ed79a 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -303,7 +303,7 @@ static void file_draw_string(int sx, int sy, const char *string, float width, in fs.align = align; BLI_strncpy(fname, string, FILE_MAXFILE); - file_shorten_string(fname, width + 1.0f, 0); + UI_text_clip_middle_ex(&fs, fname, width + 1.0f, UI_DPI_ICON_SIZE, sizeof(fname), NULL); /* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict (for buttons it works) */ rect.xmin = sx; diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index f1fd4e2b683..dbb5e8a773d 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -101,7 +101,6 @@ void file_operator_to_sfile(struct SpaceFile *sfile, struct wmOperator *op); /* filesel.c */ -float file_shorten_string(char *string, float w, int front); float file_string_width(const char *str); float file_font_pointsize(void); diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 82409c9ecb4..29a8a06fa23 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -398,58 +398,6 @@ void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y) } } -/* Shorten a string to a given width w. - * If front is set, shorten from the front, - * otherwise shorten from the end. */ -float file_shorten_string(char *string, float w, int front) -{ - char temp[FILE_MAX]; - short shortened = 0; - float sw = 0; - float pad = 0; - - if (w <= 0) { - *string = '\0'; - return 0.0; - } - - sw = file_string_width(string); - if (front == 1) { - const char *s = string; - BLI_strncpy(temp, "...", 4); - pad = file_string_width(temp); - while ((*s) && (sw + pad > w)) { - s++; - sw = file_string_width(s); - shortened = 1; - } - if (shortened) { - int slen = strlen(s); - BLI_strncpy(temp + 3, s, slen + 1); - temp[slen + 4] = '\0'; - BLI_strncpy(string, temp, slen + 4); - } - } - else { - const char *s = string; - while (sw > w) { - int slen = strlen(string); - string[slen - 1] = '\0'; - sw = file_string_width(s); - shortened = 1; - } - - if (shortened) { - int slen = strlen(string); - if (slen > 3) { - BLI_strncpy(string + slen - 3, "...", 4); - } - } - } - - return sw; -} - float file_string_width(const char *str) { uiStyle *style = UI_style_get(); -- cgit v1.2.3 From 7478eb9bd09965f7d27064b500c91322f4fe3f14 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 May 2015 03:13:47 +1000 Subject: Cleanup: wrapped function indentation --- source/blender/editors/interface/interface.c | 23 +-- source/blender/editors/interface/interface_draw.c | 5 +- .../blender/editors/interface/interface_handlers.c | 128 +++++++------ source/blender/editors/interface/interface_icons.c | 15 +- .../blender/editors/interface/interface_intern.h | 24 +-- .../blender/editors/interface/interface_layout.c | 39 ++-- source/blender/editors/interface/interface_ops.c | 5 +- source/blender/editors/interface/interface_panel.c | 9 +- .../blender/editors/interface/interface_regions.c | 29 +-- .../editors/interface/interface_templates.c | 82 +++++---- source/blender/editors/interface/interface_utils.c | 7 +- .../blender/editors/interface/interface_widgets.c | 10 +- source/blender/editors/interface/resources.c | 5 +- source/blender/editors/interface/view2d.c | 199 ++++++++++++--------- source/blender/editors/interface/view2d_ops.c | 10 +- 15 files changed, 345 insertions(+), 245 deletions(-) diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 5c548d3afd5..b63871f5c82 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -3105,9 +3105,10 @@ void ui_block_cm_to_scene_linear_v3(uiBlock *block, float pixel[3]) * - \a a2 Number of decimal point values to display. 0 defaults to 3 (0.000) * 1,2,3, and a maximum of 4, all greater values will be clamped to 4. */ -static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, - int x, int y, short width, short height, - void *poin, float min, float max, float a1, float a2, const char *tip) +static uiBut *ui_def_but( + uiBlock *block, int type, int retval, const char *str, + int x, int y, short width, short height, + void *poin, float min, float max, float a1, float a2, const char *tip) { uiBut *but; int slen; @@ -3375,10 +3376,11 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu * When this kind of change won't disrupt branches, best look into making more * of our UI functions take prop rather then propname. */ -static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *str, - int x, int y, short width, short height, - PointerRNA *ptr, PropertyRNA *prop, int index, - float min, float max, float a1, float a2, const char *tip) +static uiBut *ui_def_but_rna( + uiBlock *block, int type, int retval, const char *str, + int x, int y, short width, short height, + PointerRNA *ptr, PropertyRNA *prop, int index, + float min, float max, float a1, float a2, const char *tip) { const PropertyType proptype = RNA_property_type(prop); uiBut *but; @@ -4386,9 +4388,10 @@ static void operator_enum_call_cb(struct bContext *UNUSED(C), void *but, void *a /* Same parameters as for uiDefSearchBut, with additional operator type and properties, used by callback * to call again the right op with the right options (properties values). */ -uiBut *uiDefSearchButO_ptr(uiBlock *block, wmOperatorType *ot, IDProperty *properties, - void *arg, int retval, int icon, int maxlen, int x, int y, - short width, short height, float a1, float a2, const char *tip) +uiBut *uiDefSearchButO_ptr( + uiBlock *block, wmOperatorType *ot, IDProperty *properties, + void *arg, int retval, int icon, int maxlen, int x, int y, + short width, short height, float a1, float a2, const char *tip) { uiBut *but; diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 414903fa194..e2504bbc743 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -508,8 +508,9 @@ static void draw_scope_end(const rctf *rect, GLint *scissor) UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f); } -static void histogram_draw_one(float r, float g, float b, float alpha, - float x, float y, float w, float h, const float *data, int res, const bool is_line) +static void histogram_draw_one( + float r, float g, float b, float alpha, + float x, float y, float w, float h, const float *data, int res, const bool is_line) { int i; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 7ed02c9e83e..9ee263846a4 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -52,9 +52,9 @@ #include "BLI_linklist.h" #include "BLI_string.h" #include "BLI_string_utf8.h" +#include "BLI_string_cursor_utf8.h" #include "BLI_rect.h" #include "BLI_utildefines.h" -#include "BLI_string_cursor_utf8.h" #include "BLF_translation.h" @@ -328,8 +328,9 @@ static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, c static uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event); static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type); static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state); -static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *data, - const bool mousemove, const bool onfree); +static void button_activate_exit( + bContext *C, uiBut *but, uiHandleButtonData *data, + const bool mousemove, const bool onfree); static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *userdata); static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type); @@ -477,10 +478,9 @@ static float ui_mouse_scale_warp_factor(const bool shift) return shift ? 0.05f : 1.0f; } -static void ui_mouse_scale_warp(uiHandleButtonData *data, - const float mx, const float my, - float *r_mx, float *r_my, - const bool shift) +static void ui_mouse_scale_warp( + uiHandleButtonData *data, const float mx, const float my, + float *r_mx, float *r_my, const bool shift) { const float fac = ui_mouse_scale_warp_factor(shift); @@ -1063,8 +1063,9 @@ typedef struct uiDragToggleHandle { int xy_last[2]; } uiDragToggleHandle; -static bool ui_drag_toggle_set_xy_xy(bContext *C, ARegion *ar, const bool is_set, const eButType but_type_start, - const int xy_src[2], const int xy_dst[2]) +static bool ui_drag_toggle_set_xy_xy( + bContext *C, ARegion *ar, const bool is_set, const eButType but_type_start, + const int xy_src[2], const int xy_dst[2]) { /* popups such as layers won't re-evaluate on redraw */ const bool do_check = (ar->regiontype == RGN_TYPE_TEMPORARY); @@ -2183,8 +2184,9 @@ static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data, /* this is used for both utf8 and ascii, its meant to be used for single keys, * notice the buffer is either copied or not, so its not suitable for pasting in * - campbell */ -static bool ui_textedit_type_buf(uiBut *but, uiHandleButtonData *data, - const char *utf8_buf, int utf8_buf_len) +static bool ui_textedit_type_buf( + uiBut *but, uiHandleButtonData *data, + const char *utf8_buf, int utf8_buf_len) { char *str; int len; @@ -2228,8 +2230,9 @@ static bool ui_textedit_type_ascii(uiBut *but, uiHandleButtonData *data, char as return ui_textedit_type_buf(but, data, buf, 1); } -static void ui_textedit_move(uiBut *but, uiHandleButtonData *data, strCursorJumpDirection direction, - const bool select, strCursorJumpType jump) +static void ui_textedit_move( + uiBut *but, uiHandleButtonData *data, strCursorJumpDirection direction, + const bool select, strCursorJumpType jump) { const char *str = data->str; const int len = strlen(str); @@ -3128,9 +3131,13 @@ int ui_but_menu_direction(uiBut *but) return 0; } -/* Hack for uiList UI_BTYPE_LISTROW buttons to "give" events to overlaying UI_BTYPE_TEXT buttons (cltr-clic rename feature & co). */ -static uiBut *ui_but_list_row_text_activate(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event, - uiButtonActivateType activate_type) +/** + * Hack for uiList UI_BTYPE_LISTROW buttons to "give" events to overlaying UI_BTYPE_TEXT buttons + * (cltr-clic rename feature & co). + */ +static uiBut *ui_but_list_row_text_activate( + bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event, + uiButtonActivateType activate_type) { ARegion *ar = CTX_wm_region(C); uiBut *labelbut = ui_but_find_mouse_over_ex(ar, event->x, event->y, true); @@ -3472,8 +3479,9 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con } /* var names match ui_numedit_but_NUM */ -static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, float softmax, float softrange, - const enum eSnapType snap) +static float ui_numedit_apply_snapf( + uiBut *but, float tempf, float softmin, float softmax, float softrange, + const enum eSnapType snap) { if (tempf == softmin || tempf == softmax || snap == SNAP_OFF) { /* pass */ @@ -3532,8 +3540,9 @@ static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, floa return tempf; } -static float ui_numedit_apply_snap(int temp, float softmin, float softmax, - const enum eSnapType snap) +static float ui_numedit_apply_snap( + int temp, float softmin, float softmax, + const enum eSnapType snap) { if (temp == softmin || temp == softmax) return temp; @@ -3552,9 +3561,10 @@ static float ui_numedit_apply_snap(int temp, float softmin, float softmax, return temp; } -static bool ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, - int mx, - const enum eSnapType snap, float fac) +static bool ui_numedit_but_NUM( + uiBut *but, uiHandleButtonData *data, + int mx, + const enum eSnapType snap, float fac) { float deler, tempf, softmin, softmax, softrange; int lvalue, temp; @@ -3888,9 +3898,10 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton return retval; } -static bool ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, - int mx, const bool is_horizontal, - const bool snap, const bool shift) +static bool ui_numedit_but_SLI( + uiBut *but, uiHandleButtonData *data, + int mx, const bool is_horizontal, + const bool snap, const bool shift) { float deler, f, tempf, softmin, softmax, softrange; int temp, lvalue; @@ -4376,9 +4387,10 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co return WM_UI_HANDLER_CONTINUE; } -static bool ui_numedit_but_UNITVEC(uiBut *but, uiHandleButtonData *data, - int mx, int my, - const enum eSnapType snap) +static bool ui_numedit_but_UNITVEC( + uiBut *but, uiHandleButtonData *data, + int mx, int my, + const enum eSnapType snap) { float dx, dy, rad, radsq, mrad, *fp; int mdx, mdy; @@ -4678,9 +4690,10 @@ static void ui_color_picker_to_rgb_HSVCUBE_v(uiBut *but, const float hsv[3], flo hsv_to_rgb_v(hsv, rgb); } -static bool ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, - int mx, int my, - const enum eSnapType snap, const bool shift) +static bool ui_numedit_but_HSVCUBE( + uiBut *but, uiHandleButtonData *data, + int mx, int my, + const enum eSnapType snap, const bool shift) { ColorPicker *cpicker = but->custom_data; float *hsv = cpicker->color_data; @@ -4797,9 +4810,10 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, return changed; } -static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, - const wmNDOFMotionData *ndof, - const enum eSnapType snap, const bool shift) +static void ui_ndofedit_but_HSVCUBE( + uiBut *but, uiHandleButtonData *data, + const wmNDOFMotionData *ndof, + const enum eSnapType snap, const bool shift) { ColorPicker *cpicker = but->custom_data; float *hsv = cpicker->color_data; @@ -4962,9 +4976,10 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu return WM_UI_HANDLER_CONTINUE; } -static bool ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, - float mx, float my, - const enum eSnapType snap, const bool shift) +static bool ui_numedit_but_HSVCIRCLE( + uiBut *but, uiHandleButtonData *data, + float mx, float my, + const enum eSnapType snap, const bool shift) { rcti rect; bool changed = true; @@ -5059,9 +5074,10 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, return changed; } -static void ui_ndofedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, - const wmNDOFMotionData *ndof, - const enum eSnapType snap, const bool shift) +static void ui_ndofedit_but_HSVCIRCLE( + uiBut *but, uiHandleButtonData *data, + const wmNDOFMotionData *ndof, + const enum eSnapType snap, const bool shift) { ColorPicker *cpicker = but->custom_data; float *hsv = cpicker->color_data; @@ -5320,7 +5336,8 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle return WM_UI_HANDLER_CONTINUE; } -static bool ui_numedit_but_CURVE(uiBlock *block, uiBut *but, uiHandleButtonData *data, +static bool ui_numedit_but_CURVE( + uiBlock *block, uiBut *but, uiHandleButtonData *data, int evtx, int evty, bool snap, const bool shift) { @@ -5754,9 +5771,10 @@ static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, con return WM_UI_HANDLER_CONTINUE; } -static bool ui_numedit_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonData *data, - int mx, int my, - const bool shift) +static bool ui_numedit_but_TRACKPREVIEW( + bContext *C, uiBut *but, uiHandleButtonData *data, + int mx, int my, + const bool shift) { MovieClipScopes *scopes = (MovieClipScopes *)but->poin; bool changed = true; @@ -7197,8 +7215,9 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA } } -static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *data, - const bool mousemove, const bool onfree) +static void button_activate_exit( + bContext *C, uiBut *but, uiHandleButtonData *data, + const bool mousemove, const bool onfree) { uiBlock *block = but->block; uiBut *bt; @@ -8005,8 +8024,9 @@ static void ui_mouse_motion_towards_reinit(uiPopupBlockHandle *menu, const int x ui_mouse_motion_towards_init_ex(menu, xy, true); } -static bool ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *menu, const int xy[2], - const bool use_wiggle_room) +static bool ui_mouse_motion_towards_check( + uiBlock *block, uiPopupBlockHandle *menu, const int xy[2], + const bool use_wiggle_room) { float p1[2], p2[2], p3[2], p4[2]; float oldp[2] = {menu->towards_xy[0], menu->towards_xy[1]}; @@ -8194,8 +8214,9 @@ static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my, uiBut *to_bt) * * Without this keyboard navigation from menu's wont work. */ -static bool ui_menu_pass_event_to_parent_if_nonactive(uiPopupBlockHandle *menu, const uiBut *but, - const int level, const int retval) +static bool ui_menu_pass_event_to_parent_if_nonactive( + uiPopupBlockHandle *menu, const uiBut *but, + const int level, const int retval) { if ((level != 0) && (but == NULL)) { menu->menuretval = UI_RETURN_OUT | UI_RETURN_OUT_PARENT; @@ -9414,8 +9435,9 @@ void UI_popup_handlers_remove_all(bContext *C, ListBase *handlers) WM_event_free_ui_handler_all(C, handlers, ui_popup_handler, ui_popup_handler_remove); } -bool UI_textbutton_activate_rna(const bContext *C, ARegion *ar, - const void *rna_poin_data, const char *rna_prop_id) +bool UI_textbutton_activate_rna( + const bContext *C, ARegion *ar, + const void *rna_poin_data, const char *rna_prop_id) { uiBlock *block; uiBut *but = NULL; diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 679681cb372..6536c0a869e 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1037,8 +1037,9 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), } } -static void icon_draw_texture(float x, float y, float w, float h, int ix, int iy, - int UNUSED(iw), int ih, float alpha, const float rgb[3]) +static void icon_draw_texture( + float x, float y, float w, float h, int ix, int iy, + int UNUSED(iw), int ih, float alpha, const float rgb[3]) { float x1, x2, y1, y2; @@ -1088,8 +1089,9 @@ static int get_draw_size(enum eIconSizes size) -static void icon_draw_size(float x, float y, int icon_id, float aspect, float alpha, const float rgb[3], - enum eIconSizes size, int draw_size, const bool UNUSED(nocreate), const bool is_preview) +static void icon_draw_size( + float x, float y, int icon_id, float aspect, float alpha, const float rgb[3], + enum eIconSizes size, int draw_size, const bool UNUSED(nocreate), const bool is_preview) { bTheme *btheme = UI_GetTheme(); Icon *icon = NULL; @@ -1317,8 +1319,9 @@ int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big return rnaicon; } -static void icon_draw_at_size(float x, float y, int icon_id, float aspect, float alpha, - enum eIconSizes size, const bool nocreate) +static void icon_draw_at_size( + float x, float y, int icon_id, float aspect, float alpha, + enum eIconSizes size, const bool nocreate) { int draw_size = get_draw_size(size); icon_draw_size(x, y, icon_id, aspect, alpha, NULL, size, draw_size, nocreate, false); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index d9558af5f71..a3192d3b8d0 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -451,8 +451,9 @@ extern void ui_but_hsv_set(uiBut *but); extern void ui_but_v3_get(uiBut *but, float vec[3]); extern void ui_but_v3_set(uiBut *but, const float vec[3]); -extern void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rect, - const float mx, const float my); +extern void ui_hsvcircle_vals_from_pos( + float *val_rad, float *val_dist, const rcti *rect, + const float mx, const float my); extern void ui_hsvcircle_pos_from_vals(struct uiBut *but, const rcti *rect, float *hsv, float *xpos, float *ypos); extern void ui_hsvcube_pos_from_vals(struct uiBut *but, const rcti *rect, float *hsv, float *xp, float *yp); bool ui_but_is_colorpicker_display_space(struct uiBut *but); @@ -581,14 +582,17 @@ bool ui_searchbox_apply(uiBut *but, struct ARegion *ar); void ui_searchbox_free(struct bContext *C, struct ARegion *ar); void ui_but_search_refresh(uiBut *but); -uiBlock *ui_popup_block_refresh(struct bContext *C, uiPopupBlockHandle *handle, - ARegion *butregion, uiBut *but); - -uiPopupBlockHandle *ui_popup_block_create(struct bContext *C, struct ARegion *butregion, uiBut *but, - uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, - void *arg); -uiPopupBlockHandle *ui_popup_menu_create(struct bContext *C, struct ARegion *butregion, uiBut *but, - uiMenuCreateFunc create_func, void *arg); +uiBlock *ui_popup_block_refresh( + struct bContext *C, uiPopupBlockHandle *handle, + ARegion *butregion, uiBut *but); + +uiPopupBlockHandle *ui_popup_block_create( + struct bContext *C, struct ARegion *butregion, uiBut *but, + uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, + void *arg); +uiPopupBlockHandle *ui_popup_menu_create( + struct bContext *C, struct ARegion *butregion, uiBut *but, + uiMenuCreateFunc create_func, void *arg); void ui_popup_block_free(struct bContext *C, uiPopupBlockHandle *handle); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index eeda7a2c390..e8974b8571c 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -356,9 +356,10 @@ static void ui_layer_but_cb(bContext *C, void *arg_but, void *arg_index) } /* create buttons for an item with an RNA array */ -static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, int icon, - PointerRNA *ptr, PropertyRNA *prop, int len, int x, int y, int w, int UNUSED(h), - bool expand, bool slider, bool toggle, bool icon_only) +static void ui_item_array( + uiLayout *layout, uiBlock *block, const char *name, int icon, + PointerRNA *ptr, PropertyRNA *prop, int len, int x, int y, int w, int UNUSED(h), + bool expand, bool slider, bool toggle, bool icon_only) { uiStyle *style = layout->root->style; uiBut *but; @@ -545,8 +546,9 @@ static void ui_item_enum_expand_handle(bContext *C, void *arg1, void *arg2) RNA_property_enum_set(&but->rnapoin, but->rnaprop, current_value); } } -static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, - const char *uiname, int h, bool icon_only) +static void ui_item_enum_expand( + uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, + const char *uiname, int h, bool icon_only) { /* XXX The way this function currently handles uiname parameter is insane and inconsistent with general UI API: * * uiname is the *enum property* label. @@ -877,8 +879,9 @@ void uiItemEnumO(uiLayout *layout, const char *opname, const char *name, int ico } -void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname, IDProperty *properties, - int context, int flag) +void uiItemsFullEnumO( + uiLayout *layout, const char *opname, const char *propname, IDProperty *properties, + int context, int flag) { wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */ @@ -1129,8 +1132,9 @@ void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname) /* RNA property items */ -static void ui_item_rna_size(uiLayout *layout, const char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, - int index, bool icon_only, int *r_w, int *r_h) +static void ui_item_rna_size( + uiLayout *layout, const char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, + int index, bool icon_only, int *r_w, int *r_h) { PropertyType type; PropertySubType subtype; @@ -1680,8 +1684,9 @@ static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt) layout->root->block->flag ^= UI_BLOCK_IS_FLIP; } -static uiBut *ui_item_menu(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN, - const char *tip, bool force_menu) +static uiBut *ui_item_menu( + uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN, + const char *tip, bool force_menu) { uiBlock *block = layout->root->block; uiBut *but; @@ -2736,8 +2741,9 @@ void ui_layout_list_set_labels_active(uiLayout *layout) } } -uiLayout *uiLayoutListBox(uiLayout *layout, uiList *ui_list, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr, - PropertyRNA *actprop) +uiLayout *uiLayoutListBox( + uiLayout *layout, uiList *ui_list, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr, + PropertyRNA *actprop) { uiLayoutItemBx *box = ui_layout_box(layout, UI_BTYPE_LISTBOX); uiBut *but = box->roundbox; @@ -3336,9 +3342,10 @@ static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), void *op_pt, #endif /* this function does not initialize the layout, functions can be called on the layout before and after */ -void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, - bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *), - const char label_align, const short flag) +void uiLayoutOperatorButs( + const bContext *C, uiLayout *layout, wmOperator *op, + bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *), + const char label_align, const short flag) { if (!op->properties) { IDPropertyTemplate val = {0}; diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 72abfcb9293..4f78a1a440e 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -553,8 +553,9 @@ void UI_editsource_active_but_test(uiBut *but) BLI_ghash_insert(ui_editsource_info->hash, but, but_store); } -static int editsource_text_edit(bContext *C, wmOperator *op, - char filepath[FILE_MAX], int line) +static int editsource_text_edit( + bContext *C, wmOperator *op, + char filepath[FILE_MAX], int line) { struct Main *bmain = CTX_data_main(C); Text *text; diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 239d6f7c493..95fca10d60b 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -1508,10 +1508,11 @@ void UI_panel_category_clear_all(ARegion *ar) } /* based on UI_draw_roundbox_gl_mode, check on making a version which allows us to skip some sides */ -static void ui_panel_category_draw_tab(int mode, float minx, float miny, float maxx, float maxy, float rad, - int roundboxtype, - const bool use_highlight, const bool use_shadow, - const unsigned char highlight_fade[3]) +static void ui_panel_category_draw_tab( + int mode, float minx, float miny, float maxx, float maxy, float rad, + int roundboxtype, + const bool use_highlight, const bool use_shadow, + const unsigned char highlight_fade[3]) { float vec[4][2] = { {0.195, 0.02}, diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 7cb9dca78bf..9f5aa37351a 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -179,9 +179,10 @@ typedef struct uiTooltipData { BLI_STATIC_ASSERT(UI_TIP_LC_MAX == UI_TIP_LC_ALERT + 1, "invalid lc-max"); BLI_STATIC_ASSERT(sizeof(((uiTooltipData *)NULL)->format[0]) <= sizeof(int), "oversize"); -static void rgb_tint(float col[3], - float h, float h_strength, - float v, float v_strength) +static void rgb_tint( + float col[3], + float h, float h_strength, + float v, float v_strength) { float col_hsv_from[3]; float col_hsv_to[3]; @@ -1808,9 +1809,10 @@ uiBlock *ui_popup_block_refresh( return block; } -uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut *but, - uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, - void *arg) +uiPopupBlockHandle *ui_popup_block_create( + bContext *C, ARegion *butregion, uiBut *but, + uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, + void *arg) { wmWindow *window = CTX_wm_window(C); static ARegionType type; @@ -2571,8 +2573,9 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi return pup->block; } -uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut *but, - uiMenuCreateFunc menu_func, void *arg) +uiPopupBlockHandle *ui_popup_menu_create( + bContext *C, ARegion *butregion, uiBut *but, + uiMenuCreateFunc menu_func, void *arg) { wmWindow *window = CTX_wm_window(C); uiStyle *style = UI_style_get_dpi(); @@ -2850,8 +2853,9 @@ int UI_pie_menu_invoke(struct bContext *C, const char *idname, const wmEvent *ev return OPERATOR_INTERFACE; } -int UI_pie_menu_invoke_from_operator_enum(struct bContext *C, const char *title, const char *opname, - const char *propname, const wmEvent *event) +int UI_pie_menu_invoke_from_operator_enum( + struct bContext *C, const char *title, const char *opname, + const char *propname, const wmEvent *event) { uiPieMenu *pie; uiLayout *layout; @@ -2867,8 +2871,9 @@ int UI_pie_menu_invoke_from_operator_enum(struct bContext *C, const char *title, return OPERATOR_INTERFACE; } -int UI_pie_menu_invoke_from_rna_enum(struct bContext *C, const char *title, const char *path, - const wmEvent *event) +int UI_pie_menu_invoke_from_rna_enum( + struct bContext *C, const char *title, const char *path, + const wmEvent *event) { PointerRNA ctx_ptr; PointerRNA r_ptr; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 8d2ee04a2e9..90bcddde0c0 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -403,8 +403,9 @@ static const char *template_id_context(StructRNA *type) } #endif -static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag, - const char *newop, const char *openop, const char *unlinkop) +static void template_ID( + bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag, + const char *newop, const char *openop, const char *unlinkop) { uiBut *but; uiBlock *block; @@ -620,8 +621,9 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str UI_block_align_end(block); } -static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, - const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols) +static void ui_template_id( + uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols) { TemplateID *template; PropertyRNA *prop; @@ -661,21 +663,24 @@ static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const MEM_freeN(template); } -void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, - const char *openop, const char *unlinkop) +void uiTemplateID( + uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop) { ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE, 0, 0); } -void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, - const char *openop, const char *unlinkop) +void uiTemplateIDBrowse( + uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop) { ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME, 0, 0); } -void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, - const char *openop, const char *unlinkop, int rows, int cols) +void uiTemplateIDPreview( + uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop, int rows, int cols) { ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS, rows, cols); @@ -688,8 +693,9 @@ void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const c * - propname: property identifier for property that ID-pointer gets stored to * - proptypename: property identifier for property used to determine the type of ID-pointer that can be used */ -void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, - const char *text) +void uiTemplateAnyID( + uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, + const char *text) { PropertyRNA *propID, *propType; uiLayout *split, *row, *sub; @@ -823,8 +829,9 @@ static int modifier_is_simulation(ModifierData *md) } } -static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, - ModifierData *md, int index, int cageIndex, int lastCageIndex) +static uiLayout *draw_modifier( + uiLayout *layout, Scene *scene, Object *ob, + ModifierData *md, int index, int cageIndex, int lastCageIndex) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); PointerRNA ptr; @@ -1286,8 +1293,9 @@ static void do_preview_buttons(bContext *C, void *arg, int event) } } -void uiTemplatePreview(uiLayout *layout, bContext *C, ID *id, int show_buttons, ID *parent, MTex *slot, - const char *preview_id) +void uiTemplatePreview( + uiLayout *layout, bContext *C, ID *id, int show_buttons, ID *parent, MTex *slot, + const char *preview_id) { uiLayout *row, *col; uiBlock *block; @@ -1495,8 +1503,9 @@ static void colorband_update_cb(bContext *UNUSED(C), void *bt_v, void *coba_v) bt->rnapoin.data = coba->data + coba->cur; } -static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, const rctf *butr, - RNAUpdateCb *cb, int expand) +static void colorband_buttons_layout( + uiLayout *layout, uiBlock *block, ColorBand *coba, const rctf *butr, + RNAUpdateCb *cb, int expand) { uiLayout *row, *split, *subsplit; uiBut *bt; @@ -2074,8 +2083,9 @@ static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v) } /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */ -static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, - int brush, int neg_slope, RNAUpdateCb *cb) +static void curvemap_buttons_layout( + uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, + int brush, int neg_slope, RNAUpdateCb *cb) { CurveMapping *cumap = ptr->data; CurveMap *cm = &cumap->cm[cumap->cur]; @@ -2236,8 +2246,9 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe UI_block_funcN_set(block, NULL, NULL, NULL); } -void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propname, int type, - int levels, int brush, int neg_slope) +void uiTemplateCurveMapping( + uiLayout *layout, PointerRNA *ptr, const char *propname, int type, + int levels, int brush, int neg_slope) { RNAUpdateCb *cb; PropertyRNA *prop = RNA_struct_find_property(ptr, propname); @@ -2280,8 +2291,9 @@ void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propn #define WHEEL_SIZE (5 * U.widget_unit) /* This template now follows User Preference for type - name is not correct anymore... */ -void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, - int lock, int lock_luminosity, int cubic) +void uiTemplateColorPicker( + uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, + int lock, int lock_luminosity, int cubic) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); uiBlock *block = uiLayoutGetBlock(layout); @@ -2456,8 +2468,9 @@ static void handle_layer_buttons(bContext *C, void *arg1, void *arg2) * - for now, grouping of layers is determined by dividing up the length of * the array of layer bitflags */ -void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname, - PointerRNA *used_ptr, const char *used_propname, int active_layer) +void uiTemplateLayers( + uiLayout *layout, PointerRNA *ptr, const char *propname, + PointerRNA *used_ptr, const char *used_propname, int active_layer) { uiLayout *uRow, *uCol; PropertyRNA *prop, *used_prop = NULL; @@ -2523,8 +2536,9 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname, } } -void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propname, - PointerRNA *used_ptr, const char *used_propname, int active_state) +void uiTemplateGameStates( + uiLayout *layout, PointerRNA *ptr, const char *propname, + PointerRNA *used_ptr, const char *used_propname, int active_state) { uiLayout *uRow, *uCol; PropertyRNA *prop, *used_prop = NULL; @@ -2764,8 +2778,9 @@ typedef struct { int end_idx; /* Index of last item to display + 1. */ } uiListLayoutdata; -static void uilist_prepare(uiList *ui_list, int len, int activei, int rows, int maxrows, int columns, - uiListLayoutdata *layoutdata) +static void uilist_prepare( + uiList *ui_list, int len, int activei, int rows, int maxrows, int columns, + uiListLayoutdata *layoutdata) { uiListDyn *dyn_data = ui_list->dyn_data; int activei_row, max_scroll; @@ -2851,9 +2866,10 @@ static char *uilist_item_tooltip_func(bContext *UNUSED(C), void *argN, const cha return BLI_sprintfN("%s - %s", tip, dyn_tooltip); } -void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, const char *list_id, - PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, const char *active_propname, - const char *item_dyntip_propname, int rows, int maxrows, int layout_type, int columns) +void uiTemplateList( + uiLayout *layout, bContext *C, const char *listtype_name, const char *list_id, + PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, const char *active_propname, + const char *item_dyntip_propname, int rows, int maxrows, int layout_type, int columns) { uiListType *ui_list_type; uiList *ui_list = NULL; diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 14d97dd883e..0823238fcb1 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -157,9 +157,10 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind * \a check_prop callback filters functions to avoid drawing certain properties, * in cases where PROP_HIDDEN flag can't be used for a property. */ -int uiDefAutoButsRNA(uiLayout *layout, PointerRNA *ptr, - bool (*check_prop)(PointerRNA *, PropertyRNA *), - const char label_align) +int uiDefAutoButsRNA( + uiLayout *layout, PointerRNA *ptr, + bool (*check_prop)(PointerRNA *, PropertyRNA *), + const char label_align) { uiLayout *split, *col; int flag; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index cc7f975b275..f5ee8e1cf6e 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -835,8 +835,9 @@ static int ui_but_draw_menu_icon(const uiBut *but) /* icons have been standardized... and this call draws in untransformed coordinates */ -static void widget_draw_icon(const uiBut *but, BIFIconID icon, float alpha, const rcti *rect, - const bool show_menu_icon) +static void widget_draw_icon( + const uiBut *but, BIFIconID icon, float alpha, const rcti *rect, + const bool show_menu_icon) { float xs = 0.0f, ys = 0.0f; float aspect, height; @@ -932,8 +933,9 @@ static void ui_text_clip_give_next_off(uiBut *but, const char *str) * This func assumes things like kerning handling have already been handled! * Return the length of modified (right-clipped + ellipsis) string. */ -static void ui_text_clip_right_ex(uiFontStyle *fstyle, char *str, const size_t max_len, const float okwidth, - const char *sep, const int sep_len, const float sep_strwidth, size_t *r_final_len) +static void ui_text_clip_right_ex( + uiFontStyle *fstyle, char *str, const size_t max_len, const float okwidth, + const char *sep, const int sep_len, const float sep_strwidth, size_t *r_final_len) { float tmp; int l_end; diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 8e003e50df3..ed61518de6b 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1511,8 +1511,9 @@ void UI_GetColorPtrShade3ubv(const unsigned char cp[3], unsigned char col[3], in } /* get a 3 byte color, blended and shaded between two other char color pointers */ -void UI_GetColorPtrBlendShade3ubv(const unsigned char cp1[3], const unsigned char cp2[3], unsigned char col[3], - float fac, int offset) +void UI_GetColorPtrBlendShade3ubv( + const unsigned char cp1[3], const unsigned char cp2[3], unsigned char col[3], + float fac, int offset) { int r, g, b; diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index b4a120b2dea..09b97b43ea1 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -99,11 +99,12 @@ BLI_INLINE void clamp_rctf_to_rcti(rcti *dst, const rctf *src) /* XXX still unresolved: scrolls hide/unhide vs region mask handling */ /* XXX there's V2D_SCROLL_HORIZONTAL_HIDE and V2D_SCROLL_HORIZONTAL_FULLR ... */ -/* helper to allow scrollbars to dynamically hide - * - returns a copy of the scrollbar settings with the flags to display - * horizontal/vertical scrollbars removed - * - input scroll value is the v2d->scroll var - * - hide flags are set per region at drawtime +/** + * helper to allow scrollbars to dynamically hide + * - returns a copy of the scrollbar settings with the flags to display + * horizontal/vertical scrollbars removed + * - input scroll value is the v2d->scroll var + * - hide flags are set per region at drawtime */ static int view2d_scroll_mapped(int scroll) { @@ -197,11 +198,12 @@ static void view2d_masks(View2D *v2d, int check_scrollers) /* Refresh and Validation */ -/* Initialize all relevant View2D data (including view rects if first time) and/or refresh mask sizes after view resize - * - for some of these presets, it is expected that the region will have defined some - * additional settings necessary for the customization of the 2D viewport to its requirements - * - this function should only be called from region init() callbacks, where it is expected that - * this is called before UI_view2d_size_update(), as this one checks that the rects are properly initialized. +/** + * Initialize all relevant View2D data (including view rects if first time) and/or refresh mask sizes after view resize + * - for some of these presets, it is expected that the region will have defined some + * additional settings necessary for the customization of the 2D viewport to its requirements + * - this function should only be called from region init() callbacks, where it is expected that + * this is called before UI_view2d_size_update(), as this one checks that the rects are properly initialized. */ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) { @@ -1192,20 +1194,23 @@ static void step_to_grid(float *step, int *power, int unit) } } -/* Initialize settings necessary for drawing gridlines in a 2d-view - * - Currently, will return pointer to View2DGrid struct that needs to - * be freed with UI_view2d_grid_free() - * - Is used for scrollbar drawing too (for units drawing) - * - Units + clamping args will be checked, to make sure they are valid values that can be used - * so it is very possible that we won't return grid at all! - * - * - xunits,yunits = V2D_UNIT_* grid steps in seconds or frames - * - xclamp,yclamp = V2D_CLAMP_* only show whole-number intervals - * - winx = width of region we're drawing to, note: not used but keeping for completeness. - * - winy = height of region we're drawing into +/** + * Initialize settings necessary for drawing gridlines in a 2d-view + * + * - Currently, will return pointer to View2DGrid struct that needs to + * be freed with UI_view2d_grid_free() + * - Is used for scrollbar drawing too (for units drawing) + * - Units + clamping args will be checked, to make sure they are valid values that can be used + * so it is very possible that we won't return grid at all! + * + * - xunits,yunits = V2D_UNIT_* grid steps in seconds or frames + * - xclamp,yclamp = V2D_CLAMP_* only show whole-number intervals + * - winx = width of region we're drawing to, note: not used but keeping for completeness. + * - winy = height of region we're drawing into */ -View2DGrid *UI_view2d_grid_calc(Scene *scene, View2D *v2d, - short xunits, short xclamp, short yunits, short yclamp, int UNUSED(winx), int winy) +View2DGrid *UI_view2d_grid_calc( + Scene *scene, View2D *v2d, + short xunits, short xclamp, short yunits, short yclamp, int UNUSED(winx), int winy) { View2DGrid *grid; @@ -1483,9 +1488,11 @@ void UI_view2d_grid_free(View2DGrid *grid) /* *********************************************************************** */ /* Scrollers */ -/* View2DScrollers is typedef'd in UI_view2d.h - * WARNING: the start of this struct must not change, as view2d_ops.c uses this too. - * For now, we don't need to have a separate (internal) header for structs like this... +/** + * View2DScrollers is typedef'd in UI_view2d.h + * + * \warning The start of this struct must not change, as view2d_ops.c uses this too. + * For now, we don't need to have a separate (internal) header for structs like this... */ struct View2DScrollers { /* focus bubbles */ @@ -1502,8 +1509,9 @@ struct View2DScrollers { }; /* Calculate relevant scroller properties */ -View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, - short xunits, short xclamp, short yunits, short yclamp) +View2DScrollers *UI_view2d_scrollers_calc( + const bContext *C, View2D *v2d, + short xunits, short xclamp, short yunits, short yclamp) { View2DScrollers *scrollers; rcti vert, hor; @@ -1885,18 +1893,22 @@ void UI_view2d_scrollers_free(View2DScrollers *scrollers) /* *********************************************************************** */ /* List View Utilities */ -/* Get the view-coordinates of the nominated cell - * - columnwidth, rowheight = size of each 'cell' - * - startx, starty = coordinates (in 'tot' rect space) that the list starts from - * This should be (0,0) for most views. However, for those where the starting row was offsetted - * (like for Animation Editor channel lists, to make the first entry more visible), these will be - * the min-coordinates of the first item. - * - column, row = the 2d-coordinates (in 2D-view / 'tot' rect space) the cell exists at - * - rect = coordinates of the cell (passed as single var instead of 4 separate, as it's more useful this way) +/** Get the view-coordinates of the nominated cell + * + * \param columnwidth, rowheight: size of each 'cell' + * \param startx, starty: coordinates (in 'tot' rect space) that the list starts from. + * This should be (0,0) for most views. However, for those where the starting row was offsetted + * (like for Animation Editor channel lists, to make the first entry more visible), these will be + * the min-coordinates of the first item. + * \param column, row: The 2d-coordinates + * (in 2D-view / 'tot' rect space) the cell exists at + * \param rect: coordinates of the cell + * (passed as single var instead of 4 separate, as it's more useful this way) */ -void UI_view2d_listview_cell_to_view(View2D *v2d, float columnwidth, float rowheight, - float startx, float starty, - int column, int row, rctf *rect) +void UI_view2d_listview_cell_to_view( + View2D *v2d, float columnwidth, float rowheight, + float startx, float starty, + int column, int row, rctf *rect) { /* sanity checks */ if (ELEM(NULL, v2d, rect)) { @@ -1930,17 +1942,20 @@ void UI_view2d_listview_cell_to_view(View2D *v2d, float columnwidth, float rowhe } } -/* Get the 'cell' (row, column) that the given 2D-view coordinates (i.e. in 'tot' rect space) lie in. - * - columnwidth, rowheight = size of each 'cell' - * - startx, starty = coordinates (in 'tot' rect space) that the list starts from - * This should be (0,0) for most views. However, for those where the starting row was offsetted - * (like for Animation Editor channel lists, to make the first entry more visible), these will be - * the min-coordinates of the first item. - * - viewx, viewy = 2D-coordinates (in 2D-view / 'tot' rect space) to get the cell for - * - column, row = the 'coordinates' of the relevant 'cell' +/** + * Get the 'cell' (row, column) that the given 2D-view coordinates (i.e. in 'tot' rect space) lie in. + * + * \param columnwidth, rowheight: size of each 'cell' + * \param startx, starty: coordinates (in 'tot' rect space) that the list starts from. + * This should be (0,0) for most views. However, for those where the starting row was offsetted + * (like for Animation Editor channel lists, to make the first entry more visible), these will be + * the min-coordinates of the first item. + * \param viewx, viewy: 2D-coordinates (in 2D-view / 'tot' rect space) to get the cell for + * \param column, row: the 'coordinates' of the relevant 'cell' */ -void UI_view2d_listview_view_to_cell(View2D *v2d, float columnwidth, float rowheight, float startx, float starty, - float viewx, float viewy, int *column, int *row) +void UI_view2d_listview_view_to_cell( + View2D *v2d, float columnwidth, float rowheight, float startx, float starty, + float viewx, float viewy, int *column, int *row) { /* adjust view coordinates to be all positive ints, corrected for the start offset */ const int x = (int)(floorf(fabsf(viewx) + 0.5f) - startx); @@ -1967,13 +1982,16 @@ void UI_view2d_listview_view_to_cell(View2D *v2d, float columnwidth, float rowhe *row = 0; } -/* Get the 'extreme' (min/max) column and row indices which are visible within the 'cur' rect - * - columnwidth, rowheight = size of each 'cell' - * - startx, starty = coordinates that the list starts from, which should be (0,0) for most views - * - column/row_min/max = the starting and ending column/row indices +/** + * Get the 'extreme' (min/max) column and row indices which are visible within the 'cur' rect + * + * \param columnwidth, rowheight: Size of each 'cell' + * \param startx, starty: Coordinates that the list starts from, which should be (0,0) for most views + * \param column, row_min, max: The starting and ending column/row indices */ -void UI_view2d_listview_visible_cells(View2D *v2d, float columnwidth, float rowheight, float startx, float starty, - int *column_min, int *column_max, int *row_min, int *row_max) +void UI_view2d_listview_visible_cells( + View2D *v2d, float columnwidth, float rowheight, float startx, float starty, + int *column_min, int *column_max, int *row_min, int *row_max) { /* using 'cur' rect coordinates, call the cell-getting function to get the cells for this */ if (v2d) { @@ -1999,10 +2017,11 @@ float UI_view2d_region_to_view_y(struct View2D *v2d, float y) return (v2d->cur.ymin + (BLI_rctf_size_y(&v2d->cur) * (y - v2d->mask.ymin) / BLI_rcti_size_y(&v2d->mask))); } -/* Convert from screen/region space to 2d-View space - * - * - x,y = coordinates to convert - * - viewx,viewy = resultant coordinates +/** + * Convert from screen/region space to 2d-View space + * + * \param x, y: coordinates to convert + * \param viewx, viewy: resultant coordinates */ void UI_view2d_region_to_view(View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) { @@ -2030,11 +2049,12 @@ float UI_view2d_view_to_region_y(View2D *v2d, float y) return (v2d->mask.ymin + (((y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur)) * BLI_rcti_size_y(&v2d->mask))); } -/* Convert from 2d-View space to screen/region space - * - Coordinates are clamped to lie within bounds of region +/** + * Convert from 2d-View space to screen/region space + * \note Coordinates are clamped to lie within bounds of region * - * - x,y = coordinates to convert - * - regionx,regiony = resultant coordinates + * \param x, y: Coordinates to convert. + * \param regionx, regiony: Resultant coordinates. */ bool UI_view2d_view_to_region_clip(View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) { @@ -2057,11 +2077,13 @@ bool UI_view2d_view_to_region_clip(View2D *v2d, float x, float y, int *r_region_ } } -/* Convert from 2d-view space to screen/region space - * - Coordinates are NOT clamped to lie within bounds of region +/** + * Convert from 2d-view space to screen/region space * - * - x,y = coordinates to convert - * - regionx,regiony = resultant coordinates + * \note Coordinates are NOT clamped to lie within bounds of region. + * + * \param x, y: Coordinates to convert. + * \param regionx, regiony: Resultant coordinates. */ void UI_view2d_view_to_region(View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) { @@ -2175,25 +2197,30 @@ View2D *UI_view2d_fromcontext_rwin(const bContext *C) } -/* Calculate the scale per-axis of the drawing-area - * - Is used to inverse correct drawing of icons, etc. that need to follow view - * but not be affected by scale +/** + * Calculate the scale per-axis of the drawing-area + * + * Is used to inverse correct drawing of icons, etc. that need to follow view + * but not be affected by scale * - * - x,y = scale on each axis + * \param x, y: scale on each axis */ void UI_view2d_scale_get(View2D *v2d, float *x, float *y) { if (x) *x = BLI_rcti_size_x(&v2d->mask) / BLI_rctf_size_x(&v2d->cur); if (y) *y = BLI_rcti_size_y(&v2d->mask) / BLI_rctf_size_y(&v2d->cur); } -/* Same as UI_view2d_scale_get() - 1.0f / x, y */ +/** + * Same as ``UI_view2d_scale_get() - 1.0f / x, y`` + */ void UI_view2d_scale_get_inverse(View2D *v2d, float *x, float *y) { if (x) *x = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); if (y) *y = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask); } -/* Simple functions for consistent center offset access. +/** + * Simple functions for consistent center offset access. * Used by node editor to shift view center for each individual node tree. */ void UI_view2d_center_get(struct View2D *v2d, float *x, float *y) @@ -2239,13 +2266,15 @@ void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac) UI_view2d_curRect_validate(v2d); } -/* Check if mouse is within scrollers - * - Returns appropriate code for match - * 'h' = in horizontal scroller - * 'v' = in vertical scroller - * 0 = not in scroller - * - * - x,y = mouse coordinates in screen (not region) space +/** + * Check if mouse is within scrollers + * + * \param x, y: Mouse coordinates in screen (not region) space. + * + * \return appropriate code for match. + * - 'h' = in horizontal scroller. + * - 'v' = in vertical scroller. + * - 0 = not in scroller. */ short UI_view2d_mouse_in_scrollers(const bContext *C, View2D *v2d, int x, int y) { @@ -2288,8 +2317,9 @@ typedef struct View2DString { static MemArena *g_v2d_strings_arena = NULL; static View2DString *g_v2d_strings = NULL; -void UI_view2d_text_cache_add(View2D *v2d, float x, float y, - const char *str, size_t str_len, const char col[4]) +void UI_view2d_text_cache_add( + View2D *v2d, float x, float y, + const char *str, size_t str_len, const char col[4]) { int mval[2]; @@ -2319,8 +2349,9 @@ void UI_view2d_text_cache_add(View2D *v2d, float x, float y, } /* no clip (yet) */ -void UI_view2d_text_cache_add_rectf(View2D *v2d, const rctf *rect_view, - const char *str, size_t str_len, const char col[4]) +void UI_view2d_text_cache_add_rectf( + View2D *v2d, const rctf *rect_view, + const char *str, size_t str_len, const char col[4]) { rcti rect; diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 816c9a93d8c..9fed02ee096 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -620,8 +620,9 @@ static int view_zoom_poll(bContext *C) } /* apply transform to view (i.e. adjust 'cur' rect) */ -static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool use_mousepos, - const float facx, const float facy) +static void view_zoomstep_apply_ex( + bContext *C, v2dViewZoomData *vzd, const bool use_mousepos, + const float facx, const float facy) { ARegion *ar = CTX_wm_region(C); View2D *v2d = &ar->v2d; @@ -1406,8 +1407,9 @@ static float smooth_view_rect_to_fac(const rctf *rect_a, const rctf *rect_b) /* will start timer if appropriate */ /* the arguments are the desired situation */ -void UI_view2d_smooth_view(bContext *C, ARegion *ar, - const rctf *cur, const int smooth_viewtx) +void UI_view2d_smooth_view( + bContext *C, ARegion *ar, + const rctf *cur, const int smooth_viewtx) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); -- cgit v1.2.3 From e59bd19fa75e65b794e4c67bdcfb8d13867900f9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 May 2015 05:17:25 +1000 Subject: Cleanup: style & const's --- intern/cycles/bvh/bvh_node.h | 3 +-- source/blender/bmesh/intern/bmesh_marking.c | 14 +++++++------- source/blender/bmesh/tools/bmesh_triangulate.c | 1 - source/blender/editors/gpencil/gpencil_select.c | 1 - source/blender/editors/object/object_data_transfer.c | 3 --- source/blender/editors/object/object_shapekey.c | 1 - source/blender/editors/screen/area.c | 2 +- source/blender/editors/screen/screen_context.c | 3 +-- source/blender/editors/sculpt_paint/paint_stroke.c | 6 ++---- source/blender/editors/space_sequencer/sequencer_scopes.c | 1 - source/blender/makesdna/DNA_packedFile_types.h | 3 +-- 11 files changed, 13 insertions(+), 25 deletions(-) diff --git a/intern/cycles/bvh/bvh_node.h b/intern/cycles/bvh/bvh_node.h index 1656bb367a4..44f5518229b 100644 --- a/intern/cycles/bvh/bvh_node.h +++ b/intern/cycles/bvh/bvh_node.h @@ -24,8 +24,7 @@ CCL_NAMESPACE_BEGIN -enum BVH_STAT -{ +enum BVH_STAT { BVH_STAT_NODE_COUNT, BVH_STAT_INNER_COUNT, BVH_STAT_LEAF_COUNT, diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index a735f3955fc..93be42ae566 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -73,9 +73,9 @@ static void recount_totsels(BMesh *bm) /** \name BMesh helper functions for selection flushing. * \{ */ -static bool bm_vert_is_edge_select_any_other(BMVert *v, BMEdge *e_first) +static bool bm_vert_is_edge_select_any_other(const BMVert *v, const BMEdge *e_first) { - BMEdge *e_iter = e_first; + const BMEdge *e_iter = e_first; /* start by stepping over the current edge */ while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first) { @@ -87,10 +87,10 @@ static bool bm_vert_is_edge_select_any_other(BMVert *v, BMEdge *e_first) } #if 0 -static bool bm_vert_is_edge_select_any(BMVert *v) +static bool bm_vert_is_edge_select_any(const BMVert *v) { if (v->e) { - BMEdge *e_iter, *e_first; + const BMEdge *e_iter, *e_first; e_iter = e_first = v->e; do { if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) { @@ -104,7 +104,7 @@ static bool bm_vert_is_edge_select_any(BMVert *v) static bool bm_edge_is_face_select_any_other(BMLoop *l_first) { - BMLoop *l_iter = l_first; + const BMLoop *l_iter = l_first; /* start by stepping over the current face */ while ((l_iter = l_iter->radial_next) != l_first) { @@ -116,10 +116,10 @@ static bool bm_edge_is_face_select_any_other(BMLoop *l_first) } #if 0 -static bool bm_edge_is_face_select_any(BMEdge *e) +static bool bm_edge_is_face_select_any(const BMEdge *e) { if (e->l) { - BMLoop *l_iter, *l_first; + const BMLoop *l_iter, *l_first; l_iter = l_first = e->l; do { if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) { diff --git a/source/blender/bmesh/tools/bmesh_triangulate.c b/source/blender/bmesh/tools/bmesh_triangulate.c index 404776a0769..6f2aaf28179 100644 --- a/source/blender/bmesh/tools/bmesh_triangulate.c +++ b/source/blender/bmesh/tools/bmesh_triangulate.c @@ -34,7 +34,6 @@ #include "BLI_utildefines.h" #include "BLI_alloca.h" #include "BLI_memarena.h" -#include "BLI_listbase.h" #include "BLI_heap.h" #include "BLI_edgehash.h" diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 98bce3030a5..9d0cb6d711a 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -40,7 +40,6 @@ #include "BLI_utildefines.h" #include "DNA_gpencil_types.h" -#include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "BKE_context.h" diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index a7802b6a411..b3b2299f77f 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -29,8 +29,6 @@ * \ingroup edobj */ -#include "MEM_guardedalloc.h" - #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" @@ -59,7 +57,6 @@ #include "ED_object.h" #include "UI_interface.h" -#include "UI_resources.h" #include "object_intern.h" diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 674eb25942f..8f8bfc47b10 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -48,7 +48,6 @@ #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" -#include "DNA_scene_types.h" #include "DNA_object_types.h" #include "BKE_context.h" diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index a0ab8de0101..3a4034d9074 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2069,7 +2069,7 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float fill_co #define MAX_METADATA_STR 1024 -const char *meta_data_list[] = +static const char *meta_data_list[] = { "File", "Strip", diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 3431ce9f50a..fc4ee47b568 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -81,7 +81,6 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult ScrArea *sa = CTX_wm_area(C); Scene *scene = sc->scene; Base *base; - unsigned int lay = scene->lay; #if 0 /* Using the context breaks adding objects in the UI. Need to find out why - campbell */ Object *obact = CTX_data_active_object(C); @@ -119,7 +118,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult int selectable_objects = CTX_data_equals(member, "selectable_objects"); for (base = scene->base.first; base; base = base->next) { - if (base->lay & lay) { + if (base->lay & scene->lay) { if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) { if (selectable_objects) CTX_data_id_list_add(result, &base->object->id); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index f0963cae1ce..2ae544706df 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -671,8 +671,7 @@ PaintStroke *paint_stroke_new(bContext *C, get_imapaint_zoom(C, &zoomx, &zoomy); stroke->zoom_2d = max_ff(zoomx, zoomy); - if (stroke->stroke_mode == BRUSH_STROKE_INVERT) - { + if (stroke->stroke_mode == BRUSH_STROKE_INVERT) { if (br->flag & (BRUSH_CURVE)) { RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL); } @@ -1137,8 +1136,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) copy_v2_fl2(mouse, event->mval[0], event->mval[1]); paint_stroke_line_constrain(stroke, mouse); - if (stroke->stroke_started && (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)))) - { + if (stroke->stroke_started && (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)))) { if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) || (br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) { copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position); } diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index 404671cac84..c197aabedfd 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -29,7 +29,6 @@ #include #include -#include "BLI_math_color.h" #include "BLI_utildefines.h" #include "IMB_colormanagement.h" diff --git a/source/blender/makesdna/DNA_packedFile_types.h b/source/blender/makesdna/DNA_packedFile_types.h index ef0a0f642d6..56140c84cb1 100644 --- a/source/blender/makesdna/DNA_packedFile_types.h +++ b/source/blender/makesdna/DNA_packedFile_types.h @@ -40,8 +40,7 @@ typedef struct PackedFile { void *data; } PackedFile; -enum PF_FileStatus -{ +enum PF_FileStatus { PF_EQUAL = 0, PF_DIFFERS = 1, PF_NOFILE = 2, -- cgit v1.2.3 From 22bbd1c51219aafb40adb3e9a206f660a621fd70 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 May 2015 07:11:31 +1000 Subject: BMesh: improve rip tool /w mon-manifold verts Can now rip from multiple fans (mixed single faces or larger regions) Also add BM_vert_is_manifold_region which only checks if a vert has disconnected fans. --- source/blender/bmesh/intern/bmesh_queries.c | 99 ++++++++++++++++++++++++++ source/blender/bmesh/intern/bmesh_queries.h | 3 + source/blender/editors/mesh/editmesh_rip.c | 106 +++++++++++++--------------- 3 files changed, 153 insertions(+), 55 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 031fc68e66f..63e36178e0f 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -917,6 +917,105 @@ bool BM_vert_is_manifold(const BMVert *v) return (loop_num == loop_num_region); } +#define LOOP_VISIT _FLAG_WALK +#define EDGE_VISIT _FLAG_WALK + +static int bm_loop_region_count__recursive(BMEdge *e, BMVert *v) +{ + BMLoop *l_iter, *l_first; + int count = 0; + + BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)); + BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT); + + l_iter = l_first = e->l; + do { + if (l_iter->v == v) { + BMEdge *e_other = l_iter->prev->e; + if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) { + BM_ELEM_API_FLAG_ENABLE(l_iter, LOOP_VISIT); + count += 1; + } + if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) { + count += bm_loop_region_count__recursive(e_other, v); + } + } + else if (l_iter->next->v == v) { + BMEdge *e_other = l_iter->next->e; + if (!BM_ELEM_API_FLAG_TEST(l_iter->next, LOOP_VISIT)) { + BM_ELEM_API_FLAG_ENABLE(l_iter->next, LOOP_VISIT); + count += 1; + } + if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) { + count += bm_loop_region_count__recursive(e_other, v); + } + } + else { + BLI_assert(0); + } + } while ((l_iter = l_iter->radial_next) != l_first); + + return count; +} + +static int bm_loop_region_count__clear(BMLoop *l) +{ + int count = 0; + BMEdge *e_iter, *e_first; + + /* clear flags */ + e_iter = e_first = l->e; + do { + BM_ELEM_API_FLAG_DISABLE(e_iter, EDGE_VISIT); + if (e_iter->l) { + BMLoop *l_iter, *l_first; + l_iter = l_first = e_iter->l; + do { + if (l_iter->v == l->v) { + BM_ELEM_API_FLAG_DISABLE(l_iter, LOOP_VISIT); + count += 1; + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, l->v)) != e_first); + + return count; +} + +/** + * The number of loops connected to this loop (not including disconnected regions). + */ +int BM_loop_region_loops_count_ex(BMLoop *l, int *r_loop_total) +{ + const int count = bm_loop_region_count__recursive(l->e, l->v); + const int count_total = bm_loop_region_count__clear(l); + if (r_loop_total) { + *r_loop_total = count_total; + } + return count; +} + +#undef LOOP_VISIT +#undef EDGE_VISIT + +int BM_loop_region_loops_count(BMLoop *l) +{ + return BM_loop_region_loops_count_ex(l, NULL); +} + +/** + * A version of #BM_vert_is_manifold + * which only checks if we're connected to multiple isolated regions. + */ +bool BM_vert_is_manifold_region(const BMVert *v) +{ + BMLoop *l_first = BM_vert_find_first_loop((BMVert *)v); + int count, count_total; + + count = BM_loop_region_loops_count_ex(l_first, &count_total); + return (count == count_total); +} + /** * Check if the edge is convex or concave * (depends on face winding) diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index e4f7c78bdc1..f0a348db16a 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -85,12 +85,15 @@ bool BM_vert_is_wire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool BM_vert_is_manifold(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_vert_is_manifold_region(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool BM_vert_is_boundary(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool BM_edge_is_convex(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int BM_loop_region_loops_count_ex(BMLoop *l, int *r_loop_total) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); +int BM_loop_region_loops_count(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); bool BM_loop_is_convex(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index abd88ae65aa..1e207a8edf8 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -532,14 +532,14 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve BMesh *bm = em->bm; BMIter iter, liter; BMLoop *l; - BMEdge *e, *e2; + BMEdge *e2; BMVert *v; const int totvert_orig = bm->totvert; int i; float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]}; float dist_sq = FLT_MAX; float d; - bool is_wire; + bool is_wire, is_manifold_region; BMEditSelection ese; int totboundary_edge = 0; @@ -565,17 +565,19 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve } is_wire = BM_vert_is_wire(v); + is_manifold_region = BM_vert_is_manifold_region(v); e2 = NULL; - if (v->e) { + { + BMEdge *e; /* find closest edge to mouse cursor */ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { /* consider wire as boundary for this purpose, * otherwise we can't a face away from a wire edge */ totboundary_edge += (BM_edge_is_boundary(e) || BM_edge_is_wire(e)); if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - if (BM_edge_is_manifold(e)) { + if ((is_manifold_region == false) || BM_edge_is_manifold(e)) { d = edbm_rip_edgedist_squared(ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT); if ((e2 == NULL) || (d < dist_sq)) { dist_sq = d; @@ -584,67 +586,60 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve } } } - - /* if we are ripping a single vertex from 3 faces, - * then measure the distance to the face corner as well as the edge */ - if (BM_vert_face_count_is_equal(v, 3) && - BM_vert_edge_count_is_equal(v, 3)) - { - BMEdge *e_all[3]; - BMLoop *l_all[3]; - int i1, i2; - - BM_iter_as_array(bm, BM_EDGES_OF_VERT, v, (void **)e_all, 3); - BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)l_all, 3); - - /* not do a loop similar to the one above, but test against loops */ - for (i1 = 0; i1 < 3; i1++) { - /* consider wire as boundary for this purpose, - * otherwise we can't a face away from a wire edge */ - float l_mid_co[3]; - l = l_all[i1]; - edbm_calc_loop_co(l, l_mid_co); - d = edbm_rip_edgedist_squared(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT); - if ((e2 == NULL) || (d < dist_sq)) { - dist_sq = d; - - /* find the edge that is not in this loop */ - e2 = NULL; - for (i2 = 0; i2 < 3; i2++) { - if (!BM_edge_in_loop(e_all[i2], l)) { - e2 = e_all[i2]; - break; - } - } - BLI_assert(e2 != NULL); - } - } - } } - if (e2) { + if (e2 && (is_manifold_region == false)) { /* Try to split off a non-manifold fan (when we have multiple disconnected fans) */ - - /* note: we're lazy here and first split then check there are any faces remaining, - * this isn't good practice, however its less hassle then checking for multiple-disconnected regions */ BMLoop *l_sep = e2->l->v == v ? e2->l : e2->l->next; BMVert *v_new; + BLI_assert(l_sep->v == v); v_new = bmesh_urmv_loop_region(bm, l_sep); - if (BM_vert_find_first_loop(v)) { - BM_vert_select_set(bm, v, false); - BM_select_history_remove(bm, v); + BLI_assert(BM_vert_find_first_loop(v)); - BM_vert_select_set(bm, v_new, true); - if (ese.ele) { - BM_select_history_store(bm, v_new); - } + BM_vert_select_set(bm, v, false); + BM_select_history_remove(bm, v); - return OPERATOR_FINISHED; + BM_vert_select_set(bm, v_new, true); + if (ese.ele) { + BM_select_history_store(bm, v_new); } - else { - /* rewind */ - BM_vert_splice(bm, v, v_new); + return OPERATOR_FINISHED; + } + + /* if we are ripping a single vertex from 3 faces, + * then measure the distance to the face corner as well as the edge */ + if (BM_vert_face_count_is_equal(v, 3) && + BM_vert_edge_count_is_equal(v, 3)) + { + BMEdge *e_all[3]; + BMLoop *l_all[3]; + int i1, i2; + + BM_iter_as_array(bm, BM_EDGES_OF_VERT, v, (void **)e_all, 3); + BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)l_all, 3); + + /* not do a loop similar to the one above, but test against loops */ + for (i1 = 0; i1 < 3; i1++) { + /* consider wire as boundary for this purpose, + * otherwise we can't a face away from a wire edge */ + float l_mid_co[3]; + l = l_all[i1]; + edbm_calc_loop_co(l, l_mid_co); + d = edbm_rip_edgedist_squared(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT); + if ((e2 == NULL) || (d < dist_sq)) { + dist_sq = d; + + /* find the edge that is not in this loop */ + e2 = NULL; + for (i2 = 0; i2 < 3; i2++) { + if (!BM_edge_in_loop(e_all[i2], l)) { + e2 = e_all[i2]; + break; + } + } + BLI_assert(e2 != NULL); + } } } @@ -703,6 +698,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve } } else { + BMEdge *e; /* a wire vert, find the best edge */ BM_ITER_ELEM (e, &iter, vout[i], BM_EDGES_OF_VERT) { if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { -- cgit v1.2.3 From 7201f6d14c0161ad9a0d4143d1c5caf872e0d93e Mon Sep 17 00:00:00 2001 From: "Sv. Lockal" Date: Tue, 5 May 2015 06:11:54 +0000 Subject: Cycles: Use curve approximation for blackbody instead of lookup table Now we calculate color in range 800..12000 using an approximation a/x+bx+c for R and G and ((at + b)t + c)t + d) for B. Max absolute error for RGB for non-lut function is less than 0.0001, which is enough to get the same 8 bit/channel color as for OSL with a noticeable performance difference. However there is a slight visible difference between previous non-OSL implementation because of lookup table interpolation and offset-by-one mistake. The previous implementation gave black color outside of soft range (t > 12000), now it gives the same color as for 12000. Also blackbody node without input connected is being converted to value input at shader compile time. Reviewers: dingto, sergey Reviewed By: dingto Subscribers: nutel, brecht, juicyfruit Differential Revision: https://developer.blender.org/D1280 --- intern/cycles/kernel/kernel_types.h | 9 +- intern/cycles/kernel/svm/svm.h | 3 +- intern/cycles/kernel/svm/svm_blackbody.h | 38 +-------- intern/cycles/kernel/svm/svm_math_util.h | 62 ++++++++++++++ intern/cycles/render/CMakeLists.txt | 2 - intern/cycles/render/blackbody.cpp | 140 ------------------------------- intern/cycles/render/blackbody.h | 28 ------- intern/cycles/render/graph.h | 1 - intern/cycles/render/nodes.cpp | 12 ++- intern/cycles/render/nodes.h | 2 - intern/cycles/render/shader.cpp | 29 ------- intern/cycles/render/shader.h | 3 - intern/cycles/render/svm.cpp | 5 -- 13 files changed, 76 insertions(+), 258 deletions(-) delete mode 100644 intern/cycles/render/blackbody.cpp delete mode 100644 intern/cycles/render/blackbody.h diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index b948f7de2f4..0491b8ddec7 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -38,12 +38,6 @@ CCL_NAMESPACE_BEGIN #define BSSRDF_MIN_RADIUS 1e-8f #define BSSRDF_MAX_HITS 4 -#define BB_DRAPER 800.0f -#define BB_MAX_TABLE_RANGE 12000.0f -#define BB_TABLE_XPOWER 1.5f -#define BB_TABLE_YPOWER 5.0f -#define BB_TABLE_SPACING 2.0f - #define BECKMANN_TABLE_SIZE 256 #define TEX_NUM_FLOAT_IMAGES 5 @@ -989,9 +983,8 @@ typedef struct KernelCurves { } KernelCurves; typedef struct KernelTables { - int blackbody_offset; int beckmann_offset; - int pad1, pad2; + int pad1, pad2, pad3; } KernelTables; typedef struct KernelData { diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index dd9173d92b3..1598019856a 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -142,6 +142,8 @@ CCL_NAMESPACE_END #include "svm_noise.h" #include "svm_texture.h" +#include "svm_math_util.h" + #include "svm_attribute.h" #include "svm_gradient.h" #include "svm_blackbody.h" @@ -164,7 +166,6 @@ CCL_NAMESPACE_END #include "svm_mapping.h" #include "svm_normal.h" #include "svm_wave.h" -#include "svm_math_util.h" #include "svm_math.h" #include "svm_mix.h" #include "svm_ramp.h" diff --git a/intern/cycles/kernel/svm/svm_blackbody.h b/intern/cycles/kernel/svm/svm_blackbody.h index b2ff97d71e6..b750ad87b7f 100644 --- a/intern/cycles/kernel/svm/svm_blackbody.h +++ b/intern/cycles/kernel/svm/svm_blackbody.h @@ -36,46 +36,10 @@ CCL_NAMESPACE_BEGIN ccl_device void svm_node_blackbody(KernelGlobals *kg, ShaderData *sd, float *stack, uint temperature_offset, uint col_offset) { - /* Output */ - float3 color_rgb = make_float3(0.0f, 0.0f, 0.0f); - /* Input */ float temperature = stack_load_float(stack, temperature_offset); - if(temperature < BB_DRAPER) { - /* just return very very dim red */ - color_rgb = make_float3(1.0e-6f,0.0f,0.0f); - } - else if(temperature <= BB_MAX_TABLE_RANGE) { - /* This is the overall size of the table */ - const int lookuptablesize = 956; - const float lookuptablenormalize = 1.0f/956.0f; - - /* reconstruct a proper index for the table lookup, compared to OSL we don't look up two colors - just one (the OSL-lerp is also automatically done for us by "lookup_table_read") */ - float t = powf((temperature - BB_DRAPER) * (1.0f / BB_TABLE_SPACING), (1.0f / BB_TABLE_XPOWER)); - - int blackbody_table_offset = kernel_data.tables.blackbody_offset; - - /* Retrieve colors from the lookup table */ - float lutval = t*lookuptablenormalize; - float R = lookup_table_read(kg, lutval, blackbody_table_offset, lookuptablesize); - lutval = (t + 319.0f*1.0f)*lookuptablenormalize; - float G = lookup_table_read(kg, lutval, blackbody_table_offset, lookuptablesize); - lutval = (t + 319.0f*2.0f)*lookuptablenormalize; - float B = lookup_table_read(kg, lutval, blackbody_table_offset, lookuptablesize); - - R = powf(R, BB_TABLE_YPOWER); - G = powf(G, BB_TABLE_YPOWER); - B = powf(B, BB_TABLE_YPOWER); - - color_rgb = make_float3(R, G, B); - } - - /* Luminance */ - float l = linear_rgb_to_gray(color_rgb); - if(l != 0.0f) - color_rgb /= l; + float3 color_rgb = svm_math_blackbody_color(temperature); if(stack_valid(col_offset)) stack_store_float3(stack, col_offset, color_rgb); diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h index ff9e662e931..645cbd3fc73 100644 --- a/intern/cycles/kernel/svm/svm_math_util.h +++ b/intern/cycles/kernel/svm/svm_math_util.h @@ -104,5 +104,67 @@ ccl_device float svm_math(NodeMath type, float Fac1, float Fac2) return Fac; } +ccl_device float3 svm_math_blackbody_color(float t) { + /* Calculate color in range 800..12000 using an approximation + * a/x+bx+c for R and G and ((at + b)t + c)t + d) for B + * Max absolute error for RGB is (0.00095, 0.00077, 0.00057), + * which is enough to get the same 8 bit/channel color. + */ + + const float rc[6][3] = { + { 2.52432244e+03f, -1.06185848e-03f, 3.11067539e+00f }, + { 3.37763626e+03f, -4.34581697e-04f, 1.64843306e+00f }, + { 4.10671449e+03f, -8.61949938e-05f, 6.41423749e-01f }, + { 4.66849800e+03f, 2.85655028e-05f, 1.29075375e-01f }, + { 4.60124770e+03f, 2.89727618e-05f, 1.48001316e-01f }, + { 3.78765709e+03f, 9.36026367e-06f, 3.98995841e-01f }, + }; + + const float gc[6][3] = { + { -7.50343014e+02f, 3.15679613e-04f, 4.73464526e-01f }, + { -1.00402363e+03f, 1.29189794e-04f, 9.08181524e-01f }, + { -1.22075471e+03f, 2.56245413e-05f, 1.20753416e+00f }, + { -1.42546105e+03f, -4.01730887e-05f, 1.44002695e+00f }, + { -1.18134453e+03f, -2.18913373e-05f, 1.30656109e+00f }, + { -5.00279505e+02f, -4.59745390e-06f, 1.09090465e+00f }, + }; + + const float bc[6][4] = { + { 0.0f, 0.0f, 0.0f, 0.0f }, /* zeros should be optimized by compiler */ + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { -2.02524603e-11f, 1.79435860e-07f, -2.60561875e-04f, -1.41761141e-02f }, + { -2.22463426e-13f, -1.55078698e-08f, 3.81675160e-04f, -7.30646033e-01f }, + { 6.72595954e-13f, -2.73059993e-08f, 4.24068546e-04f, -7.52204323e-01f }, + }; + + if(t >= 12000.0f) + return make_float3(0.826270103f, 0.994478524f, 1.56626022f); + + /* Define a macro to reduce stack usage for nvcc */ +#define MAKE_BB_RGB(i) make_float3(\ + rc[i][0] / t + rc[i][1] * t + rc[i][2],\ + gc[i][0] / t + gc[i][1] * t + gc[i][2],\ + ((bc[i][0] * t + bc[i][1]) * t + bc[i][2]) * t + bc[i][3]) + + if(t >= 6365.0f) + return MAKE_BB_RGB(5); + if(t >= 3315.0f) + return MAKE_BB_RGB(4); + if(t >= 1902.0f) + return MAKE_BB_RGB(3); + if(t >= 1449.0f) + return MAKE_BB_RGB(2); + if(t >= 1167.0f) + return MAKE_BB_RGB(1); + if(t >= 965.0f) + return MAKE_BB_RGB(0); + +#undef MAKE_BB_RGB + + /* For 800 <= t < 965 color does not change in OSL implementation, so keep color the same */ + return make_float3(4.70366907f, 0.0f, 0.0f); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index 2dc6962633d..4e8a1794813 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -18,7 +18,6 @@ set(SRC attribute.cpp background.cpp bake.cpp - blackbody.cpp buffers.cpp camera.cpp film.cpp @@ -47,7 +46,6 @@ set(SRC_HEADERS attribute.h bake.h background.h - blackbody.h buffers.h camera.h film.h diff --git a/intern/cycles/render/blackbody.cpp b/intern/cycles/render/blackbody.cpp deleted file mode 100644 index 9f77f69a964..00000000000 --- a/intern/cycles/render/blackbody.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2013, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "blackbody.h" -#include "util_color.h" -#include "util_math.h" - -#include "kernel_types.h" - -CCL_NAMESPACE_BEGIN - -vector blackbody_table_build() -{ - /* quoted from OSLs opcolor.cpp - In order to speed up the blackbody computation, we have a table - storing the precomputed BB values for a range of temperatures. Less - than BB_DRAPER always returns 0. Greater than BB_MAX_TABLE_RANGE - does the full computation, we think it'll be rare to inquire higher - temperatures. - - Since the bb function is so nonlinear, we actually space the table - entries nonlinearly, with the relationship between the table index i - and the temperature T as follows: - i = ((T-Draper)/spacing)^(1/xpower) - T = pow(i, xpower) * spacing + Draper - And furthermore, we store in the table the true value raised ^(1/5). - I tuned this a bit, and with the current values we can have all - blackbody results accurate to within 0.1% with a table size of 317 - (about 5 KB of data). - */ - - const float cie_colour_match[81][3] = { - {0.0014f,0.0000f,0.0065f}, {0.0022f,0.0001f,0.0105f}, {0.0042f,0.0001f,0.0201f}, - {0.0076f,0.0002f,0.0362f}, {0.0143f,0.0004f,0.0679f}, {0.0232f,0.0006f,0.1102f}, - {0.0435f,0.0012f,0.2074f}, {0.0776f,0.0022f,0.3713f}, {0.1344f,0.0040f,0.6456f}, - {0.2148f,0.0073f,1.0391f}, {0.2839f,0.0116f,1.3856f}, {0.3285f,0.0168f,1.6230f}, - {0.3483f,0.0230f,1.7471f}, {0.3481f,0.0298f,1.7826f}, {0.3362f,0.0380f,1.7721f}, - {0.3187f,0.0480f,1.7441f}, {0.2908f,0.0600f,1.6692f}, {0.2511f,0.0739f,1.5281f}, - {0.1954f,0.0910f,1.2876f}, {0.1421f,0.1126f,1.0419f}, {0.0956f,0.1390f,0.8130f}, - {0.0580f,0.1693f,0.6162f}, {0.0320f,0.2080f,0.4652f}, {0.0147f,0.2586f,0.3533f}, - {0.0049f,0.3230f,0.2720f}, {0.0024f,0.4073f,0.2123f}, {0.0093f,0.5030f,0.1582f}, - {0.0291f,0.6082f,0.1117f}, {0.0633f,0.7100f,0.0782f}, {0.1096f,0.7932f,0.0573f}, - {0.1655f,0.8620f,0.0422f}, {0.2257f,0.9149f,0.0298f}, {0.2904f,0.9540f,0.0203f}, - {0.3597f,0.9803f,0.0134f}, {0.4334f,0.9950f,0.0087f}, {0.5121f,1.0000f,0.0057f}, - {0.5945f,0.9950f,0.0039f}, {0.6784f,0.9786f,0.0027f}, {0.7621f,0.9520f,0.0021f}, - {0.8425f,0.9154f,0.0018f}, {0.9163f,0.8700f,0.0017f}, {0.9786f,0.8163f,0.0014f}, - {1.0263f,0.7570f,0.0011f}, {1.0567f,0.6949f,0.0010f}, {1.0622f,0.6310f,0.0008f}, - {1.0456f,0.5668f,0.0006f}, {1.0026f,0.5030f,0.0003f}, {0.9384f,0.4412f,0.0002f}, - {0.8544f,0.3810f,0.0002f}, {0.7514f,0.3210f,0.0001f}, {0.6424f,0.2650f,0.0000f}, - {0.5419f,0.2170f,0.0000f}, {0.4479f,0.1750f,0.0000f}, {0.3608f,0.1382f,0.0000f}, - {0.2835f,0.1070f,0.0000f}, {0.2187f,0.0816f,0.0000f}, {0.1649f,0.0610f,0.0000f}, - {0.1212f,0.0446f,0.0000f}, {0.0874f,0.0320f,0.0000f}, {0.0636f,0.0232f,0.0000f}, - {0.0468f,0.0170f,0.0000f}, {0.0329f,0.0119f,0.0000f}, {0.0227f,0.0082f,0.0000f}, - {0.0158f,0.0057f,0.0000f}, {0.0114f,0.0041f,0.0000f}, {0.0081f,0.0029f,0.0000f}, - {0.0058f,0.0021f,0.0000f}, {0.0041f,0.0015f,0.0000f}, {0.0029f,0.0010f,0.0000f}, - {0.0020f,0.0007f,0.0000f}, {0.0014f,0.0005f,0.0000f}, {0.0010f,0.0004f,0.0000f}, - {0.0007f,0.0002f,0.0000f}, {0.0005f,0.0002f,0.0000f}, {0.0003f,0.0001f,0.0000f}, - {0.0002f,0.0001f,0.0000f}, {0.0002f,0.0001f,0.0000f}, {0.0001f,0.0000f,0.0000f}, - {0.0001f,0.0000f,0.0000f}, {0.0001f,0.0000f,0.0000f}, {0.0000f,0.0000f,0.0000f} - }; - - const double c1 = 3.74183e-16; // 2*pi*h*c^2, W*m^2 - const double c2 = 1.4388e-2; // h*c/k, m*K - // h is Planck's const, k is Boltzmann's - const float dlambda = 5.0f * 1e-9f; // in meters - - /* Blackbody table from 800 to 12k Kelvin (319 entries (317+2 offset) * 3) */ - vector blackbody_table(956); - - float X, Y, Z; - - /* ToDo: bring this back to what OSL does with the lastTemperature limit ? */ - for(int i = 0; i <= 317; ++i) { - double Temperature = pow((double)i, (double)BB_TABLE_XPOWER) * (double)BB_TABLE_SPACING + (double)BB_DRAPER; - X = 0; - Y = 0; - Z = 0; - - /* from OSL "spectrum_to_XYZ" */ - for(int n = 0; n < 81; ++n) { - float lambda = 380.0f + 5.0f * n; - double wlm = lambda * 1e-9f; // Wavelength in meters - // N.B. spec_intens returns result in W/m^2 but it's a differential, - // needs to be scaled by dlambda! - float spec_intens = float((c1 * pow(wlm, -5.0)) / (exp(c2 / (wlm * Temperature)) -1.0)); - float Me = spec_intens * dlambda; - - X += Me * cie_colour_match[n][0]; - Y += Me * cie_colour_match[n][1]; - Z += Me * cie_colour_match[n][2]; - } - - /* Convert from xyz color space */ - float3 col = xyz_to_rgb(X, Y, Z); - - /* Clamp to zero if values are smaller */ - col = max(col, make_float3(0.0f, 0.0f, 0.0f)); - - col.x = powf(col.x, 1.0f / BB_TABLE_YPOWER); - col.y = powf(col.y, 1.0f / BB_TABLE_YPOWER); - col.z = powf(col.z, 1.0f / BB_TABLE_YPOWER); - - /* Store in table in RRRGGGBBB format */ - blackbody_table[i] = col.x; - blackbody_table[i+319*1] = col.y; - blackbody_table[i+319*2] = col.z; - } - - return blackbody_table; -} -CCL_NAMESPACE_END diff --git a/intern/cycles/render/blackbody.h b/intern/cycles/render/blackbody.h deleted file mode 100644 index 6b752a227fa..00000000000 --- a/intern/cycles/render/blackbody.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011-2013 Blender Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __BLACKBODY_H__ -#define __BLACKBODY_H__ - -#include "util_vector.h" - -CCL_NAMESPACE_BEGIN - -vector blackbody_table_build(); - -CCL_NAMESPACE_END - -#endif /* __BLACKBODY_H__ */ diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index 301938aa158..7817a4cdc6d 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -194,7 +194,6 @@ public: virtual bool has_surface_emission() { return false; } virtual bool has_surface_transparent() { return false; } virtual bool has_surface_bssrdf() { return false; } - virtual bool has_converter_blackbody() { return false; } virtual bool has_bssrdf_bump() { return false; } virtual bool has_spatial_varying() { return false; } virtual bool has_object_dependency() { return false; } diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 8529855ff2e..d17d531aa77 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -3652,9 +3652,17 @@ void BlackbodyNode::compile(SVMCompiler& compiler) ShaderInput *temperature_in = input("Temperature"); ShaderOutput *color_out = output("Color"); - compiler.stack_assign(temperature_in); compiler.stack_assign(color_out); - compiler.add_node(NODE_BLACKBODY, temperature_in->stack_offset, color_out->stack_offset); + + if(temperature_in->link == NULL) { + float3 color = svm_math_blackbody_color(temperature_in->value.x); + compiler.add_node(NODE_VALUE_V, color_out->stack_offset); + compiler.add_node(NODE_VALUE_V, color); + } + else { + compiler.stack_assign(temperature_in); + compiler.add_node(NODE_BLACKBODY, temperature_in->stack_offset, color_out->stack_offset); + } } void BlackbodyNode::compile(OSLCompiler& compiler) diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index ee984773dcf..686fb5e2fd7 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -549,8 +549,6 @@ public: class BlackbodyNode : public ShaderNode { public: SHADER_NODE_CLASS(BlackbodyNode) - - bool has_converter_blackbody() { return true; } }; class MathNode : public ShaderNode { diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 496fd0f0cb9..971cd5097de 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -15,7 +15,6 @@ */ #include "background.h" -#include "blackbody.h" #include "device.h" #include "graph.h" #include "light.h" @@ -32,7 +31,6 @@ CCL_NAMESPACE_BEGIN -vector ShaderManager::blackbody_table; vector ShaderManager::beckmann_table; /* Beckmann sampling precomputed table, see bsdf_microfacet.h */ @@ -149,7 +147,6 @@ Shader::Shader() has_surface_transparent = false; has_surface_emission = false; has_surface_bssrdf = false; - has_converter_blackbody = false; has_volume = false; has_displacement = false; has_bssrdf_bump = false; @@ -243,7 +240,6 @@ void Shader::tag_used(Scene *scene) ShaderManager::ShaderManager() { need_update = true; - blackbody_table_offset = TABLE_OFFSET_INVALID; beckmann_table_offset = TABLE_OFFSET_INVALID; } @@ -340,7 +336,6 @@ void ShaderManager::device_update_common(Device *device, uint shader_flag_size = scene->shaders.size()*4; uint *shader_flag = dscene->shader_flag.resize(shader_flag_size); uint i = 0; - bool has_converter_blackbody = false; bool has_volumes = false; foreach(Shader *shader, scene->shaders) { @@ -367,8 +362,6 @@ void ShaderManager::device_update_common(Device *device, flag |= SD_HETEROGENEOUS_VOLUME; if(shader->has_bssrdf_bump) flag |= SD_HAS_BSSRDF_BUMP; - if(shader->has_converter_blackbody) - has_converter_blackbody = true; if(shader->volume_sampling_method == VOLUME_SAMPLING_EQUIANGULAR) flag |= SD_VOLUME_EQUIANGULAR; if(shader->volume_sampling_method == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE) @@ -394,23 +387,6 @@ void ShaderManager::device_update_common(Device *device, /* lookup tables */ KernelTables *ktables = &dscene->data.tables; - - /* blackbody lookup table */ - if(has_converter_blackbody && blackbody_table_offset == TABLE_OFFSET_INVALID) { - if(blackbody_table.size() == 0) { - thread_scoped_lock lock(lookup_table_mutex); - if(blackbody_table.size() == 0) { - blackbody_table = blackbody_table_build(); - } - } - blackbody_table_offset = scene->lookup_tables->add_table(dscene, blackbody_table); - - ktables->blackbody_offset = (int)blackbody_table_offset; - } - else if(!has_converter_blackbody && blackbody_table_offset != TABLE_OFFSET_INVALID) { - scene->lookup_tables->remove_table(blackbody_table_offset); - blackbody_table_offset = TABLE_OFFSET_INVALID; - } /* beckmann lookup table */ if(beckmann_table_offset == TABLE_OFFSET_INVALID) { @@ -431,11 +407,6 @@ void ShaderManager::device_update_common(Device *device, void ShaderManager::device_free_common(Device *device, DeviceScene *dscene, Scene *scene) { - if(blackbody_table_offset != TABLE_OFFSET_INVALID) { - scene->lookup_tables->remove_table(blackbody_table_offset); - blackbody_table_offset = TABLE_OFFSET_INVALID; - } - if(beckmann_table_offset != TABLE_OFFSET_INVALID) { scene->lookup_tables->remove_table(beckmann_table_offset); beckmann_table_offset = TABLE_OFFSET_INVALID; diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index a1d697a7b7b..5bcb2c4e344 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -104,7 +104,6 @@ public: bool has_volume; bool has_displacement; bool has_surface_bssrdf; - bool has_converter_blackbody; bool has_bssrdf_bump; bool has_heterogeneous_volume; bool has_object_dependency; @@ -173,10 +172,8 @@ protected: AttributeIDMap unique_attribute_id; thread_mutex lookup_table_mutex; - static vector blackbody_table; static vector beckmann_table; - size_t blackbody_table_offset; size_t beckmann_table_offset; }; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 6f7cffa320f..d0bd34915df 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -393,10 +393,6 @@ void SVMCompiler::generate_node(ShaderNode *node, set& done) current_shader->has_heterogeneous_volume = true; } - /* detect if we have a blackbody converter, to prepare lookup table */ - if(node->has_converter_blackbody()) - current_shader->has_converter_blackbody = true; - if(node->has_object_dependency()) { current_shader->has_object_dependency = true; } @@ -716,7 +712,6 @@ void SVMCompiler::compile(Shader *shader, vector& global_svm_nodes, int in shader->has_surface_transparent = false; shader->has_surface_bssrdf = false; shader->has_bssrdf_bump = false; - shader->has_converter_blackbody = false; shader->has_volume = false; shader->has_displacement = false; shader->has_heterogeneous_volume = false; -- cgit v1.2.3 From 1648feec943017ff3087f5c913929878ef03fd59 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 May 2015 15:10:53 +1000 Subject: Cleanup: rip tool --- source/blender/editors/mesh/editmesh_rip.c | 70 ++++++++++++++++-------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 1e207a8edf8..2a0bdfc45f0 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -63,9 +63,10 @@ * point and would result in the same distance. */ #define INSET_DEFAULT 0.00001f -static float edbm_rip_edgedist_squared(ARegion *ar, float mat[4][4], - const float co1[3], const float co2[3], const float mvalf[2], - const float inset) +static float edbm_rip_edgedist_squared( + ARegion *ar, float mat[4][4], + const float co1[3], const float co2[3], const float mvalf[2], + const float inset) { float vec1[2], vec2[2], dist_sq; @@ -89,8 +90,9 @@ static float edbm_rip_edgedist_squared(ARegion *ar, float mat[4][4], } #if 0 -static float edbm_rip_linedist(ARegion *ar, float mat[4][4], - const float co1[3], const float co2[3], const float mvalf[2]) +static float edbm_rip_linedist( + ARegion *ar, float mat[4][4], + const float co1[3], const float co2[3], const float mvalf[2]) { float vec1[2], vec2[2]; @@ -114,9 +116,10 @@ static void edbm_calc_loop_co(BMLoop *l, float l_mid_co[3]) } -static float edbm_rip_edge_side_measure(BMEdge *e, BMLoop *e_l, - ARegion *ar, - float projectMat[4][4], const float fmval[2]) +static float edbm_rip_edge_side_measure( + BMEdge *e, BMLoop *e_l, + ARegion *ar, + float projectMat[4][4], const float fmval[2]) { float cent[3] = {0, 0, 0}, mid[3]; @@ -532,7 +535,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve BMesh *bm = em->bm; BMIter iter, liter; BMLoop *l; - BMEdge *e2; + BMEdge *e_best; BMVert *v; const int totvert_orig = bm->totvert; int i; @@ -567,7 +570,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve is_wire = BM_vert_is_wire(v); is_manifold_region = BM_vert_is_manifold_region(v); - e2 = NULL; + e_best = NULL; { BMEdge *e; @@ -579,18 +582,18 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { if ((is_manifold_region == false) || BM_edge_is_manifold(e)) { d = edbm_rip_edgedist_squared(ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT); - if ((e2 == NULL) || (d < dist_sq)) { + if ((e_best == NULL) || (d < dist_sq)) { dist_sq = d; - e2 = e; + e_best = e; } } } } } - if (e2 && (is_manifold_region == false)) { + if (e_best && (is_manifold_region == false)) { /* Try to split off a non-manifold fan (when we have multiple disconnected fans) */ - BMLoop *l_sep = e2->l->v == v ? e2->l : e2->l->next; + BMLoop *l_sep = e_best->l->v == v ? e_best->l : e_best->l->next; BMVert *v_new; BLI_assert(l_sep->v == v); @@ -627,18 +630,18 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve l = l_all[i1]; edbm_calc_loop_co(l, l_mid_co); d = edbm_rip_edgedist_squared(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT); - if ((e2 == NULL) || (d < dist_sq)) { + if ((e_best == NULL) || (d < dist_sq)) { dist_sq = d; /* find the edge that is not in this loop */ - e2 = NULL; + e_best = NULL; for (i2 = 0; i2 < 3; i2++) { if (!BM_edge_in_loop(e_all[i2], l)) { - e2 = e_all[i2]; + e_best = e_all[i2]; break; } } - BLI_assert(e2 != NULL); + BLI_assert(e_best != NULL); } } } @@ -747,7 +750,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve } } - if (!e2) { + if (!e_best) { BKE_report(op->reports, RPT_ERROR, "Selected vertex has no edge/face pairs attached"); return OPERATOR_CANCELLED; } @@ -762,16 +765,16 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve int larr_len = 0; /* rip two adjacent edges */ - if (BM_edge_is_boundary(e2) || BM_vert_face_count_is_equal(v, 2)) { + if (BM_edge_is_boundary(e_best) || BM_vert_face_count_is_equal(v, 2)) { /* Don't run the edge split operator in this case */ - l = BM_edge_vert_share_loop(e2->l, v); + l = BM_edge_vert_share_loop(e_best->l, v); larr[larr_len] = l; larr_len++; /* only tag for face-fill (we don't call the operator) */ - if (BM_edge_is_boundary(e2)) { - BM_elem_flag_enable(e2, BM_ELEM_TAG); + if (BM_edge_is_boundary(e_best)) { + BM_elem_flag_enable(e_best, BM_ELEM_TAG); } else { BM_elem_flag_enable(l->e, BM_ELEM_TAG); @@ -779,10 +782,10 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve } } else { - if (BM_edge_is_manifold(e2)) { + if (BM_edge_is_manifold(e_best)) { BMLoop *l_iter, *l_first; - l_iter = l_first = e2->l; + l_iter = l_first = e_best->l; do { larr[larr_len] = BM_edge_vert_share_loop(l_iter, v); BM_elem_flag_enable(larr[larr_len]->e, BM_ELEM_TAG); @@ -876,7 +879,7 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, const wmEvent *eve BMesh *bm = em->bm; BMIter iter, eiter; BMLoop *l; - BMEdge *e, *e2; + BMEdge *e_best; BMVert *v; const int totedge_orig = bm->totedge; float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]}; @@ -890,11 +893,12 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, const wmEvent *eve /* expand edge selection */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BMEdge *e; bool all_manifold; int totedge_manifold; /* manifold, visible edges */ int i; - e2 = NULL; + e_best = NULL; i = 0; totedge_manifold = 0; all_manifold = true; @@ -906,7 +910,7 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, const wmEvent *eve /* important to check selection rather then tag here * else we get feedback loop */ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - e2 = e; + e_best = e; i++; } totedge_manifold++; @@ -919,18 +923,18 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, const wmEvent *eve } /* single edge, extend */ - if (i == 1 && e2->l) { + if (i == 1 && e_best->l) { /* note: if the case of 3 edges has one change in loop stepping, * if this becomes more involved we may be better off splitting * the 3 edge case into its own else-if branch */ if ((totedge_manifold == 4 || totedge_manifold == 3) || (all_manifold == false)) { - BMLoop *l_a = e2->l; + BMLoop *l_a = e_best->l; BMLoop *l_b = l_a->radial_next; /* find the best face to follow, this way the edge won't point away from * the mouse when there are more than 4 (takes the shortest face fan around) */ - l = (edbm_rip_edge_side_measure(e2, l_a, ar, projectMat, fmval) < - edbm_rip_edge_side_measure(e2, l_b, ar, projectMat, fmval)) ? l_a : l_b; + l = (edbm_rip_edge_side_measure(e_best, l_a, ar, projectMat, fmval) < + edbm_rip_edge_side_measure(e_best, l_b, ar, projectMat, fmval)) ? l_a : l_b; l = BM_loop_other_edge_loop(l, v); /* important edge is manifold else we can be attempting to split off a fan that don't budge, @@ -948,7 +952,7 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, const wmEvent *eve } } else { - e = BM_vert_other_disk_edge(v, e2); + e = BM_vert_other_disk_edge(v, e_best); if (e) { BLI_assert(!BM_elem_flag_test(e, BM_ELEM_TAG)); -- cgit v1.2.3 From ea5f9fee8da4086adeb4ce902e9d58c446ef4ac8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 May 2015 15:59:26 +1000 Subject: Cleanup: function arg wrapping --- source/blender/bmesh/operators/bmo_bridge.c | 14 ++++--- source/blender/bmesh/operators/bmo_connect_pair.c | 27 ++++++++----- source/blender/bmesh/operators/bmo_dupe.c | 31 +++++++------- .../blender/bmesh/operators/bmo_fill_attribute.c | 10 +++-- source/blender/bmesh/operators/bmo_fill_grid.c | 26 +++++++----- source/blender/bmesh/operators/bmo_hull.c | 44 +++++++++++--------- .../blender/bmesh/operators/bmo_join_triangles.c | 5 ++- source/blender/bmesh/operators/bmo_removedoubles.c | 5 ++- source/blender/bmesh/operators/bmo_subdivide.c | 22 +++++----- .../bmesh/operators/bmo_subdivide_edgering.c | 47 ++++++++++++---------- 10 files changed, 132 insertions(+), 99 deletions(-) diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c index 6002dcf2c0d..b4570e03c83 100644 --- a/source/blender/bmesh/operators/bmo_bridge.c +++ b/source/blender/bmesh/operators/bmo_bridge.c @@ -87,8 +87,9 @@ static void bm_vert_loop_pair(BMesh *bm, BMVert *v1, BMVert *v2, BMLoop **l1, BM } /* el_b can have any offset */ -static float bm_edgeloop_offset_length(LinkData *el_a, LinkData *el_b, - LinkData *el_b_first, const float len_max) +static float bm_edgeloop_offset_length( + LinkData *el_a, LinkData *el_b, + LinkData *el_b_first, const float len_max) { float len = 0.0f; BLI_assert(el_a->prev == NULL); /* must be first */ @@ -137,10 +138,11 @@ static bool bm_edge_test_cb(BMEdge *e, void *bm_v) return BMO_elem_flag_test((BMesh *)bm_v, e, EDGE_MARK); } -static void bridge_loop_pair(BMesh *bm, - struct BMEdgeLoopStore *el_store_a, - struct BMEdgeLoopStore *el_store_b, - const bool use_merge, const float merge_factor, const int twist_offset) +static void bridge_loop_pair( + BMesh *bm, + struct BMEdgeLoopStore *el_store_a, + struct BMEdgeLoopStore *el_store_b, + const bool use_merge, const float merge_factor, const int twist_offset) { const float eps = 0.00001f; LinkData *el_a_first, *el_b_first; diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c index fbc128b375f..cf0e233fe6c 100644 --- a/source/blender/bmesh/operators/bmo_connect_pair.c +++ b/source/blender/bmesh/operators/bmo_connect_pair.c @@ -152,8 +152,9 @@ static void min_dist_dir_update(MinDistDir *dist, const float dist_dir[3]) /** \} */ -static int state_isect_co_pair(const PathContext *pc, - const float co_a[3], const float co_b[3]) +static int state_isect_co_pair( + const PathContext *pc, + const float co_a[3], const float co_b[3]) { const float diff_a = dot_m3_v3_row_x((float (*)[3])pc->matrix, co_a) - pc->axis_sep; const float diff_b = dot_m3_v3_row_x((float (*)[3])pc->matrix, co_b) - pc->axis_sep; @@ -169,15 +170,17 @@ static int state_isect_co_pair(const PathContext *pc, } } -static int state_isect_co_exact(const PathContext *pc, - const float co[3]) +static int state_isect_co_exact( + const PathContext *pc, + const float co[3]) { const float diff = dot_m3_v3_row_x((float (*)[3])pc->matrix, co) - pc->axis_sep; return (fabsf(diff) <= CONNECT_EPS); } -static float state_calc_co_pair_fac(const PathContext *pc, - const float co_a[3], const float co_b[3]) +static float state_calc_co_pair_fac( + const PathContext *pc, + const float co_a[3], const float co_b[3]) { float diff_a, diff_b, diff_tot; @@ -187,9 +190,10 @@ static float state_calc_co_pair_fac(const PathContext *pc, return (diff_tot > FLT_EPSILON) ? (diff_a / diff_tot) : 0.5f; } -static void state_calc_co_pair(const PathContext *pc, - const float co_a[3], const float co_b[3], - float r_co[3]) +static void state_calc_co_pair( + const PathContext *pc, + const float co_a[3], const float co_b[3], + float r_co[3]) { const float fac = state_calc_co_pair_fac(pc, co_a, co_b); interp_v3_v3v3(r_co, co_a, co_b, fac); @@ -213,8 +217,9 @@ static bool state_link_find(const PathLinkState *state, BMElem *ele) return false; } -static void state_link_add(PathContext *pc, PathLinkState *state, - BMElem *ele, BMElem *ele_from) +static void state_link_add( + PathContext *pc, PathLinkState *state, + BMElem *ele, BMElem *ele_from) { PathLink *step_new = BLI_mempool_alloc(pc->link_pool); BLI_assert(ele != ele_from); diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c index a5a6480c187..33048e6c86e 100644 --- a/source/blender/bmesh/operators/bmo_dupe.c +++ b/source/blender/bmesh/operators/bmo_dupe.c @@ -44,9 +44,10 @@ * * Copy an existing vertex from one bmesh to another. */ -static BMVert *bmo_vert_copy(BMOperator *op, - BMOpSlot *slot_vertmap_out, - BMesh *bm_dst, BMesh *bm_src, BMVert *v_src, GHash *vhash) +static BMVert *bmo_vert_copy( + BMOperator *op, + BMOpSlot *slot_vertmap_out, + BMesh *bm_dst, BMesh *bm_src, BMVert *v_src, GHash *vhash) { BMVert *v_dst; @@ -72,12 +73,13 @@ static BMVert *bmo_vert_copy(BMOperator *op, * * Copy an existing edge from one bmesh to another. */ -static BMEdge *bmo_edge_copy(BMOperator *op, - BMOpSlot *slot_edgemap_out, - BMOpSlot *slot_boundarymap_out, - BMesh *bm_dst, BMesh *bm_src, - BMEdge *e_src, - GHash *vhash, GHash *ehash) +static BMEdge *bmo_edge_copy( + BMOperator *op, + BMOpSlot *slot_edgemap_out, + BMOpSlot *slot_boundarymap_out, + BMesh *bm_dst, BMesh *bm_src, + BMEdge *e_src, + GHash *vhash, GHash *ehash) { BMEdge *e_dst; BMVert *e_dst_v1, *e_dst_v2; @@ -131,11 +133,12 @@ static BMEdge *bmo_edge_copy(BMOperator *op, * * Copy an existing face from one bmesh to another. */ -static BMFace *bmo_face_copy(BMOperator *op, - BMOpSlot *slot_facemap_out, - BMesh *bm_dst, BMesh *bm_src, - BMFace *f_src, - GHash *vhash, GHash *ehash) +static BMFace *bmo_face_copy( + BMOperator *op, + BMOpSlot *slot_facemap_out, + BMesh *bm_dst, BMesh *bm_src, + BMFace *f_src, + GHash *vhash, GHash *ehash) { BMFace *f_dst; BMVert **vtar = BLI_array_alloca(vtar, f_src->len); diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c index d9f50ac891c..85bca744d86 100644 --- a/source/blender/bmesh/operators/bmo_fill_attribute.c +++ b/source/blender/bmesh/operators/bmo_fill_attribute.c @@ -61,8 +61,9 @@ static bool bm_loop_is_face_untag(BMElem *ele, void *UNUSED(user_data)) /** * Copy all attributes from adjacent untagged faces. */ -static void bm_face_copy_shared_all(BMesh *bm, BMLoop *l, - const bool use_normals, const bool use_data) +static void bm_face_copy_shared_all( + BMesh *bm, BMLoop *l, + const bool use_normals, const bool use_data) { BMLoop *l_other = l->radial_next; BMFace *f = l->f, *f_other; @@ -90,8 +91,9 @@ static void bm_face_copy_shared_all(BMesh *bm, BMLoop *l, /** * Flood fill attributes. */ -static unsigned int bmesh_face_attribute_fill(BMesh *bm, - const bool use_normals, const bool use_data) +static unsigned int bmesh_face_attribute_fill( + BMesh *bm, + const bool use_normals, const bool use_data) { BLI_LINKSTACK_DECLARE(loop_queue_prev, BMLoop *); BLI_LINKSTACK_DECLARE(loop_queue_next, BMLoop *); diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c index dd954adcd55..fd1e91a0b30 100644 --- a/source/blender/bmesh/operators/bmo_fill_grid.c +++ b/source/blender/bmesh/operators/bmo_fill_grid.c @@ -114,8 +114,9 @@ static void quad_verts_to_barycentric_tri( /** * Assign a loop pair from 2 verts (which _must_ share an edge) */ -static void bm_loop_pair_from_verts(BMVert *v_a, BMVert *v_b, - BMLoop *l_pair[2]) +static void bm_loop_pair_from_verts( + BMVert *v_a, BMVert *v_b, + BMLoop *l_pair[2]) { BMEdge *e = BM_edge_exists(v_a, v_b); if (e->l) { @@ -185,8 +186,9 @@ static void bm_loop_interp_from_grid_boundary_2(BMesh *bm, BMLoop *l, BMLoop *l_ /** * Avoids calling #barycentric_weights_v2_quad often by caching weights into an array. */ -static void barycentric_weights_v2_grid_cache(const unsigned int xtot, const unsigned int ytot, - float (*weight_table)[4]) +static void barycentric_weights_v2_grid_cache( + const unsigned int xtot, const unsigned int ytot, + float (*weight_table)[4]) { float x_step = 1.0f / (float)(xtot - 1); float y_step = 1.0f / (float)(ytot - 1); @@ -216,9 +218,10 @@ static void barycentric_weights_v2_grid_cache(const unsigned int xtot, const uns * * \param v_grid 2d array of verts, all boundary verts must be set, we fill in the middle. */ -static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const unsigned int xtot, unsigned const int ytot, - const short mat_nr, const bool use_smooth, - const bool use_flip, const bool use_interp_simple) +static void bm_grid_fill_array( + BMesh *bm, BMVert **v_grid, const unsigned int xtot, unsigned const int ytot, + const short mat_nr, const bool use_smooth, + const bool use_flip, const bool use_interp_simple) { const bool use_vert_interp = CustomData_has_interp(&bm->vdata); const bool use_loop_interp = CustomData_has_interp(&bm->ldata); @@ -485,10 +488,11 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const unsigned int xt #undef XY } -static void bm_grid_fill(BMesh *bm, - struct BMEdgeLoopStore *estore_a, struct BMEdgeLoopStore *estore_b, - struct BMEdgeLoopStore *estore_rail_a, struct BMEdgeLoopStore *estore_rail_b, - const short mat_nr, const bool use_smooth, const bool use_interp_simple) +static void bm_grid_fill( + BMesh *bm, + struct BMEdgeLoopStore *estore_a, struct BMEdgeLoopStore *estore_b, + struct BMEdgeLoopStore *estore_rail_a, struct BMEdgeLoopStore *estore_rail_b, + const short mat_nr, const bool use_smooth, const bool use_interp_simple) { #define USE_FLIP_DETECT diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c index fb99c9777d0..fe4a0204335 100644 --- a/source/blender/bmesh/operators/bmo_hull.c +++ b/source/blender/bmesh/operators/bmo_hull.c @@ -67,8 +67,9 @@ typedef struct HullTriangle { /*************************** Hull Triangles ***************************/ -static void hull_add_triangle(BMesh *bm, GSet *hull_triangles, BLI_mempool *pool, - BMVert *v1, BMVert *v2, BMVert *v3) +static void hull_add_triangle( + BMesh *bm, GSet *hull_triangles, BLI_mempool *pool, + BMVert *v1, BMVert *v2, BMVert *v3) { HullTriangle *t; int i; @@ -189,8 +190,9 @@ static LinkData *final_edges_find_link(ListBase *adj, BMVert *v) return NULL; } -static int hull_final_edges_lookup(HullFinalEdges *final_edges, - BMVert *v1, BMVert *v2) +static int hull_final_edges_lookup( + HullFinalEdges *final_edges, + BMVert *v1, BMVert *v2) { ListBase *adj; @@ -259,8 +261,9 @@ static void hull_final_edges_free(HullFinalEdges *final_edges) /**************************** Final Output ****************************/ -static void hull_remove_overlapping(BMesh *bm, GSet *hull_triangles, - HullFinalEdges *final_edges) +static void hull_remove_overlapping( + BMesh *bm, GSet *hull_triangles, + HullFinalEdges *final_edges) { GSetIterator hull_iter; @@ -296,8 +299,9 @@ static void hull_remove_overlapping(BMesh *bm, GSet *hull_triangles, } } -static void hull_mark_interior_elements(BMesh *bm, BMOperator *op, - HullFinalEdges *final_edges) +static void hull_mark_interior_elements( + BMesh *bm, BMOperator *op, + HullFinalEdges *final_edges) { BMEdge *e; BMFace *f; @@ -425,8 +429,9 @@ static int hull_input_vert_count(BMOperator *op) return count; } -static BMVert **hull_input_verts_copy(BMOperator *op, - const int num_input_verts) +static BMVert **hull_input_verts_copy( + BMOperator *op, + const int num_input_verts) { BMOIter oiter; BMVert *v; @@ -441,8 +446,9 @@ static BMVert **hull_input_verts_copy(BMOperator *op, return input_verts; } -static float (*hull_verts_for_bullet(BMVert **input_verts, - const int num_input_verts))[3] +static float (*hull_verts_for_bullet( + BMVert **input_verts, + const int num_input_verts))[3] { float (*coords)[3] = MEM_callocN(sizeof(*coords) * num_input_verts, __func__); int i; @@ -454,9 +460,10 @@ static float (*hull_verts_for_bullet(BMVert **input_verts, return coords; } -static BMVert **hull_verts_from_bullet(plConvexHull hull, - BMVert **input_verts, - const int num_input_verts) +static BMVert **hull_verts_from_bullet( + plConvexHull hull, + BMVert **input_verts, + const int num_input_verts) { const int num_verts = plConvexHullNumVertices(hull); BMVert **hull_verts = MEM_mallocN(sizeof(*hull_verts) * @@ -478,9 +485,10 @@ static BMVert **hull_verts_from_bullet(plConvexHull hull, return hull_verts; } -static void hull_from_bullet(BMesh *bm, BMOperator *op, - GSet *hull_triangles, - BLI_mempool *pool) +static void hull_from_bullet( + BMesh *bm, BMOperator *op, + GSet *hull_triangles, + BLI_mempool *pool) { int *fvi = NULL; BLI_array_declare(fvi); diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index 6562f26062f..7fef9e1190a 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -45,8 +45,9 @@ #define FACE_OUT (1 << 0) /* assumes edges are validated before reaching this poin */ -static float measure_facepair(const float v1[3], const float v2[3], - const float v3[3], const float v4[3], float limit) +static float measure_facepair( + const float v1[3], const float v2[3], + const float v3[3], const float v4[3], float limit) { /* gives a 'weight' to a pair of triangles that join an edge to decide how good a join they would make */ /* Note: this is more complicated than it needs to be and should be cleaned up.. */ diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index 73b6268e78b..74bcbbaf463 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -522,8 +522,9 @@ void bmo_collapse_uvs_exec(BMesh *bm, BMOperator *op) } -static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, - BMOperator *optarget, BMOpSlot *optarget_slot) +static void bmesh_find_doubles_common( + BMesh *bm, BMOperator *op, + BMOperator *optarget, BMOpSlot *optarget_slot) { BMVert **verts; int verts_len; diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 410da65f828..e3304298647 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -80,8 +80,9 @@ static void bmo_subd_init_shape_info(BMesh *bm, SubDParams *params) } -typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts, - const SubDParams *params); +typedef void (*subd_pattern_fill_fp)( + BMesh *bm, BMFace *face, BMVert **verts, + const SubDParams *params); /* * note: this is a pattern-based edge subdivider. @@ -1176,14 +1177,15 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } /* editmesh-emulating function */ -void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, - const float smooth, const short smooth_falloff, const bool use_smooth_even, - const float fractal, const float along_normal, - const int numcuts, - const int seltype, const int cornertype, - const short use_single_edge, const short use_grid_fill, - const short use_only_quads, - const int seed) +void BM_mesh_esubdivide( + BMesh *bm, const char edge_hflag, + const float smooth, const short smooth_falloff, const bool use_smooth_even, + const float fractal, const float along_normal, + const int numcuts, + const int seltype, const int cornertype, + const short use_single_edge, const short use_grid_fill, + const short use_only_quads, + const int seed) { BMOperator op; diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c index c01ad10d716..0e619b4cece 100644 --- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c +++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c @@ -80,8 +80,9 @@ static unsigned int bm_verts_tag_count(BMesh *bm) } #endif -static float bezier_handle_calc_length_v3(const float co_a[3], const float no_a[3], - const float co_b[3], const float no_b[3]) +static float bezier_handle_calc_length_v3( + const float co_a[3], const float no_a[3], + const float co_b[3], const float no_b[3]) { const float dot = dot_v3v3(no_a, no_b); /* gives closest approx at a circle with 2 parallel handles */ @@ -538,12 +539,13 @@ static void bm_edgering_pair_store_free( /* -------------------------------------------------------------------- */ /* Interpolation Function */ -static void bm_edgering_pair_interpolate(BMesh *bm, LoopPairStore *lpair, - struct BMEdgeLoopStore *el_store_a, - struct BMEdgeLoopStore *el_store_b, - ListBase *eloops_ring, - const int interp_mode, const int cuts, const float smooth, - const float *falloff_cache) +static void bm_edgering_pair_interpolate( + BMesh *bm, LoopPairStore *lpair, + struct BMEdgeLoopStore *el_store_a, + struct BMEdgeLoopStore *el_store_b, + ListBase *eloops_ring, + const int interp_mode, const int cuts, const float smooth, + const float *falloff_cache) { const int resolu = cuts + 2; const int dims = 3; @@ -878,9 +880,10 @@ static bool bm_edgering_pair_order_is_flipped(BMesh *UNUSED(bm), * Takes 2 edge loops that share edges, * sort their verts and rotates the list so the lined up. */ -static void bm_edgering_pair_order(BMesh *bm, - struct BMEdgeLoopStore *el_store_a, - struct BMEdgeLoopStore *el_store_b) +static void bm_edgering_pair_order( + BMesh *bm, + struct BMEdgeLoopStore *el_store_a, + struct BMEdgeLoopStore *el_store_b) { ListBase *lb_a = BM_edgeloop_verts_get(el_store_a); ListBase *lb_b = BM_edgeloop_verts_get(el_store_b); @@ -951,11 +954,12 @@ static void bm_edgering_pair_order(BMesh *bm, * * \note loops are _not_ aligned. */ -static void bm_edgering_pair_subdiv(BMesh *bm, - struct BMEdgeLoopStore *el_store_a, - struct BMEdgeLoopStore *el_store_b, - ListBase *eloops_ring, - const int cuts) +static void bm_edgering_pair_subdiv( + BMesh *bm, + struct BMEdgeLoopStore *el_store_a, + struct BMEdgeLoopStore *el_store_b, + ListBase *eloops_ring, + const int cuts) { ListBase *lb_a = BM_edgeloop_verts_get(el_store_a); // ListBase *lb_b = BM_edgeloop_verts_get(el_store_b); @@ -1043,11 +1047,12 @@ static void bm_edgering_pair_subdiv(BMesh *bm, bm_edgeloop_vert_tag(el_store_b, false); } -static void bm_edgering_pair_ringsubd(BMesh *bm, LoopPairStore *lpair, - struct BMEdgeLoopStore *el_store_a, - struct BMEdgeLoopStore *el_store_b, - const int interp_mode, const int cuts, const float smooth, - const float *falloff_cache) +static void bm_edgering_pair_ringsubd( + BMesh *bm, LoopPairStore *lpair, + struct BMEdgeLoopStore *el_store_a, + struct BMEdgeLoopStore *el_store_b, + const int interp_mode, const int cuts, const float smooth, + const float *falloff_cache) { ListBase eloops_ring = {NULL}; bm_edgering_pair_order(bm, el_store_a, el_store_b); -- cgit v1.2.3 From e5e73ccc901e478e85e312579dd2bc63dfae0292 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 May 2015 17:08:29 +1000 Subject: Math Lib: rename fill_*, to copy_* matching convention for fixed length api, eg: copy_v3_fl --- source/blender/blenkernel/intern/DerivedMesh.c | 12 ++++++------ source/blender/blenkernel/intern/customdata.c | 4 ++-- source/blender/blenkernel/intern/deform.c | 8 ++++---- source/blender/blenkernel/intern/editderivedmesh.c | 4 ++-- source/blender/blenkernel/intern/mesh_remap.c | 4 ++-- source/blender/blenlib/BLI_math_vector.h | 12 ++++++------ source/blender/blenlib/intern/astar.c | 2 +- source/blender/blenlib/intern/math_interp.c | 8 ++++---- source/blender/blenlib/intern/math_vector.c | 12 ++++++------ source/blender/blenloader/intern/versioning_260.c | 2 +- source/blender/bmesh/intern/bmesh_interp.c | 2 +- source/blender/bmesh/tools/bmesh_decimate_dissolve.c | 2 +- source/blender/bmesh/tools/bmesh_path.c | 6 +++--- source/blender/editors/sculpt_paint/paint_vertex_proj.c | 2 +- source/blender/editors/space_view3d/view3d_buttons.c | 2 +- source/blender/editors/transform/transform.c | 2 +- source/blender/editors/transform/transform_conversions.c | 2 +- source/blender/editors/util/numinput.c | 8 ++++---- source/blender/editors/uvedit/uvedit_ops.c | 4 ++-- source/blender/imbuf/intern/tiff.c | 4 ++-- source/blender/makesrna/intern/rna_object.c | 2 +- source/blender/modifiers/intern/MOD_array.c | 10 +++++----- source/blender/modifiers/intern/MOD_correctivesmooth.c | 2 +- source/blender/modifiers/intern/MOD_skin.c | 2 +- source/blender/modifiers/intern/MOD_solidify.c | 6 +++--- source/blender/python/mathutils/mathutils_Matrix.c | 2 +- source/blender/python/mathutils/mathutils_Vector.c | 14 +++++++------- 27 files changed, 70 insertions(+), 70 deletions(-) diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 38ae0461c84..411de80ddbc 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -295,11 +295,11 @@ void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges, dm->dirty = 0; /* don't use CustomData_reset(...); because we dont want to touch customdata */ - fill_vn_i(dm->vertData.typemap, CD_NUMTYPES, -1); - fill_vn_i(dm->edgeData.typemap, CD_NUMTYPES, -1); - fill_vn_i(dm->faceData.typemap, CD_NUMTYPES, -1); - fill_vn_i(dm->loopData.typemap, CD_NUMTYPES, -1); - fill_vn_i(dm->polyData.typemap, CD_NUMTYPES, -1); + copy_vn_i(dm->vertData.typemap, CD_NUMTYPES, -1); + copy_vn_i(dm->edgeData.typemap, CD_NUMTYPES, -1); + copy_vn_i(dm->faceData.typemap, CD_NUMTYPES, -1); + copy_vn_i(dm->loopData.typemap, CD_NUMTYPES, -1); + copy_vn_i(dm->polyData.typemap, CD_NUMTYPES, -1); } void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type, @@ -1276,7 +1276,7 @@ static void calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, int const d else { weightpaint_color(col, dm_wcinfo, 0.0f); } - fill_vn_i((int *)r_wtcol_v, numVerts, *((int *)col)); + copy_vn_i((int *)r_wtcol_v, numVerts, *((int *)col)); } } diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index add6bb0fd0b..eced263d493 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -1091,7 +1091,7 @@ static void layerDefault_mcol(void *data, int count) static void layerDefault_origindex(void *data, int count) { - fill_vn_i((int *)data, count, ORIGINDEX_NONE); + copy_vn_i((int *)data, count, ORIGINDEX_NONE); } static void layerInterp_bweight( @@ -1542,7 +1542,7 @@ static void CustomData_external_free(CustomData *data) void CustomData_reset(CustomData *data) { memset(data, 0, sizeof(*data)); - fill_vn_i(data->typemap, CD_NUMTYPES, -1); + copy_vn_i(data->typemap, CD_NUMTYPES, -1); } void CustomData_free(CustomData *data, int totelem) diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 72133cf6460..88885da474b 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -982,7 +982,7 @@ void BKE_defvert_extract_vgroup_to_vertweights( } } else { - fill_vn_fl(r_weights, num_verts, invert_vgroup ? 1.0f : 0.0f); + copy_vn_fl(r_weights, num_verts, invert_vgroup ? 1.0f : 0.0f); } } @@ -1008,7 +1008,7 @@ void BKE_defvert_extract_vgroup_to_edgeweights( MEM_freeN(tmp_weights); } else { - fill_vn_fl(r_weights, num_edges, 0.0f); + copy_vn_fl(r_weights, num_edges, 0.0f); } } @@ -1031,7 +1031,7 @@ void BKE_defvert_extract_vgroup_to_loopweights( MEM_freeN(tmp_weights); } else { - fill_vn_fl(r_weights, num_loops, 0.0f); + copy_vn_fl(r_weights, num_loops, 0.0f); } } @@ -1060,7 +1060,7 @@ void BKE_defvert_extract_vgroup_to_polyweights( MEM_freeN(tmp_weights); } else { - fill_vn_fl(r_weights, num_polys, 0.0f); + copy_vn_fl(r_weights, num_polys, 0.0f); } } diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 40f3022c192..5230634fe4c 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -1968,7 +1968,7 @@ static void statvis_calc_thickness( BLI_assert(min <= max); - fill_vn_fl(face_dists, em->bm->totface, max); + copy_vn_fl(face_dists, em->bm->totface, max); if (use_jit) { int j; @@ -2223,7 +2223,7 @@ static void statvis_calc_sharp( (void)vertexCos; /* TODO */ - fill_vn_fl(vert_angles, em->bm->totvert, -M_PI); + copy_vn_fl(vert_angles, em->bm->totvert, -M_PI); /* first assign float values to verts */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c index f3e2f395002..36b8a3264e9 100644 --- a/source/blender/blenkernel/intern/mesh_remap.c +++ b/source/blender/blenkernel/intern/mesh_remap.c @@ -707,7 +707,7 @@ void BKE_mesh_remap_calc_edges_from_dm( BLI_space_transform_apply_normal(space_transform, v2_no); } - fill_vn_fl(weights, (int)numedges_src, 0.0f); + copy_vn_fl(weights, (int)numedges_src, 0.0f); /* We adjust our ray-casting grid to ray_radius (the smaller, the more rays are cast), * with lower/upper bounds. */ @@ -1916,7 +1916,7 @@ void BKE_mesh_remap_calc_polys_from_dm( BLI_space_transform_apply_normal(space_transform, tmp_no); } - fill_vn_fl(weights, (int)numpolys_src, 0.0f); + copy_vn_fl(weights, (int)numpolys_src, 0.0f); if (UNLIKELY((size_t)mp->totloop > tmp_poly_size)) { tmp_poly_size = (size_t)mp->totloop; diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 82a2b9c9ab2..04c2baa5359 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -308,7 +308,7 @@ void dist_ensure_v2_v2fl(float v1[2], const float v2[2], const float dist); void axis_sort_v3(const float axis_values[3], int r_axis_order[3]); /***************************** Array Functions *******************************/ -/* attempted to follow fixed length vertex functions. names could be improved*/ +/* follow fixed length vector function conventions. */ double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int size) ATTR_WARN_UNUSED_RESULT; double len_squared_vn(const float *array, const int size) ATTR_WARN_UNUSED_RESULT; float normalize_vn_vn(float *array_tar, const float *array_src, const int size); @@ -329,11 +329,11 @@ void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_ void msub_vn_vn(float *array_tar, const float *array_src, const float f, const int size); void msub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const float f, const int size); void interp_vn_vn(float *array_tar, const float *array_src, const float t, const int size); -void fill_vn_i(int *array_tar, const int size, const int val); -void fill_vn_short(short *array_tar, const int size, const short val); -void fill_vn_ushort(unsigned short *array_tar, const int size, const unsigned short val); -void fill_vn_uchar(unsigned char *array_tar, const int size, const unsigned char val); -void fill_vn_fl(float *array_tar, const int size, const float val); +void copy_vn_i(int *array_tar, const int size, const int val); +void copy_vn_short(short *array_tar, const int size, const short val); +void copy_vn_ushort(unsigned short *array_tar, const int size, const unsigned short val); +void copy_vn_uchar(unsigned char *array_tar, const int size, const unsigned char val); +void copy_vn_fl(float *array_tar, const int size, const float val); /**************************** Inline Definitions ******************************/ diff --git a/source/blender/blenlib/intern/astar.c b/source/blender/blenlib/intern/astar.c index b7b41d2497e..311d6dd89ae 100644 --- a/source/blender/blenlib/intern/astar.c +++ b/source/blender/blenlib/intern/astar.c @@ -229,7 +229,7 @@ bool BLI_astar_graph_solve( r_solution->steps = 0; prev_nodes[node_index_src] = -1; BLI_BITMAP_SET_ALL(done_nodes, false, as_graph->node_num); - fill_vn_fl(g_costs, as_graph->node_num, FLT_MAX); + copy_vn_fl(g_costs, as_graph->node_num, FLT_MAX); g_costs[node_index_src] = 0.0f; g_steps[node_index_src] = 0; diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c index 67850463fe2..b45d8b4c13b 100644 --- a/source/blender/blenlib/intern/math_interp.c +++ b/source/blender/blenlib/intern/math_interp.c @@ -112,10 +112,10 @@ BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, const fl /* sample area entirely outside image? */ if (ceil(u) < 0 || floor(u) > width - 1 || ceil(v) < 0 || floor(v) > height - 1) { if (float_output) { - fill_vn_fl(float_output, components, 0.0f); + copy_vn_fl(float_output, components, 0.0f); } if (byte_output) { - fill_vn_uchar(byte_output, components, 0); + copy_vn_uchar(byte_output, components, 0); } return; } @@ -281,7 +281,7 @@ BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, const f /* sample area entirely outside image? */ if (x2 < 0 || x1 > width - 1 || y2 < 0 || y1 > height - 1) { - fill_vn_fl(float_output, components, 0.0f); + copy_vn_fl(float_output, components, 0.0f); return; } @@ -323,7 +323,7 @@ BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, const f /* sample area entirely outside image? */ if (x2 < 0 || x1 > width - 1 || y2 < 0 || y1 > height - 1) { - fill_vn_uchar(byte_output, components, 0); + copy_vn_uchar(byte_output, components, 0); return; } diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 8f536bfe75c..88eccd60352 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -876,7 +876,7 @@ float normalize_vn_vn(float *array_tar, const float *array_src, const int size) mul_vn_vn_fl(array_tar, array_src, size, 1.0f / d_sqrt); } else { - fill_vn_fl(array_tar, size, 0.0f); + copy_vn_fl(array_tar, size, 0.0f); d_sqrt = 0.0f; } return d_sqrt; @@ -1051,7 +1051,7 @@ void interp_vn_vn(float *array_tar, const float *array_src, const float t, const } } -void fill_vn_i(int *array_tar, const int size, const int val) +void copy_vn_i(int *array_tar, const int size, const int val) { int *tar = array_tar + (size - 1); int i = size; @@ -1060,7 +1060,7 @@ void fill_vn_i(int *array_tar, const int size, const int val) } } -void fill_vn_short(short *array_tar, const int size, const short val) +void copy_vn_short(short *array_tar, const int size, const short val) { short *tar = array_tar + (size - 1); int i = size; @@ -1069,7 +1069,7 @@ void fill_vn_short(short *array_tar, const int size, const short val) } } -void fill_vn_ushort(unsigned short *array_tar, const int size, const unsigned short val) +void copy_vn_ushort(unsigned short *array_tar, const int size, const unsigned short val) { unsigned short *tar = array_tar + (size - 1); int i = size; @@ -1078,7 +1078,7 @@ void fill_vn_ushort(unsigned short *array_tar, const int size, const unsigned sh } } -void fill_vn_uchar(unsigned char *array_tar, const int size, const unsigned char val) +void copy_vn_uchar(unsigned char *array_tar, const int size, const unsigned char val) { unsigned char *tar = array_tar + (size - 1); int i = size; @@ -1087,7 +1087,7 @@ void fill_vn_uchar(unsigned char *array_tar, const int size, const unsigned char } } -void fill_vn_fl(float *array_tar, const int size, const float val) +void copy_vn_fl(float *array_tar, const int size, const float val) { float *tar = array_tar + (size - 1); int i = size; diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index 734dc33ea24..72a320281fe 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -845,7 +845,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main) Object *ob; for (ob = main->object.first; ob; ob = ob->id.next) { if (is_zero_v3(ob->dscale)) { - fill_vn_fl(ob->dscale, 3, 1.0f); + copy_vn_fl(ob->dscale, 3, 1.0f); } } } diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index 169af6f62c3..30ac76ab7e1 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -1057,7 +1057,7 @@ LinkNode *BM_vert_loop_groups_data_layer_create( mul_vn_fl(lf->data_weights, lf->data_len, 1.0f / lwc.weight_accum); } else { - fill_vn_fl(lf->data_weights, lf->data_len, 1.0f / (float)lf->data_len); + copy_vn_fl(lf->data_weights, lf->data_len, 1.0f / (float)lf->data_len); } BLI_linklist_prepend_arena(&groups, lf, lwc.arena); diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index 09c7b932b7a..6d3b738a462 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -190,7 +190,7 @@ void BM_mesh_decimate_dissolve_ex( /* prepare for cleanup */ BM_mesh_elem_index_ensure(bm, BM_VERT); vert_reverse_lookup = MEM_mallocN(sizeof(int) * bm->totvert, __func__); - fill_vn_i(vert_reverse_lookup, bm->totvert, -1); + copy_vn_i(vert_reverse_lookup, bm->totvert, -1); for (i = 0; i < vinput_len; i++) { BMVert *v = vinput_arr[i]; vert_reverse_lookup[BM_elem_index_get(v)] = i; diff --git a/source/blender/bmesh/tools/bmesh_path.c b/source/blender/bmesh/tools/bmesh_path.c index 8ae3507a738..6633803414b 100644 --- a/source/blender/bmesh/tools/bmesh_path.c +++ b/source/blender/bmesh/tools/bmesh_path.c @@ -126,7 +126,7 @@ LinkNode *BM_mesh_calc_path_vert( verts_prev = MEM_callocN(sizeof(*verts_prev) * totvert, __func__); cost = MEM_mallocN(sizeof(*cost) * totvert, __func__); - fill_vn_fl(cost, totvert, 1e20f); + copy_vn_fl(cost, totvert, 1e20f); /* * Arrays are now filled as follows: @@ -252,7 +252,7 @@ LinkNode *BM_mesh_calc_path_edge( edges_prev = MEM_callocN(sizeof(*edges_prev) * totedge, "SeamPathPrevious"); cost = MEM_mallocN(sizeof(*cost) * totedge, "SeamPathCost"); - fill_vn_fl(cost, totedge, 1e20f); + copy_vn_fl(cost, totedge, 1e20f); /* * Arrays are now filled as follows: @@ -378,7 +378,7 @@ LinkNode *BM_mesh_calc_path_face( faces_prev = MEM_callocN(sizeof(*faces_prev) * totface, __func__); cost = MEM_mallocN(sizeof(*cost) * totface, __func__); - fill_vn_fl(cost, totface, 1e20f); + copy_vn_fl(cost, totface, 1e20f); /* * Arrays are now filled as follows: diff --git a/source/blender/editors/sculpt_paint/paint_vertex_proj.c b/source/blender/editors/sculpt_paint/paint_vertex_proj.c index ae729248f7e..c939eb6df35 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_proj.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_proj.c @@ -186,7 +186,7 @@ static void vpaint_proj_dm_map_cosnos_update(struct VertProjHandle *vp_handle, /* highly unlikely this will become unavailable once painting starts (perhaps with animated modifiers) */ if (LIKELY(dm->foreachMappedVert)) { - fill_vn_fl(vp_handle->dists_sq, me->totvert, FLT_MAX); + copy_vn_fl(vp_handle->dists_sq, me->totvert, FLT_MAX); dm->foreachMappedVert(dm, vpaint_proj_dm_map_cosnos_update__map_cb, &vp_update, DM_FOREACH_USE_NORMAL); } diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 87fe29325bc..1f8a69adba0 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -199,7 +199,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float bool has_skinradius = false; PointerRNA data_ptr; - fill_vn_fl(median, NBR_TRANSFORM_PROPERTIES, 0.0f); + copy_vn_fl(median, NBR_TRANSFORM_PROPERTIES, 0.0f); tot = totedgedata = totcurvedata = totlattdata = totcurvebweight = 0; /* make sure we got storage */ diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 3cf0c53d564..7d80044762c 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -6017,7 +6017,7 @@ static bool createEdgeSlideVerts(TransInfo *t) loop_dir = MEM_callocN(sizeof(float) * 3 * loop_nr, "sv loop_dir"); loop_maxdist = MEM_mallocN(sizeof(float) * loop_nr, "sv loop_maxdist"); - fill_vn_fl(loop_maxdist, loop_nr, -1.0f); + copy_vn_fl(loop_maxdist, loop_nr, -1.0f); BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 8aa26c32413..9efbc1bc549 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -2124,7 +2124,7 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__); /* we shouldn't need this, but with incorrect selection flushing * its possible we have a selected vertex thats not in a face, for now best not crash in that case. */ - fill_vn_i(vert_map, bm->totvert, -1); + copy_vn_i(vert_map, bm->totvert, -1); BM_mesh_elem_table_ensure(bm, htype); ele_array = (htype == BM_FACE) ? (void **)bm->ftable : (void **)bm->etable; diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c index 050631362b4..effb45a61ab 100644 --- a/source/blender/editors/util/numinput.c +++ b/source/blender/editors/util/numinput.c @@ -73,14 +73,14 @@ void initNumInput(NumInput *n) { n->idx_max = 0; n->unit_sys = USER_UNIT_NONE; - fill_vn_i(n->unit_type, NUM_MAX_ELEMENTS, B_UNIT_NONE); + copy_vn_i(n->unit_type, NUM_MAX_ELEMENTS, B_UNIT_NONE); n->unit_use_radians = false; n->flag = 0; - fill_vn_short(n->val_flag, NUM_MAX_ELEMENTS, 0); + copy_vn_short(n->val_flag, NUM_MAX_ELEMENTS, 0); zero_v3(n->val); - fill_vn_fl(n->val_org, NUM_MAX_ELEMENTS, 0.0f); - fill_vn_fl(n->val_inc, NUM_MAX_ELEMENTS, 1.0f); + copy_vn_fl(n->val_org, NUM_MAX_ELEMENTS, 0.0f); + copy_vn_fl(n->val_inc, NUM_MAX_ELEMENTS, 1.0f); n->idx = 0; n->str[0] = '\0'; diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 2ec7fe677ae..37070a37c05 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -2120,7 +2120,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo /* mark 1 vertex as being hit */ hitv = BLI_array_alloca(hitv, hit.efa->len); hituv = BLI_array_alloca(hituv, hit.efa->len); - fill_vn_i(hitv, hit.efa->len, 0xFFFFFFFF); + copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF); hitv[hit.lindex] = BM_elem_index_get(hit.l->v); hituv[hit.lindex] = hit.luv->uv; @@ -2137,7 +2137,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo /* mark 2 edge vertices as being hit */ hitv = BLI_array_alloca(hitv, hit.efa->len); hituv = BLI_array_alloca(hituv, hit.efa->len); - fill_vn_i(hitv, hit.efa->len, 0xFFFFFFFF); + copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF); hitv[hit.lindex] = BM_elem_index_get(hit.l->v); hitv[(hit.lindex + 1) % hit.efa->len] = BM_elem_index_get(hit.l->next->v); diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c index 4d58642e9c4..62097635296 100644 --- a/source/blender/imbuf/intern/tiff.c +++ b/source/blender/imbuf/intern/tiff.c @@ -454,7 +454,7 @@ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image) if (bitspersample == 32) { if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */ - fill_vn_fl(fbuf, ibuf->x, 1.0f); + copy_vn_fl(fbuf, ibuf->x, 1.0f); else if (chan >= spp) /* for grayscale, duplicate first channel into G and B */ success |= TIFFReadScanline(image, fbuf, row, 0); else @@ -464,7 +464,7 @@ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image) } else if (bitspersample == 16) { if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */ - fill_vn_ushort(sbuf, ibuf->x, 65535); + copy_vn_ushort(sbuf, ibuf->x, 65535); else if (chan >= spp) /* for grayscale, duplicate first channel into G and B */ success |= TIFFReadScanline(image, fbuf, row, 0); else diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 92f8ad62924..8bb3e9c265b 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1387,7 +1387,7 @@ static void rna_Object_boundbox_get(PointerRNA *ptr, float *values) memcpy(values, bb->vec, sizeof(bb->vec)); } else { - fill_vn_fl(values, sizeof(bb->vec) / sizeof(float), 0.0f); + copy_vn_fl(values, sizeof(bb->vec) / sizeof(float), 0.0f); } } diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 8ebee0dc1b4..44660b15c3c 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -364,22 +364,22 @@ static void dm_merge_transform( /* set origindex */ index_orig = result->getVertDataArray(result, CD_ORIGINDEX); if (index_orig) { - fill_vn_i(index_orig + cap_verts_index, cap_nverts, ORIGINDEX_NONE); + copy_vn_i(index_orig + cap_verts_index, cap_nverts, ORIGINDEX_NONE); } index_orig = result->getEdgeDataArray(result, CD_ORIGINDEX); if (index_orig) { - fill_vn_i(index_orig + cap_edges_index, cap_nedges, ORIGINDEX_NONE); + copy_vn_i(index_orig + cap_edges_index, cap_nedges, ORIGINDEX_NONE); } index_orig = result->getPolyDataArray(result, CD_ORIGINDEX); if (index_orig) { - fill_vn_i(index_orig + cap_polys_index, cap_npolys, ORIGINDEX_NONE); + copy_vn_i(index_orig + cap_polys_index, cap_npolys, ORIGINDEX_NONE); } index_orig = result->getLoopDataArray(result, CD_ORIGINDEX); if (index_orig) { - fill_vn_i(index_orig + cap_loops_index, cap_nloops, ORIGINDEX_NONE); + copy_vn_i(index_orig + cap_loops_index, cap_nloops, ORIGINDEX_NONE); } } @@ -525,7 +525,7 @@ static DerivedMesh *arrayModifier_doArray( if (use_merge) { /* Will need full_doubles_map for handling merge */ full_doubles_map = MEM_mallocN(sizeof(int) * result_nverts, "mod array doubles map"); - fill_vn_i(full_doubles_map, result_nverts, -1); + copy_vn_i(full_doubles_map, result_nverts, -1); } /* copy customdata to original geometry */ diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index 295f303974d..162f45b4e91 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -391,7 +391,7 @@ static void smooth_verts( smooth_weights); } else { - fill_vn_fl(smooth_weights, (int)numVerts, 1.0f); + copy_vn_fl(smooth_weights, (int)numVerts, 1.0f); } if (csmd->flag & MOD_CORRECTIVESMOOTH_PIN_BOUNDARY) { diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 50b1404a8e5..5ebb3f98f6c 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -1801,7 +1801,7 @@ static void skin_set_orig_indices(DerivedMesh *dm) totpoly = dm->getNumPolys(dm); orig = CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, totpoly); - fill_vn_i(orig, totpoly, ORIGINDEX_NONE); + copy_vn_i(orig, totpoly, ORIGINDEX_NONE); } /* diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index c96080d8cf9..fdba8e54a98 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -298,7 +298,7 @@ static DerivedMesh *applyModifier( /* save doing 2 loops here... */ #if 0 - fill_vn_i(edge_users, numEdges, INVALID_UNUSED); + copy_vn_i(edge_users, numEdges, INVALID_UNUSED); #endif for (eidx = 0, ed = orig_medge; eidx < numEdges; eidx++, ed++) { @@ -505,7 +505,7 @@ static DerivedMesh *applyModifier( unsigned int i; vert_lens = MEM_mallocN(sizeof(float) * numVerts, "vert_lens"); - fill_vn_fl(vert_lens, (int)numVerts, FLT_MAX); + copy_vn_fl(vert_lens, (int)numVerts, FLT_MAX); for (i = 0; i < numEdges; i++) { const float ed_len_sq = len_squared_v3v3(mvert[medge[i].v1].co, mvert[medge[i].v2].co); vert_lens[medge[i].v1] = min_ff(vert_lens[medge[i].v1], ed_len_sq); @@ -672,7 +672,7 @@ static DerivedMesh *applyModifier( float *vert_lens_sq = MEM_mallocN(sizeof(float) * numVerts, "vert_lens"); const float offset = fabsf(smd->offset) * smd->offset_clamp; const float offset_sq = offset * offset; - fill_vn_fl(vert_lens_sq, (int)numVerts, FLT_MAX); + copy_vn_fl(vert_lens_sq, (int)numVerts, FLT_MAX); for (i = 0; i < numEdges; i++) { const float ed_len = len_squared_v3v3(mvert[medge[i].v1].co, mvert[medge[i].v2].co); vert_lens_sq[medge[i].v1] = min_ff(vert_lens_sq[medge[i].v1], ed_len); diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 67905f8e340..91e2a635400 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -1858,7 +1858,7 @@ static PyObject *Matrix_zero(MatrixObject *self) if (BaseMath_Prepare_ForWrite(self) == -1) return NULL; - fill_vn_fl(self->matrix, self->num_col * self->num_row, 0.0f); + copy_vn_fl(self->matrix, self->num_col * self->num_row, 0.0f); if (BaseMath_WriteCallback(self) == -1) return NULL; diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index a33b55c35dc..3d7a505eb12 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -76,7 +76,7 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } - fill_vn_fl(vec, size, 0.0f); + copy_vn_fl(vec, size, 0.0f); break; case 1: if ((size = mathutils_array_parse_alloc(&vec, 2, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1) { @@ -142,7 +142,7 @@ static PyObject *C_Vector_Fill(PyObject *cls, PyObject *args) return NULL; } - fill_vn_fl(vec, size, fill); + copy_vn_fl(vec, size, fill); return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); } @@ -339,7 +339,7 @@ static PyObject *Vector_zero(VectorObject *self) if (BaseMath_Prepare_ForWrite(self) == -1) return NULL; - fill_vn_fl(self->vec, self->size, 0.0f); + copy_vn_fl(self->vec, self->size, 0.0f); if (BaseMath_WriteCallback(self) == -1) return NULL; @@ -426,7 +426,7 @@ static PyObject *Vector_resize(VectorObject *self, PyObject *value) /* If the vector has increased in length, set all new elements to 0.0f */ if (size > self->size) { - fill_vn_fl(self->vec + self->size, size - self->size, 0.0f); + copy_vn_fl(self->vec + self->size, size - self->size, 0.0f); } self->size = size; @@ -465,7 +465,7 @@ static PyObject *Vector_resized(VectorObject *self, PyObject *value) return NULL; } - fill_vn_fl(vec, size, 0.0f); + copy_vn_fl(vec, size, 0.0f); memcpy(vec, self->vec, self->size * sizeof(float)); return Vector_CreatePyObject_alloc(vec, size, NULL); @@ -2236,7 +2236,7 @@ static int Vector_length_set(VectorObject *self, PyObject *value) return -1; } if (param == 0.0) { - fill_vn_fl(self->vec, self->size, 0.0f); + copy_vn_fl(self->vec, self->size, 0.0f); return 0; } @@ -3030,7 +3030,7 @@ PyObject *Vector_CreatePyObject( memcpy(self->vec, vec, size * sizeof(float)); } else { /* new empty */ - fill_vn_fl(self->vec, size, 0.0f); + copy_vn_fl(self->vec, size, 0.0f); if (size == 4) { /* do the homogeneous thing */ self->vec[3] = 1.0f; } -- cgit v1.2.3 From d01b226870c4ace33024e7643d41fb5a7443c310 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Tue, 5 May 2015 10:38:45 +0200 Subject: Cleanup: Remove leftover from Distorted Noise node in XML reader. --- intern/cycles/app/cycles_xml.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index b47f20b22a9..1cfc8145b0f 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -503,10 +503,6 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug xml_read_int(&magic->depth, node, "depth"); snode = magic; } - else if(string_iequals(node.name(), "noise_texture")) { - NoiseTextureNode *dist = new NoiseTextureNode(); - snode = dist; - } else if(string_iequals(node.name(), "wave_texture")) { WaveTextureNode *wave = new WaveTextureNode(); xml_read_enum(&wave->type, WaveTextureNode::type_enum, node, "type"); -- cgit v1.2.3 From b5e96530353ef22d184a60cd2b59a5e451ee211f Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Tue, 5 May 2015 15:18:29 +0200 Subject: BGE: Remove function DisableCcdPhysicsController and EnableCcdPhysicsController in CcdPhysicsEnvironment Replace EnableCcdPhysicsController by AddCcdPhysicsController and DisableCcdPhysicsController by RemoveCcdPhysicsController. Tested with compound shapes and collision sensors. Reviewers:agoose77, ideasman42 --- .../Physics/Bullet/CcdPhysicsController.cpp | 4 +- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 71 +++++----------------- .../Physics/Bullet/CcdPhysicsEnvironment.h | 4 -- 3 files changed, 18 insertions(+), 61 deletions(-) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 0a71c0a7aac..3ed01a402ed 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -1627,7 +1627,7 @@ void CcdPhysicsController::AddCompoundChild(PHY_IPhysicsController* child) // must update the broadphase cache, GetPhysicsEnvironment()->RefreshCcdPhysicsController(this); // remove the children - GetPhysicsEnvironment()->DisableCcdPhysicsController(childCtrl); + GetPhysicsEnvironment()->RemoveCcdPhysicsController(childCtrl); } /* Reverse function of the above, it will remove a shape from a compound shape @@ -1683,7 +1683,7 @@ void CcdPhysicsController::RemoveCompoundChild(PHY_IPhysicsController* child) // must update the broadphase cache, GetPhysicsEnvironment()->RefreshCcdPhysicsController(this); // reactivate the children - GetPhysicsEnvironment()->EnableCcdPhysicsController(childCtrl); + GetPhysicsEnvironment()->AddCcdPhysicsController(childCtrl); } PHY_IPhysicsController* CcdPhysicsController::GetReplica() diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 0ecb79d91ea..c81d9c7de94 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -461,6 +461,11 @@ m_scalingPropagated(false) void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl) { + // the controller is already added we do nothing + if (!m_controllers.insert(ctrl).second) { + return; + } + btRigidBody* body = ctrl->GetRigidBody(); btCollisionObject* obj = ctrl->GetCollisionObject(); @@ -469,8 +474,6 @@ void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl) if (body) body->setGravity( m_gravity ); - m_controllers.insert(ctrl); - if (body) { //use explicit group/filter for finer control over collision in bullet => near/radar sensor @@ -505,6 +508,15 @@ void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl) bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctrl) { + // the controller is still used as sensor + if (ctrl->m_registerCount != 0) + printf("Warning: removing controller with non-zero m_registerCount: %d\n", ctrl->m_registerCount); + + // if the physics controller is already removed we do nothing + if (!m_controllers.erase(ctrl) || !m_triggerControllers.erase(ctrl)) { + return false; + } + //also remove constraint btRigidBody* body = ctrl->GetRigidBody(); if (body) @@ -555,13 +567,6 @@ bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctr } } } - if (ctrl->m_registerCount != 0) - printf("Warning: removing controller with non-zero m_registerCount: %d\n", ctrl->m_registerCount); - - //remove it from the triggers - m_triggerControllers.erase(ctrl); - - return (m_controllers.erase(ctrl) != 0); } void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask) @@ -597,43 +602,6 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr ctrl->m_cci.m_collisionFlags = newCollisionFlags; } -void CcdPhysicsEnvironment::EnableCcdPhysicsController(CcdPhysicsController* ctrl) -{ - if (m_controllers.insert(ctrl).second) - { - btCollisionObject* obj = ctrl->GetCollisionObject(); - obj->setUserPointer(ctrl); - // update the position of the object from the user - if (ctrl->GetMotionState()) - { - btTransform xform = CcdPhysicsController::GetTransformFromMotionState(ctrl->GetMotionState()); - ctrl->SetCenterOfMassTransform(xform); - } - m_dynamicsWorld->addCollisionObject(obj, - ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); - } -} - -void CcdPhysicsEnvironment::DisableCcdPhysicsController(CcdPhysicsController* ctrl) -{ - if (m_controllers.erase(ctrl)) - { - btRigidBody* body = ctrl->GetRigidBody(); - if (body) - { - m_dynamicsWorld->removeRigidBody(body); - } else - { - if (ctrl->GetSoftBody()) - { - } else - { - m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject()); - } - } - } -} - void CcdPhysicsEnvironment::RefreshCcdPhysicsController(CcdPhysicsController* ctrl) { btCollisionObject* obj = ctrl->GetCollisionObject(); @@ -2204,15 +2172,8 @@ btTypedConstraint* CcdPhysicsEnvironment::GetConstraintById(int constraintId) void CcdPhysicsEnvironment::AddSensor(PHY_IPhysicsController* ctrl) { - CcdPhysicsController* ctrl1 = (CcdPhysicsController* )ctrl; - // addSensor() is a "light" function for bullet because it is used - // dynamically when the sensor is activated. Use enableCcdPhysicsController() instead - //if (m_controllers.insert(ctrl1).second) - //{ - // addCcdPhysicsController(ctrl1); - //} - EnableCcdPhysicsController(ctrl1); + AddCcdPhysicsController(ctrl1); } bool CcdPhysicsEnvironment::RemoveCollisionCallback(PHY_IPhysicsController* ctrl) @@ -2227,7 +2188,7 @@ bool CcdPhysicsEnvironment::RemoveCollisionCallback(PHY_IPhysicsController* ctrl void CcdPhysicsEnvironment::RemoveSensor(PHY_IPhysicsController* ctrl) { - DisableCcdPhysicsController((CcdPhysicsController*)ctrl); + RemoveCcdPhysicsController((CcdPhysicsController*)ctrl); } void CcdPhysicsEnvironment::AddTouchCallback(int response_class, PHY_ResponseCallback callback, void *user) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 3b1fe63db0b..1fa97d9ab22 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -221,10 +221,6 @@ protected: void UpdateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask); - void DisableCcdPhysicsController(CcdPhysicsController* ctrl); - - void EnableCcdPhysicsController(CcdPhysicsController* ctrl); - void RefreshCcdPhysicsController(CcdPhysicsController* ctrl); bool IsActiveCcdPhysicsController(CcdPhysicsController *ctrl); -- cgit v1.2.3 From 35c67d6750627fd19a36dd3b527b57d19704334d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 May 2015 02:22:00 +1000 Subject: Fix reading uninitialized memory finding paths --- source/blender/blenkernel/intern/bpath.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 7c2b0a8a840..265cb0aa403 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -370,6 +370,9 @@ static bool rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR], BLI_join_dirfile(path_src, sizeof(path_src), path_dir, path_file); + /* so functions can check old value */ + BLI_strncpy(path_dst, path_src, FILE_MAX); + if (absbase) { BLI_path_abs(path_src, absbase); } -- cgit v1.2.3 From 962d53e144149ab75ea28327ccbb22e91fa5d91e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 May 2015 03:23:20 +1000 Subject: Workaround ld.gold failing with msgfmt --- intern/locale/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/intern/locale/CMakeLists.txt b/intern/locale/CMakeLists.txt index 5d933f326f7..6896702fcbf 100644 --- a/intern/locale/CMakeLists.txt +++ b/intern/locale/CMakeLists.txt @@ -63,6 +63,12 @@ blender_add_lib(bf_intern_locale "${SRC}" "${INC}" "${INC_SYS}") # ----------------------------------------------------------------------------- # Build msgfmt executable + +if(CMAKE_COMPILER_IS_GNUCC) + # workaroud ld.gold linker bug + string(REPLACE "-fuse-ld=gold" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +endif() + set(MSFFMT_SRC msgfmt.cc ) -- cgit v1.2.3 From 4616a7a4d3656049f8aef1170a9715c19a2aeed1 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Tue, 5 May 2015 19:42:27 +0200 Subject: BGE: Fix collision callbacks for compound controllers It fix some mistakes in b5e96530353ef22d184a60cd2b59a5e451ee211f and made a more safety behavior for collision callbacks used in compound controllers during adding and removing. --- .../Physics/Bullet/CcdPhysicsController.h | 5 +++++ .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 26 +++++++++++++++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 4fcdc70c5a8..e3172e7fc45 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -515,6 +515,11 @@ protected: return (--m_registerCount == 0) ? true : false; } + bool Registered() const + { + return (m_registerCount != 0); + } + void addCcdConstraintRef(btTypedConstraint* c); void removeCcdConstraintRef(btTypedConstraint* c); btTypedConstraint* getCcdConstraintRef(int index); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index c81d9c7de94..37cc26f6364 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -466,6 +466,14 @@ void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl) return; } + /* In the case of compound child controller (see also RemoveCcdPhysicsController) + * we add the controller to the trigger controlers list : m_triggerControllers + * if it use collision callbacks. + */ + if (ctrl->Registered()) { + m_triggerControllers.insert(ctrl); + } + btRigidBody* body = ctrl->GetRigidBody(); btCollisionObject* obj = ctrl->GetCollisionObject(); @@ -508,15 +516,21 @@ void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl) bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctrl) { - // the controller is still used as sensor - if (ctrl->m_registerCount != 0) - printf("Warning: removing controller with non-zero m_registerCount: %d\n", ctrl->m_registerCount); - // if the physics controller is already removed we do nothing - if (!m_controllers.erase(ctrl) || !m_triggerControllers.erase(ctrl)) { + if (!m_controllers.erase(ctrl)) { return false; } + /* In the case of compound child controller which use collision callbacks + * we remove it from the m_triggerControllers list but leave m_registerCount + * to know in AddCcdPhysicsController if we have to add it in m_triggerControllers + * and to avoid an useless added in RequestCollisionCallback, indeed we can't register + * more than one time a controller. + */ + if (ctrl->Registered()) { + m_triggerControllers.erase(ctrl); + } + //also remove constraint btRigidBody* body = ctrl->GetRigidBody(); if (body) @@ -567,6 +581,8 @@ bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctr } } } + + return true; } void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask) -- cgit v1.2.3 From b45ad4b2143f29430eebdc37014172b216d71720 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 6 May 2015 00:01:16 +0500 Subject: Cycles: Fix for wrong clamp usage in fast math --- intern/cycles/util/util_math_fast.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/intern/cycles/util/util_math_fast.h b/intern/cycles/util/util_math_fast.h index 1acceee22a5..c1a1be603f4 100644 --- a/intern/cycles/util/util_math_fast.h +++ b/intern/cycles/util/util_math_fast.h @@ -360,7 +360,7 @@ ccl_device float fast_log2f(float x) { /* NOTE: clamp to avoid special cases and make result "safe" from large * negative values/nans. */ - clamp(x, FLT_MIN, FLT_MAX); + x = clamp(x, FLT_MIN, FLT_MAX); unsigned bits = __float_as_uint(x); int exponent = (int)(bits >> 23) - 127; float f = __uint_as_float((bits & 0x007FFFFF) | 0x3f800000) - 1.0f; @@ -402,7 +402,7 @@ ccl_device float fast_logb(float x) { /* Don't bother with denormals. */ x = fabsf(x); - clamp(x, FLT_MIN, FLT_MAX); + x = clamp(x, FLT_MIN, FLT_MAX); unsigned bits = __float_as_uint(x); return (int)(bits >> 23) - 127; } @@ -410,7 +410,7 @@ ccl_device float fast_logb(float x) ccl_device float fast_exp2f(float x) { /* Clamp to safe range for final addition. */ - clamp(x, -126.0f, 126.0f); + x = clamp(x, -126.0f, 126.0f); /* Range reduction. */ int m = (int)x; x -= m; x = 1.0f - (1.0f - x); /* Crush denormals (does not affect max ulps!). */ -- cgit v1.2.3 From 1d0f1a1ec9c098f3b1307b13b0c98edbca5469df Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 5 May 2015 21:39:34 +0200 Subject: Fix T44593: particle volume distribution not working with large meshes. --- source/blender/blenkernel/intern/particle_distribute.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 4a2540e385b..28a2d0556d7 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -490,7 +490,7 @@ static void distribute_from_faces_exec(ParticleTask *thread, ParticleData *pa, i static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa, int p) { ParticleThreadContext *ctx= thread->ctx; DerivedMesh *dm= ctx->dm; - float *v1, *v2, *v3, *v4, nor[3], co1[3], co2[3]; + float *v1, *v2, *v3, *v4, nor[3], co[3]; float cur_d, min_d, randu, randv; int distr= ctx->distr; int i, intersect, tot; @@ -530,14 +530,12 @@ static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa, /* experimental */ tot=dm->getNumTessFaces(dm); - psys_interpolate_face(mvert,mface,0,0,pa->fuv,co1,nor,0,0,0,0); + psys_interpolate_face(mvert,mface,0,0,pa->fuv,co,nor,0,0,0,0); normalize_v3(nor); - mul_v3_fl(nor,-100.0); + negate_v3(nor); - add_v3_v3v3(co2,co1,nor); - - min_d=2.0; + min_d=FLT_MAX; intersect=0; for (i=0,mface=dm->getTessFaceDataArray(dm,CD_MFACE); iv2].co; v3=mvert[mface->v3].co; - if (isect_line_tri_v3(co1, co2, v2, v3, v1, &cur_d, 0)) { + if (isect_ray_tri_v3(co, nor, v2, v3, v1, &cur_d, 0)) { if (cur_dfoffset=cur_d*50.0f; /* to the middle of volume */ + pa->foffset=cur_d*0.5f; /* to the middle of volume */ intersect=1; } } if (mface->v4) { v4=mvert[mface->v4].co; - if (isect_line_tri_v3(co1, co2, v4, v1, v3, &cur_d, 0)) { + if (isect_ray_tri_v3(co, nor, v4, v1, v3, &cur_d, 0)) { if (cur_dfoffset=cur_d*50.0f; /* to the middle of volume */ + pa->foffset=cur_d*0.5f; /* to the middle of volume */ intersect=1; } } -- cgit v1.2.3 From c641a5563fa034b8faa4d1aaeba1258f9df2e19b Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 5 May 2015 21:52:09 +0200 Subject: Fix T44612: add support for mouse button 6 and 7 on OS X. --- intern/ghost/intern/GHOST_SystemCocoa.mm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index ed1200b967c..bdcaadba2f3 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -73,6 +73,10 @@ static GHOST_TButtonMask convertButton(int button) return GHOST_kButtonMaskButton4; case 4: return GHOST_kButtonMaskButton5; + case 5: + return GHOST_kButtonMaskButton6; + case 6: + return GHOST_kButtonMaskButton7; default: return GHOST_kButtonMaskLeft; } -- cgit v1.2.3 From e00142bfa73ace6ba2e66923e3c36b08b72c57ed Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 May 2015 06:05:31 +1000 Subject: BLI_path: add PATH search utility functions --- source/blender/blenkernel/intern/appdir.c | 87 +++---------------------- source/blender/blenlib/BLI_path_util.h | 5 ++ source/blender/blenlib/intern/path_util.c | 103 ++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 79 deletions(-) diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 60e81003c40..33ef53eb2e0 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -500,54 +500,6 @@ const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, con /* -------------------------------------------------------------------- */ /* Preset paths */ -/** - * Tries appending each of the semicolon-separated extensions in the PATHEXT - * environment variable (Windows-only) onto *name in turn until such a file is found. - * Returns success/failure. - */ -static int add_win32_extension(char *name) -{ - int retval = 0; - int type; - - type = BLI_exists(name); - if ((type == 0) || S_ISDIR(type)) { -#ifdef _WIN32 - char filename[FILE_MAX]; - char ext[FILE_MAX]; - const char *extensions = getenv("PATHEXT"); - if (extensions) { - char *temp; - do { - strcpy(filename, name); - temp = strstr(extensions, ";"); - if (temp) { - strncpy(ext, extensions, temp - extensions); - ext[temp - extensions] = 0; - extensions = temp + 1; - strcat(filename, ext); - } - else { - strcat(filename, extensions); - } - - type = BLI_exists(filename); - if (type && (!S_ISDIR(type))) { - retval = 1; - strcpy(name, filename); - break; - } - } while (temp); - } -#endif - } - else { - retval = 1; - } - - return (retval); -} - /** * Checks if name is a fully qualified filename to an executable. * If not it searches $PATH for the file. On Windows it also @@ -562,16 +514,8 @@ static int add_win32_extension(char *name) */ static void bli_where_am_i(char *fullname, const size_t maxlen, const char *name) { - char filename[FILE_MAX]; - const char *path = NULL, *temp; - -#ifdef _WIN32 - const char *separator = ";"; -#else - const char *separator = ":"; -#endif + const char *path = NULL; - #ifdef WITH_BINRELOC /* linux uses binreloc since argv[0] is not reliable, call br_init( NULL ) first */ path = br_find_exe(NULL); @@ -611,34 +555,19 @@ static void bli_where_am_i(char *fullname, const size_t maxlen, const char *name else BLI_join_dirfile(fullname, maxlen, wdir, name); - add_win32_extension(fullname); /* XXX, doesnt respect length */ +#ifdef _WIN32 + BLI_path_binary_extensions_add_win32(fullname, maxlen); +#endif } else if (BLI_last_slash(name)) { // full path BLI_strncpy(fullname, name, maxlen); - add_win32_extension(fullname); +#ifdef _WIN32 + BLI_path_binary_extensions_add_win32(fullname, maxlen); +#endif } else { - // search for binary in $PATH - path = getenv("PATH"); - if (path) { - do { - temp = strstr(path, separator); - if (temp) { - strncpy(filename, path, temp - path); - filename[temp - path] = 0; - path = temp + 1; - } - else { - strncpy(filename, path, sizeof(filename)); - } - BLI_path_append(fullname, maxlen, name); - if (add_win32_extension(filename)) { - BLI_strncpy(fullname, filename, maxlen); - break; - } - } while (temp); - } + BLI_path_binary_search(fullname, maxlen, name); } #if defined(DEBUG) if (!STREQ(name, fullname)) { diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index c35b01e7f55..0513625772d 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -78,6 +78,11 @@ void BLI_del_slash(char *string) ATTR_NONNULL(); const char *BLI_first_slash(const char *string) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; void BLI_path_native_slash(char *path) ATTR_NONNULL(); +#ifdef _WIN32 +bool BLI_path_binary_extensions_add_win32(char *name, const size_t maxlen); +#endif +bool BLI_path_binary_search(char *fullname, const size_t maxlen, const char *name); + void BLI_getlastdir(const char *dir, char *last, const size_t maxlen); bool BLI_testextensie(const char *str, const char *ext) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; bool BLI_testextensie_n(const char *str, ...) ATTR_NONNULL(1) ATTR_SENTINEL(0); diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 58b01f7e140..67b28e82796 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1020,6 +1020,109 @@ bool BLI_path_cwd(char *path) return wasrelative; } +#ifdef _WIN32 +/** + * Tries appending each of the semicolon-separated extensions in the PATHEXT + * environment variable (Windows-only) onto *name in turn until such a file is found. + * Returns success/failure. + */ +bool BLI_path_binary_extensions_add_win32(char *name, const size_t maxlen) +{ + bool retval = false; + int type; + + type = BLI_exists(name); + if ((type == 0) || S_ISDIR(type)) { + char filename[FILE_MAX]; + char ext[FILE_MAX]; + const char *extensions = getenv("PATHEXT"); + if (extensions) { + const char *temp; + do { + strcpy(filename, name); + temp = strchr(extensions, ';'); + if (temp) { + strncpy(ext, extensions, temp - extensions); + ext[temp - extensions] = 0; + extensions = temp + 1; + strcat(filename, ext); + } + else { + strcat(filename, extensions); + } + + type = BLI_exists(filename); + if (type && (!S_ISDIR(type))) { + retval = true; + BLI_strncpy(name, filename, maxlen); + break; + } + } while (temp); + } + } + else { + retval = true; + } + + return retval; +} +#endif /* WIN32 */ + +/** + * Search for a binary (executable) + */ +bool BLI_path_binary_search( + char *fullname, const size_t maxlen, + const char *name) +{ + const char *path; + bool retval = false; + +#ifdef _WIN32 + const char separator = ';'; +#else + const char separator = ':'; +#endif + + path = getenv("PATH"); + if (path) { + char filename[FILE_MAX]; + const char *temp; + + do { + temp = strchr(path, separator); + if (temp) { + strncpy(filename, path, temp - path); + filename[temp - path] = 0; + path = temp + 1; + } + else { + strncpy(filename, path, sizeof(filename)); + } + + BLI_path_append(filename, maxlen, name); + if ( +#ifdef _WIN32 + BLI_path_binary_extensions_add_win32(filename, maxlen) +#else + BLI_exists(filename) +#endif + ) + { + BLI_strncpy(fullname, filename, maxlen); + retval = true; + break; + } + } while (temp); + } + + if (retval == false) { + *fullname = '\0'; + } + + return retval; +} + /** * Copies into *last the part of *dir following the second-last slash. */ -- cgit v1.2.3 From c246e0c3b6bfd4c57d12f8c3b232968b59757e26 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 May 2015 06:34:19 +1000 Subject: Prefer name 'program' over 'binary' binary-search is confusing! --- source/blender/blenkernel/intern/appdir.c | 6 +++--- source/blender/blenlib/BLI_path_util.h | 4 ++-- source/blender/blenlib/intern/path_util.c | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 33ef53eb2e0..61aa0eb617a 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -556,18 +556,18 @@ static void bli_where_am_i(char *fullname, const size_t maxlen, const char *name BLI_join_dirfile(fullname, maxlen, wdir, name); #ifdef _WIN32 - BLI_path_binary_extensions_add_win32(fullname, maxlen); + BLI_path_program_extensions_add_win32(fullname, maxlen); #endif } else if (BLI_last_slash(name)) { // full path BLI_strncpy(fullname, name, maxlen); #ifdef _WIN32 - BLI_path_binary_extensions_add_win32(fullname, maxlen); + BLI_path_program_extensions_add_win32(fullname, maxlen); #endif } else { - BLI_path_binary_search(fullname, maxlen, name); + BLI_path_program_search(fullname, maxlen, name); } #if defined(DEBUG) if (!STREQ(name, fullname)) { diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 0513625772d..30b57c5f41b 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -79,9 +79,9 @@ const char *BLI_first_slash(const char *string) ATTR_NONNULL() ATTR_WARN_UNUSED_ void BLI_path_native_slash(char *path) ATTR_NONNULL(); #ifdef _WIN32 -bool BLI_path_binary_extensions_add_win32(char *name, const size_t maxlen); +bool BLI_path_program_extensions_add_win32(char *name, const size_t maxlen); #endif -bool BLI_path_binary_search(char *fullname, const size_t maxlen, const char *name); +bool BLI_path_program_search(char *fullname, const size_t maxlen, const char *name); void BLI_getlastdir(const char *dir, char *last, const size_t maxlen); bool BLI_testextensie(const char *str, const char *ext) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 67b28e82796..b079478f397 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1026,7 +1026,7 @@ bool BLI_path_cwd(char *path) * environment variable (Windows-only) onto *name in turn until such a file is found. * Returns success/failure. */ -bool BLI_path_binary_extensions_add_win32(char *name, const size_t maxlen) +bool BLI_path_program_extensions_add_win32(char *name, const size_t maxlen) { bool retval = false; int type; @@ -1071,7 +1071,7 @@ bool BLI_path_binary_extensions_add_win32(char *name, const size_t maxlen) /** * Search for a binary (executable) */ -bool BLI_path_binary_search( +bool BLI_path_program_search( char *fullname, const size_t maxlen, const char *name) { @@ -1103,7 +1103,7 @@ bool BLI_path_binary_search( BLI_path_append(filename, maxlen, name); if ( #ifdef _WIN32 - BLI_path_binary_extensions_add_win32(filename, maxlen) + BLI_path_program_extensions_add_win32(filename, maxlen) #else BLI_exists(filename) #endif -- cgit v1.2.3 From bc2f77e1da8f4a4e9074223824c9d3d29fc87a7b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 May 2015 11:07:15 +1000 Subject: Add bpy.app.binary_path_python Access to the python binary distributed with Blender, fallback to system python executable (matching Blender's version). --- source/blender/blenkernel/BKE_appdir.h | 5 ++++ source/blender/blenkernel/intern/appdir.c | 39 +++++++++++++++++++++++++++++++ source/blender/python/intern/bpy_app.c | 31 +++++++++++++++++++++++- 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h index 5e42f17be03..077fe2a629c 100644 --- a/source/blender/blenkernel/BKE_appdir.h +++ b/source/blender/blenkernel/BKE_appdir.h @@ -38,6 +38,11 @@ void BKE_appdir_program_path_init(const char *argv0); const char *BKE_appdir_program_path(void); const char *BKE_appdir_program_dir(void); +/* find python executable */ +bool BKE_appdir_program_python_search( + char *fullpath, const size_t fullpath_len, + const int version_major, const int version_minor); + /* Initialize path to temporary directory. */ void BKE_tempdir_init(char *userdir); void BKE_tempdir_system_init(char *dir); diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 61aa0eb617a..4c7cda95ad1 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -599,6 +599,45 @@ const char *BKE_appdir_program_dir(void) return bprogdir; } +bool BKE_appdir_program_python_search( + char *fullpath, const size_t fullpath_len, + const int version_major, const int version_minor) +{ + const char *basename = "python"; + bool is_found = false; + + { + const char *python_bin_dir = BKE_appdir_folder_id(BLENDER_SYSTEM_PYTHON, "bin"); + if (python_bin_dir) { + BLI_join_dirfile(fullpath, fullpath_len, python_bin_dir, basename); + if ( +#ifdef _WIN32 + BLI_path_program_extensions_add_win32(fullpath, fullpath_len) +#else + BLI_exists(fullpath) +#endif + ) + { + is_found = true; + } + } + } + + if (is_found == false) { + char python_ver[16]; + BLI_snprintf(python_ver, sizeof(python_ver), "%s%d.%d", basename, version_major, version_minor); + if (BLI_path_program_search(fullpath, fullpath_len, python_ver)) { + is_found = true; + } + } + + if (is_found == false) { + *fullpath = '\0'; + } + + return is_found; +} + /** * Gets the temp directory when blender first runs. * If the default path is not found, use try $TEMP diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index 04ab34efeb4..1cf0c44fd87 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -220,6 +220,33 @@ static int bpy_app_debug_set(PyObject *UNUSED(self), PyObject *value, void *clos return 0; } + + +PyDoc_STRVAR(bpy_app_binary_path_python_doc, +"String, the path to the python executable (read-only)" +); +static PyObject *bpy_app_binary_path_python_get(PyObject *UNUSED(self), void *UNUSED(closure)) +{ + /* refcount is held in BlenderAppType.tp_dict */ + static PyObject *ret = NULL; + + if (ret == NULL) { + /* only run once */ + char fullpath[1024]; + BKE_appdir_program_python_search( + fullpath, sizeof(fullpath), + PY_MAJOR_VERSION, PY_MINOR_VERSION); + ret = PyC_UnicodeFromByte(fullpath); + PyDict_SetItemString(BlenderAppType.tp_dict, "binary_path_python", ret); + } + else { + Py_INCREF(ret); + } + + return ret; + +} + PyDoc_STRVAR(bpy_app_debug_value_doc, "Int, number which can be set to non-zero values for testing purposes" ); @@ -287,7 +314,9 @@ static PyGetSetDef bpy_app_getsets[] = { {(char *)"debug_wm", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_WM}, {(char *)"debug_depsgraph", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH}, {(char *)"debug_simdata", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_SIMDATA}, - {(char *)"debug_gpumem", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_GPU_MEM}, + {(char *)"debug_gpumem", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_GPU_MEM}, + + {(char *)"binary_path_python", bpy_app_binary_path_python_get, NULL, (char *)bpy_app_binary_path_python_doc, NULL}, {(char *)"debug_value", bpy_app_debug_value_get, bpy_app_debug_value_set, (char *)bpy_app_debug_value_doc, NULL}, {(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL}, -- cgit v1.2.3 From 0abb6f3ef0b10ca372b1d463505b8d7a230efac6 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 6 May 2015 11:46:47 +0200 Subject: Patch D1283 by Alexander Romanov fixes reroute node type update not correct when root reroute node is plugged in a different type of input --- source/blender/nodes/intern/node_common.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c index 0e250dc3aa4..c397af97783 100644 --- a/source/blender/nodes/intern/node_common.c +++ b/source/blender/nodes/intern/node_common.c @@ -50,6 +50,10 @@ #include "node_util.h" #include "NOD_common.h" +enum { + REFINE_FORWARD = 1 << 0, + REFINE_BACKWARD = 1 << 1, +}; /**** Group ****/ @@ -251,7 +255,7 @@ void register_node_type_reroute(void) nodeRegisterType(ntype); } -static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node) +static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node, int flag) { bNodeSocket *input = node->inputs.first; bNodeSocket *output = node->outputs.first; @@ -275,11 +279,14 @@ static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node) if (nodeLinkIsHidden(link)) continue; - if (tonode == node && fromnode->type == NODE_REROUTE && !fromnode->done) - node_reroute_inherit_type_recursive(ntree, fromnode); - - if (fromnode == node && tonode->type == NODE_REROUTE && !tonode->done) - node_reroute_inherit_type_recursive(ntree, tonode); + if (flag & REFINE_FORWARD) { + if (tonode == node && fromnode->type == NODE_REROUTE && !fromnode->done) + node_reroute_inherit_type_recursive(ntree, fromnode, REFINE_FORWARD); + } + if (flag & REFINE_BACKWARD) { + if (fromnode == node && tonode->type == NODE_REROUTE && !tonode->done) + node_reroute_inherit_type_recursive(ntree, tonode, REFINE_BACKWARD); + } } /* determine socket type from unambiguous input/output connection if possible */ @@ -329,7 +336,7 @@ void ntree_update_reroute_nodes(bNodeTree *ntree) for (node = ntree->nodes.first; node; node = node->next) if (node->type == NODE_REROUTE && !node->done) - node_reroute_inherit_type_recursive(ntree, node); + node_reroute_inherit_type_recursive(ntree, node, REFINE_FORWARD | REFINE_BACKWARD); } static bool node_is_connected_to_output_recursive(bNodeTree *ntree, bNode *node) -- cgit v1.2.3 From 69bf3a9e94298912f31398a4df9144d94f5604e5 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 6 May 2015 11:59:39 +0200 Subject: Updating node standard value won't work if node is hidden, patch by Alexander Romanov with minor changes. --- source/blender/blenkernel/intern/node.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 0d375b0dbeb..8ea19b3cde5 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -3082,10 +3082,14 @@ void nodeSynchronizeID(bNode *node, bool copy_to_id) bNodeSocket *sock; Material *ma = (Material *)node->id; int a; + short check_flags = SOCK_UNAVAIL; + + if (!copy_to_id) + check_flags |= SOCK_HIDDEN; /* hrmf, case in loop isn't super fast, but we don't edit 100s of material at same time either! */ for (a = 0, sock = node->inputs.first; sock; sock = sock->next, a++) { - if (!nodeSocketIsHidden(sock)) { + if (!(sock->flag & check_flags)) { if (copy_to_id) { switch (a) { case MAT_IN_COLOR: -- cgit v1.2.3 From 3f04f64eea166528bf850118af07ba601c145d80 Mon Sep 17 00:00:00 2001 From: Martijn Berger Date: Wed, 6 May 2015 12:35:41 +0200 Subject: [cmake] move FindLLVM to its own file --- CMakeLists.txt | 65 ++-------------------- build_files/cmake/Modules/FindLLVM.cmake | 94 ++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 61 deletions(-) create mode 100644 build_files/cmake/Modules/FindLLVM.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index ea1ca3d37b2..ae2c67b59bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1059,70 +1059,13 @@ if(UNIX AND NOT APPLE) endif() endif() - # XXX Maybe most of this section should go into an llvm module? if(WITH_LLVM) + find_package_wrapper(LLVM) - if(LLVM_ROOT_DIR) - if(NOT DEFINED LLVM_VERSION) - find_program(LLVM_CONFIG llvm-config-${LLVM_VERSION} HINTS ${LLVM_ROOT_DIR}/bin NO_CMAKE_PATH) - endif() - if(NOT LLVM_CONFIG) - find_program(LLVM_CONFIG llvm-config HINTS ${LLVM_ROOT_DIR}/bin NO_CMAKE_PATH) - endif() - else() - if(NOT DEFINED LLVM_VERSION) - find_program(LLVM_CONFIG llvm-config-${LLVM_VERSION}) - endif() - if(NOT LLVM_CONFIG) - find_program(LLVM_CONFIG llvm-config) - endif() - endif() - - if(NOT DEFINED LLVM_VERSION) - execute_process(COMMAND ${LLVM_CONFIG} --version - OUTPUT_VARIABLE LLVM_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE) - set(LLVM_VERSION ${LLVM_VERSION} CACHE STRING "Version of LLVM to use") + if(NOT LLVM_FOUND) + set(WITH_LLVM OFF) + message(STATUS "LLVM not found") endif() - if(NOT DEFINED LLVM_ROOT_DIR) - execute_process(COMMAND ${LLVM_CONFIG} --prefix - OUTPUT_VARIABLE LLVM_ROOT_DIR - OUTPUT_STRIP_TRAILING_WHITESPACE) - set(LLVM_ROOT_DIR ${LLVM_ROOT_DIR} CACHE PATH "Path to the LLVM installation") - endif() - if(NOT DEFINED LLVM_LIBPATH) - execute_process(COMMAND ${LLVM_CONFIG} --libdir - OUTPUT_VARIABLE LLVM_LIBPATH - OUTPUT_STRIP_TRAILING_WHITESPACE) - set(LLVM_LIBPATH ${LLVM_LIBPATH} CACHE PATH "Path to the LLVM library path") - mark_as_advanced(LLVM_LIBPATH) - endif() - - if(LLVM_STATIC) - find_library(LLVM_LIBRARY - NAMES LLVMAnalysis # first of a whole bunch of libs to get - PATHS ${LLVM_LIBPATH}) - else() - find_library(LLVM_LIBRARY - NAMES LLVM-${LLVM_VERSION} - PATHS ${LLVM_LIBPATH}) - endif() - - - if(LLVM_LIBRARY AND LLVM_ROOT_DIR AND LLVM_LIBPATH) - if(LLVM_STATIC) - # if static LLVM libraries were requested, use llvm-config to generate - # the list of what libraries we need, and substitute that in the right - # way for LLVM_LIBRARY. - execute_process(COMMAND ${LLVM_CONFIG} --libfiles - OUTPUT_VARIABLE LLVM_LIBRARY - OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REPLACE " " ";" LLVM_LIBRARY "${LLVM_LIBRARY}") - endif() - else() - message(FATAL_ERROR "LLVM not found.") - endif() - endif() if(WITH_LLVM OR WITH_SDL_DYNLOAD) diff --git a/build_files/cmake/Modules/FindLLVM.cmake b/build_files/cmake/Modules/FindLLVM.cmake new file mode 100644 index 00000000000..43791c8df8c --- /dev/null +++ b/build_files/cmake/Modules/FindLLVM.cmake @@ -0,0 +1,94 @@ +# - Find LLVM library +# Find the native LLVM includes and library +# This module defines +# LLVM_INCLUDE_DIRS, where to find LLVM.h, Set when LLVM_INCLUDE_DIR is found. +# LLVM_LIBRARIES, libraries to link against to use LLVM. +# LLVM_ROOT_DIR, The base directory to search for LLVM. +# This can also be an environment variable. +# LLVM_FOUND, If false, do not try to use LLVM. +# +# also defined, but not for general use are +# LLVM_LIBRARY, where to find the LLVM library. + +#============================================================================= +# Copyright 2015 Blender Foundation. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= + +if(LLVM_ROOT_DIR) + if(DEFINED LLVM_VERSION) + find_program(LLVM_CONFIG llvm-config-${LLVM_VERSION} HINTS ${LLVM_ROOT_DIR}/bin NO_CMAKE_PATH) + endif() + if(NOT LLVM_CONFIG) + find_program(LLVM_CONFIG llvm-config HINTS ${LLVM_ROOT_DIR}/bin NO_CMAKE_PATH) + endif() +else() + if(DEFINED LLVM_VERSION) + message(running llvm-config-${LLVM_VERSION}) + find_program(LLVM_CONFIG llvm-config-${LLVM_VERSION}) + endif() + if(NOT LLVM_CONFIG) + find_program(LLVM_CONFIG llvm-config) + endif() +endif() + +if(NOT DEFINED LLVM_VERSION) + execute_process(COMMAND ${LLVM_CONFIG} --version + OUTPUT_VARIABLE LLVM_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(LLVM_VERSION ${LLVM_VERSION} CACHE STRING "Version of LLVM to use") +endif() +if(NOT LLVM_ROOT_DIR) + execute_process(COMMAND ${LLVM_CONFIG} --prefix + OUTPUT_VARIABLE LLVM_ROOT_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(LLVM_ROOT_DIR ${LLVM_ROOT_DIR} CACHE PATH "Path to the LLVM installation") +endif() +if(NOT LLVM_LIBPATH) + execute_process(COMMAND ${LLVM_CONFIG} --libdir + OUTPUT_VARIABLE LLVM_LIBPATH + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(LLVM_LIBPATH ${LLVM_LIBPATH} CACHE PATH "Path to the LLVM library path") + mark_as_advanced(LLVM_LIBPATH) +endif() + +if(LLVM_STATIC) + find_library(LLVM_LIBRARY + NAMES LLVMAnalysis # first of a whole bunch of libs to get + PATHS ${LLVM_LIBPATH}) +else() + find_library(LLVM_LIBRARY + NAMES LLVM-${LLVM_VERSION} + PATHS ${LLVM_LIBPATH}) +endif() + + +if(LLVM_LIBRARY AND LLVM_ROOT_DIR AND LLVM_LIBPATH) + if(LLVM_STATIC) + # if static LLVM libraries were requested, use llvm-config to generate + # the list of what libraries we need, and substitute that in the right + # way for LLVM_LIBRARY. + execute_process(COMMAND ${LLVM_CONFIG} --libfiles + OUTPUT_VARIABLE LLVM_LIBRARY + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_LIBRARY "${LLVM_LIBRARY}") + endif() +endif() + + +# handle the QUIETLY and REQUIRED arguments and set SDL2_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LLVM DEFAULT_MSG + LLVM_LIBRARY) + +MARK_AS_ADVANCED( + LLVM_LIBRARY +) + -- cgit v1.2.3 From 27c3886064a54101ab50f654ebd01a802c679958 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 6 May 2015 12:40:26 +0200 Subject: Cleanup: use functions we already use elsewhere for bone detection instead of the ninja code that we use now. --- .../blender/editors/animation/keyframes_general.c | 37 ++++++++-------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 02e16ff3446..b3dc0021f00 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -559,24 +559,15 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data) * storing the relevant information here helps avoiding crashes if we undo-repaste */ if ((aci->id_type == ID_OB) && (((Object *)aci->id)->type == OB_ARMATURE) && aci->rna_path) { Object *ob = (Object *)aci->id; - char *str_start; - - if ((str_start = strstr(aci->rna_path, "pose.bones["))) { - bPoseChannel *pchan; - int length = 0; - char *str_end; - - str_start += 12; - str_end = strchr(str_start, '\"'); - length = str_end - str_start; - str_start[length] = 0; - pchan = BKE_pose_channel_find_name(ob->pose, str_start); - str_start[length] = '\"'; - - if (pchan) { - aci->is_bone = true; - } + bPoseChannel *pchan; + char *bone_name; + + bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones["); + pchan = BKE_pose_channel_find_name(ob->pose, bone_name); + if (pchan) { + aci->is_bone = true; } + if (bone_name) MEM_freeN(bone_name); } BLI_addtail(&animcopybuf, aci); @@ -635,22 +626,22 @@ static void flip_names(tAnimCopybufItem *aci, char **name) char bname_new[MAX_VGROUP_NAME]; char *str_iter, *str_end; int length, prefix_l, postfix_l; - + str_start += 12; prefix_l = str_start - aci->rna_path; - + str_end = strchr(str_start, '\"'); - + length = str_end - str_start; postfix_l = strlen(str_end); - + /* more ninja stuff, temporary substitute with NULL terminator */ str_start[length] = 0; BKE_deform_flip_side_name(bname_new, str_start, false); str_start[length] = '\"'; - + str_iter = *name = MEM_mallocN(sizeof(char) * (prefix_l + postfix_l + length + 1), "flipped_path"); - + BLI_strncpy(str_iter, aci->rna_path, prefix_l + 1); str_iter += prefix_l; BLI_strncpy(str_iter, bname_new, length + 1); -- cgit v1.2.3 From d80ff8ce80607bb9fd3944ea272e0bee80ccf7c0 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 6 May 2015 13:05:59 +0200 Subject: Image proxies now correctly support metadata (needs to regenerate proxies though) --- source/blender/blenkernel/intern/sequencer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index bb48023de56..5429d113518 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1737,6 +1737,7 @@ static void seq_proxy_build_frame(const SeqRenderData *context, Sequence *seq, i if (ibuf_tmp->x != rectx || ibuf_tmp->y != recty) { ibuf = IMB_dupImBuf(ibuf_tmp); + IMB_metadata_copy(ibuf, ibuf_tmp); IMB_freeImBuf(ibuf_tmp); IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty); } -- cgit v1.2.3 From df422314c10bb6ef0b33afa4d203916823efa976 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 6 May 2015 13:58:06 +0200 Subject: Only use render view name in render filenames if we are actually using multiview. --- source/blender/render/intern/source/pipeline.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index a4089002ba5..7f08e576747 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -3121,10 +3121,11 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen BLI_strncpy(filepath, name, sizeof(filepath)); for (view_id = 0, rv = rr->views.first; rv; rv = rv->next, view_id++) { - BKE_scene_multiview_view_filepath_get(&scene->r, filepath, rv->name, name); + if (!is_mono) { + BKE_scene_multiview_view_filepath_get(&scene->r, filepath, rv->name, name); + } if (rd->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) { - RE_WriteRenderResult(reports, rr, name, &rd->im_format, false, rv->name); printf("Saved: %s\n", name); } -- cgit v1.2.3 From 15751238d5d9cf7868c131f09b224f5c41b518f3 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Wed, 6 May 2015 14:21:39 +0200 Subject: BGE: Fix compound child shape added on instance game object --- source/gameengine/Physics/Bullet/CcdPhysicsController.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 3ed01a402ed..dfcad865e09 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -1576,8 +1576,7 @@ void CcdPhysicsController::AddCompoundChild(PHY_IPhysicsController* child) const btCollisionShape* childShape = childBody->getCollisionShape(); if (!rootShape || !childShape || - rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE || - childShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) + rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE) return; btCompoundShape* compoundShape = (btCompoundShape*)rootShape; // compute relative transformation between parent and child -- cgit v1.2.3 From aaa6b39bfeb315a017e0d69f9780e894d4154e76 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 6 May 2015 14:46:45 +0200 Subject: Quick patch-up for opengl render metadata. Camera here is incorrect for multiview (as is in real multiview render) but at least it works now. --- source/blender/editors/render/render_opengl.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 7fbdf9dc66b..3f3bdaa59d0 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -146,6 +146,7 @@ static void screen_opengl_views_setup(OGLRender *oglrender) RenderView *rv; SceneRenderView *srv; bool is_multiview; + Object *camera; View3D *v3d = oglrender->v3d; RenderData *rd = &oglrender->scene->r; @@ -236,6 +237,10 @@ static void screen_opengl_views_setup(OGLRender *oglrender) } BLI_unlock_thread(LOCK_DRAW_IMAGE); + /* will only work for non multiview correctly */ + camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, "new opengl render view"); + BKE_render_result_stamp_info(oglrender->scene, camera, rr); + RE_ReleaseResult(oglrender->re); } @@ -474,12 +479,9 @@ static void screen_opengl_render_write(OGLRender *oglrender) RenderResult *rr; bool ok; char name[FILE_MAX]; - Object *camera = RE_GetCamera(oglrender->re); rr = RE_AcquireResultRead(oglrender->re); - BKE_render_result_stamp_info(scene, camera, rr); - BKE_image_path_from_imformat( name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false, NULL); -- cgit v1.2.3 From 5ffd10a6da956210062f5cd18c61de348f379849 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 6 May 2015 15:30:00 +0200 Subject: OpenGL render: Update metadata as before, for every frame written to a file, since we need the updated times and frames. This was lost during stamp code refactoring. The refactoring moved the stamp when render is initialized so we would be guaranteed to have correct cameras even when saving render stills at a later time (and even if cameras were changed). For regular render this would work since render init takes care of stamp, but for openGL rendering we need to do this manually. Still not 100% correct, does not apply multiview cameras to metadata --- source/blender/editors/render/render_opengl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 3f3bdaa59d0..fbe6316905f 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -487,6 +487,7 @@ static void screen_opengl_render_write(OGLRender *oglrender) &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false, NULL); /* write images as individual images or stereo */ + BKE_render_result_stamp_info(scene, scene->camera, rr); ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, false, name); RE_ReleaseResultImage(oglrender->re); @@ -809,6 +810,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) } } else { + BKE_render_result_stamp_info(scene, scene->camera, rr); ok = RE_WriteRenderViewsImage(op->reports, rr, scene, true, name); if (ok) { printf("Saved: %s", name); -- cgit v1.2.3 From 1d88bfce4017875490113a81dccd45df3f13a7c6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 May 2015 23:50:54 +1000 Subject: Shader node: support native render capabilities D1188 by @a.romanov --- source/blender/blenkernel/BKE_scene.h | 1 + source/blender/blenkernel/intern/scene.c | 6 ++++++ source/blender/makesrna/intern/rna_render.c | 6 ++++++ source/blender/nodes/shader/node_shader_tree.c | 3 ++- source/blender/render/extern/include/RE_engine.h | 1 + 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 75a5e919bad..442a43871c1 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -133,6 +133,7 @@ int get_render_shadow_samples(const struct RenderData *r, int samples); float get_render_aosss_error(const struct RenderData *r, float error); bool BKE_scene_use_new_shading_nodes(const struct Scene *scene); +bool BKE_scene_use_shading_nodes_custom(struct Scene *scene); bool BKE_scene_uses_blender_internal(const struct Scene *scene); bool BKE_scene_uses_blender_game(const struct Scene *scene); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 575a42ed690..f810630c83b 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -2011,6 +2011,12 @@ bool BKE_scene_use_new_shading_nodes(const Scene *scene) return (type && type->flag & RE_USE_SHADING_NODES); } +bool BKE_scene_use_shading_nodes_custom(Scene *scene) +{ + RenderEngineType *type = RE_engines_find(scene->r.engine); + return (type && type->flag & RE_USE_SHADING_NODES_CUSTOM); +} + bool BKE_scene_uses_blender_internal(const Scene *scene) { return STREQ(scene->r.engine, RE_engine_id_BLENDER_RENDER); diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index dbb572b7333..ee51dcf2acf 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -257,6 +257,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo /* setup dummy engine & engine type to store static properties in */ dummyengine.type = &dummyet; + dummyet.flag |= RE_USE_SHADING_NODES_CUSTOM; RNA_pointer_create(NULL, &RNA_RenderEngine, &dummyengine, &dummyptr); /* validate the python class */ @@ -628,6 +629,11 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_SHADING_NODES); RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + prop = RNA_def_property(srna, "bl_use_shading_nodes_custom", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_SHADING_NODES_CUSTOM); + RNA_def_property_boolean_default(prop, true); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + prop = RNA_def_property(srna, "bl_use_exclude_layers", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_EXCLUDE_LAYERS); RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index 57cc1eab929..a49d6ea76da 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -69,7 +69,8 @@ static int shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype)) return (scene->r.engine[0] == '\0' || STREQ(scene->r.engine, RE_engine_id_BLENDER_RENDER) || STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME) || - STREQ(scene->r.engine, RE_engine_id_CYCLES)); + STREQ(scene->r.engine, RE_engine_id_CYCLES) || + !BKE_scene_use_shading_nodes_custom(scene)); } static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from) diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 9d3c74163d5..4e48060c54f 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -61,6 +61,7 @@ struct BakePixel; #define RE_USE_EXCLUDE_LAYERS 32 #define RE_USE_SAVE_BUFFERS 64 #define RE_USE_TEXTURE_PREVIEW 128 +#define RE_USE_SHADING_NODES_CUSTOM 256 /* RenderEngine.flag */ #define RE_ENGINE_ANIMATION 1 -- cgit v1.2.3 From 14d55ab7a3923e0c411e082adf61d1ed76698358 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 May 2015 00:18:11 +1000 Subject: Cleanup: use ntreeFromID --- source/blender/blenkernel/intern/library.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 42856e82062..ce118fe9fde 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -1415,16 +1415,11 @@ void id_clear_lib_data(Main *bmain, ID *id) /* internal bNodeTree blocks inside ID types below * also stores id->lib, make sure this stays in sync. */ - switch (GS(id->name)) { - case ID_SCE: ntree = ((Scene *)id)->nodetree; break; - case ID_MA: ntree = ((Material *)id)->nodetree; break; - case ID_LA: ntree = ((Lamp *)id)->nodetree; break; - case ID_WO: ntree = ((World *)id)->nodetree; break; - case ID_TE: ntree = ((Tex *)id)->nodetree; break; - case ID_LS: ntree = ((FreestyleLineStyle *)id)->nodetree; break; - } - if (ntree) + ntree = ntreeFromID(id); + + if (ntree) { ntree->id.lib = NULL; + } } /* next to indirect usage in read/writefile also in editobject.c scene.c */ -- cgit v1.2.3 From 51f33a2e55e6e269545ff319e0d99da67ea08b40 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Wed, 6 May 2015 17:03:24 +0200 Subject: collada:custom normals generated by normals modifier have not been exported correctly. Also triangulating during export did not work. --- source/blender/collada/GeometryExporter.cpp | 10 +++++----- source/blender/collada/collada_utils.cpp | 11 ++++++----- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index 1353d988137..b29b4c9c484 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -82,9 +82,6 @@ void GeometryExporter::operator()(Object *ob) this->export_settings->apply_modifiers, this->export_settings->triangulate); - Mesh *mesh = (Mesh *) ob->data; - me->flag = mesh->flag; - std::string geom_id = get_geometry_id(ob, use_instantiation); std::vector nor; std::vector norind; @@ -610,16 +607,19 @@ void GeometryExporter::create_normals(std::vector &normals, std::vector< MVert *verts = me->mvert; MLoop *mloops = me->mloop; float(*lnors)[3]; + bool use_custom_normals = false; BKE_mesh_calc_normals_split(me); if (CustomData_has_layer(&me->ldata, CD_NORMAL)) { lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL); + use_custom_normals = true; } for (int poly_index = 0; poly_index < me->totpoly; poly_index++) { MPoly *mpoly = &me->mpoly[poly_index]; + bool use_vertex_normals = use_custom_normals || mpoly->flag & ME_SMOOTH; - if (!(mpoly->flag & ME_SMOOTH)) { + if (!use_vertex_normals) { // For flat faces use face normal as vertex normal: float vector[3]; @@ -634,7 +634,7 @@ void GeometryExporter::create_normals(std::vector &normals, std::vector< BCPolygonNormalsIndices poly_indices; for (int loop_index = 0; loop_index < mpoly->totloop; loop_index++) { unsigned int loop_idx = mpoly->loopstart + loop_index; - if (mpoly->flag & ME_SMOOTH) { + if (use_vertex_normals) { float normalized[3]; normalize_v3_v3(normalized, lnors[loop_idx]); diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index d3813e2fb7a..e45c8537948 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -144,6 +144,7 @@ Mesh *bc_get_mesh_copy(Scene *scene, Object *ob, BC_export_mesh_type export_mesh { Mesh *tmpmesh; CustomDataMask mask = CD_MASK_MESH; + Mesh *mesh = (Mesh *)ob->data; DerivedMesh *dm = NULL; if (apply_modifiers) { switch (export_mesh_type) { @@ -165,14 +166,14 @@ Mesh *bc_get_mesh_copy(Scene *scene, Object *ob, BC_export_mesh_type export_mesh tmpmesh = BKE_mesh_add(G.main, "ColladaMesh"); // name is not important here DM_to_mesh(dm, tmpmesh, ob, CD_MASK_MESH, true); + tmpmesh->flag = mesh->flag; if (triangulate) { - bc_triangulate_mesh(tmpmesh); + BKE_mesh_tessface_calc(tmpmesh); + } + else { + BKE_mesh_tessface_ensure(tmpmesh); } - - // XXX Not sure if we need that for ngon_export as well. - BKE_mesh_tessface_ensure(tmpmesh); - return tmpmesh; } -- cgit v1.2.3 From 4487358da7b38d3375fa3ea2034f5acffa25b2a5 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 6 May 2015 17:50:10 +0200 Subject: Fix T44618: Rip Fill on a single vert would only generate one of the two expected faces. Was tagging (for filling) the wrong edge for one of the two involved loops... --- source/blender/editors/mesh/editmesh_rip.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 2a0bdfc45f0..44c0f83cb9f 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -784,11 +784,20 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve else { if (BM_edge_is_manifold(e_best)) { BMLoop *l_iter, *l_first; - l_iter = l_first = e_best->l; do { larr[larr_len] = BM_edge_vert_share_loop(l_iter, v); - BM_elem_flag_enable(larr[larr_len]->e, BM_ELEM_TAG); + + if (do_fill) { + /* Only needed when filling... + * Also, we never want to tag best edge, that one won't change during split. See T44618. */ + if (larr[larr_len]->e == e_best) { + BM_elem_flag_enable(larr[larr_len]->prev->e, BM_ELEM_TAG); + } + else { + BM_elem_flag_enable(larr[larr_len]->e, BM_ELEM_TAG); + } + } larr_len++; } while ((l_iter = l_iter->radial_next) != l_first); } -- cgit v1.2.3 From c740027e309875e7008dfcfd1f2a611c788f0368 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 May 2015 04:43:33 +1000 Subject: Fix T44381: Text Editor: Un-indent undo fails D1284 by @mikidep --- source/blender/blenkernel/intern/text.c | 125 +++++++++++++++++++++++++++++--- 1 file changed, 116 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 1966d5af7d1..c901fa40acc 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -1896,6 +1896,47 @@ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c) text->undo_buf[text->undo_pos + 1] = 0; } +/* extends Link */ +struct LinkInt { + struct LinkInt *next, *prev; + int value; +}; + +/* unindentLines points to a ListBase composed of LinkInt elements, listing the numbers + * of the lines that should not be indented back. */ +static void txt_undo_add_unindent_op(Text *text, const ListBase *line_index_mask, const int line_index_mask_len) +{ + struct LinkInt *idata; + + BLI_assert(BLI_listbase_count(line_index_mask) == line_index_mask_len); + + /* OP byte + UInt32 count + counted UInt32 line numbers + UInt32 count + 12-bytes selection + OP byte */ + if (!max_undo_test(text, 1 + 4 + (line_index_mask_len * 4) + 4 + 12 + 1)) { + return; + } + + /* Opening buffer sequence with OP */ + text->undo_pos++; + text->undo_buf[text->undo_pos] = UNDO_UNINDENT; + text->undo_pos++; + /* Adding number of line numbers to read */ + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len); + + /* Adding linenumbers of lines that shall not be indented if undoing */ + for (idata = line_index_mask->first; idata; idata = idata->next) { + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, idata->value); + } + + /* Adding number of line numbers to read again */ + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len); + /* Adding current selection */ + txt_undo_store_cursors(text); + /* Closing with OP (same as above) */ + text->undo_buf[text->undo_pos] = UNDO_UNINDENT; + /* Marking as last undo operation */ + text->undo_buf[text->undo_pos + 1] = 0; +} + static unsigned short txt_undo_read_uint16(const char *undo_buf, int *undo_pos) { unsigned short val; @@ -2190,7 +2231,6 @@ void txt_do_undo(Text *text) text->undo_pos--; break; case UNDO_INDENT: - case UNDO_UNINDENT: case UNDO_COMMENT: case UNDO_UNCOMMENT: case UNDO_DUPLICATE: @@ -2204,9 +2244,6 @@ void txt_do_undo(Text *text) if (op == UNDO_INDENT) { txt_unindent(text); } - else if (op == UNDO_UNINDENT) { - txt_indent(text); - } else if (op == UNDO_COMMENT) { txt_uncomment(text); } @@ -2225,6 +2262,37 @@ void txt_do_undo(Text *text) text->undo_pos--; break; + case UNDO_UNINDENT: + { + int count; + int i; + /* Get and restore the cursors */ + txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + + /* Un-unindent */ + txt_indent(text); + + /* Get the count */ + count = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); + /* Iterate! */ + txt_pop_sel(text); + + for (i = 0; i < count; i++) { + txt_move_to(text, txt_undo_read_uint32(text->undo_buf, &text->undo_pos), 0, 0); + /* Un-un-unindent */ + txt_unindent(text); + } + /* Restore selection */ + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + /* Jumo over count */ + txt_undo_read_uint32(text->undo_buf, &text->undo_pos); + /* Jump over closing OP byte */ + text->undo_pos--; + break; + } default: //XXX error("Undo buffer error - resetting"); text->undo_pos = -1; @@ -2354,7 +2422,6 @@ void txt_do_redo(Text *text) break; case UNDO_INDENT: - case UNDO_UNINDENT: case UNDO_COMMENT: case UNDO_UNCOMMENT: case UNDO_DUPLICATE: @@ -2370,9 +2437,6 @@ void txt_do_redo(Text *text) if (op == UNDO_INDENT) { txt_indent(text); } - else if (op == UNDO_UNINDENT) { - txt_unindent(text); - } else if (op == UNDO_COMMENT) { txt_comment(text); } @@ -2402,6 +2466,26 @@ void txt_do_redo(Text *text) txt_move_to(text, selln, selc, 1); break; + case UNDO_UNINDENT: + { + int count; + int i; + + text->undo_pos++; + /* Scan all the stuff described in txt_undo_add_unindent_op */ + count = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); + for (i = 0; i < count; i++) { + txt_redo_read_uint32(text->undo_buf, &text->undo_pos); + } + /* Count again */ + txt_redo_read_uint32(text->undo_buf, &text->undo_pos); + /* Get the selection and re-unindent */ + txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + txt_unindent(text); + break; + } default: //XXX error("Undo buffer error - resetting"); text->undo_pos = -1; @@ -2802,6 +2886,12 @@ void txt_unindent(Text *text) int indentlen = 1; bool unindented_first = false; + /* List of lines that are already at indent level 0, to store them later into the undo buffer */ + ListBase line_index_mask = {NULL, NULL}; + int line_index_mask_len = 0; + int curl_span_init = 0; + + /* hardcoded: TXT_TABSIZE = 4 spaces: */ int spaceslen = TXT_TABSIZE; @@ -2815,6 +2905,10 @@ void txt_unindent(Text *text) indentlen = spaceslen; } + if (!undoing) { + curl_span_init = txt_get_span(text->lines.first, text->curl); + } + while (true) { bool changed = false; if (STREQLEN(text->curl->line, remove, indentlen)) { @@ -2824,6 +2918,16 @@ void txt_unindent(Text *text) memmove(text->curl->line, text->curl->line + indentlen, text->curl->len + 1); changed = true; } + else { + if (!undoing) { + /* Create list element for 0 indent line */ + struct LinkInt *idata = MEM_mallocN(sizeof(struct LinkInt), __func__); + idata->value = curl_span_init + num; + BLI_assert(idata->value == txt_get_span(text->lines.first, text->curl)); + BLI_addtail(&line_index_mask, idata); + line_index_mask_len += 1; + } + } txt_make_dirty(text); txt_clean_text(text); @@ -2836,6 +2940,7 @@ void txt_unindent(Text *text) else { text->curl = text->curl->next; num++; + } } @@ -2849,8 +2954,10 @@ void txt_unindent(Text *text) } if (!undoing) { - txt_undo_add_op(text, UNDO_UNINDENT); + txt_undo_add_unindent_op(text, &line_index_mask, line_index_mask_len); } + + BLI_freelistN(&line_index_mask); } void txt_comment(Text *text) -- cgit v1.2.3 From 4d7b0e4fe35732687fb01625ede63f8a1b762d37 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 May 2015 05:23:07 +1000 Subject: Correct own error: is_manifold_region on wire vert --- source/blender/bmesh/intern/bmesh_queries.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 63e36178e0f..9bc45025456 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -1010,10 +1010,12 @@ int BM_loop_region_loops_count(BMLoop *l) bool BM_vert_is_manifold_region(const BMVert *v) { BMLoop *l_first = BM_vert_find_first_loop((BMVert *)v); - int count, count_total; - - count = BM_loop_region_loops_count_ex(l_first, &count_total); - return (count == count_total); + if (l_first) { + int count, count_total; + count = BM_loop_region_loops_count_ex(l_first, &count_total); + return (count == count_total); + } + return true; } /** -- cgit v1.2.3 From 4a5933bb74c4658c5ae35bafa4f0f6145a0430a5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 May 2015 05:34:07 +1000 Subject: Rip tool, support filling-edges with fill enabled --- source/blender/editors/mesh/editmesh_rip.c | 31 ++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 44c0f83cb9f..c7a7828f3b2 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -607,6 +607,11 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve if (ese.ele) { BM_select_history_store(bm, v_new); } + + if (do_fill) { + BM_edge_create(bm, v, v_new, NULL, BM_CREATE_NOP); + } + return OPERATOR_FINISHED; } @@ -719,6 +724,15 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve } } + /* vout[0] == best + * vout[1] == glue + * vout[2+] == splice with glue (when vout_len > 2) + */ + if (vi_best != 0) { + SWAP(BMVert *, vout[0], vout[vi_best]); + vi_best = 0; + } + /* select the vert from the best region */ v = vout[vi_best]; BM_vert_select_set(bm, v, true); @@ -729,21 +743,18 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve /* splice all others back together */ if (vout_len > 2) { - - /* vout[0] == best - * vout[1] == glue - * vout[2+] == splice with glue - */ - if (vi_best != 0) { - SWAP(BMVert *, vout[0], vout[vi_best]); - vi_best = 0; - } - for (i = 2; i < vout_len; i++) { BM_vert_splice(bm, vout[1], vout[i]); } } + if (do_fill) { + if (do_fill) { + /* match extrude vert-order */ + BM_edge_create(bm, vout[1], vout[0], NULL, BM_CREATE_NOP); + } + } + MEM_freeN(vout); return OPERATOR_FINISHED; -- cgit v1.2.3 From 7c3a714124f1c5292284cec249052a26500cac5d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 6 May 2015 21:54:13 +0200 Subject: Fix T44624: world menu appears in node editor header with Blender internal. --- release/scripts/startup/bl_ui/space_node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index 18890aadc93..e20d980db58 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -67,7 +67,7 @@ class NODE_HT_header(Header): if snode_id and not (scene.render.use_shading_nodes == 0 and ob.type == 'LAMP'): layout.prop(snode_id, "use_nodes") - if snode.shader_type == 'WORLD': + if scene.render.use_shading_nodes and snode.shader_type == 'WORLD': row = layout.row() row.enabled = not snode.pin row.template_ID(scene, "world", new="world.new") -- cgit v1.2.3 From de180aba35ea0bc203abb4995b9fbcaa2d97aaa2 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 6 May 2015 22:51:49 +0200 Subject: Feature request: Dyntopo detail expressed in percentage of brush radius. Not sure how useful this will be but people have requested it so, here it is... --- release/scripts/startup/bl_ui/space_view3d_toolbar.py | 2 ++ source/blender/editors/sculpt_paint/sculpt.c | 13 ++++++++++--- source/blender/makesdna/DNA_scene_types.h | 5 ++++- source/blender/makesrna/intern/rna_sculpt_paint.c | 7 +++++++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 51dd8b05f93..5fa3a559ab9 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -1471,6 +1471,8 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel): row = sub.row(align=True) row.prop(sculpt, "constant_detail") row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER') + elif (sculpt.detail_type_method == 'BRUSH'): + sub.prop(sculpt, "detail_percent") else: sub.prop(sculpt, "detail_size") sub.prop(sculpt, "detail_refine_method", text="") diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 1d2f623bf9d..e2403a57556 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -4379,6 +4379,9 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *UNUSED(st if (sd->flags & SCULPT_DYNTOPO_DETAIL_CONSTANT) { BKE_pbvh_bmesh_detail_size_set(ss->pbvh, sd->constant_detail / 100.0f); } + else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) { + BKE_pbvh_bmesh_detail_size_set(ss->pbvh, ss->cache->radius * sd->detail_percent / 100.0f); + } else { BKE_pbvh_bmesh_detail_size_set( ss->pbvh, @@ -5072,10 +5075,10 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) ts->sculpt->flags |= SCULPT_DYNTOPO_SUBDIVIDE | SCULPT_DYNTOPO_COLLAPSE; } - if (!ts->sculpt->detail_size) { + if (!ts->sculpt->detail_size) ts->sculpt->detail_size = 12; - } - + if (!ts->sculpt->detail_percent) + ts->sculpt->detail_percent = 25; if (ts->sculpt->constant_detail == 0.0f) ts->sculpt->constant_detail = 30.0f; @@ -5308,6 +5311,10 @@ static int sculpt_set_detail_size_exec(bContext *C, wmOperator *UNUSED(op)) set_brush_rc_props(&props_ptr, "sculpt", "constant_detail", NULL, 0); RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.constant_detail"); } + else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) { + set_brush_rc_props(&props_ptr, "sculpt", "constant_detail", NULL, 0); + RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.detail_percent"); + } else { set_brush_rc_props(&props_ptr, "sculpt", "detail_size", NULL, 0); RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.detail_size"); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index ff2a7468832..a40b8aff08e 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1021,6 +1021,8 @@ typedef struct Sculpt { /* scale for constant detail size */ float constant_detail; + float detail_percent; + float pad; struct Object *gravity_object; void *pad2; @@ -1851,7 +1853,8 @@ typedef enum SculptFlags { SCULPT_DYNTOPO_COLLAPSE = (1 << 11), /* If set, dynamic-topology detail size will be constant in object space */ - SCULPT_DYNTOPO_DETAIL_CONSTANT = (1 << 13) + SCULPT_DYNTOPO_DETAIL_CONSTANT = (1 << 13), + SCULPT_DYNTOPO_DETAIL_BRUSH = (1 << 14), } SculptFlags; typedef enum ImagePaintMode { diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index a975ea3d7e4..d5e99d4f3e9 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -462,6 +462,8 @@ static void rna_def_sculpt(BlenderRNA *brna) "Relative Detail", "Mesh detail is relative to the brush size and detail size"}, {SCULPT_DYNTOPO_DETAIL_CONSTANT, "CONSTANT", 0, "Constant Detail", "Mesh detail is constant in object space according to detail size"}, + {SCULPT_DYNTOPO_DETAIL_BRUSH, "BRUSH", 0, + "Brush Detail", "Mesh detail is relative to brush radius"}, {0, NULL, 0, NULL, NULL} }; @@ -519,6 +521,11 @@ static void rna_def_sculpt(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Detail Size", "Maximum edge length for dynamic topology sculpting (in pixels)"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); + prop = RNA_def_property(srna, "detail_percent", PROP_FLOAT, PROP_PERCENTAGE); + RNA_def_property_ui_range(prop, 0.5, 100.0, 10, 2); + RNA_def_property_ui_text(prop, "Detail Percentage", "Maximum edge length for dynamic topology sculpting (in brush percenage)"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); + prop = RNA_def_property(srna, "constant_detail", PROP_FLOAT, PROP_PERCENTAGE); RNA_def_property_range(prop, 0.001, 10000.0); RNA_def_property_ui_range(prop, 0.1, 100.0, 10, 2); -- cgit v1.2.3 From fb0dd596e9a58f095730359a11759c40ea46be44 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Wed, 6 May 2015 22:55:46 +0200 Subject: BGE : KX_VertexProxy support for more than 2 UV channel. I have added an optional named "index" argument for methode get/setUV, I have also modified the and set to deprecated methodes setUV2 and getUV2 : the doc was wrong and the methode can't be called anyway because it declared as VARARG in the .h and convert directly the args value to a vector in the .cpp. Reviewers: sybren, lordloki, hg1 Reviewed By: lordloki, hg1 Subscribers: agoose77 Differential Revision: https://developer.blender.org/D1240 --- .../rst/bge_types/bge.types.KX_VertexProxy.rst | 28 +++++++++++---- source/gameengine/Ketsji/KX_VertexProxy.cpp | 41 ++++++++++++++++------ source/gameengine/Ketsji/KX_VertexProxy.h | 6 ++-- 3 files changed, 55 insertions(+), 20 deletions(-) diff --git a/doc/python_api/rst/bge_types/bge.types.KX_VertexProxy.rst b/doc/python_api/rst/bge_types/bge.types.KX_VertexProxy.rst index 73d692770d6..d1bd6758cbc 100644 --- a/doc/python_api/rst/bge_types/bge.types.KX_VertexProxy.rst +++ b/doc/python_api/rst/bge_types/bge.types.KX_VertexProxy.rst @@ -25,6 +25,12 @@ base class --- :class:`SCA_IObject` :type: Vector((u, v)) + .. attribute:: uvs + + A list of all the texture coordinates of the vertex. + + :type: list of Vector((u, v)) + .. attribute:: normal The normal of the vertex. @@ -120,18 +126,24 @@ base class --- :class:`SCA_IObject` :arg pos: the new position for this vertex in local coordinates. - .. method:: getUV() + .. method:: getUV(index=0) Gets the UV (texture) coordinates of this vertex. + :arg index: the UV (texture) channel (optional). + :type index: integer + :return: this vertexes UV (texture) coordinates. :rtype: Vector((u, v)) - .. method:: setUV(uv) + .. method:: setUV(uv, index=0) Sets the UV (texture) coordinates of this vertex. - :type: Vector((u, v)) + :arg uv: the UV (texture) coordinate of this vertex. + :type uv: Vector((u, v)) + :arg index: the UV (texture) channel (optional). + :type index: integer .. method:: getUV2() @@ -140,14 +152,16 @@ base class --- :class:`SCA_IObject` :return: this vertexes UV (texture) coordinates. :rtype: Vector((u, v)) - .. method:: setUV2(uv, unit) + .. deprecated:: use :meth:`getUV` + + .. method:: setUV2(uv) Sets the 2nd UV (texture) coordinates of this vertex. - :type: Vector((u, v)) + :arg uv: the 2nd (texture) UV coordinate of this vertex. + :type uv: Vector((u, v)) - :arg unit: optional argument, FLAT==1, SECOND_UV==2, defaults to SECOND_UV - :arg unit: integer + .. deprecated:: use :meth:`setUV` .. method:: getRGBA() diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index cd1c9eed91b..163416526f3 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -63,11 +63,11 @@ PyTypeObject KX_VertexProxy::Type = { PyMethodDef KX_VertexProxy::Methods[] = { {"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_NOARGS}, {"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_O}, - {"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV1, METH_NOARGS}, - {"setUV", (PyCFunction)KX_VertexProxy::sPySetUV1, METH_O}, + {"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV, METH_VARARGS}, + {"setUV", (PyCFunction)KX_VertexProxy::sPySetUV, METH_VARARGS}, {"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_NOARGS}, - {"setUV2", (PyCFunction)KX_VertexProxy::sPySetUV2,METH_VARARGS}, + {"setUV2", (PyCFunction)KX_VertexProxy::sPySetUV2, METH_O}, {"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_NOARGS}, {"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_O}, @@ -423,7 +423,6 @@ int KX_VertexProxy::pyattr_set_uvs(void *self_v, const struct KX_PYATTRIBUTE_DEF if (PyVecTo(PySequence_GetItem(value, i), vec)) { self->m_vertex->SetUV(i, vec); - self->m_mesh->SetMeshModified(true); } else { @@ -559,25 +558,45 @@ PyObject *KX_VertexProxy::PySetRGBA(PyObject *value) return NULL; } - -PyObject *KX_VertexProxy::PyGetUV1() +PyObject *KX_VertexProxy::PyGetUV(PyObject *args) { - return PyObjectFrom(MT_Vector2(m_vertex->getUV(0))); + int index = 0; + if (!PyArg_ParseTuple(args, "|i:getUV", &index)) + return NULL; + + if (index < 0 || index > (RAS_TexVert::MAX_UNIT - 1)) { + PyErr_Format(PyExc_TypeError, "vert.getUV(index): KX_VertexProxy, expected an int between 0 and %i", (RAS_TexVert::MAX_UNIT - 1)); + return NULL; + } + + return PyObjectFrom(MT_Vector2(m_vertex->getUV(index))); } -PyObject *KX_VertexProxy::PySetUV1(PyObject *value) +PyObject *KX_VertexProxy::PySetUV(PyObject *args) { + PyObject *pyvect; + int index = 0; + if (!PyArg_ParseTuple(args, "O|i:setUV", &pyvect, &index)) + return NULL; + + if (index < 0 || index > (RAS_TexVert::MAX_UNIT - 1)) { + PyErr_Format(PyExc_TypeError, "vert.setUV(uv, index): KX_VertexProxy, expected an int between 0 and %i", (RAS_TexVert::MAX_UNIT - 1)); + return NULL; + } + MT_Point2 vec; - if (!PyVecTo(value, vec)) + if (!PyVecTo(pyvect, vec)) return NULL; - m_vertex->SetUV(0, vec); + m_vertex->SetUV(index, vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; } PyObject *KX_VertexProxy::PyGetUV2() { + ShowDeprecationWarning("getUV2()", "getUV(1)"); + return PyObjectFrom(MT_Vector2(m_vertex->getUV(1))); } @@ -587,6 +606,8 @@ PyObject *KX_VertexProxy::PySetUV2(PyObject *args) if (!PyVecTo(args, vec)) return NULL; + ShowDeprecationWarning("setUV2(uv)", "setUV(uv, 1)"); + m_vertex->SetUV(1, vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h index 8070825ad11..91cf29deca1 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.h +++ b/source/gameengine/Ketsji/KX_VertexProxy.h @@ -94,11 +94,11 @@ public: KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ); KX_PYMETHOD_O(KX_VertexProxy,SetXYZ); - KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV1); - KX_PYMETHOD_O(KX_VertexProxy,SetUV1); + KX_PYMETHOD_VARARGS(KX_VertexProxy, GetUV); + KX_PYMETHOD_VARARGS(KX_VertexProxy, SetUV); KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV2); - KX_PYMETHOD_VARARGS(KX_VertexProxy,SetUV2); + KX_PYMETHOD_O(KX_VertexProxy, SetUV2); KX_PYMETHOD_NOARGS(KX_VertexProxy,GetRGBA); KX_PYMETHOD_O(KX_VertexProxy,SetRGBA); -- cgit v1.2.3 From e73f1035d7e544f83cadceb5a44acfa1e9fb1921 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 6 May 2015 22:58:22 +0200 Subject: Fix T44598: blender internal not giving same result on repeated texture bakes. --- source/blender/render/intern/source/bake.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c index b602753dff4..0210bec5ab4 100644 --- a/source/blender/render/intern/source/bake.c +++ b/source/blender/render/intern/source/bake.c @@ -34,6 +34,7 @@ #include "MEM_guardedalloc.h" #include "BLI_math.h" +#include "BLI_rand.h" #include "BLI_threads.h" #include "BLI_utildefines.h" @@ -75,6 +76,8 @@ extern struct Render R; typedef struct BakeShade { + int thread; + ShadeSample ssamp; ObjectInstanceRen *obi; VlakRen *vlr; @@ -737,6 +740,9 @@ static void bake_single_vertex(BakeShade *bs, VertRen *vert, float u, float v) MLoopCol *basevcol; MLoop *mloop; + /* per vertex fixed seed */ + BLI_thread_srandom(bs->thread, vert->index); + origindex = RE_vertren_get_origindex(bs->obi->obr, vert, 0); if (!origindex || *origindex == ORIGINDEX_NONE) return; @@ -811,6 +817,9 @@ static void shade_tface(BakeShade *bs) Image *ima = tface->tpage; float vec[4][2]; int a, i1, i2, i3; + + /* per face fixed seed */ + BLI_thread_srandom(bs->thread, vlr->index); /* check valid zspan */ if (ima != bs->ima) { @@ -1037,6 +1046,8 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up /* get the threads running */ for (a = 0; a < re->r.threads; a++) { + handles[a].thread = a; + /* set defaults in handles */ handles[a].ssamp.shi[0].lay = re->lay; -- cgit v1.2.3 From 236360c838a1029b5b45207b335d4c2df5e101ef Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 6 May 2015 23:29:59 +0200 Subject: Change fix for T44530 which caused a "regression". Looks like the previous commit here is really correct and fixes cases of distortion that were in mirror-subsurf combination since blender 2.5. This may cause some changed files in which case we will be adding an option, but it is expected this will only happen with low res models, and hand painted textures, and the better distortion here compensates for that enough to consider not adding a compatibility option yet. Leaving the facemap winding argument as is just in case we do consider to add the option. --- source/blender/blenkernel/intern/subsurf_ccg.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 2b05a6c8fc5..68ef1565bd4 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -300,7 +300,11 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */ limit[0] = limit[1] = STD_UV_CONNECT_LIMIT; - vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, 0, limit, false); + /* previous behaviour here is without accounting for winding, however this causes stretching in + * UV map in really simple cases with mirror + subsurf, see second part of T44530. Also, initially + * intention is to treat merged vertices from mirror modifier as seams, see code below with ME_VERT_MERGED + * This fixes a very old regression (2.49 was correct here) */ + vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, 0, limit, true); if (!vmap) return 0; -- cgit v1.2.3 From 2d590670b491004b68c680a60cac0c2daac52ae2 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 6 May 2015 23:58:15 +0200 Subject: Fix T44614: Maya keymap left mouse click to add cut not working. --- release/scripts/presets/keyconfig/maya.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py index 28799d1cf67..cdd16f26877 100644 --- a/release/scripts/presets/keyconfig/maya.py +++ b/release/scripts/presets/keyconfig/maya.py @@ -698,10 +698,10 @@ kmi.properties.level = 5 km = kc.keymaps.new('Knife Tool Modal Map', space_type='EMPTY', region_type='WINDOW', modal=True) kmi = km.keymap_items.new_modal('CANCEL', 'ESC', 'ANY', any=True) +kmi = km.keymap_items.new_modal('ADD_CUT', 'LEFTMOUSE', 'ANY') kmi = km.keymap_items.new_modal('PANNING', 'LEFTMOUSE', 'ANY', alt=True) kmi = km.keymap_items.new_modal('PANNING', 'MIDDLEMOUSE', 'ANY', alt=True) kmi = km.keymap_items.new_modal('PANNING', 'RIGHTMOUSE', 'ANY', alt=True) -kmi = km.keymap_items.new_modal('ADD_CUT', 'LEFTMOUSE', 'PRESS', any=True) kmi = km.keymap_items.new_modal('CANCEL', 'RIGHTMOUSE', 'ANY') kmi = km.keymap_items.new_modal('CONFIRM', 'RET', 'PRESS', any=True) kmi = km.keymap_items.new_modal('CONFIRM', 'NUMPAD_ENTER', 'PRESS', any=True) -- cgit v1.2.3 From 165598e49e47e91fcb397abc059bc518947a7f92 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 May 2015 10:12:12 +1000 Subject: Correct typo: ifdef'd now, but obviously wrong --- intern/cycles/kernel/kernel_bake.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index 7790b9caa5a..2fca83c615f 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -208,7 +208,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, filter_x = filter_y = 0.5f; } else { - path_rng_2D(kg, &rng, sample, num_samples, PRNG_FILTER_U, &filter_x, &filter_x); + path_rng_2D(kg, &rng, sample, num_samples, PRNG_FILTER_U, &filter_x, &filter_y); } /* subpixel u/v offset */ -- cgit v1.2.3 From 3ec8bcebf32812a569ba36a0473cf98e85d0e8c7 Mon Sep 17 00:00:00 2001 From: Anatoly TechTonik Date: Thu, 7 May 2015 10:27:40 +0200 Subject: Fix T27642: Add version in .exe installer properties --- release/windows/installer/00.sconsblender.nsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/release/windows/installer/00.sconsblender.nsi b/release/windows/installer/00.sconsblender.nsi index f6e5b783faa..2d91b9da7f1 100644 --- a/release/windows/installer/00.sconsblender.nsi +++ b/release/windows/installer/00.sconsblender.nsi @@ -70,6 +70,13 @@ InstallDir $INSTDIR ; $INSTDIR is set inside .onInit BrandingText "Blender Foundation | http://www.blender.org" ComponentText "This will install Blender [VERSION] on your computer." +VIAddVersionKey "ProductName" "Blender" +VIAddVersionKey "CompanyName" "http://www.blender.org" +VIAddVersionKey "FileDescription" "Free open source 3D content creation suite." +VIAddVersionKey "FileVersion" "[SHORTVERSION].0.0" + +VIProductVersion "[SHORTVERSION].0.0" + DirText "Use the field below to specify the folder where you want Blender to be copied to. To specify a different folder, type a new name or use the Browse button to select an existing folder." SilentUnInstall normal -- cgit v1.2.3 From 0e9b210595e3a1f07e079b9f3e5e3abb9a2039a9 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 7 May 2015 10:56:45 +0200 Subject: Fix T44630: incorrect mirror modifier merge limit tooltip. --- source/blender/makesrna/intern/rna_modifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 8d0e95504a8..1c719b1376b 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1433,7 +1433,7 @@ static void rna_def_modifier_mirror(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "tolerance"); RNA_def_property_range(prop, 0, FLT_MAX); RNA_def_property_ui_range(prop, 0, 1, 0.01, 6); - RNA_def_property_ui_text(prop, "Merge Limit", "Distance from axis within which mirrored vertices are merged"); + RNA_def_property_ui_text(prop, "Merge Limit", "Distance within which mirrored vertices are merged"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "mirror_object", PROP_POINTER, PROP_NONE); -- cgit v1.2.3 From 11cf1ebdd1fa81a475bc13d72fa1b20d7b479191 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 7 May 2015 11:42:09 +0200 Subject: Fix first part of T44627, locking alpha should happen in straight space for float images or we get inconsistent premultiplied values. --- source/blender/editors/sculpt_paint/paint_image_proj.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 70127d0d425..6f34db4e424 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -4664,7 +4664,14 @@ static void *do_projectpaint_thread(void *ph_v) } if (lock_alpha) { - if (is_floatbuf) projPixel->pixel.f_pt[3] = projPixel->origColor.f_pt[3]; + if (is_floatbuf) { + /* slightly more involved case since floats are in premultiplied space we need + * to make sure alpha is consistent, see T44627 */ + float rgb_straight[4]; + premul_to_straight_v4_v4(rgb_straight, projPixel->pixel.f_pt); + rgb_straight[3] = projPixel->origColor.f_pt[3]; + straight_to_premul_v4_v4(projPixel->pixel.f_pt, rgb_straight); + } else projPixel->pixel.ch_pt[3] = projPixel->origColor.ch_pt[3]; } @@ -4833,7 +4840,14 @@ static void *do_projectpaint_thread(void *ph_v) } if (lock_alpha) { - if (is_floatbuf) projPixel->pixel.f_pt[3] = projPixel->origColor.f_pt[3]; + if (is_floatbuf) { + /* slightly more involved case since floats are in premultiplied space we need + * to make sure alpha is consistent, see T44627 */ + float rgb_straight[4]; + premul_to_straight_v4_v4(rgb_straight, projPixel->pixel.f_pt); + rgb_straight[3] = projPixel->origColor.f_pt[3]; + straight_to_premul_v4_v4(projPixel->pixel.f_pt, rgb_straight); + } else projPixel->pixel.ch_pt[3] = projPixel->origColor.ch_pt[3]; } -- cgit v1.2.3 From 9ca2b76a9ffe3213649a409b6a82a471be0e2ca5 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 7 May 2015 15:02:43 +0500 Subject: Cycles: Cleanup, make it more clear what endif closes what ifdef --- intern/cycles/kernel/svm/svm.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 1598019856a..c13fae76bd3 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -275,7 +275,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade case NODE_TEX_BRICK: svm_node_tex_brick(kg, sd, stack, node, &offset); break; -#endif +#endif /* __TEXTURES__ */ case NODE_CAMERA: svm_node_camera(kg, sd, stack, node.y, node.z, node.w); break; @@ -302,9 +302,9 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade case NODE_HAIR_INFO: svm_node_hair_info(kg, sd, stack, node.y, node.z); break; -#endif +#endif /* __HAIR__ */ -#endif +#endif /* __EXTRA_NODES__ */ case NODE_CONVERT: svm_node_convert(sd, stack, node.y, node.z, node.w); break; @@ -342,7 +342,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade case NODE_HSV: svm_node_hsv(kg, sd, stack, node.y, node.z, node.w, &offset); break; -#endif +#endif /* __EXTRA_NODES__ */ case NODE_ATTR: svm_node_attr(kg, sd, stack, node); break; @@ -353,7 +353,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade case NODE_ATTR_BUMP_DY: svm_node_attr_bump_dy(kg, sd, stack, node); break; -#endif +#endif /* __EXTRA_NODES__ */ case NODE_FRESNEL: svm_node_fresnel(sd, stack, node.y, node.z, node.w); break; @@ -388,7 +388,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade case NODE_NORMAL: svm_node_normal(kg, sd, stack, node.y, node.z, node.w, &offset); break; -#endif +#endif /* __EXTRA_NODES__ */ case NODE_MAPPING: svm_node_mapping(kg, sd, stack, node.y, node.z, &offset); break; @@ -420,7 +420,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade case NODE_LIGHT_FALLOFF: svm_node_light_falloff(sd, stack, node); break; -#endif +#endif /* __EXTRA_NODES__ */ case NODE_TANGENT: svm_node_tangent(kg, sd, stack, node); break; -- cgit v1.2.3 From cb7fdf45cd66b65d11b930ad0140b9457c7d401b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 May 2015 19:50:46 +1000 Subject: EdgeSlide: fix divide by zero --- source/blender/editors/transform/transform.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 7d80044762c..3e7fefe57fa 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -5460,7 +5460,7 @@ static BMEdge *get_other_edge(BMVert *v, BMEdge *e) } /* interpoaltes along a line made up of 2 segments (used for edge slide) */ -static void interp_line_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float t) +static void interp_line_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], float t) { float t_mid, t_delta; @@ -5468,17 +5468,28 @@ static void interp_line_v3_v3v3v3(float p[3], const float v1[3], const float v2[ t_mid = line_point_factor_v3(v2, v1, v3); t_delta = t - t_mid; - if (fabsf(t_delta) < FLT_EPSILON) { - copy_v3_v3(p, v2); - } - else if (t_delta < 0.0f) { - interp_v3_v3v3(p, v1, v2, t / t_mid); + if (t_delta < 0.0f) { + if (UNLIKELY(fabsf(t_mid) < FLT_EPSILON)) { + copy_v3_v3(p, v2); + } + else { + interp_v3_v3v3(p, v1, v2, t / t_mid); + } } else { - interp_v3_v3v3(p, v2, v3, (t - t_mid) / (1.0f - t_mid)); + t = t - t_mid; + t_mid = 1.0f - t_mid; + + if (UNLIKELY(fabsf(t_mid) < FLT_EPSILON)) { + copy_v3_v3(p, v3); + } + else { + interp_v3_v3v3(p, v2, v3, t / t_mid); + } } } + static void len_v3_ensure(float v[3], const float length) { normalize_v3(v); -- cgit v1.2.3 From 2ec808a4bc0654f401932f8b11ffb59582afb9dc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 May 2015 19:57:54 +1000 Subject: EdgeSlide: use pairs for TransDataEdgeSlideVert no functional changes --- source/blender/editors/transform/transform.c | 64 ++++++++++++++-------------- source/blender/editors/transform/transform.h | 4 +- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 3e7fefe57fa..7687ade032a 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -5664,7 +5664,7 @@ static void calcNonProportionalEdgeSlide(TransInfo *t, EdgeSlideData *sld, const for (i = 0; i < sld->totsv; i++, sv++) { /* Set length */ - sv->edge_len = len_v3v3(sv->dir_a, sv->dir_b); + sv->edge_len = len_v3v3(sv->dir_side[0], sv->dir_side[1]); ED_view3d_project_float_v2_m4(ar, sv->v->co, v_proj, projectMat); dist_sq = len_squared_v2v2(mval, v_proj); @@ -5892,14 +5892,14 @@ static bool createEdgeSlideVerts(TransInfo *t) if (l_a || l_a_prev) { BMLoop *l_tmp = BM_loop_other_edge_loop(l_a ? l_a : l_a_prev, v); - sv->v_a = BM_edge_other_vert(l_tmp->e, v); - copy_v3_v3(sv->dir_a, vec_a); + sv->v_side[0] = BM_edge_other_vert(l_tmp->e, v); + copy_v3_v3(sv->dir_side[0], vec_a); } if (l_b || l_b_prev) { BMLoop *l_tmp = BM_loop_other_edge_loop(l_b ? l_b : l_b_prev, v); - sv->v_b = BM_edge_other_vert(l_tmp->e, v); - copy_v3_v3(sv->dir_b, vec_b); + sv->v_side[1] = BM_edge_other_vert(l_tmp->e, v); + copy_v3_v3(sv->dir_side[1], vec_b); } v_prev = v; @@ -5918,23 +5918,23 @@ static bool createEdgeSlideVerts(TransInfo *t) if (l_a) { BMLoop *l_tmp = BM_loop_other_edge_loop(l_a, v); - sv->v_a = BM_edge_other_vert(l_tmp->e, v); + sv->v_side[0] = BM_edge_other_vert(l_tmp->e, v); if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) { - get_next_loop(v, l_a, e_prev, l_tmp->e, sv->dir_a); + get_next_loop(v, l_a, e_prev, l_tmp->e, sv->dir_side[0]); } else { - sub_v3_v3v3(sv->dir_a, BM_edge_other_vert(l_tmp->e, v)->co, v->co); + sub_v3_v3v3(sv->dir_side[0], BM_edge_other_vert(l_tmp->e, v)->co, v->co); } } if (l_b) { BMLoop *l_tmp = BM_loop_other_edge_loop(l_b, v); - sv->v_b = BM_edge_other_vert(l_tmp->e, v); + sv->v_side[1] = BM_edge_other_vert(l_tmp->e, v); if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) { - get_next_loop(v, l_b, e_prev, l_tmp->e, sv->dir_b); + get_next_loop(v, l_b, e_prev, l_tmp->e, sv->dir_side[1]); } else { - sub_v3_v3v3(sv->dir_b, BM_edge_other_vert(l_tmp->e, v)->co, v->co); + sub_v3_v3v3(sv->dir_side[1], BM_edge_other_vert(l_tmp->e, v)->co, v->co); } } @@ -6055,19 +6055,19 @@ static bool createEdgeSlideVerts(TransInfo *t) BLI_assert(sv_table[BM_elem_index_get(v)] != -1); j = sv_table[BM_elem_index_get(v)]; - if (sv_array[j].v_b) { - ED_view3d_project_float_v3_m4(ar, sv_array[j].v_b->co, sco_b, projectMat); + if (sv_array[j].v_side[1]) { + ED_view3d_project_float_v3_m4(ar, sv_array[j].v_side[1]->co, sco_b, projectMat); } else { - add_v3_v3v3(sco_b, v->co, sv_array[j].dir_b); + add_v3_v3v3(sco_b, v->co, sv_array[j].dir_side[1]); ED_view3d_project_float_v3_m4(ar, sco_b, sco_b, projectMat); } - if (sv_array[j].v_a) { - ED_view3d_project_float_v3_m4(ar, sv_array[j].v_a->co, sco_a, projectMat); + if (sv_array[j].v_side[0]) { + ED_view3d_project_float_v3_m4(ar, sv_array[j].v_side[0]->co, sco_a, projectMat); } else { - add_v3_v3v3(sco_a, v->co, sv_array[j].dir_a); + add_v3_v3v3(sco_a, v->co, sv_array[j].dir_side[0]); ED_view3d_project_float_v3_m4(ar, sco_a, sco_a, projectMat); } @@ -6108,8 +6108,8 @@ static bool createEdgeSlideVerts(TransInfo *t) /* switch a/b if loop direction is different from global direction */ l_nr = sv_array->loop_nr; if (dot_v3v3(loop_dir[l_nr], mval_dir) < 0.0f) { - swap_v3_v3(sv_array->dir_a, sv_array->dir_b); - SWAP(BMVert *, sv_array->v_a, sv_array->v_b); + swap_v3_v3(sv_array->dir_side[0], sv_array->dir_side[1]); + SWAP(BMVert *, sv_array->v_side[0], sv_array->v_side[1]); } } @@ -6280,8 +6280,8 @@ static void drawEdgeSlide(const struct bContext *C, TransInfo *t) const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; const int alpha_shade = -30; - add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_a); - add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_b); + add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]); + add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]); if (v3d && v3d->zbuf) glDisable(GL_DEPTH_TEST); @@ -6297,12 +6297,12 @@ static void drawEdgeSlide(const struct bContext *C, TransInfo *t) glLineWidth(line_size); UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); glBegin(GL_LINES); - if (curr_sv->v_a) { - glVertex3fv(curr_sv->v_a->co); + if (curr_sv->v_side[0]) { + glVertex3fv(curr_sv->v_side[0]->co); glVertex3fv(curr_sv->v_co_orig); } - if (curr_sv->v_b) { - glVertex3fv(curr_sv->v_b->co); + if (curr_sv->v_side[1]) { + glVertex3fv(curr_sv->v_side[1]->co); glVertex3fv(curr_sv->v_co_orig); } bglEnd(); @@ -6312,10 +6312,10 @@ static void drawEdgeSlide(const struct bContext *C, TransInfo *t) glPointSize(ctrl_size); bglBegin(GL_POINTS); if (sld->flipped_vtx) { - if (curr_sv->v_b) bglVertex3fv(curr_sv->v_b->co); + if (curr_sv->v_side[1]) bglVertex3fv(curr_sv->v_side[1]->co); } else { - if (curr_sv->v_a) bglVertex3fv(curr_sv->v_a->co); + if (curr_sv->v_side[0]) bglVertex3fv(curr_sv->v_side[0]->co); } bglEnd(); @@ -6355,12 +6355,12 @@ static void doEdgeSlide(TransInfo *t, float perc) for (i = 0; i < sld->totsv; i++, sv++) { float vec[3]; if (perc > 0.0f) { - copy_v3_v3(vec, sv->dir_a); + copy_v3_v3(vec, sv->dir_side[0]); mul_v3_fl(vec, perc); add_v3_v3v3(sv->v->co, sv->v_co_orig, vec); } else { - copy_v3_v3(vec, sv->dir_b); + copy_v3_v3(vec, sv->dir_side[1]); mul_v3_fl(vec, -perc); add_v3_v3v3(sv->v->co, sv->v_co_orig, vec); } @@ -6372,7 +6372,7 @@ static void doEdgeSlide(TransInfo *t, float perc) * a/b verts, this could be changed/improved so the distance is still met but the verts are moved along * their original path (which may not be straight), however how it works now is OK and matches 2.4x - Campbell * - * \note len_v3v3(curr_sv->dir_a, curr_sv->dir_b) + * \note len_v3v3(curr_sv->dir_side[0], curr_sv->dir_side[1]) * is the same as the distance between the original vert locations, same goes for the lines below. */ TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; @@ -6385,8 +6385,8 @@ static void doEdgeSlide(TransInfo *t, float perc) if (sv->edge_len > FLT_EPSILON) { const float fac = min_ff(sv->edge_len, curr_length_perc) / sv->edge_len; - add_v3_v3v3(co_a, sv->v_co_orig, sv->dir_a); - add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_b); + add_v3_v3v3(co_a, sv->v_co_orig, sv->dir_side[0]); + add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_side[1]); if (sld->flipped_vtx) { interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index f5a9b3d6ae0..7edcdbfdf24 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -213,10 +213,10 @@ typedef struct TransDataEdgeSlideVert { float edge_len; - struct BMVert *v_a, *v_b; + struct BMVert *v_side[2]; /* add origvert.co to get the original locations */ - float dir_a[3], dir_b[3]; + float dir_side[2][3]; int loop_nr; } TransDataEdgeSlideVert; -- cgit v1.2.3 From 94b9b259e7a158522d99f126893a2ced0cffc9bc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 May 2015 20:10:05 +1000 Subject: Cleanup: remove unneeded context arg --- source/blender/editors/transform/transform.c | 30 +++++++++++++++------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 7687ade032a..cb04d2bf8fa 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -99,8 +99,8 @@ static void drawTransformApply(const struct bContext *C, ARegion *ar, void *arg) static void doEdgeSlide(TransInfo *t, float perc); static void doVertSlide(TransInfo *t, float perc); -static void drawEdgeSlide(const struct bContext *C, TransInfo *t); -static void drawVertSlide(const struct bContext *C, TransInfo *t); +static void drawEdgeSlide(TransInfo *t); +static void drawVertSlide(TransInfo *t); static void len_v3_ensure(float v[3], const float length); static void postInputRotation(TransInfo *t, float values[3]); @@ -1829,8 +1829,8 @@ static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), voi drawSnapping(C, t); /* edge slide, vert slide */ - drawEdgeSlide(C, t); - drawVertSlide(C, t); + drawEdgeSlide(t); + drawVertSlide(t); } /* just draw a little warning message in the top-right corner of the viewport to warn that autokeying is enabled */ @@ -6265,13 +6265,14 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven return TREDRAW_NOTHING; } -static void drawEdgeSlide(const struct bContext *C, TransInfo *t) +static void drawEdgeSlide(TransInfo *t) { - if (t->mode == TFM_EDGE_SLIDE) { - EdgeSlideData *sld = (EdgeSlideData *)t->customData; + if ((t->mode == TFM_EDGE_SLIDE) && t->customData) { + EdgeSlideData *sld = t->customData; + /* Non-Prop mode */ - if (sld && sld->is_proportional == false) { - View3D *v3d = CTX_wm_view3d(C); + if (sld->is_proportional == false) { + View3D *v3d = t->view; float co_a[3], co_b[3], co_mark[3]; TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; const float fac = (sld->perc + 1.0f) / 2.0f; @@ -6825,13 +6826,14 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven return TREDRAW_NOTHING; } -static void drawVertSlide(const struct bContext *C, TransInfo *t) +static void drawVertSlide(TransInfo *t) { - if (t->mode == TFM_VERT_SLIDE) { - VertSlideData *sld = (VertSlideData *)t->customData; + if ((t->mode == TFM_VERT_SLIDE) && t->customData) { + VertSlideData *sld = t->customData; + /* Non-Prop mode */ - if (sld) { - View3D *v3d = CTX_wm_view3d(C); + { + View3D *v3d = t->view; TransDataVertSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; TransDataVertSlideVert *sv; const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; -- cgit v1.2.3 From e3b0d5e99ba70a5b89fa3351b1e53d683967c944 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 May 2015 21:28:03 +1000 Subject: EdgeSlide: support for un-clamped sliding Functionality matches vertex slide. --- source/blender/editors/transform/transform.c | 220 +++++++++++++++-------- source/blender/editors/transform/transform.h | 3 + source/blender/editors/transform/transform_ops.c | 2 +- 3 files changed, 153 insertions(+), 72 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index cb04d2bf8fa..eb19b9cc855 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -5445,6 +5445,19 @@ static void slide_origdata_free_date( /** \name Transform Edge Slide * \{ */ +static void calcEdgeSlideCustomPoints(struct TransInfo *t) +{ + EdgeSlideData *sld = t->customData; + + setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start); + + /* setCustomPoints isn't normally changing as the mouse moves, + * in this case apply mouse input immediatly so we don't refresh + * with the value from the previous points */ + applyMouseInput(t, &t->mouse, t->mval, t->values); +} + + static BMEdge *get_other_edge(BMVert *v, BMEdge *e) { BMIter iter; @@ -6202,7 +6215,7 @@ static void initEdgeSlide(TransInfo *t) t->customFree = freeEdgeSlideVerts; /* set custom point first if you want value to be initialized by init */ - setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start); + calcEdgeSlideCustomPoints(t); initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO_FLIP); t->idx_max = 0; @@ -6228,6 +6241,7 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven case EKEY: if (event->val == KM_PRESS) { sld->is_proportional = !sld->is_proportional; + calcEdgeSlideCustomPoints(t); return TREDRAW_HARD; } break; @@ -6237,6 +6251,17 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven if (sld->is_proportional == false) { sld->flipped_vtx = !sld->flipped_vtx; } + calcEdgeSlideCustomPoints(t); + return TREDRAW_HARD; + } + break; + } + case CKEY: + { + /* use like a modifier key */ + if (event->val == KM_PRESS) { + t->flag ^= T_ALT_TRANSFORM; + calcEdgeSlideCustomPoints(t); return TREDRAW_HARD; } break; @@ -6257,6 +6282,11 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven } break; } + case MOUSEMOVE: + { + calcEdgeSlideCustomPoints(t); + break; + } default: break; } @@ -6269,20 +6299,12 @@ static void drawEdgeSlide(TransInfo *t) { if ((t->mode == TFM_EDGE_SLIDE) && t->customData) { EdgeSlideData *sld = t->customData; + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); /* Non-Prop mode */ - if (sld->is_proportional == false) { + if ((sld->is_proportional == false) || (is_clamp == false)) { View3D *v3d = t->view; - float co_a[3], co_b[3], co_mark[3]; - TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; - const float fac = (sld->perc + 1.0f) / 2.0f; - const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; - const float guide_size = ctrl_size - 0.5f; const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; - const int alpha_shade = -30; - - add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]); - add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]); if (v3d && v3d->zbuf) glDisable(GL_DEPTH_TEST); @@ -6295,42 +6317,88 @@ static void drawEdgeSlide(TransInfo *t) glMultMatrixf(t->obedit->obmat); - glLineWidth(line_size); - UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - glBegin(GL_LINES); - if (curr_sv->v_side[0]) { - glVertex3fv(curr_sv->v_side[0]->co); - glVertex3fv(curr_sv->v_co_orig); - } - if (curr_sv->v_side[1]) { - glVertex3fv(curr_sv->v_side[1]->co); - glVertex3fv(curr_sv->v_co_orig); - } - bglEnd(); + if (sld->is_proportional == false) { + float co_a[3], co_b[3], co_mark[3]; + TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + const float fac = (sld->perc + 1.0f) / 2.0f; + const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; + const float guide_size = ctrl_size - 0.5f; + const int alpha_shade = -30; + add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]); + add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]); - UI_ThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade); - glPointSize(ctrl_size); - bglBegin(GL_POINTS); - if (sld->flipped_vtx) { - if (curr_sv->v_side[1]) bglVertex3fv(curr_sv->v_side[1]->co); - } - else { - if (curr_sv->v_side[0]) bglVertex3fv(curr_sv->v_side[0]->co); - } - bglEnd(); + glLineWidth(line_size); + UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + glBegin(GL_LINES); + if (curr_sv->v_side[0]) { + glVertex3fv(curr_sv->v_side[0]->co); + glVertex3fv(curr_sv->v_co_orig); + } + if (curr_sv->v_side[1]) { + glVertex3fv(curr_sv->v_side[1]->co); + glVertex3fv(curr_sv->v_co_orig); + } + glEnd(); - UI_ThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade); - glPointSize(guide_size); - bglBegin(GL_POINTS); + UI_ThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade); + glPointSize(ctrl_size); + bglBegin(GL_POINTS); + if (sld->flipped_vtx) { + if (curr_sv->v_side[1]) bglVertex3fv(curr_sv->v_side[1]->co); + } + else { + if (curr_sv->v_side[0]) bglVertex3fv(curr_sv->v_side[0]->co); + } + bglEnd(); + + UI_ThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade); + glPointSize(guide_size); + bglBegin(GL_POINTS); #if 0 - interp_v3_v3v3(co_mark, co_b, co_a, fac); - bglVertex3fv(co_mark); + interp_v3_v3v3(co_mark, co_b, co_a, fac); + bglVertex3fv(co_mark); #endif - interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac); - bglVertex3fv(co_mark); - bglEnd(); + interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac); + bglVertex3fv(co_mark); + bglEnd(); + } + else { + if (is_clamp == false) { + const int side_index = sld->curr_side_unclamp; + TransDataEdgeSlideVert *sv; + int i; + const int alpha_shade = -160; + + glLineWidth(line_size); + UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + glBegin(GL_LINES); + + sv = sld->sv; + for (i = 0; i < sld->totsv; i++, sv++) { + float a[3], b[3]; + + if (!is_zero_v3(sv->dir_side[side_index])) { + copy_v3_v3(a, sv->dir_side[side_index]); + } + else { + copy_v3_v3(a, sv->dir_side[!side_index]); + } + mul_v3_fl(a, 100.0f); + negate_v3_v3(b, a); + add_v3_v3(a, sv->v_co_orig); + add_v3_v3(b, sv->v_co_orig); + + glVertex3fv(a); + glVertex3fv(b); + } + glEnd(); + } + else { + BLI_assert(0); + } + } glPopMatrix(); glPopAttrib(); @@ -6353,17 +6421,30 @@ static void doEdgeSlide(TransInfo *t, float perc) sv = svlist; if (sld->is_proportional == true) { - for (i = 0; i < sld->totsv; i++, sv++) { - float vec[3]; - if (perc > 0.0f) { - copy_v3_v3(vec, sv->dir_side[0]); - mul_v3_fl(vec, perc); - add_v3_v3v3(sv->v->co, sv->v_co_orig, vec); + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + if (is_clamp) { + const int side_index = (perc < 0.0f); + const float perc_final = fabsf(perc); + for (i = 0; i < sld->totsv; i++, sv++) { + madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, sv->dir_side[side_index], perc_final); } - else { - copy_v3_v3(vec, sv->dir_side[1]); - mul_v3_fl(vec, -perc); - add_v3_v3v3(sv->v->co, sv->v_co_orig, vec); + + sld->curr_side_unclamp = side_index; + } + else { + const int side_index = sld->curr_side_unclamp; + const float perc_init = fabsf(perc) * ((sld->curr_side_unclamp == (perc < 0.0f)) ? 1 : -1); + for (i = 0; i < sld->totsv; i++, sv++) { + float dir_flip[3]; + float perc_final = perc_init; + if (!is_zero_v3(sv->dir_side[side_index])) { + copy_v3_v3(dir_flip, sv->dir_side[side_index]); + } + else { + copy_v3_v3(dir_flip, sv->dir_side[!side_index]); + perc_final *= -1; + } + madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, dir_flip, perc_final); } } } @@ -6405,44 +6486,41 @@ static void doEdgeSlide(TransInfo *t, float perc) static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2])) { char str[MAX_INFO_LEN]; + size_t ofs = 0; float final; EdgeSlideData *sld = t->customData; bool flipped = sld->flipped_vtx; bool is_proportional = sld->is_proportional; + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num)); final = t->values[0]; snapGridIncrement(t, &final); /* only do this so out of range values are not displayed */ - CLAMP(final, -1.0f, 1.0f); + if (is_constrained) { + CLAMP(final, -1.0f, 1.0f); + } applyNumInput(&t->num, &final); + /* header string */ + ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Edge Slide: "), MAX_INFO_LEN - ofs); if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); - - if (is_proportional) { - BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %s (E)ven: %s"), - &c[0], WM_bool_as_string(!is_proportional)); - } - else { - BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %s (E)ven: %s, (F)lipped: %s"), - &c[0], WM_bool_as_string(!is_proportional), WM_bool_as_string(flipped)); - } - } - else if (is_proportional) { - BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %.4f (E)ven: %s"), - final, WM_bool_as_string(!is_proportional)); + ofs += BLI_strncpy_rlen(str + ofs, &c[0], MAX_INFO_LEN - ofs); } else { - BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %.4f (E)ven: %s, (F)lipped: %s"), - final, WM_bool_as_string(!is_proportional), WM_bool_as_string(flipped)); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "%.4f ", final); } - - CLAMP(final, -1.0f, 1.0f); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(!is_proportional)); + if (!is_proportional) { + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped)); + } + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp)); + /* done with header string */ t->values[0] = final; @@ -6830,6 +6908,7 @@ static void drawVertSlide(TransInfo *t) { if ((t->mode == TFM_VERT_SLIDE) && t->customData) { VertSlideData *sld = t->customData; + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); /* Non-Prop mode */ { @@ -6839,7 +6918,6 @@ static void drawVertSlide(TransInfo *t) const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; const int alpha_shade = -160; - const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); int i; if (v3d && v3d->zbuf) diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 7edcdbfdf24..418fb8e1961 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -253,6 +253,9 @@ typedef struct EdgeSlideData { bool flipped_vtx; int curr_sv_index; + + /** when un-clamped - use this index: #TransDataEdgeSlideVert.dir_side */ + int curr_side_unclamp; } EdgeSlideData; diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 8e0b3d708e2..fdb9d51602d 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -848,7 +848,7 @@ static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot) ot->cancel = transform_cancel; ot->poll = ED_operator_editmesh; - RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f); + RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f); Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV); } -- cgit v1.2.3 From e39ec27bbaebcb85b2541e9756b408c554f602cb Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 7 May 2015 14:08:28 +0200 Subject: Fix crash when rendering opengl from sequencer. --- source/blender/editors/render/render_opengl.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index fbe6316905f..5c69748e423 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -238,8 +238,13 @@ static void screen_opengl_views_setup(OGLRender *oglrender) BLI_unlock_thread(LOCK_DRAW_IMAGE); /* will only work for non multiview correctly */ - camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, "new opengl render view"); - BKE_render_result_stamp_info(oglrender->scene, camera, rr); + if (v3d) { + camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, "new opengl render view"); + BKE_render_result_stamp_info(oglrender->scene, camera, rr); + } + else { + BKE_render_result_stamp_info(oglrender->scene, oglrender->scene->camera, rr); + } RE_ReleaseResult(oglrender->re); } -- cgit v1.2.3 From e6a7fdd3092939d4a0a1a08459c464597970427a Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 7 May 2015 14:49:40 +0200 Subject: Fix T44627, black spots with lock alpha in projection paint: Painting would revert alpha even on unpainted pixels, where values would contain garbage. --- .../blender/editors/sculpt_paint/paint_image_proj.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 6f34db4e424..00fac6b1c8e 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -4837,18 +4837,18 @@ static void *do_projectpaint_thread(void *ph_v) else do_projectpaint_draw(ps, projPixel, texrgb, mask, ps->dither, projPixel->x_px, projPixel->y_px); break; } - } - if (lock_alpha) { - if (is_floatbuf) { - /* slightly more involved case since floats are in premultiplied space we need - * to make sure alpha is consistent, see T44627 */ - float rgb_straight[4]; - premul_to_straight_v4_v4(rgb_straight, projPixel->pixel.f_pt); - rgb_straight[3] = projPixel->origColor.f_pt[3]; - straight_to_premul_v4_v4(projPixel->pixel.f_pt, rgb_straight); + if (lock_alpha) { + if (is_floatbuf) { + /* slightly more involved case since floats are in premultiplied space we need + * to make sure alpha is consistent, see T44627 */ + float rgb_straight[4]; + premul_to_straight_v4_v4(rgb_straight, projPixel->pixel.f_pt); + rgb_straight[3] = projPixel->origColor.f_pt[3]; + straight_to_premul_v4_v4(projPixel->pixel.f_pt, rgb_straight); + } + else projPixel->pixel.ch_pt[3] = projPixel->origColor.ch_pt[3]; } - else projPixel->pixel.ch_pt[3] = projPixel->origColor.ch_pt[3]; } /* done painting */ -- cgit v1.2.3 From 15fd37fab23ad906942726162a677d9254a94be4 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 7 May 2015 15:03:55 +0200 Subject: Rake: store last position from mouse, don't store halfpoint between last and current position. patch by Bastien --- source/blender/blenkernel/intern/paint.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 3900ba8b5ea..1284ffda0ff 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -536,7 +536,6 @@ static void update_brush_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, const float mouse_pos[2]) { if ((brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) || (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) { - const float u = 0.5f; const float r = RAKE_THRESHHOLD; float rotation; @@ -546,8 +545,7 @@ void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, cons if (len_squared_v2(dpos) >= r * r) { rotation = atan2f(dpos[0], dpos[1]); - interp_v2_v2v2(ups->last_rake, ups->last_rake, - mouse_pos, u); + copy_v2_v2(ups->last_rake, mouse_pos); ups->last_rake_angle = rotation; -- cgit v1.2.3 From aa3fc89257f839260e7577881f399011a709badf Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 7 May 2015 15:16:10 +0200 Subject: Fix T44611: 'make_links_data' modifiers would fail and crash with multires modifier. Since it was not ensuring dest has valid mdisp data matching new multires modifier subdiv level... Also, fixed a bug in `multires_subdivide()`, which would crash when trying to increase from level 0 (aka no subdiv) to > 1 (wrong check, trying to interpolate when it should not). And added a few sanity checks. --- source/blender/blenkernel/BKE_multires.h | 5 ++-- source/blender/blenkernel/intern/multires.c | 44 +++++++++++++++++++---------- source/blender/blenkernel/intern/object.c | 7 +++++ 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 627b8d6fdbd..a8242a529f3 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -79,8 +79,9 @@ struct DerivedMesh *get_multires_dm(struct Scene *scene, struct MultiresModifier struct Object *ob); void multiresModifier_del_levels(struct MultiresModifierData *, struct Object *, int direction); void multiresModifier_base_apply(struct MultiresModifierData *mmd, struct Object *ob); -void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob, - int updateblock, int simple); +void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob, int updateblock, int simple); +void multiresModifier_sync_levels_ex( + struct Object *ob_dst, struct MultiresModifierData *mmd_src, struct MultiresModifierData *mmd_dst); int multiresModifier_reshape(struct Scene *scene, struct MultiresModifierData *mmd, struct Object *dst, struct Object *src); int multiresModifier_reshapeFromDM(struct Scene *scene, struct MultiresModifierData *mmd, diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index e4bf05c2b5b..0c984c38b8e 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -882,18 +882,20 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl { Mesh *me = ob->data; MDisps *mdisps; - int lvl = mmd->totlvl; + const int lvl = mmd->totlvl; if ((totlvl > multires_max_levels) || (me->totpoly == 0)) return; + BLI_assert(totlvl > lvl); + multires_force_update(ob); mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); if (!mdisps) mdisps = multires_mdisps_initialize_hidden(me, totlvl); - if (mdisps->disps && !updateblock && totlvl > 1) { + if (mdisps->disps && !updateblock && lvl != 0) { /* upsample */ DerivedMesh *lowdm, *cddm, *highdm; CCGElem **highGridData, **lowGridData, **subGridData; @@ -910,6 +912,7 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl /* create multires DM from original mesh at low level */ lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple, has_mask); + BLI_assert(lowdm != cddm); cddm->release(cddm); /* copy subsurf grids and replace them with low displaced grids */ @@ -2137,27 +2140,38 @@ void multires_load_old(Object *ob, Mesh *me) me->mr = NULL; } -/* If 'ob' and 'to_ob' both have multires modifiers, synchronize them - * such that 'ob' has the same total number of levels as 'to_ob'. */ -static void multires_sync_levels(Scene *scene, Object *ob, Object *to_ob) +/* If 'ob_src' and 'ob_dst' both have multires modifiers, synchronize them + * such that 'ob_dst' has the same total number of levels as 'ob_src'. */ +void multiresModifier_sync_levels_ex(Object *ob_dst, MultiresModifierData *mmd_src, MultiresModifierData *mmd_dst) { - MultiresModifierData *mmd = get_multires_modifier(scene, ob, 1); - MultiresModifierData *to_mmd = get_multires_modifier(scene, to_ob, 1); + if (mmd_src->totlvl == mmd_dst->totlvl) { + return; + } + + if (mmd_src->totlvl > mmd_dst->totlvl) { + multires_subdivide(mmd_dst, ob_dst, mmd_src->totlvl, false, mmd_dst->simple); + } + else { + multires_del_higher(mmd_dst, ob_dst, mmd_src->totlvl); + } +} - if (!mmd) { +static void multires_sync_levels(Scene *scene, Object *ob_src, Object *ob_dst) +{ + MultiresModifierData *mmd_src = get_multires_modifier(scene, ob_src, true); + MultiresModifierData *mmd_dst = get_multires_modifier(scene, ob_dst, true); + + if (!mmd_src) { /* object could have MDISP even when there is no multires modifier * this could lead to troubles due to i've got no idea how mdisp could be * upsampled correct without modifier data. * just remove mdisps if no multires present (nazgul) */ - multires_customdata_delete(ob->data); + multires_customdata_delete(ob_src->data); } - if (mmd && to_mmd) { - if (mmd->totlvl > to_mmd->totlvl) - multires_del_higher(mmd, ob, to_mmd->totlvl); - else - multires_subdivide(mmd, ob, to_mmd->totlvl, 0, mmd->simple); + if (mmd_src && mmd_dst) { + multiresModifier_sync_levels_ex(ob_dst, mmd_src, mmd_dst); } } @@ -2276,7 +2290,7 @@ void multiresModifier_scale_disp(Scene *scene, Object *ob) void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob) { float smat[3][3], tmat[3][3], mat[3][3]; - multires_sync_levels(scene, ob, to_ob); + multires_sync_levels(scene, to_ob, ob); /* construct scale matrix for displacement */ BKE_object_scale_to_mat3(to_ob, tmat); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index bd0b7275174..5b29187e7cd 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -96,6 +96,7 @@ #include "BKE_editmesh.h" #include "BKE_mball.h" #include "BKE_modifier.h" +#include "BKE_multires.h" #include "BKE_node.h" #include "BKE_object.h" #include "BKE_paint.h" @@ -280,6 +281,12 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src) nmd = modifier_new(md->type); BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); + + if (md->type == eModifierType_Multires) { + /* Has to be done after mod creation, but *before* we actually copy its settings! */ + multiresModifier_sync_levels_ex(ob_dst, (MultiresModifierData *)md, (MultiresModifierData *)nmd); + } + modifier_copyData(md, nmd); BLI_addtail(&ob_dst->modifiers, nmd); modifier_unique_name(&ob_dst->modifiers, nmd); -- cgit v1.2.3 From a2eb94b47032502a65027db4b241a40e56f767eb Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 7 May 2015 15:32:37 +0200 Subject: Fix T44631: Custom Normal Data Transfer crash. Own stupid mistake in rBcdabf7e3... --- source/blender/blenkernel/intern/mesh_remap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c index 36b8a3264e9..0ed10687fae 100644 --- a/source/blender/blenkernel/intern/mesh_remap.c +++ b/source/blender/blenkernel/intern/mesh_remap.c @@ -1304,7 +1304,7 @@ void BKE_mesh_remap_calc_loops_from_dm( /* A same vert may be at the boundary of several islands! Hence, we have to ensure * poly/loop we are currently considering *belongs* to current island! */ - if (island_store.items_to_islands[lidx_src] != tindex) { + if (use_islands && island_store.items_to_islands[lidx_src] != tindex) { continue; } -- cgit v1.2.3 From a5dead2e8cee27c33771f7d74020ef9e15beceee Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 7 May 2015 18:10:34 +0200 Subject: Fix T44604 bad quality of rake with bezier curves. We can calculate tangents analytically for bezier curves, so just make them awesome. New code uses forward differencing calculation for efficiency just like curve calculation. Picture before/after: http://www.pasteall.org/pic/87843 --- source/blender/blenkernel/BKE_curve.h | 1 + source/blender/blenkernel/BKE_paint.h | 1 + source/blender/blenkernel/intern/curve.c | 24 +++++++++++++++++ source/blender/blenkernel/intern/paint.c | 7 +++-- source/blender/editors/sculpt_paint/paint_stroke.c | 30 ++++++++++++++++++++-- 5 files changed, 57 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 9de13ce9240..3ecd472f65b 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -120,6 +120,7 @@ void BKE_curve_bevel_make(struct Scene *scene, struct Object *ob, struct ListBa const bool for_render, const bool use_render_resolution); void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride); +void BKE_curve_forward_diff_tangent_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride); void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect); diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 34b645ea62c..09ccc3dced7 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -144,6 +144,7 @@ float paint_grid_paint_mask(const struct GridPaintMask *gpm, unsigned level, /* stroke related */ void paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, struct Brush *brush, const float mouse_pos[2]); +void paint_update_brush_rake_rotation(struct UnifiedPaintSettings *ups, struct Brush *brush, float rotation); void BKE_paint_stroke_get_average(struct Scene *scene, struct Object *ob, float stroke[3]); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 30ceaea89b8..c27460b81c0 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1384,6 +1384,30 @@ void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float } } +/* forward differencing method for first derivative of cubic bezier curve */ +void BKE_curve_forward_diff_tangent_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride) +{ + float rt0, rt1, rt2, f; + int a; + + f = 1.0f / (float)it; + + rt0 = 3.0f * (q1 - q0); + rt1 = f * (3.0f * (q3 - q0) + 9.0f * (q1 - q2)); + rt2 = 6.0f * (q0 + q2)- 12.0f * q1; + + q0 = rt0; + q1 = f * (rt1 + rt2); + q2 = 2.0f * f * rt1; + + for (a = 0; a <= it; a++) { + *p = q0; + p = (float *)(((char *)p) + stride); + q0 += q1; + q1 += q2; + } +} + static void forward_diff_bezier_cotangent(const float p0[3], const float p1[3], const float p2[3], const float p3[3], float p[3], int it, int stride) { diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 1284ffda0ff..0bda740af53 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -519,7 +519,7 @@ float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level, /* threshold to move before updating the brush rotation */ #define RAKE_THRESHHOLD 20 -static void update_brush_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, float rotation) +void paint_update_brush_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, float rotation) { if (brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) ups->brush_rotation = rotation; @@ -527,7 +527,6 @@ static void update_brush_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, ups->brush_rotation = 0.0f; if (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE) - /* here, translation contains the mouse coordinates. */ ups->brush_rotation_sec = rotation; else ups->brush_rotation_sec = 0.0f; @@ -549,12 +548,12 @@ void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, cons ups->last_rake_angle = rotation; - update_brush_rake_rotation(ups, brush, rotation); + paint_update_brush_rake_rotation(ups, brush, rotation); } /* make sure we reset here to the last rotation to avoid accumulating * values in case a random rotation is also added */ else { - update_brush_rake_rotation(ups, brush, ups->last_rake_angle); + paint_update_brush_rake_rotation(ups, brush, ups->last_rake_angle); } } else { diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 2ae544706df..d5c3e7e7fab 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -347,7 +347,8 @@ static bool paint_brush_update(bContext *C, if (!stroke->brush_init) { copy_v2_v2(ups->last_rake, mouse_init); } - else { + /* curve strokes do their own rake calculation */ + else if (!(brush->flag & BRUSH_CURVE)) { paint_calculate_rake_rotation(ups, brush, mouse_init); } } @@ -954,6 +955,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str Brush *br = stroke->brush; if (br->flag & BRUSH_CURVE) { + UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; const Scene *scene = CTX_data_scene(C); const float spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f); PaintCurve *pc = br->paint_curve; @@ -974,29 +976,53 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str for (i = 0; i < pc->tot_points - 1; i++, pcp++) { int j; float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2]; + float tangents[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2]; PaintCurvePoint *pcp_next = pcp + 1; + bool do_rake = false; - for (j = 0; j < 2; j++) + for (j = 0; j < 2; j++) { BKE_curve_forward_diff_bezier( pcp->bez.vec[1][j], pcp->bez.vec[2][j], pcp_next->bez.vec[0][j], pcp_next->bez.vec[1][j], data + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2])); + } + if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) || + (br->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) + { + do_rake = true; + for (j = 0; j < 2; j++) { + BKE_curve_forward_diff_tangent_bezier( + pcp->bez.vec[1][j], + pcp->bez.vec[2][j], + pcp_next->bez.vec[0][j], + pcp_next->bez.vec[1][j], + tangents + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2])); + } + } for (j = 0; j < PAINT_CURVE_NUM_SEGMENTS; j++) { + float rotation = 0.0f; + if (do_rake) { + normalize_v2_v2(&tangents[2 * j], &tangents[2 * j]); + rotation = atan2f(tangents[2 * j], tangents[2 * j + 1]); + } + if (!stroke->stroke_started) { stroke->last_pressure = 1.0; copy_v2_v2(stroke->last_mouse_position, data + 2 * j); stroke->stroke_started = stroke->test_start(C, op, stroke->last_mouse_position); if (stroke->stroke_started) { + paint_update_brush_rake_rotation(ups, br, rotation); paint_brush_stroke_add_step(C, op, data + 2 * j, 1.0); paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1)); } } else { + paint_update_brush_rake_rotation(ups, br, rotation); paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1)); } } -- cgit v1.2.3 From 0a82c3cfefa64a7c0bdafb4ef34600142e411616 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 7 May 2015 18:32:35 +0200 Subject: Minor cleanup --- source/blender/editors/sculpt_paint/paint_stroke.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index d5c3e7e7fab..21beb97ffae 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -1004,10 +1004,9 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str } for (j = 0; j < PAINT_CURVE_NUM_SEGMENTS; j++) { - float rotation = 0.0f; if (do_rake) { - normalize_v2_v2(&tangents[2 * j], &tangents[2 * j]); - rotation = atan2f(tangents[2 * j], tangents[2 * j + 1]); + float rotation = atan2f(tangents[2 * j], tangents[2 * j + 1]); + paint_update_brush_rake_rotation(ups, br, rotation); } if (!stroke->stroke_started) { @@ -1016,13 +1015,11 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str stroke->stroke_started = stroke->test_start(C, op, stroke->last_mouse_position); if (stroke->stroke_started) { - paint_update_brush_rake_rotation(ups, br, rotation); paint_brush_stroke_add_step(C, op, data + 2 * j, 1.0); paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1)); } } else { - paint_update_brush_rake_rotation(ups, br, rotation); paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1)); } } -- cgit v1.2.3 From e0109604319739e2bc62b7ecf868fea9e1192b60 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 8 May 2015 06:46:16 +1000 Subject: DNA; document how to ignore a struct --- source/blender/makesdna/DNA_documentation.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/source/blender/makesdna/DNA_documentation.h b/source/blender/makesdna/DNA_documentation.h index 0dd7f37f8b4..0a0d46d70ff 100644 --- a/source/blender/makesdna/DNA_documentation.h +++ b/source/blender/makesdna/DNA_documentation.h @@ -48,6 +48,24 @@ * be badly defined. The reason for this is that it is called with * different types of arguments. It takes a char* at this moment... * + * - Ignoring structs: + * + * Sometimes we need to define structs in DNA which aren't written + * to disk, and can be excluded from blend file DNA string. + * in this case, add two '#' chars directly before the struct. eg. + * + * \code{.c} + * # + * # + * typedef struct MyStruct { + * int value; + * } MyStruct; + * \endcode + * + * Ignored structs can only be referred to from non-ignored structs + * when referred to as a pointer (where they're usually allocated + * and cleared in ``readfile.c``). + * * - %Path to the header files * * Also because of historical reasons, there is a path prefix to the -- cgit v1.2.3 From a077be36580e40af7ef3a84e8a52b8e90a61a0e5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 8 May 2015 07:25:39 +1000 Subject: Cleanup: use r_* prefix for return args --- source/blender/blenkernel/BKE_image.h | 2 +- source/blender/blenkernel/BKE_movieclip.h | 2 +- source/blender/blenkernel/BKE_tracking.h | 2 +- source/blender/blenkernel/intern/image.c | 26 ++++++++-------- source/blender/blenkernel/intern/movieclip.c | 8 ++--- source/blender/blenkernel/intern/packedFile.c | 12 ++++---- source/blender/blenkernel/intern/tracking.c | 6 ++-- source/blender/editors/include/BIF_glutil.h | 4 +-- source/blender/editors/include/ED_image.h | 2 +- source/blender/editors/screen/glutil.c | 2 +- source/blender/editors/space_clip/clip_editor.c | 16 +++++----- source/blender/editors/space_image/image_edit.c | 6 ++-- source/blender/makesrna/intern/rna_sequencer.c | 4 +-- source/blender/windowmanager/WM_keymap.h | 3 +- source/blender/windowmanager/intern/wm_keymap.c | 36 +++++++++++++---------- source/blender/windowmanager/intern/wm_playanim.c | 6 ++-- source/blender/windowmanager/intern/wm_window.c | 18 ++++++------ source/blender/windowmanager/wm_window.h | 6 ++-- source/blenderplayer/bad_level_call_stubs/stubs.c | 2 +- 19 files changed, 85 insertions(+), 78 deletions(-) diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 155f26d9bd9..a49301eebee 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -155,7 +155,7 @@ bool BKE_image_has_ibuf(struct Image *ima, struct ImageUser *iuser); /* same as above, but can be used to retrieve images being rendered in * a thread safe way, always call both acquire and release */ -struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **lock_r); +struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock); void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock); struct ImagePool *BKE_image_pool_new(void); diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index 2cdd2ec88e0..7d7675270de 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -60,7 +60,7 @@ void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr); void BKE_movieclip_update_scopes(struct MovieClip *clip, struct MovieClipUser *user, struct MovieClipScopes *scopes); -void BKE_movieclip_get_cache_segments(struct MovieClip *clip, struct MovieClipUser *user, int *totseg_r, int **points_r); +void BKE_movieclip_get_cache_segments(struct MovieClip *clip, struct MovieClipUser *user, int *r_totseg, int **r_points); void BKE_movieclip_build_proxy_frame(struct MovieClip *clip, int clip_flag, struct MovieDistortion *distortion, int cfra, int *build_sizes, int build_count, bool undistorted); diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index ea56c084fb5..b03a234e1e7 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -90,7 +90,7 @@ struct MovieTrackingTrack *BKE_tracking_track_get_named(struct MovieTracking *tr struct MovieTrackingObject *object, const char *name); struct MovieTrackingTrack *BKE_tracking_track_get_indexed(struct MovieTracking *tracking, int tracknr, - struct ListBase **tracksbase_r); + struct ListBase **r_tracksbase); struct MovieTrackingTrack *BKE_tracking_track_get_active(struct MovieTracking *tracking); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 5169559d80b..4275b0200d0 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -101,7 +101,7 @@ static SpinLock image_spin; /* prototypes */ static size_t image_num_files(struct Image *ima); -static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r); +static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock); static void image_update_views_format(Image *ima, ImageUser *iuser); static void image_add_view(Image *ima, const char *viewname, const char *filepath); @@ -3522,7 +3522,7 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) /* showing RGBA result itself (from compo/sequence) or * like exr, using layers etc */ /* always returns a single ibuf, also during render progress */ -static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_r) +static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_lock) { Render *re; RenderResult rres; @@ -3540,7 +3540,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ return NULL; /* if we the caller is not going to release the lock, don't give the image */ - if (!lock_r) + if (!r_lock) return NULL; re = RE_GetRender(iuser->scene->id.name); @@ -3569,10 +3569,10 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ return NULL; } - /* release is done in BKE_image_release_ibuf using lock_r */ + /* release is done in BKE_image_release_ibuf using r_lock */ if (from_render) { BLI_lock_thread(LOCK_VIEWER); - *lock_r = re; + *r_lock = re; rv = NULL; } else { @@ -3855,13 +3855,13 @@ BLI_INLINE bool image_quick_test(Image *ima, ImageUser *iuser) * * not thread-safe, so callee should worry about thread locks */ -static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) +static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock) { ImBuf *ibuf = NULL; int frame = 0, index = 0; - if (lock_r) - *lock_r = NULL; + if (r_lock) + *r_lock = NULL; /* quick reject tests */ if (!image_quick_test(ima, iuser)) @@ -3910,14 +3910,14 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) if (ima->type == IMA_TYPE_R_RESULT) { /* always verify entirely, and potentially * returns pointer to release later */ - ibuf = image_get_render_result(ima, iuser, lock_r); + ibuf = image_get_render_result(ima, iuser, r_lock); } else if (ima->type == IMA_TYPE_COMPOSITE) { /* requires lock/unlock, otherwise don't return image */ - if (lock_r) { + if (r_lock) { /* unlock in BKE_image_release_ibuf */ BLI_lock_thread(LOCK_VIEWER); - *lock_r = ima; + *r_lock = ima; /* XXX anim play for viewer nodes not yet supported */ frame = 0; // XXX iuser ? iuser->framenr : 0; @@ -3951,13 +3951,13 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) * * references the result, BKE_image_release_ibuf should be used to de-reference */ -ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) +ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock) { ImBuf *ibuf; BLI_spin_lock(&image_spin); - ibuf = image_acquire_ibuf(ima, iuser, lock_r); + ibuf = image_acquire_ibuf(ima, iuser, r_lock); BLI_spin_unlock(&image_spin); diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 1aeb7bed86c..f063933f3f9 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1129,15 +1129,15 @@ void BKE_movieclip_get_aspect(MovieClip *clip, float *aspx, float *aspy) } /* get segments of cached frames. useful for debugging cache policies */ -void BKE_movieclip_get_cache_segments(MovieClip *clip, MovieClipUser *user, int *totseg_r, int **points_r) +void BKE_movieclip_get_cache_segments(MovieClip *clip, MovieClipUser *user, int *r_totseg, int **r_points) { - *totseg_r = 0; - *points_r = NULL; + *r_totseg = 0; + *r_points = NULL; if (clip->cache) { int proxy = rendersize_to_proxy(user, clip->flag); - IMB_moviecache_get_cache_segments(clip->cache->moviecache, proxy, user->render_flag, totseg_r, points_r); + IMB_moviecache_get_cache_segments(clip->cache->moviecache, proxy, user->render_flag, r_totseg, r_points); } } diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 68212521617..800df252c69 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -478,7 +478,7 @@ char *unpackFile(ReportList *reports, const char *abs_name, const char *local_na } static void unpack_generate_paths( - const char *name, ID *id, char *abspath_r, char *relpath_r, size_t abspathlen, size_t relpathlen) + const char *name, ID *id, char *r_abspath, char *r_relpath, size_t abspathlen, size_t relpathlen) { char tempname[FILE_MAX]; char tempdir[FILE_MAXDIR]; @@ -500,19 +500,19 @@ static void unpack_generate_paths( switch (GS(id->name)) { case ID_VF: - BLI_snprintf(relpath_r, relpathlen, "//fonts/%s", tempname); + BLI_snprintf(r_relpath, relpathlen, "//fonts/%s", tempname); break; case ID_SO: - BLI_snprintf(relpath_r, relpathlen, "//sounds/%s", tempname); + BLI_snprintf(r_relpath, relpathlen, "//sounds/%s", tempname); break; case ID_IM: - BLI_snprintf(relpath_r, relpathlen, "//textures/%s", tempname); + BLI_snprintf(r_relpath, relpathlen, "//textures/%s", tempname); break; } { - size_t len = BLI_strncpy_rlen(abspath_r, tempdir, abspathlen); - BLI_strncpy(abspath_r + len, tempname, abspathlen - len); + size_t len = BLI_strncpy_rlen(r_abspath, tempdir, abspathlen); + BLI_strncpy(r_abspath + len, tempname, abspathlen - len); } } diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index e3f04296f50..f9ae987db70 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -730,7 +730,7 @@ MovieTrackingTrack *BKE_tracking_track_get_named(MovieTracking *tracking, MovieT return NULL; } -MovieTrackingTrack *BKE_tracking_track_get_indexed(MovieTracking *tracking, int tracknr, ListBase **tracksbase_r) +MovieTrackingTrack *BKE_tracking_track_get_indexed(MovieTracking *tracking, int tracknr, ListBase **r_tracksbase) { MovieTrackingObject *object; int cur = 1; @@ -743,7 +743,7 @@ MovieTrackingTrack *BKE_tracking_track_get_indexed(MovieTracking *tracking, int while (track) { if (track->flag & TRACK_HAS_BUNDLE) { if (cur == tracknr) { - *tracksbase_r = tracksbase; + *r_tracksbase = tracksbase; return track; } @@ -756,7 +756,7 @@ MovieTrackingTrack *BKE_tracking_track_get_indexed(MovieTracking *tracking, int object = object->next; } - *tracksbase_r = NULL; + *r_tracksbase = NULL; return NULL; } diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h index 4dc39681ed2..b904417cfcb 100644 --- a/source/blender/editors/include/BIF_glutil.h +++ b/source/blender/editors/include/BIF_glutil.h @@ -181,8 +181,8 @@ typedef struct gla2DDrawInfo gla2DDrawInfo; #if 0 gla2DDrawInfo *glaBegin2DDraw(struct rcti *screen_rect, struct rctf *world_rect); -void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *sc_x_r, int *sc_y_r); -void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int screen_r[2]); +void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *r_sc_x, int *r_sc_y); +void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int r_screen[2]); void glaEnd2DDraw(gla2DDrawInfo *di); diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index fc42d2b5495..f49d4b508c6 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -47,7 +47,7 @@ struct Mask *ED_space_image_get_mask(struct SpaceImage *sima); void ED_space_image_set_mask(struct bContext *C, struct SpaceImage *sima, struct Mask *mask); bool ED_space_image_color_sample(struct Scene *scene, struct SpaceImage *sima, struct ARegion *ar, int mval[2], float r_col[3]); -struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **lock_r); +struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **r_lock); void ED_space_image_release_buffer(struct SpaceImage *sima, struct ImBuf *ibuf, void *lock); bool ED_space_image_has_buffer(struct SpaceImage *sima); diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 8a8b61e09fe..fd65d81baad 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -841,7 +841,7 @@ void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *r_sc_x /** * Translate the \a world point from world coordinates into screen space. */ -void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int screen_r[2]) +void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int r_screen[2]) { screen_r[0] = (world[0] - di->world_rect.xmin) * di->wo_to_sc[0]; screen_r[1] = (world[1] - di->world_rect.ymin) * di->wo_to_sc[1]; diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 89693a403fe..9acb9f3effc 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -626,8 +626,9 @@ static bool check_prefetch_break(void) } /* read file for specified frame number to the memory */ -static unsigned char *prefetch_read_file_to_memory(MovieClip *clip, int current_frame, short render_size, - short render_flag, size_t *size_r) +static unsigned char *prefetch_read_file_to_memory( + MovieClip *clip, int current_frame, short render_size, short render_flag, + size_t *r_size) { MovieClipUser user = {0}; char name[FILE_MAX]; @@ -660,7 +661,7 @@ static unsigned char *prefetch_read_file_to_memory(MovieClip *clip, int current_ return NULL; } - *size_r = size; + *r_size = size; close(file); @@ -698,8 +699,9 @@ static int prefetch_find_uncached_frame(MovieClip *clip, int from_frame, int end } /* get memory buffer for first uncached frame within prefetch frame range */ -static unsigned char *prefetch_thread_next_frame(PrefetchQueue *queue, MovieClip *clip, - size_t *size_r, int *current_frame_r) +static unsigned char *prefetch_thread_next_frame( + PrefetchQueue *queue, MovieClip *clip, + size_t *r_size, int *r_current_frame) { unsigned char *mem = NULL; @@ -728,9 +730,9 @@ static unsigned char *prefetch_thread_next_frame(PrefetchQueue *queue, MovieClip int frames_processed; mem = prefetch_read_file_to_memory(clip, current_frame, queue->render_size, - queue->render_flag, size_r); + queue->render_flag, r_size); - *current_frame_r = current_frame; + *r_current_frame = current_frame; queue->current_frame = current_frame; diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 19fa068a693..38c9604d14b 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -104,7 +104,7 @@ void ED_space_image_set_mask(bContext *C, SpaceImage *sima, Mask *mask) } } -ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r) +ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **r_lock) { ImBuf *ibuf; @@ -114,7 +114,7 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r) return BIF_render_spare_imbuf(); else #endif - ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, lock_r); + ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, r_lock); if (ibuf) { if (ibuf->rect || ibuf->rect_float) @@ -124,7 +124,7 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r) } } else - *lock_r = NULL; + *r_lock = NULL; return NULL; } diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 052744a9864..df996c8f31a 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -809,7 +809,7 @@ static int colbalance_seq_cmp_cb(Sequence *seq, void *arg_pt) return 1; } -static Sequence *sequence_get_by_colorbalance(Editing *ed, StripColorBalance *cb, SequenceModifierData **smd_r) +static Sequence *sequence_get_by_colorbalance(Editing *ed, StripColorBalance *cb, SequenceModifierData **r_smd) { SequenceSearchData data; @@ -820,7 +820,7 @@ static Sequence *sequence_get_by_colorbalance(Editing *ed, StripColorBalance *cb /* irritating we need to search for our sequence! */ BKE_sequencer_base_recursive_apply(&ed->seqbase, colbalance_seq_cmp_cb, &data); - *smd_r = data.smd; + *r_smd = data.smd; return data.seq; } diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h index c6c7314e963..fdde28c6bf1 100644 --- a/source/blender/windowmanager/WM_keymap.h +++ b/source/blender/windowmanager/WM_keymap.h @@ -101,7 +101,8 @@ int WM_keymap_map_type_get(struct wmKeyMapItem *kmi); const char *WM_key_event_string(short type); int WM_key_event_operator_id( const struct bContext *C, const char *opname, int opcontext, - struct IDProperty *properties, const bool is_hotkey, struct wmKeyMap **keymap_r); + struct IDProperty *properties, const bool is_hotkey, + struct wmKeyMap **r_keymap); char *WM_key_event_operator_string( const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, const bool is_strict, char *str, int len); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 82e46c1b333..0ee1f9f7eeb 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -929,7 +929,8 @@ int WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, const int len) static wmKeyMapItem *wm_keymap_item_find_handlers( const bContext *C, ListBase *handlers, const char *opname, int UNUSED(opcontext), - IDProperty *properties, const bool is_strict, const bool is_hotkey, wmKeyMap **keymap_r) + IDProperty *properties, const bool is_strict, const bool is_hotkey, + wmKeyMap **r_keymap) { wmWindowManager *wm = CTX_wm_manager(C); wmEventHandler *handler; @@ -966,7 +967,7 @@ static wmKeyMapItem *wm_keymap_item_find_handlers( #endif if (kmi->ptr && IDP_EqualsProperties_ex(properties, kmi->ptr->data, is_strict)) { - if (keymap_r) *keymap_r = keymap; + if (r_keymap) *r_keymap = keymap; return kmi; } /* Debug only, helps spotting mismatches between menu entries and shortcuts! */ @@ -1004,7 +1005,7 @@ static wmKeyMapItem *wm_keymap_item_find_handlers( } } else { - if (keymap_r) *keymap_r = keymap; + if (r_keymap) *r_keymap = keymap; return kmi; } } @@ -1013,13 +1014,14 @@ static wmKeyMapItem *wm_keymap_item_find_handlers( } /* ensure un-initialized keymap is never used */ - if (keymap_r) *keymap_r = NULL; + if (r_keymap) *r_keymap = NULL; return NULL; } static wmKeyMapItem *wm_keymap_item_find_props( const bContext *C, const char *opname, int opcontext, - IDProperty *properties, const bool is_strict, const bool is_hotkey, wmKeyMap **keymap_r) + IDProperty *properties, const bool is_strict, const bool is_hotkey, + wmKeyMap **r_keymap) { wmWindow *win = CTX_wm_window(C); ScrArea *sa = CTX_wm_area(C); @@ -1028,10 +1030,10 @@ static wmKeyMapItem *wm_keymap_item_find_props( /* look into multiple handler lists to find the item */ if (win) - found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap); if (sa && found == NULL) - found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap); if (found == NULL) { if (ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) { @@ -1040,7 +1042,7 @@ static wmKeyMapItem *wm_keymap_item_find_props( ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); if (ar) - found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap); } } else if (ELEM(opcontext, WM_OP_EXEC_REGION_CHANNELS, WM_OP_INVOKE_REGION_CHANNELS)) { @@ -1048,18 +1050,18 @@ static wmKeyMapItem *wm_keymap_item_find_props( ar = BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS); if (ar) - found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap); } else if (ELEM(opcontext, WM_OP_EXEC_REGION_PREVIEW, WM_OP_INVOKE_REGION_PREVIEW)) { if (!(ar && ar->regiontype == RGN_TYPE_PREVIEW)) ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW); if (ar) - found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap); } else { if (ar) - found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap); } } @@ -1068,7 +1070,8 @@ static wmKeyMapItem *wm_keymap_item_find_props( static wmKeyMapItem *wm_keymap_item_find( const bContext *C, const char *opname, int opcontext, - IDProperty *properties, const bool is_hotkey, bool is_strict, wmKeyMap **keymap_r) + IDProperty *properties, const bool is_hotkey, bool is_strict, + wmKeyMap **r_keymap) { wmKeyMapItem *found; @@ -1081,7 +1084,7 @@ static wmKeyMapItem *wm_keymap_item_find( is_strict = is_strict && ((ot->flag & OPTYPE_MACRO) == 0); } - found = wm_keymap_item_find_props(C, opname, opcontext, properties, is_strict, is_hotkey, keymap_r); + found = wm_keymap_item_find_props(C, opname, opcontext, properties, is_strict, is_hotkey, r_keymap); /* This block is *only* useful in one case: when op uses an enum menu in its prop member * (then, we want to rerun a comparison with that 'prop' unset). Note this remains brittle, @@ -1105,7 +1108,7 @@ static wmKeyMapItem *wm_keymap_item_find( RNA_property_unset(&opptr, ot->prop); found = wm_keymap_item_find_props(C, opname, opcontext, properties_temp, - is_strict, is_hotkey, keymap_r); + is_strict, is_hotkey, r_keymap); } IDP_FreeProperty(properties_temp); @@ -1167,9 +1170,10 @@ char *WM_key_event_operator_string( int WM_key_event_operator_id( const bContext *C, const char *opname, int opcontext, - IDProperty *properties, const bool is_hotkey, wmKeyMap **keymap_r) + IDProperty *properties, const bool is_hotkey, + wmKeyMap **r_keymap) { - wmKeyMapItem *kmi = wm_keymap_item_find(C, opname, opcontext, properties, is_hotkey, true, keymap_r); + wmKeyMapItem *kmi = wm_keymap_item_find(C, opname, opcontext, properties, is_hotkey, true, r_keymap); if (kmi) return kmi->id; diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 31883cf234c..061357c3906 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -160,11 +160,11 @@ static struct WindowStateGlobal { eWS_Qual qual; } g_WS = {NULL}; -static void playanim_window_get_size(int *width_r, int *height_r) +static void playanim_window_get_size(int *r_width, int *r_height) { GHOST_RectangleHandle bounds = GHOST_GetClientBounds(g_WS.ghost_window); - *width_r = GHOST_GetWidthRectangle(bounds); - *height_r = GHOST_GetHeightRectangle(bounds); + *r_width = GHOST_GetWidthRectangle(bounds); + *r_height = GHOST_GetHeightRectangle(bounds); GHOST_DisposeRectangle(bounds); } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index d69cf3326b7..9bcbbabc87b 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -107,25 +107,25 @@ static struct WMInitStruct { /* XXX this one should correctly check for apple top header... * done for Cocoa : returns window contents (and not frame) max size*/ -void wm_get_screensize(int *width_r, int *height_r) +void wm_get_screensize(int *r_width, int *r_height) { unsigned int uiwidth; unsigned int uiheight; GHOST_GetMainDisplayDimensions(g_system, &uiwidth, &uiheight); - *width_r = uiwidth; - *height_r = uiheight; + *r_width = uiwidth; + *r_height = uiheight; } /* size of all screens (desktop), useful since the mouse is bound by this */ -void wm_get_desktopsize(int *width_r, int *height_r) +void wm_get_desktopsize(int *r_width, int *r_height) { unsigned int uiwidth; unsigned int uiheight; GHOST_GetAllDisplayDimensions(g_system, &uiwidth, &uiheight); - *width_r = uiwidth; - *height_r = uiheight; + *r_width = uiwidth; + *r_height = uiheight; } /* keeps offset and size within monitor bounds */ @@ -1404,10 +1404,10 @@ void WM_progress_clear(wmWindow *win) /* ************************************ */ -void wm_window_get_position(wmWindow *win, int *posx_r, int *posy_r) +void wm_window_get_position(wmWindow *win, int *r_pos_x, int *r_pos_y) { - *posx_r = win->posx; - *posy_r = win->posy; + *r_pos_x = win->posx; + *r_pos_y = win->posy; } void wm_window_set_size(wmWindow *win, int width, int height) diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index fc7c9e191b0..95dc8762ae7 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -38,8 +38,8 @@ struct wmOperator; void wm_ghost_init (bContext *C); void wm_ghost_exit(void); -void wm_get_screensize(int *width_r, int *height_r); -void wm_get_desktopsize(int *width_r, int *height_r); +void wm_get_screensize(int *r_width, int *r_height); +void wm_get_desktopsize(int *r_width, int *r_height); wmWindow *wm_window_new (bContext *C); void wm_window_free (bContext *C, wmWindowManager *wm, wmWindow *win); @@ -55,7 +55,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win); void wm_window_raise (wmWindow *win); void wm_window_lower (wmWindow *win); void wm_window_set_size (wmWindow *win, int width, int height); -void wm_window_get_position (wmWindow *win, int *posx_r, int *posy_r); +void wm_window_get_position (wmWindow *win, int *r_pos_x, int *r_pos_y); void wm_window_swap_buffers (wmWindow *win); void wm_window_set_swap_interval(wmWindow *win, int interval); bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut); diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 08d01a9c79e..8e26a9e5b78 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -414,7 +414,7 @@ short ANIM_validate_keyingset(struct bContext *C, struct ListBase *dsources, str int ANIM_add_driver(struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag, int type) RET_ZERO bool ANIM_remove_driver(struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag) RET_ZERO void ED_space_image_release_buffer(struct SpaceImage *sima, struct ImBuf *ibuf, void *lock) RET_NONE -struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **lock_r) RET_NULL +struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **r_lock) RET_NULL void ED_space_image_get_zoom(struct SpaceImage *sima, struct ARegion *ar, float *zoomx, float *zoomy) RET_NONE const char *ED_info_stats_string(struct Scene *scene) RET_NULL void ED_area_tag_redraw(struct ScrArea *sa) RET_NONE -- cgit v1.2.3 From a8da11c014a664afbec3c0fe6fbbc63e67d8dedc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 8 May 2015 08:58:29 +1000 Subject: Add missing TEXTEDIT_UPDATE option --- source/blender/python/intern/bpy_props.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 0e9e6b74396..779c738b19f 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -68,7 +68,8 @@ static EnumPropertyItem property_flag_items[] = { {0, NULL, 0, NULL, NULL}}; #define BPY_PROPDEF_OPTIONS_DOC \ -" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'LIBRARY_EDITABLE', 'PROPORTIONAL'].\n" \ +" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'LIBRARY_EDITABLE', 'PROPORTIONAL'," \ + "'TEXTEDIT_UPDATE'].\n" \ " :type options: set\n" \ static EnumPropertyItem property_flag_enum_items[] = { -- cgit v1.2.3 From 9190d18b74fba4fc4134561e7a70190e12aeb045 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 8 May 2015 10:29:59 +0200 Subject: Fix T44634: Slide edge not responding to ALT + WHEEL to change reference edge in "even mode". Modal events (TFM_MODAL_EDGESLIDE_UP/_DOWN) were eaten by NOP generic transform event handling... --- source/blender/editors/transform/transform.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index eb19b9cc855..542955d9dad 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1251,11 +1251,6 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; } break; - case TFM_MODAL_EDGESLIDE_UP: - case TFM_MODAL_EDGESLIDE_DOWN: - t->redraw |= TREDRAW_HARD; - handled = true; - break; case TFM_MODAL_AUTOIK_LEN_INC: if (t->flag & T_AUTOIK) { transform_autoik_update(t, 1); @@ -1270,6 +1265,9 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; } break; + /* Those two are only handled in transform's own handler, see T44634! */ + case TFM_MODAL_EDGESLIDE_UP: + case TFM_MODAL_EDGESLIDE_DOWN: default: break; } @@ -6272,12 +6270,12 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven case TFM_MODAL_EDGESLIDE_DOWN: { sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv; - break; + return TREDRAW_HARD; } case TFM_MODAL_EDGESLIDE_UP: { sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv; - break; + return TREDRAW_HARD; } } break; -- cgit v1.2.3 From 945e302409db0c9677a857ff7d9339c21d1152b7 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 8 May 2015 10:38:53 +0200 Subject: Cleanup: #define -> enum, and get rid of useless braces in case's. --- source/blender/editors/transform/transform.c | 81 +++++++++++----------------- 1 file changed, 31 insertions(+), 50 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 542955d9dad..b49fe5eca5e 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -730,7 +730,6 @@ static void view_editmove(unsigned short UNUSED(event)) switch (event) { case WHEELUPMOUSE: - if (G.qual & LR_SHIFTKEY) { if (G.qual & LR_ALTKEY) { G.qual &= ~LR_SHIFTKEY; @@ -796,35 +795,38 @@ static void view_editmove(unsigned short UNUSED(event)) /* ************************************************* */ /* NOTE: these defines are saved in keymap files, do not change values but just add new ones */ -#define TFM_MODAL_CANCEL 1 -#define TFM_MODAL_CONFIRM 2 -#define TFM_MODAL_TRANSLATE 3 -#define TFM_MODAL_ROTATE 4 -#define TFM_MODAL_RESIZE 5 -#define TFM_MODAL_SNAP_INV_ON 6 -#define TFM_MODAL_SNAP_INV_OFF 7 -#define TFM_MODAL_SNAP_TOGGLE 8 -#define TFM_MODAL_AXIS_X 9 -#define TFM_MODAL_AXIS_Y 10 -#define TFM_MODAL_AXIS_Z 11 -#define TFM_MODAL_PLANE_X 12 -#define TFM_MODAL_PLANE_Y 13 -#define TFM_MODAL_PLANE_Z 14 -#define TFM_MODAL_CONS_OFF 15 -#define TFM_MODAL_ADD_SNAP 16 -#define TFM_MODAL_REMOVE_SNAP 17 -/* 18 and 19 used by numinput, defined in transform.h - * */ -#define TFM_MODAL_PROPSIZE_UP 20 -#define TFM_MODAL_PROPSIZE_DOWN 21 -#define TFM_MODAL_AUTOIK_LEN_INC 22 -#define TFM_MODAL_AUTOIK_LEN_DEC 23 - -#define TFM_MODAL_EDGESLIDE_UP 24 -#define TFM_MODAL_EDGESLIDE_DOWN 25 +enum { + TFM_MODAL_CANCEL = 1, + TFM_MODAL_CONFIRM = 2, + TFM_MODAL_TRANSLATE = 3, + TFM_MODAL_ROTATE = 4, + TFM_MODAL_RESIZE = 5, + TFM_MODAL_SNAP_INV_ON = 6, + TFM_MODAL_SNAP_INV_OFF = 7, + TFM_MODAL_SNAP_TOGGLE = 8, + TFM_MODAL_AXIS_X = 9, + TFM_MODAL_AXIS_Y = 10, + TFM_MODAL_AXIS_Z = 11, + TFM_MODAL_PLANE_X = 12, + TFM_MODAL_PLANE_Y = 13, + TFM_MODAL_PLANE_Z = 14, + TFM_MODAL_CONS_OFF = 15, + TFM_MODAL_ADD_SNAP = 16, + TFM_MODAL_REMOVE_SNAP = 17, + +/* 18 and 19 used by numinput, defined in transform.h */ + + TFM_MODAL_PROPSIZE_UP = 20, + TFM_MODAL_PROPSIZE_DOWN = 21, + TFM_MODAL_AUTOIK_LEN_INC = 22, + TFM_MODAL_AUTOIK_LEN_DEC = 23, + + TFM_MODAL_EDGESLIDE_UP = 24, + TFM_MODAL_EDGESLIDE_DOWN = 25, /* for analog input, like trackpad */ -#define TFM_MODAL_PROPSIZE 26 + TFM_MODAL_PROPSIZE = 26, +}; /* called in transform_ops.c, on each regeneration of keymaps */ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) @@ -6244,7 +6246,6 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven } break; case FKEY: - { if (event->val == KM_PRESS) { if (sld->is_proportional == false) { sld->flipped_vtx = !sld->flipped_vtx; @@ -6253,9 +6254,7 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven return TREDRAW_HARD; } break; - } case CKEY: - { /* use like a modifier key */ if (event->val == KM_PRESS) { t->flag ^= T_ALT_TRANSFORM; @@ -6263,28 +6262,19 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven return TREDRAW_HARD; } break; - } case EVT_MODAL_MAP: - { switch (event->val) { case TFM_MODAL_EDGESLIDE_DOWN: - { sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv; return TREDRAW_HARD; - } case TFM_MODAL_EDGESLIDE_UP: - { sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv; return TREDRAW_HARD; - } } break; - } case MOUSEMOVE: - { calcEdgeSlideCustomPoints(t); break; - } default: break; } @@ -6849,16 +6839,13 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven } break; case FKEY: - { if (event->val == KM_PRESS) { sld->flipped_vtx = !sld->flipped_vtx; calcVertSlideCustomPoints(t); return TREDRAW_HARD; } break; - } case CKEY: - { /* use like a modifier key */ if (event->val == KM_PRESS) { t->flag ^= T_ALT_TRANSFORM; @@ -6866,23 +6853,17 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven return TREDRAW_HARD; } break; - } #if 0 case EVT_MODAL_MAP: - { switch (event->val) { case TFM_MODAL_EDGESLIDE_DOWN: - { sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv; break; - } case TFM_MODAL_EDGESLIDE_UP: - { sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv; break; - } } - } + break; #endif case MOUSEMOVE: { -- cgit v1.2.3 From 900fc43bb4f366764f3a3b04929829ad7abf15ae Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Fri, 8 May 2015 12:10:26 +0200 Subject: Cleanup: Remove unused ray type flags. They were added for completeness, but it seems we don't need them. --- intern/cycles/kernel/kernel_path.h | 7 ------- intern/cycles/kernel/kernel_path_state.h | 2 +- intern/cycles/kernel/kernel_types.h | 4 +--- intern/cycles/render/osl.cpp | 6 +++--- 4 files changed, 5 insertions(+), 14 deletions(-) diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index cca7e897a7e..0ba8f694592 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -273,8 +273,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, float bssrdf_u, bssrdf_v; path_state_rng_2D(kg, rng, &state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v); subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false); - - state.flag |= PATH_RAY_BSSRDF_ANCESTOR; } } #endif @@ -392,7 +390,6 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd PathState hit_state = *state; Ray hit_ray = *ray; - hit_state.flag |= PATH_RAY_BSSRDF_ANCESTOR; hit_state.rng_offset += PRNG_BOUNCE_NUM; kernel_path_surface_connect_light(kg, rng, &bssrdf_sd[hit], tp, state, L); @@ -779,8 +776,6 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, float num_samples_inv = 1.0f/num_samples; RNG bssrdf_rng = cmj_hash(*rng, i); - state->flag |= PATH_RAY_BSSRDF_ANCESTOR; - /* do subsurface scatter step with copy of shader data, this will * replace the BSSRDF with a diffuse BSDF closure */ for(int j = 0; j < num_samples; j++) { @@ -832,8 +827,6 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, &hit_state, L); } } - - state->flag &= ~PATH_RAY_BSSRDF_ANCESTOR; } } #endif diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h index ab146c72cd0..45ea0e502ab 100644 --- a/intern/cycles/kernel/kernel_path_state.h +++ b/intern/cycles/kernel/kernel_path_state.h @@ -106,7 +106,7 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, PathState *state, int state->flag &= ~(PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP); } else if(label & LABEL_GLOSSY) { - state->flag |= PATH_RAY_GLOSSY|PATH_RAY_GLOSSY_ANCESTOR; + state->flag |= PATH_RAY_GLOSSY; state->flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP); } else { diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 0491b8ddec7..daa5ec1b9f1 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -264,9 +264,7 @@ enum PathRayFlag { PATH_RAY_MIS_SKIP = 2048, PATH_RAY_DIFFUSE_ANCESTOR = 4096, - PATH_RAY_GLOSSY_ANCESTOR = 8192, - PATH_RAY_BSSRDF_ANCESTOR = 16384, - PATH_RAY_SINGLE_PASS_DONE = 32768, + PATH_RAY_SINGLE_PASS_DONE = 8192, /* we need layer member flags to be the 20 upper bits */ PATH_RAY_LAYER_SHIFT = (32-20) diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index cd6c6eb3706..a02f91ad2cf 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -213,9 +213,9 @@ void OSLShaderManager::shading_system_init() "__unused__", "__unused__", - "diffuse_ancestor", /* PATH_RAY_DIFFUSE_ANCESTOR */ - "glossy_ancestor", /* PATH_RAY_GLOSSY_ANCESTOR */ - "bssrdf_ancestor", /* PATH_RAY_BSSRDF_ANCESTOR */ + "diffuse_ancestor", /* PATH_RAY_DIFFUSE_ANCESTOR */ + "__unused__", + "__unused__", "__unused__", /* PATH_RAY_SINGLE_PASS_DONE */ "volume_scatter", /* PATH_RAY_VOLUME_SCATTER */ }; -- cgit v1.2.3 From 3bbb4020e7f0fae80a5edd31e19b7fa97d2149e4 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 8 May 2015 12:35:38 +0200 Subject: Motionpaths: Use scene range option, takes start/end frame and preview settings into account. --- source/blender/editors/space_view3d/drawanimviz.c | 4 ++++ source/blender/makesdna/DNA_action_types.h | 1 + source/blender/makesrna/intern/rna_animviz.c | 1 + 3 files changed, 6 insertions(+) diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c index d753ad68fcc..aa06f5ec716 100644 --- a/source/blender/editors/space_view3d/drawanimviz.c +++ b/source/blender/editors/space_view3d/drawanimviz.c @@ -95,6 +95,10 @@ void draw_motion_path_instance(Scene *scene, sfra = CFRA - avs->path_bc; efra = CFRA + avs->path_ac; } + else if (avs->path_type == MOTIONPATH_TYPE_SCENE_RANGE) { + sfra = PSFRA; + efra = PEFRA; + } else { /* Use the current display range */ sfra = avs->path_sf; diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 761e76eb249..bc30c7f9fb2 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -148,6 +148,7 @@ typedef enum eMotionPaths_Types { MOTIONPATH_TYPE_RANGE = 0, /* only show the parts of the paths around the current frame */ MOTIONPATH_TYPE_ACFRA = 1, + MOTIONPATH_TYPE_SCENE_RANGE = 2, } eMotionPath_Types; /* bAnimVizSettings->path_viewflag */ diff --git a/source/blender/makesrna/intern/rna_animviz.c b/source/blender/makesrna/intern/rna_animviz.c index 719eb9f8a20..f156f616196 100644 --- a/source/blender/makesrna/intern/rna_animviz.c +++ b/source/blender/makesrna/intern/rna_animviz.c @@ -252,6 +252,7 @@ static void rna_def_animviz_paths(BlenderRNA *brna) {MOTIONPATH_TYPE_ACFRA, "CURRENT_FRAME", 0, "Around Frame", "Display Paths of poses within a fixed number of frames around the current frame"}, {MOTIONPATH_TYPE_RANGE, "RANGE", 0, "In Range", "Display Paths of poses within specified range"}, + {MOTIONPATH_TYPE_SCENE_RANGE, "SCENE", 0, "Scene Range", "Display Paths based on scene start/end frames (preview setting taken into account)"}, {0, NULL, 0, NULL, NULL} }; -- cgit v1.2.3 From 4c79608b3bd89004ea0784c112098cdfb91bee2a Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 8 May 2015 17:13:39 +0200 Subject: Revert "Motionpaths: Use scene range option, takes start/end frame and preview" Looks like this does not work for animators here after all, will use a different code for this (probably not hardcoded) This reverts commit 3bbb4020e7f0fae80a5edd31e19b7fa97d2149e4. --- source/blender/editors/space_view3d/drawanimviz.c | 4 ---- source/blender/makesdna/DNA_action_types.h | 1 - source/blender/makesrna/intern/rna_animviz.c | 1 - 3 files changed, 6 deletions(-) diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c index aa06f5ec716..d753ad68fcc 100644 --- a/source/blender/editors/space_view3d/drawanimviz.c +++ b/source/blender/editors/space_view3d/drawanimviz.c @@ -95,10 +95,6 @@ void draw_motion_path_instance(Scene *scene, sfra = CFRA - avs->path_bc; efra = CFRA + avs->path_ac; } - else if (avs->path_type == MOTIONPATH_TYPE_SCENE_RANGE) { - sfra = PSFRA; - efra = PEFRA; - } else { /* Use the current display range */ sfra = avs->path_sf; diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index bc30c7f9fb2..761e76eb249 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -148,7 +148,6 @@ typedef enum eMotionPaths_Types { MOTIONPATH_TYPE_RANGE = 0, /* only show the parts of the paths around the current frame */ MOTIONPATH_TYPE_ACFRA = 1, - MOTIONPATH_TYPE_SCENE_RANGE = 2, } eMotionPath_Types; /* bAnimVizSettings->path_viewflag */ diff --git a/source/blender/makesrna/intern/rna_animviz.c b/source/blender/makesrna/intern/rna_animviz.c index f156f616196..719eb9f8a20 100644 --- a/source/blender/makesrna/intern/rna_animviz.c +++ b/source/blender/makesrna/intern/rna_animviz.c @@ -252,7 +252,6 @@ static void rna_def_animviz_paths(BlenderRNA *brna) {MOTIONPATH_TYPE_ACFRA, "CURRENT_FRAME", 0, "Around Frame", "Display Paths of poses within a fixed number of frames around the current frame"}, {MOTIONPATH_TYPE_RANGE, "RANGE", 0, "In Range", "Display Paths of poses within specified range"}, - {MOTIONPATH_TYPE_SCENE_RANGE, "SCENE", 0, "Scene Range", "Display Paths based on scene start/end frames (preview setting taken into account)"}, {0, NULL, 0, NULL, NULL} }; -- cgit v1.2.3 From 2e6634e4a8a78809453816d2c623495e21454e69 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Fri, 8 May 2015 18:08:02 +0200 Subject: BGE: Cleanup function UpdateMesh and SetMesh in CcdPhysicsController.cpp "if (value == true)" -> "if(value)" "if (ptr == NULL)" -> "if (!ptr)" "vector" -> "std::vector" And other blender typo. --- .../Physics/Bullet/CcdPhysicsController.cpp | 418 ++++++++++----------- 1 file changed, 203 insertions(+), 215 deletions(-) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index dfcad865e09..b6d2f849437 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -1875,7 +1875,7 @@ CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mes return NULL; } -bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, bool polytope) +bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject *meshobj, DerivedMesh *dm, bool polytope) { int numpolys, numverts; @@ -1887,7 +1887,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, bool free_dm = false; // No mesh object or mesh has no polys - if (!meshobj || meshobj->HasColliderPolygon()==false) { + if (!meshobj || !meshobj->HasColliderPolygon()) { m_vertexArray.clear(); m_polygonIndexArray.clear(); m_triFaceArray.clear(); @@ -1910,80 +1910,83 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, /* double lookup */ const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); - if (index_mf_to_mpoly == NULL) { + if (!index_mf_to_mpoly) { index_mp_to_orig = NULL; } m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH; /* Convert blender geometry into bullet mesh, need these vars for mapping */ - vector vert_tag_array(numverts, false); - unsigned int tot_bt_verts= 0; + std::vector vert_tag_array(numverts, false); + unsigned int tot_bt_verts = 0; - if (polytope) - { + if (polytope) { // Tag verts we're using - for (int p2=0; p2GetPolygon(origi); + RAS_Polygon *poly = meshobj->GetPolygon(origi); // only add polygons that have the collision flag set - if (poly->IsCollider()) - { - if (vert_tag_array[mf->v1] == false) {vert_tag_array[mf->v1] = true; tot_bt_verts++;} - if (vert_tag_array[mf->v2] == false) {vert_tag_array[mf->v2] = true; tot_bt_verts++;} - if (vert_tag_array[mf->v3] == false) {vert_tag_array[mf->v3] = true; tot_bt_verts++;} - if (mf->v4 && vert_tag_array[mf->v4] == false) {vert_tag_array[mf->v4] = true; tot_bt_verts++;} + if (poly->IsCollider()) { + if (!vert_tag_array[mf->v1]) { + vert_tag_array[mf->v1] = true; + tot_bt_verts++; + } + if (!vert_tag_array[mf->v2]) { + vert_tag_array[mf->v2] = true; + tot_bt_verts++; + } + if (!vert_tag_array[mf->v3]) { + vert_tag_array[mf->v3] = true; + tot_bt_verts++; + } + if (mf->v4 && !vert_tag_array[mf->v4]) { + vert_tag_array[mf->v4] = true; + tot_bt_verts++; + } } } - + /* Can happen with ngons */ if (!tot_bt_verts) { goto cleanup_empty_mesh; } - m_vertexArray.resize(tot_bt_verts*3); + m_vertexArray.resize(tot_bt_verts * 3); - btScalar *bt= &m_vertexArray[0]; + btScalar *bt = &m_vertexArray[0]; - for (int p2=0; p2GetPolygon(origi); + RAS_Polygon *poly = meshobj->GetPolygon(origi); // only add polygons that have the collisionflag set - if (poly->IsCollider()) - { - if (vert_tag_array[mf->v1]==true) - { - const float* vtx = mvert[mf->v1].co; + if (poly->IsCollider()) { + if (vert_tag_array[mf->v1]) { + const float *vtx = mvert[mf->v1].co; vert_tag_array[mf->v1] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; *bt++ = vtx[2]; } - if (vert_tag_array[mf->v2]==true) - { - const float* vtx = mvert[mf->v2].co; + if (vert_tag_array[mf->v2]) { + const float *vtx = mvert[mf->v2].co; vert_tag_array[mf->v2] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; *bt++ = vtx[2]; } - if (vert_tag_array[mf->v3]==true) - { - const float* vtx = mvert[mf->v3].co; + if (vert_tag_array[mf->v3]) { + const float *vtx = mvert[mf->v3].co; vert_tag_array[mf->v3] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; *bt++ = vtx[2]; } - if (mf->v4 && vert_tag_array[mf->v4]==true) - { - const float* vtx = mvert[mf->v4].co; + if (mf->v4 && vert_tag_array[mf->v4]) { + const float *vtx = mvert[mf->v4].co; vert_tag_array[mf->v4] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; @@ -1993,28 +1996,38 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, } } else { - unsigned int tot_bt_tris= 0; - vector vert_remap_array(numverts, 0); - + unsigned int tot_bt_tris = 0; + std::vector vert_remap_array(numverts, 0); + // Tag verts we're using - for (int p2=0; p2GetPolygon(origi); + RAS_Polygon *poly = meshobj->GetPolygon(origi); // only add polygons that have the collision flag set - if (poly->IsCollider()) - { - if (vert_tag_array[mf->v1]==false) - {vert_tag_array[mf->v1] = true;vert_remap_array[mf->v1] = tot_bt_verts;tot_bt_verts++;} - if (vert_tag_array[mf->v2]==false) - {vert_tag_array[mf->v2] = true;vert_remap_array[mf->v2] = tot_bt_verts;tot_bt_verts++;} - if (vert_tag_array[mf->v3]==false) - {vert_tag_array[mf->v3] = true;vert_remap_array[mf->v3] = tot_bt_verts;tot_bt_verts++;} - if (mf->v4 && vert_tag_array[mf->v4]==false) - {vert_tag_array[mf->v4] = true;vert_remap_array[mf->v4] = tot_bt_verts;tot_bt_verts++;} - tot_bt_tris += (mf->v4 ? 2:1); /* a quad or a tri */ + if (poly->IsCollider()) { + if (!vert_tag_array[mf->v1]) { + vert_tag_array[mf->v1] = true; + vert_remap_array[mf->v1] = tot_bt_verts; + tot_bt_verts++; + } + if (!vert_tag_array[mf->v2]) { + vert_tag_array[mf->v2] = true; + vert_remap_array[mf->v2] = tot_bt_verts; + tot_bt_verts++; + } + if (!vert_tag_array[mf->v3]) { + vert_tag_array[mf->v3] = true; + vert_remap_array[mf->v3] = tot_bt_verts; + tot_bt_verts++; + } + if (mf->v4 && !vert_tag_array[mf->v4]) { + vert_tag_array[mf->v4] = true; + vert_remap_array[mf->v4] = tot_bt_verts; + tot_bt_verts++; + } + tot_bt_tris += (mf->v4 ? 2 : 1); /* a quad or a tri */ } } @@ -2023,43 +2036,39 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, goto cleanup_empty_mesh; } - m_vertexArray.resize(tot_bt_verts*3); + m_vertexArray.resize(tot_bt_verts * 3); m_polygonIndexArray.resize(tot_bt_tris); - m_triFaceArray.resize(tot_bt_tris*3); - btScalar *bt= &m_vertexArray[0]; - int *poly_index_pt= &m_polygonIndexArray[0]; - int *tri_pt= &m_triFaceArray[0]; + m_triFaceArray.resize(tot_bt_tris * 3); + btScalar *bt = &m_vertexArray[0]; + int *poly_index_pt = &m_polygonIndexArray[0]; + int *tri_pt = &m_triFaceArray[0]; UVco *uv_pt = NULL; - if (tface) - { - m_triFaceUVcoArray.resize(tot_bt_tris*3); + if (tface) { + m_triFaceUVcoArray.resize(tot_bt_tris * 3); uv_pt = &m_triFaceUVcoArray[0]; - } - else + } + else m_triFaceUVcoArray.clear(); - for (int p2=0; p2GetPolygon(origi); + RAS_Polygon *poly = meshobj->GetPolygon(origi); // only add polygons that have the collisionflag set - if (poly->IsCollider()) - { - MVert *v1= &mvert[mf->v1]; - MVert *v2= &mvert[mf->v2]; - MVert *v3= &mvert[mf->v3]; + if (poly->IsCollider()) { + MVert *v1 = &mvert[mf->v1]; + MVert *v2 = &mvert[mf->v2]; + MVert *v3 = &mvert[mf->v3]; // the face indices tri_pt[0] = vert_remap_array[mf->v1]; tri_pt[1] = vert_remap_array[mf->v2]; tri_pt[2] = vert_remap_array[mf->v3]; - tri_pt= tri_pt+3; - if (tf) - { + tri_pt = tri_pt + 3; + if (tf) { uv_pt[0].uv[0] = tf->uv[0][0]; uv_pt[0].uv[1] = tf->uv[0][1]; uv_pt[1].uv[0] = tf->uv[1][0]; @@ -2074,19 +2083,19 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, poly_index_pt++; // the vertex location - if (vert_tag_array[mf->v1]==true) { /* *** v1 *** */ + if (vert_tag_array[mf->v1]) { /* *** v1 *** */ vert_tag_array[mf->v1] = false; *bt++ = v1->co[0]; *bt++ = v1->co[1]; *bt++ = v1->co[2]; } - if (vert_tag_array[mf->v2]==true) { /* *** v2 *** */ + if (vert_tag_array[mf->v2]) { /* *** v2 *** */ vert_tag_array[mf->v2] = false; *bt++ = v2->co[0]; *bt++ = v2->co[1]; *bt++ = v2->co[2]; } - if (vert_tag_array[mf->v3]==true) { /* *** v3 *** */ + if (vert_tag_array[mf->v3]) { /* *** v3 *** */ vert_tag_array[mf->v3] = false; *bt++ = v3->co[0]; *bt++ = v3->co[1]; @@ -2095,12 +2104,12 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, if (mf->v4) { - MVert *v4= &mvert[mf->v4]; + MVert *v4 = &mvert[mf->v4]; tri_pt[0] = vert_remap_array[mf->v1]; tri_pt[1] = vert_remap_array[mf->v3]; tri_pt[2] = vert_remap_array[mf->v4]; - tri_pt= tri_pt+3; + tri_pt = tri_pt + 3; if (tf) { uv_pt[0].uv[0] = tf->uv[0][0]; @@ -2117,7 +2126,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, poly_index_pt++; // the vertex location - if (vert_tag_array[mf->v4] == true) { /* *** v4 *** */ + if (vert_tag_array[mf->v4]) { /* *** v4 *** */ vert_tag_array[mf->v4] = false; *bt++ = v4->co[0]; *bt++ = v4->co[1]; @@ -2131,27 +2140,27 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, /* If this ever gets confusing, print out an OBJ file for debugging */ #if 0 printf("# vert count %d\n", m_vertexArray.size()); - for (i=0; irelease(dm); @@ -2159,10 +2168,9 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, } // sharing only on static mesh at present, if you change that, you must also change in FindMesh - if (!polytope && !dm) - { + if (!polytope && !dm) { // triangle shape can be shared, store the mesh object in the map - m_meshShapeMap.insert(std::pair(meshobj,this)); + m_meshShapeMap.insert(std::pair(meshobj, this)); } return true; @@ -2185,51 +2193,50 @@ cleanup_empty_mesh: /* Updates the arrays used by CreateBulletShape(), * take care that recalcLocalAabb() runs after CreateBulletShape is called. * */ -bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RAS_MeshObject* meshobj) +bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RAS_MeshObject *meshobj) { int numpolys; int numverts; - unsigned int tot_bt_tris= 0; - unsigned int tot_bt_verts= 0; + unsigned int tot_bt_tris = 0; + unsigned int tot_bt_verts = 0; int i, j; int v_orig; /* Use for looping over verts in a face as a try or 2 tris */ - const int quad_verts[7]= {0,1,2, 0,2,3, -1}; - const int tri_verts[4]= {0,1,2, -1}; + const int quad_verts[7] = {0, 1, 2, 0, 2, 3, -1}; + const int tri_verts[4] = {0, 1, 2, -1}; const int *fv_pt; - if (gameobj==NULL && meshobj==NULL) + if (!gameobj && !meshobj) return false; - + if (m_shapeType != PHY_SHAPE_MESH) return false; - RAS_Deformer *deformer= gameobj ? gameobj->GetDeformer():NULL; - DerivedMesh* dm = NULL; + RAS_Deformer *deformer = gameobj ? gameobj->GetDeformer() : NULL; + DerivedMesh *dm = NULL; if (deformer) dm = deformer->GetPhysicsMesh(); - + /* get the mesh from the object if not defined */ - if (meshobj==NULL) { - + if (!meshobj) { /* modifier mesh */ if (dm) - meshobj= deformer->GetRasMesh(); - + meshobj = deformer->GetRasMesh(); + /* game object first mesh */ - if (meshobj==NULL) { + if (!meshobj) { if (gameobj->GetMeshCount() > 0) { - meshobj= gameobj->GetMesh(0); + meshobj = gameobj->GetMesh(0); } } } - - if (dm && deformer->GetRasMesh() == meshobj) - { /* + + if (dm && deformer->GetRasMesh() == meshobj) { + /* * Derived Mesh Update * * */ @@ -2241,8 +2248,8 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA /* double lookup */ const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); - if (index_mf_to_mpoly == NULL) { + const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); + if (!index_mf_to_mpoly) { index_mp_to_orig = NULL; } @@ -2251,31 +2258,28 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA int flen; - if (CustomData_has_layer(&dm->faceData, CD_MTFACE)) - { + if (CustomData_has_layer(&dm->faceData, CD_MTFACE)) { MTFace *tface = (MTFace *)dm->getTessFaceDataArray(dm, CD_MTFACE); MTFace *tf; - vector vert_tag_array(numverts, false); - vector vert_remap_array(numverts, 0); + std::vector vert_tag_array(numverts, false); + std::vector vert_remap_array(numverts, 0); - for (mf= mface, tf= tface, i=0; i < numpolys; mf++, tf++, i++) { - if (tf->mode & TF_DYNAMIC) - { + for (mf = mface, tf = tface, i = 0; i < numpolys; mf++, tf++, i++) { + if (tf->mode & TF_DYNAMIC) { if (mf->v4) { - tot_bt_tris+= 2; - flen= 4; - } else { + tot_bt_tris += 2; + flen = 4; + } + else { tot_bt_tris++; - flen= 3; + flen = 3; } - for (j=0; jv1 + j)); - if (vert_tag_array[v_orig]==false) - { + if (!vert_tag_array[v_orig]) { vert_tag_array[v_orig] = true; vert_remap_array[v_orig] = tot_bt_verts; tot_bt_verts++; @@ -2284,42 +2288,40 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA } } - m_vertexArray.resize(tot_bt_verts*3); - btScalar *bt= &m_vertexArray[0]; + m_vertexArray.resize(tot_bt_verts * 3); + btScalar *bt = &m_vertexArray[0]; - m_triFaceArray.resize(tot_bt_tris*3); - int *tri_pt= &m_triFaceArray[0]; + m_triFaceArray.resize(tot_bt_tris * 3); + int *tri_pt = &m_triFaceArray[0]; - m_triFaceUVcoArray.resize(tot_bt_tris*3); - UVco *uv_pt= &m_triFaceUVcoArray[0]; + m_triFaceUVcoArray.resize(tot_bt_tris * 3); + UVco *uv_pt = &m_triFaceUVcoArray[0]; m_polygonIndexArray.resize(tot_bt_tris); - int *poly_index_pt= &m_polygonIndexArray[0]; + int *poly_index_pt = &m_polygonIndexArray[0]; - for (mf= mface, tf= tface, i=0; i < numpolys; mf++, tf++, i++) - { - if (tf->mode & TF_DYNAMIC) - { + for (mf = mface, tf = tface, i = 0; i < numpolys; mf++, tf++, i++) { + if (tf->mode & TF_DYNAMIC) { int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i; if (mf->v4) { - fv_pt= quad_verts; + fv_pt = quad_verts; *poly_index_pt++ = origi; *poly_index_pt++ = origi; - flen= 4; - } else { - fv_pt= tri_verts; + flen = 4; + } + else { + fv_pt = tri_verts; *poly_index_pt++ = origi; - flen= 3; + flen = 3; } - for (; *fv_pt > -1; fv_pt++) - { + for (; *fv_pt > -1; fv_pt++) { v_orig = (*(&mf->v1 + (*fv_pt))); if (vert_tag_array[v_orig]) { - mv= mvert + v_orig; + mv = mvert + v_orig; *bt++ = mv->co[0]; *bt++ = mv->co[1]; *bt++ = mv->co[2]; @@ -2337,37 +2339,37 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA else { /* no need for a vertex mapping. simple/fast */ - tot_bt_verts= numverts; + tot_bt_verts = numverts; - for (mf= mface, i=0; i < numpolys; mf++, i++) { - tot_bt_tris += (mf->v4 ? 2:1); + for (mf = mface, i = 0; i < numpolys; mf++, i++) { + tot_bt_tris += (mf->v4 ? 2 : 1); } - m_vertexArray.resize(tot_bt_verts*3); - btScalar *bt= &m_vertexArray[0]; + m_vertexArray.resize(tot_bt_verts * 3); + btScalar *bt = &m_vertexArray[0]; - m_triFaceArray.resize(tot_bt_tris*3); - int *tri_pt= &m_triFaceArray[0]; + m_triFaceArray.resize(tot_bt_tris * 3); + int *tri_pt = &m_triFaceArray[0]; m_polygonIndexArray.resize(tot_bt_tris); - int *poly_index_pt= &m_polygonIndexArray[0]; + int *poly_index_pt = &m_polygonIndexArray[0]; m_triFaceUVcoArray.clear(); - for (mv= mvert, i=0; i < numverts; mv++, i++) { + for (mv = mvert, i = 0; i < numverts; mv++, i++) { *bt++ = mv->co[0]; *bt++ = mv->co[1]; *bt++ = mv->co[2]; } - for (mf= mface, i=0; i < numpolys; mf++, i++) { + for (mf = mface, i = 0; i < numpolys; mf++, i++) { int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i; if (mf->v4) { - fv_pt= quad_verts; + fv_pt = quad_verts; *poly_index_pt++ = origi; *poly_index_pt++ = origi; } else { - fv_pt= tri_verts; + fv_pt = tri_verts; *poly_index_pt++ = origi; } @@ -2376,51 +2378,47 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA } } } - else { /* - * RAS Mesh Update - * - * */ - + else { /* + * RAS Mesh Update + * + * */ + /* Note!, gameobj can be NULL here */ /* transverts are only used for deformed RAS_Meshes, the RAS_TexVert data * is too hard to get at, see below for details */ - float (*transverts)[3] = NULL; - int transverts_tot= 0; /* with deformed meshes - should always be greater than the max orginal index, or we get crashes */ + float(*transverts)[3] = NULL; + int transverts_tot = 0; /* with deformed meshes - should always be greater than the max orginal index, or we get crashes */ if (deformer) { /* map locations from the deformed array * * Could call deformer->Update(); but rely on redraw updating. * */ - transverts= deformer->GetTransVerts(&transverts_tot); + transverts = deformer->GetTransVerts(&transverts_tot); } // Tag verts we're using - numpolys= meshobj->NumPolygons(); - numverts= meshobj->m_sharedvertex_map.size(); + numpolys = meshobj->NumPolygons(); + numverts = meshobj->m_sharedvertex_map.size(); const float *xyz; - vector vert_tag_array(numverts, false); - vector vert_remap_array(numverts, 0); + std::vector vert_tag_array(numverts, false); + std::vector vert_remap_array(numverts, 0); - for (int p=0; pGetPolygon(p); - if (poly->IsCollider()) - { - for (i=0; i < poly->VertexCount(); i++) - { - v_orig= poly->GetVertex(i)->getOrigIndex(); - if (vert_tag_array[v_orig]==false) - { + for (int p = 0; p < numpolys; p++) { + RAS_Polygon *poly = meshobj->GetPolygon(p); + if (poly->IsCollider()) { + for (i = 0; i < poly->VertexCount(); i++) { + v_orig = poly->GetVertex(i)->getOrigIndex(); + if (!vert_tag_array[v_orig]) { vert_tag_array[v_orig] = true; vert_remap_array[v_orig] = tot_bt_verts; tot_bt_verts++; } } - tot_bt_tris += (poly->VertexCount()==4 ? 2:1); + tot_bt_tris += (poly->VertexCount() == 4 ? 2 : 1); } } @@ -2428,32 +2426,27 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA if (tot_bt_tris == 0 || tot_bt_verts == 0) return false; - m_vertexArray.resize(tot_bt_verts*3); - btScalar *bt= &m_vertexArray[0]; + m_vertexArray.resize(tot_bt_verts * 3); + btScalar *bt = &m_vertexArray[0]; - m_triFaceArray.resize(tot_bt_tris*3); - int *tri_pt= &m_triFaceArray[0]; + m_triFaceArray.resize(tot_bt_tris * 3); + int *tri_pt = &m_triFaceArray[0]; /* cant be used for anything useful in this case, since we don't rely on the original mesh * will just be an array like pythons range(tot_bt_tris) */ m_polygonIndexArray.resize(tot_bt_tris); - for (int p=0; pGetPolygon(p); + for (int p = 0; p < numpolys; p++) { + RAS_Polygon *poly = meshobj->GetPolygon(p); - if (poly->IsCollider()) - { + if (poly->IsCollider()) { /* quad or tri loop */ - fv_pt= (poly->VertexCount()==3 ? tri_verts:quad_verts); + fv_pt = (poly->VertexCount() == 3 ? tri_verts : quad_verts); - for (; *fv_pt > -1; fv_pt++) - { - v_orig= poly->GetVertex(*fv_pt)->getOrigIndex(); - - if (vert_tag_array[v_orig]) - { + for (; *fv_pt > -1; fv_pt++) { + v_orig = poly->GetVertex(*fv_pt)->getOrigIndex(); + if (vert_tag_array[v_orig]) { if (transverts) { /* deformed mesh, using RAS_TexVert locations would be too troublesome * because they are use the gameob as a hash in the material slot */ @@ -2463,33 +2456,30 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA } else { /* static mesh python may have modified */ - xyz= meshobj->GetVertexLocation( v_orig ); + xyz = meshobj->GetVertexLocation(v_orig); *bt++ = xyz[0]; *bt++ = xyz[1]; *bt++ = xyz[2]; } - vert_tag_array[v_orig] = false; } - *tri_pt++ = vert_remap_array[v_orig]; } } - m_polygonIndexArray[p] = p; /* dumb counting */ } } - + #if 0 /* needs #include */ printf("# vert count %d\n", m_vertexArray.size()); - for (int i=0; i::iterator mit = m_meshShapeMap.find(m_meshObject); + std::map::iterator mit = m_meshShapeMap.find(m_meshObject); if (mit != m_meshShapeMap.end()) { m_meshShapeMap.erase(mit); m_meshShapeMap[meshobj] = this; } - m_meshObject= meshobj; - + m_meshObject = meshobj; + if (dm) { dm->needsFree = 1; dm->release(dm); @@ -2519,8 +2509,6 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA return true; } - - bool CcdShapeConstructionInfo::SetProxy(CcdShapeConstructionInfo* shapeInfo) { if (shapeInfo == NULL) -- cgit v1.2.3 From b65c77e664478750a26c384d39baa13cf45aa545 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 8 May 2015 19:25:51 +0200 Subject: Add Intel's 3000 driver to exceptions for df/dy calculations. Should fix another case of SSAO effect reversal. --- source/blender/gpu/intern/gpu_extensions.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 54e3339eb29..c0178567466 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -264,7 +264,8 @@ void gpu_extensions_init(void) GG.dfdyfactors[1] = -1.0; } else if (GG.device == GPU_DEVICE_INTEL && GG.os == GPU_OS_WIN && - (strstr(version, "4.0.0 - Build 9.18.10.3165"))) { + (strstr(version, "4.0.0 - Build 9.18.10.3165") || + strstr(version, "3.1.0 - Build 9.17.10.4101"))) { GG.dfdyfactors[0] = -1.0; GG.dfdyfactors[1] = 1.0; } -- cgit v1.2.3 From a08d90f0706270c87352ff7c33777905291c45a1 Mon Sep 17 00:00:00 2001 From: Ines Almeida Date: Fri, 8 May 2015 19:22:41 +0100 Subject: matcaps browser: changing emboss style and grid direction according to T44613 --- source/blender/editors/interface/interface_templates.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 90bcddde0c0..fe1a1b9096d 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1651,7 +1651,7 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem) /* arg_litem is malloced, can be freed by parent button */ cb = *((RNAUpdateCb *)arg_litem); - block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); + block = UI_block_begin(C, ar, "_popup", UI_EMBOSS_PULLDOWN); UI_block_flag_enable(block, UI_BLOCK_LOOP); @@ -1672,7 +1672,7 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem) } UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); - UI_block_direction_set(block, UI_DIR_UP); + UI_block_direction_set(block, UI_DIR_DOWN); if (free) { MEM_freeN(item); -- cgit v1.2.3 From 6ee0327594b2308b3111e1b8a7e52ed5959899fc Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Fri, 8 May 2015 20:55:50 +0200 Subject: Fix T38335: incorrect triangle index in raycast result Previously we forgot to do a special operation for indexes to convert a quad to two triangles. --- source/gameengine/Physics/Bullet/CcdPhysicsController.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index b6d2f849437..4285093fde0 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -2382,7 +2382,6 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RA * RAS Mesh Update * * */ - /* Note!, gameobj can be NULL here */ /* transverts are only used for deformed RAS_Meshes, the RAS_TexVert data @@ -2437,7 +2436,7 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RA m_polygonIndexArray.resize(tot_bt_tris); - for (int p = 0; p < numpolys; p++) { + for (int p = 0; p < numpolys;) { RAS_Polygon *poly = meshobj->GetPolygon(p); if (poly->IsCollider()) { @@ -2466,7 +2465,12 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RA *tri_pt++ = vert_remap_array[v_orig]; } } - m_polygonIndexArray[p] = p; /* dumb counting */ + m_polygonIndexArray[p] = p; + if (poly->VertexCount() == 4) { + // if the poly is a quad we transform it in two triangles + m_polygonIndexArray[p + 1] = p++; + } + p++; } } -- cgit v1.2.3 From 54ac84f2b841f6948c8befca8ded95c101a5a2c4 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 8 May 2015 22:20:18 +0200 Subject: Fix 3D View Properties scrollbar being not set to top in startup.blend --- source/blender/blenloader/intern/versioning_defaults.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index d320b305c06..045f422e4ac 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -121,9 +121,15 @@ void BLO_update_defaults_startup_blend(Main *bmain) } } - /* Remove all stored panels, we want to use defaults (order, open/closed) as defined by UI code here! */ for (ar = area->regionbase.first; ar; ar = ar->next) { + /* Remove all stored panels, we want to use defaults (order, open/closed) as defined by UI code here! */ BLI_freelistN(&ar->panels); + + /* simple fix for 3d view properties scrollbar being not set to top */ + if (ar->regiontype == RGN_TYPE_UI) { + ar->v2d.cur.ymax = ar->v2d.tot.ymax; + ar->v2d.cur.ymin = ar->v2d.cur.ymax - ar->winy; + } } } } -- cgit v1.2.3 From eb811538960147e68fd6c2c530ed3ca67fa875e6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 9 May 2015 11:00:50 +1000 Subject: Cleanup: warning (sequence-point) --- source/gameengine/Physics/Bullet/CcdPhysicsController.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 4285093fde0..5c5a4d3cc56 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -2436,7 +2436,7 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RA m_polygonIndexArray.resize(tot_bt_tris); - for (int p = 0; p < numpolys;) { + for (int p = 0; p < numpolys; p++) { RAS_Polygon *poly = meshobj->GetPolygon(p); if (poly->IsCollider()) { @@ -2467,10 +2467,10 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RA } m_polygonIndexArray[p] = p; if (poly->VertexCount() == 4) { + p++; // if the poly is a quad we transform it in two triangles - m_polygonIndexArray[p + 1] = p++; + m_polygonIndexArray[p] = p; } - p++; } } -- cgit v1.2.3 From 8c1b805f87209ae6282d77b213ed2527f2d7c207 Mon Sep 17 00:00:00 2001 From: Tamito Kajiyama Date: Sat, 9 May 2015 13:04:29 +0900 Subject: Freestyle: Partial fix for a crash with Save Buffers option enabled. Prevents null pointer references in the case of the Save Buffers option enabled. This is a regression likely due to rBd5f1b9c22233. --- .../intern/blender_interface/FRS_freestyle.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 291ed98f905..64c6bd33924 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -493,12 +493,18 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r rl = render_get_active_layer( freestyle_render, freestyle_render->result ); if (!rl) { if (G.debug & G_DEBUG_FREESTYLE) { - cout << "No Freestyle result image to composite" << endl; + cout << "No source render layer to composite" << endl; } return; } - src = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname); + src = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, freestyle_render->viewname); + if (!src) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "No source result image to composite" << endl; + } + return; + } #if 0 if (G.debug & G_DEBUG_FREESTYLE) { cout << "src: " << rl->rectx << " x " << rl->recty << endl; @@ -506,13 +512,19 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r #endif rl = RE_GetRenderLayer(re->result, srl->name); - if (!rl || src == NULL) { + if (!rl) { if (G.debug & G_DEBUG_FREESTYLE) { - cout << "No layer to composite to" << endl; + cout << "No destination render layer to composite to" << endl; } return; } dest = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname); + if (!dest) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "No destination result image to composite to" << endl; + } + return; + } #if 0 if (G.debug & G_DEBUG_FREESTYLE) { cout << "dest: " << rl->rectx << " x " << rl->recty << endl; -- cgit v1.2.3 From 7eac672e4f3a1592e64fd37a40ce23ac02569e6f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 May 2015 18:53:57 +0500 Subject: Cycles: Set default closure values to some of the nodes Previously it was only set at compilation time which is all fine but does not let us to check which closure the node corresponds to prior to the compilation. --- intern/cycles/render/nodes.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index d17d531aa77..d3f26a08292 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1609,6 +1609,7 @@ ShaderEnum AnisotropicBsdfNode::distribution_enum = aniso_distribution_init(); AnisotropicBsdfNode::AnisotropicBsdfNode() { + closure = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID; distribution = ustring("GGX"); add_input("Tangent", SHADER_SOCKET_VECTOR, ShaderInput::TANGENT); @@ -1661,6 +1662,7 @@ ShaderEnum GlossyBsdfNode::distribution_enum = glossy_distribution_init(); GlossyBsdfNode::GlossyBsdfNode() { + closure = CLOSURE_BSDF_MICROFACET_GGX_ID; distribution = ustring("GGX"); add_input("Roughness", SHADER_SOCKET_FLOAT, 0.2f); @@ -1699,6 +1701,7 @@ ShaderEnum GlassBsdfNode::distribution_enum = glass_distribution_init(); GlassBsdfNode::GlassBsdfNode() { + closure = CLOSURE_BSDF_SHARP_GLASS_ID; distribution = ustring("Sharp"); add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f); @@ -1738,6 +1741,7 @@ ShaderEnum RefractionBsdfNode::distribution_enum = refraction_distribution_init( RefractionBsdfNode::RefractionBsdfNode() { + closure = CLOSURE_BSDF_REFRACTION_ID; distribution = ustring("Sharp"); add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f); @@ -1776,6 +1780,7 @@ ShaderEnum ToonBsdfNode::component_enum = toon_component_init(); ToonBsdfNode::ToonBsdfNode() { + closure = CLOSURE_BSDF_DIFFUSE_TOON_ID; component = ustring("Diffuse"); add_input("Size", SHADER_SOCKET_FLOAT, 0.5f); @@ -2135,6 +2140,7 @@ ShaderEnum HairBsdfNode::component_enum = hair_component_init(); HairBsdfNode::HairBsdfNode() { + closure = CLOSURE_BSDF_HAIR_REFLECTION_ID; component = ustring("Reflection"); add_input("Offset", SHADER_SOCKET_FLOAT); -- cgit v1.2.3 From c9133778cf7e5ba488891fcb04bcb52e557d4d51 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 May 2015 18:55:46 +0500 Subject: Cycles: Add CPU compat headers to some of the OSL implementation files This header was already included into some of the implementation files already, and this change is needed for some upcoming changes in the way how kernel_types.h works. --- intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp | 1 + intern/cycles/kernel/osl/bsdf_phong_ramp.cpp | 1 + intern/cycles/kernel/osl/osl_bssrdf.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp index 8f9c2efd470..43929fbe928 100644 --- a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp +++ b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp @@ -34,6 +34,7 @@ #include +#include "kernel_compat_cpu.h" #include "osl_closures.h" #include "kernel_types.h" diff --git a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp index c5851747b54..497c4f0dc5c 100644 --- a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp +++ b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp @@ -34,6 +34,7 @@ #include +#include "kernel_compat_cpu.h" #include "osl_closures.h" #include "kernel_types.h" diff --git a/intern/cycles/kernel/osl/osl_bssrdf.cpp b/intern/cycles/kernel/osl/osl_bssrdf.cpp index 84ef85e089d..88998037751 100644 --- a/intern/cycles/kernel/osl/osl_bssrdf.cpp +++ b/intern/cycles/kernel/osl/osl_bssrdf.cpp @@ -34,6 +34,7 @@ #include +#include "kernel_compat_cpu.h" #include "osl_bssrdf.h" #include "osl_closures.h" -- cgit v1.2.3 From d69c80f717e9dc9efc1325653b0c87fbb2254af9 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 May 2015 18:57:51 +0500 Subject: Cycles: Presumably correct workaround for addrspace in camera motion blur --- intern/cycles/kernel/kernel_camera.h | 44 +++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index ded222e20ff..1e81210007c 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -16,17 +16,6 @@ CCL_NAMESPACE_BEGIN -/* Workaround for explicit conversion from constant to private memory - * pointer when using OpenCL. - * - * TODO(sergey): Find a real solution for this. - */ -#ifdef __KERNEL_OPENCL__ -# define __motion_as_decoupled_const_ptr(motion) ((motion)) -#else -# define __motion_as_decoupled_const_ptr(motion) ((const DecompMotionTransform*)(motion)) -#endif - /* Perspective Camera */ ccl_device float2 camera_sample_aperture(KernelGlobals *kg, float u, float v) @@ -80,9 +69,16 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo #ifdef __CAMERA_MOTION__ if(kernel_data.cam.have_motion) { +#ifdef __KERNEL_OPENCL__ + const MotionTransform tfm = kernel_data.cam.motion; transform_motion_interpolate(&cameratoworld, - __motion_as_decoupled_const_ptr(&kernel_data.cam.motion), + ((const DecompMotionTransform*)&tfm), ray->time); +#else + transform_motion_interpolate(&cameratoworld, + ((const DecompMotionTransform*)&kernel_data.cam.motion), + ray->time); +#endif } #endif @@ -144,9 +140,16 @@ ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, fl #ifdef __CAMERA_MOTION__ if(kernel_data.cam.have_motion) { +#ifdef __KERNEL_OPENCL__ + const MotionTransform tfm = kernel_data.cam.motion; transform_motion_interpolate(&cameratoworld, - __motion_as_decoupled_const_ptr(&kernel_data.cam.motion), + (const DecompMotionTransform*)&tfm, ray->time); +#else + transform_motion_interpolate(&cameratoworld, + (const DecompMotionTransform*)&kernel_data.cam.motion, + ray->time); +#endif } #endif @@ -220,11 +223,19 @@ ccl_device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float Transform cameratoworld = kernel_data.cam.cameratoworld; #ifdef __CAMERA_MOTION__ - if(kernel_data.cam.have_motion) + if(kernel_data.cam.have_motion) { +#ifdef __KERNEL_OPENCL__ + const MotionTransform tfm = kernel_data.cam.motion; + transform_motion_interpolate(&cameratoworld, + (const DecompMotionTransform*)&tfm, + ray->time); +#else transform_motion_interpolate(&cameratoworld, - __motion_as_decoupled_const_ptr(&kernel_data.cam.motion), + (const DecompMotionTransform*)&kernel_data.cam.motion, ray->time); #endif + } +#endif ray->P = transform_point(&cameratoworld, ray->P); ray->D = transform_direction(&cameratoworld, ray->D); @@ -329,7 +340,4 @@ ccl_device_inline float3 camera_world_to_ndc(KernelGlobals *kg, ShaderData *sd, } } -#undef __motion_as_decoupled_const_ptr - CCL_NAMESPACE_END - -- cgit v1.2.3 From 0e4ddaadd487ebdd80399e2fd24cb8b12bd7f721 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 May 2015 19:05:49 +0500 Subject: Cycles: Change the way how we pass requested capabilities to the device Previously we only had experimental flag passed to device's load_kernel() which was all fine. But since we're gonna to have some extra parameters passed there it makes sense to wrap them into a single struct, which will make it easier to pass stuff around. --- intern/cycles/device/device.h | 20 +++++++++++++++++++- intern/cycles/device/device_cuda.cpp | 6 +++--- intern/cycles/device/device_multi.cpp | 4 ++-- intern/cycles/device/device_network.cpp | 10 +++++----- intern/cycles/render/session.cpp | 9 ++++++++- intern/cycles/render/session.h | 3 +++ 6 files changed, 40 insertions(+), 12 deletions(-) diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 7eb3f6c822b..98155900748 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -69,6 +69,22 @@ public: } }; +class DeviceRequestedFeatures { +public: + /* Use experimental feature set. */ + bool experimental; + + DeviceRequestedFeatures() + { + experimental = false; + } + + bool modified(const DeviceRequestedFeatures& requested_features) + { + return !(experimental == requested_features.experimental); + } +}; + /* Device */ struct DeviceDrawParams { @@ -125,7 +141,9 @@ public: virtual void *osl_memory() { return NULL; } /* load/compile kernels, must be called before adding tasks */ - virtual bool load_kernels(bool /*experimental*/) { return true; } + virtual bool load_kernels( + const DeviceRequestedFeatures& /*requested_features*/) + { return true; } /* tasks */ virtual int get_split_task_count(DeviceTask& task) = 0; diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 9d3b16b1e1b..04319ba4775 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -309,18 +309,18 @@ public: return cubin; } - bool load_kernels(bool experimental) + bool load_kernels(const DeviceRequestedFeatures& requested_features) { /* check if cuda init succeeded */ if(cuContext == 0) return false; /* check if GPU is supported */ - if(!support_device(experimental)) + if(!support_device(requested_features.experimental)) return false; /* get kernel */ - string cubin = compile_kernel(experimental); + string cubin = compile_kernel(requested_features.experimental); if(cubin == "") return false; diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp index 8da489a0ab5..c0a1516f2de 100644 --- a/intern/cycles/device/device_multi.cpp +++ b/intern/cycles/device/device_multi.cpp @@ -89,10 +89,10 @@ public: return error_msg; } - bool load_kernels(bool experimental) + bool load_kernels(const DeviceRequestedFeatures& requested_features) { foreach(SubDevice& sub, devices) - if(!sub.device->load_kernels(experimental)) + if(!sub.device->load_kernels(requested_features)) return false; return true; diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp index 90cd6a76d63..454f7301975 100644 --- a/intern/cycles/device/device_network.cpp +++ b/intern/cycles/device/device_network.cpp @@ -196,7 +196,7 @@ public: } } - bool load_kernels(bool experimental) + bool load_kernels(const DeviceRequestedFeatures& requested_features) { if(error_func.have_error()) return false; @@ -204,7 +204,7 @@ public: thread_scoped_lock lock(rpc_lock); RPCSend snd(socket, &error_func, "load_kernels"); - snd.add(experimental); + snd.add(requested_features.experimental); snd.write(); bool result; @@ -607,11 +607,11 @@ protected: device->tex_free(mem); } else if(rcv.name == "load_kernels") { - bool experimental; - rcv.read(experimental); + DeviceRequestedFeatures requested_features; + rcv.read(requested_features.experimental); bool result; - result = device->load_kernels(experimental); + result = device->load_kernels(requested_features); RPCSend snd(socket, &error_func, "load_kernels"); snd.add(result); snd.write(); diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 5b3826c0ea9..82197d5340a 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -593,6 +593,13 @@ void Session::run_cpu() update_progressive_refine(true); } +DeviceRequestedFeatures Session::get_requested_device_features() +{ + DeviceRequestedFeatures requested_features; + requested_features.experimental = params.experimental; + return requested_features; +} + void Session::load_kernels() { thread_scoped_lock scene_lock(scene->mutex); @@ -600,7 +607,7 @@ void Session::load_kernels() if(!kernels_loaded) { progress.set_status("Loading render kernels (may take a few minutes the first time)"); - if(!device->load_kernels(params.experimental)) { + if(!device->load_kernels(get_requested_device_features())) { string message = device->error_message(); if(message.empty()) message = "Failed loading render kernel, see console for errors"; diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 8b108b0940f..cfce5360526 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -32,6 +32,7 @@ CCL_NAMESPACE_BEGIN class BufferParams; class Device; class DeviceScene; +class DeviceRequestedFeatures; class DisplayBuffer; class Progress; class RenderBuffers; @@ -204,6 +205,8 @@ protected: bool update_progressive_refine(bool cancel); vector tile_buffers; + + DeviceRequestedFeatures get_requested_device_features(); }; CCL_NAMESPACE_END -- cgit v1.2.3 From b3299bace003d9d061b188760a263ca7b42c36d7 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 May 2015 19:09:07 +0500 Subject: Cycles: Pass requested tile size to the device via device task This is currently unused but crucial for things like calculating amount of device memory required to deal with the tasks. Maybe not really best place to store it, but consider it good enough for now. --- intern/cycles/device/device_task.h | 1 + intern/cycles/render/session.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h index 0c23d8971e0..834ea60988a 100644 --- a/intern/cycles/device/device_task.h +++ b/intern/cycles/device/device_task.h @@ -65,6 +65,7 @@ public: bool need_finish_queue; bool integrator_branched; + int2 requested_tile_size; protected: double last_update_time; }; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 82197d5340a..9ef1c1f4f1f 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -859,6 +859,7 @@ void Session::path_trace() task.update_progress_sample = function_bind(&Session::update_progress_sample, this); task.need_finish_queue = params.progressive_refine; task.integrator_branched = scene->integrator->method == Integrator::BRANCHED_PATH; + task.requested_tile_size = params.tile_size; device->task_add(task); } -- cgit v1.2.3 From 5068f7dc015eb66a292d0027b3268f535201b3af Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 May 2015 19:11:37 +0500 Subject: Cycles: Add utility function to graph to query number of closures used in it Currently unused but will be needed soon for the split kernel work. --- intern/cycles/kernel/svm/svm_types.h | 1 + intern/cycles/render/graph.cpp | 20 ++++++++++++++++++++ intern/cycles/render/graph.h | 3 +++ intern/cycles/render/nodes.cpp | 2 ++ 4 files changed, 26 insertions(+) diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 7130b14a426..848c16be327 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -426,6 +426,7 @@ typedef enum ClosureType { #define CLOSURE_IS_BACKGROUND(type) (type == CLOSURE_BACKGROUND_ID) #define CLOSURE_IS_AMBIENT_OCCLUSION(type) (type == CLOSURE_AMBIENT_OCCLUSION_ID) #define CLOSURE_IS_PHASE(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID) +#define CLOSURE_IS_GLASS(type) (type >= CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID) #define CLOSURE_WEIGHT_CUTOFF 1e-5f diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index b36cbb5ea6f..ab89ee3ae37 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -833,6 +833,26 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight } } +int ShaderGraph::get_num_closures() +{ + int num_closures = 0; + foreach(ShaderNode *node, nodes) { + if(node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) { + BsdfNode *bsdf_node = static_cast(node); + /* TODO(sergey): Make it more generic approach, maybe some utility + * macros like CLOSURE_IS_FOO()? + */ + if(CLOSURE_IS_BSSRDF(bsdf_node->closure)) + num_closures = num_closures + 3; + else if(CLOSURE_IS_GLASS(bsdf_node->closure)) + num_closures = num_closures + 2; + else + num_closures = num_closures + 1; + } + } + return num_closures; +} + void ShaderGraph::dump_graph(const char *filename) { FILE *fd = fopen(filename, "w"); diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index 7817a4cdc6d..6744804ef19 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -82,6 +82,7 @@ enum ShaderNodeSpecialType { SHADER_SPECIAL_TYPE_SCRIPT, SHADER_SPECIAL_TYPE_BACKGROUND, SHADER_SPECIAL_TYPE_IMAGE_SLOT, + SHADER_SPECIAL_TYPE_CLOSURE, }; /* Enum @@ -253,6 +254,8 @@ public: void remove_unneeded_nodes(); void finalize(bool do_bump = false, bool do_osl = false); + int get_num_closures(); + void dump_graph(const char *filename); protected: diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index d3f26a08292..7eaecc2751c 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1520,6 +1520,8 @@ void ProxyNode::compile(OSLCompiler& /*compiler*/) BsdfNode::BsdfNode(bool scattering_) : ShaderNode("bsdf"), scattering(scattering_) { + special_type = SHADER_SPECIAL_TYPE_CLOSURE; + add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL); add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); -- cgit v1.2.3 From 17c95d0a96e306b2f38ff6e489064d6f021e494c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 May 2015 19:15:58 +0500 Subject: Cycles: Add utility function to count maximum number of closures used by session This will be used by split kernel in order to compile most optimal kernel. Maximum number of closures is actually being cached in the session, so viewport rendering will not trigger kernel re-loading when number of closures goes down. --- intern/cycles/render/session.cpp | 15 +++++++++++++++ intern/cycles/render/session.h | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 9ef1c1f4f1f..cfd974346c3 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -20,6 +20,7 @@ #include "buffers.h" #include "camera.h" #include "device.h" +#include "graph.h" #include "integrator.h" #include "scene.h" #include "session.h" @@ -77,6 +78,9 @@ Session::Session(const SessionParams& params_) gpu_need_tonemap = false; pause = false; kernels_loaded = false; + + /* TODO(sergey): Check if it's indeed optimal value for the split kernel. */ + max_closure_global = 1; } Session::~Session() @@ -935,4 +939,15 @@ void Session::device_free() */ } +int Session::get_max_closure_count() +{ + int max_closures = 0; + for(int i = 0; i < scene->shaders.size(); i++) { + int num_closures = scene->shaders[i]->graph->get_num_closures(); + max_closures = max(max_closures, num_closures); + } + max_closure_global = max(max_closure_global, max_closures); + return max_closure_global; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index cfce5360526..c669bccd34b 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -207,6 +207,14 @@ protected: vector tile_buffers; DeviceRequestedFeatures get_requested_device_features(); + + /* ** Split kernel routines ** */ + + /* Maximumnumber of closure during session lifetime. */ + int max_closure_global; + + /* Get maximum number of closures to be used in kernel. */ + int get_max_closure_count(); }; CCL_NAMESPACE_END -- cgit v1.2.3 From 6fc166967989072bda085ae4cf54fc513f6f1daf Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 May 2015 19:22:16 +0500 Subject: Cycles: Initial work towards selective nodes support compilation The goal is to be able to compile kernel with nodes which are actually needed to render current scene, hence improving performance of the kernel, The idea is: - Have few node groups, starting with a group which contains nodes are used really often, and then couple of groups which will be extension of this one. - Have feature-based nodes disabling, so it's possible to disable nodes related to features which are not used with the currently used nodes group. This commit only lays down needed routines for this approach, actual split will happen later after gathering statistics from bunch of production scenes. --- intern/cycles/kernel/kernel_compat_cpu.h | 8 ++++++++ intern/cycles/kernel/kernel_compat_cuda.h | 8 ++++++++ intern/cycles/kernel/kernel_compat_opencl.h | 10 ++++++++++ intern/cycles/kernel/svm/svm.h | 13 ++++++++++++- intern/cycles/kernel/svm/svm_types.h | 17 +++++++++++++++++ intern/cycles/render/graph.h | 18 ++++++++++++++++++ intern/cycles/render/nodes.h | 1 + intern/cycles/render/shader.cpp | 19 +++++++++++++++++++ intern/cycles/render/shader.h | 3 +++ 9 files changed, 96 insertions(+), 1 deletion(-) diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h index 200667a0911..b209fff88e6 100644 --- a/intern/cycles/kernel/kernel_compat_cpu.h +++ b/intern/cycles/kernel/kernel_compat_cpu.h @@ -26,6 +26,14 @@ # pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif +/* Selective nodes compilation. */ +#ifndef __NODES_MAX_GROUP__ +# define __NODES_MAX_GROUP__ NODE_GROUP_LEVEL_MAX +#endif +#ifndef __NODES_FEATURES__ +# define __NODES_FEATURES__ NODE_FEATURE_ALL +#endif + #include "util_debug.h" #include "util_math.h" #include "util_simd.h" diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h index 904736c190c..61e208fcab3 100644 --- a/intern/cycles/kernel/kernel_compat_cuda.h +++ b/intern/cycles/kernel/kernel_compat_cuda.h @@ -22,6 +22,14 @@ #define CCL_NAMESPACE_BEGIN #define CCL_NAMESPACE_END +/* Selective nodes compilation. */ +#ifndef __NODES_MAX_GROUP__ +# define __NODES_MAX_GROUP__ NODE_GROUP_LEVEL_MAX +#endif +#ifndef __NODES_FEATURES__ +# define __NODES_FEATURES__ NODE_FEATURE_ALL +#endif + #include #include diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h index d480ec0f270..12b0f117600 100644 --- a/intern/cycles/kernel/kernel_compat_opencl.h +++ b/intern/cycles/kernel/kernel_compat_opencl.h @@ -37,6 +37,16 @@ #define ccl_may_alias #define ccl_constant __constant #define ccl_global __global +#define ccl_local __local +#define ccl_private __private + +/* Selective nodes compilation. */ +#ifndef __NODES_MAX_GROUP__ +# define __NODES_MAX_GROUP__ NODE_GROUP_LEVEL_MAX +#endif +#ifndef __NODES_FEATURES__ +# define __NODES_FEATURES__ NODE_FEATURE_ALL +#endif /* no assert in opencl */ #define kernel_assert(cond) diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index c13fae76bd3..b1561963e5d 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -182,8 +182,10 @@ CCL_NAMESPACE_END CCL_NAMESPACE_BEGIN -/* Main Interpreter Loop */ +#define NODES_GROUP(group) ((group) <= __NODES_MAX_GROUP__) +#define NODES_FEATURE(feature) (__NODES_FEATURES__ & (feature) != 0) +/* Main Interpreter Loop */ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderType type, int path_flag) { float stack[SVM_STACK_SIZE]; @@ -193,6 +195,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade uint4 node = read_node(kg, &offset); switch(node.x) { +#if NODES_GROUP(NODE_GROUP_LEVEL_0) case NODE_SHADER_JUMP: { if(type == SHADER_TYPE_SURFACE) offset = node.y; else if(type == SHADER_TYPE_VOLUME) offset = node.z; @@ -215,9 +218,11 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade case NODE_CLOSURE_AMBIENT_OCCLUSION: svm_node_closure_ambient_occlusion(sd, stack, node); break; +#if NODES_FEATURE(NODE_FEATURE_VOLUME) case NODE_CLOSURE_VOLUME: svm_node_closure_volume(kg, sd, stack, node, path_flag); break; +#endif /* NODES_FEATURE(NODE_FEATURE_VOLUME) */ case NODE_CLOSURE_SET_WEIGHT: svm_node_closure_set_weight(sd, node.y, node.z, node.w); break; @@ -230,6 +235,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade case NODE_MIX_CLOSURE: svm_node_mix_closure(sd, stack, node); break; +#endif /* NODES_GROUP(NODE_GROUP_LEVEL_0) */ case NODE_JUMP_IF_ZERO: if(stack_load_float(stack, node.z) == 0.0f) offset += node.y; @@ -299,9 +305,11 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade svm_node_particle_info(kg, sd, stack, node.y, node.z); break; #ifdef __HAIR__ +# if NODES_FEATURE(NODE_FEATURE_HAIR) case NODE_HAIR_INFO: svm_node_hair_info(kg, sd, stack, node.y, node.z); break; +# endif /* NODES_FEATURE(NODE_FEATURE_HAIR) */ #endif /* __HAIR__ */ #endif /* __EXTRA_NODES__ */ @@ -434,6 +442,9 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade } } +#undef NODES_GROUP +#undef NODES_FEATURE + CCL_NAMESPACE_END #endif /* __SVM_H__ */ diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 848c16be327..4f2117a605b 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -28,6 +28,23 @@ CCL_NAMESPACE_BEGIN /* Nodes */ +/* Known frequencies of used nodes, used for selective nodes compilation + * in the kernel. Currently only affects split OpenCL kernel. + * + * Keep as defines so it's easy to check which nodes are to be compiled + * from preprocessor. + * + * Lower the number of group more often the node is used. + */ +#define NODE_GROUP_LEVEL_0 0 +#define NODE_GROUP_LEVEL_1 1 +#define NODE_GROUP_LEVEL_2 2 +#define NODE_GROUP_LEVEL_MAX NODE_GROUP_LEVEL_2 + +#define NODE_FEATURE_VOLUME (1 << 0) +#define NODE_FEATURE_HAIR (1 << 1) +#define NODE_FEATURE_ALL (NODE_FEATURE_VOLUME|NODE_FEATURE_HAIR) + typedef enum NodeType { NODE_END = 0, NODE_CLOSURE_BSDF, diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index 6744804ef19..e6271009999 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -207,6 +207,24 @@ public: ShaderBump bump; /* for bump mapping utility */ ShaderNodeSpecialType special_type; /* special node type */ + + /* ** Selective nodes compilation ** */ + + /* TODO(sergey): More explicitly mention in the function names + * that those functions are for selective compilation only? + */ + + /* Nodes are split into several groups, group of level 0 contains + * nodes which are most commonly used, further levels are extension + * of previous one and includes less commonly used nodes. + */ + virtual int get_group() { return NODE_GROUP_LEVEL_0; } + + /* Node feature are used to disable huge nodes inside the group, + * so it's possible to disable huge nodes inside of the required + * nodes group. + */ + virtual int get_feature() { return 0; } }; diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 686fb5e2fd7..ac7bbaf3547 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -415,6 +415,7 @@ public: void attributes(Shader *shader, AttributeRequestSet *attributes); bool has_spatial_varying() { return true; } + virtual int get_feature() { return NODE_FEATURE_HAIR; } }; class ValueNode : public ShaderNode { diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 971cd5097de..2eaba3fa786 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -480,5 +480,24 @@ void ShaderManager::add_default(Scene *scene) } } +void ShaderManager::get_requested_features(Scene *scene, int& max_group, int& features) +{ + max_group = NODE_GROUP_LEVEL_0; + features = 0; + for(int i = 0; i < scene->shaders.size(); i++) { + Shader *shader = scene->shaders[i]; + foreach(ShaderNode *node, shader->graph->nodes) { + max_group = min(max_group, node->get_group()); + features |= node->get_feature(); + if(node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) { + BsdfNode *bsdf_node = static_cast(node); + if(CLOSURE_IS_VOLUME(bsdf_node->closure)) { + features |= NODE_FEATURE_VOLUME; + } + } + } + } +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index 5bcb2c4e344..27b239601d0 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -165,6 +165,9 @@ public: * have any shader assigned explicitly */ static void add_default(Scene *scene); + /* Selective nodes compilation. */ + void get_requested_features(Scene *scene, int& max_group, int& features); + protected: ShaderManager(); -- cgit v1.2.3 From f680c1b54a28a02fb86271bca649da0660542e9a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 May 2015 19:28:00 +0500 Subject: Cycles: Communicate number of closures and nodes feature set to the device This way device can actually make a decision of how it can optimize the kernel in order to make it most efficient. --- intern/cycles/device/device.h | 25 ++++++++++++++++++++++++- intern/cycles/device/device_network.cpp | 6 ++++++ intern/cycles/render/session.cpp | 12 ++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 98155900748..4d40518644e 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -74,14 +74,37 @@ public: /* Use experimental feature set. */ bool experimental; + /* Maximum number of closures in shader trees. */ + int max_closure; + + /* Selective nodes compilation. */ + + /* Identifier of a node group up to which all the nodes needs to be + * compiled in. Nodes from higher group indices will be ignores. + */ + int max_nodes_group; + + /* Features bitfield indicating which features from the requested group + * will be compiled in. Nodes which corresponds to features which are not + * in this bitfield will be ignored even if they're in the requested group. + */ + int nodes_features; + DeviceRequestedFeatures() { + /* TODO(sergey): Find more meaningful defaults. */ experimental = false; + max_closure = 0; + max_nodes_group = 0; + nodes_features = 0; } bool modified(const DeviceRequestedFeatures& requested_features) { - return !(experimental == requested_features.experimental); + return !(experimental == requested_features.experimental && + max_closure == requested_features.max_closure && + max_nodes_group == requested_features.max_nodes_group && + nodes_features == requested_features.nodes_features); } }; diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp index 454f7301975..ca6d668a79d 100644 --- a/intern/cycles/device/device_network.cpp +++ b/intern/cycles/device/device_network.cpp @@ -205,6 +205,9 @@ public: RPCSend snd(socket, &error_func, "load_kernels"); snd.add(requested_features.experimental); + snd.add(requested_features.max_closure); + snd.add(requested_features.max_nodes_group); + snd.add(requested_features.nodes_features); snd.write(); bool result; @@ -609,6 +612,9 @@ protected: else if(rcv.name == "load_kernels") { DeviceRequestedFeatures requested_features; rcv.read(requested_features.experimental); + rcv.read(requested_features.max_closure); + rcv.read(requested_features.max_nodes_group); + rcv.read(requested_features.nodes_features); bool result; result = device->load_kernels(requested_features); diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index cfd974346c3..aacb81faf83 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -601,6 +601,18 @@ DeviceRequestedFeatures Session::get_requested_device_features() { DeviceRequestedFeatures requested_features; requested_features.experimental = params.experimental; + if(!params.background) { + requested_features.max_closure = 64; + requested_features.max_nodes_group = NODE_GROUP_LEVEL_2; + requested_features.nodes_features = NODE_FEATURE_ALL; + } + else { + requested_features.max_closure = get_max_closure_count(); + scene->shader_manager->get_requested_features( + scene, + requested_features.max_nodes_group, + requested_features.nodes_features); + } return requested_features; } -- cgit v1.2.3 From 7f4479da425b2d44a585f1b7b63f91d9dfecef02 Mon Sep 17 00:00:00 2001 From: George Kyriazis Date: Sat, 9 May 2015 19:34:30 +0500 Subject: Cycles: OpenCL kernel split This commit contains all the work related on the AMD megakernel split work which was mainly done by Varun Sundar, George Kyriazis and Lenny Wang, plus some help from Sergey Sharybin, Martijn Berger, Thomas Dinges and likely someone else which we're forgetting to mention. Currently only AMD cards are enabled for the new split kernel, but it is possible to force split opencl kernel to be used by setting the following environment variable: CYCLES_OPENCL_SPLIT_KERNEL_TEST=1. Not all the features are supported yet, and that being said no motion blur, camera blur, SSS and volumetrics for now. Also transparent shadows are disabled on AMD device because of some compiler bug. This kernel is also only implements regular path tracing and supporting branched one will take a bit. Branched path tracing is exposed to the interface still, which is a bit misleading and will be hidden there soon. More feature will be enabled once they're ported to the split kernel and tested. Neither regular CPU nor CUDA has any difference, they're generating the same exact code, which means no regressions/improvements there. Based on the research paper: https://research.nvidia.com/sites/default/files/publications/laine2013hpg_paper.pdf Here's the documentation: https://docs.google.com/document/d/1LuXW-CV-sVJkQaEGZlMJ86jZ8FmoPfecaMdR-oiWbUY/edit Design discussion of the patch: https://developer.blender.org/T44197 Differential Revision: https://developer.blender.org/D1200 --- intern/cycles/device/device.h | 2 + intern/cycles/device/device_opencl.cpp | 2440 +++++++++++++++++++- intern/cycles/kernel/CMakeLists.txt | 28 + intern/cycles/kernel/closure/bsdf.h | 100 +- intern/cycles/kernel/geom/geom_attribute.h | 8 +- intern/cycles/kernel/geom/geom_bvh.h | 2 + intern/cycles/kernel/geom/geom_motion_triangle.h | 36 +- intern/cycles/kernel/geom/geom_object.h | 69 +- intern/cycles/kernel/geom/geom_primitive.h | 36 +- intern/cycles/kernel/geom/geom_triangle.h | 42 +- intern/cycles/kernel/kernel.cl | 61 +- intern/cycles/kernel/kernel_accumulate.h | 2 +- .../kernel/kernel_background_buffer_update.cl | 282 +++ intern/cycles/kernel/kernel_camera.h | 13 +- intern/cycles/kernel/kernel_compat_cpu.h | 2 + intern/cycles/kernel/kernel_compat_cuda.h | 1 + intern/cycles/kernel/kernel_compat_opencl.h | 6 + intern/cycles/kernel/kernel_data_init.cl | 384 +++ intern/cycles/kernel/kernel_debug.h | 2 +- intern/cycles/kernel/kernel_differential.h | 6 +- intern/cycles/kernel/kernel_direct_lighting.cl | 137 ++ intern/cycles/kernel/kernel_emission.h | 85 +- intern/cycles/kernel/kernel_globals.h | 2 +- ...holdout_emission_blurring_pathtermination_ao.cl | 283 +++ intern/cycles/kernel/kernel_lamp_emission.cl | 209 ++ .../cycles/kernel/kernel_next_iteration_setup.cl | 176 ++ intern/cycles/kernel/kernel_passes.h | 38 +- intern/cycles/kernel/kernel_path.h | 55 +- intern/cycles/kernel/kernel_path_common.h | 50 + intern/cycles/kernel/kernel_path_state.h | 6 +- intern/cycles/kernel/kernel_path_surface.h | 48 +- intern/cycles/kernel/kernel_queue_enqueue.cl | 98 + intern/cycles/kernel/kernel_queues.h | 132 ++ intern/cycles/kernel/kernel_random.h | 18 +- intern/cycles/kernel/kernel_scene_intersect.cl | 164 ++ intern/cycles/kernel/kernel_shader.h | 297 +-- intern/cycles/kernel/kernel_shader_eval.cl | 93 + intern/cycles/kernel/kernel_shaderdata_vars.h | 99 + intern/cycles/kernel/kernel_shadow.h | 54 +- intern/cycles/kernel/kernel_shadow_blocked.cl | 126 + intern/cycles/kernel/kernel_split.h | 87 + intern/cycles/kernel/kernel_sum_all_radiance.cl | 59 + intern/cycles/kernel/kernel_types.h | 187 +- intern/cycles/kernel/kernel_work_stealing.h | 193 ++ intern/cycles/kernel/svm/svm.h | 2 +- intern/cycles/kernel/svm/svm_attribute.h | 6 +- intern/cycles/kernel/svm/svm_camera.h | 2 +- intern/cycles/kernel/svm/svm_closure.h | 140 +- intern/cycles/kernel/svm/svm_displace.h | 10 +- intern/cycles/kernel/svm/svm_fresnel.h | 14 +- intern/cycles/kernel/svm/svm_geometry.h | 42 +- intern/cycles/kernel/svm/svm_image.h | 6 +- intern/cycles/kernel/svm/svm_light_path.h | 14 +- intern/cycles/kernel/svm/svm_tex_coord.h | 114 +- intern/cycles/kernel/svm/svm_vector_transform.h | 2 +- intern/cycles/kernel/svm/svm_wireframe.h | 37 +- intern/cycles/render/session.cpp | 5 +- 57 files changed, 5784 insertions(+), 828 deletions(-) create mode 100644 intern/cycles/kernel/kernel_background_buffer_update.cl create mode 100644 intern/cycles/kernel/kernel_data_init.cl create mode 100644 intern/cycles/kernel/kernel_direct_lighting.cl create mode 100644 intern/cycles/kernel/kernel_holdout_emission_blurring_pathtermination_ao.cl create mode 100644 intern/cycles/kernel/kernel_lamp_emission.cl create mode 100644 intern/cycles/kernel/kernel_next_iteration_setup.cl create mode 100644 intern/cycles/kernel/kernel_path_common.h create mode 100644 intern/cycles/kernel/kernel_queue_enqueue.cl create mode 100644 intern/cycles/kernel/kernel_queues.h create mode 100644 intern/cycles/kernel/kernel_scene_intersect.cl create mode 100644 intern/cycles/kernel/kernel_shader_eval.cl create mode 100644 intern/cycles/kernel/kernel_shaderdata_vars.h create mode 100644 intern/cycles/kernel/kernel_shadow_blocked.cl create mode 100644 intern/cycles/kernel/kernel_split.h create mode 100644 intern/cycles/kernel/kernel_sum_all_radiance.cl create mode 100644 intern/cycles/kernel/kernel_work_stealing.h diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 4d40518644e..162f51252b0 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -55,6 +55,7 @@ public: bool advanced_shading; bool pack_images; bool extended_images; /* flag for GPU and Multi device */ + bool use_split_kernel; /* Denotes if the device is going to run cycles using split-kernel */ vector multi_devices; DeviceInfo() @@ -66,6 +67,7 @@ public: advanced_shading = true; pack_images = false; extended_images = false; + use_split_kernel = false; } }; diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 1147cbd69b4..25eb160d71b 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -39,6 +39,30 @@ CCL_NAMESPACE_BEGIN #define CL_MEM_PTR(p) ((cl_mem)(uintptr_t)(p)) +#define KERNEL_APPEND_ARG(kernel_name, arg) \ + opencl_assert(clSetKernelArg(kernel_name, narg++, sizeof(arg), (void*)&arg)) + +/* Macro declarations used with split kernel */ + +/* Macro to enable/disable work-stealing */ +#define __WORK_STEALING__ + +#define SPLIT_KERNEL_LOCAL_SIZE_X 64 +#define SPLIT_KERNEL_LOCAL_SIZE_Y 1 + +/* This value may be tuned according to the scene we are rendering. + * + * Modifying PATH_ITER_INC_FACTOR value proportional to number of expected + * ray-bounces will improve performance. + */ +#define PATH_ITER_INC_FACTOR 8 + +/* When allocate global memory in chunks. We may not be able to + * allocate exactly "CL_DEVICE_MAX_MEM_ALLOC_SIZE" bytes in chunks; + * Since some bytes may be needed for aligning chunks of memory; + * This is the amount of memory that we dedicate for that purpose. + */ +#define DATA_ALLOCATION_MEM_FACTOR 5000000 //5MB static cl_device_type opencl_device_type() { @@ -94,11 +118,11 @@ static string opencl_kernel_build_options(const string& platform, const string * build_options += "-D__KERNEL_OPENCL_AMD__ "; else if(platform == "Intel(R) OpenCL") { - build_options += "-D__KERNEL_OPENCL_INTEL_CPU__"; + build_options += "-D__KERNEL_OPENCL_INTEL_CPU__ "; /* options for gdb source level kernel debugging. this segfaults on linux currently */ if(opencl_kernel_use_debug() && debug_src) - build_options += "-g -s \"" + *debug_src + "\""; + build_options += "-g -s \"" + *debug_src + "\" "; } if(opencl_kernel_use_debug()) @@ -118,14 +142,18 @@ class OpenCLCache { thread_mutex *mutex; cl_context context; - cl_program program; + /* cl_program for shader, bake, film_convert kernels (used in OpenCLDeviceBase) */ + cl_program ocl_dev_base_program; + /* cl_program for megakernel (used in OpenCLDeviceMegaKernel) */ + cl_program ocl_dev_megakernel_program; - Slot() : mutex(NULL), context(NULL), program(NULL) {} + Slot() : mutex(NULL), context(NULL), ocl_dev_base_program(NULL), ocl_dev_megakernel_program(NULL) {} Slot(const Slot &rhs) : mutex(rhs.mutex) , context(rhs.context) - , program(rhs.program) + , ocl_dev_base_program(rhs.ocl_dev_base_program) + , ocl_dev_megakernel_program(rhs.ocl_dev_megakernel_program) { /* copy can only happen in map insert, assert that */ assert(mutex == NULL); @@ -236,6 +264,12 @@ class OpenCLCache } public: + + enum ProgramName { + OCL_DEV_BASE_PROGRAM, + OCL_DEV_MEGAKERNEL_PROGRAM, + }; + /* see get_something comment */ static cl_context get_context(cl_platform_id platform, cl_device_id device, thread_scoped_lock &slot_locker) @@ -254,10 +288,21 @@ public: } /* see get_something comment */ - static cl_program get_program(cl_platform_id platform, cl_device_id device, + static cl_program get_program(cl_platform_id platform, cl_device_id device, ProgramName program_name, thread_scoped_lock &slot_locker) { - cl_program program = get_something(platform, device, &Slot::program, slot_locker); + cl_program program = NULL; + + if(program_name == OCL_DEV_BASE_PROGRAM) { + /* Get program related to OpenCLDeviceBase */ + program = get_something(platform, device, &Slot::ocl_dev_base_program, slot_locker); + } + else if(program_name == OCL_DEV_MEGAKERNEL_PROGRAM) { + /* Get program related to megakernel */ + program = get_something(platform, device, &Slot::ocl_dev_megakernel_program, slot_locker); + } else { + assert(!"Invalid program name"); + } if(!program) return NULL; @@ -284,10 +329,18 @@ public: } /* see store_something comment */ - static void store_program(cl_platform_id platform, cl_device_id device, cl_program program, + static void store_program(cl_platform_id platform, cl_device_id device, cl_program program, ProgramName program_name, thread_scoped_lock &slot_locker) { - store_something(platform, device, program, &Slot::program, slot_locker); + if(program_name == OCL_DEV_BASE_PROGRAM) { + store_something(platform, device, program, &Slot::ocl_dev_base_program, slot_locker); + } + else if(program_name == OCL_DEV_MEGAKERNEL_PROGRAM) { + store_something(platform, device, program, &Slot::ocl_dev_megakernel_program, slot_locker); + } else { + assert(!"Invalid program name\n"); + return; + } /* increment reference count in OpenCL. * The caller is going to release the object when done with it. */ @@ -304,8 +357,10 @@ public: thread_scoped_lock cache_lock(self.cache_lock); foreach(CacheMap::value_type &item, self.cache) { - if(item.second.program != NULL) - clReleaseProgram(item.second.program); + if(item.second.ocl_dev_base_program != NULL) + clReleaseProgram(item.second.ocl_dev_base_program); + if(item.second.ocl_dev_megakernel_program != NULL) + clReleaseProgram(item.second.ocl_dev_megakernel_program); if(item.second.context != NULL) clReleaseContext(item.second.context); } @@ -314,7 +369,7 @@ public: } }; -class OpenCLDevice : public Device +class OpenCLDeviceBase : public Device { public: DedicatedTaskPool task_pool; @@ -323,7 +378,6 @@ public: cl_platform_id cpPlatform; cl_device_id cdDevice; cl_program cpProgram; - cl_kernel ckPathTraceKernel; cl_kernel ckFilmConvertByteKernel; cl_kernel ckFilmConvertHalfFloatKernel; cl_kernel ckShaderKernel; @@ -385,7 +439,7 @@ public: } } - OpenCLDevice(DeviceInfo& info, Stats &stats, bool background_) + OpenCLDeviceBase(DeviceInfo& info, Stats &stats, bool background_) : Device(info, stats, background_) { cpPlatform = NULL; @@ -393,7 +447,6 @@ public: cxContext = NULL; cqCommandQueue = NULL; cpProgram = NULL; - ckPathTraceKernel = NULL; ckFilmConvertByteKernel = NULL; ckFilmConvertHalfFloatKernel = NULL; ckShaderKernel = NULL; @@ -501,7 +554,7 @@ public: if(opencl_error(ciErr)) return; - fprintf(stderr,"Device init succes\n"); + fprintf(stderr, "Device init success\n"); device_initialized = true; } @@ -547,7 +600,11 @@ public: return true; } - bool load_binary(const string& kernel_path, const string& clbin, const string *debug_src = NULL) + bool load_binary(const string& /*kernel_path*/, + const string& clbin, + string custom_kernel_build_options, + cl_program *program, + const string *debug_src = NULL) { /* read binary into memory */ vector binary; @@ -562,7 +619,7 @@ public: size_t size = binary.size(); const uint8_t *bytes = &binary[0]; - cpProgram = clCreateProgramWithBinary(cxContext, 1, &cdDevice, + *program = clCreateProgramWithBinary(cxContext, 1, &cdDevice, &size, &bytes, &status, &ciErr); if(opencl_error(status) || opencl_error(ciErr)) { @@ -570,16 +627,16 @@ public: return false; } - if(!build_kernel(kernel_path, debug_src)) + if(!build_kernel(program, custom_kernel_build_options, debug_src)) return false; return true; } - bool save_binary(const string& clbin) + bool save_binary(cl_program *program, const string& clbin) { size_t size = 0; - clGetProgramInfo(cpProgram, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &size, NULL); + clGetProgramInfo(*program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &size, NULL); if(!size) return false; @@ -587,7 +644,7 @@ public: vector binary(size); uint8_t *bytes = &binary[0]; - clGetProgramInfo(cpProgram, CL_PROGRAM_BINARIES, sizeof(uint8_t*), &bytes, NULL); + clGetProgramInfo(*program, CL_PROGRAM_BINARIES, sizeof(uint8_t*), &bytes, NULL); if(!path_write_binary(clbin, binary)) { opencl_error(string_printf("OpenCL failed to write cached binary %s.", clbin.c_str())); @@ -597,20 +654,23 @@ public: return true; } - bool build_kernel(const string& /*kernel_path*/, const string *debug_src = NULL) + bool build_kernel(cl_program *kernel_program, + string custom_kernel_build_options, + const string *debug_src = NULL) { - string build_options = opencl_kernel_build_options(platform_name, debug_src); - - ciErr = clBuildProgram(cpProgram, 0, NULL, build_options.c_str(), NULL, NULL); + string build_options; + build_options = opencl_kernel_build_options(platform_name, debug_src) + custom_kernel_build_options; + + ciErr = clBuildProgram(*kernel_program, 0, NULL, build_options.c_str(), NULL, NULL); /* show warnings even if build is successful */ size_t ret_val_size = 0; - clGetProgramBuildInfo(cpProgram, cdDevice, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size); + clGetProgramBuildInfo(*kernel_program, cdDevice, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size); if(ret_val_size > 1) { - vector build_log(ret_val_size+1); - clGetProgramBuildInfo(cpProgram, cdDevice, CL_PROGRAM_BUILD_LOG, ret_val_size, &build_log[0], NULL); + vector build_log(ret_val_size + 1); + clGetProgramBuildInfo(*kernel_program, cdDevice, CL_PROGRAM_BUILD_LOG, ret_val_size, &build_log[0], NULL); build_log[ret_val_size] = '\0'; fprintf(stderr, "OpenCL kernel build output:\n"); @@ -625,12 +685,15 @@ public: return true; } - bool compile_kernel(const string& kernel_path, const string& kernel_md5, const string *debug_src = NULL) + bool compile_kernel(const string& kernel_path, + string source, + string custom_kernel_build_options, + cl_program *kernel_program, + const string *debug_src = NULL) { /* we compile kernels consisting of many files. unfortunately opencl * kernel caches do not seem to recognize changes in included files. * so we force recompile on changes by adding the md5 hash of all files */ - string source = "#include \"kernel.cl\" // " + kernel_md5 + "\n"; source = path_source_replace_includes(source, kernel_path); if(debug_src) @@ -639,7 +702,7 @@ public: size_t source_len = source.size(); const char *source_str = source.c_str(); - cpProgram = clCreateProgramWithSource(cxContext, 1, &source_str, &source_len, &ciErr); + *kernel_program = clCreateProgramWithSource(cxContext, 1, &source_str, &source_len, &ciErr); if(opencl_error(ciErr)) return false; @@ -647,7 +710,7 @@ public: double starttime = time_dt(); printf("Compiling OpenCL kernel ...\n"); - if(!build_kernel(kernel_path, debug_src)) + if(!build_kernel(kernel_program, custom_kernel_build_options, debug_src)) return false; printf("Kernel compilation finished in %.2lfs.\n", time_dt() - starttime); @@ -655,7 +718,7 @@ public: return true; } - string device_md5_hash() + string device_md5_hash(string kernel_custom_build_options = "") { MD5Hash md5; char version[256], driver[256], name[256], vendor[256]; @@ -671,12 +734,13 @@ public: md5.append((uint8_t*)driver, strlen(driver)); string options = opencl_kernel_build_options(platform_name); + options += kernel_custom_build_options; md5.append((uint8_t*)options.c_str(), options.size()); return md5.get_hex(); } - bool load_kernels(bool /*experimental*/) + bool load_kernels(const DeviceRequestedFeatures& /*requested_features*/) { /* verify if device was initialized */ if(!device_initialized) { @@ -686,7 +750,7 @@ public: /* try to use cached kernel */ thread_scoped_lock cache_locker; - cpProgram = OpenCLCache::get_program(cpPlatform, cdDevice, cache_locker); + cpProgram = OpenCLCache::get_program(cpPlatform, cdDevice, OpenCLCache::OCL_DEV_BASE_PROGRAM, cache_locker); if(!cpProgram) { /* verify we have right opencl version */ @@ -712,28 +776,27 @@ public: } /* if exists already, try use it */ - if(path_exists(clbin) && load_binary(kernel_path, clbin, debug_src)) { + if(path_exists(clbin) && load_binary(kernel_path, clbin, "", &cpProgram)) { /* kernel loaded from binary */ } else { + + string init_kernel_source = "#include \"kernel.cl\" // " + kernel_md5 + "\n"; + /* if does not exist or loading binary failed, compile kernel */ - if(!compile_kernel(kernel_path, kernel_md5, debug_src)) + if(!compile_kernel(kernel_path, init_kernel_source, "", &cpProgram, debug_src)) return false; /* save binary for reuse */ - if(!save_binary(clbin)) + if(!save_binary(&cpProgram, clbin)) return false; } /* cache the program */ - OpenCLCache::store_program(cpPlatform, cdDevice, cpProgram, cache_locker); + OpenCLCache::store_program(cpPlatform, cdDevice, cpProgram, OpenCLCache::OCL_DEV_BASE_PROGRAM, cache_locker); } /* find kernels */ - ckPathTraceKernel = clCreateKernel(cpProgram, "kernel_ocl_path_trace", &ciErr); - if(opencl_error(ciErr)) - return false; - ckFilmConvertByteKernel = clCreateKernel(cpProgram, "kernel_ocl_convert_to_byte", &ciErr); if(opencl_error(ciErr)) return false; @@ -753,7 +816,7 @@ public: return true; } - ~OpenCLDevice() + ~OpenCLDeviceBase() { task_pool.stop(); @@ -766,12 +829,14 @@ public: delete mt->second; } - if(ckPathTraceKernel) - clReleaseKernel(ckPathTraceKernel); if(ckFilmConvertByteKernel) clReleaseKernel(ckFilmConvertByteKernel); if(ckFilmConvertHalfFloatKernel) clReleaseKernel(ckFilmConvertHalfFloatKernel); + if(ckShaderKernel) + clReleaseKernel(ckShaderKernel); + if(ckBakeKernel) + clReleaseKernel(ckBakeKernel); if(cpProgram) clReleaseProgram(cpProgram); if(cqCommandQueue) @@ -913,42 +978,6 @@ public: opencl_assert(clFlush(cqCommandQueue)); } - void path_trace(RenderTile& rtile, int sample) - { - /* cast arguments to cl types */ - cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer); - cl_mem d_buffer = CL_MEM_PTR(rtile.buffer); - cl_mem d_rng_state = CL_MEM_PTR(rtile.rng_state); - cl_int d_x = rtile.x; - cl_int d_y = rtile.y; - cl_int d_w = rtile.w; - cl_int d_h = rtile.h; - cl_int d_sample = sample; - cl_int d_offset = rtile.offset; - cl_int d_stride = rtile.stride; - - /* sample arguments */ - cl_uint narg = 0; - - opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_data), (void*)&d_data)); - opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_buffer), (void*)&d_buffer)); - opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_rng_state), (void*)&d_rng_state)); - -#define KERNEL_TEX(type, ttype, name) \ - set_kernel_arg_mem(ckPathTraceKernel, &narg, #name); -#include "kernel_textures.h" - - opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_sample), (void*)&d_sample)); - opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_x), (void*)&d_x)); - opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_y), (void*)&d_y)); - opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_w), (void*)&d_w)); - opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_h), (void*)&d_h)); - opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_offset), (void*)&d_offset)); - opencl_assert(clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_stride), (void*)&d_stride)); - - enqueue_kernel(ckPathTraceKernel, d_w, d_h); - } - void set_kernel_arg_mem(cl_kernel kernel, cl_uint *narg, const char *name) { cl_mem ptr; @@ -985,23 +1014,23 @@ public: cl_kernel ckFilmConvertKernel = (rgba_byte)? ckFilmConvertByteKernel: ckFilmConvertHalfFloatKernel; - opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_data), (void*)&d_data)); - opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_rgba), (void*)&d_rgba)); - opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_buffer), (void*)&d_buffer)); + /* TODO : Make the kernel launch similar to Cuda */ + KERNEL_APPEND_ARG(ckFilmConvertKernel, d_data); + KERNEL_APPEND_ARG(ckFilmConvertKernel, d_rgba); + KERNEL_APPEND_ARG(ckFilmConvertKernel, d_buffer); #define KERNEL_TEX(type, ttype, name) \ set_kernel_arg_mem(ckFilmConvertKernel, &narg, #name); #include "kernel_textures.h" +#undef KERNEL_TEX - opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_sample_scale), (void*)&d_sample_scale)); - opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_x), (void*)&d_x)); - opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_y), (void*)&d_y)); - opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_w), (void*)&d_w)); - opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_h), (void*)&d_h)); - opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_offset), (void*)&d_offset)); - opencl_assert(clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_stride), (void*)&d_stride)); - - + KERNEL_APPEND_ARG(ckFilmConvertKernel, d_sample_scale); + KERNEL_APPEND_ARG(ckFilmConvertKernel, d_x); + KERNEL_APPEND_ARG(ckFilmConvertKernel, d_y); + KERNEL_APPEND_ARG(ckFilmConvertKernel, d_w); + KERNEL_APPEND_ARG(ckFilmConvertKernel, d_h); + KERNEL_APPEND_ARG(ckFilmConvertKernel, d_offset); + KERNEL_APPEND_ARG(ckFilmConvertKernel, d_stride); enqueue_kernel(ckFilmConvertKernel, d_w, d_h); } @@ -1034,19 +1063,21 @@ public: cl_int d_sample = sample; - opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_data), (void*)&d_data)); - opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_input), (void*)&d_input)); - opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_output), (void*)&d_output)); + /* TODO : Make the kernel launch similar to Cuda */ + KERNEL_APPEND_ARG(kernel, d_data); + KERNEL_APPEND_ARG(kernel, d_input); + KERNEL_APPEND_ARG(kernel, d_output); #define KERNEL_TEX(type, ttype, name) \ set_kernel_arg_mem(kernel, &narg, #name); #include "kernel_textures.h" +#undef KERNEL_TEX - opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_shader_eval_type), (void*)&d_shader_eval_type)); - opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_shader_x), (void*)&d_shader_x)); - opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_shader_w), (void*)&d_shader_w)); - opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_offset), (void*)&d_offset)); - opencl_assert(clSetKernelArg(kernel, narg++, sizeof(d_sample), (void*)&d_sample)); + KERNEL_APPEND_ARG(kernel, d_shader_eval_type); + KERNEL_APPEND_ARG(kernel, d_shader_x); + KERNEL_APPEND_ARG(kernel, d_shader_w); + KERNEL_APPEND_ARG(kernel, d_offset); + KERNEL_APPEND_ARG(kernel, d_sample); enqueue_kernel(kernel, task.shader_w, 1); @@ -1054,6 +1085,305 @@ public: } } + class OpenCLDeviceTask : public DeviceTask { + public: + OpenCLDeviceTask(OpenCLDeviceBase *device, DeviceTask& task) + : DeviceTask(task) + { + run = function_bind(&OpenCLDeviceBase::thread_run, + device, + this); + } + }; + + int get_split_task_count(DeviceTask& /*task*/) + { + return 1; + } + + void task_add(DeviceTask& task) + { + task_pool.push(new OpenCLDeviceTask(this, task)); + } + + void task_wait() + { + task_pool.wait(); + } + + void task_cancel() + { + task_pool.cancel(); + } + + virtual void thread_run(DeviceTask * /*task*/) = 0; + +protected: + class ArgumentWrapper { + public: + ArgumentWrapper() : size(0), pointer(NULL) {} + template + ArgumentWrapper(T& argument) : size(sizeof(argument)), + pointer(&argument) { } + size_t size; + void *pointer; + }; + + /* TODO(sergey): In the future we can use variadic templates, once + * C++0x is allowed. Should allow to clean this up a bit. + */ + int kernel_set_args(cl_kernel kernel, + int start_argument_index, + const ArgumentWrapper& arg1 = ArgumentWrapper(), + const ArgumentWrapper& arg2 = ArgumentWrapper(), + const ArgumentWrapper& arg3 = ArgumentWrapper(), + const ArgumentWrapper& arg4 = ArgumentWrapper(), + const ArgumentWrapper& arg5 = ArgumentWrapper(), + const ArgumentWrapper& arg6 = ArgumentWrapper(), + const ArgumentWrapper& arg7 = ArgumentWrapper(), + const ArgumentWrapper& arg8 = ArgumentWrapper(), + const ArgumentWrapper& arg9 = ArgumentWrapper(), + const ArgumentWrapper& arg10 = ArgumentWrapper(), + const ArgumentWrapper& arg11 = ArgumentWrapper(), + const ArgumentWrapper& arg12 = ArgumentWrapper(), + const ArgumentWrapper& arg13 = ArgumentWrapper(), + const ArgumentWrapper& arg14 = ArgumentWrapper(), + const ArgumentWrapper& arg15 = ArgumentWrapper(), + const ArgumentWrapper& arg16 = ArgumentWrapper(), + const ArgumentWrapper& arg17 = ArgumentWrapper(), + const ArgumentWrapper& arg18 = ArgumentWrapper(), + const ArgumentWrapper& arg19 = ArgumentWrapper(), + const ArgumentWrapper& arg20 = ArgumentWrapper(), + const ArgumentWrapper& arg21 = ArgumentWrapper(), + const ArgumentWrapper& arg22 = ArgumentWrapper(), + const ArgumentWrapper& arg23 = ArgumentWrapper(), + const ArgumentWrapper& arg24 = ArgumentWrapper(), + const ArgumentWrapper& arg25 = ArgumentWrapper(), + const ArgumentWrapper& arg26 = ArgumentWrapper(), + const ArgumentWrapper& arg27 = ArgumentWrapper(), + const ArgumentWrapper& arg28 = ArgumentWrapper(), + const ArgumentWrapper& arg29 = ArgumentWrapper(), + const ArgumentWrapper& arg30 = ArgumentWrapper(), + const ArgumentWrapper& arg31 = ArgumentWrapper(), + const ArgumentWrapper& arg32 = ArgumentWrapper(), + const ArgumentWrapper& arg33 = ArgumentWrapper()) + { + int current_arg_index = 0; +#define FAKE_VARARG_HANDLE_ARG(arg) \ + do { \ + if(arg.pointer != NULL) { \ + opencl_assert(clSetKernelArg( \ + kernel, \ + start_argument_index + current_arg_index, \ + arg.size, arg.pointer)); \ + ++current_arg_index; \ + } \ + else { \ + return current_arg_index; \ + } \ + } while(false) + FAKE_VARARG_HANDLE_ARG(arg1); + FAKE_VARARG_HANDLE_ARG(arg2); + FAKE_VARARG_HANDLE_ARG(arg3); + FAKE_VARARG_HANDLE_ARG(arg4); + FAKE_VARARG_HANDLE_ARG(arg5); + FAKE_VARARG_HANDLE_ARG(arg6); + FAKE_VARARG_HANDLE_ARG(arg7); + FAKE_VARARG_HANDLE_ARG(arg8); + FAKE_VARARG_HANDLE_ARG(arg9); + FAKE_VARARG_HANDLE_ARG(arg10); + FAKE_VARARG_HANDLE_ARG(arg11); + FAKE_VARARG_HANDLE_ARG(arg12); + FAKE_VARARG_HANDLE_ARG(arg13); + FAKE_VARARG_HANDLE_ARG(arg14); + FAKE_VARARG_HANDLE_ARG(arg15); + FAKE_VARARG_HANDLE_ARG(arg16); + FAKE_VARARG_HANDLE_ARG(arg17); + FAKE_VARARG_HANDLE_ARG(arg18); + FAKE_VARARG_HANDLE_ARG(arg19); + FAKE_VARARG_HANDLE_ARG(arg20); + FAKE_VARARG_HANDLE_ARG(arg21); + FAKE_VARARG_HANDLE_ARG(arg22); + FAKE_VARARG_HANDLE_ARG(arg23); + FAKE_VARARG_HANDLE_ARG(arg24); + FAKE_VARARG_HANDLE_ARG(arg25); + FAKE_VARARG_HANDLE_ARG(arg26); + FAKE_VARARG_HANDLE_ARG(arg27); + FAKE_VARARG_HANDLE_ARG(arg28); + FAKE_VARARG_HANDLE_ARG(arg29); + FAKE_VARARG_HANDLE_ARG(arg30); + FAKE_VARARG_HANDLE_ARG(arg31); + FAKE_VARARG_HANDLE_ARG(arg32); + FAKE_VARARG_HANDLE_ARG(arg33); +#undef FAKE_VARARG_HANDLE_ARG + return current_arg_index; + } + + inline void release_kernel_safe(cl_kernel kernel) + { + if(kernel) { + clReleaseKernel(kernel); + } + } + + inline void release_mem_object_safe(cl_mem mem) + { + if(mem != NULL) { + clReleaseMemObject(mem); + } + } + + inline void release_program_safe(cl_program program) + { + if(program) { + clReleaseProgram(program); + } + } +}; + +class OpenCLDeviceMegaKernel : public OpenCLDeviceBase +{ +public: + cl_kernel ckPathTraceKernel; + cl_program path_trace_program; + + OpenCLDeviceMegaKernel(DeviceInfo& info, Stats &stats, bool background_) + : OpenCLDeviceBase(info, stats, background_) + { + ckPathTraceKernel = NULL; + path_trace_program = NULL; + } + + bool load_kernels(const DeviceRequestedFeatures& requested_features) + { + /* Get Shader, bake and film convert kernels. + * It'll also do verification of OpenCL actually initialized. + */ + if(!OpenCLDeviceBase::load_kernels(requested_features)) { + return false; + } + + /* Try to use cached kernel. */ + thread_scoped_lock cache_locker; + path_trace_program = OpenCLCache::get_program(cpPlatform, + cdDevice, + OpenCLCache::OCL_DEV_MEGAKERNEL_PROGRAM, + cache_locker); + + if(!path_trace_program) { + /* Verify we have right opencl version. */ + if(!opencl_version_check()) + return false; + + /* Calculate md5 hash to detect changes. */ + string kernel_path = path_get("kernel"); + string kernel_md5 = path_files_md5_hash(kernel_path); + string custom_kernel_build_options = "-D__COMPILE_ONLY_MEGAKERNEL__ "; + string device_md5 = device_md5_hash(custom_kernel_build_options); + + /* Path to cached binary. */ + string clbin = string_printf("cycles_kernel_%s_%s.clbin", + device_md5.c_str(), + kernel_md5.c_str()); + clbin = path_user_get(path_join("cache", clbin)); + + /* Path to preprocessed source for debugging. */ + string clsrc, *debug_src = NULL; + if(opencl_kernel_use_debug()) { + clsrc = string_printf("cycles_kernel_%s_%s.cl", + device_md5.c_str(), + kernel_md5.c_str()); + clsrc = path_user_get(path_join("cache", clsrc)); + debug_src = &clsrc; + } + + /* If exists already, try use it. */ + if(path_exists(clbin) && load_binary(kernel_path, + clbin, + custom_kernel_build_options, + &path_trace_program, + debug_src)) { + /* Kernel loaded from binary, nothing to do. */ + } + else { + string init_kernel_source = "#include \"kernel.cl\" // " + + kernel_md5 + "\n"; + /* If does not exist or loading binary failed, compile kernel. */ + if(!compile_kernel(kernel_path, + init_kernel_source, + custom_kernel_build_options, + &path_trace_program, + debug_src)) + { + return false; + } + /* Save binary for reuse. */ + if(!save_binary(&path_trace_program, clbin)) { + return false; + } + } + /* Cache the program. */ + OpenCLCache::store_program(cpPlatform, + cdDevice, + path_trace_program, + OpenCLCache::OCL_DEV_MEGAKERNEL_PROGRAM, + cache_locker); + } + + /* Find kernels. */ + ckPathTraceKernel = clCreateKernel(path_trace_program, + "kernel_ocl_path_trace", + &ciErr); + if(opencl_error(ciErr)) + return false; + return true; + } + + ~OpenCLDeviceMegaKernel() + { + task_pool.stop(); + release_kernel_safe(ckPathTraceKernel); + release_program_safe(path_trace_program); + } + + void path_trace(RenderTile& rtile, int sample) + { + /* Cast arguments to cl types. */ + cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer); + cl_mem d_buffer = CL_MEM_PTR(rtile.buffer); + cl_mem d_rng_state = CL_MEM_PTR(rtile.rng_state); + cl_int d_x = rtile.x; + cl_int d_y = rtile.y; + cl_int d_w = rtile.w; + cl_int d_h = rtile.h; + cl_int d_offset = rtile.offset; + cl_int d_stride = rtile.stride; + + /* Sample arguments. */ + cl_int d_sample = sample; + cl_uint narg = 0; + + /* TODO : Make the kernel launch similar to Cuda. */ + KERNEL_APPEND_ARG(ckPathTraceKernel, d_data); + KERNEL_APPEND_ARG(ckPathTraceKernel, d_buffer); + KERNEL_APPEND_ARG(ckPathTraceKernel, d_rng_state); + +#define KERNEL_TEX(type, ttype, name) \ + set_kernel_arg_mem(ckPathTraceKernel, &narg, #name); +#include "kernel_textures.h" +#undef KERNEL_TEX + + KERNEL_APPEND_ARG(ckPathTraceKernel, d_sample); + KERNEL_APPEND_ARG(ckPathTraceKernel, d_x); + KERNEL_APPEND_ARG(ckPathTraceKernel, d_y); + KERNEL_APPEND_ARG(ckPathTraceKernel, d_w); + KERNEL_APPEND_ARG(ckPathTraceKernel, d_h); + KERNEL_APPEND_ARG(ckPathTraceKernel, d_offset); + KERNEL_APPEND_ARG(ckPathTraceKernel, d_stride); + + enqueue_kernel(ckPathTraceKernel, d_w, d_h); + } + void thread_run(DeviceTask *task) { if(task->type == DeviceTask::FILM_CONVERT) { @@ -1064,8 +1394,7 @@ public: } else if(task->type == DeviceTask::PATH_TRACE) { RenderTile tile; - - /* keep rendering tiles until done */ + /* Keep rendering tiles until done. */ while(task->acquire_tile(this, tile)) { int start_sample = tile.start_sample; int end_sample = tile.start_sample + tile.num_samples; @@ -1083,47 +1412,1908 @@ public: task->update_progress(&tile); } + /* Complete kernel execution before release tile */ + /* This helps in multi-device render; + * The device that reaches the critical-section function + * release_tile waits (stalling other devices from entering + * release_tile) for all kernels to complete. If device1 (a + * slow-render device) reaches release_tile first then it would + * stall device2 (a fast-render device) from proceeding to render + * next tile. + */ + clFinish(cqCommandQueue); + task->release_tile(tile); } } } +}; - class OpenCLDeviceTask : public DeviceTask { - public: - OpenCLDeviceTask(OpenCLDevice *device, DeviceTask& task) - : DeviceTask(task) +/* TODO(sergey): This is to keep tile split on OpenCL level working + * for now, since withotu this viewport render does not work as it + * should. + * + * Ideally it'll be done on the higher level, but we need to get ready + * for merge rather soon, so let's keep split logic private here in + * the file. + */ +class SplitRenderTile : public RenderTile { +public: + SplitRenderTile() + : RenderTile(), + buffer_offset_x(0), + buffer_offset_y(0), + rng_state_offset_x(0), + rng_state_offset_y(0), + buffer_rng_state_stride(0) {} + + explicit SplitRenderTile(RenderTile& tile) + : RenderTile(), + buffer_offset_x(0), + buffer_offset_y(0), + rng_state_offset_x(0), + rng_state_offset_y(0), + buffer_rng_state_stride(0) + { + x = tile.x; + y = tile.y; + w = tile.w; + h = tile.h; + start_sample = tile.start_sample; + num_samples = tile.num_samples; + sample = tile.sample; + resolution = tile.resolution; + offset = tile.offset; + stride = tile.stride; + buffer = tile.buffer; + rng_state = tile.rng_state; + buffers = tile.buffers; + } + + /* Split kernel is device global memory constained; + * hence split kernel cant render big tile size's in + * one go. If the user sets a big tile size (big tile size + * is a term relative to the available device global memory), + * we split the tile further and then call path_trace on + * each of those split tiles. The following variables declared, + * assist in achieving that purpose + */ + int buffer_offset_x; + int buffer_offset_y; + int rng_state_offset_x; + int rng_state_offset_y; + int buffer_rng_state_stride; +}; + +/* OpenCLDeviceSplitKernel's declaration/definition. */ +class OpenCLDeviceSplitKernel : public OpenCLDeviceBase +{ +public: + /* Kernel declaration. */ + cl_kernel ckPathTraceKernel_data_init; + cl_kernel ckPathTraceKernel_scene_intersect; + cl_kernel ckPathTraceKernel_lamp_emission; + cl_kernel ckPathTraceKernel_queue_enqueue; + cl_kernel ckPathTraceKernel_background_buffer_update; + cl_kernel ckPathTraceKernel_shader_lighting; + cl_kernel ckPathTraceKernel_holdout_emission_blurring_pathtermination_ao; + cl_kernel ckPathTraceKernel_direct_lighting; + cl_kernel ckPathTraceKernel_shadow_blocked_direct_lighting; + cl_kernel ckPathTraceKernel_setup_next_iteration; + cl_kernel ckPathTraceKernel_sum_all_radiance; + + /* cl_program declaration. */ + cl_program data_init_program; + cl_program scene_intersect_program; + cl_program lamp_emission_program; + cl_program queue_enqueue_program; + cl_program background_buffer_update_program; + cl_program shader_eval_program; + cl_program holdout_emission_blurring_termination_ao_program; + cl_program direct_lighting_program; + cl_program shadow_blocked_program; + cl_program next_iteration_setup_program; + cl_program sum_all_radiance_program; + + /* Global memory variables [porting]; These memory is used for + * co-operation between different kernels; Data written by one + * kernel will be avaible to another kernel via this global + * memory. + */ + cl_mem rng_coop; + cl_mem throughput_coop; + cl_mem L_transparent_coop; + cl_mem PathRadiance_coop; + cl_mem Ray_coop; + cl_mem PathState_coop; + cl_mem Intersection_coop; + cl_mem kgbuffer; /* KernelGlobals buffer. */ + + /* Global buffers for ShaderData. */ + cl_mem sd; /* ShaderData used in the main path-iteration loop. */ + cl_mem sd_DL_shadow; /* ShaderData used in Direct Lighting and + * shadow_blocked kernel. + */ + + /* Global buffers of each member of ShaderData. */ + cl_mem P_sd; + cl_mem P_sd_DL_shadow; + cl_mem N_sd; + cl_mem N_sd_DL_shadow; + cl_mem Ng_sd; + cl_mem Ng_sd_DL_shadow; + cl_mem I_sd; + cl_mem I_sd_DL_shadow; + cl_mem shader_sd; + cl_mem shader_sd_DL_shadow; + cl_mem flag_sd; + cl_mem flag_sd_DL_shadow; + cl_mem prim_sd; + cl_mem prim_sd_DL_shadow; + cl_mem type_sd; + cl_mem type_sd_DL_shadow; + cl_mem u_sd; + cl_mem u_sd_DL_shadow; + cl_mem v_sd; + cl_mem v_sd_DL_shadow; + cl_mem object_sd; + cl_mem object_sd_DL_shadow; + cl_mem time_sd; + cl_mem time_sd_DL_shadow; + cl_mem ray_length_sd; + cl_mem ray_length_sd_DL_shadow; + cl_mem ray_depth_sd; + cl_mem ray_depth_sd_DL_shadow; + cl_mem transparent_depth_sd; + cl_mem transparent_depth_sd_DL_shadow; +#ifdef __RAY_DIFFERENTIALS__ + cl_mem dP_sd, dI_sd; + cl_mem dP_sd_DL_shadow, dI_sd_DL_shadow; + cl_mem du_sd, dv_sd; + cl_mem du_sd_DL_shadow, dv_sd_DL_shadow; +#endif +#ifdef __DPDU__ + cl_mem dPdu_sd, dPdv_sd; + cl_mem dPdu_sd_DL_shadow, dPdv_sd_DL_shadow; +#endif + cl_mem closure_sd; + cl_mem closure_sd_DL_shadow; + cl_mem num_closure_sd; + cl_mem num_closure_sd_DL_shadow; + cl_mem randb_closure_sd; + cl_mem randb_closure_sd_DL_shadow; + cl_mem ray_P_sd; + cl_mem ray_P_sd_DL_shadow; + cl_mem ray_dP_sd; + cl_mem ray_dP_sd_DL_shadow; + + /* Global memory required for shadow blocked and accum_radiance. */ + cl_mem BSDFEval_coop; + cl_mem ISLamp_coop; + cl_mem LightRay_coop; + cl_mem AOAlpha_coop; + cl_mem AOBSDF_coop; + cl_mem AOLightRay_coop; + cl_mem Intersection_coop_AO; + cl_mem Intersection_coop_DL; + +#ifdef WITH_CYCLES_DEBUG + /* DebugData memory */ + cl_mem debugdata_coop; +#endif + + /* Global state array that tracks ray state. */ + cl_mem ray_state; + + /* Per sample buffers. */ + cl_mem per_sample_output_buffers; + + /* Denotes which sample each ray is being processed for. */ + cl_mem work_array; + + /* Queue */ + cl_mem Queue_data; /* Array of size queuesize * num_queues * sizeof(int). */ + cl_mem Queue_index; /* Array of size num_queues * sizeof(int); + * Tracks the size of each queue. + */ + + /* Flag to make sceneintersect and lampemission kernel use queues. */ + cl_mem use_queues_flag; + + /* Required-memory size. */ + size_t throughput_size; + size_t L_transparent_size; + size_t rayState_size; + size_t hostRayState_size; + size_t work_element_size; + size_t ISLamp_size; + + /* Sizes of memory required for shadow blocked function. */ + size_t AOAlpha_size; + size_t AOBSDF_size; + + /* Amount of memory in output buffer associated with one pixel/thread. */ + size_t per_thread_output_buffer_size; + + /* Total allocatable available device memory. */ + size_t total_allocatable_memory; + + /* host version of ray_state; Used in checking host path-iteration + * termination. + */ + char *hostRayStateArray; + + /* Number of path-iterations to be done in one shot. */ + unsigned int PathIteration_times; + +#ifdef __WORK_STEALING__ + /* Work pool with respect to each work group. */ + cl_mem work_pool_wgs; + + /* Denotes the maximum work groups possible w.r.t. current tile size. */ + unsigned int max_work_groups; +#endif + + /* clos_max value for which the kernels have been loaded currently. */ + int current_clos_max; + + /* Marked True in constructor and marked false at the end of path_trace(). */ + bool first_tile; + + OpenCLDeviceSplitKernel(DeviceInfo& info, Stats &stats, bool background_) + : OpenCLDeviceBase(info, stats, background_) + { + + info.use_split_kernel = true; + background = background_; + + /* Initialize kernels. */ + ckPathTraceKernel_data_init = NULL; + ckPathTraceKernel_scene_intersect = NULL; + ckPathTraceKernel_lamp_emission = NULL; + ckPathTraceKernel_background_buffer_update = NULL; + ckPathTraceKernel_shader_lighting = NULL; + ckPathTraceKernel_holdout_emission_blurring_pathtermination_ao = NULL; + ckPathTraceKernel_direct_lighting = NULL; + ckPathTraceKernel_shadow_blocked_direct_lighting = NULL; + ckPathTraceKernel_setup_next_iteration = NULL; + ckPathTraceKernel_sum_all_radiance = NULL; + ckPathTraceKernel_queue_enqueue = NULL; + + /* Initialize program. */ + data_init_program = NULL; + scene_intersect_program = NULL; + lamp_emission_program = NULL; + queue_enqueue_program = NULL; + background_buffer_update_program = NULL; + shader_eval_program = NULL; + holdout_emission_blurring_termination_ao_program = NULL; + direct_lighting_program = NULL; + shadow_blocked_program = NULL; + next_iteration_setup_program = NULL; + sum_all_radiance_program = NULL; + + /* Initialize cl_mem variables. */ + kgbuffer = NULL; + sd = NULL; + sd_DL_shadow = NULL; + + P_sd = NULL; + P_sd_DL_shadow = NULL; + N_sd = NULL; + N_sd_DL_shadow = NULL; + Ng_sd = NULL; + Ng_sd_DL_shadow = NULL; + I_sd = NULL; + I_sd_DL_shadow = NULL; + shader_sd = NULL; + shader_sd_DL_shadow = NULL; + flag_sd = NULL; + flag_sd_DL_shadow = NULL; + prim_sd = NULL; + prim_sd_DL_shadow = NULL; + type_sd = NULL; + type_sd_DL_shadow = NULL; + u_sd = NULL; + u_sd_DL_shadow = NULL; + v_sd = NULL; + v_sd_DL_shadow = NULL; + object_sd = NULL; + object_sd_DL_shadow = NULL; + time_sd = NULL; + time_sd_DL_shadow = NULL; + ray_length_sd = NULL; + ray_length_sd_DL_shadow = NULL; + ray_depth_sd = NULL; + ray_depth_sd_DL_shadow = NULL; + transparent_depth_sd = NULL; + transparent_depth_sd_DL_shadow = NULL; +#ifdef __RAY_DIFFERENTIALS__ + dP_sd = NULL; + dI_sd = NULL; + dP_sd_DL_shadow = NULL; + dI_sd_DL_shadow = NULL; + du_sd = NULL; + dv_sd = NULL; + du_sd_DL_shadow = NULL; + dv_sd_DL_shadow = NULL; +#endif +#ifdef __DPDU__ + dPdu_sd = NULL; + dPdv_sd = NULL; + dPdu_sd_DL_shadow = NULL; + dPdv_sd_DL_shadow = NULL; +#endif + closure_sd = NULL; + closure_sd_DL_shadow = NULL; + num_closure_sd = NULL; + num_closure_sd_DL_shadow = NULL; + randb_closure_sd = NULL; + randb_closure_sd_DL_shadow = NULL; + ray_P_sd = NULL; + ray_P_sd_DL_shadow = NULL; + ray_dP_sd = NULL; + ray_dP_sd_DL_shadow = NULL; + + rng_coop = NULL; + throughput_coop = NULL; + L_transparent_coop = NULL; + PathRadiance_coop = NULL; + Ray_coop = NULL; + PathState_coop = NULL; + Intersection_coop = NULL; + ray_state = NULL; + + AOAlpha_coop = NULL; + AOBSDF_coop = NULL; + AOLightRay_coop = NULL; + BSDFEval_coop = NULL; + ISLamp_coop = NULL; + LightRay_coop = NULL; + Intersection_coop_AO = NULL; + Intersection_coop_DL = NULL; + +#ifdef WITH_CYCLES_DEBUG + debugdata_coop = NULL; +#endif + + work_array = NULL; + + /* Queue. */ + Queue_data = NULL; + Queue_index = NULL; + use_queues_flag = NULL; + + per_sample_output_buffers = NULL; + + /* Initialize required memory size. */ + throughput_size = sizeof(float3); + L_transparent_size = sizeof(float); + rayState_size = sizeof(char); + hostRayState_size = sizeof(char); + work_element_size = sizeof(unsigned int); + ISLamp_size = sizeof(int); + + /* Initialize sizes of memory required for shadow blocked function. */ + AOAlpha_size = sizeof(float3); + AOBSDF_size = sizeof(float3); + + per_thread_output_buffer_size = 0; + hostRayStateArray = NULL; + PathIteration_times = PATH_ITER_INC_FACTOR; +#ifdef __WORK_STEALING__ + work_pool_wgs = NULL; + max_work_groups = 0; +#endif + current_clos_max = -1; + first_tile = true; + + /* Get device's maximum memory that can be allocated. */ + ciErr = clGetDeviceInfo(cdDevice, + CL_DEVICE_MAX_MEM_ALLOC_SIZE, + sizeof(size_t), + &total_allocatable_memory, + NULL); + assert(ciErr == CL_SUCCESS); + if(platform_name == "AMD Accelerated Parallel Processing") { + /* This value is tweak-able; AMD platform does not seem to + * give maximum performance when all of CL_DEVICE_MAX_MEM_ALLOC_SIZE + * is considered for further computation. + */ + total_allocatable_memory /= 2; + } + } + + /* TODO(sergey): Seems really close to load_kernel(), + * could it be de-duplicated? + */ + bool load_split_kernel(string kernel_path, + string kernel_init_source, + string clbin, + string custom_kernel_build_options, + cl_program *program) + { + if(!opencl_version_check()) + return false; + + clbin = path_user_get(path_join("cache", clbin)); + + /* Path to preprocessed source for debugging. */ + string *debug_src = NULL; + + /* If exists already, try use it. */ + if(path_exists(clbin) && load_binary(kernel_path, + clbin, + custom_kernel_build_options, + program, + debug_src)) { + /* Kernel loaded from binary. */ + } + else { + /* If does not exist or loading binary failed, compile kernel. */ + if(!compile_kernel(kernel_path, + kernel_init_source, + custom_kernel_build_options, + program)) + { + return false; + } + /* Save binary for reuse. */ + if(!save_binary(program, clbin)) { + return false; + } + } + return true; + } + + /* Split kernel utility functions. */ + size_t get_tex_size(const char *tex_name) + { + cl_mem ptr; + size_t ret_size = 0; + MemMap::iterator i = mem_map.find(tex_name); + if(i != mem_map.end()) { + ptr = CL_MEM_PTR(i->second); + ciErr = clGetMemObjectInfo(ptr, + CL_MEM_SIZE, + sizeof(ret_size), + &ret_size, + NULL); + assert(ciErr == CL_SUCCESS); + } + return ret_size; + } + + size_t get_shader_closure_size(int max_closure) + { + return (sizeof(ShaderClosure)* max_closure); + } + + size_t get_shader_data_size(size_t shader_closure_size) + { + /* ShaderData size without accounting for ShaderClosure array. */ + size_t shader_data_size = + sizeof(ShaderData) - (sizeof(ShaderClosure) * MAX_CLOSURE); + return (shader_data_size + shader_closure_size); + } + + /* Returns size of KernelGlobals structure associated with OpenCL. */ + size_t get_KernelGlobals_size() + { + /* Copy dummy KernelGlobals related to OpenCL from kernel_globals.h to + * fetch its size. + */ + typedef struct KernelGlobals { + ccl_constant KernelData *data; +#define KERNEL_TEX(type, ttype, name) \ + ccl_global type *name; +#include "kernel_textures.h" +#undef KERNEL_TEX + } KernelGlobals; + + return sizeof(KernelGlobals); + } + + /* Returns size of Structure of arrays implementation of. */ + size_t get_shaderdata_soa_size() + { + size_t shader_soa_size = 0; + +#define SD_VAR(type, what) \ + shader_soa_size += sizeof(void *); +#define SD_CLOSURE_VAR(type, what, max_closure) + shader_soa_size += sizeof(void *); + #include "kernel_shaderdata_vars.h" +#undef SD_VAR +#undef SD_CLOSURE_VAR + + return shader_soa_size; + } + + bool load_kernels(const DeviceRequestedFeatures& requested_features) + { + /* If it is an interactive render; we ceil clos_max value to a multiple + * of 5 in order to limit re-compilations. + */ + /* TODO(sergey): Decision about this should be done on higher levels. */ + int max_closure = requested_features.max_closure; + if(!background) { + assert((max_closure != 0) && "clos_max value is 0" ); + max_closure = (((max_closure - 1) / 5) + 1) * 5; + /* clos_max value shouldn't be greater than MAX_CLOSURE. */ + max_closure = (max_closure > MAX_CLOSURE) ? MAX_CLOSURE : max_closure; + if(current_clos_max == max_closure) { + /* Present kernels have been created with the same closure count + * build option. + */ + return true; + } + } + /* Get Shader, bake and film_convert kernels. + * It'll also do verification of OpenCL actually initialized. + */ + if(!OpenCLDeviceBase::load_kernels(requested_features)) { + return false; + } + + string svm_build_options = ""; + string max_closure_build_option = ""; + string compute_device_type_build_option = ""; + + /* Set svm_build_options. */ + svm_build_options += " -D__NODES_MAX_GROUP__=" + + string_printf("%d", requested_features.max_nodes_group); + svm_build_options += " -D__NODES_FEATURES__=" + + string_printf("%d", requested_features.nodes_features); + + /* Set max closure build option. */ + max_closure_build_option += string_printf("-D__MAX_CLOSURE__=%d ", + max_closure); + + /* Set compute device build option. */ + cl_device_type device_type; + ciErr = clGetDeviceInfo(cdDevice, + CL_DEVICE_TYPE, + sizeof(cl_device_type), + &device_type, + NULL); + assert(ciErr == CL_SUCCESS); + if(device_type == CL_DEVICE_TYPE_GPU) { + compute_device_type_build_option = "-D__COMPUTE_DEVICE_GPU__ "; + } + + string kernel_path = path_get("kernel"); + string kernel_md5 = path_files_md5_hash(kernel_path); + string device_md5; + string custom_kernel_build_options; + string kernel_init_source; + string clbin; + + string common_custom_build_options = ""; + common_custom_build_options += "-D__SPLIT_KERNEL__ "; + common_custom_build_options += max_closure_build_option;; +#ifdef __WORK_STEALING__ + common_custom_build_options += "-D__WORK_STEALING__ "; +#endif + +#define LOAD_KERNEL(program, name) \ + do { \ + kernel_init_source = "#include \"kernel_" name ".cl\" // " + \ + kernel_md5 + "\n"; \ + custom_kernel_build_options = common_custom_build_options; \ + device_md5 = device_md5_hash(custom_kernel_build_options); \ + clbin = string_printf("cycles_kernel_%s_%s_" name ".clbin", \ + device_md5.c_str(), kernel_md5.c_str()); \ + if(!load_split_kernel(kernel_path, kernel_init_source, clbin, \ + custom_kernel_build_options, &program)) \ + { \ + return false; \ + } \ + } while(false) + + /* TODO(sergey): If names are unified we can save some more bits of + * code here. + */ + LOAD_KERNEL(data_init_program, "data_init"); + LOAD_KERNEL(scene_intersect_program, "scene_intersect"); + LOAD_KERNEL(lamp_emission_program, "lamp_emission"); + LOAD_KERNEL(queue_enqueue_program, "queue_enqueue"); + LOAD_KERNEL(background_buffer_update_program, "background_buffer_update"); + LOAD_KERNEL(shader_eval_program, "shader_eval"); + LOAD_KERNEL(holdout_emission_blurring_termination_ao_program, + "holdout_emission_blurring_pathtermination_ao"); + LOAD_KERNEL(direct_lighting_program, "direct_lighting"); + LOAD_KERNEL(shadow_blocked_program, "shadow_blocked"); + LOAD_KERNEL(next_iteration_setup_program, "next_iteration_setup"); + LOAD_KERNEL(sum_all_radiance_program, "sum_all_radiance"); + +#undef LOAD_KERNEL + +#define GLUE(a, b) a ## b +#define FIND_KERNEL(kernel, program, function) \ + do { \ + GLUE(ckPathTraceKernel_, kernel) = \ + clCreateKernel(GLUE(program, _program), \ + "kernel_ocl_path_trace_" function, &ciErr); \ + if(opencl_error(ciErr)) { \ + return false; \ + } \ + } while(false) + + FIND_KERNEL(data_init, data_init, "data_initialization"); + FIND_KERNEL(scene_intersect, scene_intersect, "scene_intersect"); + FIND_KERNEL(lamp_emission, lamp_emission, "lamp_emission"); + FIND_KERNEL(queue_enqueue, queue_enqueue, "queue_enqueue"); + FIND_KERNEL(background_buffer_update, background_buffer_update, "background_buffer_update"); + FIND_KERNEL(shader_lighting, shader_eval, "shader_evaluation"); + FIND_KERNEL(holdout_emission_blurring_pathtermination_ao, + holdout_emission_blurring_termination_ao, + "holdout_emission_blurring_pathtermination_ao"); + FIND_KERNEL(direct_lighting, direct_lighting, "direct_lighting"); + FIND_KERNEL(shadow_blocked_direct_lighting, shadow_blocked, "shadow_blocked_direct_lighting"); + FIND_KERNEL(setup_next_iteration, next_iteration_setup, "setup_next_iteration"); + FIND_KERNEL(sum_all_radiance, sum_all_radiance, "sum_all_radiance"); +#undef FIND_KERNEL +#undef GLUE + + current_clos_max = max_closure; + + return true; + } + + ~OpenCLDeviceSplitKernel() + { + task_pool.stop(); + + /* Release kernels */ + release_kernel_safe(ckPathTraceKernel_data_init); + release_kernel_safe(ckPathTraceKernel_scene_intersect); + release_kernel_safe(ckPathTraceKernel_lamp_emission); + release_kernel_safe(ckPathTraceKernel_queue_enqueue); + release_kernel_safe(ckPathTraceKernel_background_buffer_update); + release_kernel_safe(ckPathTraceKernel_shader_lighting); + release_kernel_safe(ckPathTraceKernel_holdout_emission_blurring_pathtermination_ao); + release_kernel_safe(ckPathTraceKernel_direct_lighting); + release_kernel_safe(ckPathTraceKernel_shadow_blocked_direct_lighting); + release_kernel_safe(ckPathTraceKernel_setup_next_iteration); + release_kernel_safe(ckPathTraceKernel_sum_all_radiance); + + /* Release global memory */ + release_mem_object_safe(P_sd); + release_mem_object_safe(P_sd_DL_shadow); + release_mem_object_safe(N_sd); + release_mem_object_safe(N_sd_DL_shadow); + release_mem_object_safe(Ng_sd); + release_mem_object_safe(Ng_sd_DL_shadow); + release_mem_object_safe(I_sd); + release_mem_object_safe(I_sd_DL_shadow); + release_mem_object_safe(shader_sd); + release_mem_object_safe(shader_sd_DL_shadow); + release_mem_object_safe(flag_sd); + release_mem_object_safe(flag_sd_DL_shadow); + release_mem_object_safe(prim_sd); + release_mem_object_safe(prim_sd_DL_shadow); + release_mem_object_safe(type_sd); + release_mem_object_safe(type_sd_DL_shadow); + release_mem_object_safe(u_sd); + release_mem_object_safe(u_sd_DL_shadow); + release_mem_object_safe(v_sd); + release_mem_object_safe(v_sd_DL_shadow); + release_mem_object_safe(object_sd); + release_mem_object_safe(object_sd_DL_shadow); + release_mem_object_safe(time_sd); + release_mem_object_safe(time_sd_DL_shadow); + release_mem_object_safe(ray_length_sd); + release_mem_object_safe(ray_length_sd_DL_shadow); + release_mem_object_safe(ray_depth_sd); + release_mem_object_safe(ray_depth_sd_DL_shadow); + release_mem_object_safe(transparent_depth_sd); + release_mem_object_safe(transparent_depth_sd_DL_shadow); +#ifdef __RAY_DIFFERENTIALS__ + release_mem_object_safe(dP_sd); + release_mem_object_safe(dP_sd_DL_shadow); + release_mem_object_safe(dI_sd); + release_mem_object_safe(dI_sd_DL_shadow); + release_mem_object_safe(du_sd); + release_mem_object_safe(du_sd_DL_shadow); + release_mem_object_safe(dv_sd); + release_mem_object_safe(dv_sd_DL_shadow); +#endif +#ifdef __DPDU__ + release_mem_object_safe(dPdu_sd); + release_mem_object_safe(dPdu_sd_DL_shadow); + release_mem_object_safe(dPdv_sd); + release_mem_object_safe(dPdv_sd_DL_shadow); +#endif + release_mem_object_safe(closure_sd); + release_mem_object_safe(closure_sd_DL_shadow); + release_mem_object_safe(num_closure_sd); + release_mem_object_safe(num_closure_sd_DL_shadow); + release_mem_object_safe(randb_closure_sd); + release_mem_object_safe(randb_closure_sd_DL_shadow); + release_mem_object_safe(ray_P_sd); + release_mem_object_safe(ray_P_sd_DL_shadow); + release_mem_object_safe(ray_dP_sd); + release_mem_object_safe(ray_dP_sd_DL_shadow); + release_mem_object_safe(rng_coop); + release_mem_object_safe(throughput_coop); + release_mem_object_safe(L_transparent_coop); + release_mem_object_safe(PathRadiance_coop); + release_mem_object_safe(Ray_coop); + release_mem_object_safe(PathState_coop); + release_mem_object_safe(Intersection_coop); + release_mem_object_safe(kgbuffer); + release_mem_object_safe(sd); + release_mem_object_safe(sd_DL_shadow); + release_mem_object_safe(ray_state); + release_mem_object_safe(AOAlpha_coop); + release_mem_object_safe(AOBSDF_coop); + release_mem_object_safe(AOLightRay_coop); + release_mem_object_safe(BSDFEval_coop); + release_mem_object_safe(ISLamp_coop); + release_mem_object_safe(LightRay_coop); + release_mem_object_safe(Intersection_coop_AO); + release_mem_object_safe(Intersection_coop_DL); +#ifdef WITH_CYCLES_DEBUG + release_mem_object_safe(debugdata_coop); +#endif + release_mem_object_safe(use_queues_flag); + release_mem_object_safe(Queue_data); + release_mem_object_safe(Queue_index); + release_mem_object_safe(work_array); +#ifdef __WORK_STEALING__ + release_mem_object_safe(work_pool_wgs); +#endif + release_mem_object_safe(per_sample_output_buffers); + + /* Release programs */ + release_program_safe(data_init_program); + release_program_safe(scene_intersect_program); + release_program_safe(lamp_emission_program); + release_program_safe(queue_enqueue_program); + release_program_safe(background_buffer_update_program); + release_program_safe(shader_eval_program); + release_program_safe(holdout_emission_blurring_termination_ao_program); + release_program_safe(direct_lighting_program); + release_program_safe(shadow_blocked_program); + release_program_safe(next_iteration_setup_program); + release_program_safe(sum_all_radiance_program); + + if(hostRayStateArray != NULL) { + free(hostRayStateArray); + } + } + + void path_trace(SplitRenderTile& rtile, int2 max_render_feasible_tile_size) + { + /* cast arguments to cl types */ + cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer); + cl_mem d_buffer = CL_MEM_PTR(rtile.buffer); + cl_mem d_rng_state = CL_MEM_PTR(rtile.rng_state); + cl_int d_x = rtile.x; + cl_int d_y = rtile.y; + cl_int d_w = rtile.w; + cl_int d_h = rtile.h; + cl_int d_offset = rtile.offset; + cl_int d_stride = rtile.stride; + + /* Make sure that set render feasible tile size is a multiple of local + * work size dimensions. + */ + assert(max_render_feasible_tile_size.x % SPLIT_KERNEL_LOCAL_SIZE_X == 0); + assert(max_render_feasible_tile_size.y % SPLIT_KERNEL_LOCAL_SIZE_Y == 0); + + /* ray_state and hostRayStateArray should be of same size. */ + assert(hostRayState_size == rayState_size); + assert(rayState_size == 1); + + size_t global_size[2]; + size_t local_size[2] = {SPLIT_KERNEL_LOCAL_SIZE_X, + SPLIT_KERNEL_LOCAL_SIZE_Y}; + + /* Set the range of samples to be processed for every ray in + * path-regeneration logic. + */ + cl_int start_sample = rtile.start_sample; + cl_int end_sample = rtile.start_sample + rtile.num_samples; + cl_int num_samples = rtile.num_samples; + +#ifdef __WORK_STEALING__ + global_size[0] = (((d_w - 1) / local_size[0]) + 1) * local_size[0]; + global_size[1] = (((d_h - 1) / local_size[1]) + 1) * local_size[1]; + unsigned int num_parallel_samples = 1; +#else + global_size[1] = (((d_h - 1) / local_size[1]) + 1) * local_size[1]; + unsigned int num_threads = max_render_feasible_tile_size.x * + max_render_feasible_tile_size.y; + unsigned int num_tile_columns_possible = num_threads / global_size[1]; + /* Estimate number of parallel samples that can be + * processed in parallel. + */ + unsigned int num_parallel_samples = min(num_tile_columns_possible / d_w, + rtile.num_samples); + /* Wavefront size in AMD is 64. + * TODO(sergey): What about other platforms? + */ + if(num_parallel_samples >= 64) { + /* TODO(sergey): Could use generic round-up here. */ + num_parallel_samples = (num_parallel_samples / 64) * 64 + } + assert(num_parallel_samples != 0); + + global_size[0] = d_w * num_parallel_samples; +#endif /* __WORK_STEALING__ */ + + assert(global_size[0] * global_size[1] <= + max_render_feasible_tile_size.x * max_render_feasible_tile_size.y); + + /* Allocate all required global memory once. */ + if(first_tile) { + size_t num_global_elements = max_render_feasible_tile_size.x * + max_render_feasible_tile_size.y; + /* TODO(sergey): This will actually over-allocate if + * particular kernel does not support multiclosure. + */ + size_t ShaderClosure_size = get_shader_closure_size(current_clos_max); + +#ifdef __WORK_STEALING__ + /* Calculate max groups */ + size_t max_global_size[2]; + size_t tile_x = max_render_feasible_tile_size.x; + size_t tile_y = max_render_feasible_tile_size.y; + max_global_size[0] = (((tile_x - 1) / local_size[0]) + 1) * local_size[0]; + max_global_size[1] = (((tile_y - 1) / local_size[1]) + 1) * local_size[1]; + max_work_groups = (max_global_size[0] * max_global_size[1]) / + (local_size[0] * local_size[1]); + /* Allocate work_pool_wgs memory. */ + work_pool_wgs = mem_alloc(max_work_groups * sizeof(unsigned int)); +#endif /* __WORK_STEALING__ */ + + /* Allocate queue_index memory only once. */ + Queue_index = mem_alloc(NUM_QUEUES * sizeof(int)); + use_queues_flag = mem_alloc(sizeof(char)); + kgbuffer = mem_alloc(get_KernelGlobals_size()); + + /* Create global buffers for ShaderData. */ + sd = mem_alloc(get_shaderdata_soa_size()); + sd_DL_shadow = mem_alloc(get_shaderdata_soa_size()); + P_sd = mem_alloc(num_global_elements * sizeof(float3)); + P_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3)); + N_sd = mem_alloc(num_global_elements * sizeof(float3)); + N_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3)); + Ng_sd = mem_alloc(num_global_elements * sizeof(float3)); + Ng_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3)); + I_sd = mem_alloc(num_global_elements * sizeof(float3)); + I_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3)); + shader_sd = mem_alloc(num_global_elements * sizeof(int)); + shader_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int)); + flag_sd = mem_alloc(num_global_elements * sizeof(int)); + flag_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int)); + prim_sd = mem_alloc(num_global_elements * sizeof(int)); + prim_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int)); + type_sd = mem_alloc(num_global_elements * sizeof(int)); + type_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int)); + u_sd = mem_alloc(num_global_elements * sizeof(float)); + u_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float)); + v_sd = mem_alloc(num_global_elements * sizeof(float)); + v_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float)); + object_sd = mem_alloc(num_global_elements * sizeof(int)); + object_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int)); + time_sd = mem_alloc(num_global_elements * sizeof(float)); + time_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float)); + ray_length_sd = mem_alloc(num_global_elements * sizeof(float)); + ray_length_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float)); + ray_depth_sd = mem_alloc(num_global_elements * sizeof(int)); + ray_depth_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int)); + transparent_depth_sd = mem_alloc(num_global_elements * sizeof(int)); + transparent_depth_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int)); + +#ifdef __RAY_DIFFERENTIALS__ + dP_sd = mem_alloc(num_global_elements * sizeof(differential3)); + dP_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(differential3)); + dI_sd = mem_alloc(num_global_elements * sizeof(differential3)); + dI_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(differential3)); + du_sd = mem_alloc(num_global_elements * sizeof(differential)); + du_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(differential)); + dv_sd = mem_alloc(num_global_elements * sizeof(differential)); + dv_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(differential)); +#endif + +#ifdef __DPDU__ + dPdu_sd = mem_alloc(num_global_elements * sizeof(float3)); + dPdu_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3)); + dPdv_sd = mem_alloc(num_global_elements * sizeof(float3)); + dPdv_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3)); +#endif + closure_sd = mem_alloc(num_global_elements * ShaderClosure_size); + closure_sd_DL_shadow = mem_alloc(num_global_elements * 2 * ShaderClosure_size); + num_closure_sd = mem_alloc(num_global_elements * sizeof(int)); + num_closure_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int)); + randb_closure_sd = mem_alloc(num_global_elements * sizeof(float)); + randb_closure_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float)); + ray_P_sd = mem_alloc(num_global_elements * sizeof(float3)); + ray_P_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3)); + ray_dP_sd = mem_alloc(num_global_elements * sizeof(differential3)); + ray_dP_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(differential3)); + + /* Creation of global memory buffers which are shared among + * the kernels. + */ + rng_coop = mem_alloc(num_global_elements * sizeof(RNG)); + throughput_coop = mem_alloc(num_global_elements * throughput_size); + L_transparent_coop = mem_alloc(num_global_elements * L_transparent_size); + PathRadiance_coop = mem_alloc(num_global_elements * sizeof(PathRadiance)); + Ray_coop = mem_alloc(num_global_elements * sizeof(Ray)); + PathState_coop = mem_alloc(num_global_elements * sizeof(PathState)); + Intersection_coop = mem_alloc(num_global_elements * sizeof(Intersection)); + AOAlpha_coop = mem_alloc(num_global_elements * AOAlpha_size); + AOBSDF_coop = mem_alloc(num_global_elements * AOBSDF_size); + AOLightRay_coop = mem_alloc(num_global_elements * sizeof(Ray)); + BSDFEval_coop = mem_alloc(num_global_elements * sizeof(BsdfEval)); + ISLamp_coop = mem_alloc(num_global_elements * ISLamp_size); + LightRay_coop = mem_alloc(num_global_elements * sizeof(Ray)); + Intersection_coop_AO = mem_alloc(num_global_elements * sizeof(Intersection)); + Intersection_coop_DL = mem_alloc(num_global_elements * sizeof(Intersection)); + +#ifdef WITH_CYCLES_DEBUG + debugdata_coop = mem_alloc(num_global_elements * sizeof(DebugData)); +#endif + + ray_state = mem_alloc(num_global_elements * rayState_size); + + hostRayStateArray = (char *)calloc(num_global_elements, hostRayState_size); + assert(hostRayStateArray != NULL && "Can't create hostRayStateArray memory"); + + Queue_data = mem_alloc(num_global_elements * (NUM_QUEUES * sizeof(int)+sizeof(int))); + work_array = mem_alloc(num_global_elements * work_element_size); + per_sample_output_buffers = mem_alloc(num_global_elements * + per_thread_output_buffer_size); + } + + cl_int dQueue_size = global_size[0] * global_size[1]; + cl_int total_num_rays = global_size[0] * global_size[1]; + + cl_uint start_arg_index = + kernel_set_args(ckPathTraceKernel_data_init, + 0, + kgbuffer, + sd, + sd_DL_shadow, + P_sd, + P_sd_DL_shadow, + N_sd, + N_sd_DL_shadow, + Ng_sd, + Ng_sd_DL_shadow, + I_sd, + I_sd_DL_shadow, + shader_sd, + shader_sd_DL_shadow, + flag_sd, + flag_sd_DL_shadow, + prim_sd, + prim_sd_DL_shadow, + type_sd, + type_sd_DL_shadow, + u_sd, + u_sd_DL_shadow, + v_sd, + v_sd_DL_shadow, + object_sd, + object_sd_DL_shadow, + time_sd, + time_sd_DL_shadow, + ray_length_sd, + ray_length_sd_DL_shadow, + ray_depth_sd, + ray_depth_sd_DL_shadow, + transparent_depth_sd, + transparent_depth_sd_DL_shadow); + + start_arg_index += + kernel_set_args(ckPathTraceKernel_data_init, +#ifdef __RAY_DIFFERENTIALS__ + start_arg_index, + dP_sd, + dP_sd_DL_shadow, + dI_sd, + dI_sd_DL_shadow, + du_sd, + du_sd_DL_shadow, + dv_sd, + dv_sd_DL_shadow, +#endif +#ifdef __DPDU__ + dPdu_sd, + dPdu_sd_DL_shadow, + dPdv_sd, + dPdv_sd_DL_shadow, +#endif + closure_sd, + closure_sd_DL_shadow, + num_closure_sd, + num_closure_sd_DL_shadow, + randb_closure_sd, + randb_closure_sd_DL_shadow, + ray_P_sd, + ray_P_sd_DL_shadow, + ray_dP_sd, + ray_dP_sd_DL_shadow, + d_data, + per_sample_output_buffers, + d_rng_state, + rng_coop, + throughput_coop, + L_transparent_coop, + PathRadiance_coop, + Ray_coop, + PathState_coop, + ray_state); + +/* TODO(segrey): Avoid map lookup here. */ +#define KERNEL_TEX(type, ttype, name) \ + set_kernel_arg_mem(ckPathTraceKernel_data_init, &start_arg_index, #name); +#include "kernel_textures.h" +#undef KERNEL_TEX + + start_arg_index += + kernel_set_args(ckPathTraceKernel_data_init, + start_arg_index, + start_sample, + d_x, + d_y, + d_w, + d_h, + d_offset, + d_stride, + rtile.rng_state_offset_x, + rtile.rng_state_offset_y, + rtile.buffer_rng_state_stride, + Queue_data, + Queue_index, + dQueue_size, + use_queues_flag, + work_array, +#ifdef __WORK_STEALING__ + work_pool_wgs, + num_samples, +#endif +#ifdef WITH_CYCLES_DEBUG + debugdata_coop, +#endif + num_parallel_samples); + + kernel_set_args(ckPathTraceKernel_scene_intersect, + 0, + kgbuffer, + d_data, + rng_coop, + Ray_coop, + PathState_coop, + Intersection_coop, + ray_state, + d_w, + d_h, + Queue_data, + Queue_index, + dQueue_size, + use_queues_flag, +#ifdef WITH_CYCLES_DEBUG + debugdata_coop, +#endif + num_parallel_samples); + + kernel_set_args(ckPathTraceKernel_lamp_emission, + 0, + kgbuffer, + d_data, + sd, + throughput_coop, + PathRadiance_coop, + Ray_coop, + PathState_coop, + Intersection_coop, + ray_state, + d_w, + d_h, + Queue_data, + Queue_index, + dQueue_size, + use_queues_flag, + num_parallel_samples); + + kernel_set_args(ckPathTraceKernel_queue_enqueue, + 0, + Queue_data, + Queue_index, + ray_state, + dQueue_size); + + kernel_set_args(ckPathTraceKernel_background_buffer_update, + 0, + kgbuffer, + d_data, + sd, + per_sample_output_buffers, + d_rng_state, + rng_coop, + throughput_coop, + PathRadiance_coop, + Ray_coop, + PathState_coop, + L_transparent_coop, + ray_state, + d_w, + d_h, + d_x, + d_y, + d_stride, + rtile.rng_state_offset_x, + rtile.rng_state_offset_y, + rtile.buffer_rng_state_stride, + work_array, + Queue_data, + Queue_index, + dQueue_size, + end_sample, + start_sample, +#ifdef __WORK_STEALING__ + work_pool_wgs, + num_samples, +#endif +#ifdef WITH_CYCLES_DEBUG + debugdata_coop, +#endif + num_parallel_samples); + + kernel_set_args(ckPathTraceKernel_shader_lighting, + 0, + kgbuffer, + d_data, + sd, + rng_coop, + Ray_coop, + PathState_coop, + Intersection_coop, + ray_state, + Queue_data, + Queue_index, + dQueue_size); + + kernel_set_args(ckPathTraceKernel_holdout_emission_blurring_pathtermination_ao, + 0, + kgbuffer, + d_data, + sd, + per_sample_output_buffers, + rng_coop, + throughput_coop, + L_transparent_coop, + PathRadiance_coop, + PathState_coop, + Intersection_coop, + AOAlpha_coop, + AOBSDF_coop, + AOLightRay_coop, + d_w, + d_h, + d_x, + d_y, + d_stride, + ray_state, + work_array, + Queue_data, + Queue_index, + dQueue_size, +#ifdef __WORK_STEALING__ + start_sample, +#endif + num_parallel_samples); + + kernel_set_args(ckPathTraceKernel_direct_lighting, + 0, + kgbuffer, + d_data, + sd, + sd_DL_shadow, + rng_coop, + PathState_coop, + ISLamp_coop, + LightRay_coop, + BSDFEval_coop, + ray_state, + Queue_data, + Queue_index, + dQueue_size); + + kernel_set_args(ckPathTraceKernel_shadow_blocked_direct_lighting, + 0, + kgbuffer, + d_data, + sd_DL_shadow, + PathState_coop, + LightRay_coop, + AOLightRay_coop, + Intersection_coop_AO, + Intersection_coop_DL, + ray_state, + Queue_data, + Queue_index, + dQueue_size, + total_num_rays); + + kernel_set_args(ckPathTraceKernel_setup_next_iteration, + 0, + kgbuffer, + d_data, + sd, + rng_coop, + throughput_coop, + PathRadiance_coop, + Ray_coop, + PathState_coop, + LightRay_coop, + ISLamp_coop, + BSDFEval_coop, + AOLightRay_coop, + AOBSDF_coop, + AOAlpha_coop, + ray_state, + Queue_data, + Queue_index, + dQueue_size, + use_queues_flag); + + kernel_set_args(ckPathTraceKernel_sum_all_radiance, + 0, + d_data, + d_buffer, + per_sample_output_buffers, + num_parallel_samples, + d_w, + d_h, + d_stride, + rtile.buffer_offset_x, + rtile.buffer_offset_y, + rtile.buffer_rng_state_stride, + start_sample); + + /* Macro for Enqueuing split kernels. */ +#define GLUE(a, b) a ## b +#define ENQUEUE_SPLIT_KERNEL(kernelName, globalSize, localSize) \ + opencl_assert(clEnqueueNDRangeKernel(cqCommandQueue, \ + GLUE(ckPathTraceKernel_, \ + kernelName), \ + 2, \ + NULL, \ + globalSize, \ + localSize, \ + 0, \ + NULL, \ + NULL)) + + /* Enqueue ckPathTraceKernel_data_init kernel. */ + ENQUEUE_SPLIT_KERNEL(data_init, global_size, local_size); + bool activeRaysAvailable = true; + + /* Record number of time host intervention has been made */ + unsigned int numHostIntervention = 0; + unsigned int numNextPathIterTimes = PathIteration_times; + while(activeRaysAvailable) { + /* Twice the global work size of other kernels for + * ckPathTraceKernel_shadow_blocked_direct_lighting. */ + size_t global_size_shadow_blocked[2]; + global_size_shadow_blocked[0] = global_size[0] * 2; + global_size_shadow_blocked[1] = global_size[1]; + + /* Do path-iteration in host [Enqueue Path-iteration kernels. */ + for(int PathIter = 0; PathIter < PathIteration_times; PathIter++) { + ENQUEUE_SPLIT_KERNEL(scene_intersect, global_size, local_size); + ENQUEUE_SPLIT_KERNEL(lamp_emission, global_size, local_size); + ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size); + ENQUEUE_SPLIT_KERNEL(background_buffer_update, global_size, local_size); + ENQUEUE_SPLIT_KERNEL(shader_lighting, global_size, local_size); + ENQUEUE_SPLIT_KERNEL(holdout_emission_blurring_pathtermination_ao, global_size, local_size); + ENQUEUE_SPLIT_KERNEL(direct_lighting, global_size, local_size); + ENQUEUE_SPLIT_KERNEL(shadow_blocked_direct_lighting, global_size_shadow_blocked, local_size); + ENQUEUE_SPLIT_KERNEL(setup_next_iteration, global_size, local_size); + } + + /* Read ray-state into Host memory to decide if we should exit + * path-iteration in host. + */ + ciErr = clEnqueueReadBuffer(cqCommandQueue, + ray_state, + CL_TRUE, + 0, + global_size[0] * global_size[1] * sizeof(char), + hostRayStateArray, + 0, + NULL, + NULL); + assert(ciErr == CL_SUCCESS); + + activeRaysAvailable = false; + + for(int rayStateIter = 0; + rayStateIter < global_size[0] * global_size[1]; + ++rayStateIter) + { + if(int8_t(hostRayStateArray[rayStateIter]) != RAY_INACTIVE) { + /* Not all rays are RAY_INACTIVE. */ + activeRaysAvailable = true; + break; + } + } + + if(activeRaysAvailable) { + numHostIntervention++; + PathIteration_times = PATH_ITER_INC_FACTOR; + /* Host intervention done before all rays become RAY_INACTIVE; + * Set do more initial iterations for the next tile. + */ + numNextPathIterTimes += PATH_ITER_INC_FACTOR; + } + } + + /* Execute SumALLRadiance kernel to accumulate radiance calculated in + * per_sample_output_buffers into RenderTile's output buffer. + */ + size_t sum_all_radiance_local_size[2] = {16, 16}; + size_t sum_all_radiance_global_size[2]; + sum_all_radiance_global_size[0] = + (((d_w - 1) / sum_all_radiance_local_size[0]) + 1) * + sum_all_radiance_local_size[0]; + sum_all_radiance_global_size[1] = + (((d_h - 1) / sum_all_radiance_local_size[1]) + 1) * + sum_all_radiance_local_size[1]; + ENQUEUE_SPLIT_KERNEL(sum_all_radiance, + sum_all_radiance_global_size, + sum_all_radiance_local_size); + +#undef ENQUEUE_SPLIT_KERNEL +#undef GLUE + + if(numHostIntervention == 0) { + /* This means that we are executing kernel more than required + * Must avoid this for the next sample/tile. + */ + PathIteration_times = ((numNextPathIterTimes - PATH_ITER_INC_FACTOR) <= 0) ? + PATH_ITER_INC_FACTOR : numNextPathIterTimes - PATH_ITER_INC_FACTOR; + } + else { + /* Number of path-iterations done for this tile is set as + * Initial path-iteration times for the next tile + */ + PathIteration_times = numNextPathIterTimes; + } + + first_tile = false; + } + + /* Calculates the amount of memory that has to be always + * allocated in order for the split kernel to function. + * This memory is tile/scene-property invariant (meaning, + * the value returned by this function does not depend + * on the user set tile size or scene properties. + */ + size_t get_invariable_mem_allocated() + { + size_t total_invariable_mem_allocated = 0; + size_t KernelGlobals_size = 0; + size_t ShaderData_SOA_size = 0; + + KernelGlobals_size = get_KernelGlobals_size(); + ShaderData_SOA_size = get_shaderdata_soa_size(); + + total_invariable_mem_allocated += KernelGlobals_size; /* KernelGlobals size */ + total_invariable_mem_allocated += NUM_QUEUES * sizeof(unsigned int); /* Queue index size */ + total_invariable_mem_allocated += sizeof(char); /* use_queues_flag size */ + total_invariable_mem_allocated += ShaderData_SOA_size; /* sd size */ + total_invariable_mem_allocated += ShaderData_SOA_size; /* sd_DL_shadow size */ + + return total_invariable_mem_allocated; + } + + /* Calculate the memory that has-to-be/has-been allocated for + * the split kernel to function. + */ + size_t get_tile_specific_mem_allocated(const int2 tile_size) + { + size_t tile_specific_mem_allocated = 0; + + /* Get required tile info */ + unsigned int user_set_tile_w = tile_size.x; + unsigned int user_set_tile_h = tile_size.y; + +#ifdef __WORK_STEALING__ + /* Calculate memory to be allocated for work_pools in + * case of work_stealing. + */ + size_t max_global_size[2]; + size_t max_num_work_pools = 0; + max_global_size[0] = + (((user_set_tile_w - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) * + SPLIT_KERNEL_LOCAL_SIZE_X; + max_global_size[1] = + (((user_set_tile_h - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) * + SPLIT_KERNEL_LOCAL_SIZE_Y; + max_num_work_pools = + (max_global_size[0] * max_global_size[1]) / + (SPLIT_KERNEL_LOCAL_SIZE_X * SPLIT_KERNEL_LOCAL_SIZE_Y); + tile_specific_mem_allocated += max_num_work_pools * sizeof(unsigned int); +#endif + + tile_specific_mem_allocated += + user_set_tile_w * user_set_tile_h * per_thread_output_buffer_size; + tile_specific_mem_allocated += + user_set_tile_w * user_set_tile_h * sizeof(RNG); + + return tile_specific_mem_allocated; + } + + /* Calculates the texture memories and KernelData (d_data) memory + * that has been allocated. + */ + size_t get_scene_specific_mem_allocated(cl_mem d_data) + { + size_t scene_specific_mem_allocated = 0; + /* Calculate texture memories. */ +#define KERNEL_TEX(type, ttype, name) \ + scene_specific_mem_allocated += get_tex_size(#name); +#include "kernel_textures.h" +#undef KERNEL_TEX + size_t d_data_size; + ciErr = clGetMemObjectInfo(d_data, + CL_MEM_SIZE, + sizeof(d_data_size), + &d_data_size, + NULL); + assert(ciErr == CL_SUCCESS && "Can't get d_data mem object info"); + scene_specific_mem_allocated += d_data_size; + return scene_specific_mem_allocated; + } + + /* Calculate the memory required for one thread in split kernel. */ + size_t get_per_thread_memory() + { + size_t shader_closure_size = 0; + size_t shaderdata_volume = 0; + shader_closure_size = get_shader_closure_size(current_clos_max); + /* TODO(sergey): This will actually over-allocate if + * particular kernel does not support multiclosure. + */ + shaderdata_volume = get_shader_data_size(shader_closure_size); + size_t retval = sizeof(RNG) + + throughput_size + L_transparent_size + + rayState_size + work_element_size + + ISLamp_size + sizeof(PathRadiance) + sizeof(Ray) + sizeof(PathState) + + sizeof(Intersection) /* Overall isect */ + + sizeof(Intersection) /* Instersection_coop_AO */ + + sizeof(Intersection) /* Intersection coop DL */ + + shaderdata_volume /* Overall ShaderData */ + + (shaderdata_volume * 2) /* ShaderData : DL and shadow */ + + sizeof(Ray) + sizeof(BsdfEval) + AOAlpha_size + AOBSDF_size + sizeof(Ray) + + (sizeof(int)* NUM_QUEUES) + + per_thread_output_buffer_size; + return retval; + } + + /* Considers the total memory available in the device and + * and returns the maximum global work size possible. + */ + size_t get_feasible_global_work_size(int2 tile_size, cl_mem d_data) + { + /* Calculate invariably allocated memory. */ + size_t invariable_mem_allocated = get_invariable_mem_allocated(); + /* Calculate tile specific allocated memory. */ + size_t tile_specific_mem_allocated = + get_tile_specific_mem_allocated(tile_size); + /* Calculate scene specific allocated memory. */ + size_t scene_specific_mem_allocated = + get_scene_specific_mem_allocated(d_data); + /* Calculate total memory available for the threads in global work size. */ + size_t available_memory = total_allocatable_memory + - invariable_mem_allocated + - tile_specific_mem_allocated + - scene_specific_mem_allocated + - DATA_ALLOCATION_MEM_FACTOR; + size_t per_thread_memory_required = get_per_thread_memory(); + return (available_memory / per_thread_memory_required); + } + + /* Checks if the device has enough memory to render the whole tile; + * If not, we should split single tile into multiple tiles of small size + * and process them all. + */ + bool need_to_split_tile(unsigned int d_w, + unsigned int d_h, + int2 max_render_feasible_tile_size) + { + size_t global_size_estimate[2]; + /* TODO(sergey): Such round-ups are in quite few places, need to replace + * them with an utility macro. + */ + global_size_estimate[0] = + (((d_w - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) * + SPLIT_KERNEL_LOCAL_SIZE_X; + global_size_estimate[1] = + (((d_h - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) * + SPLIT_KERNEL_LOCAL_SIZE_Y; + if((global_size_estimate[0] * global_size_estimate[1]) > + (max_render_feasible_tile_size.x * max_render_feasible_tile_size.y)) { - run = function_bind(&OpenCLDevice::thread_run, device, this); + return true; } - }; + else { + return false; + } + } - int get_split_task_count(DeviceTask& /*task*/) + /* Considers the scene properties, global memory available in the device + * and returns a rectanglular tile dimension (approx the maximum) + * that should render on split kernel. + */ + int2 get_max_render_feasible_tile_size(size_t feasible_global_work_size) { - return 1; + int2 max_render_feasible_tile_size; + int square_root_val = (int)sqrt(feasible_global_work_size); + max_render_feasible_tile_size.x = square_root_val; + max_render_feasible_tile_size.y = square_root_val; + /* Ciel round-off max_render_feasible_tile_size. */ + int2 ceil_render_feasible_tile_size; + ceil_render_feasible_tile_size.x = + (((max_render_feasible_tile_size.x - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) * + SPLIT_KERNEL_LOCAL_SIZE_X; + ceil_render_feasible_tile_size.y = + (((max_render_feasible_tile_size.y - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) * + SPLIT_KERNEL_LOCAL_SIZE_Y; + if(ceil_render_feasible_tile_size.x * ceil_render_feasible_tile_size.y <= + feasible_global_work_size) + { + return ceil_render_feasible_tile_size; + } + /* Floor round-off max_render_feasible_tile_size. */ + int2 floor_render_feasible_tile_size; + floor_render_feasible_tile_size.x = + (max_render_feasible_tile_size.x / SPLIT_KERNEL_LOCAL_SIZE_X) * + SPLIT_KERNEL_LOCAL_SIZE_X; + floor_render_feasible_tile_size.y = + (max_render_feasible_tile_size.y / SPLIT_KERNEL_LOCAL_SIZE_Y) * + SPLIT_KERNEL_LOCAL_SIZE_Y; + return floor_render_feasible_tile_size; } - void task_add(DeviceTask& task) + /* Try splitting the current tile into multiple smaller + * almost-square-tiles. + */ + int2 get_split_tile_size(RenderTile rtile, + int2 max_render_feasible_tile_size) { - task_pool.push(new OpenCLDeviceTask(this, task)); + int2 split_tile_size; + int num_global_threads = max_render_feasible_tile_size.x * + max_render_feasible_tile_size.y; + int d_w = rtile.w; + int d_h = rtile.h; + /* Ceil round off d_w and d_h */ + d_w = (((d_w - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) * + SPLIT_KERNEL_LOCAL_SIZE_X; + d_h = (((d_h - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) * + SPLIT_KERNEL_LOCAL_SIZE_Y; + while(d_w * d_h > num_global_threads) { + /* Halve the longer dimension. */ + if(d_w >= d_h) { + d_w = d_w / 2; + d_w = (((d_w - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) * + SPLIT_KERNEL_LOCAL_SIZE_X; + } + else { + d_h = d_h / 2; + d_h = (((d_h - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) * + SPLIT_KERNEL_LOCAL_SIZE_Y; + } + } + split_tile_size.x = d_w; + split_tile_size.y = d_h; + return split_tile_size; } - void task_wait() + /* Splits existing tile into multiple tiles of tile size split_tile_size. */ + vector split_tiles(RenderTile rtile, int2 split_tile_size) { - task_pool.wait(); + vector to_path_trace_rtile; + int d_w = rtile.w; + int d_h = rtile.h; + int num_tiles_x = (((d_w - 1) / split_tile_size.x) + 1); + int num_tiles_y = (((d_h - 1) / split_tile_size.y) + 1); + /* Buffer and rng_state offset calc. */ + size_t offset_index = rtile.offset + (rtile.x + rtile.y * rtile.stride); + size_t offset_x = offset_index % rtile.stride; + size_t offset_y = offset_index / rtile.stride; + /* Resize to_path_trace_rtile. */ + to_path_trace_rtile.resize(num_tiles_x * num_tiles_y); + for(int tile_iter_y = 0; tile_iter_y < num_tiles_y; tile_iter_y++) { + for(int tile_iter_x = 0; tile_iter_x < num_tiles_x; tile_iter_x++) { + int rtile_index = tile_iter_y * num_tiles_x + tile_iter_x; + to_path_trace_rtile[rtile_index].rng_state_offset_x = offset_x + tile_iter_x * split_tile_size.x; + to_path_trace_rtile[rtile_index].rng_state_offset_y = offset_y + tile_iter_y * split_tile_size.y; + to_path_trace_rtile[rtile_index].buffer_offset_x = offset_x + tile_iter_x * split_tile_size.x; + to_path_trace_rtile[rtile_index].buffer_offset_y = offset_y + tile_iter_y * split_tile_size.y; + to_path_trace_rtile[rtile_index].start_sample = rtile.start_sample; + to_path_trace_rtile[rtile_index].num_samples = rtile.num_samples; + to_path_trace_rtile[rtile_index].sample = rtile.sample; + to_path_trace_rtile[rtile_index].resolution = rtile.resolution; + to_path_trace_rtile[rtile_index].offset = rtile.offset; + to_path_trace_rtile[rtile_index].buffers = rtile.buffers; + to_path_trace_rtile[rtile_index].buffer = rtile.buffer; + to_path_trace_rtile[rtile_index].rng_state = rtile.rng_state; + to_path_trace_rtile[rtile_index].x = rtile.x + (tile_iter_x * split_tile_size.x); + to_path_trace_rtile[rtile_index].y = rtile.y + (tile_iter_y * split_tile_size.y); + to_path_trace_rtile[rtile_index].buffer_rng_state_stride = rtile.stride; + /* Fill width and height of the new render tile. */ + to_path_trace_rtile[rtile_index].w = (tile_iter_x == (num_tiles_x - 1)) ? + (d_w - (tile_iter_x * split_tile_size.x)) /* Border tile */ + : split_tile_size.x; + to_path_trace_rtile[rtile_index].h = (tile_iter_y == (num_tiles_y - 1)) ? + (d_h - (tile_iter_y * split_tile_size.y)) /* Border tile */ + : split_tile_size.y; + to_path_trace_rtile[rtile_index].stride = to_path_trace_rtile[rtile_index].w; + } + } + return to_path_trace_rtile; } - void task_cancel() + void thread_run(DeviceTask *task) { - task_pool.cancel(); + if(task->type == DeviceTask::FILM_CONVERT) { + film_convert(*task, task->buffer, task->rgba_byte, task->rgba_half); + } + else if(task->type == DeviceTask::SHADER) { + shader(*task); + } + else if(task->type == DeviceTask::PATH_TRACE) { + RenderTile tile; + bool initialize_data_and_check_render_feasibility = false; + bool need_to_split_tiles_further = false; + int2 max_render_feasible_tile_size; + size_t feasible_global_work_size; + const int2 tile_size = task->requested_tile_size; + /* Keep rendering tiles until done. */ + while(task->acquire_tile(this, tile)) { + if(!initialize_data_and_check_render_feasibility) { + /* Initialize data. */ + /* Calculate per_thread_output_buffer_size. */ + size_t output_buffer_size = 0; + ciErr = clGetMemObjectInfo((cl_mem)tile.buffer, + CL_MEM_SIZE, + sizeof(output_buffer_size), + &output_buffer_size, + NULL); + assert(ciErr == CL_SUCCESS && "Can't get tile.buffer mem object info"); + /* This value is different when running on AMD and NV. */ + if(background) { + /* In offline render the number of buffer elements + * associated with tile.buffer is the current tile size. + */ + per_thread_output_buffer_size = + output_buffer_size / (tile.w * tile.h); + } + else { + /* interactive rendering, unlike offline render, the number of buffer elements + * associated with tile.buffer is the entire viewport size. + */ + per_thread_output_buffer_size = + output_buffer_size / (tile.buffers->params.width * + tile.buffers->params.height); + } + /* Check render feasibility. */ + feasible_global_work_size = get_feasible_global_work_size( + tile_size, + CL_MEM_PTR(const_mem_map["__data"]->device_pointer)); + max_render_feasible_tile_size = + get_max_render_feasible_tile_size( + feasible_global_work_size); + need_to_split_tiles_further = + need_to_split_tile(tile_size.x, + tile_size.y, + max_render_feasible_tile_size); + initialize_data_and_check_render_feasibility = true; + } + if(need_to_split_tiles_further) { + int2 split_tile_size = + get_split_tile_size(tile, + max_render_feasible_tile_size); + vector to_path_trace_render_tiles = + split_tiles(tile, split_tile_size); + /* Print message to console */ + if(background && (to_path_trace_render_tiles.size() > 1)) { + fprintf(stderr, "Message : Tiles need to be split " + "further inside path trace (due to insufficient " + "device-global-memory for split kernel to " + "function) \n" + "The current tile of dimensions %dx%d is split " + "into tiles of dimension %dx%d for render \n", + tile.w, tile.h, + split_tile_size.x, + split_tile_size.y); + } + /* Process all split tiles. */ + for(int tile_iter = 0; + tile_iter < to_path_trace_render_tiles.size(); + ++tile_iter) + { + path_trace(to_path_trace_render_tiles[tile_iter], + max_render_feasible_tile_size); + } + } + else { + /* No splitting required; process the entire tile at once. */ + /* Render feasible tile size is user-set-tile-size itself. */ + max_render_feasible_tile_size.x = + (((tile_size.x - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) * + SPLIT_KERNEL_LOCAL_SIZE_X; + max_render_feasible_tile_size.y = + (((tile_size.y - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) * + SPLIT_KERNEL_LOCAL_SIZE_Y; + /* buffer_rng_state_stride is stride itself. */ + SplitRenderTile split_tile(tile); + split_tile.buffer_rng_state_stride = tile.stride; + path_trace(split_tile, max_render_feasible_tile_size); + } + tile.sample = tile.start_sample + tile.num_samples; + + /* Complete kernel execution before release tile. */ + /* This helps in multi-device render; + * The device that reaches the critical-section function + * release_tile waits (stalling other devices from entering + * release_tile) for all kernels to complete. If device1 (a + * slow-render device) reaches release_tile first then it would + * stall device2 (a fast-render device) from proceeding to render + * next tile. + */ + clFinish(cqCommandQueue); + + task->release_tile(tile); + } + } + } + +protected: + cl_mem mem_alloc(size_t bufsize, cl_mem_flags mem_flag = CL_MEM_READ_WRITE) + { + cl_mem ptr; + ptr = clCreateBuffer(cxContext, mem_flag, bufsize, NULL, &ciErr); + if(opencl_error(ciErr)) { + assert(0); + } + return ptr; } }; +/* Returns true in case of successful detection of platform and device type, + * else returns false. + */ +static bool get_platform_and_devicetype(const DeviceInfo info, + string &platform_name, + cl_device_type &device_type) +{ + cl_platform_id platform_id; + cl_device_id device_id; + cl_uint num_platforms; + cl_int ciErr; + + /* TODO(sergey): Use some generic error print helper function/ */ + ciErr = clGetPlatformIDs(0, NULL, &num_platforms); + if(ciErr != CL_SUCCESS) { + fprintf(stderr, "Can't getPlatformIds. file - %s, line - %d\n", __FILE__, __LINE__); + return false; + } + + if(num_platforms == 0) { + fprintf(stderr, "No OpenCL platforms found. file - %s, line - %d\n", __FILE__, __LINE__); + return false; + } + + vector platforms(num_platforms, NULL); + + ciErr = clGetPlatformIDs(num_platforms, &platforms[0], NULL); + if(ciErr != CL_SUCCESS) { + fprintf(stderr, "Can't getPlatformIds. file - %s, line - %d\n", __FILE__, __LINE__); + return false; + } + + int num_base = 0; + int total_devices = 0; + + for(int platform = 0; platform < num_platforms; platform++) { + cl_uint num_devices; + + ciErr = clGetDeviceIDs(platforms[platform], opencl_device_type(), 0, NULL, &num_devices); + if(ciErr != CL_SUCCESS) { + fprintf(stderr, "Can't getDeviceIDs. file - %s, line - %d\n", __FILE__, __LINE__); + return false; + } + + total_devices += num_devices; + + if(info.num - num_base >= num_devices) { + /* num doesn't refer to a device in this platform */ + num_base += num_devices; + continue; + } + + /* device is in this platform */ + platform_id = platforms[platform]; + + /* get devices */ + vector device_ids(num_devices, NULL); + + ciErr = clGetDeviceIDs(platform_id, opencl_device_type(), num_devices, &device_ids[0], NULL); + if(ciErr != CL_SUCCESS) { + fprintf(stderr, "Can't getDeviceIDs. file - %s, line - %d\n", __FILE__, __LINE__); + return false; + } + + device_id = device_ids[info.num - num_base]; + + char name[256]; + ciErr = clGetPlatformInfo(platform_id, CL_PLATFORM_NAME, sizeof(name), &name, NULL); + if(ciErr != CL_SUCCESS) { + fprintf(stderr, "Can't getPlatformIDs. file - %s, line - %d \n", __FILE__, __LINE__); + return false; + } + platform_name = name; + + ciErr = clGetDeviceInfo(device_id, CL_DEVICE_TYPE, sizeof(cl_device_type), &device_type, NULL); + if(ciErr != CL_SUCCESS) { + fprintf(stderr, "Can't getDeviceInfo. file - %s, line - %d \n", __FILE__, __LINE__); + return false; + } + + break; + } + + if(total_devices == 0) { + fprintf(stderr, "No devices found. file - %s, line - %d \n", __FILE__, __LINE__); + return false; + } + + return true; +} + Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background) { - return new OpenCLDevice(info, stats, background); + string platform_name; + cl_device_type device_type; + if(get_platform_and_devicetype(info, platform_name, device_type)) { + const bool force_split_kernel = + getenv("CYCLES_OPENCL_SPLIT_KERNEL_TEST") != NULL; + /* TODO(sergey): Replace string lookups with more enum-like API, + * similar to device/venfdor checks blender's gpu. + */ + if(force_split_kernel || + (platform_name == "AMD Accelerated Parallel Processing" && + device_type == CL_DEVICE_TYPE_GPU)) + { + /* If the device is an AMD GPU, take split kernel path. */ + VLOG(1) << "Using split kernel"; + return new OpenCLDeviceSplitKernel(info, stats, background); + } else { + /* For any other device, take megakernel path. */ + VLOG(1) << "Using megekernel"; + return new OpenCLDeviceMegaKernel(info, stats, background); + } + } else { + /* If we can't retrieve platform and device type information for some + * reason, we default to megakernel path. + */ + VLOG(1) << "Failed to rertieve platform or device, using megakernel"; + return new OpenCLDeviceMegaKernel(info, stats, background); + } } -bool device_opencl_init(void) { +bool device_opencl_init(void) +{ static bool initialized = false; static bool result = false; @@ -1132,13 +3322,7 @@ bool device_opencl_init(void) { initialized = true; - // OpenCL disabled for now, only works with this environment variable set - if(!getenv("CYCLES_OPENCL_TEST")) { - result = false; - } - else { - result = clewInit() == CLEW_SUCCESS; - } + result = clewInit() == CLEW_SUCCESS; return result; } diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 83b3450fc1c..85b2760073b 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -14,6 +14,17 @@ set(INC_SYS set(SRC kernel.cpp kernel.cl + kernel_data_init.cl + kernel_queue_enqueue.cl + kernel_scene_intersect.cl + kernel_lamp_emission.cl + kernel_background_buffer_update.cl + kernel_shader_eval.cl + kernel_holdout_emission_blurring_pathtermination_ao.cl + kernel_direct_lighting.cl + kernel_shadow_blocked.cl + kernel_next_iteration_setup.cl + kernel_sum_all_radiance.cl kernel.cu ) @@ -36,17 +47,22 @@ set(SRC_HEADERS kernel_montecarlo.h kernel_passes.h kernel_path.h + kernel_path_common.h kernel_path_state.h kernel_path_surface.h kernel_path_volume.h kernel_projection.h + kernel_queues.h kernel_random.h kernel_shader.h + kernel_shaderdata_vars.h kernel_shadow.h + kernel_split.h kernel_subsurface.h kernel_textures.h kernel_types.h kernel_volume.h + kernel_work_stealing.h ) set(SRC_CLOSURE_HEADERS @@ -68,6 +84,7 @@ set(SRC_CLOSURE_HEADERS closure/emissive.h closure/volume.h ) + set(SRC_SVM_HEADERS svm/svm.h svm/svm_attribute.h @@ -284,6 +301,17 @@ endif() #delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${KERNEL_PREPROCESSED}" ${CYCLES_INSTALL_PATH}/kernel) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel.cl" ${CYCLES_INSTALL_PATH}/kernel) +delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel_data_init.cl" ${CYCLES_INSTALL_PATH}/kernel) +delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel_queue_enqueue.cl" ${CYCLES_INSTALL_PATH}/kernel) +delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel_scene_intersect.cl" ${CYCLES_INSTALL_PATH}/kernel) +delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel_lamp_emission.cl" ${CYCLES_INSTALL_PATH}/kernel) +delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel_background_buffer_update.cl" ${CYCLES_INSTALL_PATH}/kernel) +delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel_shader_eval.cl" ${CYCLES_INSTALL_PATH}/kernel) +delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel_holdout_emission_blurring_pathtermination_ao.cl" ${CYCLES_INSTALL_PATH}/kernel) +delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel_direct_lighting.cl" ${CYCLES_INSTALL_PATH}/kernel) +delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel_shadow_blocked.cl" ${CYCLES_INSTALL_PATH}/kernel) +delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel_next_iteration_setup.cl" ${CYCLES_INSTALL_PATH}/kernel) +delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel_sum_all_radiance.cl" ${CYCLES_INSTALL_PATH}/kernel) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel.cu" ${CYCLES_INSTALL_PATH}/kernel) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_CLOSURE_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/closure) diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index 2b9e2a4e44d..558aa0dc6a9 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -47,79 +47,79 @@ ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const Shader switch(sc->type) { case CLOSURE_BSDF_DIFFUSE_ID: case CLOSURE_BSDF_BSSRDF_ID: - label = bsdf_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_diffuse_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; #ifdef __SVM__ case CLOSURE_BSDF_OREN_NAYAR_ID: - label = bsdf_oren_nayar_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_oren_nayar_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; /*case CLOSURE_BSDF_PHONG_RAMP_ID: - label = bsdf_phong_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_phong_ramp_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_DIFFUSE_RAMP_ID: - label = bsdf_diffuse_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_diffuse_ramp_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break;*/ case CLOSURE_BSDF_TRANSLUCENT_ID: - label = bsdf_translucent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_translucent_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_REFLECTION_ID: - label = bsdf_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_reflection_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_REFRACTION_ID: - label = bsdf_refraction_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_refraction_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_TRANSPARENT_ID: - label = bsdf_transparent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_transparent_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: - label = bsdf_microfacet_ggx_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_microfacet_ggx_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - label = bsdf_microfacet_beckmann_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_microfacet_beckmann_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID: - label = bsdf_ashikhmin_shirley_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_ashikhmin_shirley_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - label = bsdf_ashikhmin_velvet_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_ashikhmin_velvet_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_DIFFUSE_TOON_ID: - label = bsdf_diffuse_toon_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_diffuse_toon_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_GLOSSY_TOON_ID: - label = bsdf_glossy_toon_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_glossy_toon_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_HAIR_REFLECTION_ID: - label = bsdf_hair_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_hair_reflection_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: - label = bsdf_hair_transmission_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + label = bsdf_hair_transmission_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; #endif #ifdef __VOLUME__ case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID: - label = volume_henyey_greenstein_sample(sc, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = volume_henyey_greenstein_sample(sc, ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; #endif default: @@ -139,67 +139,67 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade return OSLShader::bsdf_eval(sd, sc, omega_in, *pdf); #endif - if(dot(sd->Ng, omega_in) >= 0.0f) { + if(dot(ccl_fetch(sd, Ng), omega_in) >= 0.0f) { switch(sc->type) { case CLOSURE_BSDF_DIFFUSE_ID: case CLOSURE_BSDF_BSSRDF_ID: - eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_diffuse_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; #ifdef __SVM__ case CLOSURE_BSDF_OREN_NAYAR_ID: - eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_oren_nayar_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; /*case CLOSURE_BSDF_PHONG_RAMP_ID: - eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_phong_ramp_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_DIFFUSE_RAMP_ID: - eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_diffuse_ramp_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break;*/ case CLOSURE_BSDF_TRANSLUCENT_ID: - eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_translucent_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_REFLECTION_ID: - eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_reflection_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_REFRACTION_ID: - eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_refraction_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_TRANSPARENT_ID: - eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_transparent_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: - eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_microfacet_ggx_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_microfacet_beckmann_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID: - eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_ashikhmin_shirley_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_ashikhmin_velvet_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_DIFFUSE_TOON_ID: - eval = bsdf_diffuse_toon_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_diffuse_toon_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_GLOSSY_TOON_ID: - eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_glossy_toon_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_HAIR_REFLECTION_ID: - eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_hair_reflection_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: - eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf); + eval = bsdf_hair_transmission_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; #endif #ifdef __VOLUME__ case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID: - eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf); + eval = volume_henyey_greenstein_eval_phase(sc, ccl_fetch(sd, I), omega_in, pdf); break; #endif default: @@ -211,57 +211,57 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade switch(sc->type) { case CLOSURE_BSDF_DIFFUSE_ID: case CLOSURE_BSDF_BSSRDF_ID: - eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf); + eval = bsdf_diffuse_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; #ifdef __SVM__ case CLOSURE_BSDF_OREN_NAYAR_ID: - eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf); + eval = bsdf_oren_nayar_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_TRANSLUCENT_ID: - eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf); + eval = bsdf_translucent_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_REFLECTION_ID: - eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf); + eval = bsdf_reflection_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_REFRACTION_ID: - eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf); + eval = bsdf_refraction_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_TRANSPARENT_ID: - eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf); + eval = bsdf_transparent_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: - eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf); + eval = bsdf_microfacet_ggx_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf); + eval = bsdf_microfacet_beckmann_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID: - eval = bsdf_ashikhmin_shirley_eval_transmit(sc, sd->I, omega_in, pdf); + eval = bsdf_ashikhmin_shirley_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf); + eval = bsdf_ashikhmin_velvet_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_DIFFUSE_TOON_ID: - eval = bsdf_diffuse_toon_eval_transmit(sc, sd->I, omega_in, pdf); + eval = bsdf_diffuse_toon_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_GLOSSY_TOON_ID: - eval = bsdf_glossy_toon_eval_transmit(sc, sd->I, omega_in, pdf); + eval = bsdf_glossy_toon_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_HAIR_REFLECTION_ID: - eval = bsdf_hair_reflection_eval_transmit(sc, sd->I, omega_in, pdf); + eval = bsdf_hair_reflection_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: - eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf); + eval = bsdf_hair_transmission_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; #endif #ifdef __VOLUME__ case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID: - eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf); + eval = volume_henyey_greenstein_eval_phase(sc, ccl_fetch(sd, I), omega_in, pdf); break; #endif default: diff --git a/intern/cycles/kernel/geom/geom_attribute.h b/intern/cycles/kernel/geom/geom_attribute.h index 9ac16e86085..c7364e9edac 100644 --- a/intern/cycles/kernel/geom/geom_attribute.h +++ b/intern/cycles/kernel/geom/geom_attribute.h @@ -29,13 +29,13 @@ CCL_NAMESPACE_BEGIN ccl_device_inline int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem) { - if(sd->object == PRIM_NONE) + if(ccl_fetch(sd, object) == PRIM_NONE) return (int)ATTR_STD_NOT_FOUND; /* for SVM, find attribute by unique id */ - uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride; + uint attr_offset = ccl_fetch(sd, object)*kernel_data.bvh.attributes_map_stride; #ifdef __HAIR__ - attr_offset = (sd->type & PRIMITIVE_ALL_CURVE)? attr_offset + ATTR_PRIM_CURVE: attr_offset; + attr_offset = (ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE)? attr_offset + ATTR_PRIM_CURVE: attr_offset; #endif uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset); @@ -49,7 +49,7 @@ ccl_device_inline int find_attribute(KernelGlobals *kg, const ShaderData *sd, ui *elem = (AttributeElement)attr_map.y; - if(sd->prim == PRIM_NONE && (AttributeElement)attr_map.y != ATTR_ELEMENT_MESH) + if(ccl_fetch(sd, prim) == PRIM_NONE && (AttributeElement)attr_map.y != ATTR_ELEMENT_MESH) return ATTR_STD_NOT_FOUND; /* return result */ diff --git a/intern/cycles/kernel/geom/geom_bvh.h b/intern/cycles/kernel/geom/geom_bvh.h index 2e8e27c709d..3d0d406dd0b 100644 --- a/intern/cycles/kernel/geom/geom_bvh.h +++ b/intern/cycles/kernel/geom/geom_bvh.h @@ -447,6 +447,7 @@ ccl_device_inline float3 ray_offset(float3 P, float3 Ng) #endif } +#if defined(__SHADOW_RECORD_ALL__) || defined (__VOLUME_RECORD_ALL__) /* ToDo: Move to another file? */ ccl_device int intersections_compare(const void *a, const void *b) { @@ -460,6 +461,7 @@ ccl_device int intersections_compare(const void *a, const void *b) else return 0; } +#endif CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/geom/geom_motion_triangle.h b/intern/cycles/kernel/geom/geom_motion_triangle.h index a5a25f4a9ae..4ea9e4714c4 100644 --- a/intern/cycles/kernel/geom/geom_motion_triangle.h +++ b/intern/cycles/kernel/geom/geom_motion_triangle.h @@ -236,25 +236,25 @@ ccl_device_inline float3 motion_triangle_refine_subsurface(KernelGlobals *kg, Sh ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, bool subsurface) { /* get shader */ - sd->shader = kernel_tex_fetch(__tri_shader, sd->prim); + ccl_fetch(sd, shader) = kernel_tex_fetch(__tri_shader, ccl_fetch(sd, prim)); /* get motion info */ int numsteps, numverts; - object_motion_info(kg, sd->object, &numsteps, &numverts, NULL); + object_motion_info(kg, ccl_fetch(sd, object), &numsteps, &numverts, NULL); /* figure out which steps we need to fetch and their interpolation factor */ int maxstep = numsteps*2; - int step = min((int)(sd->time*maxstep), maxstep-1); - float t = sd->time*maxstep - step; + int step = min((int)(ccl_fetch(sd, time)*maxstep), maxstep-1); + float t = ccl_fetch(sd, time)*maxstep - step; /* find attribute */ AttributeElement elem; - int offset = find_attribute_motion(kg, sd->object, ATTR_STD_MOTION_VERTEX_POSITION, &elem); + int offset = find_attribute_motion(kg, ccl_fetch(sd, object), ATTR_STD_MOTION_VERTEX_POSITION, &elem); kernel_assert(offset != ATTR_STD_NOT_FOUND); /* fetch vertex coordinates */ float3 verts[3], next_verts[3]; - float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim)); + float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim))); motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts); motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step+1, next_verts); @@ -268,33 +268,33 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg, ShaderD #ifdef __SUBSURFACE__ if(!subsurface) #endif - sd->P = motion_triangle_refine(kg, sd, isect, ray, verts); + ccl_fetch(sd, P) = motion_triangle_refine(kg, sd, isect, ray, verts); #ifdef __SUBSURFACE__ else - sd->P = motion_triangle_refine_subsurface(kg, sd, isect, ray, verts); + ccl_fetch(sd, P) = motion_triangle_refine_subsurface(kg, sd, isect, ray, verts); #endif /* compute face normal */ float3 Ng; - if(sd->flag & SD_NEGATIVE_SCALE_APPLIED) + if(ccl_fetch(sd, flag) & SD_NEGATIVE_SCALE_APPLIED) Ng = normalize(cross(verts[2] - verts[0], verts[1] - verts[0])); else Ng = normalize(cross(verts[1] - verts[0], verts[2] - verts[0])); - sd->Ng = Ng; - sd->N = Ng; + ccl_fetch(sd, Ng) = Ng; + ccl_fetch(sd, N) = Ng; /* compute derivatives of P w.r.t. uv */ #ifdef __DPDU__ - sd->dPdu = (verts[0] - verts[2]); - sd->dPdv = (verts[1] - verts[2]); + ccl_fetch(sd, dPdu) = (verts[0] - verts[2]); + ccl_fetch(sd, dPdv) = (verts[1] - verts[2]); #endif /* compute smooth normal */ - if(sd->shader & SHADER_SMOOTH_NORMAL) { + if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) { /* find attribute */ AttributeElement elem; - int offset = find_attribute_motion(kg, sd->object, ATTR_STD_MOTION_VERTEX_NORMAL, &elem); + int offset = find_attribute_motion(kg, ccl_fetch(sd, object), ATTR_STD_MOTION_VERTEX_NORMAL, &elem); kernel_assert(offset != ATTR_STD_NOT_FOUND); /* fetch vertex coordinates */ @@ -308,10 +308,10 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg, ShaderD normals[2] = (1.0f - t)*normals[2] + t*next_normals[2]; /* interpolate between vertices */ - float u = sd->u; - float v = sd->v; + float u = ccl_fetch(sd, u); + float v = ccl_fetch(sd, v); float w = 1.0f - u - v; - sd->N = (u*normals[0] + v*normals[1] + w*normals[2]); + ccl_fetch(sd, N) = (u*normals[0] + v*normals[1] + w*normals[2]); } } diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h index 7df71010232..40cbca243a7 100644 --- a/intern/cycles/kernel/geom/geom_object.h +++ b/intern/cycles/kernel/geom/geom_object.h @@ -123,9 +123,9 @@ ccl_device_inline Transform object_fetch_transform_motion_test(KernelGlobals *kg ccl_device_inline void object_position_transform(KernelGlobals *kg, const ShaderData *sd, float3 *P) { #ifdef __OBJECT_MOTION__ - *P = transform_point(&sd->ob_tfm, *P); + *P = transform_point(&ccl_fetch(sd, ob_tfm), *P); #else - Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM); *P = transform_point(&tfm, *P); #endif } @@ -135,9 +135,9 @@ ccl_device_inline void object_position_transform(KernelGlobals *kg, const Shader ccl_device_inline void object_inverse_position_transform(KernelGlobals *kg, const ShaderData *sd, float3 *P) { #ifdef __OBJECT_MOTION__ - *P = transform_point(&sd->ob_itfm, *P); + *P = transform_point(&ccl_fetch(sd, ob_itfm), *P); #else - Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM); + Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_INVERSE_TRANSFORM); *P = transform_point(&tfm, *P); #endif } @@ -147,9 +147,9 @@ ccl_device_inline void object_inverse_position_transform(KernelGlobals *kg, cons ccl_device_inline void object_inverse_normal_transform(KernelGlobals *kg, const ShaderData *sd, float3 *N) { #ifdef __OBJECT_MOTION__ - *N = normalize(transform_direction_transposed(&sd->ob_tfm, *N)); + *N = normalize(transform_direction_transposed(&ccl_fetch(sd, ob_tfm), *N)); #else - Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM); *N = normalize(transform_direction_transposed(&tfm, *N)); #endif } @@ -159,9 +159,9 @@ ccl_device_inline void object_inverse_normal_transform(KernelGlobals *kg, const ccl_device_inline void object_normal_transform(KernelGlobals *kg, const ShaderData *sd, float3 *N) { #ifdef __OBJECT_MOTION__ - *N = normalize(transform_direction_transposed(&sd->ob_itfm, *N)); + *N = normalize(transform_direction_transposed(&ccl_fetch(sd, ob_itfm), *N)); #else - Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM); + Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_INVERSE_TRANSFORM); *N = normalize(transform_direction_transposed(&tfm, *N)); #endif } @@ -171,9 +171,9 @@ ccl_device_inline void object_normal_transform(KernelGlobals *kg, const ShaderDa ccl_device_inline void object_dir_transform(KernelGlobals *kg, const ShaderData *sd, float3 *D) { #ifdef __OBJECT_MOTION__ - *D = transform_direction(&sd->ob_tfm, *D); + *D = transform_direction(&ccl_fetch(sd, ob_tfm), *D); #else - Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM); *D = transform_direction(&tfm, *D); #endif } @@ -183,9 +183,9 @@ ccl_device_inline void object_dir_transform(KernelGlobals *kg, const ShaderData ccl_device_inline void object_inverse_dir_transform(KernelGlobals *kg, const ShaderData *sd, float3 *D) { #ifdef __OBJECT_MOTION__ - *D = transform_direction(&sd->ob_itfm, *D); + *D = transform_direction(&ccl_fetch(sd, ob_itfm), *D); #else - Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM); + Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_INVERSE_TRANSFORM); *D = transform_direction(&tfm, *D); #endif } @@ -194,13 +194,13 @@ ccl_device_inline void object_inverse_dir_transform(KernelGlobals *kg, const Sha ccl_device_inline float3 object_location(KernelGlobals *kg, const ShaderData *sd) { - if(sd->object == OBJECT_NONE) + if(ccl_fetch(sd, object) == OBJECT_NONE) return make_float3(0.0f, 0.0f, 0.0f); #ifdef __OBJECT_MOTION__ - return make_float3(sd->ob_tfm.x.w, sd->ob_tfm.y.w, sd->ob_tfm.z.w); + return make_float3(ccl_fetch(sd, ob_tfm).x.w, ccl_fetch(sd, ob_tfm).y.w, ccl_fetch(sd, ob_tfm).z.w); #else - Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM); return make_float3(tfm.x.w, tfm.y.w, tfm.z.w); #endif } @@ -296,7 +296,7 @@ ccl_device_inline void object_motion_info(KernelGlobals *kg, int object, int *nu ccl_device int shader_pass_id(KernelGlobals *kg, const ShaderData *sd) { - return kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2 + 1); + return kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*2 + 1); } /* Particle data from which object was instanced */ @@ -377,7 +377,7 @@ ccl_device_inline float3 bvh_inverse_direction(float3 dir) /* Transform ray into object space to enter static object in BVH */ -ccl_device_inline void bvh_instance_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float *t) +ccl_device_inline void bvh_instance_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, ccl_addr_space float *t) { Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); @@ -425,7 +425,7 @@ ccl_device_inline void qbvh_instance_push(KernelGlobals *kg, /* Transorm ray to exit static object in BVH */ -ccl_device_inline void bvh_instance_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float *t) +ccl_device_inline void bvh_instance_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, ccl_addr_space float *t) { if(*t != FLT_MAX) { Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); @@ -520,5 +520,38 @@ ccl_device_inline void bvh_instance_motion_pop_factor(KernelGlobals *kg, int obj #endif +/* TODO(sergey): This is only for until we've got OpenCL 2.0 + * on all devices we consider supported. It'll be replaced with + * generic address space. + */ + +#ifdef __KERNEL_OPENCL__ +ccl_device_inline void object_dir_transform_addrspace(KernelGlobals *kg, + const ShaderData *sd, + ccl_addr_space float3 *D) +{ + float3 private_D = *D; + object_dir_transform(kg, sd, &private_D); + *D = private_D; +} + +ccl_device_inline void object_normal_transform_addrspace(KernelGlobals *kg, + const ShaderData *sd, + ccl_addr_space float3 *N) +{ + float3 private_N = *N; + object_dir_transform(kg, sd, &private_N); + *N = private_N; +} +#endif + +#ifndef __KERNEL_OPENCL__ +# define object_dir_transform_auto object_dir_transform +# define object_normal_transform_auto object_normal_transform +#else +# define object_dir_transform_auto object_dir_transform_addrspace +# define object_normal_transform_auto object_normal_transform_addrspace +#endif + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/geom/geom_primitive.h b/intern/cycles/kernel/geom/geom_primitive.h index d2543c5943e..30f12d32355 100644 --- a/intern/cycles/kernel/geom/geom_primitive.h +++ b/intern/cycles/kernel/geom/geom_primitive.h @@ -25,16 +25,16 @@ CCL_NAMESPACE_BEGIN ccl_device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy) { - if(sd->type & PRIMITIVE_ALL_TRIANGLE) { + if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) { return triangle_attribute_float(kg, sd, elem, offset, dx, dy); } #ifdef __HAIR__ - else if(sd->type & PRIMITIVE_ALL_CURVE) { + else if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) { return curve_attribute_float(kg, sd, elem, offset, dx, dy); } #endif #ifdef __VOLUME__ - else if(sd->object != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) { + else if(ccl_fetch(sd, object) != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) { return volume_attribute_float(kg, sd, elem, offset, dx, dy); } #endif @@ -47,16 +47,16 @@ ccl_device float primitive_attribute_float(KernelGlobals *kg, const ShaderData * ccl_device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy) { - if(sd->type & PRIMITIVE_ALL_TRIANGLE) { + if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) { return triangle_attribute_float3(kg, sd, elem, offset, dx, dy); } #ifdef __HAIR__ - else if(sd->type & PRIMITIVE_ALL_CURVE) { + else if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) { return curve_attribute_float3(kg, sd, elem, offset, dx, dy); } #endif #ifdef __VOLUME__ - else if(sd->object != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) { + else if(ccl_fetch(sd, object) != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) { return volume_attribute_float3(kg, sd, elem, offset, dx, dy); } #endif @@ -108,9 +108,9 @@ ccl_device bool primitive_ptex(KernelGlobals *kg, ShaderData *sd, float2 *uv, in ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd) { #ifdef __HAIR__ - if(sd->type & PRIMITIVE_ALL_CURVE) + if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) #ifdef __DPDU__ - return normalize(sd->dPdu); + return normalize(ccl_fetch(sd, dPdu)); #else return make_float3(0.0f, 0.0f, 0.0f); #endif @@ -124,12 +124,12 @@ ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd) float3 data = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL); data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f); object_normal_transform(kg, sd, &data); - return cross(sd->N, normalize(cross(data, sd->N))); + return cross(ccl_fetch(sd, N), normalize(cross(data, ccl_fetch(sd, N)))); } else { /* otherwise use surface derivatives */ #ifdef __DPDU__ - return normalize(sd->dPdu); + return normalize(ccl_fetch(sd, dPdu)); #else return make_float3(0.0f, 0.0f, 0.0f); #endif @@ -144,16 +144,16 @@ ccl_device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd) float3 center; #ifdef __HAIR__ - bool is_curve_primitive = sd->type & PRIMITIVE_ALL_CURVE; + bool is_curve_primitive = ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE; if(is_curve_primitive) { center = curve_motion_center_location(kg, sd); - if(!(sd->flag & SD_TRANSFORM_APPLIED)) + if(!(ccl_fetch(sd, flag) & SD_TRANSFORM_APPLIED)) object_position_transform(kg, sd, ¢er); } else #endif - center = sd->P; + center = ccl_fetch(sd, P); float3 motion_pre = center, motion_post = center; @@ -164,16 +164,16 @@ ccl_device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd) if(offset != ATTR_STD_NOT_FOUND) { /* get motion info */ int numverts, numkeys; - object_motion_info(kg, sd->object, NULL, &numverts, &numkeys); + object_motion_info(kg, ccl_fetch(sd, object), NULL, &numverts, &numkeys); /* lookup attributes */ - int offset_next = (sd->type & PRIMITIVE_ALL_TRIANGLE)? offset + numverts: offset + numkeys; + int offset_next = (ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE)? offset + numverts: offset + numkeys; motion_pre = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL); motion_post = primitive_attribute_float3(kg, sd, elem, offset_next, NULL, NULL); #ifdef __HAIR__ - if(is_curve_primitive && (sd->flag & SD_OBJECT_HAS_VERTEX_MOTION) == 0) { + if(is_curve_primitive && (ccl_fetch(sd, flag) & SD_OBJECT_HAS_VERTEX_MOTION) == 0) { object_position_transform(kg, sd, &motion_pre); object_position_transform(kg, sd, &motion_post); } @@ -184,10 +184,10 @@ ccl_device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd) * transformation was set match the world/object space of motion_pre/post */ Transform tfm; - tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_PRE); + tfm = object_fetch_vector_transform(kg, ccl_fetch(sd, object), OBJECT_VECTOR_MOTION_PRE); motion_pre = transform_point(&tfm, motion_pre); - tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_POST); + tfm = object_fetch_vector_transform(kg, ccl_fetch(sd, object), OBJECT_VECTOR_MOTION_POST); motion_post = transform_point(&tfm, motion_post); float3 motion_center; diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h index dd3928682e3..995dfac5b09 100644 --- a/intern/cycles/kernel/geom/geom_triangle.h +++ b/intern/cycles/kernel/geom/geom_triangle.h @@ -27,14 +27,14 @@ CCL_NAMESPACE_BEGIN ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd) { /* load triangle vertices */ - float4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); + float4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim)); float3 v0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x))); float3 v1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y))); float3 v2 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z))); /* return normal */ - if(sd->flag & SD_NEGATIVE_SCALE_APPLIED) + if(ccl_fetch(sd, flag) & SD_NEGATIVE_SCALE_APPLIED) return normalize(cross(v2 - v0, v1 - v0)); else return normalize(cross(v1 - v0, v2 - v0)); @@ -94,7 +94,7 @@ ccl_device_inline float3 triangle_smooth_normal(KernelGlobals *kg, int prim, flo /* Ray differentials on triangle */ -ccl_device_inline void triangle_dPdudv(KernelGlobals *kg, int prim, float3 *dPdu, float3 *dPdv) +ccl_device_inline void triangle_dPdudv(KernelGlobals *kg, int prim, ccl_addr_space float3 *dPdu, ccl_addr_space float3 *dPdv) { /* fetch triangle vertex coordinates */ float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim); @@ -116,34 +116,34 @@ ccl_device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *s if(dx) *dx = 0.0f; if(dy) *dy = 0.0f; - return kernel_tex_fetch(__attributes_float, offset + sd->prim); + return kernel_tex_fetch(__attributes_float, offset + ccl_fetch(sd, prim)); } else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) { - float4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); + float4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim)); float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.x)); float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.y)); float f2 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.z)); #ifdef __RAY_DIFFERENTIALS__ - if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2; - if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2; + if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2; + if(dy) *dy = ccl_fetch(sd, du).dy*f0 + ccl_fetch(sd, dv).dy*f1 - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*f2; #endif - return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2; + return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2; } else if(elem == ATTR_ELEMENT_CORNER) { - int tri = offset + sd->prim*3; + int tri = offset + ccl_fetch(sd, prim)*3; float f0 = kernel_tex_fetch(__attributes_float, tri + 0); float f1 = kernel_tex_fetch(__attributes_float, tri + 1); float f2 = kernel_tex_fetch(__attributes_float, tri + 2); #ifdef __RAY_DIFFERENTIALS__ - if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2; - if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2; + if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2; + if(dy) *dy = ccl_fetch(sd, du).dy*f0 + ccl_fetch(sd, dv).dy*f1 - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*f2; #endif - return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2; + return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2; } else { if(dx) *dx = 0.0f; @@ -159,24 +159,24 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f); if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f); - return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim)); + return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + ccl_fetch(sd, prim))); } else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) { - float4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); + float4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim)); float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x))); float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y))); float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z))); #ifdef __RAY_DIFFERENTIALS__ - if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2; - if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2; + if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2; + if(dy) *dy = ccl_fetch(sd, du).dy*f0 + ccl_fetch(sd, dv).dy*f1 - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*f2; #endif - return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2; + return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2; } else if(elem == ATTR_ELEMENT_CORNER || elem == ATTR_ELEMENT_CORNER_BYTE) { - int tri = offset + sd->prim*3; + int tri = offset + ccl_fetch(sd, prim)*3; float3 f0, f1, f2; if(elem == ATTR_ELEMENT_CORNER) { @@ -191,11 +191,11 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData } #ifdef __RAY_DIFFERENTIALS__ - if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2; - if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2; + if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2; + if(dy) *dy = ccl_fetch(sd, du).dy*f0 + ccl_fetch(sd, dv).dy*f1 - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*f2; #endif - return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2; + return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2; } else { if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f); diff --git a/intern/cycles/kernel/kernel.cl b/intern/cycles/kernel/kernel.cl index 5a47260a4ee..19e394936ee 100644 --- a/intern/cycles/kernel/kernel.cl +++ b/intern/cycles/kernel/kernel.cl @@ -25,6 +25,8 @@ #include "kernel_path.h" #include "kernel_bake.h" +#ifdef __COMPILE_ONLY_MEGAKERNEL__ + __kernel void kernel_ocl_path_trace( ccl_constant KernelData *data, ccl_global float *buffer, @@ -52,17 +54,18 @@ __kernel void kernel_ocl_path_trace( kernel_path_trace(kg, buffer, rng_state, sample, x, y, offset, stride); } -__kernel void kernel_ocl_convert_to_byte( +#else // __COMPILE_ONLY_MEGAKERNEL__ + +__kernel void kernel_ocl_shader( ccl_constant KernelData *data, - ccl_global uchar4 *rgba, - ccl_global float *buffer, + ccl_global uint4 *input, + ccl_global float4 *output, #define KERNEL_TEX(type, ttype, name) \ ccl_global type *name, #include "kernel_textures.h" - float sample_scale, - int sx, int sy, int sw, int sh, int offset, int stride) + int type, int sx, int sw, int offset, int sample) { KernelGlobals kglobals, *kg = &kglobals; @@ -73,23 +76,21 @@ __kernel void kernel_ocl_convert_to_byte( #include "kernel_textures.h" int x = sx + get_global_id(0); - int y = sy + get_global_id(1); - if(x < sx + sw && y < sy + sh) - kernel_film_convert_to_byte(kg, rgba, buffer, sample_scale, x, y, offset, stride); + if(x < sx + sw) + kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, x, sample); } -__kernel void kernel_ocl_convert_to_half_float( +__kernel void kernel_ocl_bake( ccl_constant KernelData *data, - ccl_global uchar4 *rgba, - ccl_global float *buffer, + ccl_global uint4 *input, + ccl_global float4 *output, #define KERNEL_TEX(type, ttype, name) \ ccl_global type *name, #include "kernel_textures.h" - float sample_scale, - int sx, int sy, int sw, int sh, int offset, int stride) + int type, int sx, int sw, int offset, int sample) { KernelGlobals kglobals, *kg = &kglobals; @@ -100,22 +101,22 @@ __kernel void kernel_ocl_convert_to_half_float( #include "kernel_textures.h" int x = sx + get_global_id(0); - int y = sy + get_global_id(1); - if(x < sx + sw && y < sy + sh) - kernel_film_convert_to_half_float(kg, rgba, buffer, sample_scale, x, y, offset, stride); + if(x < sx + sw) + kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, x, offset, sample); } -__kernel void kernel_ocl_shader( +__kernel void kernel_ocl_convert_to_byte( ccl_constant KernelData *data, - ccl_global uint4 *input, - ccl_global float4 *output, + ccl_global uchar4 *rgba, + ccl_global float *buffer, #define KERNEL_TEX(type, ttype, name) \ ccl_global type *name, #include "kernel_textures.h" - int type, int sx, int sw, int offset, int sample) + float sample_scale, + int sx, int sy, int sw, int sh, int offset, int stride) { KernelGlobals kglobals, *kg = &kglobals; @@ -126,21 +127,23 @@ __kernel void kernel_ocl_shader( #include "kernel_textures.h" int x = sx + get_global_id(0); + int y = sy + get_global_id(1); - if(x < sx + sw) - kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, x, sample); + if(x < sx + sw && y < sy + sh) + kernel_film_convert_to_byte(kg, rgba, buffer, sample_scale, x, y, offset, stride); } -__kernel void kernel_ocl_bake( +__kernel void kernel_ocl_convert_to_half_float( ccl_constant KernelData *data, - ccl_global uint4 *input, - ccl_global float4 *output, + ccl_global uchar4 *rgba, + ccl_global float *buffer, #define KERNEL_TEX(type, ttype, name) \ ccl_global type *name, #include "kernel_textures.h" - int type, int sx, int sw, int offset, int sample) + float sample_scale, + int sx, int sy, int sw, int sh, int offset, int stride) { KernelGlobals kglobals, *kg = &kglobals; @@ -151,8 +154,10 @@ __kernel void kernel_ocl_bake( #include "kernel_textures.h" int x = sx + get_global_id(0); + int y = sy + get_global_id(1); - if(x < sx + sw) - kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, x, offset, sample); + if(x < sx + sw && y < sy + sh) + kernel_film_convert_to_half_float(kg, rgba, buffer, sample_scale, x, y, offset, stride); } +#endif // __COMPILE_ONLY_MEGAKERNEL__ \ No newline at end of file diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 369c615eade..257728b6244 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -176,7 +176,7 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass) #endif } -ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, float3 *throughput, +ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, ccl_addr_space float3 *throughput, BsdfEval *bsdf_eval, float bsdf_pdf, int bounce, int bsdf_label) { float inverse_pdf = 1.0f/bsdf_pdf; diff --git a/intern/cycles/kernel/kernel_background_buffer_update.cl b/intern/cycles/kernel/kernel_background_buffer_update.cl new file mode 100644 index 00000000000..bf08477cfbf --- /dev/null +++ b/intern/cycles/kernel/kernel_background_buffer_update.cl @@ -0,0 +1,282 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kernel_split.h" + +/* + * Note on kernel_ocl_path_trace_background_buffer_update kernel. + * This is the fourth kernel in the ray tracing logic, and the third + * of the path iteration kernels. This kernel takes care of rays that hit + * the background (sceneintersect kernel), and for the rays of + * state RAY_UPDATE_BUFFER it updates the ray's accumulated radiance in + * the output buffer. This kernel also takes care of rays that have been determined + * to-be-regenerated. + * + * We will empty QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue in this kernel + * + * Typically all rays that are in state RAY_HIT_BACKGROUND, RAY_UPDATE_BUFFER + * will be eventually set to RAY_TO_REGENERATE state in this kernel. Finally all rays of ray_state + * RAY_TO_REGENERATE will be regenerated and put in queue QUEUE_ACTIVE_AND_REGENERATED_RAYS. + * + * The input and output are as follows, + * + * rng_coop ---------------------------------------------|--- kernel_ocl_path_trace_background_buffer_update --|--- PathRadiance_coop + * throughput_coop --------------------------------------| |--- L_transparent_coop + * per_sample_output_buffers ----------------------------| |--- per_sample_output_buffers + * Ray_coop ---------------------------------------------| |--- ray_state + * PathState_coop ---------------------------------------| |--- Queue_data (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) + * L_transparent_coop -----------------------------------| |--- Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS) + * ray_state --------------------------------------------| |--- Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) + * Queue_data (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) ----| |--- Queue_index (QUEUE_ACTIVE_AND_REGENERATED_RAYS) + * Queue_index (QUEUE_ACTIVE_AND_REGENERATED_RAYS) ------| |--- work_array + * parallel_samples -------------------------------------| |--- PathState_coop + * end_sample -------------------------------------------| |--- throughput_coop + * kg (globals + data) ----------------------------------| |--- rng_coop + * rng_state --------------------------------------------| |--- Ray + * PathRadiance_coop ------------------------------------| | + * sw ---------------------------------------------------| | + * sh ---------------------------------------------------| | + * sx ---------------------------------------------------| | + * sy ---------------------------------------------------| | + * stride -----------------------------------------------| | + * work_array -------------------------------------------| |--- work_array + * queuesize --------------------------------------------| | + * start_sample -----------------------------------------| |--- work_pool_wgs + * work_pool_wgs ----------------------------------------| | + * num_samples ------------------------------------------| | + * + * note on shader_data : shader_data argument is neither an input nor an output for this kernel. It is just filled and consumed here itself. + * Note on Queues : + * This kernel fetches rays from QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. + * + * State of queues when this kernel is called : + * At entry, + * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE rays + * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_UPDATE_BUFFER, RAY_HIT_BACKGROUND, RAY_TO_REGENERATE rays + * At exit, + * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE and RAY_REGENERATED rays + * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be empty + */ +__kernel void kernel_ocl_path_trace_background_buffer_update( + ccl_global char *globals, + ccl_constant KernelData *data, + ccl_global char *shader_data, + ccl_global float *per_sample_output_buffers, + ccl_global uint *rng_state, + ccl_global uint *rng_coop, /* Required for buffer Update */ + ccl_global float3 *throughput_coop, /* Required for background hit processing */ + PathRadiance *PathRadiance_coop, /* Required for background hit processing and buffer Update */ + ccl_global Ray *Ray_coop, /* Required for background hit processing */ + ccl_global PathState *PathState_coop, /* Required for background hit processing */ + ccl_global float *L_transparent_coop, /* Required for background hit processing and buffer Update */ + ccl_global char *ray_state, /* Stores information on the current state of a ray */ + int sw, int sh, int sx, int sy, int stride, + int rng_state_offset_x, + int rng_state_offset_y, + int rng_state_stride, + ccl_global unsigned int *work_array, /* Denotes work of each ray */ + ccl_global int *Queue_data, /* Queues memory */ + ccl_global int *Queue_index, /* Tracks the number of elements in each queue */ + int queuesize, /* Size (capacity) of each queue */ + int end_sample, + int start_sample, +#ifdef __WORK_STEALING__ + ccl_global unsigned int *work_pool_wgs, + unsigned int num_samples, +#endif +#ifdef __KERNEL_DEBUG__ + DebugData *debugdata_coop, +#endif + int parallel_samples /* Number of samples to be processed in parallel */ + ) +{ + ccl_local unsigned int local_queue_atomics; + if(get_local_id(0) == 0 && get_local_id(1) == 0) { + local_queue_atomics = 0; + } + barrier(CLK_LOCAL_MEM_FENCE); + + int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0); + if(ray_index == 0) { + /* We will empty this queue in this kernel */ + Queue_index[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] = 0; + } + char enqueue_flag = 0; + ray_index = get_ray_index(ray_index, QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS, Queue_data, queuesize, 1); + +#ifdef __COMPUTE_DEVICE_GPU__ + /* If we are executing on a GPU device, we exit all threads that are not required. + * If we are executing on a CPU device, then we need to keep all threads active + * since we have barrier() calls later in the kernel. CPU devices + * expect all threads to execute barrier statement. + */ + if(ray_index == QUEUE_EMPTY_SLOT) + return; +#endif + +#ifndef __COMPUTE_DEVICE_GPU__ + if(ray_index != QUEUE_EMPTY_SLOT) { +#endif + /* Load kernel globals structure and ShaderData strucuture */ + KernelGlobals *kg = (KernelGlobals *)globals; + ShaderData *sd = (ShaderData *)shader_data; + +#ifdef __KERNEL_DEBUG__ + DebugData *debug_data = &debugdata_coop[ray_index]; +#endif + ccl_global PathState *state = &PathState_coop[ray_index]; + PathRadiance *L = L = &PathRadiance_coop[ray_index]; + ccl_global Ray *ray = &Ray_coop[ray_index]; + ccl_global float3 *throughput = &throughput_coop[ray_index]; + ccl_global float *L_transparent = &L_transparent_coop[ray_index]; + ccl_global uint *rng = &rng_coop[ray_index]; + +#ifdef __WORK_STEALING__ + unsigned int my_work; + ccl_global float *initial_per_sample_output_buffers; + ccl_global uint *initial_rng; +#endif + unsigned int sample; + unsigned int tile_x; + unsigned int tile_y; + unsigned int pixel_x; + unsigned int pixel_y; + unsigned int my_sample_tile; + +#ifdef __WORK_STEALING__ + my_work = work_array[ray_index]; + sample = get_my_sample(my_work, sw, sh, parallel_samples, ray_index) + start_sample; + get_pixel_tile_position(&pixel_x, &pixel_y, &tile_x, &tile_y, my_work, sw, sh, sx, sy, parallel_samples, ray_index); + my_sample_tile = 0; + initial_per_sample_output_buffers = per_sample_output_buffers; + initial_rng = rng_state; +#else // __WORK_STEALING__ + sample = work_array[ray_index]; + int tile_index = ray_index / parallel_samples; + /* buffer and rng_state's stride is "stride". Find x and y using ray_index */ + tile_x = tile_index % sw; + tile_y = tile_index / sw; + my_sample_tile = ray_index - (tile_index * parallel_samples); +#endif + rng_state += (rng_state_offset_x + tile_x) + (rng_state_offset_y + tile_y) * rng_state_stride; + per_sample_output_buffers += (((tile_x + (tile_y * stride)) * parallel_samples) + my_sample_tile) * kernel_data.film.pass_stride; + + if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) { + /* eval background shader if nothing hit */ + if(kernel_data.background.transparent && (state->flag & PATH_RAY_CAMERA)) { + *L_transparent = (*L_transparent) + average((*throughput)); +#ifdef __PASSES__ + if(!(kernel_data.film.pass_flag & PASS_BACKGROUND)) +#endif + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); + } + + if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) + { +#ifdef __BACKGROUND__ + /* sample background shader */ + float3 L_background = indirect_background(kg, state, ray, sd); + path_radiance_accum_background(L, (*throughput), L_background, state->bounce); +#endif + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); + } + } + + if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) { + float3 L_sum = path_radiance_clamp_and_sum(kg, L); + kernel_write_light_passes(kg, per_sample_output_buffers, L, sample); +#ifdef __KERNEL_DEBUG__ + kernel_write_debug_passes(kg, per_sample_output_buffers, state, debug_data, sample); +#endif + float4 L_rad = make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - (*L_transparent)); + + /* accumulate result in output buffer */ + kernel_write_pass_float4(per_sample_output_buffers, sample, L_rad); + path_rng_end(kg, rng_state, *rng); + + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE); + } + + if(IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) { +#ifdef __WORK_STEALING__ + /* We have completed current work; So get next work */ + int valid_work = get_next_work(work_pool_wgs, &my_work, sw, sh, num_samples, parallel_samples, ray_index); + if(!valid_work) { + /* If work is invalid, this means no more work is available and the thread may exit */ + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_INACTIVE); + } +#else + if((sample + parallel_samples) >= end_sample) { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_INACTIVE); + } +#endif + if(IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) { +#ifdef __WORK_STEALING__ + work_array[ray_index] = my_work; + /* Get the sample associated with the current work */ + sample = get_my_sample(my_work, sw, sh, parallel_samples, ray_index) + start_sample; + /* Get pixel and tile position associated with current work */ + get_pixel_tile_position(&pixel_x, &pixel_y, &tile_x, &tile_y, my_work, sw, sh, sx, sy, parallel_samples, ray_index); + my_sample_tile = 0; + + /* Remap rng_state according to the current work */ + rng_state = initial_rng + ((rng_state_offset_x + tile_x) + (rng_state_offset_y + tile_y) * rng_state_stride); + /* Remap per_sample_output_buffers according to the current work */ + per_sample_output_buffers = initial_per_sample_output_buffers + + (((tile_x + (tile_y * stride)) * parallel_samples) + my_sample_tile) * kernel_data.film.pass_stride; +#else + work_array[ray_index] = sample + parallel_samples; + sample = work_array[ray_index]; + + /* Get ray position from ray index */ + pixel_x = sx + ((ray_index / parallel_samples) % sw); + pixel_y = sy + ((ray_index / parallel_samples) / sw); +#endif + + /* initialize random numbers and ray */ + kernel_path_trace_setup(kg, rng_state, sample, pixel_x, pixel_y, rng, ray); + + if(ray->t != 0.0f) { + /* Initialize throughput, L_transparent, Ray, PathState; These rays proceed with path-iteration*/ + *throughput = make_float3(1.0f, 1.0f, 1.0f); + *L_transparent = 0.0f; + path_radiance_init(L, kernel_data.film.use_light_pass); + path_state_init(kg, state, rng, sample, ray); +#ifdef __KERNEL_DEBUG__ + debug_data_init(debug_data); +#endif + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED); + enqueue_flag = 1; + } else { + /*These rays do not participate in path-iteration */ + float4 L_rad = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + /* accumulate result in output buffer */ + kernel_write_pass_float4(per_sample_output_buffers, sample, L_rad); + path_rng_end(kg, rng_state, *rng); + + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE); + } + } + } +#ifndef __COMPUTE_DEVICE_GPU__ + } +#endif + + /* Enqueue RAY_REGENERATED rays into QUEUE_ACTIVE_AND_REGENERATED_RAYS; These rays + * will be made active during next SceneIntersectkernel + */ + enqueue_ray_index_local(ray_index, QUEUE_ACTIVE_AND_REGENERATED_RAYS, enqueue_flag, queuesize, &local_queue_atomics, Queue_data, Queue_index); +} diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index 1e81210007c..3ce5134181a 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -39,7 +39,7 @@ ccl_device float2 camera_sample_aperture(KernelGlobals *kg, float u, float v) return bokeh; } -ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, Ray *ray) +ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, ccl_addr_space Ray *ray) { /* create ray form raster position */ Transform rastertocamera = kernel_data.cam.rastertocamera; @@ -108,8 +108,7 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo } /* Orthographic Camera */ - -ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, Ray *ray) +ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, ccl_addr_space Ray *ray) { /* create ray form raster position */ Transform rastertocamera = kernel_data.cam.rastertocamera; @@ -175,7 +174,7 @@ ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, fl /* Panorama Camera */ -ccl_device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, Ray *ray) +ccl_device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, ccl_addr_space Ray *ray) { Transform rastertocamera = kernel_data.cam.rastertocamera; float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f)); @@ -256,7 +255,7 @@ ccl_device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float /* Common */ ccl_device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, float filter_v, - float lens_u, float lens_v, float time, Ray *ray) + float lens_u, float lens_v, float time, ccl_addr_space Ray *ray) { /* pixel filter */ int filter_table_offset = kernel_data.film.filter_table_offset; @@ -319,7 +318,7 @@ ccl_device_inline float3 camera_world_to_ndc(KernelGlobals *kg, ShaderData *sd, { if(kernel_data.cam.type != CAMERA_PANORAMA) { /* perspective / ortho */ - if(sd->object == PRIM_NONE && kernel_data.cam.type == CAMERA_PERSPECTIVE) + if(ccl_fetch(sd, object) == PRIM_NONE && kernel_data.cam.type == CAMERA_PERSPECTIVE) P += camera_position(kg); Transform tfm = kernel_data.cam.worldtondc; @@ -329,7 +328,7 @@ ccl_device_inline float3 camera_world_to_ndc(KernelGlobals *kg, ShaderData *sd, /* panorama */ Transform tfm = kernel_data.cam.worldtocamera; - if(sd->object != OBJECT_NONE) + if(ccl_fetch(sd, object) != OBJECT_NONE) P = normalize(transform_point(&tfm, P)); else P = normalize(transform_direction(&tfm, P)); diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h index b209fff88e6..7a5f70ff3da 100644 --- a/intern/cycles/kernel/kernel_compat_cpu.h +++ b/intern/cycles/kernel/kernel_compat_cpu.h @@ -40,6 +40,8 @@ #include "util_half.h" #include "util_types.h" +#define ccl_addr_space + /* On x86_64, versions of glibc < 2.16 have an issue where expf is * much slower than the double version. This was fixed in glibc 2.16. */ diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h index 61e208fcab3..9fdd3abfec3 100644 --- a/intern/cycles/kernel/kernel_compat_cuda.h +++ b/intern/cycles/kernel/kernel_compat_cuda.h @@ -41,6 +41,7 @@ #define ccl_global #define ccl_constant #define ccl_may_alias +#define ccl_addr_space /* No assert supported for CUDA */ diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h index 12b0f117600..e8b36d2605d 100644 --- a/intern/cycles/kernel/kernel_compat_opencl.h +++ b/intern/cycles/kernel/kernel_compat_opencl.h @@ -40,6 +40,12 @@ #define ccl_local __local #define ccl_private __private +#ifdef __SPLIT_KERNEL__ +#define ccl_addr_space __global +#else +#define ccl_addr_space +#endif + /* Selective nodes compilation. */ #ifndef __NODES_MAX_GROUP__ # define __NODES_MAX_GROUP__ NODE_GROUP_LEVEL_MAX diff --git a/intern/cycles/kernel/kernel_data_init.cl b/intern/cycles/kernel/kernel_data_init.cl new file mode 100644 index 00000000000..dbf9e62ccbf --- /dev/null +++ b/intern/cycles/kernel/kernel_data_init.cl @@ -0,0 +1,384 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kernel_split.h" + +/* + * Note on kernel_ocl_path_trace_data_initialization kernel + * This kernel Initializes structures needed in path-iteration kernels. + * This is the first kernel in ray-tracing logic. + * + * Ray state of rays outside the tile-boundary will be marked RAY_INACTIVE + * + * Its input and output are as follows, + * + * Un-initialized rng---------------|--- kernel_ocl_path_trace_data_initialization ---|--- Initialized rng + * Un-initialized throughput -------| |--- Initialized throughput + * Un-initialized L_transparent ----| |--- Initialized L_transparent + * Un-initialized PathRadiance -----| |--- Initialized PathRadiance + * Un-initialized Ray --------------| |--- Initialized Ray + * Un-initialized PathState --------| |--- Initialized PathState + * Un-initialized QueueData --------| |--- Initialized QueueData (to QUEUE_EMPTY_SLOT) + * Un-initilaized QueueIndex -------| |--- Initialized QueueIndex (to 0) + * Un-initialized use_queues_flag---| |--- Initialized use_queues_flag (to false) + * Un-initialized ray_state --------| |--- Initialized ray_state + * parallel_samples --------------- | |--- Initialized per_sample_output_buffers + * rng_state -----------------------| |--- Initialized work_array + * data ----------------------------| |--- Initialized work_pool_wgs + * start_sample --------------------| | + * sx ------------------------------| | + * sy ------------------------------| | + * sw ------------------------------| | + * sh ------------------------------| | + * stride --------------------------| | + * queuesize -----------------------| | + * num_samples ---------------------| | + * + * Note on Queues : + * All slots in queues are initialized to queue empty slot; + * The number of elements in the queues is initialized to 0; + */ +__kernel void kernel_ocl_path_trace_data_initialization( + ccl_global char *globals, + ccl_global char *shader_data_sd, /* Arguments related to ShaderData */ + ccl_global char *shader_data_sd_DL_shadow, /* Arguments related to ShaderData */ + + ccl_global float3 *P_sd, + ccl_global float3 *P_sd_DL_shadow, + + ccl_global float3 *N_sd, + ccl_global float3 *N_sd_DL_shadow, + + ccl_global float3 *Ng_sd, + ccl_global float3 *Ng_sd_DL_shadow, + + ccl_global float3 *I_sd, + ccl_global float3 *I_sd_DL_shadow, + + ccl_global int *shader_sd, + ccl_global int *shader_sd_DL_shadow, + + ccl_global int *flag_sd, + ccl_global int *flag_sd_DL_shadow, + + ccl_global int *prim_sd, + ccl_global int *prim_sd_DL_shadow, + + ccl_global int *type_sd, + ccl_global int *type_sd_DL_shadow, + + ccl_global float *u_sd, + ccl_global float *u_sd_DL_shadow, + + ccl_global float *v_sd, + ccl_global float *v_sd_DL_shadow, + + ccl_global int *object_sd, + ccl_global int *object_sd_DL_shadow, + + ccl_global float *time_sd, + ccl_global float *time_sd_DL_shadow, + + ccl_global float *ray_length_sd, + ccl_global float *ray_length_sd_DL_shadow, + + ccl_global int *ray_depth_sd, + ccl_global int *ray_depth_sd_DL_shadow, + + ccl_global int *transparent_depth_sd, + ccl_global int *transparent_depth_sd_DL_shadow, + #ifdef __RAY_DIFFERENTIALS__ + ccl_global differential3 *dP_sd, + ccl_global differential3 *dP_sd_DL_shadow, + + ccl_global differential3 *dI_sd, + ccl_global differential3 *dI_sd_DL_shadow, + + ccl_global differential *du_sd, + ccl_global differential *du_sd_DL_shadow, + + ccl_global differential *dv_sd, + ccl_global differential *dv_sd_DL_shadow, + #endif + #ifdef __DPDU__ + ccl_global float3 *dPdu_sd, + ccl_global float3 *dPdu_sd_DL_shadow, + + ccl_global float3 *dPdv_sd, + ccl_global float3 *dPdv_sd_DL_shadow, + #endif + ShaderClosure *closure_sd, + ShaderClosure *closure_sd_DL_shadow, + + ccl_global int *num_closure_sd, + ccl_global int *num_closure_sd_DL_shadow, + + ccl_global float *randb_closure_sd, + ccl_global float *randb_closure_sd_DL_shadow, + + ccl_global float3 *ray_P_sd, + ccl_global float3 *ray_P_sd_DL_shadow, + + ccl_global differential3 *ray_dP_sd, + ccl_global differential3 *ray_dP_sd_DL_shadow, + + ccl_constant KernelData *data, + ccl_global float *per_sample_output_buffers, + ccl_global uint *rng_state, + ccl_global uint *rng_coop, /* rng array to store rng values for all rays */ + ccl_global float3 *throughput_coop, /* throughput array to store throughput values for all rays */ + ccl_global float *L_transparent_coop, /* L_transparent array to store L_transparent values for all rays */ + PathRadiance *PathRadiance_coop, /* PathRadiance array to store PathRadiance values for all rays */ + ccl_global Ray *Ray_coop, /* Ray array to store Ray information for all rays */ + ccl_global PathState *PathState_coop, /* PathState array to store PathState information for all rays */ + ccl_global char *ray_state, /* Stores information on current state of a ray */ + +#define KERNEL_TEX(type, ttype, name) \ + ccl_global type *name, +#include "kernel_textures.h" + + int start_sample, int sx, int sy, int sw, int sh, int offset, int stride, + int rng_state_offset_x, + int rng_state_offset_y, + int rng_state_stride, + ccl_global int *Queue_data, /* Memory for queues */ + ccl_global int *Queue_index, /* Tracks the number of elements in queues */ + int queuesize, /* size (capacity) of the queue */ + ccl_global char *use_queues_flag, /* flag to decide if scene-intersect kernel should use queues to fetch ray index */ + ccl_global unsigned int *work_array, /* work array to store which work each ray belongs to */ +#ifdef __WORK_STEALING__ + ccl_global unsigned int *work_pool_wgs, /* Work pool for each work group */ + unsigned int num_samples, /* Total number of samples per pixel */ +#endif +#ifdef __KERNEL_DEBUG__ + DebugData *debugdata_coop, +#endif + int parallel_samples /* Number of samples to be processed in parallel */ + ) +{ + + /* Load kernel globals structure */ + KernelGlobals *kg = (KernelGlobals *)globals; + + kg->data = data; +#define KERNEL_TEX(type, ttype, name) \ + kg->name = name; +#include "kernel_textures.h" + + /* Load ShaderData structure */ + ShaderData *sd = (ShaderData *)shader_data_sd; + ShaderData *sd_DL_shadow = (ShaderData *)shader_data_sd_DL_shadow; + + sd->P = P_sd; + sd_DL_shadow->P = P_sd_DL_shadow; + + sd->N = N_sd; + sd_DL_shadow->N = N_sd_DL_shadow; + + sd->Ng = Ng_sd; + sd_DL_shadow->Ng = Ng_sd_DL_shadow; + + sd->I = I_sd; + sd_DL_shadow->I = I_sd_DL_shadow; + + sd->shader = shader_sd; + sd_DL_shadow->shader = shader_sd_DL_shadow; + + sd->flag = flag_sd; + sd_DL_shadow->flag = flag_sd_DL_shadow; + + sd->prim = prim_sd; + sd_DL_shadow->prim = prim_sd_DL_shadow; + + sd->type = type_sd; + sd_DL_shadow->type = type_sd_DL_shadow; + + sd->u = u_sd; + sd_DL_shadow->u = u_sd_DL_shadow; + + sd->v = v_sd; + sd_DL_shadow->v = v_sd_DL_shadow; + + sd->object = object_sd; + sd_DL_shadow->object = object_sd_DL_shadow; + + sd->time = time_sd; + sd_DL_shadow->time = time_sd_DL_shadow; + + sd->ray_length = ray_length_sd; + sd_DL_shadow->ray_length = ray_length_sd_DL_shadow; + + sd->ray_depth = ray_depth_sd; + sd_DL_shadow->ray_depth = ray_depth_sd_DL_shadow; + + sd->transparent_depth = transparent_depth_sd; + sd_DL_shadow->transparent_depth = transparent_depth_sd_DL_shadow; + +#ifdef __RAY_DIFFERENTIALS__ + sd->dP = dP_sd; + sd_DL_shadow->dP = dP_sd_DL_shadow; + + sd->dI = dI_sd; + sd_DL_shadow->dI = dI_sd_DL_shadow; + + sd->du = du_sd; + sd_DL_shadow->du = du_sd_DL_shadow; + + sd->dv = dv_sd; + sd_DL_shadow->dv = dv_sd_DL_shadow; +#ifdef __DPDU__ + sd->dPdu = dPdu_sd; + sd_DL_shadow->dPdu = dPdu_sd_DL_shadow; + + sd->dPdv = dPdv_sd; + sd_DL_shadow->dPdv = dPdv_sd_DL_shadow; +#endif +#endif + + sd->closure = closure_sd; + sd_DL_shadow->closure = closure_sd_DL_shadow; + + sd->num_closure = num_closure_sd; + sd_DL_shadow->num_closure = num_closure_sd_DL_shadow; + + sd->randb_closure = randb_closure_sd; + sd_DL_shadow->randb_closure = randb_closure_sd_DL_shadow; + + sd->ray_P = ray_P_sd; + sd_DL_shadow->ray_P = ray_P_sd_DL_shadow; + + sd->ray_dP = ray_dP_sd; + sd_DL_shadow->ray_dP = ray_dP_sd_DL_shadow; + + int thread_index = get_global_id(1) * get_global_size(0) + get_global_id(0); + +#ifdef __WORK_STEALING__ + int lid = get_local_id(1) * get_local_size(0) + get_local_id(0); + /* Initialize work_pool_wgs */ + if(lid == 0) { + int group_index = get_group_id(1) * get_num_groups(0) + get_group_id(0); + work_pool_wgs[group_index] = 0; + } + barrier(CLK_LOCAL_MEM_FENCE); +#endif // __WORK_STEALING__ + + /* Initialize queue data and queue index */ + if(thread_index < queuesize) { + /* Initialize active ray queue */ + Queue_data[QUEUE_ACTIVE_AND_REGENERATED_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT; + /* Initialize background and buffer update queue */ + Queue_data[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT; + /* Initialize shadow ray cast of AO queue */ + Queue_data[QUEUE_SHADOW_RAY_CAST_AO_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT; + /* Initialize shadow ray cast of direct lighting queue */ + Queue_data[QUEUE_SHADOW_RAY_CAST_DL_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT; + } + + if(thread_index == 0) { + Queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = 0; + Queue_index[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] = 0; + Queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS] = 0; + Queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS] = 0; + /* The scene-intersect kernel should not use the queues very first time. + * since the queue would be empty. + */ + use_queues_flag[0] = 0; + } + + int x = get_global_id(0); + int y = get_global_id(1); + + if(x < (sw * parallel_samples) && y < sh) { + + int ray_index = x + y * (sw * parallel_samples); + + /* This is the first assignment to ray_state; So we dont use ASSIGN_RAY_STATE macro */ + ray_state[ray_index] = RAY_ACTIVE; + + unsigned int my_sample; + unsigned int pixel_x; + unsigned int pixel_y; + unsigned int tile_x; + unsigned int tile_y; + unsigned int my_sample_tile; + +#ifdef __WORK_STEALING__ + unsigned int my_work = 0; + /* get work */ + get_next_work(work_pool_wgs, &my_work, sw, sh, num_samples, parallel_samples, ray_index); + /* Get the sample associated with the work */ + my_sample = get_my_sample(my_work, sw, sh, parallel_samples, ray_index) + start_sample; + + my_sample_tile = 0; + + /* Get pixel and tile position associated with the work */ + get_pixel_tile_position(&pixel_x, &pixel_y, &tile_x, &tile_y, my_work, sw, sh, sx, sy, parallel_samples, ray_index); + work_array[ray_index] = my_work; +#else // __WORK_STEALING__ + + unsigned int tile_index = ray_index / parallel_samples; + tile_x = tile_index % sw; + tile_y = tile_index / sw; + my_sample_tile = ray_index - (tile_index * parallel_samples); + my_sample = my_sample_tile + start_sample; + + /* Initialize work array */ + work_array[ray_index] = my_sample ; + + /* Calculate pixel position of this ray */ + pixel_x = sx + tile_x; + pixel_y = sy + tile_y; +#endif // __WORK_STEALING__ + + rng_state += (rng_state_offset_x + tile_x) + (rng_state_offset_y + tile_y) * rng_state_stride; + + /* Initialise per_sample_output_buffers to all zeros */ + per_sample_output_buffers += (((tile_x + (tile_y * stride)) * parallel_samples) + (my_sample_tile)) * kernel_data.film.pass_stride; + int per_sample_output_buffers_iterator = 0; + for(per_sample_output_buffers_iterator = 0; per_sample_output_buffers_iterator < kernel_data.film.pass_stride; per_sample_output_buffers_iterator++) { + per_sample_output_buffers[per_sample_output_buffers_iterator] = 0.0f; + } + + /* initialize random numbers and ray */ + kernel_path_trace_setup(kg, rng_state, my_sample, pixel_x, pixel_y, &rng_coop[ray_index], &Ray_coop[ray_index]); + + if(Ray_coop[ray_index].t != 0.0f) { + /* Initialize throuput, L_transparent, Ray, PathState; These rays proceed with path-iteration*/ + throughput_coop[ray_index] = make_float3(1.0f, 1.0f, 1.0f); + L_transparent_coop[ray_index] = 0.0f; + path_radiance_init(&PathRadiance_coop[ray_index], kernel_data.film.use_light_pass); + path_state_init(kg, &PathState_coop[ray_index], &rng_coop[ray_index], my_sample, &Ray_coop[ray_index]); +#ifdef __KERNEL_DEBUG__ + debug_data_init(&debugdata_coop[ray_index]); +#endif + } else { + /*These rays do not participate in path-iteration */ + + float4 L_rad = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + /* accumulate result in output buffer */ + kernel_write_pass_float4(per_sample_output_buffers, my_sample, L_rad); + path_rng_end(kg, rng_state, rng_coop[ray_index]); + + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE); + } + } + + /* Mark rest of the ray-state indices as RAY_INACTIVE */ + if(thread_index < (get_global_size(0) * get_global_size(1)) - (sh * (sw * parallel_samples))) { + /* First assignment, hence we dont use ASSIGN_RAY_STATE macro */ + ray_state[((sw * parallel_samples) * sh) + thread_index] = RAY_INACTIVE; + } +} diff --git a/intern/cycles/kernel/kernel_debug.h b/intern/cycles/kernel/kernel_debug.h index f532442ba41..94ede397848 100644 --- a/intern/cycles/kernel/kernel_debug.h +++ b/intern/cycles/kernel/kernel_debug.h @@ -23,7 +23,7 @@ ccl_device_inline void debug_data_init(DebugData *debug_data) ccl_device_inline void kernel_write_debug_passes(KernelGlobals *kg, ccl_global float *buffer, - PathState *state, + ccl_addr_space PathState *state, DebugData *debug_data, int sample) { diff --git a/intern/cycles/kernel/kernel_differential.h b/intern/cycles/kernel/kernel_differential.h index e5fbd5b450e..ae1e70f0167 100644 --- a/intern/cycles/kernel/kernel_differential.h +++ b/intern/cycles/kernel/kernel_differential.h @@ -18,7 +18,7 @@ CCL_NAMESPACE_BEGIN /* See "Tracing Ray Differentials", Homan Igehy, 1999. */ -ccl_device void differential_transfer(differential3 *dP_, const differential3 dP, float3 D, const differential3 dD, float3 Ng, float t) +ccl_device void differential_transfer(ccl_addr_space differential3 *dP_, const differential3 dP, float3 D, const differential3 dD, float3 Ng, float t) { /* ray differential transfer through homogeneous medium, to * compute dPdx/dy at a shading point from the incoming ray */ @@ -31,7 +31,7 @@ ccl_device void differential_transfer(differential3 *dP_, const differential3 dP dP_->dy = tmpy - dot(tmpy, Ng)*tmp; } -ccl_device void differential_incoming(differential3 *dI, const differential3 dD) +ccl_device void differential_incoming(ccl_addr_space differential3 *dI, const differential3 dD) { /* compute dIdx/dy at a shading point, we just need to negate the * differential of the ray direction */ @@ -40,7 +40,7 @@ ccl_device void differential_incoming(differential3 *dI, const differential3 dD) dI->dy = -dD.dy; } -ccl_device void differential_dudv(differential *du, differential *dv, float3 dPdu, float3 dPdv, differential3 dP, float3 Ng) +ccl_device void differential_dudv(ccl_addr_space differential *du, ccl_addr_space differential *dv, float3 dPdu, float3 dPdv, differential3 dP, float3 Ng) { /* now we have dPdx/dy from the ray differential transfer, and dPdu/dv * from the primitive, we can compute dudx/dy and dvdx/dy. these are diff --git a/intern/cycles/kernel/kernel_direct_lighting.cl b/intern/cycles/kernel/kernel_direct_lighting.cl new file mode 100644 index 00000000000..8bdc7dc0fd1 --- /dev/null +++ b/intern/cycles/kernel/kernel_direct_lighting.cl @@ -0,0 +1,137 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kernel_split.h" + +/* + * Note on kernel_ocl_path_trace_direct_lighting kernel. + * This is the eighth kernel in the ray tracing logic. This is the seventh + * of the path iteration kernels. This kernel takes care of direct lighting + * logic. However, the "shadow ray cast" part of direct lighting is handled + * in the next kernel. + * + * This kernels determines the rays for which a shadow_blocked() function associated with direct lighting should be executed. + * Those rays for which a shadow_blocked() function for direct-lighting must be executed, are marked with flag RAY_SHADOW_RAY_CAST_DL and + * enqueued into the queue QUEUE_SHADOW_RAY_CAST_DL_RAYS + * + * The input and output are as follows, + * + * rng_coop -----------------------------------------|--- kernel_ocl_path_trace_direct_lighting --|--- BSDFEval_coop + * PathState_coop -----------------------------------| |--- ISLamp_coop + * shader_data --------------------------------------| |--- LightRay_coop + * ray_state ----------------------------------------| |--- ray_state + * Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS) ---| | + * kg (globals + data) ------------------------------| | + * queuesize ----------------------------------------| | + * + * note on shader_DL : shader_DL is neither input nor output to this kernel; shader_DL is filled and consumed in this kernel itself. + * Note on Queues : + * This kernel only reads from the QUEUE_ACTIVE_AND_REGENERATED_RAYS queue and processes + * only the rays of state RAY_ACTIVE; If a ray needs to execute the corresponding shadow_blocked + * part, after direct lighting, the ray is marked with RAY_SHADOW_RAY_CAST_DL flag. + * + * State of queues when this kernel is called : + * state of queues QUEUE_ACTIVE_AND_REGENERATED_RAYS and QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be same + * before and after this kernel call. + * QUEUE_SHADOW_RAY_CAST_DL_RAYS queue will be filled with rays for which a shadow_blocked function must be executed, after this + * kernel call. Before this kernel call the QUEUE_SHADOW_RAY_CAST_DL_RAYS will be empty. + */ +__kernel void kernel_ocl_path_trace_direct_lighting( + ccl_global char *globals, + ccl_constant KernelData *data, + ccl_global char *shader_data, /* Required for direct lighting */ + ccl_global char *shader_DL, /* Required for direct lighting */ + ccl_global uint *rng_coop, /* Required for direct lighting */ + ccl_global PathState *PathState_coop, /* Required for direct lighting */ + ccl_global int *ISLamp_coop, /* Required for direct lighting */ + ccl_global Ray *LightRay_coop, /* Required for direct lighting */ + ccl_global BsdfEval *BSDFEval_coop, /* Required for direct lighting */ + ccl_global char *ray_state, /* Denotes the state of each ray */ + ccl_global int *Queue_data, /* Queue memory */ + ccl_global int *Queue_index, /* Tracks the number of elements in each queue */ + int queuesize /* Size (capacity) of each queue */ + ) +{ + ccl_local unsigned int local_queue_atomics; + if(get_local_id(0) == 0 && get_local_id(1) == 0) { + local_queue_atomics = 0; + } + barrier(CLK_LOCAL_MEM_FENCE); + + char enqueue_flag = 0; + int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0); + ray_index = get_ray_index(ray_index, QUEUE_ACTIVE_AND_REGENERATED_RAYS, Queue_data, queuesize, 0); + +#ifdef __COMPUTE_DEVICE_GPU__ + /* If we are executing on a GPU device, we exit all threads that are not required + * If we are executing on a CPU device, then we need to keep all threads active + * since we have barrier() calls later in the kernel. CPU devices, + * expect all threads to execute barrier statement. + */ + if(ray_index == QUEUE_EMPTY_SLOT) + return; +#endif + +#ifndef __COMPUTE_DEVICE_GPU__ + if(ray_index != QUEUE_EMPTY_SLOT) { +#endif + if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { + /* Load kernel globals structure and ShaderData structure */ + KernelGlobals *kg = (KernelGlobals *)globals; + ShaderData *sd = (ShaderData *)shader_data; + ShaderData *sd_DL = (ShaderData *)shader_DL; + + ccl_global PathState *state = &PathState_coop[ray_index]; + + /* direct lighting */ +#ifdef __EMISSION__ + if((kernel_data.integrator.use_direct_light && (ccl_fetch(sd, flag) & SD_BSDF_HAS_EVAL))) { + /* sample illumination from lights to find path contribution */ + ccl_global RNG* rng = &rng_coop[ray_index]; + float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT); + float light_u, light_v; + path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v); + +#ifdef __OBJECT_MOTION__ + light_ray.time = sd->time; +#endif + LightSample ls; + light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls); + + Ray light_ray; + BsdfEval L_light; + bool is_lamp; + if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce, sd_DL)) { + /* write intermediate data to global memory to access from the next kernel */ + LightRay_coop[ray_index] = light_ray; + BSDFEval_coop[ray_index] = L_light; + ISLamp_coop[ray_index] = is_lamp; + /// mark ray state for next shadow kernel + ADD_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL); + enqueue_flag = 1; + } + } +#endif + } +#ifndef __COMPUTE_DEVICE_GPU__ + } +#endif + +#ifdef __EMISSION__ + /* Enqueue RAY_SHADOW_RAY_CAST_DL rays */ + enqueue_ray_index_local(ray_index, QUEUE_SHADOW_RAY_CAST_DL_RAYS, enqueue_flag, queuesize, &local_queue_atomics, Queue_data, Queue_index); +#endif +} diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 6c5a5fac8c5..1fee5835360 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -17,12 +17,20 @@ CCL_NAMESPACE_BEGIN /* Direction Emission */ - ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg, - LightSample *ls, float3 I, differential3 dI, float t, float time, int bounce, int transparent_bounce) + LightSample *ls, float3 I, differential3 dI, float t, float time, int bounce, int transparent_bounce +#ifdef __SPLIT_KERNEL__ + ,ShaderData *sd_input +#endif +) { /* setup shading at emitter */ - ShaderData sd; +#ifdef __SPLIT_KERNEL__ + ShaderData *sd = sd_input; +#else + ShaderData sd_object; + ShaderData *sd = &sd_object; +#endif float3 eval; #ifdef __BACKGROUND_MIS__ @@ -37,23 +45,23 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg, ray.dP = differential3_zero(); ray.dD = dI; - shader_setup_from_background(kg, &sd, &ray, bounce+1, transparent_bounce); - eval = shader_eval_background(kg, &sd, 0, SHADER_CONTEXT_EMISSION); + shader_setup_from_background(kg, sd, &ray, bounce+1, transparent_bounce); + eval = shader_eval_background(kg, sd, 0, SHADER_CONTEXT_EMISSION); } else #endif { - shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, ls->u, ls->v, t, time, bounce+1, transparent_bounce); + shader_setup_from_sample(kg, sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, ls->u, ls->v, t, time, bounce+1, transparent_bounce); - ls->Ng = sd.Ng; + ls->Ng = ccl_fetch(sd, Ng); /* no path flag, we're evaluating this for all closures. that's weak but * we'd have to do multiple evaluations otherwise */ - shader_eval_surface(kg, &sd, 0.0f, 0, SHADER_CONTEXT_EMISSION); + shader_eval_surface(kg, sd, 0.0f, 0, SHADER_CONTEXT_EMISSION); /* evaluate emissive closure */ - if(sd.flag & SD_EMISSION) - eval = shader_emissive_eval(kg, &sd); + if(ccl_fetch(sd, flag) & SD_EMISSION) + eval = shader_emissive_eval(kg, sd); else eval = make_float3(0.0f, 0.0f, 0.0f); } @@ -63,9 +71,14 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg, return eval; } +/* The argument sd_DL is meaningful only for split kernel. Other uses can just pass NULL */ ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, LightSample *ls, Ray *ray, BsdfEval *eval, bool *is_lamp, - int bounce, int transparent_bounce) + int bounce, int transparent_bounce +#ifdef __SPLIT_KERNEL__ + , ShaderData *sd_DL +#endif + ) { if(ls->pdf == 0.0f) return false; @@ -74,7 +87,14 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, differential3 dD = differential3_zero(); /* evaluate closure */ - float3 light_eval = direct_emissive_eval(kg, ls, -ls->D, dD, ls->t, sd->time, bounce, transparent_bounce); + + float3 light_eval = direct_emissive_eval(kg, ls, -ls->D, dD, ls->t, ccl_fetch(sd, time), + bounce, + transparent_bounce +#ifdef __SPLIT_KERNEL__ + ,sd_DL +#endif + ); if(is_zero(light_eval)) return false; @@ -83,7 +103,7 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, float bsdf_pdf; #ifdef __VOLUME__ - if(sd->prim != PRIM_NONE) + if(ccl_fetch(sd, prim) != PRIM_NONE) shader_bsdf_eval(kg, sd, ls->D, eval, &bsdf_pdf); else shader_volume_phase_eval(kg, sd, ls->D, eval, &bsdf_pdf); @@ -118,8 +138,8 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, if(ls->shader & SHADER_CAST_SHADOW) { /* setup ray */ - bool transmit = (dot(sd->Ng, ls->D) < 0.0f); - ray->P = ray_offset(sd->P, (transmit)? -sd->Ng: sd->Ng); + bool transmit = (dot(ccl_fetch(sd, Ng), ls->D) < 0.0f); + ray->P = ray_offset(ccl_fetch(sd, P), (transmit)? -ccl_fetch(sd, Ng): ccl_fetch(sd, Ng)); if(ls->t == FLT_MAX) { /* distant light */ @@ -132,7 +152,7 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, ray->D = normalize_len(ray->D, &ray->t); } - ray->dP = sd->dP; + ray->dP = ccl_fetch(sd, dP); ray->dD = differential3_zero(); } else { @@ -154,14 +174,14 @@ ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, Shader float3 L = shader_emissive_eval(kg, sd); #ifdef __HAIR__ - if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) && (sd->type & PRIMITIVE_ALL_TRIANGLE)) + if(!(path_flag & PATH_RAY_MIS_SKIP) && (ccl_fetch(sd, flag) & SD_USE_MIS) && (ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE)) #else - if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS)) + if(!(path_flag & PATH_RAY_MIS_SKIP) && (ccl_fetch(sd, flag) & SD_USE_MIS)) #endif { /* multiple importance sampling, get triangle light pdf, * and compute weight with respect to BSDF pdf */ - float pdf = triangle_light_pdf(kg, sd->Ng, sd->I, t); + float pdf = triangle_light_pdf(kg, ccl_fetch(sd, Ng), ccl_fetch(sd, I), t); float mis_weight = power_heuristic(bsdf_pdf, pdf); return L*mis_weight; @@ -172,7 +192,12 @@ ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, Shader /* Indirect Lamp Emission */ -ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg, PathState *state, Ray *ray, float3 *emission) +/* The argument sd is meaningful only for split kernel. Other uses can just pass NULL */ +ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg, PathState *state, Ray *ray, float3 *emission +#ifdef __SPLIT_KERNEL__ + ,ShaderData *sd +#endif + ) { bool hit_lamp = false; @@ -196,7 +221,13 @@ ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg, PathState *st } #endif - float3 L = direct_emissive_eval(kg, &ls, -ray->D, ray->dD, ls.t, ray->time, state->bounce, state->transparent_bounce); + float3 L = direct_emissive_eval(kg, &ls, -ray->D, ray->dD, ls.t, ray->time, + state->bounce, + state->transparent_bounce +#ifdef __SPLIT_KERNEL__ + ,sd +#endif + ); #ifdef __VOLUME__ if(state->volume_stack[0].shader != SHADER_NONE) { @@ -225,7 +256,11 @@ ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg, PathState *st /* Indirect Background */ -ccl_device_noinline float3 indirect_background(KernelGlobals *kg, PathState *state, Ray *ray) +ccl_device_noinline float3 indirect_background(KernelGlobals *kg, ccl_addr_space PathState *state, ccl_addr_space Ray *ray +#ifdef __SPLIT_KERNEL__ + ,ShaderData *sd_global +#endif + ) { #ifdef __BACKGROUND__ int shader = kernel_data.background.surface_shader; @@ -241,11 +276,17 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg, PathState *sta return make_float3(0.0f, 0.0f, 0.0f); } +#ifdef __SPLIT_KERNEL__ /* evaluate background closure */ + Ray priv_ray = *ray; + shader_setup_from_background(kg, sd_global, &priv_ray, state->bounce+1, state->transparent_bounce); + float3 L = shader_eval_background(kg, sd_global, state->flag, SHADER_CONTEXT_EMISSION); +#else ShaderData sd; shader_setup_from_background(kg, &sd, ray, state->bounce+1, state->transparent_bounce); float3 L = shader_eval_background(kg, &sd, state->flag, SHADER_CONTEXT_EMISSION); +#endif #ifdef __BACKGROUND_MIS__ /* check if background light exists or if we should skip pdf */ diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h index be2c879adb9..17fa18909c4 100644 --- a/intern/cycles/kernel/kernel_globals.h +++ b/intern/cycles/kernel/kernel_globals.h @@ -80,7 +80,7 @@ typedef struct KernelGlobals {} KernelGlobals; #ifdef __KERNEL_OPENCL__ -typedef struct KernelGlobals { +typedef ccl_addr_space struct KernelGlobals { ccl_constant KernelData *data; #define KERNEL_TEX(type, ttype, name) \ diff --git a/intern/cycles/kernel/kernel_holdout_emission_blurring_pathtermination_ao.cl b/intern/cycles/kernel/kernel_holdout_emission_blurring_pathtermination_ao.cl new file mode 100644 index 00000000000..a2e57771522 --- /dev/null +++ b/intern/cycles/kernel/kernel_holdout_emission_blurring_pathtermination_ao.cl @@ -0,0 +1,283 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kernel_split.h" + +/* + * Note on kernel_ocl_path_trace_holdout_emission_blurring_pathtermination_ao kernel. + * This is the sixth kernel in the ray tracing logic. This is the fifth + * of the path iteration kernels. This kernel takes care of the logic to process + * "material of type holdout", indirect primitive emission, bsdf blurring, + * probabilistic path termination and AO. + * + * This kernels determines the rays for which a shadow_blocked() function associated with AO should be executed. + * Those rays for which a shadow_blocked() function for AO must be executed are marked with flag RAY_SHADOW_RAY_CAST_ao and + * enqueued into the queue QUEUE_SHADOW_RAY_CAST_AO_RAYS + * + * Ray state of rays that are terminated in this kernel are changed to RAY_UPDATE_BUFFER + * + * The input and output are as follows, + * + * rng_coop ---------------------------------------------|--- kernel_ocl_path_trace_holdout_emission_blurring_pathtermination_ao ---|--- Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) + * throughput_coop --------------------------------------| |--- PathState_coop + * PathRadiance_coop ------------------------------------| |--- throughput_coop + * Intersection_coop ------------------------------------| |--- L_transparent_coop + * PathState_coop ---------------------------------------| |--- per_sample_output_buffers + * L_transparent_coop -----------------------------------| |--- PathRadiance_coop + * shader_data ------------------------------------------| |--- ShaderData + * ray_state --------------------------------------------| |--- ray_state + * Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS) -------| |--- Queue_data (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) + * Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) ---| |--- AOAlpha_coop + * kg (globals + data) ----------------------------------| |--- AOBSDF_coop + * parallel_samples -------------------------------------| |--- AOLightRay_coop + * per_sample_output_buffers ----------------------------| | + * sw ---------------------------------------------------| | + * sh ---------------------------------------------------| | + * sx ---------------------------------------------------| | + * sy ---------------------------------------------------| | + * stride -----------------------------------------------| | + * work_array -------------------------------------------| | + * queuesize --------------------------------------------| | + * start_sample -----------------------------------------| | + * + * Note on Queues : + * This kernel fetches rays from the queue QUEUE_ACTIVE_AND_REGENERATED_RAYS and processes only + * the rays of state RAY_ACTIVE. + * There are different points in this kernel where a ray may terminate and reach RAY_UPDATE_BUFFER + * state. These rays are enqueued into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. These rays will + * still be present in QUEUE_ACTIVE_AND_REGENERATED_RAYS queue, but since their ray-state has been + * changed to RAY_UPDATE_BUFFER, there is no problem. + * + * State of queues when this kernel is called : + * At entry, + * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE and RAY_REGENERATED rays + * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE rays. + * QUEUE_SHADOW_RAY_CAST_AO_RAYS will be empty. + * At exit, + * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE, RAY_REGENERATED and RAY_UPDATE_BUFFER rays + * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE and RAY_UPDATE_BUFFER rays + * QUEUE_SHADOW_RAY_CAST_AO_RAYS will be filled with rays marked with flag RAY_SHADOW_RAY_CAST_AO + */ + +__kernel void kernel_ocl_path_trace_holdout_emission_blurring_pathtermination_ao( + ccl_global char *globals, + ccl_constant KernelData *data, + ccl_global char *shader_data, /* Required throughout the kernel except probabilistic path termination and AO */ + ccl_global float *per_sample_output_buffers, + ccl_global uint *rng_coop, /* Required for "kernel_write_data_passes" and AO */ + ccl_global float3 *throughput_coop, /* Required for handling holdout material and AO */ + ccl_global float *L_transparent_coop, /* Required for handling holdout material */ + PathRadiance *PathRadiance_coop, /* Required for "kernel_write_data_passes" and indirect primitive emission */ + ccl_global PathState *PathState_coop, /* Required throughout the kernel and AO */ + Intersection *Intersection_coop, /* Required for indirect primitive emission */ + ccl_global float3 *AOAlpha_coop, /* Required for AO */ + ccl_global float3 *AOBSDF_coop, /* Required for AO */ + ccl_global Ray *AOLightRay_coop, /* Required for AO */ + int sw, int sh, int sx, int sy, int stride, + ccl_global char *ray_state, /* Denotes the state of each ray */ + ccl_global unsigned int *work_array, /* Denotes the work that each ray belongs to */ + ccl_global int *Queue_data, /* Queue memory */ + ccl_global int *Queue_index, /* Tracks the number of elements in each queue */ + int queuesize, /* Size (capacity) of each queue */ +#ifdef __WORK_STEALING__ + unsigned int start_sample, +#endif + int parallel_samples /* Number of samples to be processed in parallel */ + ) +{ + ccl_local unsigned int local_queue_atomics_bg; + ccl_local unsigned int local_queue_atomics_ao; + if(get_local_id(0) == 0 && get_local_id(1) == 0) { + local_queue_atomics_bg = 0; + local_queue_atomics_ao = 0; + } + barrier(CLK_LOCAL_MEM_FENCE); + + char enqueue_flag = 0; + char enqueue_flag_AO_SHADOW_RAY_CAST = 0; + int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0); + ray_index = get_ray_index(ray_index, QUEUE_ACTIVE_AND_REGENERATED_RAYS, Queue_data, queuesize, 0); + +#ifdef __COMPUTE_DEVICE_GPU__ + /* If we are executing on a GPU device, we exit all threads that are not required + * If we are executing on a CPU device, then we need to keep all threads active + * since we have barrier() calls later in the kernel. CPU devices + * expect all threads to execute barrier statement. + */ + if(ray_index == QUEUE_EMPTY_SLOT) + return; +#endif + +#ifndef __COMPUTE_DEVICE_GPU__ + if(ray_index != QUEUE_EMPTY_SLOT) { +#endif + /* Load kernel globals structure and ShaderData structure */ + KernelGlobals *kg = (KernelGlobals *)globals; + ShaderData *sd = (ShaderData *)shader_data; + +#ifdef __WORK_STEALING__ + unsigned int my_work; + unsigned int pixel_x; + unsigned int pixel_y; +#endif + unsigned int tile_x; + unsigned int tile_y; + int my_sample_tile; + unsigned int sample; + + ccl_global RNG *rng = 0x0; + ccl_global PathState *state = 0x0; + float3 throughput; + + if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { + + throughput = throughput_coop[ray_index]; + state = &PathState_coop[ray_index]; + rng = &rng_coop[ray_index]; +#ifdef __WORK_STEALING__ + my_work = work_array[ray_index]; + sample = get_my_sample(my_work, sw, sh, parallel_samples, ray_index) + start_sample; + get_pixel_tile_position(&pixel_x, &pixel_y, &tile_x, &tile_y, my_work, sw, sh, sx, sy, parallel_samples, ray_index); + my_sample_tile = 0; +#else // __WORK_STEALING__ + sample = work_array[ray_index]; + /* buffer's stride is "stride"; Find x and y using ray_index */ + int tile_index = ray_index / parallel_samples; + tile_x = tile_index % sw; + tile_y = tile_index / sw; + my_sample_tile = ray_index - (tile_index * parallel_samples); +#endif // __WORK_STEALING__ + per_sample_output_buffers += (((tile_x + (tile_y * stride)) * parallel_samples) + my_sample_tile) * kernel_data.film.pass_stride; + + /* holdout */ +#ifdef __HOLDOUT__ + if((ccl_fetch(sd, flag) & (SD_HOLDOUT|SD_HOLDOUT_MASK)) && (state->flag & PATH_RAY_CAMERA)) { + if(kernel_data.background.transparent) { + float3 holdout_weight; + + if(ccl_fetch(sd, flag) & SD_HOLDOUT_MASK) + holdout_weight = make_float3(1.0f, 1.0f, 1.0f); + else + holdout_weight = shader_holdout_eval(kg, sd); + + /* any throughput is ok, should all be identical here */ + L_transparent_coop[ray_index] += average(holdout_weight*throughput); + } + + if(ccl_fetch(sd, flag) & SD_HOLDOUT_MASK) { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); + enqueue_flag = 1; + } + } +#endif + } + + if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { + + PathRadiance *L = &PathRadiance_coop[ray_index]; + /* holdout mask objects do not write data passes */ + kernel_write_data_passes(kg, per_sample_output_buffers, L, sd, sample, state, throughput); + + /* blurring of bsdf after bounces, for rays that have a small likelihood + * of following this particular path (diffuse, rough glossy) */ + if(kernel_data.integrator.filter_glossy != FLT_MAX) { + float blur_pdf = kernel_data.integrator.filter_glossy*state->min_ray_pdf; + + if(blur_pdf < 1.0f) { + float blur_roughness = sqrtf(1.0f - blur_pdf)*0.5f; + shader_bsdf_blur(kg, sd, blur_roughness); + } + } + +#ifdef __EMISSION__ + /* emission */ + if(ccl_fetch(sd, flag) & SD_EMISSION) { + /* todo: is isect.t wrong here for transparent surfaces? */ + float3 emission = indirect_primitive_emission(kg, sd, Intersection_coop[ray_index].t, state->flag, state->ray_pdf); + path_radiance_accum_emission(L, throughput, emission, state->bounce); + } +#endif + + /* path termination. this is a strange place to put the termination, it's + * mainly due to the mixed in MIS that we use. gives too many unneeded + * shader evaluations, only need emission if we are going to terminate */ + float probability = path_state_terminate_probability(kg, state, throughput); + + if(probability == 0.0f) { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); + enqueue_flag = 1; + } + + if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { + if(probability != 1.0f) { + float terminate = path_state_rng_1D_for_decision(kg, rng, state, PRNG_TERMINATE); + + if(terminate >= probability) { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); + enqueue_flag = 1; + } else { + throughput_coop[ray_index] = throughput/probability; + } + } + } + } + +#ifdef __AO__ + if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { + /* ambient occlusion */ + if(kernel_data.integrator.use_ambient_occlusion || (ccl_fetch(sd, flag) & SD_AO)) { + /* todo: solve correlation */ + float bsdf_u, bsdf_v; + path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v); + + float ao_factor = kernel_data.background.ao_factor; + float3 ao_N; + AOBSDF_coop[ray_index] = shader_bsdf_ao(kg, sd, ao_factor, &ao_N); + AOAlpha_coop[ray_index] = shader_bsdf_alpha(kg, sd); + + float3 ao_D; + float ao_pdf; + sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); + + if(dot(ccl_fetch(sd, Ng), ao_D) > 0.0f && ao_pdf != 0.0f) { + Ray _ray; + _ray.P = ray_offset(ccl_fetch(sd, P), ccl_fetch(sd, Ng)); + _ray.D = ao_D; + _ray.t = kernel_data.background.ao_distance; +#ifdef __OBJECT_MOTION__ + _ray.time = ccl_fetch(sd, time); +#endif + _ray.dP = ccl_fetch(sd, dP); + _ray.dD = differential3_zero(); + AOLightRay_coop[ray_index] = _ray; + + ADD_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO); + enqueue_flag_AO_SHADOW_RAY_CAST = 1; + } + } + } +#endif +#ifndef __COMPUTE_DEVICE_GPU__ + } +#endif + + /* Enqueue RAY_UPDATE_BUFFER rays */ + enqueue_ray_index_local(ray_index, QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS, enqueue_flag, queuesize, &local_queue_atomics_bg, Queue_data, Queue_index); +#ifdef __AO__ + /* Enqueue to-shadow-ray-cast rays */ + enqueue_ray_index_local(ray_index, QUEUE_SHADOW_RAY_CAST_AO_RAYS, enqueue_flag_AO_SHADOW_RAY_CAST, queuesize, &local_queue_atomics_ao, Queue_data, Queue_index); +#endif +} diff --git a/intern/cycles/kernel/kernel_lamp_emission.cl b/intern/cycles/kernel/kernel_lamp_emission.cl new file mode 100644 index 00000000000..e7f8b227dd8 --- /dev/null +++ b/intern/cycles/kernel/kernel_lamp_emission.cl @@ -0,0 +1,209 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kernel_split.h" + +/* + * Note on kernel_ocl_path_trace_lamp_emission + * This is the 3rd kernel in the ray-tracing logic. This is the second of the + * path-iteration kernels. This kernel takes care of the indirect lamp emission logic. + * This kernel operates on QUEUE_ACTIVE_AND_REGENERATED_RAYS. It processes rays of state RAY_ACTIVE + * and RAY_HIT_BACKGROUND. + * We will empty QUEUE_ACTIVE_AND_REGENERATED_RAYS queue in this kernel. + * The input/output of the kernel is as follows, + * Throughput_coop ------------------------------------|--- kernel_ocl_path_trace_lamp_emission --|--- PathRadiance_coop + * Ray_coop -------------------------------------------| |--- Queue_data(QUEUE_ACTIVE_AND_REGENERATED_RAYS) + * PathState_coop -------------------------------------| |--- Queue_index(QUEUE_ACTIVE_AND_REGENERATED_RAYS) + * kg (globals + data) --------------------------------| | + * Intersection_coop ----------------------------------| | + * ray_state ------------------------------------------| | + * Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS) -----| | + * Queue_index (QUEUE_ACTIVE_AND_REGENERATED_RAYS) ----| | + * queuesize ------------------------------------------| | + * use_queues_flag ------------------------------------| | + * sw -------------------------------------------------| | + * sh -------------------------------------------------| | + * parallel_samples -----------------------------------| | + * + * note : shader_data is neither input nor output. Its just filled and consumed in the same, kernel_ocl_path_trace_lamp_emission, kernel. + */ +__kernel void kernel_ocl_path_trace_lamp_emission( + ccl_global char *globals, + ccl_constant KernelData *data, + ccl_global char *shader_data, /* Required for lamp emission */ + ccl_global float3 *throughput_coop, /* Required for lamp emission */ + PathRadiance *PathRadiance_coop, /* Required for lamp emission */ + ccl_global Ray *Ray_coop, /* Required for lamp emission */ + ccl_global PathState *PathState_coop, /* Required for lamp emission */ + Intersection *Intersection_coop, /* Required for lamp emission */ + ccl_global char *ray_state, /* Denotes the state of each ray */ + int sw, int sh, + ccl_global int *Queue_data, /* Memory for queues */ + ccl_global int *Queue_index, /* Tracks the number of elements in queues */ + int queuesize, /* Size (capacity) of queues */ + ccl_global char *use_queues_flag, /* used to decide if this kernel should use queues to fetch ray index */ + int parallel_samples /* Number of samples to be processed in parallel */ + ) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + /* We will empty this queue in this kernel */ + if(get_global_id(0) == 0 && get_global_id(1) == 0) { + Queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = 0; + } + + /* Fetch use_queues_flag */ + ccl_local char local_use_queues_flag; + if(get_local_id(0) == 0 && get_local_id(1) == 0) { + local_use_queues_flag = use_queues_flag[0]; + } + barrier(CLK_LOCAL_MEM_FENCE); + + int ray_index; + if(local_use_queues_flag) { + int thread_index = get_global_id(1) * get_global_size(0) + get_global_id(0); + ray_index = get_ray_index(thread_index, QUEUE_ACTIVE_AND_REGENERATED_RAYS, Queue_data, queuesize, 1); + + if(ray_index == QUEUE_EMPTY_SLOT) { + return; + } + } else { + if(x < (sw * parallel_samples) && y < sh){ + ray_index = x + y * (sw * parallel_samples); + } else { + return; + } + } + + if(IS_STATE(ray_state, ray_index, RAY_ACTIVE) || IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) { + KernelGlobals *kg = (KernelGlobals *)globals; + ShaderData *sd = (ShaderData *)shader_data; + PathRadiance *L = &PathRadiance_coop[ray_index]; + + float3 throughput = throughput_coop[ray_index]; + Ray ray = Ray_coop[ray_index]; + PathState state = PathState_coop[ray_index]; + +#ifdef __LAMP_MIS__ + if(kernel_data.integrator.use_lamp_mis && !(state.flag & PATH_RAY_CAMERA)) { + /* ray starting from previous non-transparent bounce */ + Ray light_ray; + + light_ray.P = ray.P - state.ray_t*ray.D; + state.ray_t += Intersection_coop[ray_index].t; + light_ray.D = ray.D; + light_ray.t = state.ray_t; + light_ray.time = ray.time; + light_ray.dD = ray.dD; + light_ray.dP = ray.dP; + /* intersect with lamp */ + float3 emission; + + if(indirect_lamp_emission(kg, &state, &light_ray, &emission, sd)) { + path_radiance_accum_emission(L, throughput, emission, state.bounce); + } + } +#endif + /* __VOLUME__ feature is disabled */ +#if 0 +#ifdef __VOLUME__ + /* volume attenuation, emission, scatter */ + if(state.volume_stack[0].shader != SHADER_NONE) { + Ray volume_ray = ray; + volume_ray.t = (hit)? isect.t: FLT_MAX; + + bool heterogeneous = volume_stack_is_heterogeneous(kg, state.volume_stack); + +#ifdef __VOLUME_DECOUPLED__ + int sampling_method = volume_stack_sampling_method(kg, state.volume_stack); + bool decoupled = kernel_volume_use_decoupled(kg, heterogeneous, true, sampling_method); + + if(decoupled) { + /* cache steps along volume for repeated sampling */ + VolumeSegment volume_segment; + ShaderData volume_sd; + + shader_setup_from_volume(kg, &volume_sd, &volume_ray, state.bounce, state.transparent_bounce); + kernel_volume_decoupled_record(kg, &state, + &volume_ray, &volume_sd, &volume_segment, heterogeneous); + + volume_segment.sampling_method = sampling_method; + + /* emission */ + if(volume_segment.closure_flag & SD_EMISSION) + path_radiance_accum_emission(&L, throughput, volume_segment.accum_emission, state.bounce); + + /* scattering */ + VolumeIntegrateResult result = VOLUME_PATH_ATTENUATED; + + if(volume_segment.closure_flag & SD_SCATTER) { + bool all = false; + + /* direct light sampling */ + kernel_branched_path_volume_connect_light(kg, rng, &volume_sd, + throughput, &state, &L, 1.0f, all, &volume_ray, &volume_segment); + + /* indirect sample. if we use distance sampling and take just + * one sample for direct and indirect light, we could share + * this computation, but makes code a bit complex */ + float rphase = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_PHASE); + float rscatter = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_SCATTER_DISTANCE); + + result = kernel_volume_decoupled_scatter(kg, + &state, &volume_ray, &volume_sd, &throughput, + rphase, rscatter, &volume_segment, NULL, true); + } + + if(result != VOLUME_PATH_SCATTERED) + throughput *= volume_segment.accum_transmittance; + + /* free cached steps */ + kernel_volume_decoupled_free(kg, &volume_segment); + + if(result == VOLUME_PATH_SCATTERED) { + if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, &state, &L, &ray)) + continue; + else + break; + } + } + else +#endif + { + /* integrate along volume segment with distance sampling */ + ShaderData volume_sd; + VolumeIntegrateResult result = kernel_volume_integrate( + kg, &state, &volume_sd, &volume_ray, &L, &throughput, rng, heterogeneous); + +#ifdef __VOLUME_SCATTER__ + if(result == VOLUME_PATH_SCATTERED) { + /* direct lighting */ + kernel_path_volume_connect_light(kg, rng, &volume_sd, throughput, &state, &L); + + /* indirect light bounce */ + if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, &state, &L, &ray)) + continue; + else + break; + } +#endif + } + } +#endif +#endif + } +} diff --git a/intern/cycles/kernel/kernel_next_iteration_setup.cl b/intern/cycles/kernel/kernel_next_iteration_setup.cl new file mode 100644 index 00000000000..49562ca6ed5 --- /dev/null +++ b/intern/cycles/kernel/kernel_next_iteration_setup.cl @@ -0,0 +1,176 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kernel_split.h" + +/* + * Note on kernel_ocl_path_trace_setup_next_iteration kernel. + * This is the tenth kernel in the ray tracing logic. This is the ninth + * of the path iteration kernels. This kernel takes care of setting up + * Ray for the next iteration of path-iteration and accumulating radiance + * corresponding to AO and direct-lighting + * + * Ray state of rays that are terminated in this kernel are changed to RAY_UPDATE_BUFFER + * + * The input and output are as follows, + * + * rng_coop ---------------------------------------------|--- kernel_ocl_path_trace_setup_next_iteration -|--- Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) + * throughput_coop --------------------------------------| |--- Queue_data (QUEUE_HITBF_BUFF_UPDATE_TOREGEN_RAYS) + * PathRadiance_coop ------------------------------------| |--- throughput_coop + * PathState_coop ---------------------------------------| |--- PathRadiance_coop + * shader_data ------------------------------------------| |--- PathState_coop + * ray_state --------------------------------------------| |--- ray_state + * Queue_data (QUEUE_ACTIVE_AND_REGENERATD_RAYS) --------| |--- Ray_coop + * Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) ---| |--- use_queues_flag + * Ray_coop ---------------------------------------------| | + * kg (globals + data) ----------------------------------| | + * LightRay_dl_coop -------------------------------------| + * ISLamp_coop ------------------------------------------| + * BSDFEval_coop ----------------------------------------| + * LightRay_ao_coop -------------------------------------| + * AOBSDF_coop ------------------------------------------| + * AOAlpha_coop -----------------------------------------| + * + * Note on queues, + * This kernel fetches rays from the queue QUEUE_ACTIVE_AND_REGENERATED_RAYS and processes only + * the rays of state RAY_ACTIVE. + * There are different points in this kernel where a ray may terminate and reach RAY_UPDATE_BUFF + * state. These rays are enqueued into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. These rays will + * still be present in QUEUE_ACTIVE_AND_REGENERATED_RAYS queue, but since their ray-state has been + * changed to RAY_UPDATE_BUFF, there is no problem. + * + * State of queues when this kernel is called : + * At entry, + * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE, RAY_REGENERATED, RAY_UPDATE_BUFFER rays. + * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE and RAY_UPDATE_BUFFER rays + * At exit, + * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE, RAY_REGENERATED and more RAY_UPDATE_BUFFER rays. + * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE and more RAY_UPDATE_BUFFER rays + */ + +__kernel void kernel_ocl_path_trace_setup_next_iteration( + ccl_global char *globals, + ccl_constant KernelData *data, + ccl_global char *shader_data, /* Required for setting up ray for next iteration */ + ccl_global uint *rng_coop, /* Required for setting up ray for next iteration */ + ccl_global float3 *throughput_coop, /* Required for setting up ray for next iteration */ + PathRadiance *PathRadiance_coop, /* Required for setting up ray for next iteration */ + ccl_global Ray *Ray_coop, /* Required for setting up ray for next iteration */ + ccl_global PathState *PathState_coop, /* Required for setting up ray for next iteration */ + ccl_global Ray *LightRay_dl_coop, /* Required for radiance update - direct lighting */ + ccl_global int *ISLamp_coop, /* Required for radiance update - direct lighting */ + ccl_global BsdfEval *BSDFEval_coop, /* Required for radiance update - direct lighting */ + ccl_global Ray *LightRay_ao_coop, /* Required for radiance update - AO */ + ccl_global float3 *AOBSDF_coop, /* Required for radiance update - AO */ + ccl_global float3 *AOAlpha_coop, /* Required for radiance update - AO */ + ccl_global char *ray_state, /* Denotes the state of each ray */ + ccl_global int *Queue_data, /* Queue memory */ + ccl_global int *Queue_index, /* Tracks the number of elements in each queue */ + int queuesize, /* Size (capacity) of each queue */ + ccl_global char *use_queues_flag /* flag to decide if scene_intersect kernel should use queues to fetch ray index */ + ) +{ + + ccl_local unsigned int local_queue_atomics; + if(get_local_id(0) == 0 && get_local_id(1) == 0) { + local_queue_atomics = 0; + } + barrier(CLK_LOCAL_MEM_FENCE); + + if(get_global_id(0) == 0 && get_global_id(1) == 0) { + /* If we are here, then it means that scene-intersect kernel + * has already been executed atleast once. From the next time, + * scene-intersect kernel may operate on queues to fetch ray index + */ + use_queues_flag[0] = 1; + + /* Mark queue indices of QUEUE_SHADOW_RAY_CAST_AO_RAYS and QUEUE_SHADOW_RAY_CAST_DL_RAYS + * queues that were made empty during the previous kernel + */ + Queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS] = 0; + Queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS] = 0; + } + + char enqueue_flag = 0; + int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0); + ray_index = get_ray_index(ray_index, QUEUE_ACTIVE_AND_REGENERATED_RAYS, Queue_data, queuesize, 0); + +#ifdef __COMPUTE_DEVICE_GPU__ + /* If we are executing on a GPU device, we exit all threads that are not required + * If we are executing on a CPU device, then we need to keep all threads active + * since we have barrier() calls later in the kernel. CPU devices, + * expect all threads to execute barrier statement. + */ + if(ray_index == QUEUE_EMPTY_SLOT) + return; +#endif + +#ifndef __COMPUTE_DEVICE_GPU__ + if(ray_index != QUEUE_EMPTY_SLOT) { +#endif + /* Load kernel globals structure and ShaderData structure */ + KernelGlobals *kg = (KernelGlobals *)globals; + ShaderData *sd = (ShaderData *)shader_data; + PathRadiance *L = 0x0; + ccl_global PathState *state = 0x0; + + /* Path radiance update for AO/Direct_lighting's shadow blocked */ + if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL) || IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO)) { + state = &PathState_coop[ray_index]; + L = &PathRadiance_coop[ray_index]; + float3 _throughput = throughput_coop[ray_index]; + + if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO)) { + float3 shadow = LightRay_ao_coop[ray_index].P; + char update_path_radiance = LightRay_ao_coop[ray_index].t; + if(update_path_radiance) { + path_radiance_accum_ao(L, _throughput, AOAlpha_coop[ray_index], AOBSDF_coop[ray_index], shadow, state->bounce); + } + REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO); + } + + if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL)) { + float3 shadow = LightRay_dl_coop[ray_index].P; + char update_path_radiance = LightRay_dl_coop[ray_index].t; + if(update_path_radiance) { + BsdfEval L_light = BSDFEval_coop[ray_index]; + path_radiance_accum_light(L, _throughput, &L_light, shadow, 1.0f, state->bounce, ISLamp_coop[ray_index]); + } + REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL); + } + } + + if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { + + ccl_global float3 *throughput = &throughput_coop[ray_index]; + ccl_global Ray *ray = &Ray_coop[ray_index]; + ccl_global RNG* rng = &rng_coop[ray_index]; + state = &PathState_coop[ray_index]; + L = &PathRadiance_coop[ray_index]; + + /* compute direct lighting and next bounce */ + if(!kernel_path_surface_bounce(kg, rng, sd, throughput, state, L, ray)) { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); + enqueue_flag = 1; + } + } +#ifndef __COMPUTE_DEVICE_GPU__ + } +#endif + + /* Enqueue RAY_UPDATE_BUFFER rays */ + enqueue_ray_index_local(ray_index, QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS, enqueue_flag, queuesize, &local_queue_atomics, Queue_data, Queue_index); +} diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index 8910e26fcc6..20cf3fa931b 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -19,23 +19,49 @@ CCL_NAMESPACE_BEGIN ccl_device_inline void kernel_write_pass_float(ccl_global float *buffer, int sample, float value) { ccl_global float *buf = buffer; +#if defined(__SPLIT_KERNEL__) && defined(__WORK_STEALING__) + atomic_add_float(buf, value); +#else *buf = (sample == 0)? value: *buf + value; +#endif // __SPLIT_KERNEL__ && __WORK_STEALING__ } ccl_device_inline void kernel_write_pass_float3(ccl_global float *buffer, int sample, float3 value) { +#if defined(__SPLIT_KERNEL__) && defined(__WORK_STEALING__) + ccl_global float *buf_x = buffer + 0; + ccl_global float *buf_y = buffer + 1; + ccl_global float *buf_z = buffer + 2; + + atomic_add_float(buf_x, value.x); + atomic_add_float(buf_y, value.y); + atomic_add_float(buf_z, value.z); +#else ccl_global float3 *buf = (ccl_global float3*)buffer; *buf = (sample == 0)? value: *buf + value; +#endif // __SPLIT_KERNEL__ && __WORK_STEALING__ } ccl_device_inline void kernel_write_pass_float4(ccl_global float *buffer, int sample, float4 value) { +#if defined(__SPLIT_KERNEL__) && defined(__WORK_STEALING__) + ccl_global float *buf_x = buffer + 0; + ccl_global float *buf_y = buffer + 1; + ccl_global float *buf_z = buffer + 2; + ccl_global float *buf_w = buffer + 3; + + atomic_add_float(buf_x, value.x); + atomic_add_float(buf_y, value.y); + atomic_add_float(buf_z, value.z); + atomic_add_float(buf_w, value.w); +#else ccl_global float4 *buf = (ccl_global float4*)buffer; *buf = (sample == 0)? value: *buf + value; +#endif // __SPLIT_KERNEL__ && __WORK_STEALING__ } ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global float *buffer, PathRadiance *L, - ShaderData *sd, int sample, PathState *state, float3 throughput) + ShaderData *sd, int sample, ccl_addr_space PathState *state, float3 throughput) { #ifdef __PASSES__ int path_flag = state->flag; @@ -49,18 +75,18 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl return; if(!(path_flag & PATH_RAY_SINGLE_PASS_DONE)) { - if(!(sd->flag & SD_TRANSPARENT) || + if(!(ccl_fetch(sd, flag) & SD_TRANSPARENT) || kernel_data.film.pass_alpha_threshold == 0.0f || average(shader_bsdf_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold) { if(sample == 0) { if(flag & PASS_DEPTH) { - float depth = camera_distance(kg, sd->P); + float depth = camera_distance(kg, ccl_fetch(sd, P)); kernel_write_pass_float(buffer + kernel_data.film.pass_depth, sample, depth); } if(flag & PASS_OBJECT_ID) { - float id = object_pass_id(kg, sd->object); + float id = object_pass_id(kg, ccl_fetch(sd, object)); kernel_write_pass_float(buffer + kernel_data.film.pass_object_id, sample, id); } if(flag & PASS_MATERIAL_ID) { @@ -70,7 +96,7 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl } if(flag & PASS_NORMAL) { - float3 normal = sd->N; + float3 normal = ccl_fetch(sd, N); kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal); } if(flag & PASS_UV) { @@ -101,7 +127,7 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl float mist_start = kernel_data.film.mist_start; float mist_inv_depth = kernel_data.film.mist_inv_depth; - float depth = camera_distance(kg, sd->P); + float depth = camera_distance(kg, ccl_fetch(sd, P)); float mist = saturate((depth - mist_start)*mist_inv_depth); /* falloff */ diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 0ba8f694592..e2dbf6e22f7 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -42,6 +42,7 @@ #include "kernel_path_state.h" #include "kernel_shadow.h" #include "kernel_emission.h" +#include "kernel_path_common.h" #include "kernel_path_surface.h" #include "kernel_path_volume.h" @@ -305,17 +306,17 @@ ccl_device void kernel_path_ao(KernelGlobals *kg, ShaderData *sd, PathRadiance * sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); - if(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) { + if(dot(ccl_fetch(sd, Ng), ao_D) > 0.0f && ao_pdf != 0.0f) { Ray light_ray; float3 ao_shadow; - light_ray.P = ray_offset(sd->P, sd->Ng); + light_ray.P = ray_offset(ccl_fetch(sd, P), ccl_fetch(sd, Ng)); light_ray.D = ao_D; light_ray.t = kernel_data.background.ao_distance; #ifdef __OBJECT_MOTION__ - light_ray.time = sd->time; + light_ray.time = ccl_fetch(sd, time); #endif - light_ray.dP = sd->dP; + light_ray.dP = ccl_fetch(sd, dP); light_ray.dD = differential3_zero(); if(!shadow_blocked(kg, state, &light_ray, &ao_shadow)) @@ -341,17 +342,17 @@ ccl_device void kernel_branched_path_ao(KernelGlobals *kg, ShaderData *sd, PathR sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); - if(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) { + if(dot(ccl_fetch(sd, Ng), ao_D) > 0.0f && ao_pdf != 0.0f) { Ray light_ray; float3 ao_shadow; - light_ray.P = ray_offset(sd->P, sd->Ng); + light_ray.P = ray_offset(ccl_fetch(sd, P), ccl_fetch(sd, Ng)); light_ray.D = ao_D; light_ray.t = kernel_data.background.ao_distance; #ifdef __OBJECT_MOTION__ - light_ray.time = sd->time; + light_ray.time = ccl_fetch(sd, time); #endif - light_ray.dP = sd->dP; + light_ray.dP = ccl_fetch(sd, dP); light_ray.dD = differential3_zero(); if(!shadow_blocked(kg, state, &light_ray, &ao_shadow)) @@ -381,7 +382,7 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd #ifdef __VOLUME__ Ray volume_ray = *ray; bool need_update_volume_stack = kernel_data.integrator.use_volumes && - sd->flag & SD_OBJECT_INTERSECTS_VOLUME; + ccl_fetch(sd, flag) & SD_OBJECT_INTERSECTS_VOLUME; #endif /* compute lighting with the BSDF closure */ @@ -712,8 +713,8 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba RNG *rng, ShaderData *sd, float3 throughput, float num_samples_adjust, PathState *state, PathRadiance *L) { - for(int i = 0; i< sd->num_closure; i++) { - const ShaderClosure *sc = &sd->closure[i]; + for(int i = 0; i< ccl_fetch(sd, num_closure); i++) { + const ShaderClosure *sc = &ccl_fetch(sd, closure)[i]; if(!CLOSURE_IS_BSDF(sc->type)) continue; @@ -764,8 +765,8 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, Ray *ray, float3 throughput) { - for(int i = 0; i< sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + for(int i = 0; i< ccl_fetch(sd, num_closure); i++) { + ShaderClosure *sc = &ccl_fetch(sd, closure)[i]; if(!CLOSURE_IS_BSSRDF(sc->type)) continue; @@ -786,7 +787,7 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, #ifdef __VOLUME__ Ray volume_ray = *ray; bool need_update_volume_stack = kernel_data.integrator.use_volumes && - sd->flag & SD_OBJECT_INTERSECTS_VOLUME; + ccl_fetch(sd, flag) & SD_OBJECT_INTERSECTS_VOLUME; #endif /* compute lighting with the BSDF closure */ @@ -1143,32 +1144,6 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in #endif -ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg, ccl_global uint *rng_state, int sample, int x, int y, RNG *rng, Ray *ray) -{ - float filter_u; - float filter_v; - - int num_samples = kernel_data.integrator.aa_samples; - - path_rng_init(kg, rng_state, sample, num_samples, rng, x, y, &filter_u, &filter_v); - - /* sample camera ray */ - - float lens_u = 0.0f, lens_v = 0.0f; - - if(kernel_data.cam.aperturesize > 0.0f) - path_rng_2D(kg, rng, sample, num_samples, PRNG_LENS_U, &lens_u, &lens_v); - - float time = 0.0f; - -#ifdef __CAMERA_MOTION__ - if(kernel_data.cam.shuttertime != -1.0f) - time = path_rng_1D(kg, rng, sample, num_samples, PRNG_TIME); -#endif - - camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, time, ray); -} - ccl_device void kernel_path_trace(KernelGlobals *kg, ccl_global float *buffer, ccl_global uint *rng_state, int sample, int x, int y, int offset, int stride) diff --git a/intern/cycles/kernel/kernel_path_common.h b/intern/cycles/kernel/kernel_path_common.h new file mode 100644 index 00000000000..1912dfa16ed --- /dev/null +++ b/intern/cycles/kernel/kernel_path_common.h @@ -0,0 +1,50 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +CCL_NAMESPACE_BEGIN + +ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg, + ccl_global uint *rng_state, + int sample, + int x, int y, + ccl_addr_space RNG *rng, + ccl_addr_space Ray *ray) +{ + float filter_u; + float filter_v; + + int num_samples = kernel_data.integrator.aa_samples; + + path_rng_init(kg, rng_state, sample, num_samples, rng, x, y, &filter_u, &filter_v); + + /* sample camera ray */ + + float lens_u = 0.0f, lens_v = 0.0f; + + if(kernel_data.cam.aperturesize > 0.0f) + path_rng_2D(kg, rng, sample, num_samples, PRNG_LENS_U, &lens_u, &lens_v); + + float time = 0.0f; + +#ifdef __CAMERA_MOTION__ + if(kernel_data.cam.shuttertime != -1.0f) + time = path_rng_1D(kg, rng, sample, num_samples, PRNG_TIME); +#endif + + camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, time, ray); +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h index 45ea0e502ab..15efb2371de 100644 --- a/intern/cycles/kernel/kernel_path_state.h +++ b/intern/cycles/kernel/kernel_path_state.h @@ -16,7 +16,7 @@ CCL_NAMESPACE_BEGIN -ccl_device_inline void path_state_init(KernelGlobals *kg, PathState *state, RNG *rng, int sample, Ray *ray) +ccl_device_inline void path_state_init(KernelGlobals *kg, ccl_addr_space PathState *state, ccl_addr_space RNG *rng, int sample, ccl_addr_space Ray *ray) { state->flag = PATH_RAY_CAMERA|PATH_RAY_MIS_SKIP; @@ -51,7 +51,7 @@ ccl_device_inline void path_state_init(KernelGlobals *kg, PathState *state, RNG #endif } -ccl_device_inline void path_state_next(KernelGlobals *kg, PathState *state, int label) +ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathState *state, int label) { /* ray through transparent keeps same flags from previous ray and is * not counted as a regular bounce, transparent has separate max */ @@ -138,7 +138,7 @@ ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, PathState *s return flag; } -ccl_device_inline float path_state_terminate_probability(KernelGlobals *kg, PathState *state, const float3 throughput) +ccl_device_inline float path_state_terminate_probability(KernelGlobals *kg, ccl_addr_space PathState *state, const float3 throughput) { if(state->flag & PATH_RAY_TRANSPARENT) { /* transparent rays treated separately */ diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h index f0d4e98c5e0..fe85a6b6e4b 100644 --- a/intern/cycles/kernel/kernel_path_surface.h +++ b/intern/cycles/kernel/kernel_path_surface.h @@ -24,7 +24,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN { #ifdef __EMISSION__ /* sample illumination from lights to find path contribution */ - if(!(sd->flag & SD_BSDF_HAS_EVAL)) + if(!(ccl_fetch(sd, flag) & SD_BSDF_HAS_EVAL)) return; Ray light_ray; @@ -32,7 +32,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN bool is_lamp; #ifdef __OBJECT_MOTION__ - light_ray.time = sd->time; + light_ray.time = ccl_fetch(sd, time); #endif if(sample_all_lights) { @@ -53,7 +53,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v); LightSample ls; - lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls); + lamp_light_sample(kg, i, light_u, light_v, ccl_fetch(sd, P), &ls); if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) { /* trace shadow ray */ @@ -85,7 +85,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN light_t = 0.5f*light_t; LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls); + light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls); if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) { /* trace shadow ray */ @@ -106,7 +106,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v); LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls); + light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls); /* sample random light */ if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) { @@ -149,15 +149,15 @@ ccl_device bool kernel_branched_path_surface_bounce(KernelGlobals *kg, RNG *rng, path_state_next(kg, state, label); /* setup ray */ - ray->P = ray_offset(sd->P, (label & LABEL_TRANSMIT)? -sd->Ng: sd->Ng); + ray->P = ray_offset(ccl_fetch(sd, P), (label & LABEL_TRANSMIT)? -ccl_fetch(sd, Ng): ccl_fetch(sd, Ng)); ray->D = bsdf_omega_in; ray->t = FLT_MAX; #ifdef __RAY_DIFFERENTIALS__ - ray->dP = sd->dP; + ray->dP = ccl_fetch(sd, dP); ray->dD = bsdf_domega_in; #endif #ifdef __OBJECT_MOTION__ - ray->time = sd->time; + ray->time = ccl_fetch(sd, time); #endif #ifdef __VOLUME__ @@ -181,12 +181,13 @@ ccl_device bool kernel_branched_path_surface_bounce(KernelGlobals *kg, RNG *rng, #endif +#ifndef __SPLIT_KERNEL__ /* path tracing: connect path directly to position on a light and add it to L */ -ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG *rng, - ShaderData *sd, float3 throughput, PathState *state, PathRadiance *L) +ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, ccl_addr_space RNG *rng, + ShaderData *sd, float3 throughput, ccl_addr_space PathState *state, PathRadiance *L) { #ifdef __EMISSION__ - if(!(kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL))) + if(!(kernel_data.integrator.use_direct_light && (ccl_fetch(sd, flag) & SD_BSDF_HAS_EVAL))) return; /* sample illumination from lights to find path contribution */ @@ -199,11 +200,11 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG bool is_lamp; #ifdef __OBJECT_MOTION__ - light_ray.time = sd->time; + light_ray.time = ccl_fetch(sd, time); #endif LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls); + light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls); if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) { /* trace shadow ray */ @@ -216,13 +217,14 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG } #endif } +#endif /* path tracing: bounce off or through surface to with new direction stored in ray */ -ccl_device_inline bool kernel_path_surface_bounce(KernelGlobals *kg, RNG *rng, - ShaderData *sd, float3 *throughput, PathState *state, PathRadiance *L, Ray *ray) +ccl_device_inline bool kernel_path_surface_bounce(KernelGlobals *kg, ccl_addr_space RNG *rng, + ShaderData *sd, ccl_addr_space float3 *throughput, ccl_addr_space PathState *state, PathRadiance *L, ccl_addr_space Ray *ray) { /* no BSDF? we can stop here */ - if(sd->flag & SD_BSDF) { + if(ccl_fetch(sd, flag) & SD_BSDF) { /* sample BSDF */ float bsdf_pdf; BsdfEval bsdf_eval; @@ -254,16 +256,16 @@ ccl_device_inline bool kernel_path_surface_bounce(KernelGlobals *kg, RNG *rng, path_state_next(kg, state, label); /* setup ray */ - ray->P = ray_offset(sd->P, (label & LABEL_TRANSMIT)? -sd->Ng: sd->Ng); + ray->P = ray_offset(ccl_fetch(sd, P), (label & LABEL_TRANSMIT)? -ccl_fetch(sd, Ng): ccl_fetch(sd, Ng)); ray->D = bsdf_omega_in; if(state->bounce == 0) - ray->t -= sd->ray_length; /* clipping works through transparent */ + ray->t -= ccl_fetch(sd, ray_length); /* clipping works through transparent */ else ray->t = FLT_MAX; #ifdef __RAY_DIFFERENTIALS__ - ray->dP = sd->dP; + ray->dP = ccl_fetch(sd, dP); ray->dD = bsdf_domega_in; #endif @@ -275,21 +277,21 @@ ccl_device_inline bool kernel_path_surface_bounce(KernelGlobals *kg, RNG *rng, return true; } #ifdef __VOLUME__ - else if(sd->flag & SD_HAS_ONLY_VOLUME) { + else if(ccl_fetch(sd, flag) & SD_HAS_ONLY_VOLUME) { /* no surface shader but have a volume shader? act transparent */ /* update path state, count as transparent */ path_state_next(kg, state, LABEL_TRANSPARENT); if(state->bounce == 0) - ray->t -= sd->ray_length; /* clipping works through transparent */ + ray->t -= ccl_fetch(sd, ray_length); /* clipping works through transparent */ else ray->t = FLT_MAX; /* setup ray position, direction stays unchanged */ - ray->P = ray_offset(sd->P, -sd->Ng); + ray->P = ray_offset(ccl_fetch(sd, P), -ccl_fetch(sd, Ng)); #ifdef __RAY_DIFFERENTIALS__ - ray->dP = sd->dP; + ray->dP = ccl_fetch(sd, dP); #endif /* enter/exit volume */ diff --git a/intern/cycles/kernel/kernel_queue_enqueue.cl b/intern/cycles/kernel/kernel_queue_enqueue.cl new file mode 100644 index 00000000000..eee7860fb84 --- /dev/null +++ b/intern/cycles/kernel/kernel_queue_enqueue.cl @@ -0,0 +1,98 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kernel_compat_opencl.h" +#include "kernel_math.h" +#include "kernel_types.h" +#include "kernel_globals.h" +#include "kernel_queues.h" + +/* + * The kernel "kernel_ocl_path_trace_queue_enqueue" enqueues rays of + * different ray state into their appropriate Queues; + * 1. Rays that have been determined to hit the background from the + * "kernel_ocl_path_trace_scene_intersect" kernel + * are enqueued in QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS; + * 2. Rays that have been determined to be actively participating in path-iteration will be enqueued into QUEUE_ACTIVE_AND_REGENERATED_RAYS. + * + * The input and output of the kernel is as follows, + * + * ray_state -------------------------------------------|--- kernel_ocl_path_trace_queue_enqueue --|--- Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS & QUEUE_HITBF_BUFF_UPDATE_TOREGEN_RAYS) + * Queue_index(QUEUE_ACTIVE_AND_REGENERATED_RAYS) ------| |--- Queue_index (QUEUE_ACTIVE_AND_REGENERATED_RAYS & QUEUE_HITBF_BUFF_UPDATE_TOREGEN_RAYS) + * Queue_index(QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) ---| | + * queuesize -------------------------------------------| | + * + * Note on Queues : + * State of queues during the first time this kernel is called : + * At entry, + * Both QUEUE_ACTIVE_AND_REGENERATED_RAYS and QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be empty. + * At exit, + * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE rays + * QUEUE_HITBF_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_HIT_BACKGROUND rays. + * + * State of queue during other times this kernel is called : + * At entry, + * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be empty. + * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will contain RAY_TO_REGENERATE and RAY_UPDATE_BUFFER rays. + * At exit, + * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE rays. + * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE, RAY_UPDATE_BUFFER, RAY_HIT_BACKGROUND rays. + */ + +__kernel void kernel_ocl_path_trace_queue_enqueue( + ccl_global int *Queue_data, /* Queue memory */ + ccl_global int *Queue_index, /* Tracks the number of elements in each queue */ + ccl_global char *ray_state, /* Denotes the state of each ray */ + int queuesize /* Size (capacity) of each queue */ + ) +{ + /* We have only 2 cases (Hit/Not-Hit) */ + ccl_local unsigned int local_queue_atomics[2]; + + int lidx = get_local_id(1) * get_local_size(0) + get_local_id(0); + int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0); + + if(lidx < 2 ) { + local_queue_atomics[lidx] = 0; + } + barrier(CLK_LOCAL_MEM_FENCE); + + int queue_number = -1; + + if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) { + queue_number = QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS; + } else if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { + queue_number = QUEUE_ACTIVE_AND_REGENERATED_RAYS; + } + + unsigned int my_lqidx; + if(queue_number != -1) { + my_lqidx = get_local_queue_index(queue_number, local_queue_atomics); + } + barrier(CLK_LOCAL_MEM_FENCE); + + if(lidx == 0) { + local_queue_atomics[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = get_global_per_queue_offset(QUEUE_ACTIVE_AND_REGENERATED_RAYS, local_queue_atomics, Queue_index); + local_queue_atomics[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] = get_global_per_queue_offset(QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS, local_queue_atomics, Queue_index); + } + barrier(CLK_LOCAL_MEM_FENCE); + + unsigned int my_gqidx; + if(queue_number != -1) { + my_gqidx = get_global_queue_index(queue_number, queuesize, my_lqidx, local_queue_atomics); + Queue_data[my_gqidx] = ray_index; + } +} diff --git a/intern/cycles/kernel/kernel_queues.h b/intern/cycles/kernel/kernel_queues.h new file mode 100644 index 00000000000..9e65e2b0768 --- /dev/null +++ b/intern/cycles/kernel/kernel_queues.h @@ -0,0 +1,132 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __KERNEL_QUEUE_H__ +#define __KERNEL_QUEUE_H__ + +/* + * Queue utility functions for split kernel + */ + +#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable +#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable + +/* + * Enqueue ray index into the queue + */ +ccl_device void enqueue_ray_index ( + int ray_index, /* Ray index to be enqueued */ + int queue_number, /* Queue in which the ray index should be enqueued*/ + ccl_global int *queues, /* Buffer of all queues */ + int queue_size, /* Size of each queue */ + ccl_global int *queue_index /* Array of size num_queues; Used for atomic increment */ + ) +{ + /* This thread's queue index */ + int my_queue_index = atomic_inc(&queue_index[queue_number]) + (queue_number * queue_size); + queues[my_queue_index] = ray_index; +} + +/* + * Get the ray index for this thread + * Returns a positive ray_index for threads that have to do some work; + * Returns 'QUEUE_EMPTY_SLOT' for threads that don't have any work + * i.e All ray's in the queue has been successfully allocated and there + * is no more ray to allocate to other threads. + */ +ccl_device int get_ray_index ( + int thread_index, /* Global thread index */ + int queue_number, /* Queue to operate on */ + ccl_global int *queues, /* Buffer of all queues */ + int queuesize, /* Size of a queue */ + int empty_queue /* Empty the queue slot as soon as we fetch the ray index */ + ) +{ + int ray_index = queues[queue_number * queuesize + thread_index]; + + if(empty_queue && ray_index != QUEUE_EMPTY_SLOT) { + queues[queue_number * queuesize + thread_index] = QUEUE_EMPTY_SLOT; + } + + return ray_index; +} + +/* The following functions are to realize Local memory variant of enqueue ray index function */ + +/* All threads should call this function */ +ccl_device void enqueue_ray_index_local( + int ray_index, /* Ray index to enqueue*/ + int queue_number, /* Queue in which to enqueue ray index */ + char enqueue_flag, /* True for threads whose ray index has to be enqueued */ + int queuesize, /* queue size */ + ccl_local unsigned int *local_queue_atomics, /* To to local queue atomics */ + ccl_global int *Queue_data, /* Queues */ + ccl_global int *Queue_index /* To do global queue atomics */ + ) +{ + int lidx = get_local_id(1) * get_local_size(0) + get_local_id(0); + + /* Get local queue id */ + unsigned int lqidx; + if(enqueue_flag) { + lqidx = atomic_inc(local_queue_atomics); + } + barrier(CLK_LOCAL_MEM_FENCE); + + /* Get global queue offset */ + if(lidx == 0) { + *local_queue_atomics = atomic_add(&Queue_index[queue_number], *local_queue_atomics); + } + barrier(CLK_LOCAL_MEM_FENCE); + + /* Get global queue index and enqueue ray */ + if(enqueue_flag) { + unsigned int my_gqidx = queue_number * queuesize + (*local_queue_atomics) + lqidx; + Queue_data[my_gqidx] = ray_index; + } +} + +ccl_device unsigned int get_local_queue_index( + int queue_number, /* Queue in which to enqueue the ray; -1 if no queue */ + ccl_local unsigned int *local_queue_atomics + ) +{ + int my_lqidx = atomic_inc(&local_queue_atomics[queue_number]); + return my_lqidx; +} + +ccl_device unsigned int get_global_per_queue_offset( + int queue_number, + ccl_local unsigned int *local_queue_atomics, + ccl_global int* global_queue_atomics + ) +{ + unsigned int queue_offset = atomic_add((&global_queue_atomics[queue_number]), local_queue_atomics[queue_number]); + return queue_offset; +} + +ccl_device unsigned int get_global_queue_index( + int queue_number, + int queuesize, + unsigned int lqidx, + ccl_local unsigned int * global_per_queue_offset + ) +{ + int my_gqidx = queuesize * queue_number + lqidx + global_per_queue_offset[queue_number]; + return my_gqidx; +} + +#endif // __KERNEL_QUEUE_H__ diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h index 40767bac013..631a2cb75de 100644 --- a/intern/cycles/kernel/kernel_random.h +++ b/intern/cycles/kernel/kernel_random.h @@ -98,7 +98,7 @@ ccl_device uint sobol_lookup(const uint m, const uint frame, const uint ex, cons return index; } -ccl_device_inline float path_rng_1D(KernelGlobals *kg, RNG *rng, int sample, int num_samples, int dimension) +ccl_device_inline float path_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, int sample, int num_samples, int dimension) { #ifdef __CMJ__ if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ) { @@ -132,7 +132,7 @@ ccl_device_inline float path_rng_1D(KernelGlobals *kg, RNG *rng, int sample, int #endif } -ccl_device_inline void path_rng_2D(KernelGlobals *kg, RNG *rng, int sample, int num_samples, int dimension, float *fx, float *fy) +ccl_device_inline void path_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, int sample, int num_samples, int dimension, float *fx, float *fy) { #ifdef __CMJ__ if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ) { @@ -149,7 +149,7 @@ ccl_device_inline void path_rng_2D(KernelGlobals *kg, RNG *rng, int sample, int } } -ccl_device_inline void path_rng_init(KernelGlobals *kg, ccl_global uint *rng_state, int sample, int num_samples, RNG *rng, int x, int y, float *fx, float *fy) +ccl_device_inline void path_rng_init(KernelGlobals *kg, ccl_global uint *rng_state, int sample, int num_samples, ccl_addr_space RNG *rng, int x, int y, float *fx, float *fy) { #ifdef __SOBOL_FULL_SCREEN__ uint px, py; @@ -261,12 +261,12 @@ ccl_device uint lcg_init(uint seed) * For branches in the path we must be careful not to reuse the same number * in a sequence and offset accordingly. */ -ccl_device_inline float path_state_rng_1D(KernelGlobals *kg, RNG *rng, const PathState *state, int dimension) +ccl_device_inline float path_state_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state, int dimension) { return path_rng_1D(kg, rng, state->sample, state->num_samples, state->rng_offset + dimension); } -ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, RNG *rng, const PathState *state, int dimension) +ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state, int dimension) { /* the rng_offset is not increased for transparent bounces. if we do then * fully transparent objects can become subtly visible by the different @@ -279,23 +279,23 @@ ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, RNG *r return path_rng_1D(kg, rng, state->sample, state->num_samples, rng_offset + dimension); } -ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, RNG *rng, const PathState *state, int dimension, float *fx, float *fy) +ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state, int dimension, float *fx, float *fy) { path_rng_2D(kg, rng, state->sample, state->num_samples, state->rng_offset + dimension, fx, fy); } -ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg, RNG *rng, const PathState *state, int branch, int num_branches, int dimension) +ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches, int dimension) { return path_rng_1D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, state->rng_offset + dimension); } -ccl_device_inline float path_branched_rng_1D_for_decision(KernelGlobals *kg, RNG *rng, const PathState *state, int branch, int num_branches, int dimension) +ccl_device_inline float path_branched_rng_1D_for_decision(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches, int dimension) { int rng_offset = state->rng_offset + state->transparent_bounce*PRNG_BOUNCE_NUM; return path_rng_1D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, rng_offset + dimension); } -ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, RNG *rng, const PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy) +ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy) { path_rng_2D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, state->rng_offset + dimension, fx, fy); } diff --git a/intern/cycles/kernel/kernel_scene_intersect.cl b/intern/cycles/kernel/kernel_scene_intersect.cl new file mode 100644 index 00000000000..6817e28a302 --- /dev/null +++ b/intern/cycles/kernel/kernel_scene_intersect.cl @@ -0,0 +1,164 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kernel_split.h" + +/* + * Note on kernel_ocl_path_trace_scene_intersect kernel. + * This is the second kernel in the ray tracing logic. This is the first + * of the path iteration kernels. This kernel takes care of scene_intersect function. + * + * This kernel changes the ray_state of RAY_REGENERATED rays to RAY_ACTIVE. + * This kernel processes rays of ray state RAY_ACTIVE + * This kernel determines the rays that have hit the background and changes their ray state to RAY_HIT_BACKGROUND. + * + * The input and output are as follows, + * + * Ray_coop ---------------------------------------|--------- kernel_ocl_path_trace_scene_intersect----------|--- PathState + * PathState_coop ---------------------------------| |--- Intersection + * ray_state --------------------------------------| |--- ray_state + * use_queues_flag --------------------------------| | + * parallel_samples -------------------------------| | + * QueueData(QUEUE_ACTIVE_AND_REGENERATED_RAYS) ---| | + * kg (data + globals) ----------------------------| | + * rng_coop ---------------------------------------| | + * sw ---------------------------------------------| | + * sh ---------------------------------------------| | + * queuesize --------------------------------------| | + * + * Note on Queues : + * Ideally we would want kernel_ocl_path_trace_scene_intersect to work on queues. + * But during the very first time, the queues wil be empty and hence we perform a direct mapping + * between ray-index and thread-index; From the next time onward, the queue will be filled and + * we may start operating on queues. + * + * State of queue during the first time this kernel is called : + * QUEUE_ACTIVE_AND_REGENERATED_RAYS and QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be empty.before and after this kernel + * + * State of queues during other times this kernel is called : + * At entry, + * QUEUE_ACTIVE_AND_REGENERATED_RAYS will have a mix of RAY_ACTIVE, RAY_UPDATE_BUFFER and RAY_REGENERATED rays; + * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE and RAY_UPDATE_BUFFER rays ; + * (The rays that are in the state RAY_UPDATE_BUFFER in both the queues are actually the same rays; These + * are the rays that were in RAY_ACTIVE state during the initial enqueue but on further processing + * , by different kernels, have turned into RAY_UPDATE_BUFFER rays. Since all kernel, even after fetching from + * QUEUE_ACTIVE_AND_REGENERATED_RAYS, proceed further based on ray state information, RAY_UPDATE_BUFFER rays + * being present in QUEUE_ACTIVE_AND_REGENERATED_RAYS does not cause any logical issues) + * At exit, + * QUEUE_ACTIVE_AND_REGENERATED_RAYS - All RAY_REGENERATED rays will have been converted to RAY_ACTIVE and + * Some rays in QUEUE_ACTIVE_AND_REGENERATED_RAYS queue will move to state RAY_HIT_BACKGROUND + * QUEUE_HITBF_BUFF_UPDATE_TOREGEN_RAYS - no change + */ + +__kernel void kernel_ocl_path_trace_scene_intersect( + ccl_global char *globals, + ccl_constant KernelData *data, + ccl_global uint *rng_coop, + ccl_global Ray *Ray_coop, /* Required for scene_intersect */ + ccl_global PathState *PathState_coop, /* Required for scene_intersect */ + Intersection *Intersection_coop, /* Required for scene_intersect */ + ccl_global char *ray_state, /* Denotes the state of each ray */ + int sw, int sh, + ccl_global int *Queue_data, /* Memory for queues */ + ccl_global int *Queue_index, /* Tracks the number of elements in queues */ + int queuesize, /* Size (capacity) of queues */ + ccl_global char *use_queues_flag, /* used to decide if this kernel should use queues to fetch ray index */ +#ifdef __KERNEL_DEBUG__ + DebugData *debugdata_coop, +#endif + int parallel_samples /* Number of samples to be processed in parallel */ + ) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + /* Fetch use_queues_flag */ + ccl_local char local_use_queues_flag; + if(get_local_id(0) == 0 && get_local_id(1) == 0) { + local_use_queues_flag = use_queues_flag[0]; + } + barrier(CLK_LOCAL_MEM_FENCE); + + int ray_index; + if(local_use_queues_flag) { + int thread_index = get_global_id(1) * get_global_size(0) + get_global_id(0); + ray_index = get_ray_index(thread_index, QUEUE_ACTIVE_AND_REGENERATED_RAYS, Queue_data, queuesize, 0); + + if(ray_index == QUEUE_EMPTY_SLOT) { + return; + } + } else { + if(x < (sw * parallel_samples) && y < sh){ + ray_index = x + y * (sw * parallel_samples); + } else { + return; + } + } + + /* All regenerated rays become active here */ + if(IS_STATE(ray_state, ray_index, RAY_REGENERATED)) + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_ACTIVE); + + if(!IS_STATE(ray_state, ray_index, RAY_ACTIVE)) + return; + + /* Load kernel globals structure */ + KernelGlobals *kg = (KernelGlobals *)globals; + +#ifdef __KERNEL_DEBUG__ + DebugData *debug_data = &debugdata_coop[ray_index]; +#endif + Intersection *isect = &Intersection_coop[ray_index]; + PathState state = PathState_coop[ray_index]; + Ray ray = Ray_coop[ray_index]; + + /* intersect scene */ + uint visibility = path_state_ray_visibility(kg, &state); + +#ifdef __HAIR__ + float difl = 0.0f, extmax = 0.0f; + uint lcg_state = 0; + RNG rng = rng_coop[ray_index]; + + if(kernel_data.bvh.have_curves) { + if((kernel_data.cam.resolution == 1) && (state.flag & PATH_RAY_CAMERA)) { + float3 pixdiff = ray.dD.dx + ray.dD.dy; + /*pixdiff = pixdiff - dot(pixdiff, ray.D)*ray.D;*/ + difl = kernel_data.curve.minimum_width * len(pixdiff) * 0.5f; + } + + extmax = kernel_data.curve.maximum_width; + lcg_state = lcg_state_init(&rng, &state, 0x51633e2d); + } + + bool hit = scene_intersect(kg, &ray, visibility, isect, &lcg_state, difl, extmax); +#else + bool hit = scene_intersect(kg, &ray, visibility, isect, NULL, 0.0f, 0.0f); +#endif + +#ifdef __KERNEL_DEBUG__ + if(state.flag & PATH_RAY_CAMERA) { + debug_data->num_bvh_traversal_steps += isect->num_traversal_steps; + } +#endif + + if(!hit) { + /* Change the state of rays that hit the background; + * These rays undergo special processing in the + * background_bufferUpdate kernel*/ + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND); + } +} diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index e9d9f72dfcd..a12419624c3 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -52,55 +52,55 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, int bounce, int transparent_bounce) { #ifdef __INSTANCING__ - sd->object = (isect->object == PRIM_NONE)? kernel_tex_fetch(__prim_object, isect->prim): isect->object; + ccl_fetch(sd, object) = (isect->object == PRIM_NONE)? kernel_tex_fetch(__prim_object, isect->prim): isect->object; #endif - sd->type = isect->type; - sd->flag = kernel_tex_fetch(__object_flag, sd->object); + ccl_fetch(sd, type) = isect->type; + ccl_fetch(sd, flag) = kernel_tex_fetch(__object_flag, ccl_fetch(sd, object)); /* matrices and time */ #ifdef __OBJECT_MOTION__ shader_setup_object_transforms(kg, sd, ray->time); - sd->time = ray->time; + ccl_fetch(sd, time) = ray->time; #endif - sd->prim = kernel_tex_fetch(__prim_index, isect->prim); - sd->ray_length = isect->t; - sd->ray_depth = bounce; - sd->transparent_depth = transparent_bounce; + ccl_fetch(sd, prim) = kernel_tex_fetch(__prim_index, isect->prim); + ccl_fetch(sd, ray_length) = isect->t; + ccl_fetch(sd, ray_depth) = bounce; + ccl_fetch(sd, transparent_depth) = transparent_bounce; #ifdef __UV__ - sd->u = isect->u; - sd->v = isect->v; + ccl_fetch(sd, u) = isect->u; + ccl_fetch(sd, v) = isect->v; #endif #ifdef __HAIR__ - if(sd->type & PRIMITIVE_ALL_CURVE) { + if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) { /* curve */ - float4 curvedata = kernel_tex_fetch(__curves, sd->prim); + float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim)); - sd->shader = __float_as_int(curvedata.z); - sd->P = bvh_curve_refine(kg, sd, isect, ray); + ccl_fetch(sd, shader) = __float_as_int(curvedata.z); + ccl_fetch(sd, P) = bvh_curve_refine(kg, sd, isect, ray); } else #endif - if(sd->type & PRIMITIVE_TRIANGLE) { + if(ccl_fetch(sd, type) & PRIMITIVE_TRIANGLE) { /* static triangle */ float3 Ng = triangle_normal(kg, sd); - sd->shader = kernel_tex_fetch(__tri_shader, sd->prim); + ccl_fetch(sd, shader) = kernel_tex_fetch(__tri_shader, ccl_fetch(sd, prim)); /* vectors */ - sd->P = triangle_refine(kg, sd, isect, ray); - sd->Ng = Ng; - sd->N = Ng; + ccl_fetch(sd, P) = triangle_refine(kg, sd, isect, ray); + ccl_fetch(sd, Ng) = Ng; + ccl_fetch(sd, N) = Ng; /* smooth normal */ - if(sd->shader & SHADER_SMOOTH_NORMAL) - sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); + if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) + ccl_fetch(sd, N) = triangle_smooth_normal(kg, ccl_fetch(sd, prim), ccl_fetch(sd, u), ccl_fetch(sd, v)); #ifdef __DPDU__ /* dPdu/dPdv */ - triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv); + triangle_dPdudv(kg, ccl_fetch(sd, prim), &ccl_fetch(sd, dPdu), &ccl_fetch(sd, dPdv)); #endif } else { @@ -108,40 +108,40 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, motion_triangle_shader_setup(kg, sd, isect, ray, false); } - sd->I = -ray->D; + ccl_fetch(sd, I) = -ray->D; - sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2); + ccl_fetch(sd, flag) |= kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*2); #ifdef __INSTANCING__ if(isect->object != OBJECT_NONE) { /* instance transform */ - object_normal_transform(kg, sd, &sd->N); - object_normal_transform(kg, sd, &sd->Ng); + object_normal_transform_auto(kg, sd, &ccl_fetch(sd, N)); + object_normal_transform_auto(kg, sd, &ccl_fetch(sd, Ng)); #ifdef __DPDU__ - object_dir_transform(kg, sd, &sd->dPdu); - object_dir_transform(kg, sd, &sd->dPdv); + object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdu)); + object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdv)); #endif } #endif /* backfacing test */ - bool backfacing = (dot(sd->Ng, sd->I) < 0.0f); + bool backfacing = (dot(ccl_fetch(sd, Ng), ccl_fetch(sd, I)) < 0.0f); if(backfacing) { - sd->flag |= SD_BACKFACING; - sd->Ng = -sd->Ng; - sd->N = -sd->N; + ccl_fetch(sd, flag) |= SD_BACKFACING; + ccl_fetch(sd, Ng) = -ccl_fetch(sd, Ng); + ccl_fetch(sd, N) = -ccl_fetch(sd, N); #ifdef __DPDU__ - sd->dPdu = -sd->dPdu; - sd->dPdv = -sd->dPdv; + ccl_fetch(sd, dPdu) = -ccl_fetch(sd, dPdu); + ccl_fetch(sd, dPdv) = -ccl_fetch(sd, dPdv); #endif } #ifdef __RAY_DIFFERENTIALS__ /* differentials */ - differential_transfer(&sd->dP, ray->dP, ray->D, ray->dD, sd->Ng, isect->t); - differential_incoming(&sd->dI, ray->dD); - differential_dudv(&sd->du, &sd->dv, sd->dPdu, sd->dPdv, sd->dP, sd->Ng); + differential_transfer(&ccl_fetch(sd, dP), ray->dP, ray->D, ray->dD, ccl_fetch(sd, Ng), isect->t); + differential_incoming(&ccl_fetch(sd, dI), ray->dD); + differential_dudv(&ccl_fetch(sd, du), &ccl_fetch(sd, dv), ccl_fetch(sd, dPdu), ccl_fetch(sd, dPdv), ccl_fetch(sd, dP), ccl_fetch(sd, Ng)); #endif } @@ -230,105 +230,105 @@ ccl_device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, int shader, int object, int prim, float u, float v, float t, float time, int bounce, int transparent_bounce) { /* vectors */ - sd->P = P; - sd->N = Ng; - sd->Ng = Ng; - sd->I = I; - sd->shader = shader; - sd->type = (prim == PRIM_NONE)? PRIMITIVE_NONE: PRIMITIVE_TRIANGLE; + ccl_fetch(sd, P) = P; + ccl_fetch(sd, N) = Ng; + ccl_fetch(sd, Ng) = Ng; + ccl_fetch(sd, I) = I; + ccl_fetch(sd, shader) = shader; + ccl_fetch(sd, type) = (prim == PRIM_NONE)? PRIMITIVE_NONE: PRIMITIVE_TRIANGLE; /* primitive */ #ifdef __INSTANCING__ - sd->object = object; + ccl_fetch(sd, object) = object; #endif /* currently no access to bvh prim index for strand sd->prim*/ - sd->prim = prim; + ccl_fetch(sd, prim) = prim; #ifdef __UV__ - sd->u = u; - sd->v = v; + ccl_fetch(sd, u) = u; + ccl_fetch(sd, v) = v; #endif - sd->ray_length = t; - sd->ray_depth = bounce; - sd->transparent_depth = transparent_bounce; + ccl_fetch(sd, ray_length) = t; + ccl_fetch(sd, ray_depth) = bounce; + ccl_fetch(sd, transparent_depth) = transparent_bounce; /* detect instancing, for non-instanced the object index is -object-1 */ #ifdef __INSTANCING__ bool instanced = false; - if(sd->prim != PRIM_NONE) { - if(sd->object >= 0) + if(ccl_fetch(sd, prim) != PRIM_NONE) { + if(ccl_fetch(sd, object) >= 0) instanced = true; else #endif - sd->object = ~sd->object; + ccl_fetch(sd, object) = ~ccl_fetch(sd, object); #ifdef __INSTANCING__ } #endif - sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2); - if(sd->object != OBJECT_NONE) { - sd->flag |= kernel_tex_fetch(__object_flag, sd->object); + ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*2); + if(ccl_fetch(sd, object) != OBJECT_NONE) { + ccl_fetch(sd, flag) |= kernel_tex_fetch(__object_flag, ccl_fetch(sd, object)); #ifdef __OBJECT_MOTION__ shader_setup_object_transforms(kg, sd, time); } - sd->time = time; + ccl_fetch(sd, time) = time; #else } #endif - if(sd->type & PRIMITIVE_TRIANGLE) { + if(ccl_fetch(sd, type) & PRIMITIVE_TRIANGLE) { /* smooth normal */ - if(sd->shader & SHADER_SMOOTH_NORMAL) { - sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); + if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) { + ccl_fetch(sd, N) = triangle_smooth_normal(kg, ccl_fetch(sd, prim), ccl_fetch(sd, u), ccl_fetch(sd, v)); #ifdef __INSTANCING__ if(instanced) - object_normal_transform(kg, sd, &sd->N); + object_normal_transform_auto(kg, sd, &ccl_fetch(sd, N)); #endif } /* dPdu/dPdv */ #ifdef __DPDU__ - triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv); + triangle_dPdudv(kg, ccl_fetch(sd, prim), &ccl_fetch(sd, dPdu), &ccl_fetch(sd, dPdv)); #ifdef __INSTANCING__ if(instanced) { - object_dir_transform(kg, sd, &sd->dPdu); - object_dir_transform(kg, sd, &sd->dPdv); + object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdu)); + object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdv)); } #endif #endif } else { #ifdef __DPDU__ - sd->dPdu = make_float3(0.0f, 0.0f, 0.0f); - sd->dPdv = make_float3(0.0f, 0.0f, 0.0f); + ccl_fetch(sd, dPdu) = make_float3(0.0f, 0.0f, 0.0f); + ccl_fetch(sd, dPdv) = make_float3(0.0f, 0.0f, 0.0f); #endif } /* backfacing test */ - if(sd->prim != PRIM_NONE) { - bool backfacing = (dot(sd->Ng, sd->I) < 0.0f); + if(ccl_fetch(sd, prim) != PRIM_NONE) { + bool backfacing = (dot(ccl_fetch(sd, Ng), ccl_fetch(sd, I)) < 0.0f); if(backfacing) { - sd->flag |= SD_BACKFACING; - sd->Ng = -sd->Ng; - sd->N = -sd->N; + ccl_fetch(sd, flag) |= SD_BACKFACING; + ccl_fetch(sd, Ng) = -ccl_fetch(sd, Ng); + ccl_fetch(sd, N) = -ccl_fetch(sd, N); #ifdef __DPDU__ - sd->dPdu = -sd->dPdu; - sd->dPdv = -sd->dPdv; + ccl_fetch(sd, dPdu) = -ccl_fetch(sd, dPdu); + ccl_fetch(sd, dPdv) = -ccl_fetch(sd, dPdv); #endif } } #ifdef __RAY_DIFFERENTIALS__ /* no ray differentials here yet */ - sd->dP = differential3_zero(); - sd->dI = differential3_zero(); - sd->du = differential_zero(); - sd->dv = differential_zero(); + ccl_fetch(sd, dP) = differential3_zero(); + ccl_fetch(sd, dI) = differential3_zero(); + ccl_fetch(sd, du) = differential_zero(); + ccl_fetch(sd, dv) = differential_zero(); #endif } @@ -355,45 +355,46 @@ ccl_device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd, ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray, int bounce, int transparent_bounce) { /* vectors */ - sd->P = ray->D; - sd->N = -ray->D; - sd->Ng = -ray->D; - sd->I = -ray->D; - sd->shader = kernel_data.background.surface_shader; - sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2); + ccl_fetch(sd, P) = ray->D; + ccl_fetch(sd, N) = -ray->D; + ccl_fetch(sd, Ng) = -ray->D; + ccl_fetch(sd, I) = -ray->D; + ccl_fetch(sd, shader) = kernel_data.background.surface_shader; + ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*2); #ifdef __OBJECT_MOTION__ - sd->time = ray->time; + ccl_fetch(sd, time) = ray->time; #endif - sd->ray_length = 0.0f; - sd->ray_depth = bounce; - sd->transparent_depth = transparent_bounce; + ccl_fetch(sd, ray_length) = 0.0f; + ccl_fetch(sd, ray_depth) = bounce; + ccl_fetch(sd, transparent_depth) = transparent_bounce; #ifdef __INSTANCING__ - sd->object = PRIM_NONE; + ccl_fetch(sd, object) = PRIM_NONE; #endif - sd->prim = PRIM_NONE; + ccl_fetch(sd, prim) = PRIM_NONE; #ifdef __UV__ - sd->u = 0.0f; - sd->v = 0.0f; + ccl_fetch(sd, u) = 0.0f; + ccl_fetch(sd, v) = 0.0f; #endif #ifdef __DPDU__ /* dPdu/dPdv */ - sd->dPdu = make_float3(0.0f, 0.0f, 0.0f); - sd->dPdv = make_float3(0.0f, 0.0f, 0.0f); + ccl_fetch(sd, dPdu) = make_float3(0.0f, 0.0f, 0.0f); + ccl_fetch(sd, dPdv) = make_float3(0.0f, 0.0f, 0.0f); #endif #ifdef __RAY_DIFFERENTIALS__ /* differentials */ - sd->dP = ray->dD; - differential_incoming(&sd->dI, sd->dP); - sd->du = differential_zero(); - sd->dv = differential_zero(); + ccl_fetch(sd, dP) = ray->dD; + differential_incoming(&ccl_fetch(sd, dI), ccl_fetch(sd, dP)); + ccl_fetch(sd, du) = differential_zero(); + ccl_fetch(sd, dv) = differential_zero(); #endif } /* ShaderData setup from point inside volume */ +#ifdef __VOLUME__ ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *sd, const Ray *ray, int bounce, int transparent_bounce) { /* vectors */ @@ -439,6 +440,7 @@ ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *s sd->ray_P = ray->P; sd->ray_dP = ray->dP; } +#endif /* Merging */ @@ -491,11 +493,11 @@ ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, const ShaderDa { /* this is the veach one-sample model with balance heuristic, some pdf * factors drop out when using balance heuristic weighting */ - for(int i = 0; i< sd->num_closure; i++) { + for(int i = 0; i< ccl_fetch(sd, num_closure); i++) { if(i == skip_bsdf) continue; - const ShaderClosure *sc = &sd->closure[i]; + const ShaderClosure *sc = ccl_fetch_array(sd, closure, i); if(CLOSURE_IS_BSDF(sc->type)) { float bsdf_pdf = 0.0f; @@ -513,7 +515,7 @@ ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, const ShaderDa *pdf = (sum_sample_weight > 0.0f)? sum_pdf/sum_sample_weight: 0.0f; } -ccl_device void shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd, +ccl_device void shader_bsdf_eval(KernelGlobals *kg, ShaderData *sd, const float3 omega_in, BsdfEval *eval, float *pdf) { bsdf_eval_init(eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass); @@ -527,22 +529,22 @@ ccl_device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd, { int sampled = 0; - if(sd->num_closure > 1) { + if(ccl_fetch(sd, num_closure) > 1) { /* pick a BSDF closure based on sample weights */ float sum = 0.0f; - for(sampled = 0; sampled < sd->num_closure; sampled++) { - const ShaderClosure *sc = &sd->closure[sampled]; + for(sampled = 0; sampled < ccl_fetch(sd, num_closure); sampled++) { + const ShaderClosure *sc = ccl_fetch_array(sd, closure, sampled); if(CLOSURE_IS_BSDF(sc->type)) sum += sc->sample_weight; } - float r = sd->randb_closure*sum; + float r = ccl_fetch(sd, randb_closure)*sum; sum = 0.0f; - for(sampled = 0; sampled < sd->num_closure; sampled++) { - const ShaderClosure *sc = &sd->closure[sampled]; + for(sampled = 0; sampled < ccl_fetch(sd, num_closure); sampled++) { + const ShaderClosure *sc = ccl_fetch_array(sd, closure, sampled); if(CLOSURE_IS_BSDF(sc->type)) { sum += sc->sample_weight; @@ -552,13 +554,14 @@ ccl_device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd, } } - if(sampled == sd->num_closure) { + if(sampled == ccl_fetch(sd, num_closure)) { *pdf = 0.0f; return LABEL_NONE; } } - const ShaderClosure *sc = &sd->closure[sampled]; + const ShaderClosure *sc = ccl_fetch_array(sd, closure, sampled); + int label; float3 eval; @@ -568,7 +571,7 @@ ccl_device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd, if(*pdf != 0.0f) { bsdf_eval_init(bsdf_eval, sc->type, eval*sc->weight, kernel_data.film.use_light_pass); - if(sd->num_closure > 1) { + if(ccl_fetch(sd, num_closure) > 1) { float sweight = sc->sample_weight; _shader_bsdf_multi_eval(kg, sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight); } @@ -595,8 +598,8 @@ ccl_device int shader_bsdf_sample_closure(KernelGlobals *kg, const ShaderData *s ccl_device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughness) { - for(int i = 0; i< sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + for(int i = 0; i< ccl_fetch(sd, num_closure); i++) { + ShaderClosure *sc = ccl_fetch_array(sd, closure, i); if(CLOSURE_IS_BSDF(sc->type)) bsdf_blur(kg, sc, roughness); @@ -605,13 +608,13 @@ ccl_device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughn ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd) { - if(sd->flag & SD_HAS_ONLY_VOLUME) + if(ccl_fetch(sd, flag) & SD_HAS_ONLY_VOLUME) return make_float3(1.0f, 1.0f, 1.0f); float3 eval = make_float3(0.0f, 0.0f, 0.0f); - for(int i = 0; i< sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + for(int i = 0; i< ccl_fetch(sd, num_closure); i++) { + ShaderClosure *sc = ccl_fetch_array(sd, closure, i); if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) // todo: make this work for osl eval += sc->weight; @@ -634,8 +637,8 @@ ccl_device float3 shader_bsdf_diffuse(KernelGlobals *kg, ShaderData *sd) { float3 eval = make_float3(0.0f, 0.0f, 0.0f); - for(int i = 0; i< sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + for(int i = 0; i< ccl_fetch(sd, num_closure); i++) { + ShaderClosure *sc = ccl_fetch_array(sd, closure, i); if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) eval += sc->weight; @@ -648,8 +651,8 @@ ccl_device float3 shader_bsdf_glossy(KernelGlobals *kg, ShaderData *sd) { float3 eval = make_float3(0.0f, 0.0f, 0.0f); - for(int i = 0; i< sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + for(int i = 0; i< ccl_fetch(sd, num_closure); i++) { + ShaderClosure *sc = ccl_fetch_array(sd, closure, i); if(CLOSURE_IS_BSDF_GLOSSY(sc->type)) eval += sc->weight; @@ -662,8 +665,8 @@ ccl_device float3 shader_bsdf_transmission(KernelGlobals *kg, ShaderData *sd) { float3 eval = make_float3(0.0f, 0.0f, 0.0f); - for(int i = 0; i< sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + for(int i = 0; i< ccl_fetch(sd, num_closure); i++) { + ShaderClosure *sc = ccl_fetch_array(sd, closure, i); if(CLOSURE_IS_BSDF_TRANSMISSION(sc->type)) eval += sc->weight; @@ -676,8 +679,8 @@ ccl_device float3 shader_bsdf_subsurface(KernelGlobals *kg, ShaderData *sd) { float3 eval = make_float3(0.0f, 0.0f, 0.0f); - for(int i = 0; i< sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + for(int i = 0; i< ccl_fetch(sd, num_closure); i++) { + ShaderClosure *sc = ccl_fetch_array(sd, closure, i); if(CLOSURE_IS_BSSRDF(sc->type) || CLOSURE_IS_BSDF_BSSRDF(sc->type)) eval += sc->weight; @@ -691,8 +694,8 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac float3 eval = make_float3(0.0f, 0.0f, 0.0f); float3 N = make_float3(0.0f, 0.0f, 0.0f); - for(int i = 0; i< sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + for(int i = 0; i< ccl_fetch(sd, num_closure); i++) { + ShaderClosure *sc = ccl_fetch_array(sd, closure, i); if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) { eval += sc->weight*ao_factor; @@ -700,12 +703,12 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac } else if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) { eval += sc->weight; - N += sd->N*average(sc->weight); + N += ccl_fetch(sd, N)*average(sc->weight); } } if(is_zero(N)) - N = sd->N; + N = ccl_fetch(sd, N); else N = normalize(N); @@ -719,8 +722,8 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b float3 N = make_float3(0.0f, 0.0f, 0.0f); float texture_blur = 0.0f, weight_sum = 0.0f; - for(int i = 0; i< sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + for(int i = 0; i< ccl_fetch(sd, num_closure); i++) { + ShaderClosure *sc = ccl_fetch_array(sd, closure, i); if(CLOSURE_IS_BSSRDF(sc->type)) { float avg_weight = fabsf(average(sc->weight)); @@ -733,7 +736,7 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b } if(N_) - *N_ = (is_zero(N))? sd->N: normalize(N); + *N_ = (is_zero(N))? ccl_fetch(sd, N): normalize(N); if(texture_blur_) *texture_blur_ = texture_blur/weight_sum; @@ -745,7 +748,7 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b ccl_device float3 emissive_eval(KernelGlobals *kg, ShaderData *sd, ShaderClosure *sc) { - return emissive_simple_eval(sd->Ng, sd->I); + return emissive_simple_eval(ccl_fetch(sd, Ng), ccl_fetch(sd, I)); } ccl_device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd) @@ -753,8 +756,8 @@ ccl_device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd) float3 eval; eval = make_float3(0.0f, 0.0f, 0.0f); - for(int i = 0; i < sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + for(int i = 0; i < ccl_fetch(sd, num_closure); i++) { + ShaderClosure *sc = ccl_fetch_array(sd, closure, i); if(CLOSURE_IS_EMISSION(sc->type)) eval += emissive_eval(kg, sd, sc)*sc->weight; @@ -769,8 +772,8 @@ ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd) { float3 weight = make_float3(0.0f, 0.0f, 0.0f); - for(int i = 0; i < sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + for(int i = 0; i < ccl_fetch(sd, num_closure); i++) { + ShaderClosure *sc = ccl_fetch_array(sd, closure, i); if(CLOSURE_IS_HOLDOUT(sc->type)) weight += sc->weight; @@ -784,8 +787,8 @@ ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd) ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag, ShaderContext ctx) { - sd->num_closure = 0; - sd->randb_closure = randb; + ccl_fetch(sd, num_closure) = 0; + ccl_fetch(sd, randb_closure) = randb; #ifdef __OSL__ if(kg->osl) @@ -796,11 +799,11 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, #ifdef __SVM__ svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, path_flag); #else - sd->closure->weight = make_float3(0.8f, 0.8f, 0.8f); - sd->closure->N = sd->N; - sd->closure->data0 = 0.0f; - sd->closure->data1 = 0.0f; - sd->flag |= bsdf_diffuse_setup(&sd->closure); + ccl_fetch_array(sd, closure, 0)->weight = make_float3(0.8f, 0.8f, 0.8f); + ccl_fetch_array(sd, closure, 0)->N = ccl_fetch(sd, N); + ccl_fetch_array(sd, closure, 0)->data0 = 0.0f; + ccl_fetch_array(sd, closure, 0)->data1 = 0.0f; + ccl_fetch(sd, flag) |= bsdf_diffuse_setup(ccl_fetch_array(sd, closure, 0)); #endif } } @@ -809,8 +812,8 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag, ShaderContext ctx) { - sd->num_closure = 0; - sd->randb_closure = 0.0f; + ccl_fetch(sd, num_closure) = 0; + ccl_fetch(sd, randb_closure) = 0.0f; #ifdef __OSL__ if(kg->osl) { @@ -825,8 +828,8 @@ ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int float3 eval = make_float3(0.0f, 0.0f, 0.0f); - for(int i = 0; i< sd->num_closure; i++) { - const ShaderClosure *sc = &sd->closure[i]; + for(int i = 0; i< ccl_fetch(sd, num_closure); i++) { + const ShaderClosure *sc = ccl_fetch_array(sd, closure, i); if(CLOSURE_IS_BACKGROUND(sc->type)) eval += sc->weight; @@ -999,8 +1002,8 @@ ccl_device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd, ccl_device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx) { - sd->num_closure = 0; - sd->randb_closure = 0.0f; + ccl_fetch(sd, num_closure) = 0; + ccl_fetch(sd, randb_closure) = 0.0f; /* this will modify sd->P */ #ifdef __SVM__ diff --git a/intern/cycles/kernel/kernel_shader_eval.cl b/intern/cycles/kernel/kernel_shader_eval.cl new file mode 100644 index 00000000000..78cf19a3df8 --- /dev/null +++ b/intern/cycles/kernel/kernel_shader_eval.cl @@ -0,0 +1,93 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kernel_split.h" + +/* + * Note on kernel_ocl_path_trace_shader_evaluation kernel + * This kernel is the 5th kernel in the ray tracing logic. This is + * the 4rd kernel in path iteration. This kernel sets up the ShaderData + * structure from the values computed by the previous kernels. It also identifies + * the rays of state RAY_TO_REGENERATE and enqueues them in QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. + * + * The input and output of the kernel is as follows, + * rng_coop -------------------------------------------|--- kernel_ocl_path_trace_shader_evaluation --|--- shader_data + * Ray_coop -------------------------------------------| |--- Queue_data (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) + * PathState_coop -------------------------------------| |--- Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) + * Intersection_coop ----------------------------------| | + * Queue_data (QUEUE_ACTIVE_AND_REGENERATD_RAYS)-------| | + * Queue_index(QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)---| | + * ray_state ------------------------------------------| | + * kg (globals + data) --------------------------------| | + * queuesize ------------------------------------------| | + * + * Note on Queues : + * This kernel reads from the QUEUE_ACTIVE_AND_REGENERATED_RAYS queue and processes + * only the rays of state RAY_ACTIVE; + * State of queues when this kernel is called, + * at entry, + * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE and RAY_REGENERATED rays + * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be empty. + * at exit, + * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE and RAY_REGENERATED rays + * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE rays + */ + +__kernel void kernel_ocl_path_trace_shader_evaluation( + ccl_global char *globals, + ccl_constant KernelData *data, + ccl_global char *shader_data, /* Output ShaderData structure to be filled */ + ccl_global uint *rng_coop, /* Required for rbsdf calculation */ + ccl_global Ray *Ray_coop, /* Required for setting up shader from ray */ + ccl_global PathState *PathState_coop, /* Required for all functions in this kernel */ + Intersection *Intersection_coop, /* Required for setting up shader from ray */ + ccl_global char *ray_state, /* Denotes the state of each ray */ + ccl_global int *Queue_data, /* queue memory */ + ccl_global int *Queue_index, /* Tracks the number of elements in each queue */ + int queuesize /* Size (capacity) of each queue */ + ) +{ + int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0); + /* Enqeueue RAY_TO_REGENERATE rays into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue */ + ccl_local unsigned int local_queue_atomics; + if(get_local_id(0) == 0 && get_local_id(1) == 0) { + local_queue_atomics = 0; + } + barrier(CLK_LOCAL_MEM_FENCE); + + char enqueue_flag = (IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) ? 1 : 0; + + enqueue_ray_index_local(ray_index, QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS, enqueue_flag, queuesize, &local_queue_atomics, Queue_data, Queue_index); + + ray_index = get_ray_index(ray_index, QUEUE_ACTIVE_AND_REGENERATED_RAYS, Queue_data, queuesize, 0); + + if(ray_index == QUEUE_EMPTY_SLOT) + return; + + /* Continue on with shader evaluation */ + if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { + KernelGlobals *kg = (KernelGlobals *)globals; + ShaderData *sd = (ShaderData *)shader_data; + Intersection *isect = &Intersection_coop[ray_index]; + ccl_global uint *rng = &rng_coop[ray_index]; + ccl_global PathState *state = &PathState_coop[ray_index]; + Ray ray = Ray_coop[ray_index]; + + shader_setup_from_ray(kg, sd, isect, &ray, state->bounce, state->transparent_bounce); + float rbsdf = path_state_rng_1D_for_decision(kg, rng, state, PRNG_BSDF); + shader_eval_surface(kg, sd, rbsdf, state->flag, SHADER_CONTEXT_MAIN); + } +} diff --git a/intern/cycles/kernel/kernel_shaderdata_vars.h b/intern/cycles/kernel/kernel_shaderdata_vars.h new file mode 100644 index 00000000000..b157b82e023 --- /dev/null +++ b/intern/cycles/kernel/kernel_shaderdata_vars.h @@ -0,0 +1,99 @@ +/* +* Copyright 2011-2015 Blender Foundation +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef SD_VAR +#define SD_VAR(type, what) +#endif +#ifndef SD_CLOSURE_VAR +#define SD_CLOSURE_VAR(type, what, max_closure) +#endif + +/* position */ +SD_VAR(float3, P) +/* smooth normal for shading */ +SD_VAR(float3, N) +/* true geometric normal */ +SD_VAR(float3, Ng) +/* view/incoming direction */ +SD_VAR(float3, I) +/* shader id */ +SD_VAR(int, shader) +/* booleans describing shader, see ShaderDataFlag */ +SD_VAR(int, flag) + +/* primitive id if there is one, ~0 otherwise */ +SD_VAR(int, prim) + +/* combined type and curve segment for hair */ +SD_VAR(int, type) + +/* parametric coordinates +* - barycentric weights for triangles */ +SD_VAR(float, u) +SD_VAR(float, v) +/* object id if there is one, ~0 otherwise */ +SD_VAR(int, object) + +/* motion blur sample time */ +SD_VAR(float, time) + +/* length of the ray being shaded */ +SD_VAR(float, ray_length) + +/* ray bounce depth */ +SD_VAR(int, ray_depth) + +/* ray transparent depth */ +SD_VAR(int, transparent_depth) + +#ifdef __RAY_DIFFERENTIALS__ +/* differential of P. these are orthogonal to Ng, not N */ +SD_VAR(differential3, dP) +/* differential of I */ +SD_VAR(differential3, dI) +/* differential of u, v */ +SD_VAR(differential, du) +SD_VAR(differential, dv) +#endif +#ifdef __DPDU__ +/* differential of P w.r.t. parametric coordinates. note that dPdu is +* not readily suitable as a tangent for shading on triangles. */ +SD_VAR(float3, dPdu) +SD_VAR(float3, dPdv) +#endif + +#ifdef __OBJECT_MOTION__ +/* object <-> world space transformations, cached to avoid +* re-interpolating them constantly for shading */ +SD_VAR(Transform, ob_tfm) +SD_VAR(Transform, ob_itfm) +#endif + +/* Closure data, we store a fixed array of closures */ +SD_CLOSURE_VAR(ShaderClosure, closure, MAX_CLOSURE) +SD_VAR(int, num_closure) +SD_VAR(float, randb_closure) + +/* ray start position, only set for backgrounds */ +SD_VAR(float3, ray_P) +SD_VAR(differential3, ray_dP) + +#ifdef __OSL__ +SD_VAR(struct KernelGlobals *, osl_globals) +#endif + +#undef SD_VAR +#undef SD_CLOSURE_VAR diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h index d7c4fa02bcf..5119b7a30c2 100644 --- a/intern/cycles/kernel/kernel_shadow.h +++ b/intern/cycles/kernel/kernel_shadow.h @@ -180,19 +180,37 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray * * potentially transparent, and only in that case start marching. this gives * one extra ray cast for the cases were we do want transparency. */ -ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, float3 *shadow) +/* The arguments sd_mem and isect_mem are meaningful only for OpenCL split kernel. Other uses can just pass a NULL */ +ccl_device_inline bool shadow_blocked(KernelGlobals *kg, ccl_addr_space PathState *state, ccl_addr_space Ray *ray_input, float3 *shadow +#ifdef __SPLIT_KERNEL__ + , ShaderData *sd_mem, Intersection *isect_mem +#endif + ) { *shadow = make_float3(1.0f, 1.0f, 1.0f); - if(ray->t == 0.0f) + if(ray_input->t == 0.0f) return false; - Intersection isect; - bool blocked = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, &isect, NULL, 0.0f, 0.0f); +#ifdef __SPLIT_KERNEL__ + Ray private_ray = *ray_input; + Ray *ray = &private_ray; +#else + Ray *ray = ray_input; +#endif + +#ifdef __SPLIT_KERNEL__ + Intersection *isect = isect_mem; +#else + Intersection isect_object; + Intersection *isect = &isect_object; +#endif + + bool blocked = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, isect, NULL, 0.0f, 0.0f); #ifdef __TRANSPARENT_SHADOWS__ if(blocked && kernel_data.integrator.transparent_shadows) { - if(shader_transparent_shadow(kg, &isect)) { + if(shader_transparent_shadow(kg, isect)) { float3 throughput = make_float3(1.0f, 1.0f, 1.0f); float3 Pend = ray->P + ray->D*ray->t; int bounce = state->transparent_bounce; @@ -204,9 +222,8 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray * if(bounce >= kernel_data.integrator.transparent_max_bounce) return true; - if(!scene_intersect(kg, ray, PATH_RAY_SHADOW_TRANSPARENT, &isect, NULL, 0.0f, 0.0f)) + if(!scene_intersect(kg, ray, PATH_RAY_SHADOW_TRANSPARENT, isect, NULL, 0.0f, 0.0f)) { - #ifdef __VOLUME__ /* attenuation for last line segment towards light */ if(ps.volume_stack[0].shader != SHADER_NONE) @@ -218,39 +235,44 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray * return false; } - if(!shader_transparent_shadow(kg, &isect)) + if(!shader_transparent_shadow(kg, isect)) return true; #ifdef __VOLUME__ /* attenuation between last surface and next surface */ if(ps.volume_stack[0].shader != SHADER_NONE) { Ray segment_ray = *ray; - segment_ray.t = isect.t; + segment_ray.t = isect->t; kernel_volume_shadow(kg, &ps, &segment_ray, &throughput); } #endif /* setup shader data at surface */ - ShaderData sd; - shader_setup_from_ray(kg, &sd, &isect, ray, state->bounce+1, bounce); +#ifdef __SPLIT_KERNEL__ + ShaderData *sd = sd_mem; +#else + ShaderData sd_object; + ShaderData *sd = &sd_object; +#endif + shader_setup_from_ray(kg, sd, isect, ray, state->bounce+1, bounce); /* attenuation from transparent surface */ - if(!(sd.flag & SD_HAS_ONLY_VOLUME)) { - shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW); - throughput *= shader_bsdf_transparency(kg, &sd); + if(!(ccl_fetch(sd, flag) & SD_HAS_ONLY_VOLUME)) { + shader_eval_surface(kg, sd, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW); + throughput *= shader_bsdf_transparency(kg, sd); } if(is_zero(throughput)) return true; /* move ray forward */ - ray->P = ray_offset(sd.P, -sd.Ng); + ray->P = ray_offset(ccl_fetch(sd, P), -ccl_fetch(sd, Ng)); if(ray->t != FLT_MAX) ray->D = normalize_len(Pend - ray->P, &ray->t); #ifdef __VOLUME__ /* exit/enter volume */ - kernel_volume_stack_enter_exit(kg, &sd, ps.volume_stack); + kernel_volume_stack_enter_exit(kg, sd, ps.volume_stack); #endif bounce++; diff --git a/intern/cycles/kernel/kernel_shadow_blocked.cl b/intern/cycles/kernel/kernel_shadow_blocked.cl new file mode 100644 index 00000000000..72a2d0affb0 --- /dev/null +++ b/intern/cycles/kernel/kernel_shadow_blocked.cl @@ -0,0 +1,126 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kernel_split.h" + +/* + * Note on kernel_ocl_path_trace_shadow_blocked kernel. + * This is the ninth kernel in the ray tracing logic. This is the eighth + * of the path iteration kernels. This kernel takes care of "shadow ray cast" + * logic of the direct lighting and AO part of ray tracing. + * + * The input and output are as follows, + * + * PathState_coop ----------------------------------|--- kernel_ocl_path_trace_shadow_blocked --| + * LightRay_dl_coop --------------------------------| |--- LightRay_dl_coop + * LightRay_ao_coop --------------------------------| |--- LightRay_ao_coop + * ray_state ---------------------------------------| |--- ray_state + * Queue_data(QUEUE_SHADOW_RAY_CAST_AO_RAYS & | |--- Queue_data (QUEUE_SHADOW_RAY_CAST_AO_RAYS & QUEUE_SHADOW_RAY_CAST_AO_RAYS) + QUEUE_SHADOW_RAY_CAST_DL_RAYS) -------| | + * Queue_index(QUEUE_SHADOW_RAY_CAST_AO_RAYS& + QUEUE_SHADOW_RAY_CAST_DL_RAYS) -------| | + * kg (globals + data) -----------------------------| | + * queuesize ---------------------------------------| | + * + * Note on shader_shadow : shader_shadow is neither input nor output to this kernel. shader_shadow is filled and consumed in this kernel itself. + * Note on queues : + * The kernel fetches from QUEUE_SHADOW_RAY_CAST_AO_RAYS and QUEUE_SHADOW_RAY_CAST_DL_RAYS queues. We will empty + * these queues this kernel. + * State of queues when this kernel is called : + * state of queues QUEUE_ACTIVE_AND_REGENERATED_RAYS and QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be same + * before and after this kernel call. + * QUEUE_SHADOW_RAY_CAST_AO_RAYS & QUEUE_SHADOW_RAY_CAST_DL_RAYS will be filled with rays marked with flags RAY_SHADOW_RAY_CAST_AO + * and RAY_SHADOW_RAY_CAST_DL respectively, during kernel entry. + * QUEUE_SHADOW_RAY_CAST_AO_RAYS and QUEUE_SHADOW_RAY_CAST_DL_RAYS will be empty at kernel exit. + */ + +__kernel void kernel_ocl_path_trace_shadow_blocked_direct_lighting( + ccl_global char *globals, + ccl_constant KernelData *data, + ccl_global char *shader_shadow, /* Required for shadow blocked */ + ccl_global PathState *PathState_coop, /* Required for shadow blocked */ + ccl_global Ray *LightRay_dl_coop, /* Required for direct lighting's shadow blocked */ + ccl_global Ray *LightRay_ao_coop, /* Required for AO's shadow blocked */ + Intersection *Intersection_coop_AO, + Intersection *Intersection_coop_DL, + ccl_global char *ray_state, + ccl_global int *Queue_data, /* Queue memory */ + ccl_global int *Queue_index, /* Tracks the number of elements in each queue */ + int queuesize, /* Size (capacity) of each queue */ + int total_num_rays + ) +{ +#if 0 + /* we will make the Queue_index entries '0' in the next kernel */ + if(get_global_id(0) == 0 && get_global_id(1) == 0) { + /* We empty this queue here */ + Queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS] = 0; + Queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS] = 0; + } +#endif + + int lidx = get_local_id(1) * get_local_id(0) + get_local_id(0); + + ccl_local unsigned int ao_queue_length; + ccl_local unsigned int dl_queue_length; + if(lidx == 0) { + ao_queue_length = Queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS]; + dl_queue_length = Queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS]; + } + barrier(CLK_LOCAL_MEM_FENCE); + + /* flag determining if the current ray is to process shadow ray for AO or DL */ + char shadow_blocked_type = -1; + /* flag determining if we need to update L */ + char update_path_radiance = 0; + + int ray_index = QUEUE_EMPTY_SLOT; + int thread_index = get_global_id(1) * get_global_size(0) + get_global_id(0); + if(thread_index < ao_queue_length + dl_queue_length) { + if(thread_index < ao_queue_length) { + ray_index = get_ray_index(thread_index, QUEUE_SHADOW_RAY_CAST_AO_RAYS, Queue_data, queuesize, 1); + shadow_blocked_type = RAY_SHADOW_RAY_CAST_AO; + } else { + ray_index = get_ray_index(thread_index - ao_queue_length, QUEUE_SHADOW_RAY_CAST_DL_RAYS, Queue_data, queuesize, 1); + shadow_blocked_type = RAY_SHADOW_RAY_CAST_DL; + } + } + + if(ray_index == QUEUE_EMPTY_SLOT) + return; + + if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL) || IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO)) { + /* Load kernel global structure */ + KernelGlobals *kg = (KernelGlobals *)globals; + ShaderData *sd_shadow = (ShaderData *)shader_shadow; + + ccl_global PathState *state = &PathState_coop[ray_index]; + ccl_global Ray *light_ray_dl_global = &LightRay_dl_coop[ray_index]; + ccl_global Ray *light_ray_ao_global = &LightRay_ao_coop[ray_index]; + Intersection *isect_ao_global = &Intersection_coop_AO[ray_index]; + Intersection *isect_dl_global = &Intersection_coop_DL[ray_index]; + + ccl_global Ray *light_ray_global = shadow_blocked_type == RAY_SHADOW_RAY_CAST_AO ? light_ray_ao_global : light_ray_dl_global; + Intersection *isect_global = RAY_SHADOW_RAY_CAST_AO ? isect_ao_global : isect_dl_global; + + float3 shadow; + update_path_radiance = !(shadow_blocked(kg, state, light_ray_global, &shadow, sd_shadow, isect_global)); + + /* We use light_ray_global's P and t to store shadow and update_path_radiance */ + light_ray_global->P = shadow; + light_ray_global->t = update_path_radiance; + } +} diff --git a/intern/cycles/kernel/kernel_split.h b/intern/cycles/kernel/kernel_split.h new file mode 100644 index 00000000000..eb386c2e5a7 --- /dev/null +++ b/intern/cycles/kernel/kernel_split.h @@ -0,0 +1,87 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _KERNEL_SPLIT_H_ +#define _KERNEL_SPLIT_H_ + +#include "kernel_compat_opencl.h" +#include "kernel_math.h" +#include "kernel_types.h" +#include "kernel_globals.h" + +/* atomic_add_float function should be defined prior to its usage in kernel_passes.h */ +#if defined(__SPLIT_KERNEL__) && defined(__WORK_STEALING__) +/* Utility functions for float atomics */ +/* float atomics impl credits : http://suhorukov.blogspot.in/2011/12/opencl-11-atomic-operations-on-floating.html */ +ccl_device_inline void atomic_add_float(volatile ccl_global float *source, const float operand) { + union { + unsigned int intVal; + float floatVal; + + } newVal; + union { + unsigned int intVal; + float floatVal; + + } prevVal; + do { + prevVal.floatVal = *source; + newVal.floatVal = prevVal.floatVal + operand; + + } while (atomic_cmpxchg((volatile ccl_global unsigned int *)source, prevVal.intVal, newVal.intVal) != prevVal.intVal); +} +#endif // __SPLIT_KERNEL__ && __WORK_STEALING__ + +#ifdef __OSL__ +#include "osl_shader.h" +#endif + +#include "kernel_random.h" +#include "kernel_projection.h" +#include "kernel_montecarlo.h" +#include "kernel_differential.h" +#include "kernel_camera.h" + +#include "geom/geom.h" + +#include "kernel_accumulate.h" +#include "kernel_shader.h" +#include "kernel_light.h" +#include "kernel_passes.h" + +#ifdef __SUBSURFACE__ +#include "kernel_subsurface.h" +#endif + +#ifdef __VOLUME__ +#include "kernel_volume.h" +#endif + +#include "kernel_path_state.h" +#include "kernel_shadow.h" +#include "kernel_emission.h" +#include "kernel_path_common.h" +#include "kernel_path_surface.h" +#include "kernel_path_volume.h" + +#ifdef __KERNEL_DEBUG__ +#include "kernel_debug.h" +#endif + +#include "kernel_queues.h" +#include "kernel_work_stealing.h" + +#endif diff --git a/intern/cycles/kernel/kernel_sum_all_radiance.cl b/intern/cycles/kernel/kernel_sum_all_radiance.cl new file mode 100644 index 00000000000..739a85d4cc8 --- /dev/null +++ b/intern/cycles/kernel/kernel_sum_all_radiance.cl @@ -0,0 +1,59 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kernel_compat_opencl.h" +#include "kernel_math.h" +#include "kernel_types.h" +#include "kernel_globals.h" + +/* +* Since we process various samples in parallel; The output radiance of different samples +* are stored in different locations; This kernel combines the output radiance contributed +* by all different samples and stores them in the RenderTile's output buffer. +*/ + +__kernel void kernel_ocl_path_trace_sum_all_radiance( + ccl_constant KernelData *data, /* To get pass_stride to offet into buffer */ + ccl_global float *buffer, /* Output buffer of RenderTile */ + ccl_global float *per_sample_output_buffer, /* Radiance contributed by all samples */ + int parallel_samples, int sw, int sh, int stride, + int buffer_offset_x, + int buffer_offset_y, + int buffer_stride, + int start_sample) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + if(x < sw && y < sh) { + buffer += ((buffer_offset_x + x) + (buffer_offset_y + y) * buffer_stride) * (data->film.pass_stride); + per_sample_output_buffer += ((x + y * stride) * parallel_samples) * (data->film.pass_stride); + + int sample_stride = (data->film.pass_stride); + + int sample_iterator = 0; + int pass_stride_iterator = 0; + int num_floats = data->film.pass_stride; + + for(sample_iterator = 0; sample_iterator < parallel_samples; sample_iterator++) { + for(pass_stride_iterator = 0; pass_stride_iterator < num_floats; pass_stride_iterator++) { + *(buffer + pass_stride_iterator) = (start_sample == 0 && sample_iterator == 0) ? *(per_sample_output_buffer + pass_stride_iterator) + : *(buffer + pass_stride_iterator) + *(per_sample_output_buffer + pass_stride_iterator); + } + per_sample_output_buffer += sample_stride; + } + } +} diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index daa5ec1b9f1..303a78d8ac0 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -24,6 +24,13 @@ #define __KERNEL_CPU__ #endif +/* TODO(sergey): This is only to make it possible to include this header + * from outside of the kernel. but this could be done somewhat cleaner? + */ +#ifndef ccl_addr_space +#define ccl_addr_space +#endif + CCL_NAMESPACE_BEGIN /* constants */ @@ -90,7 +97,19 @@ CCL_NAMESPACE_BEGIN #ifdef __KERNEL_OPENCL_NVIDIA__ #define __KERNEL_SHADING__ -#define __KERNEL_ADV_SHADING__ +/* TODO(sergey): Advanced shading code still requires work + * for split kernel. + */ +# ifndef __SPLIT_KERNEL__ +# define __KERNEL_ADV_SHADING__ +# else +# define __MULTI_CLOSURE__ +# define __TRANSPARENT_SHADOWS__ +# define __PASSES__ +# define __BACKGROUND_MIS__ +# define __LAMP_MIS__ +# define __AO__ +# endif #endif #ifdef __KERNEL_OPENCL_APPLE__ @@ -103,7 +122,7 @@ CCL_NAMESPACE_BEGIN #define __KERNEL_SHADING__ //__KERNEL_ADV_SHADING__ #define __MULTI_CLOSURE__ -#define __TRANSPARENT_SHADOWS__ +//#define __TRANSPARENT_SHADOWS__ #define __PASSES__ #define __BACKGROUND_MIS__ #define __LAMP_MIS__ @@ -117,10 +136,22 @@ CCL_NAMESPACE_BEGIN #ifdef __KERNEL_OPENCL_INTEL_CPU__ #define __CL_USE_NATIVE__ #define __KERNEL_SHADING__ -#define __KERNEL_ADV_SHADING__ +/* TODO(sergey): Advanced shading code still requires work + * for split kernel. + */ +# ifndef __SPLIT_KERNEL__ +# define __KERNEL_ADV_SHADING__ +# else +# define __MULTI_CLOSURE__ +# define __TRANSPARENT_SHADOWS__ +# define __PASSES__ +# define __BACKGROUND_MIS__ +# define __LAMP_MIS__ +# define __AO__ +# endif #endif -#endif +#endif // __KERNEL_OPENCL__ /* kernel features */ #define __SOBOL__ @@ -322,7 +353,7 @@ typedef enum PassType { #ifdef __PASSES__ -typedef struct PathRadiance { +typedef ccl_addr_space struct PathRadiance { int use_light_pass; float3 emission; @@ -374,7 +405,7 @@ typedef struct BsdfEval { #else -typedef float3 PathRadiance; +typedef ccl_addr_space float3 PathRadiance; typedef float3 BsdfEval; #endif @@ -441,9 +472,9 @@ typedef struct differential { typedef struct Ray { float3 P; /* origin */ float3 D; /* direction */ + float t; /* length of the ray */ float time; /* time (for motion blur) */ - #ifdef __RAY_DIFFERENTIALS__ differential3 dP; differential3 dD; @@ -452,7 +483,7 @@ typedef struct Ray { /* Intersection */ -typedef struct Intersection { +typedef ccl_addr_space struct Intersection { float t, u, v; int prim; int object; @@ -537,7 +568,11 @@ typedef enum AttributeStandard { /* Closure data */ #ifdef __MULTI_CLOSURE__ -#define MAX_CLOSURE 64 +# ifndef __MAX_CLOSURE__ +# define MAX_CLOSURE 64 +# else +# define MAX_CLOSURE __MAX_CLOSURE__ +# endif #else #define MAX_CLOSURE 1 #endif @@ -547,7 +582,7 @@ typedef enum AttributeStandard { * does not put own padding trying to align this members. * - We make sure OSL pointer is also 16 bytes aligned. */ -typedef struct ShaderClosure { +typedef ccl_addr_space struct ShaderClosure { float3 weight; float3 N; float3 T; @@ -632,78 +667,23 @@ enum ShaderDataFlag { struct KernelGlobals; -typedef struct ShaderData { - /* position */ - float3 P; - /* smooth normal for shading */ - float3 N; - /* true geometric normal */ - float3 Ng; - /* view/incoming direction */ - float3 I; - /* shader id */ - int shader; - /* booleans describing shader, see ShaderDataFlag */ - int flag; - - /* primitive id if there is one, ~0 otherwise */ - int prim; - - /* combined type and curve segment for hair */ - int type; - - /* parametric coordinates - * - barycentric weights for triangles */ - float u, v; - /* object id if there is one, ~0 otherwise */ - int object; - - /* motion blur sample time */ - float time; - - /* length of the ray being shaded */ - float ray_length; - - /* ray bounce depth */ - int ray_depth; - - /* ray transparent depth */ - int transparent_depth; - -#ifdef __RAY_DIFFERENTIALS__ - /* differential of P. these are orthogonal to Ng, not N */ - differential3 dP; - /* differential of I */ - differential3 dI; - /* differential of u, v */ - differential du; - differential dv; -#endif -#ifdef __DPDU__ - /* differential of P w.r.t. parametric coordinates. note that dPdu is - * not readily suitable as a tangent for shading on triangles. */ - float3 dPdu, dPdv; -#endif - -#ifdef __OBJECT_MOTION__ - /* object <-> world space transformations, cached to avoid - * re-interpolating them constantly for shading */ - Transform ob_tfm; - Transform ob_itfm; +#ifdef __SPLIT_KERNEL__ +#define SD_VAR(type, what) ccl_global type *what; +#define SD_CLOSURE_VAR(type, what, max_closure) type *what; +#define TIDX (get_global_id(1) * get_global_size(0) + get_global_id(0)) +#define ccl_fetch(s, t) (s->t[TIDX]) +#define ccl_fetch_array(s, t, index) (&s->t[TIDX * MAX_CLOSURE + index]) +#else +#define SD_VAR(type, what) type what; +#define SD_CLOSURE_VAR(type, what, max_closure) type what[max_closure]; +#define ccl_fetch(s, t) (s->t) +#define ccl_fetch_array(s, t, index) (&s->t[index]) #endif - /* Closure data, we store a fixed array of closures */ - ShaderClosure closure[MAX_CLOSURE]; - int num_closure; - float randb_closure; +typedef ccl_addr_space struct ShaderData { - /* ray start position, only set for backgrounds */ - float3 ray_P; - differential3 ray_dP; +#include "kernel_shaderdata_vars.h" -#ifdef __OSL__ - struct KernelGlobals *osl_globals; -#endif } ShaderData; /* Path State */ @@ -996,13 +976,62 @@ typedef struct KernelData { } KernelData; #ifdef __KERNEL_DEBUG__ -typedef struct DebugData { +typedef ccl_addr_space struct DebugData { // Total number of BVH node traversal steps and primitives intersections // for the camera rays. int num_bvh_traversal_steps; } DebugData; #endif +/* Declarations required for split kernel */ + +/* Macro for queues */ +/* Value marking queue's empty slot */ +#define QUEUE_EMPTY_SLOT -1 + +/* +* Queue 1 - Active rays +* Queue 2 - Background queue +* Queue 3 - Shadow ray cast kernel - AO +* Queeu 4 - Shadow ray cast kernel - direct lighting +*/ +#define NUM_QUEUES 4 + +/* Queue names */ +enum QueueNumber { + QUEUE_ACTIVE_AND_REGENERATED_RAYS, /* All active rays and regenerated rays are enqueued here */ + QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS, /* All + * 1.Background-hit rays, + * 2.Rays that has exited path-iteration but needs to update output buffer + * 3.Rays to be regenerated + * are enqueued here */ + QUEUE_SHADOW_RAY_CAST_AO_RAYS, /* All rays for which a shadow ray should be cast to determine radiance + contribution for AO are enqueued here */ + QUEUE_SHADOW_RAY_CAST_DL_RAYS, /* All rays for which a shadow ray should be cast to determine radiance + contributuin for direct lighting are enqueued here */ +}; + +/* We use RAY_STATE_MASK to get ray_state (enums 0 to 5) */ +#define RAY_STATE_MASK 0x007 +#define RAY_FLAG_MASK 0x0F8 +enum RayState { + RAY_ACTIVE = 0, // Denotes ray is actively involved in path-iteration + RAY_INACTIVE = 1, // Denotes ray has completed processing all samples and is inactive + RAY_UPDATE_BUFFER = 2, // Denoted ray has exited path-iteration and needs to update output buffer + RAY_HIT_BACKGROUND = 3, // Donotes ray has hit background + RAY_TO_REGENERATE = 4, // Denotes ray has to be regenerated + RAY_REGENERATED = 5, // Denotes ray has been regenerated + RAY_SKIP_DL = 6, // Denotes ray should skip direct lighting + RAY_SHADOW_RAY_CAST_AO = 16, // Flag's ray has to execute shadow blocked function in AO part + RAY_SHADOW_RAY_CAST_DL = 32 // Flag's ray has to execute shadow blocked function in direct lighting part +}; + +#define ASSIGN_RAY_STATE(ray_state, ray_index, state) (ray_state[ray_index] = ((ray_state[ray_index] & RAY_FLAG_MASK) | state)) +#define IS_STATE(ray_state, ray_index, state) ((ray_state[ray_index] & RAY_STATE_MASK) == state) +#define ADD_RAY_FLAG(ray_state, ray_index, flag) (ray_state[ray_index] = (ray_state[ray_index] | flag)) +#define REMOVE_RAY_FLAG(ray_state, ray_index, flag) (ray_state[ray_index] = (ray_state[ray_index] & (~flag))) +#define IS_FLAG(ray_state, ray_index, flag) (ray_state[ray_index] & flag) + CCL_NAMESPACE_END #endif /* __KERNEL_TYPES_H__ */ diff --git a/intern/cycles/kernel/kernel_work_stealing.h b/intern/cycles/kernel/kernel_work_stealing.h new file mode 100644 index 00000000000..9b83d972e97 --- /dev/null +++ b/intern/cycles/kernel/kernel_work_stealing.h @@ -0,0 +1,193 @@ +/* + * Copyright 2011-2015 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __KERNEL_WORK_STEALING_H__ +#define __KERNEL_WORK_STEALING_H__ + +/* + * Utility functions for work stealing + */ + +#ifdef __WORK_STEALING__ + +#ifdef __KERNEL_OPENCL__ +#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable +#endif + +uint get_group_id_with_ray_index(uint ray_index, + uint tile_dim_x, + uint tile_dim_y, + uint parallel_samples, + int dim) +{ + if(dim == 0) { + uint x_span = ray_index % (tile_dim_x * parallel_samples); + return x_span / get_local_size(0); + } + else /*if(dim == 1)*/ { + kernel_assert(dim == 1); + uint y_span = ray_index / (tile_dim_x * parallel_samples); + return y_span / get_local_size(1); + } +} + +uint get_total_work(uint tile_dim_x, + uint tile_dim_y, + uint grp_idx, + uint grp_idy, + uint num_samples) +{ + uint threads_within_tile_border_x = + (grp_idx == (get_num_groups(0) - 1)) ? tile_dim_x % get_local_size(0) + : get_local_size(0); + uint threads_within_tile_border_y = + (grp_idy == (get_num_groups(1) - 1)) ? tile_dim_y % get_local_size(1) + : get_local_size(1); + + threads_within_tile_border_x = + (threads_within_tile_border_x == 0) ? get_local_size(0) + : threads_within_tile_border_x; + threads_within_tile_border_y = + (threads_within_tile_border_y == 0) ? get_local_size(1) + : threads_within_tile_border_y; + + return threads_within_tile_border_x * + threads_within_tile_border_y * + num_samples; +} + +/* Returns 0 in case there is no next work available */ +/* Returns 1 in case work assigned is valid */ +int get_next_work(ccl_global uint *work_pool, + ccl_private uint *my_work, + uint tile_dim_x, + uint tile_dim_y, + uint num_samples, + uint parallel_samples, + uint ray_index) +{ + uint grp_idx = get_group_id_with_ray_index(ray_index, + tile_dim_x, + tile_dim_y, + parallel_samples, + 0); + uint grp_idy = get_group_id_with_ray_index(ray_index, + tile_dim_x, + tile_dim_y, + parallel_samples, + 1); + uint total_work = get_total_work(tile_dim_x, + tile_dim_y, + grp_idx, + grp_idy, + num_samples); + uint group_index = grp_idy * get_num_groups(0) + grp_idx; + *my_work = atomic_inc(&work_pool[group_index]); + return (*my_work < total_work) ? 1 : 0; +} + +/* This function assumes that the passed my_work is valid. */ +/* Decode sample number w.r.t. assigned my_work. */ +uint get_my_sample(uint my_work, + uint tile_dim_x, + uint tile_dim_y, + uint parallel_samples, + uint ray_index) +{ + uint grp_idx = get_group_id_with_ray_index(ray_index, + tile_dim_x, + tile_dim_y, + parallel_samples, + 0); + uint grp_idy = get_group_id_with_ray_index(ray_index, + tile_dim_x, + tile_dim_y, + parallel_samples, + 1); + uint threads_within_tile_border_x = + (grp_idx == (get_num_groups(0) - 1)) ? tile_dim_x % get_local_size(0) + : get_local_size(0); + uint threads_within_tile_border_y = + (grp_idy == (get_num_groups(1) - 1)) ? tile_dim_y % get_local_size(1) + : get_local_size(1); + + threads_within_tile_border_x = + (threads_within_tile_border_x == 0) ? get_local_size(0) + : threads_within_tile_border_x; + threads_within_tile_border_y = + (threads_within_tile_border_y == 0) ? get_local_size(1) + : threads_within_tile_border_y; + + return my_work / + (threads_within_tile_border_x * threads_within_tile_border_y); +} + +/* Decode pixel and tile position w.r.t. assigned my_work. */ +void get_pixel_tile_position(ccl_private uint *pixel_x, + ccl_private uint *pixel_y, + ccl_private uint *tile_x, + ccl_private uint *tile_y, + uint my_work, + uint tile_dim_x, + uint tile_dim_y, + uint tile_offset_x, + uint tile_offset_y, + uint parallel_samples, + uint ray_index) +{ + uint grp_idx = get_group_id_with_ray_index(ray_index, + tile_dim_x, + tile_dim_y, + parallel_samples, + 0); + uint grp_idy = get_group_id_with_ray_index(ray_index, + tile_dim_x, + tile_dim_y, + parallel_samples, + 1); + uint threads_within_tile_border_x = + (grp_idx == (get_num_groups(0) - 1)) ? tile_dim_x % get_local_size(0) + : get_local_size(0); + uint threads_within_tile_border_y = + (grp_idy == (get_num_groups(1) - 1)) ? tile_dim_y % get_local_size(1) + : get_local_size(1); + + threads_within_tile_border_x = + (threads_within_tile_border_x == 0) ? get_local_size(0) + : threads_within_tile_border_x; + threads_within_tile_border_y = + (threads_within_tile_border_y == 0) ? get_local_size(1) + : threads_within_tile_border_y; + + uint total_associated_pixels = + threads_within_tile_border_x * threads_within_tile_border_y; + uint work_group_pixel_index = my_work % total_associated_pixels; + uint work_group_pixel_x = + work_group_pixel_index % threads_within_tile_border_x; + uint work_group_pixel_y = + work_group_pixel_index / threads_within_tile_border_x; + + *pixel_x = + tile_offset_x + (grp_idx * get_local_size(0)) + work_group_pixel_x; + *pixel_y = + tile_offset_y + (grp_idy * get_local_size(1)) + work_group_pixel_y; + *tile_x = *pixel_x - tile_offset_x; + *tile_y = *pixel_y - tile_offset_y; +} + +#endif /* __WORK_STEALING__ */ + +#endif /* __KERNEL_WORK_STEALING_H__ */ diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index b1561963e5d..e5e25eb6ca8 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -189,7 +189,7 @@ CCL_NAMESPACE_BEGIN ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderType type, int path_flag) { float stack[SVM_STACK_SIZE]; - int offset = sd->shader & SHADER_MASK; + int offset = ccl_fetch(sd, shader) & SHADER_MASK; while(1) { uint4 node = read_node(kg, &offset); diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h index b63978b6e1f..025ae96f59d 100644 --- a/intern/cycles/kernel/svm/svm_attribute.h +++ b/intern/cycles/kernel/svm/svm_attribute.h @@ -22,12 +22,12 @@ ccl_device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd, uint4 node, NodeAttributeType *type, NodeAttributeType *mesh_type, AttributeElement *elem, int *offset, uint *out_offset) { - if(sd->object != OBJECT_NONE) { + if(ccl_fetch(sd, object) != OBJECT_NONE) { /* find attribute by unique id */ uint id = node.y; - uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride; + uint attr_offset = ccl_fetch(sd, object)*kernel_data.bvh.attributes_map_stride; #ifdef __HAIR__ - attr_offset = (sd->type & PRIMITIVE_ALL_CURVE)? attr_offset + ATTR_PRIM_CURVE: attr_offset; + attr_offset = (ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE)? attr_offset + ATTR_PRIM_CURVE: attr_offset; #endif uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset); diff --git a/intern/cycles/kernel/svm/svm_camera.h b/intern/cycles/kernel/svm/svm_camera.h index 90249dfd978..00678a49d70 100644 --- a/intern/cycles/kernel/svm/svm_camera.h +++ b/intern/cycles/kernel/svm/svm_camera.h @@ -23,7 +23,7 @@ ccl_device void svm_node_camera(KernelGlobals *kg, ShaderData *sd, float *stack, float3 vector; Transform tfm = kernel_data.cam.worldtocamera; - vector = transform_point(&tfm, sd->P); + vector = transform_point(&tfm, ccl_fetch(sd, P)); zdepth = vector.z; distance = len(vector); diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 0d2d155f827..7cdcbc2d30c 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -25,12 +25,12 @@ ccl_device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type sc->data0 = eta; sc->data1 = 0.0f; sc->data2 = 0.0f; - sd->flag |= bsdf_refraction_setup(sc); + ccl_fetch(sd, flag) |= bsdf_refraction_setup(sc); } else { sc->data0 = 0.0f; sc->data1 = 0.0f; - sd->flag |= bsdf_reflection_setup(sc); + ccl_fetch(sd, flag) |= bsdf_reflection_setup(sc); } } else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) { @@ -39,9 +39,9 @@ ccl_device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type sc->data2 = eta; if(refract) - sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc); + ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_refraction_setup(sc); else - sd->flag |= bsdf_microfacet_beckmann_setup(sc); + ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_setup(sc); } else { sc->data0 = roughness; @@ -49,23 +49,23 @@ ccl_device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type sc->data2 = eta; if(refract) - sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc); + ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(sc); else - sd->flag |= bsdf_microfacet_ggx_setup(sc); + ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(sc); } } ccl_device_inline ShaderClosure *svm_node_closure_get_non_bsdf(ShaderData *sd, ClosureType type, float mix_weight) { - ShaderClosure *sc = &sd->closure[sd->num_closure]; + ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure)); - if(sd->num_closure < MAX_CLOSURE) { + if(ccl_fetch(sd, num_closure) < MAX_CLOSURE) { sc->weight *= mix_weight; sc->type = type; #ifdef __OSL__ sc->prim = NULL; #endif - sd->num_closure++; + ccl_fetch(sd, num_closure)++; return sc; } @@ -74,14 +74,15 @@ ccl_device_inline ShaderClosure *svm_node_closure_get_non_bsdf(ShaderData *sd, C ccl_device_inline ShaderClosure *svm_node_closure_get_bsdf(ShaderData *sd, float mix_weight) { - ShaderClosure *sc = &sd->closure[sd->num_closure]; + ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure)); + float3 weight = sc->weight * mix_weight; float sample_weight = fabsf(average(weight)); - if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) { + if(sample_weight > CLOSURE_WEIGHT_CUTOFF && ccl_fetch(sd, num_closure) < MAX_CLOSURE) { sc->weight = weight; sc->sample_weight = sample_weight; - sd->num_closure++; + ccl_fetch(sd, num_closure)++; #ifdef __OSL__ sc->prim = NULL; #endif @@ -93,14 +94,15 @@ ccl_device_inline ShaderClosure *svm_node_closure_get_bsdf(ShaderData *sd, float ccl_device_inline ShaderClosure *svm_node_closure_get_absorption(ShaderData *sd, float mix_weight) { - ShaderClosure *sc = &sd->closure[sd->num_closure]; + ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure)); + float3 weight = (make_float3(1.0f, 1.0f, 1.0f) - sc->weight) * mix_weight; float sample_weight = fabsf(average(weight)); - if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) { + if(sample_weight > CLOSURE_WEIGHT_CUTOFF && ccl_fetch(sd, num_closure) < MAX_CLOSURE) { sc->weight = weight; sc->sample_weight = sample_weight; - sd->num_closure++; + ccl_fetch(sd, num_closure)++; #ifdef __OSL__ sc->prim = NULL; #endif @@ -124,7 +126,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * if(mix_weight == 0.0f) return; - float3 N = stack_valid(data_node.x)? stack_load_float3(stack, data_node.x): sd->N; + float3 N = stack_valid(data_node.x)? stack_load_float3(stack, data_node.x): ccl_fetch(sd, N); float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __uint_as_float(node.z); float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w); @@ -142,13 +144,13 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->data0 = 0.0f; sc->data1 = 0.0f; sc->data2 = 0.0f; - sd->flag |= bsdf_diffuse_setup(sc); + ccl_fetch(sd, flag) |= bsdf_diffuse_setup(sc); } else { sc->data0 = roughness; sc->data1 = 0.0f; sc->data2 = 0.0f; - sd->flag |= bsdf_oren_nayar_setup(sc); + ccl_fetch(sd, flag) |= bsdf_oren_nayar_setup(sc); } } break; @@ -161,7 +163,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->data1 = 0.0f; sc->data2 = 0.0f; sc->N = N; - sd->flag |= bsdf_translucent_setup(sc); + ccl_fetch(sd, flag) |= bsdf_translucent_setup(sc); } break; } @@ -173,7 +175,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->data1 = 0.0f; sc->data2 = 0.0f; sc->N = N; - sd->flag |= bsdf_transparent_setup(sc); + ccl_fetch(sd, flag) |= bsdf_transparent_setup(sc); } break; } @@ -195,13 +197,13 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * /* setup bsdf */ if(type == CLOSURE_BSDF_REFLECTION_ID) - sd->flag |= bsdf_reflection_setup(sc); + ccl_fetch(sd, flag) |= bsdf_reflection_setup(sc); else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) - sd->flag |= bsdf_microfacet_beckmann_setup(sc); + ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_setup(sc); else if(type == CLOSURE_BSDF_MICROFACET_GGX_ID) - sd->flag |= bsdf_microfacet_ggx_setup(sc); + ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(sc); else - sd->flag |= bsdf_ashikhmin_shirley_setup(sc); + ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_setup(sc); } break; @@ -219,7 +221,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->N = N; float eta = fmaxf(param2, 1e-5f); - eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; + eta = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta; /* setup bsdf */ if(type == CLOSURE_BSDF_REFRACTION_ID) { @@ -227,7 +229,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->data1 = 0.0f; sc->data2 = 0.0f; - sd->flag |= bsdf_refraction_setup(sc); + ccl_fetch(sd, flag) |= bsdf_refraction_setup(sc); } else { sc->data0 = param1; @@ -235,9 +237,9 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->data2 = eta; if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) - sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc); + ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_refraction_setup(sc); else - sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc); + ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(sc); } } @@ -254,15 +256,15 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * #endif /* index of refraction */ float eta = fmaxf(param2, 1e-5f); - eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; + eta = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta; /* fresnel */ - float cosNO = dot(N, sd->I); + float cosNO = dot(N, ccl_fetch(sd, I)); float fresnel = fresnel_dielectric_cos(cosNO, eta); float roughness = param1; /* reflection */ - ShaderClosure *sc = &sd->closure[sd->num_closure]; + ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure)); float3 weight = sc->weight; float sample_weight = sc->sample_weight; @@ -283,7 +285,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * #endif /* refraction */ - sc = &sd->closure[sd->num_closure]; + sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure)); sc->weight = weight; sc->sample_weight = sample_weight; @@ -332,11 +334,11 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->data2 = 0.0f; if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID) - sd->flag |= bsdf_microfacet_beckmann_aniso_setup(sc); + ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_aniso_setup(sc); else if(type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID) - sd->flag |= bsdf_microfacet_ggx_aniso_setup(sc); + ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_aniso_setup(sc); else - sd->flag |= bsdf_ashikhmin_shirley_aniso_setup(sc); + ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_aniso_setup(sc); } break; } @@ -350,7 +352,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->data0 = saturate(param1); sc->data1 = 0.0f; sc->data2 = 0.0f; - sd->flag |= bsdf_ashikhmin_velvet_setup(sc); + ccl_fetch(sd, flag) |= bsdf_ashikhmin_velvet_setup(sc); } break; } @@ -366,9 +368,9 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->data2 = 0.0f; if(type == CLOSURE_BSDF_DIFFUSE_TOON_ID) - sd->flag |= bsdf_diffuse_toon_setup(sc); + ccl_fetch(sd, flag) |= bsdf_diffuse_toon_setup(sc); else - sd->flag |= bsdf_glossy_toon_setup(sc); + ccl_fetch(sd, flag) |= bsdf_glossy_toon_setup(sc); } break; } @@ -376,7 +378,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * case CLOSURE_BSDF_HAIR_REFLECTION_ID: case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: { - if(sd->flag & SD_BACKFACING && sd->type & PRIMITIVE_ALL_CURVE) { + if(ccl_fetch(sd, flag) & SD_BACKFACING && ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) { ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); if(sc) { @@ -389,11 +391,11 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->N = N; sc->data0 = 0.0f; sc->data1 = 0.0f; - sd->flag |= bsdf_transparent_setup(sc); + ccl_fetch(sd, flag) |= bsdf_transparent_setup(sc); } } else { - ShaderClosure *sc = &sd->closure[sd->num_closure]; + ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure)); sc = svm_node_closure_get_bsdf(sd, mix_weight); if(sc) { @@ -402,18 +404,18 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->data1 = param2; sc->data2 = -stack_load_float(stack, data_node.z); - if(!(sd->type & PRIMITIVE_ALL_CURVE)) { - sc->T = normalize(sd->dPdv); + if(!(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE)) { + sc->T = normalize(ccl_fetch(sd, dPdv)); sc->data2 = 0.0f; } else - sc->T = normalize(sd->dPdu); + sc->T = normalize(ccl_fetch(sd, dPdu)); if(type == CLOSURE_BSDF_HAIR_REFLECTION_ID) { - sd->flag |= bsdf_hair_reflection_setup(sc); + ccl_fetch(sd, flag) |= bsdf_hair_reflection_setup(sc); } else { - sd->flag |= bsdf_hair_transmission_setup(sc); + ccl_fetch(sd, flag) |= bsdf_hair_transmission_setup(sc); } } } @@ -423,9 +425,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * #endif #ifdef __SUBSURFACE__ +#ifndef __SPLIT_KERNEL__ +# define sc_next(sc) sc++ +# else +# define sc_next(sc) sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure)) +# endif case CLOSURE_BSSRDF_CUBIC_ID: case CLOSURE_BSSRDF_GAUSSIAN_ID: { - ShaderClosure *sc = &sd->closure[sd->num_closure]; + ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure)); float3 weight = sc->weight * mix_weight; float sample_weight = fabsf(average(weight)); @@ -435,7 +442,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR) param1 = 0.0f; - if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure+2 < MAX_CLOSURE) { + if(sample_weight > CLOSURE_WEIGHT_CUTOFF && ccl_fetch(sd, num_closure)+2 < MAX_CLOSURE) { /* radius * scale */ float3 radius = stack_load_float3(stack, data_node.z)*param1; /* sharpness */ @@ -455,10 +462,10 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->prim = NULL; #endif sc->N = N; - sd->flag |= bssrdf_setup(sc, (ClosureType)type); + ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)type); - sd->num_closure++; - sc++; + ccl_fetch(sd, num_closure)++; + sc_next(sc); } if(fabsf(weight.y) > 0.0f) { @@ -472,10 +479,10 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->prim = NULL; #endif sc->N = N; - sd->flag |= bssrdf_setup(sc, (ClosureType)type); + ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)type); - sd->num_closure++; - sc++; + ccl_fetch(sd, num_closure)++; + sc_next(sc); } if(fabsf(weight.z) > 0.0f) { @@ -489,15 +496,16 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->prim = NULL; #endif sc->N = N; - sd->flag |= bssrdf_setup(sc, (ClosureType)type); + ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)type); - sd->num_closure++; - sc++; + ccl_fetch(sd, num_closure)++; + sc_next(sc); } } break; } +# undef sc_next #endif default: break; @@ -525,7 +533,7 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float ShaderClosure *sc = svm_node_closure_get_absorption(sd, mix_weight * density); if(sc) { - sd->flag |= volume_absorption_setup(sc); + ccl_fetch(sd, flag) |= volume_absorption_setup(sc); } break; } @@ -535,7 +543,7 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float if(sc) { sc->data0 = param2; /* g */ sc->data1 = 0.0f; - sd->flag |= volume_henyey_greenstein_setup(sc); + ccl_fetch(sd, flag) |= volume_henyey_greenstein_setup(sc); } break; } @@ -560,7 +568,7 @@ ccl_device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 no else svm_node_closure_get_non_bsdf(sd, CLOSURE_EMISSION_ID, 1.0f); - sd->flag |= SD_EMISSION; + ccl_fetch(sd, flag) |= SD_EMISSION; } ccl_device void svm_node_closure_background(ShaderData *sd, float *stack, uint4 node) @@ -594,7 +602,7 @@ ccl_device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 nod else svm_node_closure_get_non_bsdf(sd, CLOSURE_HOLDOUT_ID, 1.0f); - sd->flag |= SD_HOLDOUT; + ccl_fetch(sd, flag) |= SD_HOLDOUT; } ccl_device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, uint4 node) @@ -612,15 +620,17 @@ ccl_device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, else svm_node_closure_get_non_bsdf(sd, CLOSURE_AMBIENT_OCCLUSION_ID, 1.0f); - sd->flag |= SD_AO; + ccl_fetch(sd, flag) |= SD_AO; } /* Closure Nodes */ ccl_device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight) { - if(sd->num_closure < MAX_CLOSURE) - sd->closure[sd->num_closure].weight = weight; + if(ccl_fetch(sd, num_closure) < MAX_CLOSURE) { + ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure)); + sc->weight = weight; + } } ccl_device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b) @@ -670,7 +680,7 @@ ccl_device void svm_node_mix_closure(ShaderData *sd, float *stack, uint4 node) ccl_device void svm_node_set_normal(KernelGlobals *kg, ShaderData *sd, float *stack, uint in_direction, uint out_normal) { float3 normal = stack_load_float3(stack, in_direction); - sd->N = normal; + ccl_fetch(sd, N) = normal; stack_store_float3(stack, out_normal, normal); } diff --git a/intern/cycles/kernel/svm/svm_displace.h b/intern/cycles/kernel/svm/svm_displace.h index 4a058905a93..8d4b07c9973 100644 --- a/intern/cycles/kernel/svm/svm_displace.h +++ b/intern/cycles/kernel/svm/svm_displace.h @@ -25,11 +25,11 @@ ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stac uint normal_offset, distance_offset, invert; decode_node_uchar4(node.y, &normal_offset, &distance_offset, &invert, NULL); - float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): sd->N; + float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): ccl_fetch(sd, N); /* get surface tangents from normal */ - float3 Rx = cross(sd->dP.dy, normal_in); - float3 Ry = cross(normal_in, sd->dP.dx); + float3 Rx = cross(ccl_fetch(sd, dP).dy, normal_in); + float3 Ry = cross(normal_in, ccl_fetch(sd, dP).dx); /* get bump values */ uint c_offset, x_offset, y_offset, strength_offset; @@ -40,7 +40,7 @@ ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stac float h_y = stack_load_float(stack, y_offset); /* compute surface gradient and determinant */ - float det = dot(sd->dP.dx, Rx); + float det = dot(ccl_fetch(sd, dP).dx, Rx); float3 surfgrad = (h_x - h_c)*Rx + (h_y - h_c)*Ry; float absdet = fabsf(det); @@ -65,7 +65,7 @@ ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stac ccl_device void svm_node_set_displacement(ShaderData *sd, float *stack, uint fac_offset) { float d = stack_load_float(stack, fac_offset); - sd->P += sd->N*d*0.1f; /* todo: get rid of this factor */ + ccl_fetch(sd, P) += ccl_fetch(sd, N)*d*0.1f; /* todo: get rid of this factor */ } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_fresnel.h b/intern/cycles/kernel/svm/svm_fresnel.h index 3703ec55015..23c97d80cb0 100644 --- a/intern/cycles/kernel/svm/svm_fresnel.h +++ b/intern/cycles/kernel/svm/svm_fresnel.h @@ -23,12 +23,12 @@ ccl_device void svm_node_fresnel(ShaderData *sd, float *stack, uint ior_offset, uint normal_offset, out_offset; decode_node_uchar4(node, &normal_offset, &out_offset, NULL, NULL); float eta = (stack_valid(ior_offset))? stack_load_float(stack, ior_offset): __uint_as_float(ior_value); - float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): sd->N; + float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): ccl_fetch(sd, N); eta = fmaxf(eta, 1e-5f); - eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; + eta = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta; - float f = fresnel_dielectric_cos(dot(sd->I, normal_in), eta); + float f = fresnel_dielectric_cos(dot(ccl_fetch(sd, I), normal_in), eta); stack_store_float(stack, out_offset, f); } @@ -44,18 +44,18 @@ ccl_device void svm_node_layer_weight(ShaderData *sd, float *stack, uint4 node) decode_node_uchar4(node.w, &type, &normal_offset, &out_offset, NULL); float blend = (stack_valid(blend_offset))? stack_load_float(stack, blend_offset): __uint_as_float(blend_value); - float3 normal_in = (stack_valid(normal_offset))? stack_load_float3(stack, normal_offset): sd->N; + float3 normal_in = (stack_valid(normal_offset))? stack_load_float3(stack, normal_offset): ccl_fetch(sd, N); float f; if(type == NODE_LAYER_WEIGHT_FRESNEL) { float eta = fmaxf(1.0f - blend, 1e-5f); - eta = (sd->flag & SD_BACKFACING)? eta: 1.0f/eta; + eta = (ccl_fetch(sd, flag) & SD_BACKFACING)? eta: 1.0f/eta; - f = fresnel_dielectric_cos(dot(sd->I, normal_in), eta); + f = fresnel_dielectric_cos(dot(ccl_fetch(sd, I), normal_in), eta); } else { - f = fabsf(dot(sd->I, normal_in)); + f = fabsf(dot(ccl_fetch(sd, I), normal_in)); if(blend != 0.5f) { blend = clamp(blend, 0.0f, 1.0f-1e-5f); diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index efbefa77d28..bb06254c3a9 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -23,15 +23,15 @@ ccl_device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stac float3 data; switch(type) { - case NODE_GEOM_P: data = sd->P; break; - case NODE_GEOM_N: data = sd->N; break; + case NODE_GEOM_P: data = ccl_fetch(sd, P); break; + case NODE_GEOM_N: data = ccl_fetch(sd, N); break; #ifdef __DPDU__ case NODE_GEOM_T: data = primitive_tangent(kg, sd); break; #endif - case NODE_GEOM_I: data = sd->I; break; - case NODE_GEOM_Ng: data = sd->Ng; break; + case NODE_GEOM_I: data = ccl_fetch(sd, I); break; + case NODE_GEOM_Ng: data = ccl_fetch(sd, Ng); break; #ifdef __UV__ - case NODE_GEOM_uv: data = make_float3(sd->u, sd->v, 0.0f); break; + case NODE_GEOM_uv: data = make_float3(ccl_fetch(sd, u), ccl_fetch(sd, v), 0.0f); break; #endif } @@ -44,8 +44,8 @@ ccl_device void svm_node_geometry_bump_dx(KernelGlobals *kg, ShaderData *sd, flo float3 data; switch(type) { - case NODE_GEOM_P: data = sd->P + sd->dP.dx; break; - case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dx, sd->v + sd->dv.dx, 0.0f); break; + case NODE_GEOM_P: data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx; break; + case NODE_GEOM_uv: data = make_float3(ccl_fetch(sd, u) + ccl_fetch(sd, du).dx, ccl_fetch(sd, v) + ccl_fetch(sd, dv).dx, 0.0f); break; default: svm_node_geometry(kg, sd, stack, type, out_offset); return; } @@ -61,8 +61,8 @@ ccl_device void svm_node_geometry_bump_dy(KernelGlobals *kg, ShaderData *sd, flo float3 data; switch(type) { - case NODE_GEOM_P: data = sd->P + sd->dP.dy; break; - case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dy, sd->v + sd->dv.dy, 0.0f); break; + case NODE_GEOM_P: data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy; break; + case NODE_GEOM_uv: data = make_float3(ccl_fetch(sd, u) + ccl_fetch(sd, du).dy, ccl_fetch(sd, v) + ccl_fetch(sd, dv).dy, 0.0f); break; default: svm_node_geometry(kg, sd, stack, type, out_offset); return; } @@ -83,9 +83,9 @@ ccl_device void svm_node_object_info(KernelGlobals *kg, ShaderData *sd, float *s stack_store_float3(stack, out_offset, object_location(kg, sd)); return; } - case NODE_INFO_OB_INDEX: data = object_pass_id(kg, sd->object); break; + case NODE_INFO_OB_INDEX: data = object_pass_id(kg, ccl_fetch(sd, object)); break; case NODE_INFO_MAT_INDEX: data = shader_pass_id(kg, sd); break; - case NODE_INFO_OB_RANDOM: data = object_random_number(kg, sd->object); break; + case NODE_INFO_OB_RANDOM: data = object_random_number(kg, ccl_fetch(sd, object)); break; default: data = 0.0f; break; } @@ -98,44 +98,44 @@ ccl_device void svm_node_particle_info(KernelGlobals *kg, ShaderData *sd, float { switch(type) { case NODE_INFO_PAR_INDEX: { - int particle_id = object_particle_id(kg, sd->object); + int particle_id = object_particle_id(kg, ccl_fetch(sd, object)); stack_store_float(stack, out_offset, particle_index(kg, particle_id)); break; } case NODE_INFO_PAR_AGE: { - int particle_id = object_particle_id(kg, sd->object); + int particle_id = object_particle_id(kg, ccl_fetch(sd, object)); stack_store_float(stack, out_offset, particle_age(kg, particle_id)); break; } case NODE_INFO_PAR_LIFETIME: { - int particle_id = object_particle_id(kg, sd->object); + int particle_id = object_particle_id(kg, ccl_fetch(sd, object)); stack_store_float(stack, out_offset, particle_lifetime(kg, particle_id)); break; } case NODE_INFO_PAR_LOCATION: { - int particle_id = object_particle_id(kg, sd->object); + int particle_id = object_particle_id(kg, ccl_fetch(sd, object)); stack_store_float3(stack, out_offset, particle_location(kg, particle_id)); break; } #if 0 /* XXX float4 currently not supported in SVM stack */ case NODE_INFO_PAR_ROTATION: { - int particle_id = object_particle_id(kg, sd->object); + int particle_id = object_particle_id(kg, ccl_fetch(sd, object)); stack_store_float4(stack, out_offset, particle_rotation(kg, particle_id)); break; } #endif case NODE_INFO_PAR_SIZE: { - int particle_id = object_particle_id(kg, sd->object); + int particle_id = object_particle_id(kg, ccl_fetch(sd, object)); stack_store_float(stack, out_offset, particle_size(kg, particle_id)); break; } case NODE_INFO_PAR_VELOCITY: { - int particle_id = object_particle_id(kg, sd->object); + int particle_id = object_particle_id(kg, ccl_fetch(sd, object)); stack_store_float3(stack, out_offset, particle_velocity(kg, particle_id)); break; } case NODE_INFO_PAR_ANGULAR_VELOCITY: { - int particle_id = object_particle_id(kg, sd->object); + int particle_id = object_particle_id(kg, ccl_fetch(sd, object)); stack_store_float3(stack, out_offset, particle_angular_velocity(kg, particle_id)); break; } @@ -153,7 +153,7 @@ ccl_device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *sta switch(type) { case NODE_INFO_CURVE_IS_STRAND: { - data = (sd->type & PRIMITIVE_ALL_CURVE) != 0; + data = (ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) != 0; stack_store_float(stack, out_offset, data); break; } @@ -165,7 +165,7 @@ ccl_device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *sta break; } /*case NODE_INFO_CURVE_FADE: { - data = sd->curve_transparency; + data = ccl_fetch(sd, curve_transparency); stack_store_float(stack, out_offset, data); break; }*/ diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index 08a6c01162c..caf0b37ba35 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -392,10 +392,10 @@ ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *sta ccl_device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) { /* get object space normal */ - float3 N = sd->N; + float3 N = ccl_fetch(sd, N); - N = sd->N; - if(sd->object != OBJECT_NONE) + N = ccl_fetch(sd, N); + if(ccl_fetch(sd, object) != OBJECT_NONE) object_inverse_normal_transform(kg, sd, &N); /* project from direction vector to barycentric coordinates in triangles */ diff --git a/intern/cycles/kernel/svm/svm_light_path.h b/intern/cycles/kernel/svm/svm_light_path.h index ffadafb1d0c..a235dd35224 100644 --- a/intern/cycles/kernel/svm/svm_light_path.h +++ b/intern/cycles/kernel/svm/svm_light_path.h @@ -31,10 +31,10 @@ ccl_device void svm_node_light_path(ShaderData *sd, float *stack, uint type, uin case NODE_LP_reflection: info = (path_flag & PATH_RAY_REFLECT)? 1.0f: 0.0f; break; case NODE_LP_transmission: info = (path_flag & PATH_RAY_TRANSMIT)? 1.0f: 0.0f; break; case NODE_LP_volume_scatter: info = (path_flag & PATH_RAY_VOLUME_SCATTER)? 1.0f: 0.0f; break; - case NODE_LP_backfacing: info = (sd->flag & SD_BACKFACING)? 1.0f: 0.0f; break; - case NODE_LP_ray_length: info = sd->ray_length; break; - case NODE_LP_ray_depth: info = (float)sd->ray_depth; break; - case NODE_LP_ray_transparent: info = (float)sd->transparent_depth; break; + case NODE_LP_backfacing: info = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f: 0.0f; break; + case NODE_LP_ray_length: info = ccl_fetch(sd, ray_length); break; + case NODE_LP_ray_depth: info = (float)ccl_fetch(sd, ray_depth); break; + case NODE_LP_ray_transparent: info = (float)ccl_fetch(sd, transparent_depth); break; } stack_store_float(stack, out_offset, info); @@ -53,14 +53,14 @@ ccl_device void svm_node_light_falloff(ShaderData *sd, float *stack, uint4 node) switch(type) { case NODE_LIGHT_FALLOFF_QUADRATIC: break; - case NODE_LIGHT_FALLOFF_LINEAR: strength *= sd->ray_length; break; - case NODE_LIGHT_FALLOFF_CONSTANT: strength *= sd->ray_length*sd->ray_length; break; + case NODE_LIGHT_FALLOFF_LINEAR: strength *= ccl_fetch(sd, ray_length); break; + case NODE_LIGHT_FALLOFF_CONSTANT: strength *= ccl_fetch(sd, ray_length)*ccl_fetch(sd, ray_length); break; } float smooth = stack_load_float(stack, smooth_offset); if(smooth > 0.0f) { - float squared = sd->ray_length*sd->ray_length; + float squared = ccl_fetch(sd, ray_length)*ccl_fetch(sd, ray_length); strength *= squared/(smooth + squared); } diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index a399acf3c0f..eebd9bee420 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -31,9 +31,9 @@ ccl_device void svm_node_tex_coord(KernelGlobals *kg, switch(type) { case NODE_TEXCO_OBJECT: { - data = sd->P; + data = ccl_fetch(sd, P); if(node.w == 0) { - if(sd->object != OBJECT_NONE) { + if(ccl_fetch(sd, object) != OBJECT_NONE) { object_inverse_position_transform(kg, sd, &data); } } @@ -48,48 +48,48 @@ ccl_device void svm_node_tex_coord(KernelGlobals *kg, break; } case NODE_TEXCO_NORMAL: { - data = sd->N; - if(sd->object != OBJECT_NONE) + data = ccl_fetch(sd, N); + if(ccl_fetch(sd, object) != OBJECT_NONE) object_inverse_normal_transform(kg, sd, &data); break; } case NODE_TEXCO_CAMERA: { Transform tfm = kernel_data.cam.worldtocamera; - if(sd->object != OBJECT_NONE) - data = transform_point(&tfm, sd->P); + if(ccl_fetch(sd, object) != OBJECT_NONE) + data = transform_point(&tfm, ccl_fetch(sd, P)); else - data = transform_point(&tfm, sd->P + camera_position(kg)); + data = transform_point(&tfm, ccl_fetch(sd, P) + camera_position(kg)); break; } case NODE_TEXCO_WINDOW: { - if((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) - data = camera_world_to_ndc(kg, sd, sd->ray_P); + if((path_flag & PATH_RAY_CAMERA) && ccl_fetch(sd, object) == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) + data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, ray_P)); else - data = camera_world_to_ndc(kg, sd, sd->P); + data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, P)); data.z = 0.0f; break; } case NODE_TEXCO_REFLECTION: { - if(sd->object != OBJECT_NONE) - data = 2.0f*dot(sd->N, sd->I)*sd->N - sd->I; + if(ccl_fetch(sd, object) != OBJECT_NONE) + data = 2.0f*dot(ccl_fetch(sd, N), ccl_fetch(sd, I))*ccl_fetch(sd, N) - ccl_fetch(sd, I); else - data = sd->I; + data = ccl_fetch(sd, I); break; } case NODE_TEXCO_DUPLI_GENERATED: { - data = object_dupli_generated(kg, sd->object); + data = object_dupli_generated(kg, ccl_fetch(sd, object)); break; } case NODE_TEXCO_DUPLI_UV: { - data = object_dupli_uv(kg, sd->object); + data = object_dupli_uv(kg, ccl_fetch(sd, object)); break; } case NODE_TEXCO_VOLUME_GENERATED: { - data = sd->P; + data = ccl_fetch(sd, P); #ifdef __VOLUME__ - if(sd->object != OBJECT_NONE) + if(ccl_fetch(sd, object) != OBJECT_NONE) data = volume_normalized_position(kg, sd, data); #endif break; @@ -113,9 +113,9 @@ ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, switch(type) { case NODE_TEXCO_OBJECT: { - data = sd->P + sd->dP.dx; + data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx; if(node.w == 0) { - if(sd->object != OBJECT_NONE) { + if(ccl_fetch(sd, object) != OBJECT_NONE) { object_inverse_position_transform(kg, sd, &data); } } @@ -130,48 +130,48 @@ ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, break; } case NODE_TEXCO_NORMAL: { - data = sd->N; - if(sd->object != OBJECT_NONE) + data = ccl_fetch(sd, N); + if(ccl_fetch(sd, object) != OBJECT_NONE) object_inverse_normal_transform(kg, sd, &data); break; } case NODE_TEXCO_CAMERA: { Transform tfm = kernel_data.cam.worldtocamera; - if(sd->object != OBJECT_NONE) - data = transform_point(&tfm, sd->P + sd->dP.dx); + if(ccl_fetch(sd, object) != OBJECT_NONE) + data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx); else - data = transform_point(&tfm, sd->P + sd->dP.dx + camera_position(kg)); + data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx + camera_position(kg)); break; } case NODE_TEXCO_WINDOW: { - if((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) - data = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dx); + if((path_flag & PATH_RAY_CAMERA) && ccl_fetch(sd, object) == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) + data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, ray_P) + ccl_fetch(sd, ray_dP).dx); else - data = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dx); + data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx); data.z = 0.0f; break; } case NODE_TEXCO_REFLECTION: { - if(sd->object != OBJECT_NONE) - data = 2.0f*dot(sd->N, sd->I)*sd->N - sd->I; + if(ccl_fetch(sd, object) != OBJECT_NONE) + data = 2.0f*dot(ccl_fetch(sd, N), ccl_fetch(sd, I))*ccl_fetch(sd, N) - ccl_fetch(sd, I); else - data = sd->I; + data = ccl_fetch(sd, I); break; } case NODE_TEXCO_DUPLI_GENERATED: { - data = object_dupli_generated(kg, sd->object); + data = object_dupli_generated(kg, ccl_fetch(sd, object)); break; } case NODE_TEXCO_DUPLI_UV: { - data = object_dupli_uv(kg, sd->object); + data = object_dupli_uv(kg, ccl_fetch(sd, object)); break; } case NODE_TEXCO_VOLUME_GENERATED: { - data = sd->P + sd->dP.dx; + data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx; #ifdef __VOLUME__ - if(sd->object != OBJECT_NONE) + if(ccl_fetch(sd, object) != OBJECT_NONE) data = volume_normalized_position(kg, sd, data); #endif break; @@ -198,9 +198,9 @@ ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, switch(type) { case NODE_TEXCO_OBJECT: { - data = sd->P + sd->dP.dy; + data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy; if(node.w == 0) { - if(sd->object != OBJECT_NONE) { + if(ccl_fetch(sd, object) != OBJECT_NONE) { object_inverse_position_transform(kg, sd, &data); } } @@ -215,48 +215,48 @@ ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, break; } case NODE_TEXCO_NORMAL: { - data = sd->N; - if(sd->object != OBJECT_NONE) + data = ccl_fetch(sd, N); + if(ccl_fetch(sd, object) != OBJECT_NONE) object_inverse_normal_transform(kg, sd, &data); break; } case NODE_TEXCO_CAMERA: { Transform tfm = kernel_data.cam.worldtocamera; - if(sd->object != OBJECT_NONE) - data = transform_point(&tfm, sd->P + sd->dP.dy); + if(ccl_fetch(sd, object) != OBJECT_NONE) + data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy); else - data = transform_point(&tfm, sd->P + sd->dP.dy + camera_position(kg)); + data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy + camera_position(kg)); break; } case NODE_TEXCO_WINDOW: { - if((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) - data = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dy); + if((path_flag & PATH_RAY_CAMERA) && ccl_fetch(sd, object) == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) + data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, ray_P) + ccl_fetch(sd, ray_dP).dy); else - data = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dy); + data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy); data.z = 0.0f; break; } case NODE_TEXCO_REFLECTION: { - if(sd->object != OBJECT_NONE) - data = 2.0f*dot(sd->N, sd->I)*sd->N - sd->I; + if(ccl_fetch(sd, object) != OBJECT_NONE) + data = 2.0f*dot(ccl_fetch(sd, N), ccl_fetch(sd, I))*ccl_fetch(sd, N) - ccl_fetch(sd, I); else - data = sd->I; + data = ccl_fetch(sd, I); break; } case NODE_TEXCO_DUPLI_GENERATED: { - data = object_dupli_generated(kg, sd->object); + data = object_dupli_generated(kg, ccl_fetch(sd, object)); break; } case NODE_TEXCO_DUPLI_UV: { - data = object_dupli_uv(kg, sd->object); + data = object_dupli_uv(kg, ccl_fetch(sd, object)); break; } case NODE_TEXCO_VOLUME_GENERATED: { - data = sd->P + sd->dP.dy; + data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy; #ifdef __VOLUME__ - if(sd->object != OBJECT_NONE) + if(ccl_fetch(sd, object) != OBJECT_NONE) data = volume_normalized_position(kg, sd, data); #endif break; @@ -281,7 +281,7 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st if(space == NODE_NORMAL_MAP_TANGENT) { /* tangent space */ - if(sd->object == OBJECT_NONE) { + if(ccl_fetch(sd, object) == OBJECT_NONE) { stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f)); return; } @@ -302,11 +302,11 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st float sign = primitive_attribute_float(kg, sd, attr_sign_elem, attr_sign_offset, NULL, NULL); float3 normal; - if(sd->shader & SHADER_SMOOTH_NORMAL) { + if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) { normal = primitive_attribute_float3(kg, sd, attr_normal_elem, attr_normal_offset, NULL, NULL); } else { - normal = sd->Ng; + normal = ccl_fetch(sd, Ng); object_inverse_normal_transform(kg, sd, &normal); } @@ -337,7 +337,7 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st if(strength != 1.0f) { strength = max(strength, 0.0f); - N = normalize(sd->N + (N - sd->N)*strength); + N = normalize(ccl_fetch(sd, N) + (N - ccl_fetch(sd, N))*strength); } stack_store_float3(stack, normal_offset, N); @@ -367,7 +367,7 @@ ccl_device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack float3 generated; if(attr_offset == ATTR_STD_NOT_FOUND) - generated = sd->P; + generated = ccl_fetch(sd, P); else generated = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL); @@ -380,7 +380,7 @@ ccl_device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack } object_normal_transform(kg, sd, &tangent); - tangent = cross(sd->N, normalize(cross(tangent, sd->N))); + tangent = cross(ccl_fetch(sd, N), normalize(cross(tangent, ccl_fetch(sd, N)))); stack_store_float3(stack, tangent_offset, tangent); } diff --git a/intern/cycles/kernel/svm/svm_vector_transform.h b/intern/cycles/kernel/svm/svm_vector_transform.h index 4e92f27acdb..4c32130d06d 100644 --- a/intern/cycles/kernel/svm/svm_vector_transform.h +++ b/intern/cycles/kernel/svm/svm_vector_transform.h @@ -33,7 +33,7 @@ ccl_device void svm_node_vector_transform(KernelGlobals *kg, ShaderData *sd, flo NodeVectorTransformConvertSpace to = (NodeVectorTransformConvertSpace)ito; Transform tfm; - bool is_object = (sd->object != OBJECT_NONE); + bool is_object = (ccl_fetch(sd, object) != OBJECT_NONE); bool is_direction = (type == NODE_VECTOR_TRANSFORM_TYPE_VECTOR || type == NODE_VECTOR_TRANSFORM_TYPE_NORMAL); /* From world */ diff --git a/intern/cycles/kernel/svm/svm_wireframe.h b/intern/cycles/kernel/svm/svm_wireframe.h index eaa17f8ce57..30ccd523add 100644 --- a/intern/cycles/kernel/svm/svm_wireframe.h +++ b/intern/cycles/kernel/svm/svm_wireframe.h @@ -41,9 +41,9 @@ ccl_device float wireframe(KernelGlobals *kg, float3 *P) { #ifdef __HAIR__ - if(sd->prim != PRIM_NONE && sd->type & PRIMITIVE_ALL_TRIANGLE) + if(ccl_fetch(sd, prim) != PRIM_NONE && ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) #else - if(sd->prim != PRIM_NONE) + if(ccl_fetch(sd, prim) != PRIM_NONE) #endif { float3 Co[3]; @@ -52,12 +52,12 @@ ccl_device float wireframe(KernelGlobals *kg, /* Triangles */ int np = 3; - if(sd->type & PRIMITIVE_TRIANGLE) - triangle_vertices(kg, sd->prim, Co); + if(ccl_fetch(sd, type) & PRIMITIVE_TRIANGLE) + triangle_vertices(kg, ccl_fetch(sd, prim), Co); else - motion_triangle_vertices(kg, sd->object, sd->prim, sd->time, Co); + motion_triangle_vertices(kg, ccl_fetch(sd, object), ccl_fetch(sd, prim), ccl_fetch(sd, time), Co); - if(!(sd->flag & SD_TRANSFORM_APPLIED)) { + if(!(ccl_fetch(sd, flag) & SD_TRANSFORM_APPLIED)) { object_position_transform(kg, sd, &Co[0]); object_position_transform(kg, sd, &Co[1]); object_position_transform(kg, sd, &Co[2]); @@ -66,8 +66,8 @@ ccl_device float wireframe(KernelGlobals *kg, if(pixel_size) { // Project the derivatives of P to the viewing plane defined // by I so we have a measure of how big is a pixel at this point - float pixelwidth_x = len(sd->dP.dx - dot(sd->dP.dx, sd->I) * sd->I); - float pixelwidth_y = len(sd->dP.dy - dot(sd->dP.dy, sd->I) * sd->I); + float pixelwidth_x = len(ccl_fetch(sd, dP).dx - dot(ccl_fetch(sd, dP).dx, ccl_fetch(sd, I)) * ccl_fetch(sd, I)); + float pixelwidth_y = len(ccl_fetch(sd, dP).dy - dot(ccl_fetch(sd, dP).dy, ccl_fetch(sd, I)) * ccl_fetch(sd, I)); // Take the average of both axis' length pixelwidth = (pixelwidth_x + pixelwidth_y) * 0.5f; } @@ -106,16 +106,27 @@ ccl_device void svm_node_wireframe(KernelGlobals *kg, int pixel_size = (int)use_pixel_size; /* Calculate wireframe */ - float f = wireframe(kg, sd, size, pixel_size, &sd->P); +#ifdef __SPLIT_KERNEL__ + /* TODO(sergey): This is because sd is actually a global space, + * which makes it difficult to re-use same wireframe() function. + * + * With OpenCL 2.0 it's possible to avoid this change, but for until + * then we'll be living with such an exception. + */ + float3 P = ccl_fetch(sd, P); + float f = wireframe(kg, sd, size, pixel_size, &P); +#else + float f = wireframe(kg, sd, size, pixel_size, &ccl_fetch(sd, P)); +#endif /* TODO(sergey): Think of faster way to calculate derivatives. */ if(bump_offset == NODE_BUMP_OFFSET_DX) { - float3 Px = sd->P - sd->dP.dx; - f += (f - wireframe(kg, sd, size, pixel_size, &Px)) / len(sd->dP.dx); + float3 Px = ccl_fetch(sd, P) - ccl_fetch(sd, dP).dx; + f += (f - wireframe(kg, sd, size, pixel_size, &Px)) / len(ccl_fetch(sd, dP).dx); } else if(bump_offset == NODE_BUMP_OFFSET_DY) { - float3 Py = sd->P - sd->dP.dy; - f += (f - wireframe(kg, sd, size, pixel_size, &Py)) / len(sd->dP.dy); + float3 Py = ccl_fetch(sd, P) - ccl_fetch(sd, dP).dy; + f += (f - wireframe(kg, sd, size, pixel_size, &Py)) / len(ccl_fetch(sd, dP).dy); } if(stack_valid(out_fac)) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index aacb81faf83..7b329af008d 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -807,7 +807,10 @@ void Session::update_status_time(bool show_pause, bool show_done) substatus = string_printf("Path Tracing Tile %d/%d", tile, num_tiles); - if((is_gpu && !is_multidevice) || (is_cpu && num_tiles == 1)) { + if(((is_gpu && !is_multidevice) || (is_cpu && num_tiles == 1)) && !device->info.use_split_kernel) { + /* When using split-kernel (OpenCL) each thread in a tile will be working on a different + * sample. Can't display sample number when device uses split-kernel + */ /* when rendering on GPU multithreading happens within single tile, as in * tiles are handling sequentially and in this case we could display * currently rendering sample number -- cgit v1.2.3 From 2840a5de8f26835df8e8a43972fd3eb2bae0ef73 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 May 2015 19:56:38 +0500 Subject: Cycles: Workaround for AMD compiler crashing building the split kernel It's a but in compiler but it's nice to have working kernel for until that bug is fixed. --- intern/cycles/kernel/kernel_types.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 303a78d8ac0..d8c47e48702 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -470,11 +470,27 @@ typedef struct differential { /* Ray */ typedef struct Ray { +/* TODO(sergey): This is only needed because current AMD + * compilet has hard time bulding the kernel with this + * reshuffle. And at the same time reshuffle will cause + * less optimal CPU code in certain places. + * + * We'll get rid of this nasty eception once AMD compiler + * is fixed. + */ +#ifndef __KERNEL_OPENCL_AMD__ float3 P; /* origin */ float3 D; /* direction */ float t; /* length of the ray */ float time; /* time (for motion blur) */ +#else + float t; /* length of the ray */ + float time; /* time (for motion blur) */ + float3 P; /* origin */ + float3 D; /* direction */ +#endif + #ifdef __RAY_DIFFERENTIALS__ differential3 dP; differential3 dD; -- cgit v1.2.3 From 8647c7d5010a844349ea6f7d180408cafbbb4848 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Sat, 9 May 2015 18:45:54 +0200 Subject: Fix T38335: incorrect triangle index in raycast with more than 2 quads eb81153896 broke the fix for T38335, and this fix was incomplete, now we iterate by triangles and polys in the same while block. --- .../gameengine/Physics/Bullet/CcdPhysicsController.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 5c5a4d3cc56..48f85410cf0 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -2436,7 +2436,9 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RA m_polygonIndexArray.resize(tot_bt_tris); - for (int p = 0; p < numpolys; p++) { + int p = 0; + int t = 0; + while (t < tot_bt_tris) { RAS_Polygon *poly = meshobj->GetPolygon(p); if (poly->IsCollider()) { @@ -2465,12 +2467,17 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RA *tri_pt++ = vert_remap_array[v_orig]; } } - m_polygonIndexArray[p] = p; + // first triangle + m_polygonIndexArray[t] = p; + + // if the poly is a quad we transform it in two triangles if (poly->VertexCount() == 4) { - p++; - // if the poly is a quad we transform it in two triangles - m_polygonIndexArray[p] = p; + t++; + // second triangle + m_polygonIndexArray[t] = p; } + t++; + p++; } } -- cgit v1.2.3 From 136d7a4f6239308ba8b8533b31c3d2a21c4f43cc Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 9 May 2015 23:40:26 +0500 Subject: Cycles: Only whitelist AMD GPU devices in the OpenCL section Only those ones are priority for now, all the rest are still testable if CYCLES_OPENCL_TEST or CYCLES_OPENCL_SPLIT_KERNEL_TEST environment variables are set. --- intern/cycles/device/device_opencl.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 25eb160d71b..e342010567f 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -3346,6 +3346,10 @@ void device_opencl_info(vector& devices) /* devices are numbered consecutively across platforms */ int num_base = 0; + const bool force_all_platforms = + (getenv("CYCLES_OPENCL_TEST") != NULL) || + (getenv("CYCLES_OPENCL_SPLIT_KERNEL_TEST")) != NULL; + for(int platform = 0; platform < num_platforms; platform++, num_base += num_devices) { num_devices = 0; if(clGetDeviceIDs(platform_ids[platform], opencl_device_type(), 0, NULL, &num_devices) != CL_SUCCESS || num_devices == 0) @@ -3360,6 +3364,17 @@ void device_opencl_info(vector& devices) clGetPlatformInfo(platform_ids[platform], CL_PLATFORM_NAME, sizeof(pname), &pname, NULL); string platform_name = pname; + cl_device_type device_type; + clGetDeviceInfo(device_ids[platform], CL_DEVICE_TYPE, sizeof(cl_device_type), &device_type, NULL); + + /* TODO(sergey): Make it an utility function to check whitelisted devices. */ + if(!(force_all_platforms || + (platform_name == "AMD Accelerated Parallel Processing" && + device_type == CL_DEVICE_TYPE_GPU))) + { + continue; + } + /* add devices */ for(int num = 0; num < num_devices; num++) { cl_device_id device_id = device_ids[num]; -- cgit v1.2.3 From 583fd3af659fc5526a150d30b6a7a5bc2f0d484f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 May 2015 00:53:32 +0500 Subject: Cycles: Fix typo in global space version of normal transform It was using direction transform, which is obviously wrong. --- intern/cycles/kernel/geom/geom_object.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h index 40cbca243a7..d75a9bb15ba 100644 --- a/intern/cycles/kernel/geom/geom_object.h +++ b/intern/cycles/kernel/geom/geom_object.h @@ -540,7 +540,7 @@ ccl_device_inline void object_normal_transform_addrspace(KernelGlobals *kg, ccl_addr_space float3 *N) { float3 private_N = *N; - object_dir_transform(kg, sd, &private_N); + object_normal_transform(kg, sd, &private_N); *N = private_N; } #endif -- cgit v1.2.3 From dc95ca92ca224d26423c5d63b33e7714a6a8c9ce Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Sun, 10 May 2015 00:54:06 +0200 Subject: BGE: Fix T43822 Videotexture does not use sky color for off-screen rendering Make scene background color as default for render-to-texture instead of current blue color (0, 0, 255). It is very useful for mirrors setups. Reviewers: moguri, ben2610, sybren, panzergame, hg1 Reviewed By: panzergame, hg1, moguri Subscribers: mpan3 Differential Revision: https://developer.blender.org/D1287 --- source/gameengine/Ketsji/KX_WorldInfo.cpp | 5 +++++ source/gameengine/Ketsji/KX_WorldInfo.h | 1 + source/gameengine/VideoTexture/ImageRender.cpp | 19 ++++++++++++++++--- source/gameengine/VideoTexture/ImageRender.h | 2 +- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/source/gameengine/Ketsji/KX_WorldInfo.cpp b/source/gameengine/Ketsji/KX_WorldInfo.cpp index e4bf439501f..21e72504a2b 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.cpp +++ b/source/gameengine/Ketsji/KX_WorldInfo.cpp @@ -100,6 +100,11 @@ void KX_WorldInfo::setBackColor(float r, float g, float b) } } +const float *KX_WorldInfo::getBackColor(void) const +{ + return m_backgroundcolor; +} + void KX_WorldInfo::setMistType(short type) { m_misttype = type; diff --git a/source/gameengine/Ketsji/KX_WorldInfo.h b/source/gameengine/Ketsji/KX_WorldInfo.h index 64304e594cc..0e8fe3c730a 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.h +++ b/source/gameengine/Ketsji/KX_WorldInfo.h @@ -88,6 +88,7 @@ public: void setMistIntensity(float intensity); void setMistColor(float r, float g, float b); void setBackColor(float r, float g, float b); + const float *getBackColor() const; void setAmbientColor(float r, float g, float b); void UpdateBackGround(); void UpdateWorldSettings(); diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 6a898ff50c2..2b2a6e0778b 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -75,8 +75,8 @@ ImageRender::ImageRender (KX_Scene *scene, KX_Camera * camera) : m_mirrorHalfWidth(0.f), m_mirrorHalfHeight(0.f) { - // initialize background color - setBackground(0, 0, 255, 255); + // initialize background color to scene background color as default + setBackgroundFromScene(m_scene); // retrieve rendering objects m_engine = KX_GetActiveEngine(); m_rasterizer = m_engine->GetRasterizer(); @@ -100,6 +100,18 @@ void ImageRender::setBackground (int red, int green, int blue, int alpha) m_background[3] = (alpha < 0) ? 0.f : (alpha > 255) ? 1.f : float(alpha)/255.f; } +// set background color from scene +void ImageRender::setBackgroundFromScene (KX_Scene *scene) +{ + if (scene) { + const float *background_color = scene->GetWorldInfo()->getBackColor(); + setBackground((int) (background_color[0] * 255.0f), (int) (background_color[1] * 255.0f), (int) (background_color[2] * 255.0f), 255); + } + else { + setBackground(0, 0, 255, 255); + } +} + // capture image from viewport void ImageRender::calcImage (unsigned int texId, double ts) @@ -733,7 +745,8 @@ ImageRender::ImageRender (KX_Scene *scene, KX_GameObject *observer, KX_GameObjec m_mirrorX = m_mirrorY.cross(m_mirrorZ); m_render = true; - setBackground(0, 0, 255, 255); + // set mirror background color to scene background color as default + setBackgroundFromScene(m_scene); } diff --git a/source/gameengine/VideoTexture/ImageRender.h b/source/gameengine/VideoTexture/ImageRender.h index 98dceeaafe1..bdf442c82d0 100644 --- a/source/gameengine/VideoTexture/ImageRender.h +++ b/source/gameengine/VideoTexture/ImageRender.h @@ -100,7 +100,7 @@ protected: void Render(); void SetupRenderFrame(KX_Scene *scene, KX_Camera* cam); void RenderFrame(KX_Scene* scene, KX_Camera* cam); - void SetBackGround(KX_WorldInfo* wi); + void setBackgroundFromScene(KX_Scene *scene); void SetWorldSettings(KX_WorldInfo* wi); }; -- cgit v1.2.3 From d6b57436efad545347b4403610dd3af642d4378d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 10 May 2015 15:06:44 +1000 Subject: UI: move sharp/smooth out of vertex menu Was confusing to have shade smooth/soft in both edge & vertex menu named differently. This is an edge-flag, so keep in the edge-menu, use vertex option when in vertex mode. --- release/scripts/startup/bl_ui/space_view3d.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 59fc3692e13..02acb8291db 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -2277,13 +2277,6 @@ class VIEW3D_MT_edit_mesh_vertices(Menu): layout.separator() - op = layout.operator("mesh.mark_sharp", text="Shade Smooth") - op.use_verts = True - op.clear = True - layout.operator("mesh.mark_sharp", text="Shade Sharp").use_verts = True - - layout.separator() - layout.operator("mesh.bevel").vertex_only = True layout.operator("mesh.convex_hull") layout.operator("mesh.vertices_smooth") @@ -2306,6 +2299,8 @@ class VIEW3D_MT_edit_mesh_edges(Menu): def draw(self, context): layout = self.layout + toolsettings = context.tool_settings + with_freestyle = bpy.app.build_options.freestyle layout.operator_context = 'INVOKE_REGION_WIN' @@ -2326,8 +2321,16 @@ class VIEW3D_MT_edit_mesh_edges(Menu): layout.separator() - layout.operator("mesh.mark_sharp") - layout.operator("mesh.mark_sharp", text="Clear Sharp").clear = True + if not toolsettings.mesh_select_mode[0]: + # edge mode + layout.operator("mesh.mark_sharp") + layout.operator("mesh.mark_sharp", text="Clear Sharp").clear = True + else: + # vert mode + layout.operator("mesh.mark_sharp").use_verts = True + props = layout.operator("mesh.mark_sharp", text="Clear Sharp") + props.use_verts = True + props.clear = True layout.separator() -- cgit v1.2.3 From 45d9df853ea8e01b4cfb04922c19a44545b0bd44 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 10 May 2015 15:23:41 +1000 Subject: UI: consistent naming for operator props --- release/scripts/startup/bl_ui/properties_freestyle.py | 9 +++++---- release/scripts/startup/bl_ui/space_sequencer.py | 12 ++++++------ release/scripts/startup/bl_ui/space_view3d.py | 6 +++--- release/scripts/startup/bl_ui/space_view3d_toolbar.py | 12 ++++++------ 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py index 8f8d8470fec..995136b0d97 100644 --- a/release/scripts/startup/bl_ui/properties_freestyle.py +++ b/release/scripts/startup/bl_ui/properties_freestyle.py @@ -690,10 +690,11 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel, row.prop(linestyle, "texture_spacing", text="Spacing Along Stroke") row = layout.row() - op = row.operator("wm.properties_context_change", - text="Go to Linestyle Textures Properties", - icon='TEXTURE') - op.context = 'TEXTURE' + props = row.operator( + "wm.properties_context_change", + text="Go to Linestyle Textures Properties", + icon='TEXTURE') + props.context = 'TEXTURE' elif linestyle.panel == 'MISC': pass diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 0d512b263ac..06611db3213 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -230,12 +230,12 @@ class SEQUENCER_MT_select(Menu): layout.operator("sequencer.select_active_side", text="Strips to the Left").side = 'LEFT' layout.operator("sequencer.select_active_side", text="Strips to the Right").side = 'RIGHT' - op = layout.operator("sequencer.select", text="All strips to the Left") - op.left_right = 'LEFT' - op.linked_time = True - op = layout.operator("sequencer.select", text="All strips to the Right") - op.left_right = 'RIGHT' - op.linked_time = True + props = layout.operator("sequencer.select", text="All strips to the Left") + props.left_right = 'LEFT' + props.linked_time = True + props = layout.operator("sequencer.select", text="All strips to the Right") + props.left_right = 'RIGHT' + props.linked_time = True layout.separator() layout.operator("sequencer.select_handles", text="Surrounding Handles").side = 'BOTH' diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 02acb8291db..a4de4f858e7 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1666,9 +1666,9 @@ class VIEW3D_MT_paint_weight(Menu): layout.operator("object.vertex_group_quantize", text="Quantize") layout.operator("object.vertex_group_levels", text="Levels") layout.operator("object.vertex_group_blend", text="Blend") - prop = layout.operator("object.data_transfer", text="Transfer Weights") - prop.use_reverse_transfer = True - prop.data_type = 'VGROUP_WEIGHTS' + props = layout.operator("object.data_transfer", text="Transfer Weights") + props.use_reverse_transfer = True + props.data_type = 'VGROUP_WEIGHTS' layout.operator("object.vertex_group_limit_total", text="Limit Total") layout.operator("object.vertex_group_fix", text="Fix Deforms") diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 5fa3a559ab9..1f7d5178665 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -407,9 +407,9 @@ class VIEW3D_PT_tools_shading(View3DPanel, Panel): row.operator("mesh.mark_sharp", text="Sharp") col.label(text="Vertices:") row = col.row(align=True) - op = row.operator("mesh.mark_sharp", text="Smooth") - op.use_verts = True - op.clear = True + props = row.operator("mesh.mark_sharp", text="Smooth") + props.use_verts = True + props.clear = True row.operator("mesh.mark_sharp", text="Sharp").use_verts = True col = layout.column(align=True) @@ -1607,9 +1607,9 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel): col = layout.column() col.operator("paint.weight_gradient") - prop = col.operator("object.data_transfer", text="Transfer Weights") - prop.use_reverse_transfer = True - prop.data_type = 'VGROUP_WEIGHTS' + props = col.operator("object.data_transfer", text="Transfer Weights") + props.use_reverse_transfer = True + props.data_type = 'VGROUP_WEIGHTS' class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel): -- cgit v1.2.3 From 1fb97ffeedc9aefa4351b34bdc51764817dd2140 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 10 May 2015 09:13:16 +0200 Subject: Fix T44644 Missing thread-protection (spinlock) of image in new multiview code. Many thanks to Sergey, for practically giving the solution! Note that it may also fix T44345, depends whether there are other missing protections/locks or not... --- source/blender/blenkernel/intern/image.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 4275b0200d0..eeb2f83fd73 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2427,11 +2427,15 @@ void BKE_image_verify_viewer_views(const RenderData *rd, Image *ima, ImageUser * } if (do_reset) { + BLI_spin_lock(&image_spin); + image_free_cached_frames(ima); BKE_image_free_views(ima); /* add new views */ image_viewer_create_views(rd, ima); + + BLI_spin_unlock(&image_spin); } BLI_unlock_thread(LOCK_DRAW_IMAGE); -- cgit v1.2.3 From 0525db39d13fbcbf078b8297fbe54387da49a371 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Sun, 10 May 2015 11:04:09 +0200 Subject: fix T44648: Collada finding bone chains during import crashes when no bones are there --- source/blender/collada/ArmatureImporter.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index c2ee6170470..bccaf4eddf6 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -588,9 +588,11 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin) /* and step back to edit mode to fix the leaf nodes */ ED_armature_to_edit(armature); - connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX); - fix_leaf_bones(armature, (Bone *)armature->bonebase.first); - + if (armature->bonebase.first) { + /* Do this only if Armature has bones */ + connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX); + fix_leaf_bones(armature, (Bone *)armature->bonebase.first); + } // exit armature edit mode ED_armature_from_edit(armature); ED_armature_edit_free(armature); -- cgit v1.2.3 From e8be170e79334be86f52f290949bdf226b74b4e7 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sun, 10 May 2015 12:55:30 +0200 Subject: Cycles: Do not show Branched Path integrator for OpenCL. Branched Path is not supported, neither in the Split nor Megakernel. --- intern/cycles/blender/addon/ui.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 0407e87c842..a1c6de9e427 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -55,8 +55,15 @@ def use_cpu(context): return (device_type == 'NONE' or cscene.device == 'CPU') +def use_branched_path(context): + cscene = context.scene.cycles + device_type = context.user_preferences.system.compute_device_type + + return (cscene.progressive == 'BRANCHED_PATH' and device_type != 'OPENCL') + -def draw_samples_info(layout, cscene): +def draw_samples_info(layout, context): + cscene = context.scene.cycles integrator = cscene.progressive # Calculate sample values @@ -86,7 +93,7 @@ def draw_samples_info(layout, cscene): # Draw interface # Do not draw for progressive, when Square Samples are disabled - if (integrator == 'BRANCHED_PATH') or (cscene.use_square_samples and integrator == 'PATH'): + if use_branched_path(context) or (cscene.use_square_samples and integrator == 'PATH'): col = layout.column(align=True) col.scale_y = 0.6 col.label("Total Samples:") @@ -110,6 +117,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel): scene = context.scene cscene = scene.cycles + device_type = context.user_preferences.system.compute_device_type row = layout.row(align=True) row.menu("CYCLES_MT_sampling_presets", text=bpy.types.CYCLES_MT_sampling_presets.bl_label) @@ -117,7 +125,9 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel): row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMOUT").remove_active = True row = layout.row() - row.prop(cscene, "progressive", text="") + sub = row.row() + sub.active = device_type != 'OPENCL' + sub.prop(cscene, "progressive", text="") row.prop(cscene, "use_square_samples") split = layout.split() @@ -129,7 +139,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel): sub.prop(cscene, "sample_clamp_direct") sub.prop(cscene, "sample_clamp_indirect") - if cscene.progressive == 'PATH': + if cscene.progressive == 'PATH' or use_branched_path(context) == False: col = split.column() sub = col.column(align=True) sub.label(text="Samples:") @@ -163,7 +173,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel): layout.row().prop(cscene, "use_layer_samples") break - draw_samples_info(layout, cscene) + draw_samples_info(layout, context) class CyclesRender_PT_volume_sampling(CyclesButtonsPanel, Panel): @@ -786,7 +796,7 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel): if not (lamp.type == 'AREA' and clamp.is_portal): sub = col.column(align=True) - if cscene.progressive == 'BRANCHED_PATH': + if use_branched_path(context): sub.prop(clamp, "samples") sub.prop(clamp, "max_bounces") @@ -995,7 +1005,7 @@ class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel): sub = col.column(align=True) sub.active = cworld.sample_as_light sub.prop(cworld, "sample_map_resolution") - if cscene.progressive == 'BRANCHED_PATH': + if use_branched_path(context): sub.prop(cworld, "samples") col = split.column() -- cgit v1.2.3 From a47ade34c22349d31682481b69e9e39b94cc6d0f Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sun, 10 May 2015 12:58:27 +0200 Subject: Cycles: Fix tiny greying out inconsistency for Volume settings. --- intern/cycles/blender/addon/ui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index a1c6de9e427..b5ce5a4e3cd 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1107,7 +1107,7 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel): sub = col.column() sub.active = use_cpu(context) sub.prop(cmat, "volume_sampling", text="") - col.prop(cmat, "volume_interpolation", text="") + sub.prop(cmat, "volume_interpolation", text="") col.prop(cmat, "homogeneous_volume", text="Homogeneous") layout.separator() -- cgit v1.2.3 From 1c02a201ba992adc43ec9d9a08b121edfaec4232 Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Sun, 10 May 2015 15:58:17 +0200 Subject: BGE: Cleanup constraints documentation * Fixing Python example. Behavior has changed with Blender 2.74 * Adding missing return type * Fixing typo simbolic * Fixing note for upper/lower limit * Adding link to constraints constants --- doc/python_api/examples/bge.constraints.py | 8 ++++---- doc/python_api/rst/bge.constraints.rst | 11 ++++++----- .../bge_types/bge.types.KX_ConstraintWrapper.rst | 22 ++++++++++------------ 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/doc/python_api/examples/bge.constraints.py b/doc/python_api/examples/bge.constraints.py index e76fc3dd13b..c617ac0622b 100644 --- a/doc/python_api/examples/bge.constraints.py +++ b/doc/python_api/examples/bge.constraints.py @@ -20,15 +20,15 @@ constraint_type = 2 physics_id_1 = object_1.getPhysicsId() physics_id_2 = object_2.getPhysicsId() -# Use bottom right edge of Object1 for hinge position +# use bottom right edge of Object1 for hinge position edge_position_x = 1.0 edge_position_y = 0.0 edge_position_z = -1.0 -# use Object1 y axis for angle to point hinge +# rotate the pivot z axis about 90 degrees edge_angle_x = 0.0 -edge_angle_y = 1.0 -edge_angle_z = 0.0 +edge_angle_y = 0.0 +edge_angle_z = 90.0 # create an edge constraint constraints.createConstraint(physics_id_1, physics_id_2, diff --git a/doc/python_api/rst/bge.constraints.rst b/doc/python_api/rst/bge.constraints.rst index 636a66273e8..cf8565924b0 100644 --- a/doc/python_api/rst/bge.constraints.rst +++ b/doc/python_api/rst/bge.constraints.rst @@ -22,16 +22,14 @@ Physics Constraints (bge.constraints) :type physicsid2: int :arg constrainttype: the type of the constraint. The constraint types are: - + :type constrainttype: int - :class:`POINTTOPOINT_CONSTRAINT` - :class:`LINEHINGE_CONSTRAINT` - :class:`ANGULAR_CONSTRAINT` - :class:`CONETWIST_CONSTRAINT` - :class:`VEHICLE_CONSTRAINT` - :class:`GENERIC_6DOF_CONSTRAINT` - - :type constrainttype: int - + :arg pivot_X: pivot X position :type pivot_X: float (optional) @@ -53,9 +51,12 @@ Physics Constraints (bge.constraints) :arg flag: 128 to disable collision between linked bodies :type flag: int (optional) + :return: a constraint wrapper. + :rtype: :class:`bge.types.KX_ConstraintWrapper` + .. attribute:: error - Simbolic constant string that indicates error. + Symbolic constant string that indicates error. .. function:: exportBulletFile(filename) diff --git a/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst b/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst index 53bef120f7a..2069bfb1dca 100644 --- a/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst +++ b/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst @@ -23,15 +23,13 @@ base class --- :class:`PyObjectPlus` :arg axis: :type axis: integer - .. note:: - For each axis: - * Lowerlimit == Upperlimit -> axis is locked - * Lowerlimit > Upperlimit -> axis is free - * Lowerlimit < Upperlimit -> axis it limited in that range + .. note:: + * Lowerlimit == Upperlimit -> axis is locked + * Lowerlimit > Upperlimit -> axis is free + * Lowerlimit < Upperlimit -> axis it limited in that range PHY_LINEHINGE_CONSTRAINT = 2 or PHY_ANGULAR_CONSTRAINT = 3: axis = 3 is a constraint limit, with low/high limit value - * 3: X axis angle :arg value0 (min): Set the minimum limit of the axis @@ -132,10 +130,10 @@ base class --- :class:`PyObjectPlus` Returns the contraint type (read only) :type: integer + - 1 = :class:`~bge.constraints.POINTTOPOINT_CONSTRAINT` + - 2 = :class:`~bge.constraints.LINEHINGE_CONSTRAINT` + - 3 = :class:`~bge.constraints.ANGULAR_CONSTRAINT` + - 4 = :class:`~bge.constraints.CONETWIST_CONSTRAINT` + - 11 = :class:`~bge.constraints.VEHICLE_CONSTRAINT` + - 12 = :class:`~bge.constraints.GENERIC_6DOF_CONSTRAINT` - * 1 = POINTTOPOINT_CONSTRAINT - * 2 = LINEHINGE_CONSTRAINT - * 3 = ANGULAR_CONSTRAINT (aka LINEHINGE_CONSTRAINT) - * 4 = CONETWIST_CONSTRAINT - * 11 = VEHICLE_CONSTRAINT - * 12 = GENERIC_6DOF_CONSTRAINT -- cgit v1.2.3 From 3a2c0ccdd0236bf26983f5e4d501f7bc234ed6c0 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 May 2015 20:01:24 +0500 Subject: Cycles: Correction to opencl whitelist check Was using platform as a device id accidentally. --- intern/cycles/device/device_opencl.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index e342010567f..5657e3a5992 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -3364,22 +3364,22 @@ void device_opencl_info(vector& devices) clGetPlatformInfo(platform_ids[platform], CL_PLATFORM_NAME, sizeof(pname), &pname, NULL); string platform_name = pname; - cl_device_type device_type; - clGetDeviceInfo(device_ids[platform], CL_DEVICE_TYPE, sizeof(cl_device_type), &device_type, NULL); - - /* TODO(sergey): Make it an utility function to check whitelisted devices. */ - if(!(force_all_platforms || - (platform_name == "AMD Accelerated Parallel Processing" && - device_type == CL_DEVICE_TYPE_GPU))) - { - continue; - } - /* add devices */ for(int num = 0; num < num_devices; num++) { cl_device_id device_id = device_ids[num]; char name[1024] = "\0"; + cl_device_type device_type; + clGetDeviceInfo(device_id, CL_DEVICE_TYPE, sizeof(cl_device_type), &device_type, NULL); + + /* TODO(sergey): Make it an utility function to check whitelisted devices. */ + if(!(force_all_platforms || + (platform_name == "AMD Accelerated Parallel Processing" && + device_type == CL_DEVICE_TYPE_GPU))) + { + continue; + } + if(clGetDeviceInfo(device_id, CL_DEVICE_NAME, sizeof(name), &name, NULL) != CL_SUCCESS) continue; -- cgit v1.2.3 From 2ec221aa281d8c8e8e52d59f9364b5dd373a752c Mon Sep 17 00:00:00 2001 From: "Sv. Lockal" Date: Sun, 10 May 2015 16:20:04 +0000 Subject: Cycles: Use native float->half conversion instructions for Haswell CPUs. This makes OCIO viewport color correction a little bit faster (about -0.5s for 100 samples) Also set max half float value to 65504.0 to conform with IEEE 754. --- intern/cycles/CMakeLists.txt | 4 ++-- intern/cycles/util/util_half.h | 34 ++++++++++++++++------------------ 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index c4cadfe0bf7..ed6961f49e0 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -64,7 +64,7 @@ elseif(CMAKE_COMPILER_IS_GNUCC) set(CYCLES_AVX_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mfpmath=sse") endif() if(CXX_HAS_AVX2) - set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mfpmath=sse") + set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mf16c -mfpmath=sse") endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math") elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") @@ -80,7 +80,7 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CYCLES_AVX_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx") endif() if(CXX_HAS_AVX2) - set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2") + set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mf16c") endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math") endif() diff --git a/intern/cycles/util/util_half.h b/intern/cycles/util/util_half.h index 76941569bd2..9642f8ed523 100644 --- a/intern/cycles/util/util_half.h +++ b/intern/cycles/util/util_half.h @@ -54,12 +54,10 @@ ccl_device_inline void float4_store_half(half *h, float4 f, float scale) for(int i = 0; i < 4; i++) { /* optimized float to half for pixels: * assumes no negative, no nan, no inf, and sets denormal to 0 */ - union { uint i; float f; } in; float fscale = f[i] * scale; - in.f = (fscale > 0.0f)? ((fscale < 65500.0f)? fscale: 65500.0f): 0.0f; - int x = in.i; + float x = min(max(fscale, 0.0f), 65504.0f); - int absolute = x & 0x7FFFFFFF; + int absolute = __float_as_uint(in) & 0x7FFFFFFF; int Z = absolute + 0xC8000000; int result = (absolute < 0x38800000)? 0: Z; int rshift = (result >> 13); @@ -68,20 +66,20 @@ ccl_device_inline void float4_store_half(half *h, float4 f, float scale) } #else /* same as above with SSE */ - const ssef mm_scale = ssef(scale); - const ssei mm_38800000 = ssei(0x38800000); - const ssei mm_7FFF = ssei(0x7FFF); - const ssei mm_7FFFFFFF = ssei(0x7FFFFFFF); - const ssei mm_C8000000 = ssei(0xC8000000); - - ssef mm_fscale = load4f(f) * mm_scale; - ssei x = cast(min(max(mm_fscale, ssef(0.0f)), ssef(65500.0f))); - ssei absolute = x & mm_7FFFFFFF; - ssei Z = absolute + mm_C8000000; - ssei result = andnot(absolute < mm_38800000, Z); - ssei rh = (result >> 13) & mm_7FFF; - - _mm_storel_pi((__m64*)h, _mm_castsi128_ps(_mm_packs_epi32(rh, rh))); + ssef fscale = load4f(f) * scale; + ssef x = min(max(fscale, 0.0f), 65504.0f); + +#ifdef __KERNEL_AVX2__ + ssei rpack = _mm_cvtps_ph(x, 0); +#else + ssei absolute = cast(x) & 0x7FFFFFFF; + ssei Z = absolute + 0xC8000000; + ssei result = andnot(absolute < 0x38800000, Z); + ssei rshift = (result >> 13) & 0x7FFF; + ssei rpack = _mm_packs_epi32(rshift, rshift); +#endif + + _mm_storel_pi((__m64*)h, _mm_castsi128_ps(rpack)); #endif } -- cgit v1.2.3 From 4d8f7eddda0f34f5e801d7a8a45a41b0aa945a6d Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Sun, 10 May 2015 19:21:21 +0200 Subject: BGE : Fix crash during physics mesh update. Currently we can't update the physics mesh of an added rigid body. The cause is that that we need to update all shapes to say that the mesh was changed, for static object we don't do that previously because we use a odd way to reallocate memory at the same place. So now when a mesh is changed we iterate all physics controllers which use the same shape info and recreate its shape with the correct mesh. example file : {F168100} Reviewers: scorpion81, sergof, hg1, sybren, moguri, agoose77 Reviewed By: moguri, agoose77 Subscribers: sybren Differential Revision: https://developer.blender.org/D1269 --- .../Physics/Bullet/CcdPhysicsController.cpp | 200 +++++++++------------ .../Physics/Bullet/CcdPhysicsController.h | 19 +- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 24 +-- .../Physics/Bullet/CcdPhysicsEnvironment.h | 9 + 4 files changed, 117 insertions(+), 135 deletions(-) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 48f85410cf0..efa90657efc 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -39,7 +39,6 @@ subject to the following restrictions: #include "LinearMath/btConvexHull.h" #include "BulletCollision/Gimpact/btGImpactShape.h" - #include "BulletSoftBody/btSoftRigidDynamicsWorld.h" #include "DNA_mesh_types.h" @@ -599,20 +598,13 @@ void CcdPhysicsController::CreateRigidbody() static void DeleteBulletShape(btCollisionShape* shape, bool free) { - if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) - { - // shapes based on meshes use an interface that contains the vertices. - btTriangleMeshShape* meshShape = static_cast(shape); - btStridingMeshInterface* meshInterface = meshShape->getMeshInterface(); - if (meshInterface) - delete meshInterface; - } - else if (shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) - { - btGImpactMeshShape* meshShape = static_cast(shape); - btStridingMeshInterface* meshInterface = meshShape->getMeshInterface(); - if (meshInterface) - delete meshInterface; + if (shape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) { + /* If we use Bullet scaled shape (btScaledBvhTriangleMeshShape) we have to + * free the child of the unscaled shape (btTriangleMeshShape) here. + */ + btTriangleMeshShape *meshShape = ((btScaledBvhTriangleMeshShape *)shape)->getChildShape(); + if (meshShape) + delete meshShape; } if (free) { delete shape; @@ -645,48 +637,41 @@ bool CcdPhysicsController::DeleteControllerShape( ) bool CcdPhysicsController::ReplaceControllerShape(btCollisionShape *newShape) { - - /* Note, deleting the previous collision shape must be done already */ - /* if (m_collisionShape) DeleteControllerShape(); */ + if (m_collisionShape) + DeleteControllerShape(); + + // If newShape is NULL it means to create a new Bullet shape. + if (!newShape) + newShape = m_shapeInfo->CreateBulletShape(m_cci.m_margin, m_cci.m_bGimpact, !m_cci.m_bSoft); m_object->setCollisionShape(newShape); - m_collisionShape= newShape; - m_cci.m_collisionShape= newShape; - - if (GetSoftBody()) { + m_collisionShape = newShape; + m_cci.m_collisionShape = newShape; + + btSoftBody *softBody = GetSoftBody(); + if (softBody) { + btSoftRigidDynamicsWorld *world = GetPhysicsEnvironment()->GetDynamicsWorld(); + // remove the old softBody + world->removeSoftBody(softBody); + // soft body must be recreated - m_cci.m_physicsEnv->RemoveCcdPhysicsController(this); delete m_object; m_object = NULL; // force complete reinitialization m_softbodyMappingDone = false; m_prototypeTransformInitialized = false; m_softBodyTransformInitialized = false; + CreateSoftbody(); assert(m_object); - // reinsert the new body - m_cci.m_physicsEnv->AddCcdPhysicsController(this); - } - - /* Copied from CcdPhysicsEnvironment::addCcdPhysicsController() */ - - /* without this, an object can rest on the old physics mesh - * and not move to account for the physics mesh, even with 'nosleep' */ - btSoftRigidDynamicsWorld* dw= GetPhysicsEnvironment()->GetDynamicsWorld(); - btCollisionObjectArray &obarr= dw->getCollisionObjectArray(); - btCollisionObject *ob; - btBroadphaseProxy* proxy; - - for (int i= 0; i < obarr.size(); i++) { - ob= obarr[i]; - if (ob->getCollisionShape() == newShape) { - proxy = ob->getBroadphaseHandle(); - - if (proxy) - dw->getPairCache()->cleanProxyFromPairs(proxy,dw->getDispatcher()); - } + + btSoftBody *newSoftBody = GetSoftBody(); + // set the user + newSoftBody->setUserPointer(this); + // add the new softbody + world->addSoftBody(newSoftBody); } - + return true; } @@ -1742,30 +1727,22 @@ PHY_IPhysicsController* CcdPhysicsController::GetReplicaForSensors() * 2) from_gameobj - creates the phys mesh from the DerivedMesh where possible, else the RAS_MeshObject * 3) this - update the phys mesh from DerivedMesh or RAS_MeshObject * - * Most of the logic behind this is in shapeInfo->UpdateMesh(...) + * Most of the logic behind this is in m_shapeInfo->UpdateMesh(...) */ bool CcdPhysicsController::ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject *from_meshobj) { - CcdShapeConstructionInfo *shapeInfo; - - shapeInfo = this->GetShapeInfo(); - - if (shapeInfo->m_shapeType != PHY_SHAPE_MESH/* || spc->GetSoftBody()*/) + if (m_shapeInfo->m_shapeType != PHY_SHAPE_MESH) return false; - this->DeleteControllerShape(); - - if (from_gameobj==NULL && from_meshobj==NULL) - from_gameobj = KX_GameObject::GetClientObject((KX_ClientObjectInfo*)this->GetNewClientInfo()); + if (!from_gameobj && !from_meshobj) + from_gameobj = KX_GameObject::GetClientObject((KX_ClientObjectInfo*)GetNewClientInfo()); /* updates the arrays used for making the new bullet mesh */ - shapeInfo->UpdateMesh(from_gameobj, from_meshobj); + m_shapeInfo->UpdateMesh(from_gameobj, from_meshobj); /* create the new bullet mesh */ - CcdConstructionInfo& cci = this->GetConstructionInfo(); - btCollisionShape* bm= shapeInfo->CreateBulletShape(cci.m_margin, cci.m_bGimpact, !cci.m_bSoft); + GetPhysicsEnvironment()->UpdateCcdPhysicsControllerShape(m_shapeInfo); - this->ReplaceControllerShape(bm); return true; } @@ -2494,11 +2471,9 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RA } #endif - /* force recreation of the m_unscaledShape. + /* force recreation of the m_triangleIndexVertexArray. * If this has multiple users we cant delete */ - if (m_unscaledShape) { - // don't free now so it can re-allocate under the same location and not break pointers. - // DeleteBulletShape(m_unscaledShape); + if (m_triangleIndexVertexArray) { m_forceReInstance = true; } @@ -2582,74 +2557,60 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin, b // 9 multiplications/additions and one function call for each triangle that passes the mid phase filtering // One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1 // and btScaledBvhTriangleMeshShape otherwise. - if (useGimpact) - { - btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray( + if (useGimpact) { + if (!m_triangleIndexVertexArray || m_forceReInstance) { + if (m_triangleIndexVertexArray) + delete m_triangleIndexVertexArray; + + m_triangleIndexVertexArray = new btTriangleIndexVertexArray( m_polygonIndexArray.size(), - &m_triFaceArray[0], - 3*sizeof(int), - m_vertexArray.size()/3, + m_triFaceArray.data(), + 3 * sizeof(int), + m_vertexArray.size() / 3, &m_vertexArray[0], - 3*sizeof(btScalar) - ); - btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(indexVertexArrays); - gimpactShape->setMargin(margin); - gimpactShape->updateBound(); - collisionShape = gimpactShape; - - - } else - { - if (!m_unscaledShape || m_forceReInstance) - { - - btTriangleIndexVertexArray* indexVertexArrays = 0; + 3 * sizeof(btScalar)); + m_forceReInstance = false; + } + btGImpactMeshShape *gimpactShape = new btGImpactMeshShape(m_triangleIndexVertexArray); + gimpactShape->setMargin(margin); + gimpactShape->updateBound(); + collisionShape = gimpactShape; + } + else { + if (!m_triangleIndexVertexArray || m_forceReInstance) { ///enable welding, only for the objects that need it (such as soft bodies) - if (0.f != m_weldingThreshold1) - { - btTriangleMesh* collisionMeshData = new btTriangleMesh(true,false); + if (0.0f != m_weldingThreshold1) { + btTriangleMesh *collisionMeshData = new btTriangleMesh(true, false); collisionMeshData->m_weldingThreshold = m_weldingThreshold1; - bool removeDuplicateVertices=true; + bool removeDuplicateVertices = true; // m_vertexArray not in multiple of 3 anymore, use m_triFaceArray - for (unsigned int i=0; iaddTriangle(v1, v2, v3, removeDuplicateVertices); } - indexVertexArrays = collisionMeshData; - - } else - { - indexVertexArrays = new btTriangleIndexVertexArray( + m_triangleIndexVertexArray = collisionMeshData; + } + else { + m_triangleIndexVertexArray = new btTriangleIndexVertexArray( m_polygonIndexArray.size(), - &m_triFaceArray[0], - 3*sizeof(int), - m_vertexArray.size()/3, + m_triFaceArray.data(), + 3 * sizeof(int), + m_vertexArray.size() / 3, &m_vertexArray[0], - 3*sizeof(btScalar)); - } - - // this shape will be shared and not deleted until shapeInfo is deleted - - // for UpdateMesh, reuse the last memory location so instancing wont crash. - if (m_unscaledShape) { - DeleteBulletShape(m_unscaledShape, false); - m_unscaledShape->~btBvhTriangleMeshShape(); - m_unscaledShape = new(m_unscaledShape) btBvhTriangleMeshShape( indexVertexArrays, true, useBvh ); - } else { - m_unscaledShape = new btBvhTriangleMeshShape( indexVertexArrays, true, useBvh ); + 3 * sizeof(btScalar)); } - m_forceReInstance= false; - } else if (useBvh && m_unscaledShape->getOptimizedBvh() == NULL) { - // the existing unscaledShape was not build with Bvh, do it now - m_unscaledShape->buildOptimizedBvh(); + + m_forceReInstance = false; } - collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f)); + + btBvhTriangleMeshShape *unscaledShape = new btBvhTriangleMeshShape(m_triangleIndexVertexArray, true, useBvh); + collisionShape = new btScaledBvhTriangleMeshShape(unscaledShape, btVector3(1.0f, 1.0f, 1.0f)); collisionShape->setMargin(margin); } break; @@ -2691,10 +2652,9 @@ CcdShapeConstructionInfo::~CcdShapeConstructionInfo() (*sit)->Release(); } m_shapeArray.clear(); - if (m_unscaledShape) - { - DeleteBulletShape(m_unscaledShape, true); - } + + if (m_triangleIndexVertexArray) + delete m_triangleIndexVertexArray; m_vertexArray.clear(); if (m_shapeType == PHY_SHAPE_MESH && m_meshObject != NULL) { diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index e3172e7fc45..625713d16e1 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -79,7 +79,7 @@ public: m_userData(NULL), m_refCount(1), m_meshObject(NULL), - m_unscaledShape(NULL), + m_triangleIndexVertexArray(NULL), m_forceReInstance(false), m_weldingThreshold1(0.f), m_shapeProxy(NULL) @@ -110,10 +110,11 @@ public: void AddShape(CcdShapeConstructionInfo* shapeInfo); - btTriangleMeshShape* GetMeshShape(void) + btStridingMeshInterface *GetMeshInterface() { - return (m_unscaledShape); + return m_triangleIndexVertexArray; } + CcdShapeConstructionInfo* GetChildShape(int i) { if (i < 0 || i >= (int)m_shapeArray.size()) @@ -195,8 +196,8 @@ protected: int m_refCount; // this class is shared between replicas // keep track of users so that we can release it RAS_MeshObject* m_meshObject; // Keep a pointer to the original mesh - btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape, - // the actual shape is of type btScaledBvhTriangleMeshShape + // The list of vertexes and indexes for the triangle mesh, shared between Bullet shape. + btTriangleIndexVertexArray *m_triangleIndexVertexArray; std::vector m_shapeArray; // for compound shapes bool m_forceReInstance; //use gimpact for concave dynamic/moving collision detection float m_weldingThreshold1; //welding closeby vertices together can improve softbody stability etc. @@ -535,7 +536,15 @@ protected: CcdPhysicsController (const CcdConstructionInfo& ci); + /** + * Delete the current Bullet shape used in the rigid body. + */ bool DeleteControllerShape(); + + /** + * Delete the old Bullet shape and set the new Bullet shape : newShape + * \param newShape The new Bullet shape to set, if is NULL we create a new Bullet shape + */ bool ReplaceControllerShape(btCollisionShape *newShape); virtual ~CcdPhysicsController(); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 37cc26f6364..dcc67205713 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -671,6 +671,19 @@ void CcdPhysicsEnvironment::RemoveCcdGraphicController(CcdGraphicController* ctr } } +void CcdPhysicsEnvironment::UpdateCcdPhysicsControllerShape(CcdShapeConstructionInfo *shapeInfo) +{ + for (std::set::iterator it = m_controllers.begin(); it != m_controllers.end(); ++it) { + CcdPhysicsController *ctrl = *it; + + if (ctrl->GetShapeInfo() != shapeInfo) + continue; + + ctrl->ReplaceControllerShape(NULL); + RefreshCcdPhysicsController(ctrl); + } +} + void CcdPhysicsEnvironment::BeginFrame() { @@ -1156,17 +1169,8 @@ static bool GetHitTriangle(btCollisionShape* shape, CcdShapeConstructionInfo* sh int indexstride; int numfaces; PHY_ScalarType indicestype; - btStridingMeshInterface* meshInterface = NULL; - btTriangleMeshShape* triangleShape = shapeInfo->GetMeshShape(); + btStridingMeshInterface* meshInterface = shapeInfo->GetMeshInterface(); - if (triangleShape) - meshInterface = triangleShape->getMeshInterface(); - else - { - // other possibility is gImpact - if (shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) - meshInterface = (static_cast(shape))->getMeshInterface(); - } if (!meshInterface) return false; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 1fa97d9ab22..94aea215478 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -54,6 +54,7 @@ class btOverlappingPairCache; class btIDebugDraw; class PHY_IVehicle; class CcdOverlapFilterCallBack; +class CcdShapeConstructionInfo; /** CcdPhysicsEnvironment is an experimental mainloop for physics simulation using optional continuous collision detection. * Physics Environment takes care of stepping the simulation and is a container for physics entities. @@ -229,6 +230,14 @@ protected: void RemoveCcdGraphicController(CcdGraphicController* ctrl); + /** + * Update all physics controllers shape which use the same shape construction info. + * Call RecreateControllerShape on controllers which use the same shape + * construction info that argument shapeInfo. + * You need to call this function when the shape construction info changed. + */ + void UpdateCcdPhysicsControllerShape(CcdShapeConstructionInfo *shapeInfo); + btBroadphaseInterface* GetBroadphase(); btDbvtBroadphase* GetCullingTree() { return m_cullingTree; } -- cgit v1.2.3 From 8db2a9a352c62d4a1ad3ba39dd3cf0b4a8f9ae6f Mon Sep 17 00:00:00 2001 From: "Sv. Lockal" Date: Sun, 10 May 2015 17:48:07 +0000 Subject: Cycles: Add -mf16c for previous commit for Scons Thanks to Dingto for noticing! --- intern/cycles/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript index 79e14ab9a58..75bb5bb0a97 100644 --- a/intern/cycles/SConscript +++ b/intern/cycles/SConscript @@ -140,7 +140,7 @@ else: if (env['C_COMPILER_ID'] == 'gcc' and env['CCVERSION'] >= '4.6') or (env['C_COMPILER_ID'] == 'clang' and env['CCVERSION'] >= '3.1'): kernel_flags['avx'] = kernel_flags['sse41'] + ' -mavx' - kernel_flags['avx2'] = kernel_flags['avx'] + ' -mavx2 -mfma -mlzcnt -mbmi -mbmi2' + kernel_flags['avx2'] = kernel_flags['avx'] + ' -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mf16c' for kernel_type in kernel_flags.keys(): defs.append('WITH_KERNEL_' + kernel_type.upper()) -- cgit v1.2.3 From c20c07f27a5f5497db219e5c0db8c9cc2377e37a Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 10 May 2015 20:37:38 +0200 Subject: Fix T44633: image cache broken for movies and sequences. After multiview, it was continuously unloading/loading image buffers from the cache due to mismatch in cache insert and lookup keys. --- source/blender/blenkernel/intern/image.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index eeb2f83fd73..f3f4775dbf7 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -3729,9 +3729,10 @@ static size_t image_get_multiview_index(Image *ima, ImageUser *iuser) { const bool is_multilayer = BKE_image_is_multilayer(ima); const bool is_backdrop = (ima->source == IMA_SRC_VIEWER) && (ima->type == IMA_TYPE_COMPOSITE) && (iuser == NULL); + int index = BKE_image_is_animated(ima) ? 0 : IMA_NO_INDEX; if (is_multilayer) { - return iuser ? iuser->multi_index : IMA_NO_INDEX; + return iuser ? iuser->multi_index : index; } else if (is_backdrop) { if ((ima->flag & IMA_IS_STEREO)) { @@ -3740,16 +3741,15 @@ static size_t image_get_multiview_index(Image *ima, ImageUser *iuser) } } else if ((ima->flag & IMA_IS_MULTIVIEW)) { - return iuser ? iuser->multi_index : 0; + return iuser ? iuser->multi_index : index; } - return IMA_NO_INDEX; + return index; } static void image_get_frame_and_index(Image *ima, ImageUser *iuser, int *r_frame, int *r_index) { - int frame = 0, index = 0; - index = image_get_multiview_index(ima, iuser); + int frame = 0, index = image_get_multiview_index(ima, iuser); /* see if we already have an appropriate ibuf, with image source and type */ if (ima->source == IMA_SRC_MOVIE) { @@ -3777,9 +3777,7 @@ static void image_get_frame_and_index(Image *ima, ImageUser *iuser, int *r_frame static ImBuf *image_get_cached_ibuf(Image *ima, ImageUser *iuser, int *r_frame, int *r_index) { ImBuf *ibuf = NULL; - int frame = 0, index = 0; - - index = image_get_multiview_index(ima, iuser); + int frame = 0, index = image_get_multiview_index(ima, iuser); /* see if we already have an appropriate ibuf, with image source and type */ if (ima->source == IMA_SRC_MOVIE) { -- cgit v1.2.3 From 3ec168465d31c90cc75b5ea70de492dbeb4ac992 Mon Sep 17 00:00:00 2001 From: "Sv. Lockal" Date: Sun, 10 May 2015 19:04:24 +0000 Subject: Cycles: fix compilation on 32-bit Windows for half-floats Reported by IRC user HG1. --- intern/cycles/util/util_half.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/intern/cycles/util/util_half.h b/intern/cycles/util/util_half.h index 9642f8ed523..f4bac9888a5 100644 --- a/intern/cycles/util/util_half.h +++ b/intern/cycles/util/util_half.h @@ -54,10 +54,12 @@ ccl_device_inline void float4_store_half(half *h, float4 f, float scale) for(int i = 0; i < 4; i++) { /* optimized float to half for pixels: * assumes no negative, no nan, no inf, and sets denormal to 0 */ + union { uint i; float f; } in; float fscale = f[i] * scale; - float x = min(max(fscale, 0.0f), 65504.0f); + in.f = (fscale > 0.0f)? ((fscale < 65504.0f)? fscale: 65504.0f): 0.0f; + int x = in.i; - int absolute = __float_as_uint(in) & 0x7FFFFFFF; + int absolute = x & 0x7FFFFFFF; int Z = absolute + 0xC8000000; int result = (absolute < 0x38800000)? 0: Z; int rshift = (result >> 13); -- cgit v1.2.3 From d55868c3b2004cba008e21f5607dc08076594451 Mon Sep 17 00:00:00 2001 From: "Sv. Lockal" Date: Sun, 10 May 2015 19:32:32 +0000 Subject: Cycles: And yet another compilation fix after half-float commit for clang. Suggested by Brecht, tested with gcc > 4.4 and Clang --- intern/cycles/util/util_optimization.h | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/intern/cycles/util/util_optimization.h b/intern/cycles/util/util_optimization.h index b230bb1a627..c951c35fc76 100644 --- a/intern/cycles/util/util_optimization.h +++ b/intern/cycles/util/util_optimization.h @@ -102,28 +102,7 @@ #ifdef _MSC_VER #include #else - -#ifdef __KERNEL_SSE2__ -#include /* SSE 1 */ -#include /* SSE 2 */ -#endif - -#ifdef __KERNEL_SSE3__ -#include /* SSE 3 */ -#endif - -#ifdef __KERNEL_SSSE3__ -#include /* SSSE 3 */ -#endif - -#ifdef __KERNEL_SSE41__ -#include /* SSE 4.1 */ -#endif - -#ifdef __KERNEL_AVX__ -#include /* AVX */ -#endif - +#include #endif #else -- cgit v1.2.3 From 9e2e85a36777098ea97f63a183d9e715a9d703d6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 11 May 2015 09:27:05 +1000 Subject: GHash: Add BLI_ghash_ensure_p_ex to copy the key Needed in cases where the memory from each key is owned by the GHash. --- source/blender/blenlib/BLI_ghash.h | 5 +++-- source/blender/blenlib/intern/BLI_ghash.c | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index a5c397f32f0..f5cc6c6b90c 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -44,8 +44,8 @@ typedef unsigned int (*GHashHashFP) (const void *key); typedef bool (*GHashCmpFP) (const void *a, const void *b); typedef void (*GHashKeyFreeFP) (void *key); typedef void (*GHashValFreeFP) (void *val); -typedef void *(*GHashKeyCopyFP) (void *key); -typedef void *(*GHashValCopyFP) (void *val); +typedef void *(*GHashKeyCopyFP) (const void *key); +typedef void *(*GHashValCopyFP) (const void *val); typedef struct GHash GHash; @@ -80,6 +80,7 @@ void *BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT; void *BLI_ghash_lookup_default(GHash *gh, const void *key, void *val_default) ATTR_WARN_UNUSED_RESULT; void **BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT; bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT; +bool BLI_ghash_ensure_p_ex(GHash *gh, const void *key, void ***r_val, GHashKeyCopyFP keycopyfp) ATTR_WARN_UNUSED_RESULT; bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 950d164bdbe..b0902fe727f 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -766,6 +766,28 @@ bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) return haskey; } +/** + * A version of #BLI_ghash_ensure_p copies the key on insertion. + */ +bool BLI_ghash_ensure_p_ex( + GHash *gh, const void *key, void ***r_val, + GHashKeyCopyFP keycopyfp) +{ + const unsigned int hash = ghash_keyhash(gh, key); + const unsigned int bucket_index = ghash_bucket_index(gh, hash); + GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index); + const bool haskey = (e != NULL); + + if (!haskey) { + /* keycopyfp(key) is the only difference to BLI_ghash_ensure_p */ + e = BLI_mempool_alloc(gh->entrypool); + ghash_insert_ex_keyonly_entry(gh, keycopyfp(key), bucket_index, (Entry *)e); + } + + *r_val = &e->val; + return haskey; +} + /** * Remove \a key from \a gh, or return false if the key wasn't found. * -- cgit v1.2.3 From f4bae1f6d6ab07e2b959e509c637f3e1505ee559 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 11 May 2015 10:58:53 +1000 Subject: Outliner: cleanup flag was never cleared Was running cleanup on every draw. --- source/blender/editors/space_outliner/outliner_tree.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 4b07c400220..ad37d723d1b 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -104,6 +104,8 @@ static void outliner_storage_cleanup(SpaceOops *soops) /* cleanup only after reading file or undo step, and always for * RNA datablocks view in order to save memory */ if (soops->storeflag & SO_TREESTORE_CLEANUP) { + soops->storeflag &= ~SO_TREESTORE_CLEANUP; + BLI_mempool_iternew(ts, &iter); while ((tselem = BLI_mempool_iterstep(&iter))) { if (tselem->id == NULL) unused++; -- cgit v1.2.3 From 3141870c9657e7396a3f4b360b9ed2b8ee193122 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 11 May 2015 11:06:35 +1000 Subject: Outliner: postpone rebuilding the tree On existing Blender could rebuild tree many times (on freeing each ID). Use a flag instead of immediately rebuilding. --- source/blender/blenloader/intern/readfile.c | 4 ++-- source/blender/editors/space_outliner/outliner_edit.c | 3 ++- source/blender/editors/space_outliner/outliner_tree.c | 5 +++++ source/blender/makesdna/DNA_space_types.h | 5 ++++- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 4efb61a7efc..a4dd2264816 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6051,7 +6051,7 @@ static void lib_link_screen(FileData *fd, Main *main) } if (so->treehash) { /* rebuild hash table, because it depends on ids too */ - BKE_outliner_treehash_rebuild_from_treestore(so->treehash, so->treestore); + so->storeflag |= SO_TREESTORE_REBUILD; } } } @@ -6405,7 +6405,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc } if (so->treehash) { /* rebuild hash table, because it depends on ids too */ - BKE_outliner_treehash_rebuild_from_treestore(so->treehash, so->treestore); + so->storeflag |= SO_TREESTORE_REBUILD; } } } diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 058b8c4de5a..523584e2f2d 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -1984,7 +1984,8 @@ void ED_outliner_id_unref(SpaceOops *so, const ID *id) } if (so->treehash && changed) { /* rebuild hash table, because it depends on ids too */ - BKE_outliner_treehash_rebuild_from_treestore(so->treehash, so->treestore); + /* postpone a full rebuild because this can be called many times on-free */ + so->storeflag |= SO_TREESTORE_REBUILD; } } } diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index ad37d723d1b..728a7501d5b 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -1580,6 +1580,11 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) else soops->search_flags &= ~SO_SEARCH_RECURSIVE; + if (soops->storeflag & SO_TREESTORE_REBUILD) { + soops->storeflag &= ~SO_TREESTORE_REBUILD; + BKE_outliner_treehash_rebuild_from_treestore(soops->treehash, soops->treestore); + } + if (soops->tree.first && (soops->storeflag & SO_TREESTORE_REDRAW)) return; diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index d6785da7486..9c023628164 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -290,10 +290,13 @@ typedef enum eSpaceOutliner_Mode { /* SpaceOops->storeflag */ typedef enum eSpaceOutliner_StoreFlag { - /* rebuild tree */ + /* cleanup tree */ SO_TREESTORE_CLEANUP = (1 << 0), /* if set, it allows redraws. gets set for some allqueue events */ SO_TREESTORE_REDRAW = (1 << 1), + /* rebuild the tree, similar to cleanup, + * but defer a call to BKE_outliner_treehash_rebuild_from_treestore instead */ + SO_TREESTORE_REBUILD = (1 << 2), } eSpaceOutliner_StoreFlag; /* outliner search flags (SpaceOops->search_flags) */ -- cgit v1.2.3 From 18cf235893d5d2163084afcd936713de273ece9e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 11 May 2015 12:39:08 +1000 Subject: GHash: use const keys when only used for lookups --- source/blender/blenlib/BLI_ghash.h | 6 +++--- source/blender/blenlib/intern/BLI_ghash.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index f5cc6c6b90c..a9f8d9fc268 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -81,11 +81,11 @@ void *BLI_ghash_lookup_default(GHash *gh, const void *key, void *val_default) A void **BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT; bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT; bool BLI_ghash_ensure_p_ex(GHash *gh, const void *key, void ***r_val, GHashKeyCopyFP keycopyfp) ATTR_WARN_UNUSED_RESULT; -bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); +bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, const unsigned int nentries_reserve); -void *BLI_ghash_popkey(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) ATTR_WARN_UNUSED_RESULT; +void *BLI_ghash_popkey(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp) ATTR_WARN_UNUSED_RESULT; bool BLI_ghash_haskey(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT; unsigned int BLI_ghash_size(GHash *gh) ATTR_WARN_UNUSED_RESULT; void BLI_ghash_flag_set(GHash *gh, unsigned int flag); @@ -229,7 +229,7 @@ void BLI_gset_insert(GSet *gh, void *key); bool BLI_gset_add(GSet *gs, void *key); bool BLI_gset_reinsert(GSet *gh, void *key, GSetKeyFreeFP keyfreefp); bool BLI_gset_haskey(GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT; -bool BLI_gset_remove(GSet *gs, void *key, GSetKeyFreeFP keyfreefp); +bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp); void BLI_gset_clear_ex(GSet *gs, GSetKeyFreeFP keyfreefp, const unsigned int nentries_reserve); void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp); diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index b0902fe727f..9287d62a683 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -535,7 +535,7 @@ BLI_INLINE bool ghash_insert_safe_keyonly(GHash *gh, void *key, const bool overr * Remove the entry and return it, caller must free from gh->entrypool. */ static Entry *ghash_remove_ex( - GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, + GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, const unsigned int bucket_index) { Entry *e_prev; @@ -796,7 +796,7 @@ bool BLI_ghash_ensure_p_ex( * \param valfreefp Optional callback to free the value. * \return true if \a key was removed from \a gh. */ -bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) +bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) { const unsigned int hash = ghash_keyhash(gh, key); const unsigned int bucket_index = ghash_bucket_index(gh, hash); @@ -819,7 +819,7 @@ bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFr * \param keyfreefp Optional callback to free the key. * \return the value of \a key int \a gh or NULL. */ -void *BLI_ghash_popkey(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) +void *BLI_ghash_popkey(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp) { const unsigned int hash = ghash_keyhash(gh, key); const unsigned int bucket_index = ghash_bucket_index(gh, hash); @@ -1303,7 +1303,7 @@ bool BLI_gset_reinsert(GSet *gs, void *key, GSetKeyFreeFP keyfreefp) return ghash_insert_safe_keyonly((GHash *)gs, key, true, keyfreefp); } -bool BLI_gset_remove(GSet *gs, void *key, GSetKeyFreeFP keyfreefp) +bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp) { return BLI_ghash_remove((GHash *)gs, key, keyfreefp, NULL); } -- cgit v1.2.3 From 097862cb26f98d9dbd1bc47543ea8e58f281cc5f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 11 May 2015 12:39:39 +1000 Subject: GHash: avoid redundant casts --- source/blender/blenkernel/BKE_addon.h | 2 +- source/blender/blenkernel/BKE_node.h | 2 +- source/blender/blenkernel/intern/addon.c | 6 +++--- source/blender/blenkernel/intern/effect.c | 2 +- source/blender/blenkernel/intern/node.c | 6 +++--- source/blender/bmesh/intern/bmesh_mesh.c | 6 +++--- source/blender/editors/curve/editcurve.c | 12 ++++++------ source/blender/imbuf/intern/moviecache.c | 4 ++-- source/blender/makesdna/intern/dna_genfile.c | 2 +- source/blender/makesrna/intern/rna_define.c | 2 +- source/blender/python/intern/bpy_rna.c | 4 ++-- source/blender/windowmanager/intern/wm.c | 4 ++-- source/blender/windowmanager/intern/wm_operators.c | 2 +- 13 files changed, 27 insertions(+), 27 deletions(-) diff --git a/source/blender/blenkernel/BKE_addon.h b/source/blender/blenkernel/BKE_addon.h index 9c09fffe0a0..74c1edd1c1b 100644 --- a/source/blender/blenkernel/BKE_addon.h +++ b/source/blender/blenkernel/BKE_addon.h @@ -38,7 +38,7 @@ typedef struct bAddonPrefType { bAddonPrefType *BKE_addon_pref_type_find(const char *idname, bool quiet); void BKE_addon_pref_type_add(bAddonPrefType *apt); -void BKE_addon_pref_type_remove(bAddonPrefType *apt); +void BKE_addon_pref_type_remove(const bAddonPrefType *apt); void BKE_addon_pref_type_init(void); void BKE_addon_pref_type_free(void); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index d3a8687c615..4deaf26e2f5 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -319,7 +319,7 @@ typedef struct bNodeTreeType { struct bNodeTreeType *ntreeTypeFind(const char *idname); void ntreeTypeAdd(struct bNodeTreeType *nt); -void ntreeTypeFreeLink(struct bNodeTreeType *nt); +void ntreeTypeFreeLink(const struct bNodeTreeType *nt); bool ntreeIsRegistered(struct bNodeTree *ntree); struct GHashIterator *ntreeTypeGetIterator(void); diff --git a/source/blender/blenkernel/intern/addon.c b/source/blender/blenkernel/intern/addon.c index 28667d458b8..811461b84c1 100644 --- a/source/blender/blenkernel/intern/addon.c +++ b/source/blender/blenkernel/intern/addon.c @@ -62,12 +62,12 @@ bAddonPrefType *BKE_addon_pref_type_find(const char *idname, bool quiet) void BKE_addon_pref_type_add(bAddonPrefType *apt) { - BLI_ghash_insert(global_addonpreftype_hash, (void *)apt->idname, apt); + BLI_ghash_insert(global_addonpreftype_hash, apt->idname, apt); } -void BKE_addon_pref_type_remove(bAddonPrefType *apt) +void BKE_addon_pref_type_remove(const bAddonPrefType *apt) { - BLI_ghash_remove(global_addonpreftype_hash, (void *)apt->idname, NULL, MEM_freeN); + BLI_ghash_remove(global_addonpreftype_hash, apt->idname, NULL, MEM_freeN); } void BKE_addon_pref_type_init(void) diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 296a56ada5d..785561d8239 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -1176,7 +1176,7 @@ void BKE_sim_debug_data_clear_category(const char *category) GHashIterator iter; BLI_ghashIterator_init(&iter, _sim_debug_data->gh); while (!BLI_ghashIterator_done(&iter)) { - SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); + const SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); BLI_ghashIterator_step(&iter); /* removing invalidates the current iterator, so step before removing */ if (elem->category_hash == category_hash) diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 8ea19b3cde5..69905fa8c53 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -303,7 +303,7 @@ bNodeTreeType *ntreeTypeFind(const char *idname) void ntreeTypeAdd(bNodeTreeType *nt) { - BLI_ghash_insert(nodetreetypes_hash, (void *)nt->idname, nt); + BLI_ghash_insert(nodetreetypes_hash, nt->idname, nt); /* XXX pass Main to register function? */ update_typeinfo(G.main, NULL, nt, NULL, NULL, false); } @@ -317,7 +317,7 @@ static void ntree_free_type(void *treetype_v) MEM_freeN(treetype); } -void ntreeTypeFreeLink(bNodeTreeType *nt) +void ntreeTypeFreeLink(const bNodeTreeType *nt) { BLI_ghash_remove(nodetreetypes_hash, nt->idname, NULL, ntree_free_type); } @@ -378,7 +378,7 @@ void nodeRegisterType(bNodeType *nt) BLI_assert(nt->idname[0] != '\0'); BLI_assert(nt->poll != NULL); - BLI_ghash_insert(nodetypes_hash, (void *)nt->idname, nt); + BLI_ghash_insert(nodetypes_hash, nt->idname, nt); /* XXX pass Main to register function? */ update_typeinfo(G.main, NULL, NULL, nt, NULL, false); } diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 2a6c98bce2e..2c4a98b0b7e 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -1497,7 +1497,7 @@ void BM_mesh_remap( BMVert *new_vep = verts_pool[*new_idx]; *new_vep = *ve; /* printf("mapping vert from %d to %d (%p/%p to %p)\n", i, *new_idx, *vep, verts_pool[i], new_vep);*/ - BLI_ghash_insert(vptr_map, (void *)*vep, (void *)new_vep); + BLI_ghash_insert(vptr_map, *vep, new_vep); } bm->elem_index_dirty |= BM_VERT; bm->elem_table_dirty |= BM_VERT; @@ -1528,7 +1528,7 @@ void BM_mesh_remap( for (i = totedge; i--; new_idx--, ed--, edp--) { BMEdge *new_edp = edges_pool[*new_idx]; *new_edp = *ed; - BLI_ghash_insert(eptr_map, (void *)*edp, (void *)new_edp); + BLI_ghash_insert(eptr_map, *edp, new_edp); /* printf("mapping edge from %d to %d (%p/%p to %p)\n", i, *new_idx, *edp, edges_pool[i], new_edp);*/ } bm->elem_index_dirty |= BM_EDGE; @@ -1560,7 +1560,7 @@ void BM_mesh_remap( for (i = totface; i--; new_idx--, fa--, fap--) { BMFace *new_fap = faces_pool[*new_idx]; *new_fap = *fa; - BLI_ghash_insert(fptr_map, (void *)*fap, (void *)new_fap); + BLI_ghash_insert(fptr_map, *fap, new_fap); } bm->elem_index_dirty |= BM_FACE | BM_LOOP; diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index cbbee2f206f..f50eee7033b 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -327,17 +327,17 @@ static void init_editNurb_keyIndex(EditNurb *editnurb, ListBase *origBase) editnurb->keyindex = gh; } -static CVKeyIndex *getCVKeyIndex(EditNurb *editnurb, void *cv) +static CVKeyIndex *getCVKeyIndex(EditNurb *editnurb, const void *cv) { return BLI_ghash_lookup(editnurb->keyindex, cv); } -static CVKeyIndex *popCVKeyIndex(EditNurb *editnurb, void *cv) +static CVKeyIndex *popCVKeyIndex(EditNurb *editnurb, const void *cv) { return BLI_ghash_popkey(editnurb->keyindex, cv, NULL); } -static BezTriple *getKeyIndexOrig_bezt(EditNurb *editnurb, BezTriple *bezt) +static BezTriple *getKeyIndexOrig_bezt(EditNurb *editnurb, const BezTriple *bezt) { CVKeyIndex *index = getCVKeyIndex(editnurb, bezt); @@ -370,7 +370,7 @@ static int getKeyIndexOrig_keyIndex(EditNurb *editnurb, void *cv) return index->key_index; } -static void keyIndex_delCV(EditNurb *editnurb, void *cv) +static void keyIndex_delCV(EditNurb *editnurb, const void *cv) { if (!editnurb->keyindex) { return; @@ -398,7 +398,7 @@ static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu) } if (nu->bezt) { - BezTriple *bezt = nu->bezt; + const BezTriple *bezt = nu->bezt; a = nu->pntsu; while (a--) { @@ -407,7 +407,7 @@ static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu) } } else { - BPoint *bp = nu->bp; + const BPoint *bp = nu->bp; a = nu->pntsu * nu->pntsv; while (a--) { diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c index 29bb35986e8..4b49076dcd6 100644 --- a/source/blender/imbuf/intern/moviecache.c +++ b/source/blender/imbuf/intern/moviecache.c @@ -147,8 +147,8 @@ static void check_unused_keys(MovieCache *cache) BLI_ghashIterator_init(&gh_iter, cache->hash); while (!BLI_ghashIterator_done(&gh_iter)) { - MovieCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); - MovieCacheItem *item = BLI_ghashIterator_getValue(&gh_iter); + const MovieCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); + const MovieCacheItem *item = BLI_ghashIterator_getValue(&gh_iter); bool remove; BLI_ghashIterator_step(&gh_iter); diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c index 4615a1ce9e4..389e22b2a0c 100644 --- a/source/blender/makesdna/intern/dna_genfile.c +++ b/source/blender/makesdna/intern/dna_genfile.c @@ -525,7 +525,7 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap) for (nr = 0; nr < sdna->nr_structs; nr++) { sp = sdna->structs[nr]; - BLI_ghash_insert(sdna->structs_map, (void *)sdna->types[sp[0]], (void *)(nr + 1)); + BLI_ghash_insert(sdna->structs_map, sdna->types[sp[0]], SET_INT_IN_POINTER(nr + 1)); } #endif } diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 6a0ae0a60f8..dd2a49c8380 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -3411,7 +3411,7 @@ static void rna_def_property_free(StructOrFunctionRNA *cont_, PropertyRNA *prop) if (prop->flag & PROP_RUNTIME) { if (cont->prophash) - BLI_ghash_remove(cont->prophash, (void *)prop->identifier, NULL, NULL); + BLI_ghash_remove(cont->prophash, prop->identifier, NULL, NULL); RNA_def_property_free_pointers(prop); rna_freelinkN(&cont->properties, prop); diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 2aab7e070c0..af5ec03c7ed 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -177,7 +177,7 @@ static GHash *id_weakref_pool_get(ID *id) if (weakinfo_hash == NULL) { /* we're using a ghash as a set, could use libHX's HXMAP_SINGULAR but would be an extra dep. */ weakinfo_hash = BLI_ghash_ptr_new("rna_id"); - BLI_ghash_insert(id_weakref_pool, (void *)id, weakinfo_hash); + BLI_ghash_insert(id_weakref_pool, id, weakinfo_hash); } return weakinfo_hash; @@ -203,7 +203,7 @@ static void id_weakref_pool_add(ID *id, BPy_DummyPointerRNA *pyrna) Py_DECREF(weakref_cb_py); /* function owned by the weakref now */ /* important to add at the end, since first removal looks at the end */ - BLI_ghash_insert(weakinfo_hash, (void *)weakref, id); /* using a hash table as a set, all 'id's are the same */ + BLI_ghash_insert(weakinfo_hash, weakref, id); /* using a hash table as a set, all 'id's are the same */ /* weakinfo_hash owns the weakref */ } diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 34069e0b873..c8ff6dac754 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -228,7 +228,7 @@ uiListType *WM_uilisttype_find(const char *idname, bool quiet) bool WM_uilisttype_add(uiListType *ult) { - BLI_ghash_insert(uilisttypes_hash, (void *)ult->idname, ult); + BLI_ghash_insert(uilisttypes_hash, ult->idname, ult); return 1; } @@ -285,7 +285,7 @@ MenuType *WM_menutype_find(const char *idname, bool quiet) bool WM_menutype_add(MenuType *mt) { - BLI_ghash_insert(menutypes_hash, (void *)mt->idname, mt); + BLI_ghash_insert(menutypes_hash, mt->idname, mt); return true; } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index dfff5b4982f..07d0bd0b62f 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -493,7 +493,7 @@ void WM_operatortype_remove_ptr(wmOperatorType *ot) if (ot->macro.first) wm_operatortype_free_macro(ot); - BLI_ghash_remove(global_ops_hash, (void *)ot->idname, NULL, NULL); + BLI_ghash_remove(global_ops_hash, ot->idname, NULL, NULL); WM_keyconfig_update_operatortype(); -- cgit v1.2.3 From dfbb876d4660481a980e18b66a3f8d11b5f55b23 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 11 May 2015 15:32:43 +1000 Subject: UI: initial support for UI editing selected items Add basic support (holding Alt) to edit all selected objects/bones/sequences. --- source/blender/editors/include/UI_interface.h | 4 + .../blender/editors/interface/interface_handlers.c | 322 ++++++++++++++++++++- source/blender/editors/interface/interface_ops.c | 4 +- 3 files changed, 325 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 01fd19c14e9..cc66cbe1879 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -981,6 +981,10 @@ void ED_button_operatortypes(void); void UI_drop_color_copy(struct wmDrag *drag, struct wmDropBox *drop); int UI_drop_color_poll(struct bContext *C, struct wmDrag *drag, const struct wmEvent *event); +bool UI_context_copy_to_selected_list( + struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, + struct ListBase *r_lb, bool *r_use_path_from_id, char **r_path); + /* Helpers for Operators */ uiBut *UI_context_active_but_get(const struct bContext *C); void UI_context_active_but_prop_get(const struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop, int *index); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 9ee263846a4..cfa31c8ef35 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -99,6 +99,9 @@ /* support dragging multiple number buttons at once */ #define USE_DRAG_MULTINUM +/* allow dragging/editing all other selected items at once */ +#define USE_ALLSELECT + /* so we can avoid very small mouse-moves from jumping away from keyboard navigation [#34936] */ #define USE_KEYNAV_LIMIT @@ -158,6 +161,34 @@ typedef enum uiHandleButtonState { } uiHandleButtonState; +#ifdef USE_ALLSELECT +typedef struct uiSelectContextElem { + PointerRNA ptr; + union { + bool val_b; + int val_i; + float val_f; + }; +} uiSelectContextElem; + +typedef struct uiSelectContextStore { + uiSelectContextElem *elems; + int elems_len; + bool do_free; + bool is_enabled; +} uiSelectContextStore; + +static bool ui_selectcontext_begin( + bContext *C, uiBut *but, struct uiSelectContextStore *selctx_data); +static void ui_selectcontext_apply( + bContext *C, uiBut *but, struct uiSelectContextStore *selctx_data, + const double value, const double value_orig); + +#define IS_ALLSELECT_EVENT(event) ((event)->alt != 0) + +#endif /* USE_ALLSELECT */ + + #ifdef USE_DRAG_MULTINUM /* how far to drag before we check for gesture direction (in pixels), @@ -178,6 +209,10 @@ typedef enum uiHandleButtonState { typedef struct uiButMultiState { double origvalue; uiBut *but; + +#ifdef USE_ALLSELECT + uiSelectContextStore select_others; +#endif } uiButMultiState; typedef struct uiHandleButtonMulti { @@ -210,8 +245,6 @@ typedef struct uiHandleButtonMulti { #endif /* USE_DRAG_MULTINUM */ - - typedef struct uiHandleButtonData { wmWindowManager *wm; wmWindow *window; @@ -280,6 +313,10 @@ typedef struct uiHandleButtonData { uiHandleButtonMulti multi_data; #endif +#ifdef USE_ALLSELECT + uiSelectContextStore select_others; +#endif + /* post activate */ uiButtonActivateType posttype; uiBut *postbut; @@ -909,7 +946,26 @@ static void ui_multibut_restore(uiHandleButtonData *data, uiBlock *block) static void ui_multibut_free(uiHandleButtonData *data, uiBlock *block) { +#ifdef USE_ALLSELECT + if (data->multi_data.mbuts) { + LinkNode *list = data->multi_data.mbuts; + while (list) { + LinkNode *next = list->next; + uiButMultiState *mbut_state = list->link; + + if (mbut_state->select_others.elems) { + MEM_freeN(mbut_state->select_others.elems); + } + + MEM_freeN(list->link); + MEM_freeN(list); + list = next; + } + } +#else BLI_linklist_freeN(data->multi_data.mbuts); +#endif + data->multi_data.mbuts = NULL; if (data->multi_data.bs_mbuts) { @@ -1015,6 +1071,24 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl void *active_back; ui_but_execute_begin(C, ar, but, &active_back); + +#ifdef USE_ALLSELECT + if (data->select_others.is_enabled) { + /* init once! */ + if (mbut_state->select_others.elems_len == 0) { + ui_selectcontext_begin(C, but, &mbut_state->select_others); + } + if (mbut_state->select_others.elems_len == 0) { + mbut_state->select_others.elems_len = -1; + } + } + + /* needed so we apply the right deltas */ + but->active->origvalue = mbut_state->origvalue; + but->active->select_others = mbut_state->select_others; + but->active->select_others.do_free = false; +#endif + BLI_assert(active_back == NULL); /* no need to check 'data->state' here */ if (data->str) { @@ -1225,6 +1299,205 @@ static bool ui_but_is_drag_toggle(const uiBut *but) #endif /* USE_DRAG_TOGGLE */ +#ifdef USE_ALLSELECT + +static bool ui_selectcontext_begin( + bContext *C, uiBut *but, uiSelectContextStore *selctx_data) +{ + PointerRNA ptr, lptr, idptr; + PropertyRNA *prop, *lprop; + bool success = false; + int index; + + char *path = NULL; + ListBase lb = {NULL}; + + ptr = but->rnapoin; + prop = but->rnaprop; + index = but->rnaindex; + + /* for now don't support whole colors */ + if (index == -1) + return false; + + /* if there is a valid property that is editable... */ + if (ptr.data && prop) { + CollectionPointerLink *link; + bool use_path_from_id; + int i; + + /* some facts we want to know */ + const bool is_array = RNA_property_array_check(prop); + const int rna_type = RNA_property_type(prop); + + if (!UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path)) { + goto finally; + } + + selctx_data->elems_len = BLI_listbase_count(&lb); + if (selctx_data->elems_len == 0) { + goto finally; + } + + selctx_data->elems = MEM_mallocN(sizeof(uiSelectContextElem) * selctx_data->elems_len, __func__); + + for (i = 0, link = lb.first; i < selctx_data->elems_len; i++, link = link->next) { + uiSelectContextElem *other = &selctx_data->elems[i]; + /* TODO,. de-duplicate copy_to_selected_button */ + if (link->ptr.data != ptr.data) { + if (use_path_from_id) { + /* Path relative to ID. */ + lprop = NULL; + RNA_id_pointer_create(link->ptr.id.data, &idptr); + RNA_path_resolve_property(&idptr, path, &lptr, &lprop); + } + else if (path) { + /* Path relative to elements from list. */ + lprop = NULL; + RNA_path_resolve_property(&link->ptr, path, &lptr, &lprop); + } + else { + lptr = link->ptr; + lprop = prop; + } + + /* lptr might not be the same as link->ptr! */ + if ((lptr.data != ptr.data) && + (lprop == prop) && + RNA_property_editable(&lptr, lprop)) + { + other->ptr = lptr; + if (is_array) { + if (rna_type == PROP_FLOAT) { + other->val_f = RNA_property_float_get_index(&lptr, lprop, index); + } + else if (rna_type == PROP_INT) { + other->val_i = RNA_property_int_get_index(&lptr, lprop, index); + } + /* ignored for now */ +#if 0 + else if (rna_type == PROP_BOOLEAN) { + other->val_b = RNA_property_boolean_get_index(&lptr, lprop, index); + } +#endif + } + else { + if (rna_type == PROP_FLOAT) { + other->val_f = RNA_property_float_get(&lptr, lprop); + } + else if (rna_type == PROP_INT) { + other->val_i = RNA_property_int_get(&lptr, lprop); + } + /* ignored for now */ +#if 0 + else if (rna_type == PROP_BOOLEAN) { + other->val_b = RNA_property_boolean_get(&lptr, lprop); + } + else if (rna_type == PROP_ENUM) { + other->val_i = RNA_property_enum_get(&lptr, lprop); + } +#endif + } + + continue; + } + } + + selctx_data->elems_len -= 1; + i -= 1; + } + } + + success = (selctx_data->elems_len != 0); + +finally: + if (selctx_data->elems_len == 0) { + MEM_SAFE_FREE(selctx_data->elems); + } + + MEM_SAFE_FREE(path); + BLI_freelistN(&lb); + + /* caller can clear */ + selctx_data->do_free = true; + + return success; +} + +static void ui_selectcontext_apply( + bContext *C, uiBut *but, uiSelectContextStore *selctx_data, + const double value, const double value_orig) +{ + if (selctx_data->elems) { + PropertyRNA *prop = but->rnaprop; + PropertyRNA *lprop = but->rnaprop; + int index = but->rnaindex; + int i; + + union { + bool b; + int i; + float f; + } delta; + + const bool is_array = RNA_property_array_check(prop); + const int rna_type = RNA_property_type(prop); + + if (rna_type == PROP_FLOAT) { + delta.f = value - value_orig; + } + else if (rna_type == PROP_INT) { + delta.i = (int)value - (int)value_orig; + } + else if (rna_type == PROP_ENUM) { + delta.i = RNA_property_enum_get(&but->rnapoin, prop); /* not a delta infact */ + } + else if (rna_type == PROP_BOOLEAN) { + if (is_array) { + delta.b = RNA_property_boolean_get_index(&but->rnapoin, prop, index); /* not a delta infact */ + } + else { + delta.b = RNA_property_boolean_get(&but->rnapoin, prop); /* not a delta infact */ + } + } + + for (i = 0; i < selctx_data->elems_len; i++) { + uiSelectContextElem *other = &selctx_data->elems[i]; + PointerRNA lptr = other->ptr; + if (is_array) { + if (rna_type == PROP_FLOAT) { + RNA_property_float_set_index(&lptr, lprop, index, other->val_f + delta.f); + } + else if (rna_type == PROP_INT) { + RNA_property_int_set_index(&lptr, lprop, index, other->val_i + delta.i); + } + else if (rna_type == PROP_BOOLEAN) { + RNA_property_boolean_set_index(&lptr, lprop, index, delta.b); + } + } + else { + if (rna_type == PROP_FLOAT) { + RNA_property_float_set(&lptr, lprop, other->val_f + delta.f); + } + else if (rna_type == PROP_INT) { + RNA_property_int_set(&lptr, lprop, other->val_i + delta.i); + } + else if (rna_type == PROP_BOOLEAN) { + RNA_property_boolean_set(&lptr, lprop, delta.b); + } + else if (rna_type == PROP_ENUM) { + RNA_property_enum_set(&lptr, lprop, delta.i); + } + } + + RNA_property_update(C, &lptr, prop); + } + } +} + +#endif /* USE_ALLSELECT */ + + static bool ui_but_contains_point_px_icon(uiBut *but, ARegion *ar, const wmEvent *event) { rcti rect; @@ -1609,6 +1882,21 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton else if (data->applied_interactive) { return; } + +#ifdef USE_ALLSELECT + if (data->select_others.elems_len == 0) { + wmWindow *win = CTX_wm_window(C); + /* may have been enabled before activating */ + if (data->select_others.is_enabled || IS_ALLSELECT_EVENT(win->eventstate)) { + ui_selectcontext_begin(C, but, &data->select_others); + data->select_others.is_enabled = true; + } + } + if (data->select_others.elems_len == 0) { + /* dont check again */ + data->select_others.elems_len = -1; + } +#endif } /* ensures we are writing actual values */ @@ -1713,6 +2001,10 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton } #endif +#ifdef USE_ALLSELECT + ui_selectcontext_apply(C, but, &data->select_others, data->value, data->origvalue); +#endif + but->editstr = editstr; but->editval = editval; but->editvec = editvec; @@ -2524,6 +2816,14 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) } #endif +#ifdef USE_ALLSELECT + if (is_num_but) { + if (IS_ALLSELECT_EVENT(win->eventstate)) { + data->select_others.is_enabled = true; + } + } +#endif + /* retrieve string */ data->maxlen = ui_but_string_get_max_length(but); data->str = MEM_callocN(sizeof(char) * data->maxlen + 1, "textedit str"); @@ -3102,6 +3402,15 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat data->menu->popup = but->block->handle->popup; } +#ifdef USE_ALLSELECT + { + wmWindow *win = CTX_wm_window(C); + if (IS_ALLSELECT_EVENT(win->eventstate)) { + data->select_others.is_enabled = true; + } + } +#endif + /* this makes adjacent blocks auto open from now on */ //if (but->block->auto_open == 0) but->block->auto_open = 1; } @@ -3803,7 +4112,6 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton fac = 1.0f; if (event->shift) fac /= 10.0f; - if (event->alt) fac /= 20.0f; if (ui_numedit_but_NUM(but, data, (ui_but_is_cursor_warp(but) ? screen_mx : mx), snap, fac)) ui_numedit_apply(C, block, but, data); @@ -7289,6 +7597,14 @@ static void button_activate_exit( if (data->origstr) MEM_freeN(data->origstr); +#ifdef USE_ALLSELECT + if (data->select_others.do_free) { + if (data->select_others.elems) { + MEM_freeN(data->select_others.elems); + } + } +#endif + /* redraw (data is but->active!) */ ED_region_tag_redraw(data->region); diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 4f78a1a440e..892bbd8ea97 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -261,7 +261,7 @@ static void UI_OT_unset_property_button(wmOperatorType *ot) /* Copy To Selected Operator ------------------------ */ -static bool copy_to_selected_list( +bool UI_context_copy_to_selected_list( bContext *C, PointerRNA *ptr, PropertyRNA *prop, ListBase *r_lb, bool *r_use_path_from_id, char **r_path) { @@ -325,7 +325,7 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll) CollectionPointerLink *link; ListBase lb; - if (!copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path)) + if (!UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path)) return success; for (link = lb.first; link; link = link->next) { -- cgit v1.2.3 From 5588a51c9cb89878588c8130a02d76e04a53aae2 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 11 May 2015 13:10:19 +0200 Subject: Cycles OpenGL: Don't use full matrix transform when we can just use simple addition. --- intern/cycles/device/device.cpp | 13 ++++--------- intern/cycles/device/device_cuda.cpp | 13 ++++--------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 3a33b8fb68b..839f35116fa 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -83,24 +83,19 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w draw_params.bind_display_space_shader_cb(); } - glPushMatrix(); - glTranslatef(0.0f, (float)dy, 0.0f); - glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); - glVertex2f(0.0f, 0.0f); + glVertex2f(0.0f, dy); glTexCoord2f(1.0f, 0.0f); - glVertex2f((float)width, 0.0f); + glVertex2f((float)width, dy); glTexCoord2f(1.0f, 1.0f); - glVertex2f((float)width, (float)height); + glVertex2f((float)width, (float)height + dy); glTexCoord2f(0.0f, 1.0f); - glVertex2f(0.0f, (float)height); + glVertex2f(0.0f, (float)height + dy); glEnd(); - glPopMatrix(); - if(draw_params.unbind_display_space_shader_cb) { draw_params.unbind_display_space_shader_cb(); } diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 04319ba4775..42d4f8e48ff 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -918,24 +918,19 @@ public: draw_params.bind_display_space_shader_cb(); } - glPushMatrix(); - glTranslatef(0.0f, (float)dy, 0.0f); - glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); - glVertex2f(0.0f, 0.0f); + glVertex2f(0.0f, dy); glTexCoord2f((float)w/(float)pmem.w, 0.0f); - glVertex2f((float)width, 0.0f); + glVertex2f((float)width, dy); glTexCoord2f((float)w/(float)pmem.w, (float)h/(float)pmem.h); - glVertex2f((float)width, (float)height); + glVertex2f((float)width, (float)height + dy); glTexCoord2f(0.0f, (float)h/(float)pmem.h); - glVertex2f(0.0f, (float)height); + glVertex2f(0.0f, (float)height + dy); glEnd(); - glPopMatrix(); - if(draw_params.unbind_display_space_shader_cb) { draw_params.unbind_display_space_shader_cb(); } -- cgit v1.2.3 From cc1883468d8537067e0ae6af36075d5cc2d00b68 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 11 May 2015 14:14:06 +0200 Subject: Keep valgrind happy by using tight vec3 packing instead of lax vec4 with an unused coordinate missing. --- source/blender/gpu/intern/gpu_compositing.c | 8 ++++---- source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index ab4726508e8..bf3d1753888 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -717,12 +717,12 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str int ssao_uniform, ssao_color_uniform, viewvecs_uniform, ssao_sample_params_uniform; int ssao_jitter_uniform, ssao_concentric_tex; float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, fx_ssao->attenuation, 0.0f}; - float sample_params[4]; + float sample_params[3]; sample_params[0] = fx->ssao_sample_count_cache; /* multiplier so we tile the random texture on screen */ - sample_params[2] = fx->gbuffer_dim[0] / 64.0; - sample_params[3] = fx->gbuffer_dim[1] / 64.0; + sample_params[1] = fx->gbuffer_dim[0] / 64.0; + sample_params[2] = fx->gbuffer_dim[1] / 64.0; ssao_params[3] = (passes_left == 1) ? dfdyfac[0] : dfdyfac[1]; @@ -740,7 +740,7 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str GPU_shader_uniform_vector(ssao_shader, ssao_uniform, 4, 1, ssao_params); GPU_shader_uniform_vector(ssao_shader, ssao_color_uniform, 4, 1, fx_ssao->color); GPU_shader_uniform_vector(ssao_shader, viewvecs_uniform, 4, 3, viewvecs[0]); - GPU_shader_uniform_vector(ssao_shader, ssao_sample_params_uniform, 4, 1, sample_params); + GPU_shader_uniform_vector(ssao_shader, ssao_sample_params_uniform, 3, 1, sample_params); GPU_texture_bind(src, numslots++); GPU_shader_uniform_texture(ssao_shader, color_uniform, src); diff --git a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl index 783bce75fbd..494a74dcdf8 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl @@ -15,7 +15,7 @@ varying vec4 uvcoordsvar; /* ssao_params.x : pixel scale for the ssao radious */ /* ssao_params.y : factor for the ssao darkening */ uniform vec4 ssao_params; -uniform vec4 ssao_sample_params; +uniform vec3 ssao_sample_params; uniform vec4 ssao_color; /* store the view space vectors for the corners of the view frustum here. @@ -34,7 +34,7 @@ vec3 calculate_view_space_normal(in vec3 viewposition) float calculate_ssao_factor(float depth) { /* take the normalized ray direction here */ - vec2 rotX = texture2D(jitter_tex, uvcoordsvar.xy * ssao_sample_params.zw).rg; + vec2 rotX = texture2D(jitter_tex, uvcoordsvar.xy * ssao_sample_params.yz).rg; vec2 rotY = vec2(-rotX.y, rotX.x); /* occlusion is zero in full depth */ -- cgit v1.2.3 From e38f9144212dc0e7e7f3e6be9b3315435d1669eb Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 11 May 2015 16:28:41 +0200 Subject: Cycles: use vertex buffers when possible to draw tiles on the screen. Not terribly necessary in this case, since we are just drawing a quad, but makes blender overall more GL 3.x core ready. --- intern/cycles/device/device.cpp | 79 ++++++++++++++++++++++++++++++------ intern/cycles/device/device.h | 7 +++- intern/cycles/device/device_cuda.cpp | 59 +++++++++++++++++++++------ 3 files changed, 119 insertions(+), 26 deletions(-) diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 839f35116fa..b34e0646384 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -33,6 +33,13 @@ CCL_NAMESPACE_BEGIN /* Device */ +Device::~Device() +{ + if(!background && vertex_buffer != 0) { + glDeleteBuffers(1, &vertex_buffer); + } +} + void Device::pixels_alloc(device_memory& mem) { mem_alloc(mem, MEM_READ_WRITE); @@ -67,6 +74,9 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w /* for multi devices, this assumes the inefficient method that we allocate * all pixels on the device even though we only render to a subset */ GLhalf *data_pointer = (GLhalf*)rgba.data_pointer; + float vbuffer[16], *basep; + float *vp = NULL; + data_pointer += 4*y*w; /* draw half float texture, GLSL shader for display transform assumed to be bound */ @@ -83,18 +93,63 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w draw_params.bind_display_space_shader_cb(); } - glBegin(GL_QUADS); - - glTexCoord2f(0.0f, 0.0f); - glVertex2f(0.0f, dy); - glTexCoord2f(1.0f, 0.0f); - glVertex2f((float)width, dy); - glTexCoord2f(1.0f, 1.0f); - glVertex2f((float)width, (float)height + dy); - glTexCoord2f(0.0f, 1.0f); - glVertex2f(0.0f, (float)height + dy); - - glEnd(); + if(GLEW_VERSION_1_5) { + if (!vertex_buffer) + glGenBuffers(1, &vertex_buffer); + + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); + /* invalidate old contents - avoids stalling if buffer is still waiting in queue to be rendered */ + glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW); + + vp = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + + basep = NULL; + } + else { + basep = vbuffer; + vp = vbuffer; + } + + if (vp) { + /* texture coordinate - vertex pair */ + vp[0] = 0.0f; + vp[1] = 0.0f; + vp[2] = 0.0f; + vp[3] = dy; + + vp[4] = 1.0f; + vp[5] = 0.0f; + vp[6] = (float)width; + vp[7] = dy; + + vp[8] = 1.0f; + vp[9] = 1.0f; + vp[10] = (float)width; + vp[11] = (float)height + dy; + + vp[12] = 0.0f; + vp[13] = 1.0f; + vp[14] = 0.0f; + vp[15] = (float)height + dy; + + if (vertex_buffer) + glUnmapBuffer(GL_ARRAY_BUFFER); + } + + glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), basep); + glVertexPointer(2, GL_FLOAT, 4 * sizeof(float), ((char *)basep) + 2 * sizeof(float)); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + if(vertex_buffer) { + glBindBuffer(GL_ARRAY_BUFFER, 0); + } if(draw_params.unbind_display_space_shader_cb) { draw_params.unbind_display_space_shader_cb(); diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 162f51252b0..b32f7b406c7 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -119,13 +119,16 @@ struct DeviceDrawParams { class Device { protected: - Device(DeviceInfo& info_, Stats &stats_, bool background) : background(background), info(info_), stats(stats_) {} + Device(DeviceInfo& info_, Stats &stats_, bool background) : background(background), vertex_buffer(0), info(info_), stats(stats_) {} bool background; string error_msg; + /* used for real time display */ + unsigned int vertex_buffer; + public: - virtual ~Device() {} + virtual ~Device(); /* info */ DeviceInfo info; diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 42d4f8e48ff..be6a1f3502d 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -885,6 +885,7 @@ public: { if(!background) { PixelMem pmem = pixel_mem_map[mem.device_pointer]; + float *vpointer; cuda_push_context(); @@ -918,18 +919,52 @@ public: draw_params.bind_display_space_shader_cb(); } - glBegin(GL_QUADS); - - glTexCoord2f(0.0f, 0.0f); - glVertex2f(0.0f, dy); - glTexCoord2f((float)w/(float)pmem.w, 0.0f); - glVertex2f((float)width, dy); - glTexCoord2f((float)w/(float)pmem.w, (float)h/(float)pmem.h); - glVertex2f((float)width, (float)height + dy); - glTexCoord2f(0.0f, (float)h/(float)pmem.h); - glVertex2f(0.0f, (float)height + dy); - - glEnd(); + if (!vertex_buffer) + glGenBuffers(1, &vertex_buffer); + + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); + /* invalidate old contents - avoids stalling if buffer is still waiting in queue to be rendered */ + glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW); + + vpointer = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + + if (vpointer) { + /* texture coordinate - vertex pair */ + vpointer[0] = 0.0f; + vpointer[1] = 0.0f; + vpointer[2] = 0.0f; + vpointer[3] = dy; + + vpointer[4] = (float)w/(float)pmem.w; + vpointer[5] = 0.0f; + vpointer[6] = (float)width; + vpointer[7] = dy; + + vpointer[8] = (float)w/(float)pmem.w; + vpointer[9] = (float)h/(float)pmem.h; + vpointer[10] = (float)width; + vpointer[11] = (float)height + dy; + + vpointer[12] = 0.0f; + vpointer[13] = (float)h/(float)pmem.h; + vpointer[14] = 0.0f; + vpointer[15] = (float)height + dy; + + glUnmapBuffer(GL_ARRAY_BUFFER); + } + + glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), 0); + glVertexPointer(2, GL_FLOAT, 4 * sizeof(float), (char *)NULL + 2 * sizeof(float)); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + glBindBuffer(GL_ARRAY_BUFFER, 0); if(draw_params.unbind_display_space_shader_cb) { draw_params.unbind_display_space_shader_cb(); -- cgit v1.2.3 From d30f664c0438e8378c79d5beb114b1338d0e1d94 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 11 May 2015 16:29:12 +0200 Subject: Expose PreviewImage & custom icons to py API. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit mainly: * Exposes PreviewImage struct in RNA, including ways for user to set images data. * Adds a new kind of PreviewImage, using a file path and IMB_thumb to get image. * Adds a new kind of custom icon using PreviewImage, unrelated to ID previews system. * Adds a python API (utils.previews) to allow python scripts to access those custom previews/icons. Note that loading image from files' thumbnails is done when needed (deferred loading), not when defining the custom preview/icon. WARNING: for release addons who would want to use this, please keep it to a strict minimum, really needed level. We do not want our UI to explode under hundreds of different flashy icons! For more info, see also the release notes of Blender 2.75 (http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.75/Addons) and the example/templates featured with Blender. Patch by Campbell (ideasman42), Inês (brita) and Bastien (mont29). Differential Revision: https://developer.blender.org/D1255 --- release/scripts/modules/bpy/utils/__init__.py | 1 + release/scripts/modules/bpy/utils/previews.py | 137 +++++++++ .../templates_py/ui_previews_custom_icon.py | 82 +++++ .../templates_py/ui_previews_dynamic_enum.py | 136 ++++++++ source/blender/blenkernel/BKE_icons.h | 38 ++- source/blender/blenkernel/intern/icons.c | 342 +++++++++++++++++---- source/blender/blenkernel/intern/image.c | 4 +- source/blender/blenkernel/intern/lamp.c | 2 +- source/blender/blenkernel/intern/material.c | 2 +- source/blender/blenkernel/intern/texture.c | 2 +- source/blender/blenkernel/intern/world.c | 2 +- source/blender/editors/include/ED_render.h | 10 +- .../blender/editors/include/UI_interface_icons.h | 2 +- source/blender/editors/interface/interface.c | 41 +-- source/blender/editors/interface/interface_icons.c | 151 ++++++--- .../blender/editors/interface/interface_intern.h | 3 + .../editors/interface/interface_templates.c | 14 +- source/blender/editors/render/render_preview.c | 149 +++++---- source/blender/editors/render/render_update.c | 16 +- source/blender/editors/space_image/image_ops.c | 2 +- source/blender/imbuf/IMB_thumbs.h | 2 + source/blender/imbuf/intern/thumbs.c | 4 +- source/blender/makesdna/DNA_ID.h | 22 +- source/blender/makesrna/RNA_access.h | 1 + source/blender/makesrna/intern/rna_ID.c | 236 ++++++++++++++ source/blender/makesrna/intern/rna_brush.c | 8 +- source/blender/makesrna/intern/rna_main_api.c | 7 +- source/blender/python/intern/CMakeLists.txt | 3 + source/blender/python/intern/bpy.c | 2 + source/blender/python/intern/bpy_utils_previews.c | 188 +++++++++++ source/blender/python/intern/bpy_utils_previews.h | 32 ++ source/blender/windowmanager/intern/wm_init_exit.c | 22 +- 32 files changed, 1424 insertions(+), 239 deletions(-) create mode 100644 release/scripts/modules/bpy/utils/previews.py create mode 100644 release/scripts/templates_py/ui_previews_custom_icon.py create mode 100644 release/scripts/templates_py/ui_previews_dynamic_enum.py create mode 100644 source/blender/python/intern/bpy_utils_previews.c create mode 100644 source/blender/python/intern/bpy_utils_previews.h diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py index 5f235ae3958..fa97714eee6 100644 --- a/release/scripts/modules/bpy/utils/__init__.py +++ b/release/scripts/modules/bpy/utils/__init__.py @@ -38,6 +38,7 @@ __all__ = ( "unregister_manual_map", "make_rna_paths", "manual_map", + "previews", "resource_path", "script_path_user", "script_path_pref", diff --git a/release/scripts/modules/bpy/utils/previews.py b/release/scripts/modules/bpy/utils/previews.py new file mode 100644 index 00000000000..4e8adf8e209 --- /dev/null +++ b/release/scripts/modules/bpy/utils/previews.py @@ -0,0 +1,137 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# + +""" +This module contains utility functions to handle custom previews. + +It behaves as a high-level 'cached' previews manager. + +This allows addons to generate their own previews, and use them as icons in UI widgets +('icon_value' of UILayout functions). +""" + +__all__ = ( + "new", + "remove", + ) + +import _bpy +_utils_previews = _bpy._utils_previews +del _bpy + + +_uuid_open = set() + + +# High-level previews manager. +# not accessed directly +class _BPyImagePreviewCollection(dict): + """ + Dict-like class of previews. + """ + + # Internal notes: + # - keys in the dict are stored by name + # - values are instances of bpy.types.ImagePreview + # - Blender's internal 'PreviewImage' struct uses 'self._uuid' prefix. + + def __init__(self): + super().__init__() + self._uuid = hex(id(self)) + _uuid_open.add(self._uuid) + + def __del__(self): + if self._uuid not in _uuid_open: + return + + raise ResourceWarning( + "<%s id=%s[%d]>: left open, remove with " + "'bpy.utils.previews.remove()'" % + (self.__class__.__name__, self._uuid, len(self))) + self.close() + + def _gen_key(self, name): + return ":".join((self._uuid, name)) + + def new(self, name): + if name in self: + raise KeyException("key %r already exists") + p = self[name] = _utils_previews.new( + self._gen_key(name)) + return p + new.__doc__ = _utils_previews.new.__doc__ + + def load(self, name, path, path_type, force_reload=False): + if name in self: + raise KeyException("key %r already exists") + p = self[name] = _utils_previews.load( + self._gen_key(name), path, path_type, force_reload) + return p + load.__doc__ = _utils_previews.load.__doc__ + + def release(self, name): + p = self.pop(name, None) + if p is not None: + _utils_previews.release(self._gen_key(name)) + release.__doc__ = _utils_previews.release.__doc__ + + def clear(self): + for name in self.keys(): + _utils_previews.release(self._gen_key(name)) + super().clear() + + def close(self): + self.clear() + _uuid_open.remove(self._uuid) + + def __delitem__(self, key): + return self.release(key) + + def __repr__(self): + return "<%s id=%s[%d], %s>" % ( + self.__class__.__name__, + self._uuid, + len(self), + super().__repr__()) + + +def new(): + """ + Return a new preview collection. + """ + + return _BPyImagePreviewCollection() + + +def remove(p): + """ + Remove the specified previews collection. + """ + p.close() + + +# don't complain about resources on exit (only unregister) +import atexit + +def exit_clear_warning(): + del _BPyImagePreviewCollection.__del__ + +atexit.register(exit_clear_warning) +del atexit, exit_clear_warning diff --git a/release/scripts/templates_py/ui_previews_custom_icon.py b/release/scripts/templates_py/ui_previews_custom_icon.py new file mode 100644 index 00000000000..defa2d266e6 --- /dev/null +++ b/release/scripts/templates_py/ui_previews_custom_icon.py @@ -0,0 +1,82 @@ +# This sample script demonstrates how to place a custom icon on a button or +# menu entry. +# +# IMPORTANT NOTE: if you run this sample, there will be no icon in the button +# You need to replace the image path with a real existing one. +# For distributable addons, it is recommended to place the icons inside the +# addon folder and access it relative to the py script file for portability +# +# +# Other use cases for UI-previews: +# - provide a fixed list of previews to select from +# - provide a dynamic list of preview (eg. calculated from reading a directory) +# +# For the above use cases, see the template 'ui_previews_dynamic_enum.py" + + +import os +import bpy + + +class PreviewsExamplePanel(bpy.types.Panel): + """Creates a Panel in the Object properties window""" + bl_label = "Previews Example Panel" + bl_idname = "OBJECT_PT_previews" + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "object" + + def draw(self, context): + layout = self.layout + pcoll = preview_collections["main"] + + row = layout.row() + my_icon = pcoll.get("my_icon") + row.operator("render.render", icon_value=my_icon.icon_id) + + # my_icon.icon_id can be used in any UI function that accepts + # icon_value # try also setting text="" + # to get an icon only operator button + + +# We can store multiple preview collections here, +# however in this example we only store "main" +preview_collections = {} + + +def register(): + + # Note that preview collections returned by bpy.utils.previews + # are regular py objects - you can use them to store custom data. + import bpy.utils.previews + pcoll = bpy.utils.previews.new() + + # path to the folder where the icon is + # the path is calculated relative to this py file inside the addon folder + my_icons_dir = os.path.join(os.path.dirname(__file__), "icons") + + # load a preview thumbnail of a file and store in the previews collection + pcoll.load( + # identifier + "my_icon", + # path to image + os.path.join(my_icons_dir, "icon-image.png"), + # file type to generate preview from. others are: MOVIE, FONT, BLEND + 'IMAGE') + + preview_collections["main"] = pcoll + + bpy.utils.register_class(PreviewsExamplePanel) + + +def unregister(): + + for pcoll in preview_collections.values(): + bpy.utils.previews.remove(pcoll) + preview_collections.clear() + + bpy.utils.unregister_class(PreviewsExamplePanel) + + +if __name__ == "__main__": + register() diff --git a/release/scripts/templates_py/ui_previews_dynamic_enum.py b/release/scripts/templates_py/ui_previews_dynamic_enum.py new file mode 100644 index 00000000000..1603df0335f --- /dev/null +++ b/release/scripts/templates_py/ui_previews_dynamic_enum.py @@ -0,0 +1,136 @@ +# This sample script demonstrates a dynamic EnumProperty with custom icons. +# The EnumProperty is populated dynamically with thumbnails of the contents of +# a chosen directory in 'enum_previews_from_directory_items'. +# Then, the same enum is displayed with different interfaces. Note that the +# generated icon previews do not have Blender IDs, which means that they can +# not be used with UILayout templates that require IDs, +# such as template_list and template_ID_preview. +# +# Other use cases: +# - make a fixed list of enum_items instead of calculating them in a function +# - generate isolated thumbnails to use as custom icons in buttons +# and menu items +# +# For custom icons, see the template "ui_previews_custom_icon.py". +# +# For distributable addons, it is recommended to place the icons inside the +# addon directory and access it relative to the py script file for portability: +# +# os.path.join(os.path.dirname(__file__), "images") + + +import os +import bpy + + +def enum_previews_from_directory_items(self, context): + """EnumProperty callback""" + wm = context.window_manager + + enum_items = [] + directory = wm.my_previews_dir + + # Get the preview collection (defined in register func). + pcoll = preview_collections["main"] + + if directory == pcoll.my_previews_dir: + return pcoll.my_previews + + print("Scanning directory: %s" % directory) + + if directory and os.path.exists(directory): + # Scan the directory for png files + image_paths = [] + for fn in os.listdir(directory): + if fn.lower().endswith(".png"): + image_paths.append(fn) + + for i, name in enumerate(image_paths): + # generates a thumbnail preview for a file. + # Also works with previews for 'MOVIE', 'BLEND' and 'FONT' + filepath = os.path.join(directory, name) + thumb = pcoll.load(filepath, filepath, 'IMAGE') + # enum item: (identifier, name, description, icon, number) + enum_items.append((name, name, name, thumb.icon_id, i)) + + pcoll.my_previews = enum_items + pcoll.my_previews_dir = directory + return pcoll.my_previews + + +class PreviewsExamplePanel(bpy.types.Panel): + """Creates a Panel in the Object properties window""" + bl_label = "Previews Example Panel" + bl_idname = "OBJECT_PT_previews" + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "object" + + def draw(self, context): + layout = self.layout + wm = context.window_manager + + row = layout.row() + row.prop(wm, "my_previews_dir") + + row = layout.row() + row.template_icon_view(wm, "my_previews") + + row = layout.row() + row.prop(wm, "my_previews") + + +# We can store multiple preview collections here, +# however in this example we only store "main" +preview_collections = {} + + +def register(): + from bpy.types import WindowManager + from bpy.props import ( + StringProperty, + EnumProperty, + ) + + WindowManager.my_previews_dir = StringProperty( + name="Folder Path", + subtype='DIR_PATH', + default="" + ) + + WindowManager.my_previews = EnumProperty( + items=enum_previews_from_directory_items, + ) + + # Note that preview collections returned by bpy.utils.previews + # are regular Python objects - you can use them to store custom data. + # + # This is especially useful here, since: + # - It avoids us regenerating the whole enum over and over. + # - It can store enum_items' strings + # (remember you have to keep those strings somewhere in py, + # else they get freed and Blender references invalid memory!). + import bpy.utils.previews + pcoll = bpy.utils.previews.new() + pcoll.my_previews_dir = "" + pcoll.my_previews = () + + preview_collections["main"] = pcoll + + bpy.utils.register_class(PreviewsExamplePanel) + + +def unregister(): + from bpy.types import WindowManager + + del WindowManager.my_previews + + for pcoll in preview_collections.values(): + bpy.utils.previews.remove(pcoll) + preview_collections.clear() + + bpy.utils.unregister_class(PreviewsExamplePanel) + + +if __name__ == "__main__": + register() diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index 9af0d96884a..763a3874d4e 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -48,10 +48,14 @@ typedef struct Icon Icon; struct PreviewImage; struct ID; +enum eIconSizes; + void BKE_icons_init(int first_dyn_id); /* return icon id for library object or create new icon if not found */ -int BKE_icon_getid(struct ID *id); +int BKE_icon_id_ensure(struct ID *id); + +int BKE_icon_preview_ensure(struct PreviewImage *preview); /* retrieve icon for id */ struct Icon *BKE_icon_get(int icon_id); @@ -60,8 +64,10 @@ struct Icon *BKE_icon_get(int icon_id); /* used for inserting the internal icons */ void BKE_icon_set(int icon_id, struct Icon *icon); -/* remove icon and free date if library object becomes invalid */ -void BKE_icon_delete(struct ID *id); +/* remove icon and free data if library object becomes invalid */ +void BKE_icon_id_delete(struct ID *id); + +void BKE_icon_delete(int icon_id); /* report changes - icon needs to be recalculated */ void BKE_icon_changed(int icon_id); @@ -75,8 +81,17 @@ void BKE_previewimg_freefunc(void *link); /* free the preview image */ void BKE_previewimg_free(struct PreviewImage **prv); +/* clear the preview image or icon, but does not free it */ +void BKE_previewimg_clear(struct PreviewImage *prv); + +/* clear the preview image or icon at a specific size */ +void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size); + +/* get the preview from any pointer */ +struct PreviewImage **BKE_previewimg_id_get_p(struct ID *id); + /* free the preview image belonging to the id */ -void BKE_previewimg_free_id(struct ID *id); +void BKE_previewimg_id_free(struct ID *id); /* create a new preview image */ struct PreviewImage *BKE_previewimg_create(void); @@ -85,6 +100,19 @@ struct PreviewImage *BKE_previewimg_create(void); struct PreviewImage *BKE_previewimg_copy(struct PreviewImage *prv); /* retrieve existing or create new preview image */ -struct PreviewImage *BKE_previewimg_get(struct ID *id); +struct PreviewImage *BKE_previewimg_id_ensure(struct ID *id); + +void BKE_previewimg_ensure(struct PreviewImage *prv, const int size); + +struct PreviewImage *BKE_previewimg_cached_get(const char *name); + +struct PreviewImage *BKE_previewimg_cached_ensure(const char *name); + +struct PreviewImage *BKE_previewimg_cached_thumbnail_read( + const char *name, const char *path, const int source, bool force_update); + +void BKE_previewimg_cached_release(const char *name); + +#define ICON_RENDER_DEFAULT_HEIGHT 32 #endif /* __BKE_ICONS_H__ */ diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index d3225f3fa35..450c1388f37 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -45,6 +45,7 @@ #include "BLI_utildefines.h" #include "BLI_ghash.h" +#include "BLI_string.h" #include "BKE_icons.h" #include "BKE_global.h" /* only for G.background test */ @@ -53,6 +54,10 @@ #include "GPU_extensions.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" +#include "IMB_thumbs.h" + /* GLOBALS */ static GHash *gIcons = NULL; @@ -61,6 +66,7 @@ static int gNextIconId = 1; static int gFirstIconId = 1; +static GHash *gCachedPreviews = NULL; static void icon_free(void *val) { @@ -105,30 +111,50 @@ void BKE_icons_init(int first_dyn_id) gFirstIconId = first_dyn_id; if (!gIcons) - gIcons = BLI_ghash_int_new("icons_init gh"); + gIcons = BLI_ghash_int_new(__func__); + + if (!gCachedPreviews) { + gCachedPreviews = BLI_ghash_str_new(__func__); + } } void BKE_icons_free(void) { - if (gIcons) + if (gIcons) { BLI_ghash_free(gIcons, NULL, icon_free); - gIcons = NULL; + gIcons = NULL; + } + + if (gCachedPreviews) { + BLI_ghash_free(gCachedPreviews, MEM_freeN, BKE_previewimg_freefunc); + gCachedPreviews = NULL; + } } -PreviewImage *BKE_previewimg_create(void) +static PreviewImage *previewimg_create_ex(size_t deferred_data_size) { PreviewImage *prv_img = NULL; int i; - prv_img = MEM_callocN(sizeof(PreviewImage), "img_prv"); + prv_img = MEM_mallocN(sizeof(PreviewImage) + deferred_data_size, "img_prv"); + memset(prv_img, 0, sizeof(*prv_img)); /* leave deferred data dirty */ + + if (deferred_data_size) { + prv_img->use_deferred = true; + } for (i = 0; i < NUM_ICON_SIZES; ++i) { - prv_img->changed[i] = 1; + prv_img->flag[i] |= PRV_CHANGED; prv_img->changed_timestamp[i] = 0; } return prv_img; } +PreviewImage *BKE_previewimg_create(void) +{ + return previewimg_create_ex(0); +} + void BKE_previewimg_freefunc(void *link) { PreviewImage *prv = (PreviewImage *)link; @@ -138,7 +164,6 @@ void BKE_previewimg_freefunc(void *link) for (i = 0; i < NUM_ICON_SIZES; ++i) { if (prv->rect[i]) { MEM_freeN(prv->rect[i]); - prv->rect[i] = NULL; } if (prv->gputexture[i]) GPU_texture_free(prv->gputexture[i]); @@ -156,6 +181,25 @@ void BKE_previewimg_free(PreviewImage **prv) } } +void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size) +{ + MEM_SAFE_FREE(prv->rect[size]); + if (prv->gputexture[size]) { + GPU_texture_free(prv->gputexture[size]); + } + prv->h[size] = prv->w[size] = 0; + prv->flag[size] |= PRV_CHANGED; + prv->changed_timestamp[size] = 0; +} + +void BKE_previewimg_clear(struct PreviewImage *prv) +{ + int i; + for (i = 0; i < NUM_ICON_SIZES; ++i) { + BKE_previewimg_clear_single(prv, i); + } +} + PreviewImage *BKE_previewimg_copy(PreviewImage *prv) { PreviewImage *prv_img = NULL; @@ -167,79 +211,186 @@ PreviewImage *BKE_previewimg_copy(PreviewImage *prv) if (prv->rect[i]) { prv_img->rect[i] = MEM_dupallocN(prv->rect[i]); } - else { - prv_img->rect[i] = NULL; - } prv_img->gputexture[i] = NULL; } } return prv_img; } -void BKE_previewimg_free_id(ID *id) +PreviewImage **BKE_previewimg_id_get_p(ID *id) { - if (GS(id->name) == ID_MA) { - Material *mat = (Material *)id; - BKE_previewimg_free(&mat->preview); - } - else if (GS(id->name) == ID_TE) { - Tex *tex = (Tex *)id; - BKE_previewimg_free(&tex->preview); - } - else if (GS(id->name) == ID_WO) { - World *wo = (World *)id; - BKE_previewimg_free(&wo->preview); + switch (GS(id->name)) { +#define ID_PRV_CASE(id_code, id_struct) case id_code: { return &((id_struct *)id)->preview; } + ID_PRV_CASE(ID_MA, Material); + ID_PRV_CASE(ID_TE, Tex); + ID_PRV_CASE(ID_WO, World); + ID_PRV_CASE(ID_LA, Lamp); + ID_PRV_CASE(ID_IM, Image); + ID_PRV_CASE(ID_BR, Brush); +#undef ID_PRV_CASE } - else if (GS(id->name) == ID_LA) { - Lamp *la = (Lamp *)id; - BKE_previewimg_free(&la->preview); - } - else if (GS(id->name) == ID_IM) { - Image *img = (Image *)id; - BKE_previewimg_free(&img->preview); + + return NULL; +} + +void BKE_previewimg_id_free(ID *id) +{ + PreviewImage **prv_p = BKE_previewimg_id_get_p(id); + if (prv_p) { + BKE_previewimg_free(prv_p); } - else if (GS(id->name) == ID_BR) { - Brush *br = (Brush *)id; - BKE_previewimg_free(&br->preview); +} + +PreviewImage *BKE_previewimg_id_ensure(ID *id) +{ + PreviewImage **prv_p = BKE_previewimg_id_get_p(id); + + if (prv_p) { + if (*prv_p == NULL) { + *prv_p = BKE_previewimg_create(); + } + return *prv_p; } + + return NULL; } -PreviewImage *BKE_previewimg_get(ID *id) +PreviewImage *BKE_previewimg_cached_get(const char *name) { - PreviewImage *prv_img = NULL; + return BLI_ghash_lookup(gCachedPreviews, name); +} - if (GS(id->name) == ID_MA) { - Material *mat = (Material *)id; - if (!mat->preview) mat->preview = BKE_previewimg_create(); - prv_img = mat->preview; +/** + * Generate an empty PreviewImage, if not yet existing. + */ +PreviewImage *BKE_previewimg_cached_ensure(const char *name) +{ + PreviewImage *prv = NULL; + void **prv_p; + + if (!BLI_ghash_ensure_p_ex(gCachedPreviews, name, &prv_p, (GHashKeyCopyFP)BLI_strdup)) { + *prv_p = BKE_previewimg_create(); } - else if (GS(id->name) == ID_TE) { - Tex *tex = (Tex *)id; - if (!tex->preview) tex->preview = BKE_previewimg_create(); - prv_img = tex->preview; + prv = *prv_p; + BLI_assert(prv); + + return prv; +} + +/** + * Generate a PreviewImage from given file path, using thumbnails management, if not yet existing. + */ +PreviewImage *BKE_previewimg_cached_thumbnail_read( + const char *name, const char *path, const int source, bool force_update) +{ + PreviewImage *prv = NULL; + void **prv_p; + + prv_p = BLI_ghash_lookup_p(gCachedPreviews, name); + + if (prv_p) { + prv = *prv_p; + BLI_assert(prv); } - else if (GS(id->name) == ID_WO) { - World *wo = (World *)id; - if (!wo->preview) wo->preview = BKE_previewimg_create(); - prv_img = wo->preview; + + if (prv && force_update) { + const char *prv_deferred_data = PRV_DEFERRED_DATA(prv); + if (((int)prv_deferred_data[0] == source) && STREQ(&prv_deferred_data[1], path)) { + /* If same path, no need to re-allocate preview, just clear it up. */ + BKE_previewimg_clear(prv); + } + else { + BKE_previewimg_free(&prv); + } } - else if (GS(id->name) == ID_LA) { - Lamp *la = (Lamp *)id; - if (!la->preview) la->preview = BKE_previewimg_create(); - prv_img = la->preview; + + if (!prv) { + /* We pack needed data for lazy loading (source type, in a single char, and path). */ + const size_t deferred_data_size = strlen(path) + 2; + char *deferred_data; + + prv = previewimg_create_ex(deferred_data_size); + deferred_data = PRV_DEFERRED_DATA(prv); + deferred_data[0] = source; + memcpy(&deferred_data[1], path, deferred_data_size - 1); + + force_update = true; } - else if (GS(id->name) == ID_IM) { - Image *img = (Image *)id; - if (!img->preview) img->preview = BKE_previewimg_create(); - prv_img = img->preview; + + if (force_update) { + if (prv_p) { + *prv_p = prv; + } + else { + BLI_ghash_insert(gCachedPreviews, BLI_strdup(name), prv); + } } - else if (GS(id->name) == ID_BR) { - Brush *br = (Brush *)id; - if (!br->preview) br->preview = BKE_previewimg_create(); - prv_img = br->preview; + + return prv; +} + +void BKE_previewimg_cached_release(const char *name) +{ + PreviewImage *prv = BLI_ghash_popkey(gCachedPreviews, name, MEM_freeN); + + if (prv) { + if (prv->icon_id) { + BKE_icon_delete(prv->icon_id); + } + BKE_previewimg_freefunc(prv); } +} - return prv_img; +/** Handle deferred (lazy) loading/generation of preview image, if needed. + * For now, only used with file thumbnails. */ +void BKE_previewimg_ensure(PreviewImage *prv, const int size) +{ + if (prv->use_deferred) { + const bool do_icon = ((size == ICON_SIZE_ICON) && !prv->rect[ICON_SIZE_ICON]); + const bool do_preview = ((size == ICON_SIZE_PREVIEW) && !prv->rect[ICON_SIZE_PREVIEW]); + + if (do_icon || do_preview) { + ImBuf *thumb; + char *prv_deferred_data = PRV_DEFERRED_DATA(prv); + int source = prv_deferred_data[0]; + char *path = &prv_deferred_data[1]; + int icon_w, icon_h; + + thumb = IMB_thumb_manage(path, THB_LARGE, source); + + if (thumb) { + /* PreviewImage assumes premultiplied alhpa... */ + IMB_premultiply_alpha(thumb); + + if (do_preview) { + prv->w[ICON_SIZE_PREVIEW] = thumb->x; + prv->h[ICON_SIZE_PREVIEW] = thumb->y; + prv->rect[ICON_SIZE_PREVIEW] = MEM_dupallocN(thumb->rect); + prv->flag[ICON_SIZE_PREVIEW] &= ~(PRV_CHANGED | PRV_USER_EDITED); + } + if (do_icon) { + if (thumb->x > thumb->y) { + icon_w = ICON_RENDER_DEFAULT_HEIGHT; + icon_h = (thumb->y * icon_w) / thumb->x + 1; + } + else if (thumb->x < thumb->y) { + icon_h = ICON_RENDER_DEFAULT_HEIGHT; + icon_w = (thumb->x * icon_h) / thumb->y + 1; + } + else { + icon_w = icon_h = ICON_RENDER_DEFAULT_HEIGHT; + } + + IMB_scaleImBuf(thumb, icon_w, icon_h); + prv->w[ICON_SIZE_ICON] = icon_w; + prv->h[ICON_SIZE_ICON] = icon_h; + prv->rect[ICON_SIZE_ICON] = MEM_dupallocN(thumb->rect); + prv->flag[ICON_SIZE_ICON] &= ~(PRV_CHANGED | PRV_USER_EDITED); + } + IMB_freeImBuf(thumb); + } + } + } } void BKE_icon_changed(int id) @@ -251,20 +402,20 @@ void BKE_icon_changed(int id) icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(id)); if (icon) { - PreviewImage *prv = BKE_previewimg_get((ID *)icon->obj); + PreviewImage *prv = BKE_previewimg_id_ensure((ID *)icon->obj); /* all previews changed */ if (prv) { int i; for (i = 0; i < NUM_ICON_SIZES; ++i) { - prv->changed[i] = 1; + prv->flag[i] |= PRV_CHANGED; prv->changed_timestamp[i]++; } } } } -int BKE_icon_getid(struct ID *id) +int BKE_icon_id_ensure(struct ID *id) { Icon *new_icon = NULL; @@ -277,11 +428,11 @@ int BKE_icon_getid(struct ID *id) id->icon_id = get_next_free_id(); if (!id->icon_id) { - printf("BKE_icon_getid: Internal error - not enough IDs\n"); + printf("%s: Internal error - not enough IDs\n", __func__); return 0; } - new_icon = MEM_callocN(sizeof(Icon), "texicon"); + new_icon = MEM_mallocN(sizeof(Icon), __func__); new_icon->obj = id; new_icon->type = GS(id->name); @@ -295,6 +446,40 @@ int BKE_icon_getid(struct ID *id) return id->icon_id; } +/** + * Return icon id of given preview, or create new icon if not found. + */ +int BKE_icon_preview_ensure(PreviewImage *preview) +{ + Icon *new_icon = NULL; + + if (!preview || G.background) + return 0; + + if (preview->icon_id) + return preview->icon_id; + + preview->icon_id = get_next_free_id(); + + if (!preview->icon_id) { + printf("%s: Internal error - not enough IDs\n", __func__); + return 0; + } + + new_icon = MEM_mallocN(sizeof(Icon), __func__); + + new_icon->obj = preview; + new_icon->type = 0; /* Special, tags as non-ID icon/preview. */ + + /* next two lines make sure image gets created */ + new_icon->drawinfo = NULL; + new_icon->drawinfo_free = NULL; + + BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(preview->icon_id), new_icon); + + return preview->icon_id; +} + Icon *BKE_icon_get(int icon_id) { Icon *icon = NULL; @@ -302,7 +487,7 @@ Icon *BKE_icon_get(int icon_id) icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(icon_id)); if (!icon) { - printf("BKE_icon_get: Internal error, no icon for icon ID: %d\n", icon_id); + printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id); return NULL; } @@ -314,18 +499,39 @@ void BKE_icon_set(int icon_id, struct Icon *icon) void **val_p; if (BLI_ghash_ensure_p(gIcons, SET_INT_IN_POINTER(icon_id), &val_p)) { - printf("BKE_icon_set: Internal error, icon already set: %d\n", icon_id); + printf("%s: Internal error, icon already set: %d\n", __func__, icon_id); return; } *val_p = icon; } -void BKE_icon_delete(struct ID *id) +void BKE_icon_id_delete(struct ID *id) { - if (!id->icon_id) return; /* no icon defined for library object */ BLI_ghash_remove(gIcons, SET_INT_IN_POINTER(id->icon_id), NULL, icon_free); id->icon_id = 0; } + +/** + * Remove icon and free data. + */ +void BKE_icon_delete(int icon_id) +{ + Icon *icon; + + if (!icon_id) return; /* no icon defined for library object */ + + icon = BLI_ghash_popkey(gIcons, SET_INT_IN_POINTER(icon_id), NULL); + + if (icon) { + if (icon->type) { + ((ID *)(icon->obj))->icon_id = 0; + } + else { + ((PreviewImage *)(icon->obj))->icon_id = 0; + } + icon_free(icon); + } +} diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index f3f4775dbf7..29576e4f1f6 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -338,7 +338,7 @@ void BKE_image_free(Image *ima) image_free_packedfiles(ima); - BKE_icon_delete(&ima->id); + BKE_icon_id_delete(&ima->id); ima->id.icon_id = 0; BKE_previewimg_free(&ima->preview); @@ -3001,7 +3001,7 @@ 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)); + BKE_icon_changed(BKE_icon_id_ensure(&ima->id)); /* fields */ if (ima->flag & IMA_FIELDS) { diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 96b0b95adf3..44e35c645de 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -232,7 +232,7 @@ void BKE_lamp_free(Lamp *la) } BKE_previewimg_free(&la->preview); - BKE_icon_delete(&la->id); + BKE_icon_id_delete(&la->id); la->id.icon_id = 0; } diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index eaaf1319167..283c7a6fc88 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -106,7 +106,7 @@ void BKE_material_free_ex(Material *ma, bool do_id_user) if (ma->preview) BKE_previewimg_free(&ma->preview); - BKE_icon_delete((struct ID *)ma); + BKE_icon_id_delete((struct ID *)ma); ma->id.icon_id = 0; /* is no lib link block, but material extension */ diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 8e4fcc5d1cc..246e3f2a316 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -567,7 +567,7 @@ void BKE_texture_free(Tex *tex) BKE_animdata_free((struct ID *)tex); BKE_previewimg_free(&tex->preview); - BKE_icon_delete((struct ID *)tex); + BKE_icon_id_delete((struct ID *)tex); tex->id.icon_id = 0; if (tex->nodetree) { diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index f26cbf7880a..e4736b1f54c 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -74,7 +74,7 @@ void BKE_world_free_ex(World *wrld, bool do_id_user) if (wrld->gpumaterial.first) GPU_material_free(&wrld->gpumaterial); - BKE_icon_delete((struct ID *)wrld); + BKE_icon_id_delete((struct ID *)wrld); wrld->id.icon_id = 0; } diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h index 2bc0566f4a6..414126cac13 100644 --- a/source/blender/editors/include/ED_render.h +++ b/source/blender/editors/include/ED_render.h @@ -60,11 +60,15 @@ struct Scene *ED_render_job_get_current_scene(const struct bContext *C); * - PR_BUTS_RENDER: preview is rendered for buttons window * - PR_ICON_RENDER: preview is rendered for icons. hopefully fast enough for at least 32x32 * - PR_NODE_RENDER: preview is rendered for node editor + * - PR_ICON_DEFERRED: No render, we just ensure deferred icon data gets generated. */ -#define PR_BUTS_RENDER 0 -#define PR_ICON_RENDER 1 -#define PR_NODE_RENDER 2 +enum { + PR_BUTS_RENDER = 0, + PR_ICON_RENDER = 1, + PR_NODE_RENDER = 2, + PR_ICON_DEFERRED = 3, +}; void ED_preview_init_dbase(void); void ED_preview_free_dbase(void); diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index 9d190fa81c7..92f3b0180c6 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -49,7 +49,7 @@ typedef struct IconFile { #define ICON_DEFAULT_HEIGHT_SCALE ((int)(UI_UNIT_Y * 0.8f)) #define ICON_DEFAULT_WIDTH_SCALE ((int)(UI_UNIT_X * 0.8f)) -#define PREVIEW_DEFAULT_HEIGHT 96 +#define PREVIEW_DEFAULT_HEIGHT 128 /* * Resizable Icons for Blender diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index b63871f5c82..a9cc926b275 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -3237,6 +3237,18 @@ static uiBut *ui_def_but( return but; } +void ui_def_but_icon(uiBut *but, const int icon, const int flag) { + if (icon) { + ui_icon_ensure_deferred(but->block->evil_C, icon, (flag & UI_BUT_ICON_PREVIEW) != 0); + } + but->icon = (BIFIconID)icon; + but->flag |= flag; + + if (but->str && but->str[0]) { + but->drawflag |= UI_BUT_ICON_LEFT; + } +} + static void ui_def_but_rna__disable(uiBut *but) { but->flag |= UI_BUT_DISABLED; @@ -3500,11 +3512,7 @@ static uiBut *ui_def_but_rna( but->rnaindex = 0; if (icon) { - but->icon = (BIFIconID)icon; - but->flag |= UI_HAS_ICON; - if (str[0]) { - but->drawflag |= UI_BUT_ICON_LEFT; - } + ui_def_but_icon(but, icon, UI_HAS_ICON); } if ((type == UI_BTYPE_MENU) && (but->dt == UI_EMBOSS_PULLDOWN)) { @@ -3691,8 +3699,7 @@ int UI_autocomplete_end(AutoComplete *autocpl, char *autoname) static void ui_but_update_and_icon_set(uiBut *but, int icon) { if (icon) { - but->icon = (BIFIconID) icon; - but->flag |= UI_HAS_ICON; + ui_def_but_icon(but, icon, UI_HAS_ICON); } ui_but_update(but); @@ -4066,7 +4073,7 @@ void UI_but_drag_set_value(uiBut *but) void UI_but_drag_set_image(uiBut *but, const char *path, int icon, struct ImBuf *imb, float scale) { but->dragtype = WM_DRAG_PATH; - but->icon = icon; /* no flag UI_HAS_ICON, so icon doesnt draw in button */ + ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesnt draw in button */ but->dragpoin = (void *)path; but->imb = imb; but->imb_scale = scale; @@ -4220,8 +4227,7 @@ uiBut *uiDefIconTextMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, in { uiBut *but = ui_def_but(block, UI_BTYPE_PULLDOWN, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip); - but->icon = (BIFIconID) icon; - but->flag |= UI_HAS_ICON; + ui_def_but_icon(but, icon, UI_HAS_ICON); but->drawflag |= UI_BUT_ICON_LEFT; but->flag |= UI_BUT_ICON_SUBMENU; @@ -4236,8 +4242,7 @@ uiBut *uiDefIconMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int ic { uiBut *but = ui_def_but(block, UI_BTYPE_PULLDOWN, 0, "", x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip); - but->icon = (BIFIconID) icon; - but->flag |= UI_HAS_ICON; + ui_def_but_icon(but, icon, UI_HAS_ICON); but->drawflag &= ~UI_BUT_ICON_LEFT; but->menu_create_func = func; @@ -4253,7 +4258,7 @@ uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, /* XXX temp, old menu calls pass on icon arrow, which is now UI_BUT_ICON_SUBMENU flag */ if (icon != ICON_RIGHTARROW_THIN) { - but->icon = (BIFIconID) icon; + ui_def_but_icon(but, icon, 0); but->drawflag |= UI_BUT_ICON_LEFT; } but->flag |= UI_HAS_ICON; @@ -4270,9 +4275,8 @@ uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int { uiBut *but = ui_def_but(block, UI_BTYPE_BLOCK, retval, "", x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip); - but->icon = (BIFIconID) icon; - but->flag |= UI_HAS_ICON; - + ui_def_but_icon(but, icon, UI_HAS_ICON); + but->drawflag |= UI_BUT_ICON_LEFT; but->block_create_func = func; @@ -4305,9 +4309,8 @@ uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxle { uiBut *but = ui_def_but(block, UI_BTYPE_SEARCH_MENU, retval, "", x, y, width, height, arg, 0.0, maxlen, a1, a2, tip); - but->icon = (BIFIconID) icon; - but->flag |= UI_HAS_ICON; - + ui_def_but_icon(but, icon, UI_HAS_ICON); + but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT; ui_but_update(but); diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 6536c0a869e..7c05d5f4378 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -55,6 +55,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_thumbs.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -904,10 +905,13 @@ void UI_icons_init(int first_dyn_id) static int preview_render_size(enum eIconSizes size) { switch (size) { - case ICON_SIZE_ICON: return 32; - case ICON_SIZE_PREVIEW: return PREVIEW_DEFAULT_HEIGHT; + case ICON_SIZE_ICON: + return ICON_RENDER_DEFAULT_HEIGHT; + case ICON_SIZE_PREVIEW: + return PREVIEW_RENDER_DEFAULT_HEIGHT; + default: + return 0; } - return 0; } /* Create rect for the icon @@ -923,12 +927,49 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size) else if (!prv_img->rect[size]) { prv_img->w[size] = render_size; prv_img->h[size] = render_size; - prv_img->changed[size] = 1; + prv_img->flag[size] |= PRV_CHANGED; prv_img->changed_timestamp[size] = 0; prv_img->rect[size] = MEM_callocN(render_size * render_size * sizeof(unsigned int), "prv_rect"); } } +void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool big) +{ + Icon *icon = BKE_icon_get(icon_id); + + if (icon) { + DrawInfo *di = (DrawInfo *)icon->drawinfo; + + if (!di) { + di = icon_create_drawinfo(); + + icon->drawinfo = di; + icon->drawinfo_free = UI_icons_free_drawinfo; + } + + if (di) { + if (di->type == ICON_TYPE_PREVIEW) { + PreviewImage *prv = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj; + + if (prv) { + const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON; + + if (!prv->use_deferred || prv->rect[size] || (prv->flag[size] & PRV_USER_EDITED)) { + return; + } + + icon_create_rect(prv, size); + + /* Always using job (background) version. */ + ED_preview_icon_job(C, prv, NULL, prv->rect[size], prv->w[size], prv->h[size]); + + prv->flag[size] &= ~PRV_CHANGED; + } + } + } + } +} + /* only called when icon has changed */ /* only call with valid pointer from UI_icon_draw */ static void icon_set_image( @@ -940,6 +981,11 @@ static void icon_set_image( return; } + if (prv_img->flag[size] & PRV_USER_EDITED) { + /* user-edited preview, do not auto-update! */ + return; + } + icon_create_rect(prv_img, size); if (use_job) { @@ -961,22 +1007,32 @@ PreviewImage *UI_icon_to_preview(int icon_id) if (icon) { DrawInfo *di = (DrawInfo *)icon->drawinfo; - if (di && di->data.buffer.image) { - ImBuf *bbuf; - - bbuf = IMB_ibImageFromMemory(di->data.buffer.image->datatoc_rect, di->data.buffer.image->datatoc_size, IB_rect, NULL, ""); - if (bbuf) { - PreviewImage *prv = BKE_previewimg_create(); - - prv->rect[0] = bbuf->rect; + if (di) { + if (di->type == ICON_TYPE_PREVIEW) { + PreviewImage *prv = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj; - prv->w[0] = bbuf->x; - prv->h[0] = bbuf->y; - - bbuf->rect = NULL; - IMB_freeImBuf(bbuf); - - return prv; + if (prv) { + return BKE_previewimg_copy(prv); + } + } + else if (di->data.buffer.image) { + ImBuf *bbuf; + + bbuf = IMB_ibImageFromMemory(di->data.buffer.image->datatoc_rect, di->data.buffer.image->datatoc_size, + IB_rect, NULL, __func__); + if (bbuf) { + PreviewImage *prv = BKE_previewimg_create(); + + prv->rect[0] = bbuf->rect; + + prv->w[0] = bbuf->x; + prv->h[0] = bbuf->y; + + bbuf->rect = NULL; + IMB_freeImBuf(bbuf); + + return prv; + } } } } @@ -987,6 +1043,10 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), unsigned int *rect, float alpha, const float rgb[3], const bool is_preview) { ImBuf *ima = NULL; + int draw_w = w; + int draw_h = h; + int draw_x = x; + int draw_y = y; /* sanity check */ if (w <= 0 || h <= 0 || w > 2000 || h > 2000) { @@ -1006,21 +1066,34 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), } /* rect contains image in 'rendersize', we only scale if needed */ - if (rw != w && rh != h) { + if (rw != w || rh != h) { + /* preserve aspect ratio and center */ + if (rw > rh) { + draw_w = w; + draw_h = (int)(((float)rh / (float)rw) * (float)w); + draw_y += (h - draw_h) / 2; + } + else if (rw < rh) { + draw_w = (int)(((float)rw / (float)rh) * (float)h); + draw_h = h; + draw_x += (w - draw_w) / 2; + } + /* if the image is squared, the draw_ initialization values are good */ + /* first allocate imbuf for scaling and copy preview into it */ ima = IMB_allocImBuf(rw, rh, 32, IB_rect); memcpy(ima->rect, rect, rw * rh * sizeof(unsigned int)); - IMB_scaleImBuf(ima, w, h); /* scale it */ + IMB_scaleImBuf(ima, draw_w, draw_h); /* scale it */ rect = ima->rect; } /* draw */ if (is_preview) { - glaDrawPixelsSafe(x, y, w, h, w, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glaDrawPixelsSafe(draw_x, draw_y, draw_w, draw_h, draw_w, GL_RGBA, GL_UNSIGNED_BYTE, rect); } else { - glRasterPos2f(x, y); - glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glRasterPos2f(draw_x, draw_y); + glDrawPixels(draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, rect); } if (ima) @@ -1081,10 +1154,13 @@ static void icon_draw_texture( static int get_draw_size(enum eIconSizes size) { switch (size) { - case ICON_SIZE_ICON: return ICON_DEFAULT_HEIGHT; - case ICON_SIZE_PREVIEW: return PREVIEW_DEFAULT_HEIGHT; + case ICON_SIZE_ICON: + return ICON_DEFAULT_HEIGHT; + case ICON_SIZE_PREVIEW: + return PREVIEW_DEFAULT_HEIGHT; + default: + return 0; } - return 0; } @@ -1147,9 +1223,12 @@ static void icon_draw_size( glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } else if (di->type == ICON_TYPE_PREVIEW) { - PreviewImage *pi = BKE_previewimg_get((ID *)icon->obj); + PreviewImage *pi = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj; if (pi) { + /* Do deferred loading/generation if needed. */ +// BKE_previewimg_ensure(pi, size); + /* no create icon on this level in code */ if (!pi->rect[size]) return; /* something has gone wrong! */ @@ -1164,17 +1243,17 @@ static void icon_draw_size( static void ui_id_preview_image_render_size( const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job) { - if ((pi->changed[size] || !pi->rect[size])) { /* changed only ever set by dynamic icons */ + if (((pi->flag[size] & PRV_CHANGED) || !pi->rect[size])) { /* changed only ever set by dynamic icons */ /* create the rect if necessary */ icon_set_image(C, scene, id, pi, size, use_job); - pi->changed[size] = 0; + pi->flag[size] &= ~PRV_CHANGED; } } void UI_id_icon_render(const bContext *C, Scene *scene, ID *id, const bool big, const bool use_job) { - PreviewImage *pi = BKE_previewimg_get(id); + PreviewImage *pi = BKE_previewimg_id_ensure(id); if (pi) { if (big) @@ -1186,7 +1265,7 @@ void UI_id_icon_render(const bContext *C, Scene *scene, ID *id, const bool big, static void ui_id_brush_render(const bContext *C, ID *id) { - PreviewImage *pi = BKE_previewimg_get(id); + PreviewImage *pi = BKE_previewimg_id_ensure(id); enum eIconSizes i; if (!pi) @@ -1195,9 +1274,9 @@ static void ui_id_brush_render(const bContext *C, ID *id) for (i = 0; i < NUM_ICON_SIZES; i++) { /* check if rect needs to be created; changed * only set by dynamic icons */ - if ((pi->changed[i] || !pi->rect[i])) { + if (((pi->flag[i] & PRV_CHANGED) || !pi->rect[i])) { icon_set_image(C, NULL, id, pi, i, true); - pi->changed[i] = 0; + pi->flag[i] &= ~PRV_CHANGED; } } } @@ -1208,7 +1287,7 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id) Brush *br = (Brush *)id; if (br->flag & BRUSH_CUSTOM_ICON) { - BKE_icon_getid(id); + BKE_icon_id_ensure(id); ui_id_brush_render(C, id); } else { @@ -1270,7 +1349,7 @@ int ui_id_icon_get(const bContext *C, ID *id, const bool big) case ID_IM: /* fall through */ case ID_WO: /* fall through */ case ID_LA: /* fall through */ - iconid = BKE_icon_getid(id); + iconid = BKE_icon_id_ensure(id); /* checks if not exists, or changed */ UI_id_icon_render(C, NULL, id, big, true); break; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index a3192d3b8d0..9461547a164 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -465,6 +465,8 @@ extern bool ui_but_string_set(struct bContext *C, uiBut *but, const char *str) A extern bool ui_but_string_set_eval_num(struct bContext *C, uiBut *but, const char *str, double *value) ATTR_NONNULL(); extern int ui_but_string_get_max_length(uiBut *but); extern uiBut *ui_but_drag_multi_edit_get(uiBut *but); + +void ui_def_but_icon(uiBut *but, const int icon, const int flag); extern uiButExtraIconType ui_but_icon_extra_get(uiBut *but); extern void ui_but_default_set(struct bContext *C, const bool all, const bool use_afterfunc); @@ -673,6 +675,7 @@ void ui_draw_preview_item(struct uiFontStyle *fstyle, rcti *rect, const char *na void uiStyleInit(void); /* interface_icons.c */ +void ui_icon_ensure_deferred(const struct bContext *C, const int icon_id, const bool big); int ui_id_icon_get(const struct bContext *C, struct ID *id, const bool big); /* resources.c */ diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index fe1a1b9096d..9a34e4be980 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -430,8 +430,8 @@ static void template_ID( but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, TIP_(template_id_browse_tip(type))); - but->icon = id ? ui_id_icon_get(C, id, true) : RNA_struct_ui_icon(type); - UI_but_flag_enable(but, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); + ui_def_but_icon(but, id ? ui_id_icon_get(C, id, true) : RNA_struct_ui_icon(type), + UI_HAS_ICON | UI_BUT_ICON_PREVIEW); if ((idfrom && idfrom->lib) || !editable) UI_but_flag_enable(but, UI_BUT_DISABLED); @@ -441,10 +441,9 @@ static void template_ID( else if (flag & UI_ID_BROWSE) { but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y, TIP_(template_id_browse_tip(type))); - but->icon = RNA_struct_ui_icon(type); + ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON); /* default dragging of icon for id browse buttons */ UI_but_drag_set_id(but, id); - UI_but_flag_enable(but, UI_HAS_ICON); UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); if ((idfrom && idfrom->lib) || !editable) @@ -1666,9 +1665,9 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem) icon = item[a].icon; value = item[a].value; - but = uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, icon, x, y, UI_UNIT_X * 5, UI_UNIT_Y * 5, + but = uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, ICON_NONE, x, y, UI_UNIT_X * 5, UI_UNIT_Y * 5, &cb.ptr, cb.prop, -1, 0, value, -1, -1, NULL); - UI_but_flag_enable(but, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); + ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); } UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); @@ -1708,8 +1707,7 @@ void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname) but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); - but->icon = icon; - UI_but_flag_enable(but, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); + ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); if (free_items) { MEM_freeN(items); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 65d4c2301a9..5112cd84d09 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -79,7 +79,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" - +#include "IMB_thumbs.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -128,7 +128,7 @@ ImBuf *get_brush_icon(Brush *brush) } if (brush->icon_imbuf) - BKE_icon_changed(BKE_icon_getid(&brush->id)); + BKE_icon_changed(BKE_icon_id_ensure(&brush->id)); } } } @@ -935,65 +935,87 @@ static void set_alpha(char *cp, int sizex, int sizey, char alpha) static void icon_preview_startjob(void *customdata, short *stop, short *do_update) { ShaderPreview *sp = customdata; - ID *id = sp->id; - short idtype = GS(id->name); - - if (idtype == ID_IM) { - Image *ima = (Image *)id; - ImBuf *ibuf = NULL; - ImageUser iuser = {NULL}; - /* ima->ok is zero when Image cannot load */ - if (ima == NULL || ima->ok == 0) - return; + if (sp->pr_method == PR_ICON_DEFERRED) { + PreviewImage *prv = sp->owner; + ImBuf *thumb; + char *deferred_data = PRV_DEFERRED_DATA(prv); + int source = deferred_data[0]; + char *path = &deferred_data[1]; - /* setup dummy image user */ - iuser.ok = iuser.framenr = 1; - iuser.scene = sp->scene; - - /* elubie: this needs to be changed: here image is always loaded if not - * already there. Very expensive for large images. Need to find a way to - * only get existing ibuf */ - ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); - if (ibuf == NULL || ibuf->rect == NULL) { - BKE_image_release_ibuf(ima, ibuf, NULL); - return; - } - - icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect); +// printf("generating deferred %d×%d preview for %s\n", sp->sizex, sp->sizey, path); + + thumb = IMB_thumb_manage(path, THB_LARGE, source); - *do_update = true; + if (thumb) { + /* PreviewImage assumes premultiplied alhpa... */ + IMB_premultiply_alpha(thumb); - BKE_image_release_ibuf(ima, ibuf, NULL); + icon_copy_rect(thumb, sp->sizex, sp->sizey, sp->pr_rect); + IMB_freeImBuf(thumb); + } } - else if (idtype == ID_BR) { - Brush *br = (Brush *)id; + else { + ID *id = sp->id; + short idtype = GS(id->name); + + if (idtype == ID_IM) { + Image *ima = (Image *)id; + ImBuf *ibuf = NULL; + ImageUser iuser = {NULL}; + + /* ima->ok is zero when Image cannot load */ + if (ima == NULL || ima->ok == 0) + return; + + /* setup dummy image user */ + iuser.ok = iuser.framenr = 1; + iuser.scene = sp->scene; + + /* elubie: this needs to be changed: here image is always loaded if not + * already there. Very expensive for large images. Need to find a way to + * only get existing ibuf */ + ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); + if (ibuf == NULL || ibuf->rect == NULL) { + BKE_image_release_ibuf(ima, ibuf, NULL); + return; + } - br->icon_imbuf = get_brush_icon(br); + icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect); - memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int)); + *do_update = true; - if (!(br->icon_imbuf) || !(br->icon_imbuf->rect)) - return; + BKE_image_release_ibuf(ima, ibuf, NULL); + } + else if (idtype == ID_BR) { + Brush *br = (Brush *)id; - icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect); + br->icon_imbuf = get_brush_icon(br); - *do_update = true; - } - else { - /* re-use shader job */ - shader_preview_startjob(customdata, stop, do_update); + memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int)); + + if (!(br->icon_imbuf) || !(br->icon_imbuf->rect)) + return; - /* world is rendered with alpha=0, so it wasn't displayed - * this could be render option for sky to, for later */ - if (idtype == ID_WO) { - set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255); + icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect); + + *do_update = true; } - else if (idtype == ID_MA) { - Material *ma = (Material *)id; + else { + /* re-use shader job */ + shader_preview_startjob(customdata, stop, do_update); - if (ma->material_type == MA_TYPE_HALO) + /* world is rendered with alpha=0, so it wasn't displayed + * this could be render option for sky to, for later */ + if (idtype == ID_WO) { set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255); + } + else if (idtype == ID_MA) { + Material *ma = (Material *)id; + + if (ma->material_type == MA_TYPE_HALO) + set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255); + } } } } @@ -1005,7 +1027,7 @@ static void common_preview_startjob(void *customdata, short *stop, short *do_upd { ShaderPreview *sp = customdata; - if (sp->pr_method == PR_ICON_RENDER) + if (ELEM(sp->pr_method, PR_ICON_RENDER, PR_ICON_DEFERRED)) icon_preview_startjob(customdata, stop, do_update); else shader_preview_startjob(customdata, stop, do_update); @@ -1041,29 +1063,34 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short const bool use_new_shading = BKE_scene_use_new_shading_nodes(ip->scene); while (cur_size) { + PreviewImage *prv = ip->owner; ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview"); + const bool is_render = !prv->use_deferred; /* construct shader preview from image size and previewcustomdata */ sp->scene = ip->scene; sp->owner = ip->owner; sp->sizex = cur_size->sizex; sp->sizey = cur_size->sizey; - sp->pr_method = PR_ICON_RENDER; + sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED; sp->pr_rect = cur_size->rect; sp->id = ip->id; - if (use_new_shading) { - /* texture icon rendering is hardcoded to use BI, - * so don't even think of using cycle's bmain for - * texture icons - */ - if (GS(ip->id->name) != ID_TE) - sp->pr_main = G_pr_main_cycles; - else + if (is_render) { + BLI_assert(ip->id); + if (use_new_shading) { + /* texture icon rendering is hardcoded to use BI, + * so don't even think of using cycle's bmain for + * texture icons + */ + if (GS(ip->id->name) != ID_TE) + sp->pr_main = G_pr_main_cycles; + else + sp->pr_main = G_pr_main; + } + else { sp->pr_main = G_pr_main; - } - else { - sp->pr_main = G_pr_main; + } } common_preview_startjob(sp, stop, do_update, progress); @@ -1145,7 +1172,7 @@ void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *r /* customdata for preview thread */ ip->scene = CTX_data_scene(C); - ip->owner = id; + ip->owner = owner; ip->id = id; icon_preview_add_size(ip, rect, sizex, sizey); diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index d3d5cb12ac8..dedcbb144aa 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -270,7 +270,7 @@ static void material_changed(Main *bmain, Material *ma) int texture_draw = false; /* icons */ - BKE_icon_changed(BKE_icon_getid(&ma->id)); + BKE_icon_changed(BKE_icon_id_ensure(&ma->id)); /* glsl */ if (ma->gpumaterial.first) @@ -285,7 +285,7 @@ static void material_changed(Main *bmain, Material *ma) continue; } - BKE_icon_changed(BKE_icon_getid(&parent->id)); + BKE_icon_changed(BKE_icon_id_ensure(&parent->id)); if (parent->gpumaterial.first) GPU_material_free(&parent->gpumaterial); @@ -325,7 +325,7 @@ static void lamp_changed(Main *bmain, Lamp *la) Material *ma; /* icons */ - BKE_icon_changed(BKE_icon_getid(&la->id)); + BKE_icon_changed(BKE_icon_id_ensure(&la->id)); /* glsl */ for (ob = bmain->object.first; ob; ob = ob->id.next) @@ -361,7 +361,7 @@ static void texture_changed(Main *bmain, Tex *tex) bool texture_draw = false; /* icons */ - BKE_icon_changed(BKE_icon_getid(&tex->id)); + BKE_icon_changed(BKE_icon_id_ensure(&tex->id)); /* paint overlays */ for (scene = bmain->scene.first; scene; scene = scene->id.next) @@ -372,7 +372,7 @@ static void texture_changed(Main *bmain, Tex *tex) if (!material_uses_texture(ma, tex)) continue; - BKE_icon_changed(BKE_icon_getid(&ma->id)); + BKE_icon_changed(BKE_icon_id_ensure(&ma->id)); if (ma->gpumaterial.first) GPU_material_free(&ma->gpumaterial); @@ -403,7 +403,7 @@ static void texture_changed(Main *bmain, Tex *tex) continue; } - BKE_icon_changed(BKE_icon_getid(&wo->id)); + BKE_icon_changed(BKE_icon_id_ensure(&wo->id)); if (wo->gpumaterial.first) GPU_material_free(&wo->gpumaterial); @@ -451,7 +451,7 @@ static void world_changed(Main *bmain, World *wo) Material *ma; /* icons */ - BKE_icon_changed(BKE_icon_getid(&wo->id)); + BKE_icon_changed(BKE_icon_id_ensure(&wo->id)); /* glsl */ for (ma = bmain->mat.first; ma; ma = ma->id.next) @@ -470,7 +470,7 @@ static void image_changed(Main *bmain, Image *ima) Tex *tex; /* icons */ - BKE_icon_changed(BKE_icon_getid(&ima->id)); + BKE_icon_changed(BKE_icon_id_ensure(&ima->id)); /* textures */ for (tex = bmain->tex.first; tex; tex = tex->id.next) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 75e6f77ba49..ddb1cec9180 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1346,7 +1346,7 @@ static int image_replace_exec(bContext *C, wmOperator *op) /* XXX unpackImage frees image buffers */ ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); - BKE_icon_changed(BKE_icon_getid(&sima->image->id)); + BKE_icon_changed(BKE_icon_id_ensure(&sima->image->id)); BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_RELOAD); WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image); diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h index f977a633c57..2cb56832a00 100644 --- a/source/blender/imbuf/IMB_thumbs.h +++ b/source/blender/imbuf/IMB_thumbs.h @@ -61,6 +61,8 @@ typedef enum ThumbSource { /* don't generate thumbs for images bigger then this (100mb) */ #define THUMB_SIZE_MAX (100 * 1024 * 1024) +#define PREVIEW_RENDER_DEFAULT_HEIGHT 128 + /* create thumbnail for file and returns new imbuf for thumbnail */ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, ImBuf *ibuf); diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index a608aa0db34..626f02e8ade 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -314,10 +314,10 @@ static ImBuf *thumb_create_ex( switch (size) { case THB_NORMAL: - tsize = 128; + tsize = PREVIEW_RENDER_DEFAULT_HEIGHT; break; case THB_LARGE: - tsize = 256; + tsize = PREVIEW_RENDER_DEFAULT_HEIGHT * 2; break; case THB_FAIL: tsize = 1; diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index b51b53cc801..f68de03614b 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -155,20 +155,36 @@ typedef struct Library { enum eIconSizes { ICON_SIZE_ICON = 0, - ICON_SIZE_PREVIEW = 1 + ICON_SIZE_PREVIEW = 1, + + NUM_ICON_SIZES +}; + +/* for PreviewImage->flag */ +enum ePreviewImage_Flag { + PRV_CHANGED = (1 << 0), + PRV_USER_EDITED = (1 << 1), /* if user-edited, do not auto-update this anymore! */ }; -#define NUM_ICON_SIZES (ICON_SIZE_PREVIEW + 1) typedef struct PreviewImage { /* All values of 2 are really NUM_ICON_SIZES */ unsigned int w[2]; unsigned int h[2]; - short changed[2]; + short flag[2]; short changed_timestamp[2]; unsigned int *rect[2]; + + /* Runtime-only data. */ struct GPUTexture *gputexture[2]; + int icon_id; /* Used by previews outside of ID context. */ + + char pad[3]; + char use_deferred; /* for now a mere bool, if we add more deferred loading methods we can switch to bitflag. */ } PreviewImage; +#define PRV_DEFERRED_DATA(prv) \ + (CHECK_TYPE_INLINE(prv, PreviewImage *), BLI_assert((prv)->use_deferred), (void *)((prv) + 1)) + /** * Defines for working with IDs. * diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index cff9e424f31..965d1d91614 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -280,6 +280,7 @@ extern StructRNA RNA_IKParam; extern StructRNA RNA_Image; extern StructRNA RNA_ImageFormatSettings; extern StructRNA RNA_ImagePaint; +extern StructRNA RNA_ImagePreview; extern StructRNA RNA_ImageSequence; extern StructRNA RNA_ImageTexture; extern StructRNA RNA_ImageUser; diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index db25786c599..b87b455b36f 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -34,6 +34,8 @@ #include "BLI_utildefines.h" +#include "BKE_icons.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -406,6 +408,183 @@ static void rna_Library_filepath_set(PointerRNA *ptr, const char *value) BKE_library_filepath_set(lib, value); } +/* ***** ImagePreview ***** */ + +static void rna_ImagePreview_is_custom_set(PointerRNA *ptr, int value, enum eIconSizes size) +{ + ID *id = ptr->id.data; + PreviewImage *prv_img = (PreviewImage *)ptr->data; + + if (id != NULL) { + BLI_assert(prv_img == BKE_previewimg_id_ensure(id)); + } + + if ((value && (prv_img->flag[size] & PRV_USER_EDITED)) || (!value && !(prv_img->flag[size] & PRV_USER_EDITED))) { + return; + } + + if (value) + prv_img->flag[size] |= PRV_USER_EDITED; + else + prv_img->flag[size] &= ~PRV_USER_EDITED; + + prv_img->flag[size] |= PRV_CHANGED; + + BKE_previewimg_clear_single(prv_img, size); +} + +static void rna_ImagePreview_size_get(PointerRNA *ptr, int *values, enum eIconSizes size) +{ + ID *id = (ID *)ptr->id.data; + PreviewImage *prv_img = (PreviewImage *)ptr->data; + + if (id != NULL) { + BLI_assert(prv_img == BKE_previewimg_id_ensure(id)); + } + + BKE_previewimg_ensure(prv_img, size); + + values[0] = prv_img->w[size]; + values[1] = prv_img->h[size]; +} + +static void rna_ImagePreview_size_set(PointerRNA *ptr, const int *values, enum eIconSizes size) +{ + ID *id = (ID *)ptr->id.data; + PreviewImage *prv_img = (PreviewImage *)ptr->data; + + if (id != NULL) { + BLI_assert(prv_img == BKE_previewimg_id_ensure(id)); + } + + BKE_previewimg_ensure(prv_img, size); + + if (values[0] && values[1]) { + prv_img->rect[size] = MEM_callocN(values[0] * values[1] * sizeof(unsigned int), "prv_rect"); + } + + prv_img->w[size] = values[0]; + prv_img->h[size] = values[1]; + + prv_img->flag[size] |= (PRV_CHANGED | PRV_USER_EDITED); +} + +static int rna_ImagePreview_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION], enum eIconSizes size) +{ + ID *id = ptr->id.data; + PreviewImage *prv_img = (PreviewImage *)ptr->data; + + if (id != NULL) { + BLI_assert(prv_img == BKE_previewimg_id_ensure(id)); + } + + BKE_previewimg_ensure(prv_img, size); + + length[0] = prv_img->w[size] * prv_img->h[size]; + + return length[0]; +} + +static void rna_ImagePreview_pixels_get(PointerRNA *ptr, int *values, enum eIconSizes size) +{ + ID *id = ptr->id.data; + PreviewImage *prv_img = (PreviewImage *)ptr->data; + + if (id != NULL) { + BLI_assert(prv_img == BKE_previewimg_id_ensure(id)); + } + + BKE_previewimg_ensure(prv_img, size); + + memcpy(values, prv_img->rect[size], prv_img->w[size] * prv_img->h[size] * sizeof(unsigned int)); +} + +static void rna_ImagePreview_pixels_set(PointerRNA *ptr, const int *values, enum eIconSizes size) +{ + ID *id = ptr->id.data; + PreviewImage *prv_img = (PreviewImage *)ptr->data; + + if (id != NULL) { + BLI_assert(prv_img == BKE_previewimg_id_ensure(id)); + } + + memcpy(prv_img->rect[size], values, prv_img->w[size] * prv_img->h[size] * sizeof(unsigned int)); + prv_img->flag[size] |= PRV_USER_EDITED; +} + +static void rna_ImagePreview_is_image_custom_set(PointerRNA *ptr, int value) +{ + rna_ImagePreview_is_custom_set(ptr, value, ICON_SIZE_PREVIEW); +} + +static void rna_ImagePreview_image_size_get(PointerRNA *ptr, int *values) +{ + rna_ImagePreview_size_get(ptr, values, ICON_SIZE_PREVIEW); +} + +static void rna_ImagePreview_image_size_set(PointerRNA *ptr, const int *values) +{ + rna_ImagePreview_size_set(ptr, values, ICON_SIZE_PREVIEW); +} + +static int rna_ImagePreview_image_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) +{ + return rna_ImagePreview_pixels_get_length(ptr, length, ICON_SIZE_PREVIEW); +} + +static void rna_ImagePreview_image_pixels_get(PointerRNA *ptr, int *values) +{ + rna_ImagePreview_pixels_get(ptr, values, ICON_SIZE_PREVIEW); +} + +static void rna_ImagePreview_image_pixels_set(PointerRNA *ptr, const int *values) +{ + rna_ImagePreview_pixels_set(ptr, values, ICON_SIZE_PREVIEW); +} + +static void rna_ImagePreview_is_icon_custom_set(PointerRNA *ptr, int value) +{ + rna_ImagePreview_is_custom_set(ptr, value, ICON_SIZE_ICON); +} + +static void rna_ImagePreview_icon_size_get(PointerRNA *ptr, int *values) +{ + rna_ImagePreview_size_get(ptr, values, ICON_SIZE_ICON); +} + +static void rna_ImagePreview_icon_size_set(PointerRNA *ptr, const int *values) +{ + rna_ImagePreview_size_set(ptr, values, ICON_SIZE_ICON); +} + +static int rna_ImagePreview_icon_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) +{ + return rna_ImagePreview_pixels_get_length(ptr, length, ICON_SIZE_ICON); +} + +static void rna_ImagePreview_icon_pixels_get(PointerRNA *ptr, int *values) +{ + rna_ImagePreview_pixels_get(ptr, values, ICON_SIZE_ICON); +} + +static void rna_ImagePreview_icon_pixels_set(PointerRNA *ptr, const int *values) +{ + rna_ImagePreview_pixels_set(ptr, values, ICON_SIZE_ICON); +} + +static int rna_ImagePreview_icon_id_get(PointerRNA *ptr) +{ + /* Using a callback here allows us to only generate icon matching that preview when icon_id is requested. */ + return BKE_icon_preview_ensure((PreviewImage *)(ptr->data)); +} +static void rna_ImagePreview_icon_reload(PreviewImage *prv) +{ + /* will lazy load on next use, but only in case icon is not user-modified! */ + if (!(prv->flag[ICON_SIZE_ICON] & PRV_USER_EDITED) && !(prv->flag[ICON_SIZE_PREVIEW] & PRV_USER_EDITED)) { + BKE_previewimg_clear(prv); + } +} + #else static void rna_def_ID_properties(BlenderRNA *brna) @@ -524,6 +703,62 @@ static void rna_def_ID_materials(BlenderRNA *brna) RNA_def_boolean(func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned"); } +static void rna_def_image_preview(BlenderRNA *brna) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "ImagePreview", NULL); + RNA_def_struct_sdna(srna, "PreviewImage"); + RNA_def_struct_ui_text(srna, "Image Preview", "Preview image and icon"); + + prop = RNA_def_property(srna, "is_image_custom", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag[ICON_SIZE_PREVIEW]", PRV_USER_EDITED); + RNA_def_property_boolean_funcs(prop, NULL, "rna_ImagePreview_is_image_custom_set"); + RNA_def_property_ui_text(prop, "Custom Image", "True if this preview image has been modified by py script," + "and is no more auto-generated by Blender"); + + prop = RNA_def_int_vector(srna, "image_size", 2, NULL, 0, 0, "Image Size", + "Width and height in pixels", 0, 0); + RNA_def_property_subtype(prop, PROP_PIXEL); + RNA_def_property_int_funcs(prop, "rna_ImagePreview_image_size_get", "rna_ImagePreview_image_size_set", NULL); + + prop = RNA_def_property(srna, "image_pixels", PROP_INT, PROP_NONE); + RNA_def_property_flag(prop, PROP_DYNAMIC); + RNA_def_property_multi_array(prop, 1, NULL); + RNA_def_property_ui_text(prop, "Image Pixels", "Image pixels, as bytes (always RGBA 32bits)"); + RNA_def_property_dynamic_array_funcs(prop, "rna_ImagePreview_image_pixels_get_length"); + RNA_def_property_int_funcs(prop, "rna_ImagePreview_image_pixels_get", "rna_ImagePreview_image_pixels_set", NULL); + + + prop = RNA_def_property(srna, "is_icon_custom", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag[ICON_SIZE_ICON]", PRV_USER_EDITED); + RNA_def_property_boolean_funcs(prop, NULL, "rna_ImagePreview_is_icon_custom_set"); + RNA_def_property_ui_text(prop, "Custom Icon", "True if this preview icon has been modified by py script," + "and is no more auto-generated by Blender"); + + prop = RNA_def_int_vector(srna, "icon_size", 2, NULL, 0, 0, "Icon Size", + "Width and height in pixels", 0, 0); + RNA_def_property_subtype(prop, PROP_PIXEL); + RNA_def_property_int_funcs(prop, "rna_ImagePreview_icon_size_get", "rna_ImagePreview_icon_size_set", NULL); + + prop = RNA_def_property(srna, "icon_pixels", PROP_INT, PROP_NONE); + RNA_def_property_flag(prop, PROP_DYNAMIC); + RNA_def_property_multi_array(prop, 1, NULL); + RNA_def_property_ui_text(prop, "Icon Pixels", "Icon pixels, as bytes (always RGBA 32bits)"); + RNA_def_property_dynamic_array_funcs(prop, "rna_ImagePreview_icon_pixels_get_length"); + RNA_def_property_int_funcs(prop, "rna_ImagePreview_icon_pixels_get", "rna_ImagePreview_icon_pixels_set", NULL); + + prop = RNA_def_int(srna, "icon_id", 0, INT_MIN, INT_MAX, "Icon ID", + "Unique integer identifying this preview as an icon (zero means invalid)", INT_MIN, INT_MAX); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_int_funcs(prop, "rna_ImagePreview_icon_id_get", NULL, NULL); + + func = RNA_def_function(srna, "reload", "rna_ImagePreview_icon_reload"); + RNA_def_function_ui_description(func, "Reload the preview from its source path"); +} + static void rna_def_ID(BlenderRNA *brna) { StructRNA *srna; @@ -651,6 +886,7 @@ void RNA_def_ID(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Any Type", "RNA type used for pointers to any possible data"); rna_def_ID(brna); + rna_def_image_preview(brna); rna_def_ID_properties(brna); rna_def_ID_materials(brna); rna_def_library(brna); diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 362cf77a332..e9e4282772d 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -342,8 +342,8 @@ static void rna_Brush_reset_icon(Brush *br, const char *UNUSED(type)) return; if (id->icon_id >= BIFICONID_LAST) { - BKE_icon_delete(id); - BKE_previewimg_free_id(id); + BKE_icon_id_delete(id); + BKE_previewimg_id_free(id); } id->icon_id = 0; @@ -415,8 +415,8 @@ static void rna_Brush_icon_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi br->id.icon_id = 0; if (br->flag & BRUSH_CUSTOM_ICON) { - BKE_previewimg_get(&br->id); - BKE_icon_changed(BKE_icon_getid(&br->id)); + BKE_previewimg_id_ensure(&br->id); + BKE_icon_changed(BKE_icon_id_ensure(&br->id)); } WM_main_add_notifier(NC_BRUSH | NA_EDITED, br); diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 168f23ceaa1..8b5ed66e217 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -35,6 +35,7 @@ #include "DNA_ID.h" #include "DNA_modifier_types.h" +#include "DNA_space_types.h" #include "BLI_utildefines.h" #include "BLI_path_util.h" @@ -58,6 +59,7 @@ #include "BKE_library.h" #include "BKE_object.h" #include "BKE_material.h" +#include "BKE_icons.h" #include "BKE_image.h" #include "BKE_texture.h" #include "BKE_scene.h" @@ -807,11 +809,12 @@ static int rna_Main_linestyle_is_updated_get(PointerRNA *ptr) { return DAG_id_ty #else -void RNA_api_main(StructRNA *srna) +void RNA_api_main(StructRNA *UNUSED(srna)) { #if 0 FunctionRNA *func; PropertyRNA *parm; + /* maybe we want to add functions in 'bpy.data' still? * for now they are all in collections bpy.data.images.new(...) */ func = RNA_def_function(srna, "add_image", "rna_Main_add_image"); @@ -820,8 +823,6 @@ void RNA_api_main(StructRNA *srna) RNA_def_property_flag(parm, PROP_REQUIRED); parm = RNA_def_pointer(func, "image", "Image", "", "New image"); RNA_def_function_return(func, parm); -#else - (void)srna; #endif } diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 8296027f044..ed04152182e 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -31,6 +31,7 @@ set(INC ../../blenloader ../../editors/include ../../gpu + ../../imbuf ../../makesdna ../../makesrna ../../windowmanager @@ -69,6 +70,7 @@ set(SRC bpy_rna_callback.c bpy_traceback.c bpy_util.c + bpy_utils_previews.c bpy_utils_units.c stubs.c @@ -94,6 +96,7 @@ set(SRC bpy_rna_callback.h bpy_traceback.h bpy_util.h + bpy_utils_previews.h bpy_utils_units.h ../BPY_extern.h ) diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index ec3c017a7ed..9a5e488850e 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -48,6 +48,7 @@ #include "bpy_props.h" #include "bpy_library.h" #include "bpy_operator.h" +#include "bpy_utils_previews.h" #include "bpy_utils_units.h" #include "../generic/py_capi_utils.h" @@ -330,6 +331,7 @@ void BPy_init_modules(void) PyModule_AddObject(mod, "ops", BPY_operator_module()); PyModule_AddObject(mod, "app", BPY_app_struct()); PyModule_AddObject(mod, "_utils_units", BPY_utils_units()); + PyModule_AddObject(mod, "_utils_previews", BPY_utils_previews_module()); /* bpy context */ RNA_pointer_create(NULL, &RNA_Context, (void *)BPy_GetContext(), &ctx_ptr); diff --git a/source/blender/python/intern/bpy_utils_previews.c b/source/blender/python/intern/bpy_utils_previews.c new file mode 100644 index 00000000000..5509ff50f5f --- /dev/null +++ b/source/blender/python/intern/bpy_utils_previews.c @@ -0,0 +1,188 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Bastien Montagne + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/intern/bpy_utils_previews.c + * \ingroup pythonintern + * + * This file defines a singleton py object accessed via 'bpy.utils.previews', + * which exposes low-level API for custom previews/icons. + * It is replaced in final API by an higher-level python wrapper, that handles previews by addon, + * and automatically release them on deletion. + */ + +#include +#include + +#include "BLI_utildefines.h" + +#include "RNA_types.h" +#include "RNA_access.h" + +#include "BPY_extern.h" +#include "bpy_utils_previews.h" +#include "bpy_rna.h" + +#include "MEM_guardedalloc.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" +#include "IMB_thumbs.h" + +#include "BKE_icons.h" + +#include "DNA_ID.h" + +#include "../generic/python_utildefines.h" + +#define STR_SOURCE_TYPES "'IMAGE', 'MOVIE', 'BLEND', 'FONT'" + +PyDoc_STRVAR(bpy_utils_previews_new_doc, +".. method:: new(name)\n" +"\n" +" Generate a new empty preview, or return existing one matching ``name``.\n" +"\n" +" :arg name: The name (unique id) identifying the preview.\n" +" :type name: string\n" +" :return: The Preview matching given name, or a new empty one.\n" +" :rtype: :class:`bpy.types.ImagePreview`\n" +); +static PyObject *bpy_utils_previews_new(PyObject *UNUSED(self), PyObject *args) +{ + char *name; + PreviewImage *prv; + PointerRNA ptr; + + if (!PyArg_ParseTuple(args, "s:new", &name)) { + return NULL; + } + + prv = BKE_previewimg_cached_ensure(name); + RNA_pointer_create(NULL, &RNA_ImagePreview, prv, &ptr); + + return pyrna_struct_CreatePyObject(&ptr); +} + +PyDoc_STRVAR(bpy_utils_previews_load_doc, +".. method:: load(name, path, path_type, force_reload)\n" +"\n" +" Generate a new preview from given file path, or return existing one matching ``name``.\n" +"\n" +" :arg name: The name (unique id) identifying the preview.\n" +" :type name: string\n" +" :arg path: The file path to generate the preview from.\n" +" :type path: string\n" +" :arg path_type: The type of file, needed to generate the preview in [" STR_SOURCE_TYPES "].\n" +" :type path_type: string\n" +" :arg force_reload: If True, force running thumbnail manager even if preview already exists in cache.\n" +" :type force_reload: bool\n" +" :return: The Preview matching given name, or a new empty one.\n" +" :rtype: :class:`bpy.types.ImagePreview`\n" +); +static PyObject *bpy_utils_previews_load(PyObject *UNUSED(self), PyObject *args) +{ + char *name, *path, *path_type_s; + int path_type, force_reload = false; + + PreviewImage *prv; + PointerRNA ptr; + + if (!PyArg_ParseTuple( args, "sss|p:load", &name, &path, &path_type_s, &force_reload)) { + return NULL; + } + + if (STREQ(path_type_s, "IMAGE")) { + path_type = THB_SOURCE_IMAGE; + } + else if (STREQ(path_type_s, "MOVIE")) { + path_type = THB_SOURCE_MOVIE; + } + else if (STREQ(path_type_s, "BLEND")) { + path_type = THB_SOURCE_BLEND; + } + else if (STREQ(path_type_s, "FONT")) { + path_type = THB_SOURCE_FONT; + } + else { + PyErr_Format(PyExc_ValueError, + "load: invalid '%' path type, only [" STR_SOURCE_TYPES "] " + "are supported", path_type_s); + return NULL; + } + + prv = BKE_previewimg_cached_thumbnail_read(name, path, path_type, force_reload); + RNA_pointer_create(NULL, &RNA_ImagePreview, prv, &ptr); + + return pyrna_struct_CreatePyObject(&ptr); +} + +PyDoc_STRVAR(bpy_utils_previews_release_doc, +".. method:: release(name)\n" +"\n" +" Release (free) a previously created preview.\n" +"\n" +"\n" +" :arg name: The name (unique id) identifying the preview.\n" +" :type name: string\n" +); +static PyObject *bpy_utils_previews_release(PyObject *UNUSED(self), PyObject *args) +{ + char *name; + + if (!PyArg_ParseTuple(args, "s:release", &name)) { + return NULL; + } + + BKE_previewimg_cached_release(name); + + Py_RETURN_NONE; +} + +static struct PyMethodDef bpy_utils_previews_methods[] = { + /* Can't use METH_KEYWORDS alone, see http://bugs.python.org/issue11587 */ + {"new", (PyCFunction)bpy_utils_previews_new, METH_VARARGS, bpy_utils_previews_new_doc}, + {"load", (PyCFunction)bpy_utils_previews_load, METH_VARARGS, bpy_utils_previews_load_doc}, + {"release", (PyCFunction)bpy_utils_previews_release, METH_VARARGS, bpy_utils_previews_release_doc}, + {NULL, NULL, 0, NULL} +}; + +PyDoc_STRVAR(bpy_utils_previews_doc, +"This object contains basic static methods to handle cached (non-ID) previews in Blender\n" +"(low-level API, not exposed to final users)." +); +static struct PyModuleDef bpy_utils_previews_module = { + PyModuleDef_HEAD_INIT, + "bpy._utils_previews", + bpy_utils_previews_doc, + 0, + bpy_utils_previews_methods, + NULL, NULL, NULL, NULL +}; + + +PyObject *BPY_utils_previews_module(void) +{ + PyObject *submodule; + + submodule = PyModule_Create(&bpy_utils_previews_module); + + return submodule; +} diff --git a/source/blender/python/intern/bpy_utils_previews.h b/source/blender/python/intern/bpy_utils_previews.h new file mode 100644 index 00000000000..3d7ade04b9f --- /dev/null +++ b/source/blender/python/intern/bpy_utils_previews.h @@ -0,0 +1,32 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Bastien Montagne + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/intern/bpy_utils_previews.h + * \ingroup pythonintern + */ + +#ifndef __BPY_UTILS_PREVIEWS_H__ +#define __BPY_UTILS_PREVIEWS_H__ + +PyObject *BPY_utils_previews_module(void); + +#endif /* __BPY_UTILS_PREVIEWS_H__ */ diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index b5c267e8a39..77d3e3762a8 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -172,6 +172,17 @@ void WM_init(bContext *C, int argc, const char **argv) BLF_lang_set(NULL); + if (!G.background) { + GPU_init(); + + GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); + GPU_set_linear_mipmap(true); + GPU_set_anisotropic(U.anisotropic_filter); + GPU_set_gpu_mipmapping(U.use_gpu_mipmap); + + UI_init(); + } + ED_spacemacros_init(); /* note: there is a bug where python needs initializing before loading the @@ -197,17 +208,6 @@ void WM_init(bContext *C, int argc, const char **argv) wm_init_reports(C); /* reports cant be initialized before the wm */ - if (!G.background) { - GPU_init(); - - GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); - GPU_set_linear_mipmap(true); - GPU_set_anisotropic(U.anisotropic_filter); - GPU_set_gpu_mipmapping(U.use_gpu_mipmap); - - UI_init(); - } - clear_matcopybuf(); ED_render_clear_mtex_copybuf(); -- cgit v1.2.3 From 4fc31881127786f244bc67ad45b3787c6d7917a2 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 11 May 2015 16:40:38 +0200 Subject: Cycles: Get rid of one more OpenGL matrix manipulation/push/pop. --- intern/cycles/device/device.cpp | 10 +++++----- intern/cycles/device/device.h | 2 +- intern/cycles/device/device_cuda.cpp | 12 ++++++------ intern/cycles/device/device_multi.cpp | 4 ++-- intern/cycles/render/buffers.cpp | 6 +----- 5 files changed, 15 insertions(+), 19 deletions(-) diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index b34e0646384..a9e4284f35f 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -58,7 +58,7 @@ void Device::pixels_free(device_memory& mem) mem_free(mem); } -void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int width, int height, bool transparent, +void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dx, int dy, int width, int height, bool transparent, const DeviceDrawParams &draw_params) { pixels_copy_from(rgba, y, w, h); @@ -114,22 +114,22 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w /* texture coordinate - vertex pair */ vp[0] = 0.0f; vp[1] = 0.0f; - vp[2] = 0.0f; + vp[2] = dx; vp[3] = dy; vp[4] = 1.0f; vp[5] = 0.0f; - vp[6] = (float)width; + vp[6] = (float)width + dx; vp[7] = dy; vp[8] = 1.0f; vp[9] = 1.0f; - vp[10] = (float)width; + vp[10] = (float)width + dx; vp[11] = (float)height + dy; vp[12] = 0.0f; vp[13] = 1.0f; - vp[14] = 0.0f; + vp[14] = dx; vp[15] = (float)height + dy; if (vertex_buffer) diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index b32f7b406c7..8ac3df1797c 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -181,7 +181,7 @@ public: /* opengl drawing */ virtual void draw_pixels(device_memory& mem, int y, int w, int h, - int dy, int width, int height, bool transparent, + int dx, int dy, int width, int height, bool transparent, const DeviceDrawParams &draw_params); #ifdef WITH_NETWORK diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index be6a1f3502d..4b325947f0f 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -880,7 +880,7 @@ public: } } - void draw_pixels(device_memory& mem, int y, int w, int h, int dy, int width, int height, bool transparent, + void draw_pixels(device_memory& mem, int y, int w, int h, int dx, int dy, int width, int height, bool transparent, const DeviceDrawParams &draw_params) { if(!background) { @@ -932,22 +932,22 @@ public: /* texture coordinate - vertex pair */ vpointer[0] = 0.0f; vpointer[1] = 0.0f; - vpointer[2] = 0.0f; + vpointer[2] = dx; vpointer[3] = dy; vpointer[4] = (float)w/(float)pmem.w; vpointer[5] = 0.0f; - vpointer[6] = (float)width; + vpointer[6] = (float)width + dx; vpointer[7] = dy; vpointer[8] = (float)w/(float)pmem.w; vpointer[9] = (float)h/(float)pmem.h; - vpointer[10] = (float)width; + vpointer[10] = (float)width + dx; vpointer[11] = (float)height + dy; vpointer[12] = 0.0f; vpointer[13] = (float)h/(float)pmem.h; - vpointer[14] = 0.0f; + vpointer[14] = dx; vpointer[15] = (float)height + dy; glUnmapBuffer(GL_ARRAY_BUFFER); @@ -981,7 +981,7 @@ public: return; } - Device::draw_pixels(mem, y, w, h, dy, width, height, transparent, draw_params); + Device::draw_pixels(mem, y, w, h, dx, dy, width, height, transparent, draw_params); } void thread_run(DeviceTask *task) diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp index c0a1516f2de..c61e550151f 100644 --- a/intern/cycles/device/device_multi.cpp +++ b/intern/cycles/device/device_multi.cpp @@ -236,7 +236,7 @@ public: mem.device_pointer = tmp; } - void draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int width, int height, bool transparent, + void draw_pixels(device_memory& rgba, int y, int w, int h, int dx, int dy, int width, int height, bool transparent, const DeviceDrawParams &draw_params) { device_ptr tmp = rgba.device_pointer; @@ -251,7 +251,7 @@ public: /* adjust math for w/width */ rgba.device_pointer = sub.ptr_map[tmp]; - sub.device->draw_pixels(rgba, sy, w, sh, sdy, width, sheight, transparent, draw_params); + sub.device->draw_pixels(rgba, sy, w, sh, dx, sdy, width, sheight, transparent, draw_params); i++; } diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index dc00da1bf88..011c722c000 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -369,13 +369,9 @@ void DisplayBuffer::draw_set(int width, int height) void DisplayBuffer::draw(Device *device, const DeviceDrawParams& draw_params) { if(draw_width != 0 && draw_height != 0) { - glPushMatrix(); - glTranslatef(params.full_x, params.full_y, 0.0f); device_memory& rgba = rgba_data(); - device->draw_pixels(rgba, 0, draw_width, draw_height, 0, params.width, params.height, transparent, draw_params); - - glPopMatrix(); + device->draw_pixels(rgba, 0, draw_width, draw_height, params.full_x, params.full_y, params.width, params.height, transparent, draw_params); } } -- cgit v1.2.3 From 2c4736e6db50ad74d591aa39b922c3d923cc1cfe Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 11 May 2015 17:12:31 +0200 Subject: Clearing preview image shall also unset 'user edited' flag! --- source/blender/blenkernel/intern/icons.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index 450c1388f37..daf39116d76 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -189,6 +189,7 @@ void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size) } prv->h[size] = prv->w[size] = 0; prv->flag[size] |= PRV_CHANGED; + prv->flag[size] &= ~PRV_USER_EDITED; prv->changed_timestamp[size] = 0; } -- cgit v1.2.3 From 1bf685488cf2990da656bd2a2eeea0088f99a4bf Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 11 May 2015 17:22:18 +0200 Subject: Collada Exporter: sanitize a bit lnor export. In case `BKE_mesh_calc_normals_split()` would fail, exporter would read uninitialized random mem... Should not happen, but better be safe than sorry. --- source/blender/collada/GeometryExporter.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index b29b4c9c484..a0eddadfe78 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -606,7 +606,7 @@ void GeometryExporter::create_normals(std::vector &normals, std::vector< MVert *verts = me->mvert; MLoop *mloops = me->mloop; - float(*lnors)[3]; + float(*lnors)[3] = NULL; bool use_custom_normals = false; BKE_mesh_calc_normals_split(me); @@ -630,14 +630,19 @@ void GeometryExporter::create_normals(std::vector &normals, std::vector< last_normal_index++; } - MLoop *mloop = mloops + mpoly->loopstart; BCPolygonNormalsIndices poly_indices; for (int loop_index = 0; loop_index < mpoly->totloop; loop_index++) { unsigned int loop_idx = mpoly->loopstart + loop_index; if (use_vertex_normals) { - float normalized[3]; - normalize_v3_v3(normalized, lnors[loop_idx]); + + if (use_custom_normals) { + normalize_v3_v3(normalized, lnors[loop_idx]); + } + else { + normal_short_to_float_v3(normalized, verts[mloops[loop_index].v].no); + normalize_v3(normalized); + } Normal n = { normalized[0], normalized[1], normalized[2] }; if (shared_normal_indices.find(n) != shared_normal_indices.end()) { -- cgit v1.2.3 From c7bccb30bf03a0ac4d6d135f94658c93be7b7b0f Mon Sep 17 00:00:00 2001 From: "Sv. Lockal" Date: Mon, 11 May 2015 15:49:36 +0000 Subject: Cycles: check for F16C support with __cpuid, as we do for BMI and BMI2 --- intern/cycles/util/util_system.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/intern/cycles/util/util_system.cpp b/intern/cycles/util/util_system.cpp index 7206455debd..4a88ef6de76 100644 --- a/intern/cycles/util/util_system.cpp +++ b/intern/cycles/util/util_system.cpp @@ -127,6 +127,7 @@ struct CPUCapabilities { bool sse42; bool sse4a; bool avx; + bool f16c; bool avx2; bool xop; bool fma3; @@ -202,6 +203,8 @@ static CPUCapabilities& system_cpu_capabilities() caps.avx = (xcr_feature_mask & 0x6) == 0x6; } + caps.f16c = (result[2] & ((int)1 << 29)) != 0; + __cpuid(result, 0x00000007); caps.bmi1 = (result[1] & ((int)1 << 3)) != 0; caps.bmi2 = (result[1] & ((int)1 << 8)) != 0; @@ -242,7 +245,7 @@ bool system_cpu_support_avx() bool system_cpu_support_avx2() { CPUCapabilities& caps = system_cpu_capabilities(); - return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3 && caps.sse41 && caps.avx && caps.avx2 && caps.fma3 && caps.bmi1 && caps.bmi2; + return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3 && caps.sse41 && caps.avx && caps.f16c && caps.avx2 && caps.fma3 && caps.bmi1 && caps.bmi2; } #else -- cgit v1.2.3 From ce504cffad49da80aff5b18d0f59d42998e3a9f7 Mon Sep 17 00:00:00 2001 From: Tamito Kajiyama Date: Mon, 11 May 2015 16:53:11 +0900 Subject: Freestyle: Fix for assertion failure in viewport preview. An assertion to check if `re->clipsta` < 0 (added as part of addressing T36009 in rBrB795034c17d76bef2a15e576ac9c70ae2268a823b) was failing when Freestyle viewport preview rendering takes place in the camera view with an orthographic camera (in this case, the user-defined clipping range is used without changes, so that `re->clipsta` is positive). The `re->clipsta` property has a negative value only when the 3D viewport is in an orthographic view but not in the camera view. It seems that this viewport setting cannot be identified from rendering settings accessible from Freestyle. Now a negative `re->clipsta` value is directly checked instead, without relying on other render flags. --- .../blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index f5f76516d38..bcb38bc5971 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -64,12 +64,11 @@ NodeGroup *BlenderFileLoader::Load() _viewplane_bottom = _re->viewplane.ymin; _viewplane_top = _re->viewplane.ymax; - if ((_re->r.scemode & R_VIEWPORT_PREVIEW) && (_re->r.mode & R_ORTHO)) { + if (_re->clipsta < 0.f) { // Adjust clipping start/end and set up a Z offset when the viewport preview // is used with the orthographic view. In this case, _re->clipsta is negative, // while Freestyle assumes that imported mesh data are in the camera coordinate // system with the view point located at origin [bug #36009]. - BLI_assert(_re->clipsta < 0.f); _z_near = -0.001f; _z_offset = _re->clipsta + _z_near; _z_far = -_re->clipend + _z_offset; -- cgit v1.2.3 From 8478c71a7b8f75dcf4855747347ba53639e6aac3 Mon Sep 17 00:00:00 2001 From: Mitchell Stokes Date: Mon, 11 May 2015 23:05:04 -0700 Subject: BGE: Adding material IPO support to GLSL materials Most of this patch was created by Daniel Stokes, I'm mostly just cleaning it up and testing it. Still todo: hardness. I need to figure out how to handle the integer -> float conversion on a dynamic uniform. Reviewers: psy-fi, brecht Reviewed By: psy-fi Subscribers: psy-fi Differential Revision: https://developer.blender.org/D511 --- source/blender/gpu/GPU_material.h | 8 ++++ source/blender/gpu/intern/gpu_codegen.c | 17 +++++-- source/blender/gpu/intern/gpu_material.c | 17 ++++--- source/gameengine/Ketsji/KX_BlenderMaterial.cpp | 53 +++++++++++++++++----- source/gameengine/Ketsji/KX_BlenderMaterial.h | 9 ++++ source/gameengine/Ketsji/KX_IpoConvert.cpp | 4 +- .../gameengine/Ketsji/KX_MaterialIpoController.cpp | 15 ------ 7 files changed, 82 insertions(+), 41 deletions(-) diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 7bb044a1ae3..1fb2518c07c 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -154,6 +154,14 @@ typedef enum GPUDynamicType { GPU_DYNAMIC_MIST_COLOR = 26, GPU_DYNAMIC_HORIZON_COLOR = 27, GPU_DYNAMIC_AMBIENT_COLOR = 28, + GPU_DYNAMIC_MAT_DIFFRGB = 29, + GPU_DYNAMIC_MAT_REF = 30, + GPU_DYNAMIC_MAT_SPECRGB = 31, + GPU_DYNAMIC_MAT_SPEC = 32, + GPU_DYNAMIC_MAT_HARD = 33, + GPU_DYNAMIC_MAT_EMIT = 34, + GPU_DYNAMIC_MAT_AMB = 35, + GPU_DYNAMIC_MAT_ALPHA = 36, } GPUDynamicType; GPUNodeLink *GPU_attribute(CustomDataType type, const char *name); diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index e9bc4002032..e92b58932a3 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -852,10 +852,19 @@ void GPU_pass_update_uniforms(GPUPass *pass) return; /* pass dynamic inputs to opengl, others were removed */ - for (input = inputs->first; input; input = input->next) - if (!(input->ima || input->tex || input->prv)) - GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1, - input->dynamicvec); + for (input = inputs->first; input; input = input->next) { + if (!(input->ima || input->tex || input->prv)) { + if (input->dynamictype == GPU_DYNAMIC_MAT_HARD) { + // The hardness is actually a short pointer, so we convert it here + float val = (float)(*(short*)input->dynamicvec); + GPU_shader_uniform_vector(shader, input->shaderloc, 1, 1, &val); + } + else { + GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1, + input->dynamicvec); + } + } + } } void GPU_pass_unbind(GPUPass *pass) diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 12672b5f5af..774dee9ebc2 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1449,7 +1449,6 @@ static void do_material_tex(GPUShadeInput *shi) void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi) { - float hard = ma->har; float one = 1.0f; memset(shi, 0, sizeof(*shi)); @@ -1457,20 +1456,20 @@ void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi) shi->gpumat = mat; shi->mat = ma; - GPU_link(mat, "set_rgb", GPU_uniform(&ma->r), &shi->rgb); - GPU_link(mat, "set_rgb", GPU_uniform(&ma->specr), &shi->specrgb); + GPU_link(mat, "set_rgb", GPU_dynamic_uniform(&ma->r, GPU_DYNAMIC_MAT_DIFFRGB, NULL), &shi->rgb); + GPU_link(mat, "set_rgb", GPU_dynamic_uniform(&ma->specr, GPU_DYNAMIC_MAT_SPECRGB, NULL), &shi->specrgb); GPU_link(mat, "shade_norm", GPU_builtin(GPU_VIEW_NORMAL), &shi->vn); if (mat->alpha) - GPU_link(mat, "set_value", GPU_uniform(&ma->alpha), &shi->alpha); + GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->alpha, GPU_DYNAMIC_MAT_ALPHA, NULL), &shi->alpha); else GPU_link(mat, "set_value", GPU_uniform(&one), &shi->alpha); - GPU_link(mat, "set_value", GPU_uniform(&ma->ref), &shi->refl); - GPU_link(mat, "set_value", GPU_uniform(&ma->spec), &shi->spec); - GPU_link(mat, "set_value", GPU_uniform(&ma->emit), &shi->emit); - GPU_link(mat, "set_value", GPU_uniform(&hard), &shi->har); - GPU_link(mat, "set_value", GPU_uniform(&ma->amb), &shi->amb); + GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->ref, GPU_DYNAMIC_MAT_REF, NULL), &shi->refl); + GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->spec, GPU_DYNAMIC_MAT_SPEC, NULL), &shi->spec); + GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->emit, GPU_DYNAMIC_MAT_EMIT, NULL), &shi->emit); + GPU_link(mat, "set_value", GPU_dynamic_uniform((float*)&ma->har, GPU_DYNAMIC_MAT_HARD, NULL), &shi->har); + GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->amb, GPU_DYNAMIC_MAT_AMB, NULL), &shi->amb); GPU_link(mat, "set_value", GPU_uniform(&ma->spectra), &shi->spectra); GPU_link(mat, "shade_view", GPU_builtin(GPU_VIEW_POSITION), &shi->view); GPU_link(mat, "vcol_attribute", GPU_attribute(CD_MCOL, ""), &shi->vcol); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 9f0b582045f..7ec2673bf1f 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -94,6 +94,21 @@ void KX_BlenderMaterial::Initialize( ((data->ras_mode &TEX)), game ); + Material *ma = data->material; + + // Save material data to restore on exit + mSavedData.r = ma->r; + mSavedData.g = ma->g; + mSavedData.b = ma->b; + mSavedData.a = ma->alpha; + mSavedData.specr = ma->specr; + mSavedData.specg = ma->specg; + mSavedData.specb = ma->specb; + mSavedData.spec = ma->spec; + mSavedData.ref = ma->ref; + mSavedData.hardness = ma->har; + mSavedData.emit = ma->emit; + mMaterial = data; mShader = 0; mBlenderShader = 0; @@ -124,6 +139,20 @@ void KX_BlenderMaterial::Initialize( KX_BlenderMaterial::~KX_BlenderMaterial() { + Material *ma = mMaterial->material; + // Restore Blender material data + ma->r = mSavedData.r; + ma->g = mSavedData.g; + ma->b = mSavedData.b; + ma->alpha = mSavedData.a; + ma->specr = mSavedData.specr; + ma->specg = mSavedData.specg; + ma->specb = mSavedData.specb; + ma->spec = mSavedData.spec; + ma->ref = mSavedData.ref; + ma->har = mSavedData.hardness; + ma->emit = mSavedData.emit; + // cleanup work if (mConstructed) // clean only if material was actually used @@ -793,17 +822,19 @@ void KX_BlenderMaterial::UpdateIPO( ) { // only works one deep now - mMaterial->speccolor[0] = (float)(specrgb)[0]; - mMaterial->speccolor[1] = (float)(specrgb)[1]; - mMaterial->speccolor[2] = (float)(specrgb)[2]; - mMaterial->matcolor[0] = (float)(rgba[0]); - mMaterial->matcolor[1] = (float)(rgba[1]); - mMaterial->matcolor[2] = (float)(rgba[2]); - mMaterial->alpha = (float)(alpha); - mMaterial->hard = (float)(hard); - mMaterial->emit = (float)(emit); - mMaterial->spec_f = (float)(spec); - mMaterial->ref = (float)(ref); + + // GLSL Multitexture Input + mMaterial->material->specr = mMaterial->speccolor[0] = (float)(specrgb)[0]; + mMaterial->material->specg = mMaterial->speccolor[1] = (float)(specrgb)[1]; + mMaterial->material->specb = mMaterial->speccolor[2] = (float)(specrgb)[2]; + mMaterial->material->r = mMaterial->matcolor[0] = (float)(rgba[0]); + mMaterial->material->g = mMaterial->matcolor[1] = (float)(rgba[1]); + mMaterial->material->b = mMaterial->matcolor[2] = (float)(rgba[2]); + mMaterial->material->alpha = mMaterial->alpha = (float)(rgba[3]); + mMaterial->material->har = mMaterial->hard = (float)(hard); + mMaterial->material->emit = mMaterial->emit = (float)(emit); + mMaterial->material->spec = mMaterial->spec_f = (float)(spec); + mMaterial->material->ref = mMaterial->ref = (float)(ref); } void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val) diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index b7c64215eaf..23921588d6a 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -134,6 +134,15 @@ private: bool mConstructed; // if false, don't clean on exit int mLightLayer; + struct { + float r, g, b, a; + float specr, specg, specb; + float spec; + float ref; + float hardness; + float emit; + } mSavedData; + void InitTextures(); void SetBlenderGLSLShader(); diff --git a/source/gameengine/Ketsji/KX_IpoConvert.cpp b/source/gameengine/Ketsji/KX_IpoConvert.cpp index 441c16176aa..7b00760ee7b 100644 --- a/source/gameengine/Ketsji/KX_IpoConvert.cpp +++ b/source/gameengine/Ketsji/KX_IpoConvert.cpp @@ -396,7 +396,7 @@ SG_Controller *BL_CreateMaterialIpo( ipocontr->AddInterpolator(interpolator); } - if ((sinterp = adtList->GetScalarInterpolator("specularity", 0))) { + if ((sinterp = adtList->GetScalarInterpolator("specular_intensity", 0))) { if (!ipocontr) { ipocontr = new KX_MaterialIpoController(matname_hash); } @@ -404,7 +404,7 @@ SG_Controller *BL_CreateMaterialIpo( ipocontr->AddInterpolator(interpolator); } - if ((sinterp = adtList->GetScalarInterpolator("diffuse_reflection", 0))) { + if ((sinterp = adtList->GetScalarInterpolator("diffuse_intensity", 0))) { if (!ipocontr) { ipocontr = new KX_MaterialIpoController(matname_hash); } diff --git a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp index a9617aa47b8..1faf8f17d54 100644 --- a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp +++ b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp @@ -32,21 +32,6 @@ bool KX_MaterialIpoController::Update(double currentTime) { if (m_modified) { - m_rgba[0]=0; - m_rgba[1]=0; - m_rgba[2]=0; - m_rgba[3]=0; - - m_specrgb[0] =0; - m_specrgb[1] =0; - m_specrgb[2] =0; - m_hard =0; - m_spec=0; - m_ref=0; - m_emit=0; - m_alpha = 0; - - T_InterpolatorList::iterator i; for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) { (*i)->Execute(m_ipotime); -- cgit v1.2.3 From 8a231185aaf8b5f0753320bdd5de12538c626524 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 12 May 2015 16:56:40 +1000 Subject: Doc: minor fixes - check for class/static methods assumed nonzero args. - subclass references and set-flag items are now sorted. - use 'order' for Py operator mix-ins, so operator settings don't show in random order. --- doc/python_api/sphinx_doc_gen.py | 9 +++++---- release/scripts/modules/bpy_extras/io_utils.py | 16 ++++++++++++++++ release/scripts/modules/rna_info.py | 3 ++- release/scripts/startup/bl_operators/presets.py | 6 ++++++ 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index fab66d56a79..a49378f2f0e 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -633,11 +633,11 @@ def pyfunc2sphinx(ident, fw, module_name, type_name, identifier, py_func, is_cla func_type = "function" # ther rest are class methods - elif arg_str.startswith("(self, "): - arg_str = "(" + arg_str[7:] + elif arg_str.startswith("(self, ") or arg_str == "(self)": + arg_str = "()" if (arg_str == "(self)") else ("(" + arg_str[7:]) func_type = "method" elif arg_str.startswith("(cls, "): - arg_str = "(" + arg_str[6:] + arg_str = "()" if (arg_str == "(cls)") else ("(" + arg_str[6:]) func_type = "classmethod" else: func_type = "staticmethod" @@ -923,7 +923,7 @@ def pymodule2sphinx(basepath, module_name, module, title): write_example_ref(" ", fw, module_name + "." + type_name) - descr_items = [(key, descr) for key, descr in sorted(value.__dict__.items()) if not key.startswith("__")] + descr_items = [(key, descr) for key, descr in sorted(value.__dict__.items()) if not key.startswith("_")] for key, descr in descr_items: if type(descr) == ClassMethodDescriptorType: @@ -1239,6 +1239,7 @@ def pyrna2sphinx(basepath): fw("\n\n") subclass_ids = [s.identifier for s in structs.values() if s.base is struct if not rna_info.rna_id_ignore(s.identifier)] + subclass_ids.sort() if subclass_ids: fw("subclasses --- \n" + ", ".join((":class:`%s`" % s) for s in subclass_ids) + "\n\n") diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py index 1dc6f5b2b2c..32623e2bd25 100644 --- a/release/scripts/modules/bpy_extras/io_utils.py +++ b/release/scripts/modules/bpy_extras/io_utils.py @@ -61,6 +61,12 @@ class ExportHelper: options={'HIDDEN'}, ) + # needed for mix-ins + order = [ + "filepath", + "check_existing", + ] + # subclasses can override with decorator # True == use ext, False == no ext, None == do nothing. check_extension = True @@ -109,6 +115,11 @@ class ImportHelper: subtype='FILE_PATH', ) + # needed for mix-ins + order = [ + "filepath", + ] + def invoke(self, context, event): context.window_manager.fileselect_add(self) return {'RUNNING_MODAL'} @@ -154,6 +165,11 @@ def orientation_helper_factory(name, axis_forward='Y', axis_up='Z'): update=_update_axis_up, ) + members["order"] = [ + "axis_forward", + "axis_up", + ] + return type(name, (object,), members) diff --git a/release/scripts/modules/rna_info.py b/release/scripts/modules/rna_info.py index 353362ed168..ed80423023e 100644 --- a/release/scripts/modules/rna_info.py +++ b/release/scripts/modules/rna_info.py @@ -268,7 +268,8 @@ class InfoPropertyRNA: self.default_str = "\"%s\"" % self.default elif self.type == "enum": if self.is_enum_flag: - self.default_str = "%r" % self.default # repr or set() + # self.default_str = "%r" % self.default # repr or set() + self.default_str = "{%s}" % repr(list(sorted(self.default)))[1:-1] else: self.default_str = "'%s'" % self.default elif self.array_length: diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py index 7195b7819d1..a5270f63f27 100644 --- a/release/scripts/startup/bl_operators/presets.py +++ b/release/scripts/startup/bl_operators/presets.py @@ -45,6 +45,12 @@ class AddPresetBase: options={'HIDDEN', 'SKIP_SAVE'}, ) + # needed for mix-ins + order = [ + "name", + "remove_active", + ] + @staticmethod def as_filename(name): # could reuse for other presets for char in " !@#$%^&*(){}:\";'[]<>,.\\/?": -- cgit v1.2.3 From 311f6cac921b84cdbf770fe10ef2d656ee1817e5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 12 May 2015 17:17:31 +1000 Subject: Doc: replace addons -> scripts in docstring Theres nothing add-on specific here. --- release/scripts/templates_py/ui_previews_custom_icon.py | 2 +- release/scripts/templates_py/ui_previews_dynamic_enum.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/release/scripts/templates_py/ui_previews_custom_icon.py b/release/scripts/templates_py/ui_previews_custom_icon.py index defa2d266e6..badc6614d40 100644 --- a/release/scripts/templates_py/ui_previews_custom_icon.py +++ b/release/scripts/templates_py/ui_previews_custom_icon.py @@ -3,7 +3,7 @@ # # IMPORTANT NOTE: if you run this sample, there will be no icon in the button # You need to replace the image path with a real existing one. -# For distributable addons, it is recommended to place the icons inside the +# For distributable scripts, it is recommended to place the icons inside the # addon folder and access it relative to the py script file for portability # # diff --git a/release/scripts/templates_py/ui_previews_dynamic_enum.py b/release/scripts/templates_py/ui_previews_dynamic_enum.py index 1603df0335f..5dda6967a3c 100644 --- a/release/scripts/templates_py/ui_previews_dynamic_enum.py +++ b/release/scripts/templates_py/ui_previews_dynamic_enum.py @@ -13,7 +13,7 @@ # # For custom icons, see the template "ui_previews_custom_icon.py". # -# For distributable addons, it is recommended to place the icons inside the +# For distributable scripts, it is recommended to place the icons inside the # addon directory and access it relative to the py script file for portability: # # os.path.join(os.path.dirname(__file__), "images") -- cgit v1.2.3 From f727df6076241756a07aebdd495284203702dd1b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 12 May 2015 17:59:37 +1000 Subject: Doc: correct rst syntax also remove some API docs from example --- doc/python_api/rst/bge.constraints.rst | 12 ++++++------ .../rst/bge_types/bge.types.KX_ConstraintWrapper.rst | 15 +++++++++------ release/scripts/templates_py/ui_previews_custom_icon.py | 8 +------- source/blender/python/intern/bpy_utils_previews.c | 12 ++++++------ source/blender/python/intern/bpy_utils_units.c | 10 +++++----- source/blender/python/mathutils/mathutils_Matrix.c | 2 +- 6 files changed, 28 insertions(+), 31 deletions(-) diff --git a/doc/python_api/rst/bge.constraints.rst b/doc/python_api/rst/bge.constraints.rst index cf8565924b0..eaaf806a4a9 100644 --- a/doc/python_api/rst/bge.constraints.rst +++ b/doc/python_api/rst/bge.constraints.rst @@ -23,12 +23,12 @@ Physics Constraints (bge.constraints) :arg constrainttype: the type of the constraint. The constraint types are: :type constrainttype: int - - :class:`POINTTOPOINT_CONSTRAINT` - - :class:`LINEHINGE_CONSTRAINT` - - :class:`ANGULAR_CONSTRAINT` - - :class:`CONETWIST_CONSTRAINT` - - :class:`VEHICLE_CONSTRAINT` - - :class:`GENERIC_6DOF_CONSTRAINT` + - :class:`POINTTOPOINT_CONSTRAINT` + - :class:`LINEHINGE_CONSTRAINT` + - :class:`ANGULAR_CONSTRAINT` + - :class:`CONETWIST_CONSTRAINT` + - :class:`VEHICLE_CONSTRAINT` + - :class:`GENERIC_6DOF_CONSTRAINT` :arg pivot_X: pivot X position :type pivot_X: float (optional) diff --git a/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst b/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst index 2069bfb1dca..588f568cbb0 100644 --- a/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst +++ b/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst @@ -29,6 +29,7 @@ base class --- :class:`PyObjectPlus` * Lowerlimit < Upperlimit -> axis it limited in that range PHY_LINEHINGE_CONSTRAINT = 2 or PHY_ANGULAR_CONSTRAINT = 3: + axis = 3 is a constraint limit, with low/high limit value * 3: X axis angle @@ -38,6 +39,7 @@ base class --- :class:`PyObjectPlus` :type value1: float PHY_CONE_TWIST_CONSTRAINT = 3: + axis = 3..5 are constraint limits, high limit values * 3: X axis angle * 4: Y axis angle @@ -49,6 +51,7 @@ base class --- :class:`PyObjectPlus` :type value1: float PHY_GENERIC_6DOF_CONSTRAINT = 12: + axis = 0..2 are constraint limits, with low/high limit value * 0: X axis position * 1: Y axis position @@ -130,10 +133,10 @@ base class --- :class:`PyObjectPlus` Returns the contraint type (read only) :type: integer - - 1 = :class:`~bge.constraints.POINTTOPOINT_CONSTRAINT` - - 2 = :class:`~bge.constraints.LINEHINGE_CONSTRAINT` - - 3 = :class:`~bge.constraints.ANGULAR_CONSTRAINT` - - 4 = :class:`~bge.constraints.CONETWIST_CONSTRAINT` - - 11 = :class:`~bge.constraints.VEHICLE_CONSTRAINT` - - 12 = :class:`~bge.constraints.GENERIC_6DOF_CONSTRAINT` + - 1 = :class:`~bge.constraints.POINTTOPOINT_CONSTRAINT` + - 2 = :class:`~bge.constraints.LINEHINGE_CONSTRAINT` + - 3 = :class:`~bge.constraints.ANGULAR_CONSTRAINT` + - 4 = :class:`~bge.constraints.CONETWIST_CONSTRAINT` + - 11 = :class:`~bge.constraints.VEHICLE_CONSTRAINT` + - 12 = :class:`~bge.constraints.GENERIC_6DOF_CONSTRAINT` diff --git a/release/scripts/templates_py/ui_previews_custom_icon.py b/release/scripts/templates_py/ui_previews_custom_icon.py index badc6614d40..6eb4ad2992e 100644 --- a/release/scripts/templates_py/ui_previews_custom_icon.py +++ b/release/scripts/templates_py/ui_previews_custom_icon.py @@ -56,13 +56,7 @@ def register(): my_icons_dir = os.path.join(os.path.dirname(__file__), "icons") # load a preview thumbnail of a file and store in the previews collection - pcoll.load( - # identifier - "my_icon", - # path to image - os.path.join(my_icons_dir, "icon-image.png"), - # file type to generate preview from. others are: MOVIE, FONT, BLEND - 'IMAGE') + pcoll.load("my_icon", os.path.join(my_icons_dir, "icon-image.png"), 'IMAGE') preview_collections["main"] = pcoll diff --git a/source/blender/python/intern/bpy_utils_previews.c b/source/blender/python/intern/bpy_utils_previews.c index 5509ff50f5f..fed7c7210de 100644 --- a/source/blender/python/intern/bpy_utils_previews.c +++ b/source/blender/python/intern/bpy_utils_previews.c @@ -82,16 +82,16 @@ static PyObject *bpy_utils_previews_new(PyObject *UNUSED(self), PyObject *args) } PyDoc_STRVAR(bpy_utils_previews_load_doc, -".. method:: load(name, path, path_type, force_reload)\n" +".. method:: load(name, filepath, filetype, force_reload=False)\n" "\n" " Generate a new preview from given file path, or return existing one matching ``name``.\n" "\n" " :arg name: The name (unique id) identifying the preview.\n" " :type name: string\n" -" :arg path: The file path to generate the preview from.\n" -" :type path: string\n" -" :arg path_type: The type of file, needed to generate the preview in [" STR_SOURCE_TYPES "].\n" -" :type path_type: string\n" +" :arg filepath: The file path to generate the preview from.\n" +" :type filepath: string\n" +" :arg filetype: The type of file, needed to generate the preview in [" STR_SOURCE_TYPES "].\n" +" :type filetype: string\n" " :arg force_reload: If True, force running thumbnail manager even if preview already exists in cache.\n" " :type force_reload: bool\n" " :return: The Preview matching given name, or a new empty one.\n" @@ -123,7 +123,7 @@ static PyObject *bpy_utils_previews_load(PyObject *UNUSED(self), PyObject *args) } else { PyErr_Format(PyExc_ValueError, - "load: invalid '%' path type, only [" STR_SOURCE_TYPES "] " + "load: invalid '%s' filetype, only [" STR_SOURCE_TYPES "] " "are supported", path_type_s); return NULL; } diff --git a/source/blender/python/intern/bpy_utils_units.c b/source/blender/python/intern/bpy_utils_units.c index a6df8f54cc3..d40e7e070ac 100644 --- a/source/blender/python/intern/bpy_utils_units.c +++ b/source/blender/python/intern/bpy_utils_units.c @@ -155,18 +155,18 @@ static bool bpyunits_validate(const char *usys_str, const char *ucat_str, int *r } PyDoc_STRVAR(bpyunits_to_value_doc, -".. method:: to_value(unit_system, unit_category, str_input, [str_ref_unit=None])\n" +".. method:: to_value(unit_system, unit_category, str_input, str_ref_unit=None)\n" "\n" " Convert a given input string into a float value.\n" "\n" " :arg unit_system: The unit system, from :attr:`bpy.utils.units.systems`.\n" " :type unit_system: string\n" -" :arg unit_category: The category of data we are converting (length, area, rotation, etc.), " +" :arg unit_category: The category of data we are converting (length, area, rotation, etc.),\n" " from :attr:`bpy.utils.units.categories`.\n" " :type unit_category: string\n" " :arg str_input: The string to convert to a float value.\n" " :type str_input: string\n" -" :arg str_ref_unit: A reference string from which to extract a default unit, if none is found in :arg:`str_input`.\n" +" :arg str_ref_unit: A reference string from which to extract a default unit, if none is found in ``str_input``.\n" " :type str_ref_unit: string or None\n" " :return: The converted/interpreted value.\n" " :rtype: float\n" @@ -221,13 +221,13 @@ static PyObject *bpyunits_to_value(PyObject *UNUSED(self), PyObject *args, PyObj } PyDoc_STRVAR(bpyunits_to_string_doc, -".. method:: to_string(unit_system, unit_category, value, [precision=3, [split_unit=False, [compatible_unit=False]]])\n" +".. method:: to_string(unit_system, unit_category, value, precision=3, split_unit=False, compatible_unit=False)\n" "\n" " Convert a given input float value into a string with units.\n" "\n" " :arg unit_system: The unit system, from :attr:`bpy.utils.units.systems`.\n" " :type unit_system: string\n" -" :arg unit_category: The category of data we are converting (length, area, rotation, etc.), " +" :arg unit_category: The category of data we are converting (length, area, rotation, etc.),\n" " from :attr:`bpy.utils.units.categories`.\n" " :type unit_category: string\n" " :arg value: The value to convert to a string.\n" diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 91e2a635400..817173c5bc6 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -2757,7 +2757,7 @@ PyDoc_STRVAR(matrix_doc, " matrices from 2x2 up to 4x4.\n" "\n" " :param rows: Sequence of rows.\n" -" When ommitted, a 4x4 identity matrix is constructed.\n" +" When ommitted, a 4x4 identity matrix is constructed.\n" " :type rows: 2d number sequence\n" ); PyTypeObject matrix_Type = { -- cgit v1.2.3 From 34c78a659b7f157fa369c636b255326f04392ee0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 12 May 2015 18:06:31 +1000 Subject: Doc: add bpy.utils.previews Updated sphinx_doc_gen.py to better handle pure py-classes. --- doc/python_api/sphinx_doc_gen.py | 22 +++++++++++--- release/scripts/modules/bpy/utils/previews.py | 42 ++++++++++++++++++++------- 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index a49378f2f0e..72ddf251946 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -257,6 +257,7 @@ else: "bpy.props", "bpy.types", # supports filtering "bpy.utils", + "bpy.utils.previews", "bpy_extras", "gpu", "mathutils", @@ -642,10 +643,17 @@ def pyfunc2sphinx(ident, fw, module_name, type_name, identifier, py_func, is_cla else: func_type = "staticmethod" - fw(ident + ".. %s:: %s%s\n\n" % (func_type, identifier, arg_str)) - if py_func.__doc__: - write_indented_lines(ident + " ", fw, py_func.__doc__) + doc = py_func.__doc__ + if (not doc) or (not doc.startswith(".. %s:: " % func_type)): + fw(ident + ".. %s:: %s%s\n\n" % (func_type, identifier, arg_str)) + ident_temp = ident + " " + else: + ident_temp = ident + + if doc: + write_indented_lines(ident_temp, fw, doc) fw("\n") + del doc, ident_temp if is_class: write_example_ref(ident + " ", fw, module_name + "." + type_name + "." + identifier) @@ -916,7 +924,7 @@ def pymodule2sphinx(basepath, module_name, module, title): fw(value.__doc__) else: fw(".. class:: %s\n\n" % type_name) - write_indented_lines(" ", fw, value.__doc__, False) + write_indented_lines(" ", fw, value.__doc__, True) else: fw(".. class:: %s\n\n" % type_name) fw("\n") @@ -929,6 +937,11 @@ def pymodule2sphinx(basepath, module_name, module, title): if type(descr) == ClassMethodDescriptorType: py_descr2sphinx(" ", fw, descr, module_name, type_name, key) + # needed for pure python classes + for key, descr in descr_items: + if type(descr) == types.FunctionType: + pyfunc2sphinx(" ", fw, module_name, type_name, key, descr, is_class=True) + for key, descr in descr_items: if type(descr) == MethodDescriptorType: py_descr2sphinx(" ", fw, descr, module_name, type_name, key) @@ -1608,6 +1621,7 @@ def write_rst_contents(basepath): # py modules "bpy.utils", + "bpy.utils.previews", "bpy.path", "bpy.app", "bpy.app.handlers", diff --git a/release/scripts/modules/bpy/utils/previews.py b/release/scripts/modules/bpy/utils/previews.py index 4e8adf8e209..9e407d619f1 100644 --- a/release/scripts/modules/bpy/utils/previews.py +++ b/release/scripts/modules/bpy/utils/previews.py @@ -23,13 +23,20 @@ This module contains utility functions to handle custom previews. It behaves as a high-level 'cached' previews manager. -This allows addons to generate their own previews, and use them as icons in UI widgets -('icon_value' of UILayout functions). +This allows scripts to generate their own previews, and use them as icons in UI widgets +('icon_value' for UILayout functions). + + +Custom Icon Example +------------------- + +.. literalinclude:: ../../../release/scripts/templates_py/ui_previews_custom_icon.py """ __all__ = ( "new", "remove", + "ImagePreviewCollection", ) import _bpy @@ -42,14 +49,21 @@ _uuid_open = set() # High-level previews manager. # not accessed directly -class _BPyImagePreviewCollection(dict): +class ImagePreviewCollection(dict): """ - Dict-like class of previews. + Dictionary-like class of previews. + + This is a subclass of Python's built-in dict type, + used to store multiple image previews. + + .. note:: + + - instance with :mod:`bpy.utils.previews.new` + - keys must be ``str`` type. + - values will be :class:`bpy.types.ImagePreview` """ # Internal notes: - # - keys in the dict are stored by name - # - values are instances of bpy.types.ImagePreview # - Blender's internal 'PreviewImage' struct uses 'self._uuid' prefix. def __init__(self): @@ -93,11 +107,13 @@ class _BPyImagePreviewCollection(dict): release.__doc__ = _utils_previews.release.__doc__ def clear(self): + """Clear all previews.""" for name in self.keys(): _utils_previews.release(self._gen_key(name)) super().clear() def close(self): + """Close the collection and clear all previews.""" self.clear() _uuid_open.remove(self._uuid) @@ -114,24 +130,28 @@ class _BPyImagePreviewCollection(dict): def new(): """ - Return a new preview collection. + :return: a new preview collection. + :rtype: :class:`ImagePreviewCollection` """ - return _BPyImagePreviewCollection() + return ImagePreviewCollection() -def remove(p): +def remove(pcoll): """ Remove the specified previews collection. + + :arg pcoll: Preview collection to close. + :type pcoll: :class:`ImagePreviewCollection` """ - p.close() + pcoll.close() # don't complain about resources on exit (only unregister) import atexit def exit_clear_warning(): - del _BPyImagePreviewCollection.__del__ + del ImagePreviewCollection.__del__ atexit.register(exit_clear_warning) del atexit, exit_clear_warning -- cgit v1.2.3 From f6dc0e918b2687de067f2696b070b77f1a19a00b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 12 May 2015 18:28:05 +1000 Subject: Minor tweaks to preview templates --- release/scripts/templates_py/ui_previews_custom_icon.py | 2 +- release/scripts/templates_py/ui_previews_dynamic_enum.py | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/release/scripts/templates_py/ui_previews_custom_icon.py b/release/scripts/templates_py/ui_previews_custom_icon.py index 6eb4ad2992e..53f84b2982f 100644 --- a/release/scripts/templates_py/ui_previews_custom_icon.py +++ b/release/scripts/templates_py/ui_previews_custom_icon.py @@ -31,7 +31,7 @@ class PreviewsExamplePanel(bpy.types.Panel): pcoll = preview_collections["main"] row = layout.row() - my_icon = pcoll.get("my_icon") + my_icon = pcoll["my_icon"] row.operator("render.render", icon_value=my_icon.icon_id) # my_icon.icon_id can be used in any UI function that accepts diff --git a/release/scripts/templates_py/ui_previews_dynamic_enum.py b/release/scripts/templates_py/ui_previews_dynamic_enum.py index 5dda6967a3c..5269f7fa40b 100644 --- a/release/scripts/templates_py/ui_previews_dynamic_enum.py +++ b/release/scripts/templates_py/ui_previews_dynamic_enum.py @@ -14,7 +14,7 @@ # For custom icons, see the template "ui_previews_custom_icon.py". # # For distributable scripts, it is recommended to place the icons inside the -# addon directory and access it relative to the py script file for portability: +# script directory and access it relative to the py script file for portability: # # os.path.join(os.path.dirname(__file__), "images") @@ -47,11 +47,9 @@ def enum_previews_from_directory_items(self, context): for i, name in enumerate(image_paths): # generates a thumbnail preview for a file. - # Also works with previews for 'MOVIE', 'BLEND' and 'FONT' filepath = os.path.join(directory, name) thumb = pcoll.load(filepath, filepath, 'IMAGE') - # enum item: (identifier, name, description, icon, number) - enum_items.append((name, name, name, thumb.icon_id, i)) + enum_items.append((name, name, "", thumb.icon_id, i)) pcoll.my_previews = enum_items pcoll.my_previews_dir = directory -- cgit v1.2.3 From 20e561dd6a2eaf2ae8b93253f1d526460367e287 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 12 May 2015 18:43:30 +1000 Subject: PyAPI: Remove release method, just use delitem --- release/scripts/modules/bpy/utils/previews.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/release/scripts/modules/bpy/utils/previews.py b/release/scripts/modules/bpy/utils/previews.py index 9e407d619f1..bd6b6a0d304 100644 --- a/release/scripts/modules/bpy/utils/previews.py +++ b/release/scripts/modules/bpy/utils/previews.py @@ -100,12 +100,6 @@ class ImagePreviewCollection(dict): return p load.__doc__ = _utils_previews.load.__doc__ - def release(self, name): - p = self.pop(name, None) - if p is not None: - _utils_previews.release(self._gen_key(name)) - release.__doc__ = _utils_previews.release.__doc__ - def clear(self): """Clear all previews.""" for name in self.keys(): @@ -118,7 +112,8 @@ class ImagePreviewCollection(dict): _uuid_open.remove(self._uuid) def __delitem__(self, key): - return self.release(key) + _utils_previews.release(self._gen_key(name)) + super().__delitem__(key) def __repr__(self): return "<%s id=%s[%d], %s>" % ( -- cgit v1.2.3 From ae00e42bc291c5ff3914ff604892f3d79eaa999c Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 12 May 2015 10:56:28 +0200 Subject: Fix T44677: Normal Edit Modifier Radial Mode broken with target object. Very stupid mistake, odd nobody hit this earlier... :/ --- source/blender/modifiers/intern/MOD_normal_edit.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 80636986583..8315f61c132 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -80,10 +80,13 @@ static void generate_vert_coordinates( } if (ob_center) { + float inv_obmat[4][4]; + /* Translate our coordinates so that center of ob_center is at (0, 0, 0). */ /* Get ob_center (world) coordinates in ob local coordinates. * No need to take into accound ob_center's space here, see T44027. */ - mul_v3_m4v3(diff, ob->obmat, ob_center->obmat[3]); + invert_m4_m4(inv_obmat, ob->obmat); + mul_v3_m4v3(diff, inv_obmat, ob_center->obmat[3]); negate_v3(diff); do_diff = true; -- cgit v1.2.3 From dbbe721c2afda4a3b5c8ea7e60cf3f2b011cc857 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 12 May 2015 12:50:24 +0500 Subject: Depsgraph: Move update-related functions into own files Currently it is just moving existing functions into a new file, but in the future those new files will be grown much more due to upcoming more granular scene updates. Should be no functional changes. --- source/blender/blenkernel/BKE_armature.h | 5 + source/blender/blenkernel/BKE_object.h | 4 + source/blender/blenkernel/CMakeLists.txt | 2 + source/blender/blenkernel/intern/armature.c | 492 +----------------- source/blender/blenkernel/intern/armature_update.c | 549 +++++++++++++++++++++ source/blender/blenkernel/intern/object.c | 142 +----- source/blender/blenkernel/intern/object_update.c | 204 ++++++++ 7 files changed, 767 insertions(+), 631 deletions(-) create mode 100644 source/blender/blenkernel/intern/armature_update.c create mode 100644 source/blender/blenkernel/intern/object_update.c diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index de767d39216..ada07817d31 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -142,6 +142,11 @@ void b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 result_array #define PBONE_SELECTABLE(arm, bone) \ (PBONE_VISIBLE(arm, bone) && !((bone)->flag & BONE_UNSELECTABLE)) +/* Evaluation helpers */ + +void BKE_pose_splineik_init_tree(struct Scene *scene, struct Object *ob, float ctime); +void BKE_splineik_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan_root, float ctime); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 0e0c779c033..d287eb4a057 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -178,6 +178,10 @@ void BKE_object_tfm_protected_restore(struct Object *ob, const ObjectTfmProtectedChannels *obtfm, const short protectflag); +/* Dependency graph evaluation callbacks. */ +void BKE_object_handle_data_update(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob); void BKE_object_handle_update(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); void BKE_object_handle_update_ex(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 67c8f0fc558..fe713e64c64 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -67,6 +67,7 @@ set(SRC intern/anim_sys.c intern/appdir.c intern/armature.c + intern/armature_update.c intern/autoexec.c intern/blender.c intern/bmfont.c @@ -134,6 +135,7 @@ set(SRC intern/object.c intern/object_deform.c intern/object_dupli.c + intern/object_update.c intern/ocean.c intern/outliner_treehash.c intern/packedFile.c diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index dc11bcb00aa..d5416b41b44 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1835,494 +1835,6 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm) BKE_pose_channels_hash_make(ob->pose); } - -/* ********************** SPLINE IK SOLVER ******************* */ - -/* Temporary evaluation tree data used for Spline IK */ -typedef struct tSplineIK_Tree { - struct tSplineIK_Tree *next, *prev; - - int type; /* type of IK that this serves (CONSTRAINT_TYPE_KINEMATIC or ..._SPLINEIK) */ - - bool free_points; /* free the point positions array */ - short chainlen; /* number of bones in the chain */ - - float *points; /* parametric positions for the joints along the curve */ - bPoseChannel **chain; /* chain of bones to affect using Spline IK (ordered from the tip) */ - - bPoseChannel *root; /* bone that is the root node of the chain */ - - bConstraint *con; /* constraint for this chain */ - bSplineIKConstraint *ikData; /* constraint settings for this chain */ -} tSplineIK_Tree; - -/* ----------- */ - -/* Tag the bones in the chain formed by the given bone for IK */ -static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPoseChannel *pchan_tip) -{ - bPoseChannel *pchan, *pchanRoot = NULL; - bPoseChannel *pchanChain[255]; - bConstraint *con = NULL; - bSplineIKConstraint *ikData = NULL; - float boneLengths[255], *jointPoints; - float totLength = 0.0f; - bool free_joints = 0; - int segcount = 0; - - /* find the SplineIK constraint */ - for (con = pchan_tip->constraints.first; con; con = con->next) { - if (con->type == CONSTRAINT_TYPE_SPLINEIK) { - ikData = con->data; - - /* target can only be curve */ - if ((ikData->tar == NULL) || (ikData->tar->type != OB_CURVE)) - continue; - /* skip if disabled */ - if ((con->enforce == 0.0f) || (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF))) - continue; - - /* otherwise, constraint is ok... */ - break; - } - } - if (con == NULL) - return; - - /* make sure that the constraint targets are ok - * - this is a workaround for a depsgraph bug... - */ - if (ikData->tar) { - /* note: when creating constraints that follow path, the curve gets the CU_PATH set now, - * currently for paths to work it needs to go through the bevlist/displist system (ton) - */ - - /* only happens on reload file, but violates depsgraph still... fix! */ - if (ELEM(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) { - BKE_displist_make_curveTypes(scene, ikData->tar, 0); - - /* path building may fail in EditMode after removing verts [#33268]*/ - if (ELEM(NULL, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) { - /* BLI_assert(cu->path != NULL); */ - return; - } - } - } - - /* find the root bone and the chain of bones from the root to the tip - * NOTE: this assumes that the bones are connected, but that may not be true... */ - for (pchan = pchan_tip; pchan && (segcount < ikData->chainlen); pchan = pchan->parent, segcount++) { - /* store this segment in the chain */ - pchanChain[segcount] = pchan; - - /* if performing rebinding, calculate the length of the bone */ - boneLengths[segcount] = pchan->bone->length; - totLength += boneLengths[segcount]; - } - - if (segcount == 0) - return; - else - pchanRoot = pchanChain[segcount - 1]; - - /* perform binding step if required */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_BOUND) == 0) { - float segmentLen = (1.0f / (float)segcount); - int i; - - /* setup new empty array for the points list */ - if (ikData->points) - MEM_freeN(ikData->points); - ikData->numpoints = ikData->chainlen + 1; - ikData->points = MEM_mallocN(sizeof(float) * ikData->numpoints, "Spline IK Binding"); - - /* bind 'tip' of chain (i.e. first joint = tip of bone with the Spline IK Constraint) */ - ikData->points[0] = 1.0f; - - /* perform binding of the joints to parametric positions along the curve based - * proportion of the total length that each bone occupies - */ - for (i = 0; i < segcount; i++) { - /* 'head' joints, traveling towards the root of the chain - * - 2 methods; the one chosen depends on whether we've got usable lengths - */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_EVENSPLITS) || (totLength == 0.0f)) { - /* 1) equi-spaced joints */ - ikData->points[i + 1] = ikData->points[i] - segmentLen; - } - else { - /* 2) to find this point on the curve, we take a step from the previous joint - * a distance given by the proportion that this bone takes - */ - ikData->points[i + 1] = ikData->points[i] - (boneLengths[i] / totLength); - } - } - - /* spline has now been bound */ - ikData->flag |= CONSTRAINT_SPLINEIK_BOUND; - } - - /* disallow negative values (happens with float precision) */ - CLAMP_MIN(ikData->points[segcount], 0.0f); - - /* apply corrections for sensitivity to scaling on a copy of the bind points, - * since it's easier to determine the positions of all the joints beforehand this way - */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_SCALE_LIMITED) && (totLength != 0.0f)) { - float splineLen, maxScale; - int i; - - /* make a copy of the points array, that we'll store in the tree - * - although we could just multiply the points on the fly, this approach means that - * we can introduce per-segment stretchiness later if it is necessary - */ - jointPoints = MEM_dupallocN(ikData->points); - free_joints = 1; - - /* get the current length of the curve */ - /* NOTE: this is assumed to be correct even after the curve was resized */ - splineLen = ikData->tar->curve_cache->path->totdist; - - /* calculate the scale factor to multiply all the path values by so that the - * bone chain retains its current length, such that - * maxScale * splineLen = totLength - */ - maxScale = totLength / splineLen; - - /* apply scaling correction to all of the temporary points */ - /* TODO: this is really not adequate enough on really short chains */ - for (i = 0; i < segcount; i++) - jointPoints[i] *= maxScale; - } - else { - /* just use the existing points array */ - jointPoints = ikData->points; - free_joints = 0; - } - - /* make a new Spline-IK chain, and store it in the IK chains */ - /* TODO: we should check if there is already an IK chain on this, since that would take presidence... */ - { - /* make new tree */ - tSplineIK_Tree *tree = MEM_callocN(sizeof(tSplineIK_Tree), "SplineIK Tree"); - tree->type = CONSTRAINT_TYPE_SPLINEIK; - - tree->chainlen = segcount; - - /* copy over the array of links to bones in the chain (from tip to root) */ - tree->chain = MEM_mallocN(sizeof(bPoseChannel *) * segcount, "SplineIK Chain"); - memcpy(tree->chain, pchanChain, sizeof(bPoseChannel *) * segcount); - - /* store reference to joint position array */ - tree->points = jointPoints; - tree->free_points = free_joints; - - /* store references to different parts of the chain */ - tree->root = pchanRoot; - tree->con = con; - tree->ikData = ikData; - - /* AND! link the tree to the root */ - BLI_addtail(&pchanRoot->siktree, tree); - } - - /* mark root channel having an IK tree */ - pchanRoot->flag |= POSE_IKSPLINE; -} - -/* Tag which bones are members of Spline IK chains */ -static void splineik_init_tree(Scene *scene, Object *ob, float UNUSED(ctime)) -{ - bPoseChannel *pchan; - - /* find the tips of Spline IK chains, which are simply the bones which have been tagged as such */ - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { - if (pchan->constflag & PCHAN_HAS_SPLINEIK) - splineik_init_tree_from_pchan(scene, ob, pchan); - } -} - -/* ----------- */ - -/* Evaluate spline IK for a given bone */ -static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan, - int index, float ctime) -{ - bSplineIKConstraint *ikData = tree->ikData; - float poseHead[3], poseTail[3], poseMat[4][4]; - float splineVec[3], scaleFac, radius = 1.0f; - - /* firstly, calculate the bone matrix the standard way, since this is needed for roll control */ - BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1); - - copy_v3_v3(poseHead, pchan->pose_head); - copy_v3_v3(poseTail, pchan->pose_tail); - - /* step 1: determine the positions for the endpoints of the bone */ - { - float vec[4], dir[3], rad; - float tailBlendFac = 1.0f; - - /* determine if the bone should still be affected by SplineIK */ - if (tree->points[index + 1] >= 1.0f) { - /* spline doesn't affect the bone anymore, so done... */ - pchan->flag |= POSE_DONE; - return; - } - else if ((tree->points[index] >= 1.0f) && (tree->points[index + 1] < 1.0f)) { - /* blending factor depends on the amount of the bone still left on the chain */ - tailBlendFac = (1.0f - tree->points[index + 1]) / (tree->points[index] - tree->points[index + 1]); - } - - /* tail endpoint */ - if (where_on_path(ikData->tar, tree->points[index], vec, dir, NULL, &rad, NULL)) { - /* apply curve's object-mode transforms to the position - * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root) - */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) - mul_m4_v3(ikData->tar->obmat, vec); - - /* convert the position to pose-space, then store it */ - mul_m4_v3(ob->imat, vec); - interp_v3_v3v3(poseTail, pchan->pose_tail, vec, tailBlendFac); - - /* set the new radius */ - radius = rad; - } - - /* head endpoint */ - if (where_on_path(ikData->tar, tree->points[index + 1], vec, dir, NULL, &rad, NULL)) { - /* apply curve's object-mode transforms to the position - * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root) - */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) - mul_m4_v3(ikData->tar->obmat, vec); - - /* store the position, and convert it to pose space */ - mul_m4_v3(ob->imat, vec); - copy_v3_v3(poseHead, vec); - - /* set the new radius (it should be the average value) */ - radius = (radius + rad) / 2; - } - } - - /* step 2: determine the implied transform from these endpoints - * - splineVec: the vector direction that the spline applies on the bone - * - scaleFac: the factor that the bone length is scaled by to get the desired amount - */ - sub_v3_v3v3(splineVec, poseTail, poseHead); - scaleFac = len_v3(splineVec) / pchan->bone->length; - - /* step 3: compute the shortest rotation needed to map from the bone rotation to the current axis - * - this uses the same method as is used for the Damped Track Constraint (see the code there for details) - */ - { - float dmat[3][3], rmat[3][3], tmat[3][3]; - float raxis[3], rangle; - - /* compute the raw rotation matrix from the bone's current matrix by extracting only the - * orientation-relevant axes, and normalizing them - */ - copy_v3_v3(rmat[0], pchan->pose_mat[0]); - copy_v3_v3(rmat[1], pchan->pose_mat[1]); - copy_v3_v3(rmat[2], pchan->pose_mat[2]); - normalize_m3(rmat); - - /* also, normalize the orientation imposed by the bone, now that we've extracted the scale factor */ - normalize_v3(splineVec); - - /* calculate smallest axis-angle rotation necessary for getting from the - * current orientation of the bone, to the spline-imposed direction - */ - cross_v3_v3v3(raxis, rmat[1], splineVec); - - rangle = dot_v3v3(rmat[1], splineVec); - CLAMP(rangle, -1.0f, 1.0f); - rangle = acosf(rangle); - - /* multiply the magnitude of the angle by the influence of the constraint to - * control the influence of the SplineIK effect - */ - rangle *= tree->con->enforce; - - /* construct rotation matrix from the axis-angle rotation found above - * - this call takes care to make sure that the axis provided is a unit vector first - */ - axis_angle_to_mat3(dmat, raxis, rangle); - - /* combine these rotations so that the y-axis of the bone is now aligned as the spline dictates, - * while still maintaining roll control from the existing bone animation - */ - mul_m3_m3m3(tmat, dmat, rmat); /* m1, m3, m2 */ - normalize_m3(tmat); /* attempt to reduce shearing, though I doubt this'll really help too much now... */ - copy_m4_m3(poseMat, tmat); - } - - /* step 4: set the scaling factors for the axes */ - { - /* only multiply the y-axis by the scaling factor to get nice volume-preservation */ - mul_v3_fl(poseMat[1], scaleFac); - - /* set the scaling factors of the x and z axes from... */ - switch (ikData->xzScaleMode) { - case CONSTRAINT_SPLINEIK_XZS_ORIGINAL: - { - /* original scales get used */ - float scale; - - /* x-axis scale */ - scale = len_v3(pchan->pose_mat[0]); - mul_v3_fl(poseMat[0], scale); - /* z-axis scale */ - scale = len_v3(pchan->pose_mat[2]); - mul_v3_fl(poseMat[2], scale); - break; - } - case CONSTRAINT_SPLINEIK_XZS_INVERSE: - { - /* old 'volume preservation' method using the inverse scale */ - float scale; - - /* calculate volume preservation factor which is - * basically the inverse of the y-scaling factor - */ - if (fabsf(scaleFac) != 0.0f) { - scale = 1.0f / fabsf(scaleFac); - - /* we need to clamp this within sensible values */ - /* NOTE: these should be fine for now, but should get sanitised in future */ - CLAMP(scale, 0.0001f, 100000.0f); - } - else - scale = 1.0f; - - /* apply the scaling */ - mul_v3_fl(poseMat[0], scale); - mul_v3_fl(poseMat[2], scale); - break; - } - case CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC: - { - /* improved volume preservation based on the Stretch To constraint */ - float final_scale; - - /* as the basis for volume preservation, we use the inverse scale factor... */ - if (fabsf(scaleFac) != 0.0f) { - /* NOTE: The method here is taken wholesale from the Stretch To constraint */ - float bulge = powf(1.0f / fabsf(scaleFac), ikData->bulge); - - if (bulge > 1.0f) { - if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MAX) { - float bulge_max = max_ff(ikData->bulge_max, 1.0f); - float hard = min_ff(bulge, bulge_max); - - float range = bulge_max - 1.0f; - float scale = (range > 0.0f) ? 1.0f / range : 0.0f; - float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (float)M_PI_2; - - bulge = interpf(soft, hard, ikData->bulge_smooth); - } - } - if (bulge < 1.0f) { - if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MIN) { - float bulge_min = CLAMPIS(ikData->bulge_min, 0.0f, 1.0f); - float hard = max_ff(bulge, bulge_min); - - float range = 1.0f - bulge_min; - float scale = (range > 0.0f) ? 1.0f / range : 0.0f; - float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (float)M_PI_2; - - bulge = interpf(soft, hard, ikData->bulge_smooth); - } - } - - /* compute scale factor for xz axes from this value */ - final_scale = sqrtf(bulge); - } - else { - /* no scaling, so scale factor is simple */ - final_scale = 1.0f; - } - - /* apply the scaling (assuming normalised scale) */ - mul_v3_fl(poseMat[0], final_scale); - mul_v3_fl(poseMat[2], final_scale); - break; - } - } - - /* finally, multiply the x and z scaling by the radius of the curve too, - * to allow automatic scales to get tweaked still - */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_CURVERAD) == 0) { - mul_v3_fl(poseMat[0], radius); - mul_v3_fl(poseMat[2], radius); - } - } - - /* step 5: set the location of the bone in the matrix */ - if (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) { - /* when the 'no-root' option is affected, the chain can retain - * the shape but be moved elsewhere - */ - copy_v3_v3(poseHead, pchan->pose_head); - } - else if (tree->con->enforce < 1.0f) { - /* when the influence is too low - * - blend the positions for the 'root' bone - * - stick to the parent for any other - */ - if (pchan->parent) { - copy_v3_v3(poseHead, pchan->pose_head); - } - else { - /* FIXME: this introduces popping artifacts when we reach 0.0 */ - interp_v3_v3v3(poseHead, pchan->pose_head, poseHead, tree->con->enforce); - } - } - copy_v3_v3(poseMat[3], poseHead); - - /* finally, store the new transform */ - copy_m4_m4(pchan->pose_mat, poseMat); - copy_v3_v3(pchan->pose_head, poseHead); - - /* recalculate tail, as it's now outdated after the head gets adjusted above! */ - BKE_pose_where_is_bone_tail(pchan); - - /* done! */ - pchan->flag |= POSE_DONE; -} - -/* Evaluate the chain starting from the nominated bone */ -static void splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime) -{ - tSplineIK_Tree *tree; - - /* for each pose-tree, execute it if it is spline, otherwise just free it */ - while ((tree = pchan_root->siktree.first) != NULL) { - int i; - - /* walk over each bone in the chain, calculating the effects of spline IK - * - the chain is traversed in the opposite order to storage order (i.e. parent to children) - * so that dependencies are correct - */ - for (i = tree->chainlen - 1; i >= 0; i--) { - bPoseChannel *pchan = tree->chain[i]; - splineik_evaluate_bone(tree, scene, ob, pchan, i, ctime); - } - - /* free the tree info specific to SplineIK trees now */ - if (tree->chain) - MEM_freeN(tree->chain); - if (tree->free_points) - MEM_freeN(tree->points); - - /* free this tree */ - BLI_freelinkN(&pchan_root->siktree, tree); - } -} - /* ********************** THE POSE SOLVER ******************* */ /* loc/rot/size to given mat4 */ @@ -2623,7 +2135,7 @@ void BKE_pose_where_is(Scene *scene, Object *ob) * - this is not integrated as an IK plugin, since it should be able * to function in conjunction with standard IK */ - splineik_init_tree(scene, ob, ctime); + BKE_pose_splineik_init_tree(scene, ob, ctime); /* 3. the main loop, channels are already hierarchical sorted from root to children */ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { @@ -2633,7 +2145,7 @@ void BKE_pose_where_is(Scene *scene, Object *ob) } /* 4b. if we find a Spline IK root, we handle it separated too */ else if (pchan->flag & POSE_IKSPLINE) { - splineik_execute_tree(scene, ob, pchan, ctime); + BKE_splineik_execute_tree(scene, ob, pchan, ctime); } /* 5. otherwise just call the normal solver */ else if (!(pchan->flag & POSE_DONE)) { diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c new file mode 100644 index 00000000000..f7aee3fa2d4 --- /dev/null +++ b/source/blender/blenkernel/intern/armature_update.c @@ -0,0 +1,549 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + * + * Defines and code for core node types + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "DNA_armature_types.h" +#include "DNA_constraint_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "BKE_action.h" +#include "BKE_anim.h" +#include "BKE_armature.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_displist.h" +#include "BKE_fcurve.h" +#include "BKE_scene.h" + +#include "BIK_api.h" + +#include "BKE_global.h" +#include "BKE_main.h" + +/* ********************** SPLINE IK SOLVER ******************* */ + +/* Temporary evaluation tree data used for Spline IK */ +typedef struct tSplineIK_Tree { + struct tSplineIK_Tree *next, *prev; + + int type; /* type of IK that this serves (CONSTRAINT_TYPE_KINEMATIC or ..._SPLINEIK) */ + + bool free_points; /* free the point positions array */ + short chainlen; /* number of bones in the chain */ + + float *points; /* parametric positions for the joints along the curve */ + bPoseChannel **chain; /* chain of bones to affect using Spline IK (ordered from the tip) */ + + bPoseChannel *root; /* bone that is the root node of the chain */ + + bConstraint *con; /* constraint for this chain */ + bSplineIKConstraint *ikData; /* constraint settings for this chain */ +} tSplineIK_Tree; + +/* ----------- */ + +/* Tag the bones in the chain formed by the given bone for IK */ +static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPoseChannel *pchan_tip) +{ + bPoseChannel *pchan, *pchanRoot = NULL; + bPoseChannel *pchanChain[255]; + bConstraint *con = NULL; + bSplineIKConstraint *ikData = NULL; + float boneLengths[255], *jointPoints; + float totLength = 0.0f; + bool free_joints = 0; + int segcount = 0; + + /* find the SplineIK constraint */ + for (con = pchan_tip->constraints.first; con; con = con->next) { + if (con->type == CONSTRAINT_TYPE_SPLINEIK) { + ikData = con->data; + + /* target can only be curve */ + if ((ikData->tar == NULL) || (ikData->tar->type != OB_CURVE)) + continue; + /* skip if disabled */ + if ((con->enforce == 0.0f) || (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF))) + continue; + + /* otherwise, constraint is ok... */ + break; + } + } + if (con == NULL) + return; + + /* make sure that the constraint targets are ok + * - this is a workaround for a depsgraph bug... + */ + if (ikData->tar) { + /* note: when creating constraints that follow path, the curve gets the CU_PATH set now, + * currently for paths to work it needs to go through the bevlist/displist system (ton) + */ + + /* only happens on reload file, but violates depsgraph still... fix! */ + if (ELEM(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) { + BKE_displist_make_curveTypes(scene, ikData->tar, 0); + + /* path building may fail in EditMode after removing verts [#33268]*/ + if (ELEM(NULL, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) { + /* BLI_assert(cu->path != NULL); */ + return; + } + } + } + + /* find the root bone and the chain of bones from the root to the tip + * NOTE: this assumes that the bones are connected, but that may not be true... */ + for (pchan = pchan_tip; pchan && (segcount < ikData->chainlen); pchan = pchan->parent, segcount++) { + /* store this segment in the chain */ + pchanChain[segcount] = pchan; + + /* if performing rebinding, calculate the length of the bone */ + boneLengths[segcount] = pchan->bone->length; + totLength += boneLengths[segcount]; + } + + if (segcount == 0) + return; + else + pchanRoot = pchanChain[segcount - 1]; + + /* perform binding step if required */ + if ((ikData->flag & CONSTRAINT_SPLINEIK_BOUND) == 0) { + float segmentLen = (1.0f / (float)segcount); + int i; + + /* setup new empty array for the points list */ + if (ikData->points) + MEM_freeN(ikData->points); + ikData->numpoints = ikData->chainlen + 1; + ikData->points = MEM_mallocN(sizeof(float) * ikData->numpoints, "Spline IK Binding"); + + /* bind 'tip' of chain (i.e. first joint = tip of bone with the Spline IK Constraint) */ + ikData->points[0] = 1.0f; + + /* perform binding of the joints to parametric positions along the curve based + * proportion of the total length that each bone occupies + */ + for (i = 0; i < segcount; i++) { + /* 'head' joints, traveling towards the root of the chain + * - 2 methods; the one chosen depends on whether we've got usable lengths + */ + if ((ikData->flag & CONSTRAINT_SPLINEIK_EVENSPLITS) || (totLength == 0.0f)) { + /* 1) equi-spaced joints */ + ikData->points[i + 1] = ikData->points[i] - segmentLen; + } + else { + /* 2) to find this point on the curve, we take a step from the previous joint + * a distance given by the proportion that this bone takes + */ + ikData->points[i + 1] = ikData->points[i] - (boneLengths[i] / totLength); + } + } + + /* spline has now been bound */ + ikData->flag |= CONSTRAINT_SPLINEIK_BOUND; + } + + /* disallow negative values (happens with float precision) */ + CLAMP_MIN(ikData->points[segcount], 0.0f); + + /* apply corrections for sensitivity to scaling on a copy of the bind points, + * since it's easier to determine the positions of all the joints beforehand this way + */ + if ((ikData->flag & CONSTRAINT_SPLINEIK_SCALE_LIMITED) && (totLength != 0.0f)) { + float splineLen, maxScale; + int i; + + /* make a copy of the points array, that we'll store in the tree + * - although we could just multiply the points on the fly, this approach means that + * we can introduce per-segment stretchiness later if it is necessary + */ + jointPoints = MEM_dupallocN(ikData->points); + free_joints = 1; + + /* get the current length of the curve */ + /* NOTE: this is assumed to be correct even after the curve was resized */ + splineLen = ikData->tar->curve_cache->path->totdist; + + /* calculate the scale factor to multiply all the path values by so that the + * bone chain retains its current length, such that + * maxScale * splineLen = totLength + */ + maxScale = totLength / splineLen; + + /* apply scaling correction to all of the temporary points */ + /* TODO: this is really not adequate enough on really short chains */ + for (i = 0; i < segcount; i++) + jointPoints[i] *= maxScale; + } + else { + /* just use the existing points array */ + jointPoints = ikData->points; + free_joints = 0; + } + + /* make a new Spline-IK chain, and store it in the IK chains */ + /* TODO: we should check if there is already an IK chain on this, since that would take presidence... */ + { + /* make new tree */ + tSplineIK_Tree *tree = MEM_callocN(sizeof(tSplineIK_Tree), "SplineIK Tree"); + tree->type = CONSTRAINT_TYPE_SPLINEIK; + + tree->chainlen = segcount; + + /* copy over the array of links to bones in the chain (from tip to root) */ + tree->chain = MEM_mallocN(sizeof(bPoseChannel *) * segcount, "SplineIK Chain"); + memcpy(tree->chain, pchanChain, sizeof(bPoseChannel *) * segcount); + + /* store reference to joint position array */ + tree->points = jointPoints; + tree->free_points = free_joints; + + /* store references to different parts of the chain */ + tree->root = pchanRoot; + tree->con = con; + tree->ikData = ikData; + + /* AND! link the tree to the root */ + BLI_addtail(&pchanRoot->siktree, tree); + } + + /* mark root channel having an IK tree */ + pchanRoot->flag |= POSE_IKSPLINE; +} + +/* Tag which bones are members of Spline IK chains */ +static void splineik_init_tree(Scene *scene, Object *ob, float UNUSED(ctime)) +{ + bPoseChannel *pchan; + + /* find the tips of Spline IK chains, which are simply the bones which have been tagged as such */ + for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + if (pchan->constflag & PCHAN_HAS_SPLINEIK) + splineik_init_tree_from_pchan(scene, ob, pchan); + } +} + +/* ----------- */ + +/* Evaluate spline IK for a given bone */ +static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan, + int index, float ctime) +{ + bSplineIKConstraint *ikData = tree->ikData; + float poseHead[3], poseTail[3], poseMat[4][4]; + float splineVec[3], scaleFac, radius = 1.0f; + + /* firstly, calculate the bone matrix the standard way, since this is needed for roll control */ + BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1); + + copy_v3_v3(poseHead, pchan->pose_head); + copy_v3_v3(poseTail, pchan->pose_tail); + + /* step 1: determine the positions for the endpoints of the bone */ + { + float vec[4], dir[3], rad; + float tailBlendFac = 1.0f; + + /* determine if the bone should still be affected by SplineIK */ + if (tree->points[index + 1] >= 1.0f) { + /* spline doesn't affect the bone anymore, so done... */ + pchan->flag |= POSE_DONE; + return; + } + else if ((tree->points[index] >= 1.0f) && (tree->points[index + 1] < 1.0f)) { + /* blending factor depends on the amount of the bone still left on the chain */ + tailBlendFac = (1.0f - tree->points[index + 1]) / (tree->points[index] - tree->points[index + 1]); + } + + /* tail endpoint */ + if (where_on_path(ikData->tar, tree->points[index], vec, dir, NULL, &rad, NULL)) { + /* apply curve's object-mode transforms to the position + * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root) + */ + if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) + mul_m4_v3(ikData->tar->obmat, vec); + + /* convert the position to pose-space, then store it */ + mul_m4_v3(ob->imat, vec); + interp_v3_v3v3(poseTail, pchan->pose_tail, vec, tailBlendFac); + + /* set the new radius */ + radius = rad; + } + + /* head endpoint */ + if (where_on_path(ikData->tar, tree->points[index + 1], vec, dir, NULL, &rad, NULL)) { + /* apply curve's object-mode transforms to the position + * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root) + */ + if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) + mul_m4_v3(ikData->tar->obmat, vec); + + /* store the position, and convert it to pose space */ + mul_m4_v3(ob->imat, vec); + copy_v3_v3(poseHead, vec); + + /* set the new radius (it should be the average value) */ + radius = (radius + rad) / 2; + } + } + + /* step 2: determine the implied transform from these endpoints + * - splineVec: the vector direction that the spline applies on the bone + * - scaleFac: the factor that the bone length is scaled by to get the desired amount + */ + sub_v3_v3v3(splineVec, poseTail, poseHead); + scaleFac = len_v3(splineVec) / pchan->bone->length; + + /* step 3: compute the shortest rotation needed to map from the bone rotation to the current axis + * - this uses the same method as is used for the Damped Track Constraint (see the code there for details) + */ + { + float dmat[3][3], rmat[3][3], tmat[3][3]; + float raxis[3], rangle; + + /* compute the raw rotation matrix from the bone's current matrix by extracting only the + * orientation-relevant axes, and normalizing them + */ + copy_v3_v3(rmat[0], pchan->pose_mat[0]); + copy_v3_v3(rmat[1], pchan->pose_mat[1]); + copy_v3_v3(rmat[2], pchan->pose_mat[2]); + normalize_m3(rmat); + + /* also, normalize the orientation imposed by the bone, now that we've extracted the scale factor */ + normalize_v3(splineVec); + + /* calculate smallest axis-angle rotation necessary for getting from the + * current orientation of the bone, to the spline-imposed direction + */ + cross_v3_v3v3(raxis, rmat[1], splineVec); + + rangle = dot_v3v3(rmat[1], splineVec); + CLAMP(rangle, -1.0f, 1.0f); + rangle = acosf(rangle); + + /* multiply the magnitude of the angle by the influence of the constraint to + * control the influence of the SplineIK effect + */ + rangle *= tree->con->enforce; + + /* construct rotation matrix from the axis-angle rotation found above + * - this call takes care to make sure that the axis provided is a unit vector first + */ + axis_angle_to_mat3(dmat, raxis, rangle); + + /* combine these rotations so that the y-axis of the bone is now aligned as the spline dictates, + * while still maintaining roll control from the existing bone animation + */ + mul_m3_m3m3(tmat, dmat, rmat); /* m1, m3, m2 */ + normalize_m3(tmat); /* attempt to reduce shearing, though I doubt this'll really help too much now... */ + copy_m4_m3(poseMat, tmat); + } + + /* step 4: set the scaling factors for the axes */ + { + /* only multiply the y-axis by the scaling factor to get nice volume-preservation */ + mul_v3_fl(poseMat[1], scaleFac); + + /* set the scaling factors of the x and z axes from... */ + switch (ikData->xzScaleMode) { + case CONSTRAINT_SPLINEIK_XZS_ORIGINAL: + { + /* original scales get used */ + float scale; + + /* x-axis scale */ + scale = len_v3(pchan->pose_mat[0]); + mul_v3_fl(poseMat[0], scale); + /* z-axis scale */ + scale = len_v3(pchan->pose_mat[2]); + mul_v3_fl(poseMat[2], scale); + break; + } + case CONSTRAINT_SPLINEIK_XZS_INVERSE: + { + /* old 'volume preservation' method using the inverse scale */ + float scale; + + /* calculate volume preservation factor which is + * basically the inverse of the y-scaling factor + */ + if (fabsf(scaleFac) != 0.0f) { + scale = 1.0f / fabsf(scaleFac); + + /* we need to clamp this within sensible values */ + /* NOTE: these should be fine for now, but should get sanitised in future */ + CLAMP(scale, 0.0001f, 100000.0f); + } + else + scale = 1.0f; + + /* apply the scaling */ + mul_v3_fl(poseMat[0], scale); + mul_v3_fl(poseMat[2], scale); + break; + } + case CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC: + { + /* improved volume preservation based on the Stretch To constraint */ + float final_scale; + + /* as the basis for volume preservation, we use the inverse scale factor... */ + if (fabsf(scaleFac) != 0.0f) { + /* NOTE: The method here is taken wholesale from the Stretch To constraint */ + float bulge = powf(1.0f / fabsf(scaleFac), ikData->bulge); + + if (bulge > 1.0f) { + if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MAX) { + float bulge_max = max_ff(ikData->bulge_max, 1.0f); + float hard = min_ff(bulge, bulge_max); + + float range = bulge_max - 1.0f; + float scale = (range > 0.0f) ? 1.0f / range : 0.0f; + float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (float)M_PI_2; + + bulge = interpf(soft, hard, ikData->bulge_smooth); + } + } + if (bulge < 1.0f) { + if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MIN) { + float bulge_min = CLAMPIS(ikData->bulge_min, 0.0f, 1.0f); + float hard = max_ff(bulge, bulge_min); + + float range = 1.0f - bulge_min; + float scale = (range > 0.0f) ? 1.0f / range : 0.0f; + float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (float)M_PI_2; + + bulge = interpf(soft, hard, ikData->bulge_smooth); + } + } + + /* compute scale factor for xz axes from this value */ + final_scale = sqrtf(bulge); + } + else { + /* no scaling, so scale factor is simple */ + final_scale = 1.0f; + } + + /* apply the scaling (assuming normalised scale) */ + mul_v3_fl(poseMat[0], final_scale); + mul_v3_fl(poseMat[2], final_scale); + break; + } + } + + /* finally, multiply the x and z scaling by the radius of the curve too, + * to allow automatic scales to get tweaked still + */ + if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_CURVERAD) == 0) { + mul_v3_fl(poseMat[0], radius); + mul_v3_fl(poseMat[2], radius); + } + } + + /* step 5: set the location of the bone in the matrix */ + if (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) { + /* when the 'no-root' option is affected, the chain can retain + * the shape but be moved elsewhere + */ + copy_v3_v3(poseHead, pchan->pose_head); + } + else if (tree->con->enforce < 1.0f) { + /* when the influence is too low + * - blend the positions for the 'root' bone + * - stick to the parent for any other + */ + if (pchan->parent) { + copy_v3_v3(poseHead, pchan->pose_head); + } + else { + /* FIXME: this introduces popping artifacts when we reach 0.0 */ + interp_v3_v3v3(poseHead, pchan->pose_head, poseHead, tree->con->enforce); + } + } + copy_v3_v3(poseMat[3], poseHead); + + /* finally, store the new transform */ + copy_m4_m4(pchan->pose_mat, poseMat); + copy_v3_v3(pchan->pose_head, poseHead); + + /* recalculate tail, as it's now outdated after the head gets adjusted above! */ + BKE_pose_where_is_bone_tail(pchan); + + /* done! */ + pchan->flag |= POSE_DONE; +} + +/* Evaluate the chain starting from the nominated bone */ +static void splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime) +{ + tSplineIK_Tree *tree; + + /* for each pose-tree, execute it if it is spline, otherwise just free it */ + while ((tree = pchan_root->siktree.first) != NULL) { + int i; + + /* walk over each bone in the chain, calculating the effects of spline IK + * - the chain is traversed in the opposite order to storage order (i.e. parent to children) + * so that dependencies are correct + */ + for (i = tree->chainlen - 1; i >= 0; i--) { + bPoseChannel *pchan = tree->chain[i]; + splineik_evaluate_bone(tree, scene, ob, pchan, i, ctime); + } + + /* free the tree info specific to SplineIK trees now */ + if (tree->chain) + MEM_freeN(tree->chain); + if (tree->free_points) + MEM_freeN(tree->points); + + /* free this tree */ + BLI_freelinkN(&pchan_root->siktree, tree); + } +} + +void BKE_pose_splineik_init_tree(Scene *scene, Object *ob, float ctime) +{ + splineik_init_tree(scene, ob, ctime); +} + +void BKE_splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime) +{ + splineik_execute_tree(scene, ob, pchan_root, ctime); +} diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 5b29187e7cd..d5f070bc770 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -3046,147 +3046,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx, } if (ob->recalc & OB_RECALC_DATA) { - ID *data_id = (ID *)ob->data; - AnimData *adt = BKE_animdata_from_id(data_id); - Key *key; - float ctime = BKE_scene_frame_get(scene); - - if (G.debug & G_DEBUG_DEPSGRAPH) - printf("recalcdata %s\n", ob->id.name + 2); - - if (adt) { - /* evaluate drivers - datalevel */ - /* XXX: for mesh types, should we push this to derivedmesh instead? */ - BKE_animsys_evaluate_animdata(scene, data_id, adt, ctime, ADT_RECALC_DRIVERS); - } - - key = BKE_key_from_object(ob); - if (key && key->block.first) { - if (!(ob->shapeflag & OB_SHAPE_LOCK)) - BKE_animsys_evaluate_animdata(scene, &key->id, key->adt, ctime, ADT_RECALC_DRIVERS); - } - - /* includes all keys and modifiers */ - switch (ob->type) { - case OB_MESH: - { - BMEditMesh *em = (ob == scene->obedit) ? BKE_editmesh_from_object(ob) : NULL; - uint64_t data_mask = scene->customdata_mask | CD_MASK_BAREMESH; -#ifdef WITH_FREESTYLE - /* make sure Freestyle edge/face marks appear in DM for render (see T40315) */ - if (eval_ctx->mode != DAG_EVAL_VIEWPORT) { - data_mask |= CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE; - } -#endif - if (em) { - makeDerivedMesh(scene, ob, em, data_mask, 0); /* was CD_MASK_BAREMESH */ - } - else { - makeDerivedMesh(scene, ob, NULL, data_mask, 0); - } - break; - } - case OB_ARMATURE: - if (ob->id.lib && ob->proxy_from) { - if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) { - printf("Proxy copy error, lib Object: %s proxy Object: %s\n", - ob->id.name + 2, ob->proxy_from->id.name + 2); - } - } - else { - BKE_pose_where_is(scene, ob); - } - break; - - case OB_MBALL: - BKE_displist_make_mball(eval_ctx, scene, ob); - break; - - case OB_CURVE: - case OB_SURF: - case OB_FONT: - BKE_displist_make_curveTypes(scene, ob, 0); - break; - - case OB_LATTICE: - BKE_lattice_modifiers_calc(scene, ob); - break; - - case OB_EMPTY: - if (ob->empty_drawtype == OB_EMPTY_IMAGE && ob->data) - if (BKE_image_is_animated(ob->data)) - BKE_image_user_check_frame_calc(ob->iuser, (int)ctime, 0); - break; - } - - /* related materials */ - /* XXX: without depsgraph tagging, this will always need to be run, which will be slow! - * However, not doing anything (or trying to hack around this lack) is not an option - * anymore, especially due to Cycles [#31834] - */ - if (ob->totcol) { - int a; - - for (a = 1; a <= ob->totcol; a++) { - Material *ma = give_current_material(ob, a); - - if (ma) { - /* recursively update drivers for this material */ - material_drivers_update(scene, ma, ctime); - } - } - } - else if (ob->type == OB_LAMP) - lamp_drivers_update(scene, ob->data, ctime); - - /* particles */ - if (ob != scene->obedit && ob->particlesystem.first) { - ParticleSystem *tpsys, *psys; - DerivedMesh *dm; - ob->transflag &= ~OB_DUPLIPARTS; - - psys = ob->particlesystem.first; - while (psys) { - /* ensure this update always happens even if psys is disabled */ - if (psys->recalc & PSYS_RECALC_TYPE) { - psys_changed_type(ob, psys); - } - - if (psys_check_enabled(ob, psys)) { - /* check use of dupli objects here */ - if (psys->part && (psys->part->draw_as == PART_DRAW_REND || eval_ctx->mode == DAG_EVAL_RENDER) && - ((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob) || - (psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group))) - { - ob->transflag |= OB_DUPLIPARTS; - } - - particle_system_update(scene, ob, psys); - psys = psys->next; - } - else if (psys->flag & PSYS_DELETE) { - tpsys = psys->next; - BLI_remlink(&ob->particlesystem, psys); - psys_free(ob, psys); - psys = tpsys; - } - else - psys = psys->next; - } - - if (eval_ctx->mode == DAG_EVAL_RENDER && ob->transflag & OB_DUPLIPARTS) { - /* this is to make sure we get render level duplis in groups: - * the derivedmesh must be created before init_render_mesh, - * since object_duplilist does dupliparticles before that */ - dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); - dm->release(dm); - - for (psys = ob->particlesystem.first; psys; psys = psys->next) - psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated; - } - } - - /* quick cache removed */ + BKE_object_handle_data_update(eval_ctx, scene, ob); } ob->recalc &= ~OB_RECALC_ALL; diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c new file mode 100644 index 00000000000..196c85831e0 --- /dev/null +++ b/source/blender/blenkernel/intern/object_update.c @@ -0,0 +1,204 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 20014 by Blender Foundation. + * All rights reserved. + * + * Contributor(s): Sergey Sharybin. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/object_update.c + * \ingroup bke + */ + +#include "DNA_anim_types.h" +#include "DNA_constraint_types.h" +#include "DNA_group_types.h" +#include "DNA_key_types.h" +#include "DNA_material_types.h" +#include "DNA_scene_types.h" + +#include "BLI_blenlib.h" +#include "BLI_utildefines.h" +#include "BLI_math.h" + +#include "BKE_global.h" +#include "BKE_armature.h" +#include "BKE_action.h" +#include "BKE_constraint.h" +#include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" +#include "BKE_animsys.h" +#include "BKE_displist.h" +#include "BKE_effect.h" +#include "BKE_key.h" +#include "BKE_lamp.h" +#include "BKE_lattice.h" +#include "BKE_editmesh.h" +#include "BKE_object.h" +#include "BKE_particle.h" +#include "BKE_scene.h" +#include "BKE_material.h" +#include "BKE_image.h" + +void BKE_object_handle_data_update(EvaluationContext *eval_ctx, + Scene *scene, + Object *ob) +{ + ID *data_id = (ID *)ob->data; + AnimData *adt = BKE_animdata_from_id(data_id); + Key *key; + float ctime = BKE_scene_frame_get(scene); + + if (G.debug & G_DEBUG_DEPSGRAPH) + printf("recalcdata %s\n", ob->id.name + 2); + + /* TODO(sergey): Only used by legacy depsgraph. */ + if (adt) { + /* evaluate drivers - datalevel */ + /* XXX: for mesh types, should we push this to derivedmesh instead? */ + BKE_animsys_evaluate_animdata(scene, data_id, adt, ctime, ADT_RECALC_DRIVERS); + } + + /* TODO(sergey): Only used by legacy depsgraph. */ + key = BKE_key_from_object(ob); + if (key && key->block.first) { + if (!(ob->shapeflag & OB_SHAPE_LOCK)) + BKE_animsys_evaluate_animdata(scene, &key->id, key->adt, ctime, ADT_RECALC_DRIVERS); + } + + /* includes all keys and modifiers */ + switch (ob->type) { + case OB_MESH: + { + BMEditMesh *em = (ob == scene->obedit) ? BKE_editmesh_from_object(ob) : NULL; + uint64_t data_mask = scene->customdata_mask | CD_MASK_BAREMESH; +#ifdef WITH_FREESTYLE + /* make sure Freestyle edge/face marks appear in DM for render (see T40315) */ + if (eval_ctx->mode != DAG_EVAL_VIEWPORT) { + data_mask |= CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE; + } +#endif + if (em) { + makeDerivedMesh(scene, ob, em, data_mask, 0); /* was CD_MASK_BAREMESH */ + } + else { + makeDerivedMesh(scene, ob, NULL, data_mask, 0); + } + break; + } + case OB_ARMATURE: + if (ob->id.lib && ob->proxy_from) { + if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) { + printf("Proxy copy error, lib Object: %s proxy Object: %s\n", + ob->id.name + 2, ob->proxy_from->id.name + 2); + } + } + else { + BKE_pose_where_is(scene, ob); + } + break; + + case OB_MBALL: + BKE_displist_make_mball(eval_ctx, scene, ob); + break; + + case OB_CURVE: + case OB_SURF: + case OB_FONT: + BKE_displist_make_curveTypes(scene, ob, 0); + break; + + case OB_LATTICE: + BKE_lattice_modifiers_calc(scene, ob); + break; + + case OB_EMPTY: + if (ob->empty_drawtype == OB_EMPTY_IMAGE && ob->data) + if (BKE_image_is_animated(ob->data)) + BKE_image_user_check_frame_calc(ob->iuser, (int)ctime, 0); + break; + } + + /* related materials */ + /* XXX: without depsgraph tagging, this will always need to be run, which will be slow! + * However, not doing anything (or trying to hack around this lack) is not an option + * anymore, especially due to Cycles [#31834] + */ + if (ob->totcol) { + int a; + for (a = 1; a <= ob->totcol; a++) { + Material *ma = give_current_material(ob, a); + if (ma) { + /* recursively update drivers for this material */ + material_drivers_update(scene, ma, ctime); + } + } + } + else if (ob->type == OB_LAMP) + lamp_drivers_update(scene, ob->data, ctime); + + /* particles */ + if (ob != scene->obedit && ob->particlesystem.first) { + ParticleSystem *tpsys, *psys; + DerivedMesh *dm; + ob->transflag &= ~OB_DUPLIPARTS; + psys = ob->particlesystem.first; + while (psys) { + /* ensure this update always happens even if psys is disabled */ + if (psys->recalc & PSYS_RECALC_TYPE) { + psys_changed_type(ob, psys); + } + + if (psys_check_enabled(ob, psys)) { + /* check use of dupli objects here */ + if (psys->part && (psys->part->draw_as == PART_DRAW_REND || eval_ctx->mode == DAG_EVAL_RENDER) && + ((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob) || + (psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group))) + { + ob->transflag |= OB_DUPLIPARTS; + } + + particle_system_update(scene, ob, psys); + psys = psys->next; + } + else if (psys->flag & PSYS_DELETE) { + tpsys = psys->next; + BLI_remlink(&ob->particlesystem, psys); + psys_free(ob, psys); + psys = tpsys; + } + else + psys = psys->next; + } + + if (eval_ctx->mode == DAG_EVAL_RENDER && ob->transflag & OB_DUPLIPARTS) { + /* this is to make sure we get render level duplis in groups: + * the derivedmesh must be created before init_render_mesh, + * since object_duplilist does dupliparticles before that */ + dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); + dm->release(dm); + + for (psys = ob->particlesystem.first; psys; psys = psys->next) + psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated; + } + } + + /* quick cache removed */ +} -- cgit v1.2.3 From 87fd1666542adf1507d78bf96574fd56a8be3af8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 12 May 2015 13:13:36 +0500 Subject: Depsgraph: Add utility function to tag pose for recalc Currently this function only tags pose itself, totally matching previous behavior. But this will be needed in the future once new dependency graph is landed, because of it's granular nature which relies on the fact that pose channels are all up to date when building the graph. Should be no functional changes so far. --- source/blender/blenkernel/BKE_action.h | 3 +++ source/blender/blenkernel/intern/action.c | 6 ++++++ source/blender/blenloader/intern/readfile.c | 3 ++- source/blender/blenloader/intern/versioning_legacy.c | 5 +++-- source/blender/editors/armature/pose_edit.c | 4 ++-- source/blender/editors/interface/interface_templates.c | 3 ++- source/blender/editors/object/object_add.c | 3 ++- source/blender/editors/object/object_constraint.c | 14 +++++++------- source/blender/makesrna/intern/rna_pose.c | 4 ++-- 9 files changed, 29 insertions(+), 16 deletions(-) diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 6fd490723ab..fdb465f7105 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -198,6 +198,9 @@ bool BKE_pose_copy_result(struct bPose *to, struct bPose *from); /* clear all transforms */ void BKE_pose_rest(struct bPose *pose); +/* Tag pose for recalc. Also tag all related data to be recalc. */ +void BKE_pose_tag_recalc(struct Main *bmain, struct bPose *pose); + #ifdef __cplusplus }; #endif diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 9ce198bd687..708c64f8ffc 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1317,6 +1317,12 @@ bool BKE_pose_copy_result(bPose *to, bPose *from) return true; } +/* Tag pose for recalc. Also tag all related data to be recalc. */ +void BKE_pose_tag_recalc(Main *UNUSED(bmain), bPose *pose) +{ + pose->flag |= POSE_RECALC; +} + /* For the calculation of the effects of an Action at the given frame on an object * This is currently only used for the Action Constraint */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index a4dd2264816..6634767d412 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -111,6 +111,7 @@ #include "BLF_translation.h" +#include "BKE_action.h" #include "BKE_armature.h" #include "BKE_brush.h" #include "BKE_cloth.h" @@ -3009,7 +3010,7 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose) if (rebuild) { DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); - pose->flag |= POSE_RECALC; + BKE_pose_tag_recalc(bmain, pose); } } diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 94ad348bfcf..dab22d414d8 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -77,6 +77,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BKE_action.h" #include "BKE_armature.h" #include "BKE_colortools.h" #include "BKE_constraint.h" @@ -1950,7 +1951,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) /* btw. armature_rebuild_pose is further only called on leave editmode */ if (ob->type == OB_ARMATURE) { if (ob->pose) - ob->pose->flag |= POSE_RECALC; + BKE_pose_tag_recalc(main, ob->pose); /* cannot call stuff now (pointers!), done in setup_app_data */ ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; @@ -2074,7 +2075,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) data->rootbone = -1; /* update_pose_etc handles rootbone == -1 */ - ob->pose->flag |= POSE_RECALC; + BKE_pose_tag_recalc(main, ob->pose); } } } diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index bc900315247..e87c324d7ec 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -436,7 +436,7 @@ static void pose_copy_menu(Scene *scene) pchan->constflag |= pchanact->constflag; if (ob->pose) - ob->pose->flag |= POSE_RECALC; + BKE_pose_tag_recalc(bmain, ob->pose); } break; case 6: /* Transform Locks */ @@ -550,7 +550,7 @@ static void pose_copy_menu(Scene *scene) BKE_pose_update_constraint_flags(ob->pose); /* we could work out the flags but its simpler to do this */ if (ob->pose) - ob->pose->flag |= POSE_RECALC; + BKE_pose_tag_recalc(bmain, ob->pose); } DAG_id_tag_update(&ob->id, OB_RECALC_DATA); // and all its relations diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 9a34e4be980..ccbd30d1230 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1074,7 +1074,8 @@ static void do_constraint_panels(bContext *C, void *ob_pt, int event) case B_CONSTRAINT_CHANGETARGET: { Main *bmain = CTX_data_main(C); - if (ob->pose) ob->pose->flag |= POSE_RECALC; /* checks & sorts pose channels */ + if (ob->pose) + BKE_pose_tag_recalc(bmain, ob->pose); /* checks & sorts pose channels */ DAG_relations_tag_update(bmain); break; } diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 27d77f0635e..b8c66fdd109 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -57,6 +57,7 @@ #include "BLF_translation.h" +#include "BKE_action.h" #include "BKE_anim.h" #include "BKE_animsys.h" #include "BKE_armature.h" @@ -2082,7 +2083,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base case OB_ARMATURE: DAG_id_tag_update(&obn->id, OB_RECALC_DATA); if (obn->pose) - obn->pose->flag |= POSE_RECALC; + BKE_pose_tag_recalc(bmain, obn->pose); if (dupflag & USER_DUP_ARM) { ID_NEW_US2(obn->data) else { diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index f214741467f..22db0936e39 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -1194,9 +1194,9 @@ void ED_object_constraint_update(Object *ob) DAG_id_tag_update(&ob->id, OB_RECALC_OB); } -static void object_pose_tag_update(Object *ob) +static void object_pose_tag_update(Main *bmain, Object *ob) { - ob->pose->flag |= POSE_RECALC; /* Checks & sort pose channels. */ + BKE_pose_tag_recalc(bmain, ob->pose); /* Checks & sort pose channels. */ if (ob->proxy && ob->adt) { /* We need to make use of ugly POSE_ANIMATION_WORKAROUND here too, else anim data are not reloaded * after calling `BKE_pose_rebuild()`, which causes T43872. @@ -1212,7 +1212,7 @@ void ED_object_constraint_dependency_update(Main *bmain, Object *ob) ED_object_constraint_update(ob); if (ob->pose) { - object_pose_tag_update(ob); + object_pose_tag_update(bmain, ob); } DAG_relations_tag_update(bmain); } @@ -1236,7 +1236,7 @@ void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstr ED_object_constraint_tag_update(ob, con); if (ob->pose) { - object_pose_tag_update(ob); + object_pose_tag_update(bmain, ob); } DAG_relations_tag_update(bmain); } @@ -1484,8 +1484,8 @@ static int pose_constraint_copy_exec(bContext *C, wmOperator *op) BKE_constraints_copy(&chan->constraints, &pchan->constraints, true); /* update flags (need to add here, not just copy) */ chan->constflag |= pchan->constflag; - - ob->pose->flag |= POSE_RECALC; + + BKE_pose_tag_recalc(bmain, ob->pose); DAG_id_tag_update((ID *)ob, OB_RECALC_DATA); } } @@ -1796,7 +1796,7 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase DAG_relations_tag_update(bmain); if ((ob->type == OB_ARMATURE) && (pchan)) { - ob->pose->flag |= POSE_RECALC; /* sort pose channels */ + BKE_pose_tag_recalc(bmain, ob->pose); /* sort pose channels */ if (BKE_constraints_proxylocked_owner(ob, pchan) && ob->adt) { /* We need to make use of ugly POSE_ANIMATION_WORKAROUND here too, else anim data are not reloaded * after calling `BKE_pose_rebuild()`, which causes T43872. diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 0428f5d8a9f..3ff51423e9a 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -231,7 +231,7 @@ static void rna_Pose_ik_solver_update(Main *bmain, Scene *UNUSED(scene), Pointer Object *ob = ptr->id.data; bPose *pose = ptr->data; - pose->flag |= POSE_RECALC; /* checks & sorts pose channels */ + BKE_pose_tag_recalc(bmain, pose); /* checks & sorts pose channels */ DAG_relations_tag_update(bmain); BKE_pose_update_constraint_flags(pose); @@ -356,7 +356,7 @@ static void rna_Itasc_update_rebuild(Main *bmain, Scene *scene, PointerRNA *ptr) Object *ob = ptr->id.data; bPose *pose = ob->pose; - pose->flag |= POSE_RECALC; /* checks & sorts pose channels */ + BKE_pose_tag_recalc(bmain, pose); /* checks & sorts pose channels */ rna_Itasc_update(bmain, scene, ptr); } -- cgit v1.2.3 From 31f0c27ae7d6f45cfde71cca8c4f791a089452a5 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 12 May 2015 13:29:00 +0500 Subject: Depsgraph: Add additional relations/id update tags This calls are not strictly speaking needed for the old dependency graph, but due to more granular nature of upcoming depsgraph more actions requires update of relations of IDs. On the one hand this extra tags could be wrapped with if() statements, but on the other hand it makes sense to keep tag in sync so it's clear if some issue is caused by missing/extra tag or by depsgraph itself. --- source/blender/editors/animation/anim_channels_edit.c | 4 +++- source/blender/editors/animation/anim_deps.c | 4 +++- source/blender/editors/animation/drivers.c | 5 +++-- source/blender/editors/animation/keyframing.c | 4 ++++ source/blender/editors/object/object_constraint.c | 5 ++++- source/blender/editors/object/object_edit.c | 13 ++++++++++--- source/blender/editors/object/object_modifier.c | 9 ++++++--- source/blender/editors/space_node/node_draw.c | 9 ++++++++- .../intern/blender_interface/BlenderStrokeRenderer.cpp | 4 ++++ source/blender/makesrna/intern/rna_animation.c | 1 + source/blender/makesrna/intern/rna_camera.c | 9 ++++++++- source/blender/makesrna/intern/rna_object.c | 1 + 12 files changed, 55 insertions(+), 13 deletions(-) diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 67485248bf1..fd7551abab3 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -34,6 +34,7 @@ #include "MEM_guardedalloc.h" +#include "BKE_depsgraph.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_listbase.h" @@ -1707,7 +1708,8 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op)) /* send notifier that things have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + DAG_relations_tag_update(CTX_data_main(C)); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index eb57907c9ec..a38f5dbc8ea 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -73,8 +73,10 @@ void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale) /* tag AnimData for refresh so that other views will update in realtime with these changes */ adt = BKE_animdata_from_id(id); - if (adt) + if (adt) { adt->recalc |= ADT_RECALC_ANIM; + DAG_id_tag_update(id, OB_RECALC_TIME); + } /* update data */ fcu = (ale->datatype == ALE_FCURVE) ? ale->key_data : NULL; diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 08e0daf8eb9..b2a34d7c317 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -42,6 +42,7 @@ #include "DNA_texture_types.h" #include "BKE_animsys.h" +#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_context.h" #include "BKE_report.h" @@ -450,7 +451,7 @@ static int add_driver_button_exec(bContext *C, wmOperator *op) if (success) { /* send updates */ UI_context_update_anim_flag(C); - + DAG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX } @@ -504,7 +505,7 @@ static int remove_driver_button_exec(bContext *C, wmOperator *op) if (success) { /* send updates */ UI_context_update_anim_flag(C); - + DAG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX } diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 092408d7de5..cd7a326ffd5 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -152,6 +152,10 @@ bAction *verify_adt_action(ID *id, short add) * to the wrong places */ adt->action->idroot = GS(id->name); + + /* tag depsgraph to be rebuilt to include time dependency */ + /* XXX: we probably should have bmain passed down, but that involves altering too many API's */ + DAG_relations_tag_update(G.main); } /* return the action */ diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 22db0936e39..e14674ef517 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -1260,7 +1260,10 @@ static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op)) /* there's no active constraint now, so make sure this is the case */ BKE_constraints_active_set(&ob->constraints, NULL); ED_object_constraint_update(ob); /* needed to set the flags on posebones correctly */ - + + /* relatiols */ + DAG_relations_tag_update(CTX_data_main(C)); + /* notifiers */ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob); diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 706ca5fbdfe..5e2bd438031 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -65,6 +65,7 @@ #include "BKE_curve.h" #include "BKE_effect.h" #include "BKE_depsgraph.h" +#include "BKE_global.h" #include "BKE_image.h" #include "BKE_lattice.h" #include "BKE_library.h" @@ -318,7 +319,7 @@ void OBJECT_OT_hide_render_set(wmOperatorType *ot) * Load EditMode data back into the object, * optionally freeing the editmode data. */ -static bool ED_object_editmode_load_ex(Object *obedit, const bool freedata) +static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool freedata) { if (obedit == NULL) { return false; @@ -348,6 +349,11 @@ static bool ED_object_editmode_load_ex(Object *obedit, const bool freedata) ED_armature_from_edit(obedit->data); if (freedata) ED_armature_edit_free(obedit->data); + /* TODO(sergey): Pose channels might have been changed, so need + * to inform dependency graph about this. But is it really the + * best place to do this? + */ + DAG_relations_tag_update(bmain); } else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { load_editNurb(obedit); @@ -376,7 +382,8 @@ static bool ED_object_editmode_load_ex(Object *obedit, const bool freedata) bool ED_object_editmode_load(Object *obedit) { - return ED_object_editmode_load_ex(obedit, false); + /* TODO(sergey): use proper main here? */ + return ED_object_editmode_load_ex(G.main, obedit, false); } void ED_object_editmode_exit(bContext *C, int flag) @@ -389,7 +396,7 @@ void ED_object_editmode_exit(bContext *C, int flag) if (flag & EM_WAITCURSOR) waitcursor(1); - if (ED_object_editmode_load_ex(obedit, freedata) == false) { + if (ED_object_editmode_load_ex(CTX_data_main(C), obedit, freedata) == false) { /* in rare cases (background mode) its possible active object * is flagged for editmode, without 'obedit' being set [#35489] */ if (UNLIKELY(scene->basact && (scene->basact->object->mode & OB_MODE_EDIT))) { diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 1cee54c33fa..c88f1257936 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -152,10 +152,10 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc ob->pd = object_add_collision_fields(0); ob->pd->deflect = 1; - DAG_relations_tag_update(bmain); } - else if (type == eModifierType_Surface) - DAG_relations_tag_update(bmain); + else if (type == eModifierType_Surface) { + /* pass */ + } else if (type == eModifierType_Multires) { /* set totlvl from existing MDISPS layer if object already had it */ multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob); @@ -172,6 +172,7 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc } DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DAG_relations_tag_update(bmain); return new_md; } @@ -319,6 +320,8 @@ static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md, ob->mode &= ~OB_MODE_PARTICLE_EDIT; } + DAG_relations_tag_update(bmain); + BLI_remlink(&ob->modifiers, md); modifier_free(md); diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index e27cb041dc5..c89bf8dd13a 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -123,7 +123,14 @@ void ED_node_tag_update_id(ID *id) bNodeTree *ntree = node_tree_from_ID(id); if (id == NULL || ntree == NULL) return; - + + /* TODO(sergey): With the new dependency graph it + * should be just enough to ony tag ntree itself, + * all the users of this tree will have update + * flushed from the tree, + */ + DAG_id_tag_update(&ntree->id, 0); + if (ntree->type == NTREE_SHADER) { DAG_id_tag_update(id, 0); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index 1ddc311b1ae..cfa0c45b1e3 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -127,6 +127,7 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str // Camera Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, OB_CAMERA, NULL); + DAG_relations_tag_update(freestyle_bmain); Camera *camera = (Camera *)object_camera->data; camera->type = CAM_ORTHO; @@ -506,6 +507,7 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const // If still no material, create one if (!has_mat) { Material *ma = BKE_material_add(freestyle_bmain, "stroke_material"); + DAG_relations_tag_update(freestyle_bmain); ma->mode |= MA_VERTEXCOLP; ma->mode |= MA_TRANSP; ma->mode |= MA_SHLESS; @@ -668,6 +670,7 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex) { #if 0 Object *object_mesh = BKE_object_add(freestyle_bmain, freestyle_scene, OB_MESH); + DAG_relations_tag_update(freestyle_bmain); #else Object *object_mesh = NewMesh(); #endif @@ -938,6 +941,7 @@ Object *BlenderStrokeRenderer::NewMesh() const ob->lay = 1; base = BKE_scene_base_add(freestyle_scene, ob); + DAG_relations_tag_update(freestyle_bmain); #if 0 BKE_scene_base_deselect_all(scene); BKE_scene_base_select(scene, base); diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index df1e6dd55dd..ac30c615438 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -112,6 +112,7 @@ static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value) adt = BKE_animdata_from_id(ownerId); if (adt) { adt->recalc |= ADT_RECALC_ANIM; + DAG_id_tag_update(ownerId, OB_RECALC_TIME); } } diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index 2baaa5f7cec..16f74a05f7b 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -87,6 +87,13 @@ static void rna_Camera_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointer DAG_id_tag_update(&camera->id, 0); } +static void rna_Camera_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) +{ + Camera *camera = (Camera *)ptr->id.data; + DAG_relations_tag_update(bmain); + DAG_id_tag_update(&camera->id, 0); +} + #else static void rna_def_camera_stereo_data(BlenderRNA *brna) @@ -356,7 +363,7 @@ void RNA_def_camera(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "dof_ob"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "DOF Object", "Use this object to define the depth of field focal point"); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dependency_update"); prop = RNA_def_property(srna, "gpu_dof", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "GPUDOFSettings"); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 8bb3e9c265b..2ef5c6ec12e 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -949,6 +949,7 @@ static void rna_MaterialSlot_update(Main *bmain, Scene *scene, PointerRNA *ptr) WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, ptr->id.data); WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL); + DAG_relations_tag_update(bmain); } static char *rna_MaterialSlot_path(PointerRNA *ptr) -- cgit v1.2.3 From 08d87514d3bf33f8b4770e9213ad3dcddcda9b26 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 12 May 2015 13:38:55 +0500 Subject: Depsgraph: Add utility function to check whether modifier depends on time Currently unused, based on the code from old depsgraph.c. The purpose is to re-sue the code over old and new depsgraph in an easy way. --- source/blender/blenkernel/BKE_object.h | 3 ++ source/blender/blenkernel/intern/object.c | 48 +++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index d287eb4a057..ec90cc74082 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -47,6 +47,7 @@ struct MovieClip; struct Main; struct RigidBodyWorld; struct HookModifierData; +struct ModifierData; void BKE_object_workob_clear(struct Object *workob); void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struct Object *workob); @@ -232,6 +233,8 @@ void BKE_object_groups_clear(struct Scene *scene, struct Base *base, struct KDTree *BKE_object_as_kdtree(struct Object *ob, int *r_tot); +bool BKE_object_modifier_use_time(struct Object *ob, struct ModifierData *md); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index d5f070bc770..8dfc7e0e8cd 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -3891,3 +3891,51 @@ KDTree *BKE_object_as_kdtree(Object *ob, int *r_tot) *r_tot = tot; return tree; } + +bool BKE_object_modifier_use_time(Object *ob, ModifierData *md) +{ + if (modifier_dependsOnTime(md)) { + return true; + } + + /* Check whether modifier is animated. */ + /* TODO: this should be handled as part of build_animdata() -- Aligorith */ + if (ob->adt) { + AnimData *adt = ob->adt; + FCurve *fcu; + + char pattern[MAX_NAME + 10]; + /* TODO(sergey): Escape modifier name. */ + BLI_snprintf(pattern, sizeof(pattern), "modifiers[%s", md->name); + + /* action - check for F-Curves with paths containing 'modifiers[' */ + if (adt->action) { + for (fcu = (FCurve *)adt->action->curves.first; + fcu != NULL; + fcu = (FCurve *)fcu->next) + { + if (fcu->rna_path && strstr(fcu->rna_path, pattern)) + return true; + } + } + + /* This here allows modifier properties to get driven and still update properly + * + * Workaround to get [#26764] (e.g. subsurf levels not updating when animated/driven) + * working, without the updating problems ([#28525] [#28690] [#28774] [#28777]) caused + * by the RNA updates cache introduced in r.38649 + */ + for (fcu = (FCurve *)adt->drivers.first; + fcu != NULL; + fcu = (FCurve *)fcu->next) + { + if (fcu->rna_path && strstr(fcu->rna_path, pattern)) + return true; + } + + /* XXX: also, should check NLA strips, though for now assume that nobody uses + * that and we can omit that for performance reasons... */ + } + + return false; +} -- cgit v1.2.3 From 051688b34c60a5eec7cc0227d0bda26b916d1cb8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 12 May 2015 14:06:31 +0500 Subject: Depsgraph: Make ob_get_parent_matrix() more public and reusable Currently still only used from object.c, but in the next commit it'll be also used from granular object update callbacks. --- source/blender/blenkernel/BKE_object.h | 1 + source/blender/blenkernel/intern/object.c | 11 +++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index ec90cc74082..c270ebbda7d 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -125,6 +125,7 @@ void BKE_object_matrix_local_get(struct Object *ob, float mat[4][4]); bool BKE_object_pose_context_check(struct Object *ob); struct Object *BKE_object_pose_armature_get(struct Object *ob); +void BKE_object_get_parent_matrix(struct Scene *scene, struct Object *ob, struct Object *par, float parentmat[4][4]); void BKE_object_where_is_calc(struct Scene *scene, struct Object *ob); void BKE_object_where_is_calc_ex(struct Scene *scene, struct RigidBodyWorld *rbw, struct Object *ob, float r_originmat[3][3]); void BKE_object_where_is_calc_time(struct Scene *scene, struct Object *ob, float ctime); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 8dfc7e0e8cd..e04f1b19dc5 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2052,14 +2052,12 @@ void BKE_object_to_mat4(Object *ob, float mat[4][4]) add_v3_v3v3(mat[3], ob->loc, ob->dloc); } -static void ob_get_parent_matrix(Scene *scene, Object *ob, Object *par, float parentmat[4][4]); - void BKE_object_matrix_local_get(struct Object *ob, float mat[4][4]) { if (ob->parent) { float par_imat[4][4]; - ob_get_parent_matrix(NULL, ob, ob->parent, par_imat); + BKE_object_get_parent_matrix(NULL, ob, ob->parent, par_imat); invert_m4(par_imat); mul_m4_m4m4(mat, par_imat, ob->obmat); } @@ -2351,7 +2349,8 @@ static void ob_parvert3(Object *ob, Object *par, float mat[4][4]) } } -static void ob_get_parent_matrix(Scene *scene, Object *ob, Object *par, float parentmat[4][4]) + +void BKE_object_get_parent_matrix(Scene *scene, Object *ob, Object *par, float parentmat[4][4]) { float tmat[4][4]; float vec[3]; @@ -2408,7 +2407,7 @@ static void solve_parenting(Scene *scene, Object *ob, Object *par, float obmat[4 if (ob->partype & PARSLOW) copy_m4_m4(slowmat, obmat); - ob_get_parent_matrix(scene, ob, par, totmat); + BKE_object_get_parent_matrix(scene, ob, par, totmat); /* total */ mul_m4_m4m4(tmat, totmat, ob->parentinv); @@ -2566,7 +2565,7 @@ void BKE_object_apply_mat4(Object *ob, float mat[4][4], const bool use_compat, c if (use_parent && ob->parent) { float rmat[4][4], diff_mat[4][4], imat[4][4], parent_mat[4][4]; - ob_get_parent_matrix(NULL, ob, ob->parent, parent_mat); + BKE_object_get_parent_matrix(NULL, ob, ob->parent, parent_mat); mul_m4_m4m4(diff_mat, parent_mat, ob->parentinv); invert_m4_m4(imat, diff_mat); -- cgit v1.2.3 From a09341469ee3874a0874492a7dcad79c2b99179a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 12 May 2015 13:57:11 +0500 Subject: Depsgraph: Add evaluation callbacks for granular nodes update This commit only adds callbacks which then later be used with major dependency graph commit, keeping the upcoming commit more clean to follow. Should be no functional changes so far still. --- source/blender/blenkernel/BKE_animsys.h | 12 ++ source/blender/blenkernel/BKE_armature.h | 44 +++++++ source/blender/blenkernel/BKE_curve.h | 10 ++ source/blender/blenkernel/BKE_depsgraph.h | 1 + source/blender/blenkernel/BKE_lattice.h | 7 + source/blender/blenkernel/BKE_mball.h | 7 + source/blender/blenkernel/BKE_mesh.h | 7 + source/blender/blenkernel/BKE_object.h | 22 ++++ source/blender/blenkernel/BKE_particle.h | 8 ++ source/blender/blenkernel/BKE_rigidbody.h | 15 +++ source/blender/blenkernel/intern/anim_sys.c | 67 +++++++++- source/blender/blenkernel/intern/armature.c | 44 +++++++ source/blender/blenkernel/intern/armature_update.c | 146 +++++++++++++++++++++ source/blender/blenkernel/intern/curve.c | 24 ++++ source/blender/blenkernel/intern/lattice.c | 8 ++ source/blender/blenkernel/intern/mball.c | 6 + source/blender/blenkernel/intern/mesh.c | 12 ++ source/blender/blenkernel/intern/object_update.c | 134 +++++++++++++++++++ source/blender/blenkernel/intern/particle_system.c | 11 ++ source/blender/blenkernel/intern/rigidbody.c | 50 +++++++ 20 files changed, 631 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index a8e430c78df..dc751747f32 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -175,6 +175,9 @@ void BKE_animsys_evaluate_animdata(struct Scene *scene, struct ID *id, struct An /* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only */ void BKE_animsys_evaluate_all_animation(struct Main *main, struct Scene *scene, float ctime); +/* TODO(sergey): This is mainly a temp public function. */ +struct FCurve; +bool BKE_animsys_execute_fcurve(struct PointerRNA *ptr, struct AnimMapper *remap, struct FCurve *fcu); /* ------------ Specialized API --------------- */ /* There are a few special tools which require these following functions. They are NOT to be used @@ -192,4 +195,13 @@ void animsys_evaluate_action_group(struct PointerRNA *ptr, struct bAction *act, /* ************************************* */ +/* ------------ Evaluation API --------------- */ + +struct EvaluationContext; + +void BKE_animsys_eval_animdata(struct EvaluationContext *eval_ctx, struct ID *id); +void BKE_animsys_eval_driver(struct EvaluationContext *eval_ctx, struct ID *id, struct FCurve *fcurve); + +/* ************************************* */ + #endif /* __BKE_ANIMSYS_H__*/ diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index ada07817d31..5bdf360ded2 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -143,10 +143,54 @@ void b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 result_array (PBONE_VISIBLE(arm, bone) && !((bone)->flag & BONE_UNSELECTABLE)) /* Evaluation helpers */ +struct bKinematicConstraint; +struct bPose; +struct bSplineIKConstraint; +struct EvaluationContext; + +struct bPoseChannel *BKE_armature_ik_solver_find_root(struct bPoseChannel *pchan, + struct bKinematicConstraint *data); +struct bPoseChannel* BKE_armature_splineik_solver_find_root(struct bPoseChannel *pchan, + struct bSplineIKConstraint *data); void BKE_pose_splineik_init_tree(struct Scene *scene, struct Object *ob, float ctime); void BKE_splineik_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan_root, float ctime); +void BKE_pose_eval_init(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob, + struct bPose *pose); + +void BKE_pose_eval_bone(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob, + struct bPoseChannel *pchan); + +void BKE_pose_constraints_evaluate(struct EvaluationContext *eval_ctx, + struct Object *ob, + struct bPoseChannel *pchan); + +void BKE_pose_bone_done(struct EvaluationContext *eval_ctx, + struct bPoseChannel *pchan); + +void BKE_pose_iktree_evaluate(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob, + struct bPoseChannel *rootchan); + +void BKE_pose_splineik_evaluate(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob, + struct bPoseChannel *rootchan); + +void BKE_pose_eval_flush(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob, + struct bPose *pose); + +void BKE_pose_eval_proxy_copy(struct EvaluationContext *eval_ctx, + struct Object *ob); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 3ecd472f65b..9bae2ad948d 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -184,4 +184,14 @@ void BKE_nurb_handles_autocalc(struct Nurb *nu, int flag); void BKE_nurb_bezt_handle_test(struct BezTriple *bezt, const bool use_handle); void BKE_nurb_handles_test(struct Nurb *nu, const bool use_handles); +/* **** Depsgraph evaluation **** */ + +struct EvaluationContext; + +void BKE_curve_eval_geometry(struct EvaluationContext *eval_ctx, + struct Curve *curve); + +void BKE_curve_eval_path(struct EvaluationContext *eval_ctx, + struct Curve *curve); + #endif /* __BKE_CURVE_H__ */ diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h index 1887a892b2e..f3a483fd0d8 100644 --- a/source/blender/blenkernel/BKE_depsgraph.h +++ b/source/blender/blenkernel/BKE_depsgraph.h @@ -56,6 +56,7 @@ struct Scene; */ typedef struct EvaluationContext { int mode; /* evaluation mode */ + float ctime; /* evaluation time */ } EvaluationContext; typedef enum eEvaluationMode { diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index 5fb1053b53f..4ffdb632513 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -93,4 +93,11 @@ int BKE_lattice_index_flip(struct Lattice *lt, const int index, void BKE_lattice_bitmap_from_flag(struct Lattice *lt, unsigned int *bitmap, const short flag, const bool clear, const bool respecthide); +/* **** Depsgraph evaluation **** */ + +struct EvaluationContext; + +void BKE_lattice_eval_geometry(struct EvaluationContext *eval_ctx, + struct Lattice *latt); + #endif /* __BKE_LATTICE_H__ */ diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index 321cbbbd708..62cd50099fd 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -68,4 +68,11 @@ void BKE_mball_select_all(struct MetaBall *mb); void BKE_mball_deselect_all(struct MetaBall *mb); void BKE_mball_select_swap(struct MetaBall *mb); +/* **** Depsgraph evaluation **** */ + +struct EvaluationContext; + +void BKE_mball_eval_geometry(struct EvaluationContext *eval_ctx, + struct MetaBall *mball); + #endif diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index ebf4384d5a7..570c99b7bd9 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -360,6 +360,13 @@ void BKE_mesh_strip_loose_edges(struct Mesh *me); void BKE_mesh_calc_edges_legacy(struct Mesh *me, const bool use_old); void BKE_mesh_calc_edges(struct Mesh *mesh, bool update, const bool select); +/* **** Depsgraph evaluation **** */ + +struct EvaluationContext; + +void BKE_mesh_eval_geometry(struct EvaluationContext *eval_ctx, + struct Mesh *mesh); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index c270ebbda7d..7502db21132 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -181,6 +181,28 @@ void BKE_object_tfm_protected_restore(struct Object *ob, const short protectflag); /* Dependency graph evaluation callbacks. */ +void BKE_object_eval_local_transform(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob); +void BKE_object_eval_parent(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob); +void BKE_object_eval_constraints(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob); +void BKE_object_eval_done(struct EvaluationContext *eval_ctx, struct Object *ob); + +void BKE_object_eval_modifier(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob, + struct ModifierData *md); +void BKE_object_eval_uber_transform(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob); +void BKE_object_eval_uber_data(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob); + void BKE_object_handle_data_update(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 27eeb09c58c..e03789f502b 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -459,4 +459,12 @@ typedef struct ParticleRenderData { #define DMCACHE_NOTFOUND -1 #define DMCACHE_ISCHILD -2 +/* **** Depsgraph evaluation **** */ + +struct EvaluationContext; + +void BKE_particle_system_eval(struct EvaluationContext *eval_ctx, + struct Object *ob, + struct ParticleSystem *psys); + #endif diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h index 0ae240e1f6b..b327f0c2574 100644 --- a/source/blender/blenkernel/BKE_rigidbody.h +++ b/source/blender/blenkernel/BKE_rigidbody.h @@ -98,4 +98,19 @@ void BKE_rigidbody_cache_reset(struct RigidBodyWorld *rbw); void BKE_rigidbody_rebuild_world(struct Scene *scene, float ctime); void BKE_rigidbody_do_simulation(struct Scene *scene, float ctime); +/* -------------------- */ +/* Depsgraph evaluation */ + +struct EvaluationContext; + +void BKE_rigidbody_rebuild_sim(struct EvaluationContext *eval_ctx, + struct Scene *scene); + +void BKE_rigidbody_eval_simulation(struct EvaluationContext *eval_ctx, + struct Scene *scene); + +void BKE_rigidbody_object_sync_transforms(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob); + #endif /* __BKE_RIGIDBODY_H__ */ diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 3c98d11dbdb..d5a8b8f857c 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1620,7 +1620,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind } /* Simple replacement based data-setting of the FCurve using RNA */ -static bool animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu) +bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu) { char *path = NULL; bool free_path = false; @@ -1655,7 +1655,7 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, AnimMapper /* check if this curve should be skipped */ if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) { calculate_fcurve(fcu, ctime); - animsys_execute_fcurve(ptr, remap, fcu); + BKE_animsys_execute_fcurve(ptr, remap, fcu); } } } @@ -1685,7 +1685,7 @@ static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime * NOTE: for 'layering' option later on, we should check if we should remove old value before adding * new to only be done when drivers only changed */ calculate_fcurve(fcu, ctime); - ok = animsys_execute_fcurve(ptr, NULL, fcu); + ok = BKE_animsys_execute_fcurve(ptr, NULL, fcu); /* clear recalc flag */ driver->flag &= ~DRIVER_FLAG_RECALC; @@ -1754,7 +1754,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup * /* check if this curve should be skipped */ if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) { calculate_fcurve(fcu, ctime); - animsys_execute_fcurve(ptr, remap, fcu); + BKE_animsys_execute_fcurve(ptr, remap, fcu); } } } @@ -2846,3 +2846,62 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime) } /* ***************************************** */ + +/* ************** */ +/* Evaluation API */ + +#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf + +void BKE_animsys_eval_animdata(EvaluationContext *eval_ctx, ID *id) +{ + AnimData *adt = BKE_animdata_from_id(id); + Scene *scene = NULL; /* XXX: this is only needed for flushing RNA updates, + * which should get handled as part of the graph instead... + */ + DEBUG_PRINT("%s on %s, time=%f\n\n", __func__, id->name, (double)eval_ctx->ctime); + BKE_animsys_evaluate_animdata(scene, id, adt, eval_ctx->ctime, ADT_RECALC_ANIM); +} + +void BKE_animsys_eval_driver(EvaluationContext *eval_ctx, + ID *id, + FCurve *fcu) +{ + /* TODO(sergey): De-duplicate with BKE animsys. */ + ChannelDriver *driver = fcu->driver; + PointerRNA id_ptr; + bool ok = false; + + DEBUG_PRINT("%s on %s (%s[%d])\n", + __func__, + id->name, + fcu->rna_path, + fcu->array_index); + + RNA_id_pointer_create(id, &id_ptr); + + /* check if this driver's curve should be skipped */ + if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) { + /* check if driver itself is tagged for recalculation */ + /* XXX driver recalc flag is not set yet by depsgraph! */ + if ((driver) && !(driver->flag & DRIVER_FLAG_INVALID) /*&& (driver->flag & DRIVER_FLAG_RECALC)*/) { + /* evaluate this using values set already in other places + * NOTE: for 'layering' option later on, we should check if we should remove old value before adding + * new to only be done when drivers only changed */ + //printf("\told val = %f\n", fcu->curval); + calculate_fcurve(fcu, eval_ctx->ctime); + ok = BKE_animsys_execute_fcurve(&id_ptr, NULL, fcu); + //printf("\tnew val = %f\n", fcu->curval); + + /* clear recalc flag */ + driver->flag &= ~DRIVER_FLAG_RECALC; + + /* set error-flag if evaluation failed */ + if (ok == 0) { + printf("invalid driver - %s[%d]\n", fcu->rna_path, fcu->array_index); + driver->flag |= DRIVER_FLAG_INVALID; + } + } + } +} + +#undef DEBUG_PRINT diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index d5416b41b44..498609e62ea 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1825,9 +1825,12 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm) BKE_pose_update_constraint_flags(ob->pose); /* for IK detection for example */ +#ifdef WITH_LEGACY_DEPSGRAPH /* the sorting */ + /* Sorting for new dependnecy graph is done on the scene graph level. */ if (counter > 1) DAG_pose_sort(ob); +#endif ob->pose->flag &= ~POSE_RECALC; ob->pose->flag |= POSE_WAS_REBUILT; @@ -2215,3 +2218,44 @@ BoundBox *BKE_armature_boundbox_get(Object *ob) return ob->bb; } + +/************** Graph evaluation ********************/ + +bPoseChannel *BKE_armature_ik_solver_find_root(bPoseChannel *pchan, + bKinematicConstraint *data) +{ + bPoseChannel *rootchan = pchan; + if (!(data->flag & CONSTRAINT_IK_TIP)) { + /* Exclude tip from chain. */ + rootchan = rootchan->parent; + } + if (rootchan != NULL) { + int segcount = 0; + while (rootchan->parent) { + /* Continue up chain, until we reach target number of items. */ + segcount++; + if (segcount == data->rootbone) { + break; + } + rootchan = rootchan->parent; + } + } + return rootchan; +} + +bPoseChannel* BKE_armature_splineik_solver_find_root(bPoseChannel *pchan, + bSplineIKConstraint *data) +{ + bPoseChannel *rootchan = pchan; + int segcount = 0; + BLI_assert(rootchan != NULL); + while (rootchan->parent) { + /* Continue up chain, until we reach target number of items. */ + segcount++; + if (segcount == data->chainlen) { + break; + } + rootchan = rootchan->parent; + } + return rootchan; +} diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index f7aee3fa2d4..44ffb6a6697 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -51,6 +51,12 @@ #include "BKE_global.h" #include "BKE_main.h" +#ifdef WITH_LEGACY_DEPSGRAPH +# define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH) printf +#else +# define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf +#endif + /* ********************** SPLINE IK SOLVER ******************* */ /* Temporary evaluation tree data used for Spline IK */ @@ -547,3 +553,143 @@ void BKE_splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_roo { splineik_execute_tree(scene, ob, pchan_root, ctime); } + +/* *************** Depsgraph evaluation callbacks ************ */ + +void BKE_pose_eval_init(EvaluationContext *UNUSED(eval_ctx), + Scene *scene, + Object *ob, + bPose *pose) +{ + float ctime = BKE_scene_frame_get(scene); /* not accurate... */ + bPoseChannel *pchan; + + DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + + BLI_assert(ob->type == OB_ARMATURE); + + /* We demand having proper pose. */ + BLI_assert(ob->pose != NULL); + BLI_assert((ob->pose->flag & POSE_RECALC) == 0); + + /* imat is needed for solvers. */ + invert_m4_m4(ob->imat, ob->obmat); + + /* 1. clear flags */ + for (pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) { + pchan->flag &= ~(POSE_DONE | POSE_CHAIN | POSE_IKTREE | POSE_IKSPLINE); + } + + /* 2a. construct the IK tree (standard IK) */ + BIK_initialize_tree(scene, ob, ctime); + + /* 2b. construct the Spline IK trees + * - this is not integrated as an IK plugin, since it should be able + * to function in conjunction with standard IK + */ + BKE_pose_splineik_init_tree(scene, ob, ctime); +} + +void BKE_pose_eval_bone(EvaluationContext *UNUSED(eval_ctx), + Scene *scene, + Object *ob, + bPoseChannel *pchan) +{ + bArmature *arm = (bArmature *)ob->data; + DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, pchan->name); + BLI_assert(ob->type == OB_ARMATURE); + if (arm->edbo || (arm->flag & ARM_RESTPOS)) { + Bone *bone = pchan->bone; + if (bone) { + copy_m4_m4(pchan->pose_mat, bone->arm_mat); + copy_v3_v3(pchan->pose_head, bone->arm_head); + copy_v3_v3(pchan->pose_tail, bone->arm_tail); + } + } + else { + /* TODO(sergey): Currently if there are constraints full transform is being + * evaluated in BKE_pose_constraints_evaluate. + */ + if (pchan->constraints.first == NULL) { + if (pchan->flag & POSE_IKTREE || pchan->flag & POSE_IKSPLINE) { + /* pass */ + } + else { + /* TODO(sergey): Use time source node for time. */ + float ctime = BKE_scene_frame_get(scene); /* not accurate... */ + BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1); + } + } + } +} + +void BKE_pose_constraints_evaluate(EvaluationContext *UNUSED(eval_ctx), + Object *ob, + bPoseChannel *pchan) +{ + Scene *scene = (Scene*)G.main->scene.first; + DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, pchan->name); + if (pchan->flag & POSE_IKTREE || pchan->flag & POSE_IKSPLINE) { + /* IK are being solved separately/ */ + } + else { + float ctime = BKE_scene_frame_get(scene); /* not accurate... */ + BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1); + } +} + +void BKE_pose_bone_done(EvaluationContext *UNUSED(eval_ctx), + bPoseChannel *pchan) +{ + float imat[4][4]; + DEBUG_PRINT("%s on pchan %s\n", __func__, pchan->name); + if (pchan->bone) { + invert_m4_m4(imat, pchan->bone->arm_mat); + mul_m4_m4m4(pchan->chan_mat, pchan->pose_mat, imat); + } +} + +void BKE_pose_iktree_evaluate(EvaluationContext *UNUSED(eval_ctx), + Scene *scene, + Object *ob, + bPoseChannel *rootchan) +{ + float ctime = BKE_scene_frame_get(scene); /* not accurate... */ + DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, rootchan->name); + BIK_execute_tree(scene, ob, rootchan, ctime); +} + +void BKE_pose_splineik_evaluate(EvaluationContext *UNUSED(eval_ctx), + Scene *scene, + Object *ob, + bPoseChannel *rootchan) +{ + float ctime = BKE_scene_frame_get(scene); /* not accurate... */ + DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, rootchan->name); + BKE_splineik_execute_tree(scene, ob, rootchan, ctime); +} + +void BKE_pose_eval_flush(EvaluationContext *UNUSED(eval_ctx), + Scene *scene, + Object *ob, + bPose *UNUSED(pose)) +{ + float ctime = BKE_scene_frame_get(scene); /* not accurate... */ + DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + BLI_assert(ob->type == OB_ARMATURE); + + /* 6. release the IK tree */ + BIK_release_tree(scene, ob, ctime); + + ob->recalc &= ~OB_RECALC_ALL; +} + +void BKE_pose_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), Object *ob) +{ + BLI_assert(ob->id.lib != NULL && ob->proxy_from != NULL); + DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) { + printf("Proxy copy error, lib Object: %s proxy Object: %s\n", + ob->id.name + 2, ob->proxy_from->id.name + 2); + } +} diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index c27460b81c0..c95b0055683 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -4563,3 +4563,27 @@ void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *t r_rect->xmax = r_rect->xmin + tb->w; r_rect->ymin = r_rect->ymax - tb->h; } + +/* **** Depsgraph evaluation **** */ + +void BKE_curve_eval_geometry(EvaluationContext *UNUSED(eval_ctx), + Curve *curve) +{ + if (G.debug & G_DEBUG_DEPSGRAPH) { + printf("%s on %s\n", __func__, curve->id.name); + } + if (curve->bb == NULL || (curve->bb->flag & BOUNDBOX_DIRTY)) { + BKE_curve_texspace_calc(curve); + } +} + +void BKE_curve_eval_path(EvaluationContext *UNUSED(eval_ctx), + Curve *curve) +{ + /* TODO(sergey): This will probably need to be a part of + * the modifier stack still. + */ + if (G.debug & G_DEBUG_DEPSGRAPH) { + printf("%s on %s\n", __func__, curve->id.name); + } +} diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 73dca9436ef..86927609ff6 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -53,6 +53,7 @@ #include "BKE_anim.h" #include "BKE_cdderivedmesh.h" #include "BKE_curve.h" +#include "BKE_depsgraph.h" #include "BKE_displist.h" #include "BKE_global.h" #include "BKE_key.h" @@ -1206,3 +1207,10 @@ void BKE_lattice_translate(Lattice *lt, float offset[3], bool do_keys) } } +/* **** Depsgraph evaluation **** */ + +void BKE_lattice_eval_geometry(EvaluationContext *UNUSED(eval_ctx), + Lattice *UNUSED(latt)) +{ +} + diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 8728e6f98d5..c09cd1aabdc 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -586,3 +586,9 @@ void BKE_mball_select_swap(struct MetaBall *mb) } } +/* **** Depsgraph evaluation **** */ + +void BKE_mball_eval_geometry(EvaluationContext *UNUSED(eval_ctx), + MetaBall *UNUSED(mball)) +{ +} diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index e66a4d48fc8..735e4358cb8 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2523,3 +2523,15 @@ Mesh *BKE_mesh_new_from_object( return tmpmesh; } +/* **** Depsgraph evaluation **** */ + +void BKE_mesh_eval_geometry(EvaluationContext *UNUSED(eval_ctx), + Mesh *mesh) +{ + if (G.debug & G_DEBUG_DEPSGRAPH) { + printf("%s on %s\n", __func__, mesh->id.name); + } + if (mesh->bb == NULL || (mesh->bb->flag & BOUNDBOX_DIRTY)) { + BKE_mesh_texspace_calc(mesh); + } +} diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 196c85831e0..76c20adf8c5 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -57,6 +57,100 @@ #include "BKE_material.h" #include "BKE_image.h" +#ifdef WITH_LEGACY_DEPSGRAPH +# define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH) printf +#else +# define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf +#endif + +void BKE_object_eval_local_transform(EvaluationContext *UNUSED(eval_ctx), + Scene *UNUSED(scene), + Object *ob) +{ + DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + + /* calculate local matrix */ + BKE_object_to_mat4(ob, ob->obmat); +} + +/* Evaluate parent */ +/* NOTE: based on solve_parenting(), but with the cruft stripped out */ +void BKE_object_eval_parent(EvaluationContext *UNUSED(eval_ctx), + Scene *scene, + Object *ob) +{ + Object *par = ob->parent; + + float totmat[4][4]; + float tmat[4][4]; + float locmat[4][4]; + + DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + + /* get local matrix (but don't calculate it, as that was done already!) */ + // XXX: redundant? + copy_m4_m4(locmat, ob->obmat); + + /* get parent effect matrix */ + BKE_object_get_parent_matrix(scene, ob, par, totmat); + + /* total */ + mul_m4_m4m4(tmat, totmat, ob->parentinv); + mul_m4_m4m4(ob->obmat, tmat, locmat); + + /* origin, for help line */ + if ((ob->partype & PARTYPE) == PARSKEL) { + copy_v3_v3(ob->orig, par->obmat[3]); + } + else { + copy_v3_v3(ob->orig, totmat[3]); + } +} + +void BKE_object_eval_constraints(EvaluationContext *UNUSED(eval_ctx), + Scene *scene, + Object *ob) +{ + bConstraintOb *cob; + float ctime = BKE_scene_frame_get(scene); + + DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + + /* evaluate constraints stack */ + /* TODO: split this into: + * - pre (i.e. BKE_constraints_make_evalob, per-constraint (i.e. + * - inner body of BKE_constraints_solve), + * - post (i.e. BKE_constraints_clear_evalob) + * + * Not sure why, this is from Joshua - sergey + * + */ + cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); + BKE_constraints_solve(&ob->constraints, cob, ctime); + BKE_constraints_clear_evalob(cob); +} + +void BKE_object_eval_done(EvaluationContext *UNUSED(eval_ctx), Object *ob) +{ + DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + + /* Set negative scale flag in object. */ + if (is_negative_m4(ob->obmat)) ob->transflag |= OB_NEG_SCALE; + else ob->transflag &= ~OB_NEG_SCALE; +} + +void BKE_object_eval_modifier(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob, + struct ModifierData *md) +{ + DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + (void) eval_ctx; /* Ignored. */ + (void) scene; /* Ignored. */ + (void) ob; /* Ignored. */ + (void) md; /* Ignored. */ +} + void BKE_object_handle_data_update(EvaluationContext *eval_ctx, Scene *scene, Object *ob) @@ -202,3 +296,43 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx, /* quick cache removed */ } + +void BKE_object_eval_uber_transform(EvaluationContext *UNUSED(eval_ctx), + Scene *UNUSED(scene), + Object *ob) +{ + /* TODO(sergey): Currently it's a duplicate of logic in BKE_object_handle_update_ex(). */ + // XXX: it's almost redundant now... + + /* Handle proxy copy for target, */ + if (ob->id.lib && ob->proxy_from) { + if (ob->proxy_from->proxy_group) { + /* Transform proxy into group space. */ + Object *obg = ob->proxy_from->proxy_group; + invert_m4_m4(obg->imat, obg->obmat); + mul_m4_m4m4(ob->obmat, obg->imat, ob->proxy_from->obmat); + /* Should always be true. */ + if (obg->dup_group) { + add_v3_v3(ob->obmat[3], obg->dup_group->dupli_ofs); + } + } + else + copy_m4_m4(ob->obmat, ob->proxy_from->obmat); + } + + ob->recalc &= ~(OB_RECALC_OB|OB_RECALC_TIME); + if (ob->data == NULL) { + ob->recalc &= ~OB_RECALC_DATA; + } +} + +void BKE_object_eval_uber_data(EvaluationContext *eval_ctx, + Scene *scene, + Object *ob) +{ + DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + BLI_assert(ob->type != OB_ARMATURE); + BKE_object_handle_data_update(eval_ctx, scene, ob); + + ob->recalc &= ~(OB_RECALC_DATA|OB_RECALC_TIME); +} diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 4bc46a476a5..3a19ca7304c 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -90,6 +90,7 @@ #include "BKE_modifier.h" #include "BKE_scene.h" #include "BKE_bvhutils.h" +#include "BKE_depsgraph.h" #include "PIL_time.h" @@ -4209,3 +4210,13 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) invert_m4_m4(psys->imat, ob->obmat); } +/* **** Depsgraph evaluation **** */ + +void BKE_particle_system_eval(EvaluationContext *UNUSED(eval_ctx), + Object *ob, + ParticleSystem *psys) +{ + if (G.debug & G_DEBUG_DEPSGRAPH) { + printf("%s on %s:%s\n", __func__, ob->id.name, psys->name); + } +} diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index aaf54b82f32..ff9e1a2b831 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -54,6 +54,7 @@ #include "DNA_scene_types.h" #include "BKE_cdderivedmesh.h" +#include "BKE_depsgraph.h" #include "BKE_effect.h" #include "BKE_global.h" #include "BKE_library.h" @@ -61,6 +62,7 @@ #include "BKE_object.h" #include "BKE_pointcache.h" #include "BKE_rigidbody.h" +#include "BKE_scene.h" #ifdef WITH_BULLET @@ -1610,3 +1612,51 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {} #endif #endif /* WITH_BULLET */ + +/* -------------------- */ +/* Depsgraph evaluation */ + +void BKE_rigidbody_rebuild_sim(EvaluationContext *UNUSED(eval_ctx), + Scene *scene) +{ + float ctime = BKE_scene_frame_get(scene); + + if (G.debug & G_DEBUG_DEPSGRAPH) { + printf("%s at %f\n", __func__, ctime); + } + + /* rebuild sim data (i.e. after resetting to start of timeline) */ + if (BKE_scene_check_rigidbody_active(scene)) { + BKE_rigidbody_rebuild_world(scene, ctime); + } +} + +void BKE_rigidbody_eval_simulation(EvaluationContext *UNUSED(eval_ctx), + Scene *scene) +{ + float ctime = BKE_scene_frame_get(scene); + + if (G.debug & G_DEBUG_DEPSGRAPH) { + printf("%s at %f\n", __func__, ctime); + } + + /* evaluate rigidbody sim */ + if (BKE_scene_check_rigidbody_active(scene)) { + BKE_rigidbody_do_simulation(scene, ctime); + } +} + +void BKE_rigidbody_object_sync_transforms(EvaluationContext *UNUSED(eval_ctx), + Scene *scene, + Object *ob) +{ + RigidBodyWorld *rbw = scene->rigidbody_world; + float ctime = BKE_scene_frame_get(scene); + + if (G.debug & G_DEBUG_DEPSGRAPH) { + printf("%s on %s\n", __func__, ob->id.name); + } + + /* read values pushed into RBO from sim/cache... */ + BKE_rigidbody_sync_transforms(rbw, ob, ctime); +} -- cgit v1.2.3 From bac735380189c63d2b8824cba8e0398bb35e9af2 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 12 May 2015 15:05:57 +0500 Subject: Depsgraph: New dependency graph integration commit This commit integrates the work done so far on the new dependency graph system, where goal was to replace legacy depsgraph with the new one, supporting loads of neat features like: - More granular dependency relation nature, which solves issues with fake cycles in the dependencies. - Move towards all-animatable, by better integration of drivers into the system. - Lay down some basis for upcoming copy-on-write, overrides and so on. The new system is living side-by-side with the previous one and disabled by default, so nothing will become suddenly broken. The way to enable new depsgraph is to pass `--new-depsgraph` command line argument. It's a bit early to consider the system production-ready, there are some TODOs and issues were discovered during the merge period, they'll be addressed ASAP. But it's important to merge, because it's the only way to attract artists to really start testing this system. There are number of assorted documents related on the design of the new system: * http://wiki.blender.org/index.php/User:Aligorith/GSoC2013_Depsgraph#Design_Documents * http://wiki.blender.org/index.php/User:Nazg-gul/DependencyGraph There are also some user-related information online: * http://code.blender.org/2015/02/blender-dependency-graph-branch-for-users/ * http://code.blender.org/2015/03/more-dependency-graph-tricks/ Kudos to everyone who was involved into the project: - Joshua "Aligorith" Leung -- design specification, initial code - Lukas "lukas_t" Toenne -- integrating code into blender, with further fixes - Sergey "Sergey" "Sharybin" -- some mocking around, trying to wrap up the project and so - Bassam "slikdigit" Kurdali -- stressing the new system, reporting all the issues and recording/writing documentation. - Everyone else who i forgot to mention here :) --- CMakeLists.txt | 3 + build_files/cmake/macros.cmake | 1 + build_files/scons/tools/Blender.py | 2 +- build_files/scons/tools/btools.py | 4 +- source/blender/CMakeLists.txt | 1 + source/blender/SConscript | 1 + source/blender/blenkernel/BKE_depsgraph.h | 1 + source/blender/blenkernel/BKE_modifier.h | 12 + source/blender/blenkernel/CMakeLists.txt | 5 + source/blender/blenkernel/SConscript | 4 + source/blender/blenkernel/intern/action.c | 7 +- source/blender/blenkernel/intern/armature_update.c | 2 + source/blender/blenkernel/intern/depsgraph.c | 405 ++++- source/blender/blenkernel/intern/library.c | 7 +- source/blender/blenkernel/intern/mesh.c | 5 +- source/blender/blenkernel/intern/object_update.c | 2 + source/blender/blenkernel/intern/scene.c | 120 +- source/blender/blenloader/intern/readfile.c | 1 + source/blender/depsgraph/CMakeLists.txt | 116 ++ source/blender/depsgraph/DEG_depsgraph.h | 210 +++ source/blender/depsgraph/DEG_depsgraph_build.h | 117 ++ source/blender/depsgraph/DEG_depsgraph_debug.h | 107 ++ source/blender/depsgraph/DEG_depsgraph_query.h | 191 ++ source/blender/depsgraph/SConscript | 74 + source/blender/depsgraph/intern/depsgraph.cc | 469 +++++ source/blender/depsgraph/intern/depsgraph.h | 220 +++ source/blender/depsgraph/intern/depsgraph_build.cc | 365 ++++ source/blender/depsgraph/intern/depsgraph_build.h | 404 +++++ .../depsgraph/intern/depsgraph_build_nodes.cc | 1199 +++++++++++++ .../depsgraph/intern/depsgraph_build_relations.cc | 1815 ++++++++++++++++++++ source/blender/depsgraph/intern/depsgraph_debug.cc | 1187 +++++++++++++ source/blender/depsgraph/intern/depsgraph_debug.h | 83 + source/blender/depsgraph/intern/depsgraph_eval.cc | 386 +++++ source/blender/depsgraph/intern/depsgraph_intern.h | 164 ++ source/blender/depsgraph/intern/depsgraph_query.cc | 213 +++ source/blender/depsgraph/intern/depsgraph_queue.cc | 173 ++ source/blender/depsgraph/intern/depsgraph_queue.h | 87 + source/blender/depsgraph/intern/depsgraph_tag.cc | 490 ++++++ .../depsgraph/intern/depsgraph_type_defines.cc | 98 ++ source/blender/depsgraph/intern/depsgraph_types.h | 169 ++ source/blender/depsgraph/intern/depsnode.cc | 308 ++++ source/blender/depsgraph/intern/depsnode.h | 243 +++ .../blender/depsgraph/intern/depsnode_component.cc | 314 ++++ .../blender/depsgraph/intern/depsnode_component.h | 197 +++ source/blender/depsgraph/intern/depsnode_opcodes.h | 141 ++ .../blender/depsgraph/intern/depsnode_operation.cc | 100 ++ .../blender/depsgraph/intern/depsnode_operation.h | 86 + .../blender/depsgraph/util/depsgraph_util_cycle.cc | 134 ++ .../blender/depsgraph/util/depsgraph_util_cycle.h | 31 + .../depsgraph/util/depsgraph_util_function.h | 106 ++ .../blender/depsgraph/util/depsgraph_util_hash.h | 66 + source/blender/depsgraph/util/depsgraph_util_map.h | 61 + .../depsgraph/util/depsgraph_util_pchanmap.cc | 132 ++ .../depsgraph/util/depsgraph_util_pchanmap.h | 55 + source/blender/depsgraph/util/depsgraph_util_set.h | 60 + .../depsgraph/util/depsgraph_util_transitive.cc | 133 ++ .../depsgraph/util/depsgraph_util_transitive.h | 32 + source/blender/editors/space_view3d/CMakeLists.txt | 1 + source/blender/editors/space_view3d/SConscript | 1 + source/blender/editors/space_view3d/space_view3d.c | 8 +- source/blender/editors/transform/CMakeLists.txt | 4 + source/blender/editors/transform/SConscript | 3 + .../editors/transform/transform_conversions.c | 4 + source/blender/makesdna/DNA_scene_types.h | 1 + source/blender/makesrna/SConscript | 1 + source/blender/makesrna/intern/CMakeLists.txt | 2 + source/blender/makesrna/intern/SConscript | 1 + source/blender/makesrna/intern/makesrna.c | 1 + source/blender/makesrna/intern/rna_depsgraph.c | 112 ++ source/blender/makesrna/intern/rna_internal.h | 1 + source/blender/makesrna/intern/rna_object_api.c | 6 +- source/blender/makesrna/intern/rna_scene.c | 5 + source/blender/modifiers/CMakeLists.txt | 1 + source/blender/modifiers/SConscript | 1 + source/blender/modifiers/intern/MOD_armature.c | 13 + source/blender/modifiers/intern/MOD_array.c | 23 + source/blender/modifiers/intern/MOD_bevel.c | 1 + source/blender/modifiers/intern/MOD_boolean.c | 16 + source/blender/modifiers/intern/MOD_build.c | 1 + source/blender/modifiers/intern/MOD_cast.c | 13 + source/blender/modifiers/intern/MOD_cloth.c | 22 + source/blender/modifiers/intern/MOD_collision.c | 1 + .../modifiers/intern/MOD_correctivesmooth.c | 1 + source/blender/modifiers/intern/MOD_curve.c | 21 + source/blender/modifiers/intern/MOD_datatransfer.c | 13 + source/blender/modifiers/intern/MOD_decimate.c | 1 + source/blender/modifiers/intern/MOD_displace.c | 16 + source/blender/modifiers/intern/MOD_dynamicpaint.c | 22 + source/blender/modifiers/intern/MOD_edgesplit.c | 1 + source/blender/modifiers/intern/MOD_explode.c | 1 + source/blender/modifiers/intern/MOD_fluidsim.c | 28 + source/blender/modifiers/intern/MOD_hook.c | 20 + .../blender/modifiers/intern/MOD_laplaciandeform.c | 1 + .../blender/modifiers/intern/MOD_laplaciansmooth.c | 1 + source/blender/modifiers/intern/MOD_lattice.c | 13 + source/blender/modifiers/intern/MOD_mask.c | 18 + source/blender/modifiers/intern/MOD_meshcache.c | 1 + source/blender/modifiers/intern/MOD_meshdeform.c | 14 + source/blender/modifiers/intern/MOD_mirror.c | 15 + source/blender/modifiers/intern/MOD_multires.c | 1 + source/blender/modifiers/intern/MOD_none.c | 1 + source/blender/modifiers/intern/MOD_normal_edit.c | 13 + source/blender/modifiers/intern/MOD_ocean.c | 1 + .../modifiers/intern/MOD_particleinstance.c | 15 +- .../blender/modifiers/intern/MOD_particlesystem.c | 1 + source/blender/modifiers/intern/MOD_remesh.c | 1 + source/blender/modifiers/intern/MOD_screw.c | 15 + source/blender/modifiers/intern/MOD_shapekey.c | 1 + source/blender/modifiers/intern/MOD_shrinkwrap.c | 18 + source/blender/modifiers/intern/MOD_simpledeform.c | 13 + source/blender/modifiers/intern/MOD_skin.c | 1 + source/blender/modifiers/intern/MOD_smoke.c | 107 ++ source/blender/modifiers/intern/MOD_smooth.c | 1 + source/blender/modifiers/intern/MOD_softbody.c | 1 + source/blender/modifiers/intern/MOD_solidify.c | 1 + source/blender/modifiers/intern/MOD_subsurf.c | 1 + source/blender/modifiers/intern/MOD_surface.c | 1 + source/blender/modifiers/intern/MOD_triangulate.c | 1 + source/blender/modifiers/intern/MOD_util.h | 2 + source/blender/modifiers/intern/MOD_uvproject.c | 18 + source/blender/modifiers/intern/MOD_uvwarp.c | 25 + source/blender/modifiers/intern/MOD_warp.c | 17 + source/blender/modifiers/intern/MOD_wave.c | 16 + source/blender/modifiers/intern/MOD_weightvgedit.c | 18 + source/blender/modifiers/intern/MOD_weightvgmix.c | 18 + .../modifiers/intern/MOD_weightvgproximity.c | 21 + source/blender/modifiers/intern/MOD_wireframe.c | 1 + source/blender/render/CMakeLists.txt | 1 + source/blender/render/SConscript | 1 + source/blender/render/intern/source/pipeline.c | 5 +- source/blenderplayer/CMakeLists.txt | 1 + source/creator/CMakeLists.txt | 1 + source/creator/creator.c | 14 + 133 files changed, 11844 insertions(+), 58 deletions(-) create mode 100644 source/blender/depsgraph/CMakeLists.txt create mode 100644 source/blender/depsgraph/DEG_depsgraph.h create mode 100644 source/blender/depsgraph/DEG_depsgraph_build.h create mode 100644 source/blender/depsgraph/DEG_depsgraph_debug.h create mode 100644 source/blender/depsgraph/DEG_depsgraph_query.h create mode 100644 source/blender/depsgraph/SConscript create mode 100644 source/blender/depsgraph/intern/depsgraph.cc create mode 100644 source/blender/depsgraph/intern/depsgraph.h create mode 100644 source/blender/depsgraph/intern/depsgraph_build.cc create mode 100644 source/blender/depsgraph/intern/depsgraph_build.h create mode 100644 source/blender/depsgraph/intern/depsgraph_build_nodes.cc create mode 100644 source/blender/depsgraph/intern/depsgraph_build_relations.cc create mode 100644 source/blender/depsgraph/intern/depsgraph_debug.cc create mode 100644 source/blender/depsgraph/intern/depsgraph_debug.h create mode 100644 source/blender/depsgraph/intern/depsgraph_eval.cc create mode 100644 source/blender/depsgraph/intern/depsgraph_intern.h create mode 100644 source/blender/depsgraph/intern/depsgraph_query.cc create mode 100644 source/blender/depsgraph/intern/depsgraph_queue.cc create mode 100644 source/blender/depsgraph/intern/depsgraph_queue.h create mode 100644 source/blender/depsgraph/intern/depsgraph_tag.cc create mode 100644 source/blender/depsgraph/intern/depsgraph_type_defines.cc create mode 100644 source/blender/depsgraph/intern/depsgraph_types.h create mode 100644 source/blender/depsgraph/intern/depsnode.cc create mode 100644 source/blender/depsgraph/intern/depsnode.h create mode 100644 source/blender/depsgraph/intern/depsnode_component.cc create mode 100644 source/blender/depsgraph/intern/depsnode_component.h create mode 100644 source/blender/depsgraph/intern/depsnode_opcodes.h create mode 100644 source/blender/depsgraph/intern/depsnode_operation.cc create mode 100644 source/blender/depsgraph/intern/depsnode_operation.h create mode 100644 source/blender/depsgraph/util/depsgraph_util_cycle.cc create mode 100644 source/blender/depsgraph/util/depsgraph_util_cycle.h create mode 100644 source/blender/depsgraph/util/depsgraph_util_function.h create mode 100644 source/blender/depsgraph/util/depsgraph_util_hash.h create mode 100644 source/blender/depsgraph/util/depsgraph_util_map.h create mode 100644 source/blender/depsgraph/util/depsgraph_util_pchanmap.cc create mode 100644 source/blender/depsgraph/util/depsgraph_util_pchanmap.h create mode 100644 source/blender/depsgraph/util/depsgraph_util_set.h create mode 100644 source/blender/depsgraph/util/depsgraph_util_transitive.cc create mode 100644 source/blender/depsgraph/util/depsgraph_util_transitive.h create mode 100644 source/blender/makesrna/intern/rna_depsgraph.c diff --git a/CMakeLists.txt b/CMakeLists.txt index ae2c67b59bf..a8b32b4dc0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -449,6 +449,9 @@ endif() option(WITH_CPP11 "Build with C++11 standard enabled, for development use only!" OFF) mark_as_advanced(WITH_CPP11) +# Dependency graph +option(WITH_LEGACY_DEPSGRAPH "Build Blender with legacy dependency graph" ON) + # avoid using again option_defaults_clear() diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 8b2f3f18215..7de2b25f321 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -524,6 +524,7 @@ macro(SETUP_BLENDER_SORTED_LIBS) bf_blenloader bf_imbuf bf_blenlib + bf_depsgraph bf_intern_ghost bf_intern_string bf_avi diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py index 6e7417c76ec..ecf34759033 100644 --- a/build_files/scons/tools/Blender.py +++ b/build_files/scons/tools/Blender.py @@ -372,7 +372,7 @@ def propose_priorities(): def creator(env): sources = ['creator.c']# + Blender.buildinfo(env, "dynamic") + Blender.resources - incs = ['#/intern/guardedalloc', '#/source/blender/blenlib', '#/source/blender/blenkernel', '#/source/blender/editors/include', '#/source/blender/blenloader', '#/source/blender/imbuf', '#/source/blender/renderconverter', '#/source/blender/render/extern/include', '#/source/blender/windowmanager', '#/source/blender/makesdna', '#/source/blender/makesrna', '#/source/gameengine/BlenderRoutines', '#/extern/glew/include', '#/source/blender/gpu', env['BF_OPENGL_INC']] + incs = ['#/intern/guardedalloc', '#/source/blender/blenlib', '#/source/blender/blenkernel', '#/source/blender/depsgraph', '#/source/blender/editors/include', '#/source/blender/blenloader', '#/source/blender/imbuf', '#/source/blender/renderconverter', '#/source/blender/render/extern/include', '#/source/blender/windowmanager', '#/source/blender/makesdna', '#/source/blender/makesrna', '#/source/gameengine/BlenderRoutines', '#/extern/glew/include', '#/source/blender/gpu', env['BF_OPENGL_INC']] defs = [] diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index c5342d6f349..76450fbd223 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -199,7 +199,7 @@ def validate_arguments(args, bc): 'LLIBS', 'PLATFORM_LINKFLAGS', 'MACOSX_ARCHITECTURE', 'MACOSX_SDK', 'XCODE_CUR_VER', 'C_COMPILER_ID', 'BF_CYCLES_CUDA_BINARIES_ARCH', 'BF_PROGRAM_LINKFLAGS', 'MACOSX_DEPLOYMENT_TARGET', 'WITH_BF_CYCLES_DEBUG', 'WITH_BF_CYCLES_LOGGING', - 'WITH_BF_CPP11' + 'WITH_BF_CPP11', 'WITH_BF_LEGACY_DEPSGRAPH', ] @@ -657,6 +657,8 @@ def read_opts(env, cfg, args): ('BF_PROGRAM_LINKFLAGS', 'Link flags applied only to final binaries (blender and blenderplayer, not makesrna/makesdna)', ''), (BoolVariable('WITH_BF_CPP11', '"Build with C++11 standard enabled, for development use only!', False)), + + (BoolVariable('WITH_BF_LEGACY_DEPSGRAPH', 'Build Blender with legacy dependency graph', True)), ) # end of opts.AddOptions() return localopts diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index d87d5dfc2cc..9a73921bbc7 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -102,6 +102,7 @@ add_subdirectory(bmesh) add_subdirectory(render) add_subdirectory(blenfont) add_subdirectory(blenloader) +add_subdirectory(depsgraph) add_subdirectory(ikplugin) add_subdirectory(physics) add_subdirectory(gpu) diff --git a/source/blender/SConscript b/source/blender/SConscript index 64eca6a62db..e987b6be779 100644 --- a/source/blender/SConscript +++ b/source/blender/SConscript @@ -33,6 +33,7 @@ SConscript(['avi/SConscript', 'blenkernel/SConscript', 'blenlib/SConscript', 'blenloader/SConscript', + 'depsgraph/SConscript', 'gpu/SConscript', 'editors/SConscript', 'imbuf/SConscript', diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h index f3a483fd0d8..862f91f567e 100644 --- a/source/blender/blenkernel/BKE_depsgraph.h +++ b/source/blender/blenkernel/BKE_depsgraph.h @@ -92,6 +92,7 @@ void DAG_exit(void); */ void DAG_scene_relations_update(struct Main *bmain, struct Scene *sce); +void DAG_scene_relations_validate(struct Main *bmain, struct Scene *sce); void DAG_relations_tag_update(struct Main *bmain); void DAG_scene_relations_rebuild(struct Main *bmain, struct Scene *scene); void DAG_scene_free(struct Scene *sce); diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 9c5261c1583..cc53f9409fd 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -43,6 +43,7 @@ struct bArmature; struct Main; struct ModifierData; struct BMEditMesh; +struct DepsNodeHandle; typedef enum { /* Should not be used, only for None modifier type */ @@ -260,6 +261,17 @@ typedef struct ModifierTypeInfo { struct Main *bmain, struct Scene *scene, struct Object *ob, struct DagNode *obNode); + /* Add the appropriate relations to the dependency graph. + * + * This function is optional. + */ + /* TODO(sergey): Remove once we finalyl switched to the new depsgraph. */ + void (*updateDepsgraph)(struct ModifierData *md, + struct Main *bmain, + struct Scene *scene, + struct Object *ob, + struct DepsNodeHandle *node); + /* Should return true if the modifier needs to be recalculated on time * changes. * diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index fe713e64c64..37e5b36779f 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -28,6 +28,7 @@ set(INC ../blenfont ../blenlib ../blenloader + ../depsgraph ../gpu ../ikplugin ../imbuf @@ -482,4 +483,8 @@ endif() # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") #endif() +if(WITH_LEGACY_DEPSGRAPH) + add_definitions(-DWITH_LEGACY_DEPSGRAPH) +endif() + blender_add_lib(bf_blenkernel "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 47bba5f5537..9d19e1c29b4 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -58,6 +58,7 @@ incs = [ '../blenlib', '../blenloader', '../bmesh', + '../depsgraph', '../gpu', '../ikplugin', '../imbuf', @@ -175,6 +176,9 @@ if env['WITH_BF_BINRELOC']: incs += ' #extern/binreloc/include' defs.append('WITH_BINRELOC') +if env['WITH_BF_LEGACY_DEPSGRAPH']: + defs.append('WITH_LEGACY_DEPSGRAPH') + if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [166,25]) #, cc_compileflags = env['CCFLAGS'].append('/WX') ) else: diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 708c64f8ffc..7e09ad355a7 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -54,6 +54,7 @@ #include "BKE_animsys.h" #include "BKE_constraint.h" #include "BKE_deform.h" +#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_idprop.h" @@ -1318,9 +1319,13 @@ bool BKE_pose_copy_result(bPose *to, bPose *from) } /* Tag pose for recalc. Also tag all related data to be recalc. */ -void BKE_pose_tag_recalc(Main *UNUSED(bmain), bPose *pose) +void BKE_pose_tag_recalc(Main *bmain, bPose *pose) { pose->flag |= POSE_RECALC; + /* Depsgraph components depends on actual pose state, + * if pose was changed depsgraph is to be updated as well. + */ + DAG_relations_tag_update(bmain); } /* For the calculation of the effects of an Action at the given frame on an object diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index 44ffb6a6697..aa36036ed6a 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -51,6 +51,8 @@ #include "BKE_global.h" #include "BKE_main.h" +#include "DEG_depsgraph.h" + #ifdef WITH_LEGACY_DEPSGRAPH # define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH) printf #else diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 869404ae4a6..9ee9f3d57af 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -88,16 +88,25 @@ #include "depsgraph_private.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_debug.h" +#include "DEG_depsgraph_query.h" + +#ifdef WITH_LEGACY_DEPSGRAPH + static SpinLock threaded_update_lock; void DAG_init(void) { BLI_spin_init(&threaded_update_lock); + DEG_register_node_types(); } void DAG_exit(void) { BLI_spin_end(&threaded_update_lock); + DEG_free_node_types(); } /* Queue and stack operations for dag traversal @@ -1329,8 +1338,14 @@ static void (*EditorsUpdateSceneCb)(Main *bmain, Scene *scene, int updated) = NU void DAG_editors_update_cb(void (*id_func)(Main *bmain, ID *id), void (*scene_func)(Main *bmain, Scene *scene, int updated)) { - EditorsUpdateIDCb = id_func; - EditorsUpdateSceneCb = scene_func; + if (DEG_depsgraph_use_legacy()) { + EditorsUpdateIDCb = id_func; + EditorsUpdateSceneCb = scene_func; + } + else { + /* New dependency graph. */ + DEG_editors_set_update_cb(id_func, scene_func); + } } static void dag_editors_id_update(Main *bmain, ID *id) @@ -1529,7 +1544,7 @@ static void dag_scene_build(Main *bmain, Scene *sce) Base *base; BLI_listbase_clear(&tempbase); - + build_dag(bmain, sce, DAG_RL_ALL_BUT_DATA); dag_check_cycle(sce->theDag); @@ -1621,32 +1636,65 @@ static void dag_scene_build(Main *bmain, Scene *sce) /* clear all dependency graphs */ void DAG_relations_tag_update(Main *bmain) { - Scene *sce; - - for (sce = bmain->scene.first; sce; sce = sce->id.next) - dag_scene_free(sce); + if (DEG_depsgraph_use_legacy()) { + Scene *sce; + for (sce = bmain->scene.first; sce; sce = sce->id.next) { + dag_scene_free(sce); + } + } + else { + /* New dependency graph. */ + DEG_relations_tag_update(bmain); + } } /* rebuild dependency graph only for a given scene */ void DAG_scene_relations_rebuild(Main *bmain, Scene *sce) { - dag_scene_free(sce); - DAG_scene_relations_update(bmain, sce); + if (DEG_depsgraph_use_legacy()) { + dag_scene_free(sce); + DAG_scene_relations_update(bmain, sce); + } + else { + /* New dependency graph. */ + DEG_scene_relations_rebuild(bmain, sce); + } } /* create dependency graph if it was cleared or didn't exist yet */ void DAG_scene_relations_update(Main *bmain, Scene *sce) { - if (!sce->theDag) - dag_scene_build(bmain, sce); + if (DEG_depsgraph_use_legacy()) { + if (!sce->theDag) + dag_scene_build(bmain, sce); + } + else { + /* New dependency graph. */ + DEG_scene_relations_update(bmain, sce); + } +} + +void DAG_scene_relations_validate(Main *bmain, Scene *sce) +{ + if (!DEG_depsgraph_use_legacy()) { + DEG_debug_scene_relations_validate(bmain, sce); + } } void DAG_scene_free(Scene *sce) { - if (sce->theDag) { - free_forest(sce->theDag); - MEM_freeN(sce->theDag); - sce->theDag = NULL; + if (DEG_depsgraph_use_legacy()) { + if (sce->theDag) { + free_forest(sce->theDag); + MEM_freeN(sce->theDag); + sce->theDag = NULL; + } + } + else { + if (sce->depsgraph) { + DEG_graph_free(sce->depsgraph); + sce->depsgraph = NULL; + } } } @@ -1889,7 +1937,11 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho DagAdjList *itA; Object *ob; int lasttime; - + + if (!DEG_depsgraph_use_legacy()) { + return; + } + if (sce->theDag == NULL) { printf("DAG zero... not allowed to happen!\n"); DAG_scene_relations_update(bmain, sce); @@ -2300,7 +2352,7 @@ static void dag_current_scene_layers(Main *bmain, ListBase *lb) } } -static void dag_group_on_visible_update(Group *group) +static void dag_group_on_visible_update(Scene *scene, Group *group) { GroupObject *go; @@ -2322,7 +2374,7 @@ static void dag_group_on_visible_update(Group *group) } if (go->ob->dup_group) - dag_group_on_visible_update(go->ob->dup_group); + dag_group_on_visible_update(scene, go->ob->dup_group); } } @@ -2330,7 +2382,13 @@ void DAG_on_visible_update(Main *bmain, const bool do_time) { ListBase listbase; DagSceneLayer *dsl; - + + if (!DEG_depsgraph_use_legacy()) { + /* Inform new dependnecy graphs about visibility changes. */ + DEG_on_visible_update(bmain, do_time); + return; + } + /* get list of visible scenes and layers */ dag_current_scene_layers(bmain, &listbase); @@ -2357,7 +2415,8 @@ void DAG_on_visible_update(Main *bmain, const bool do_time) oblay = (node) ? node->lay : ob->lay; if ((oblay & lay) & ~scene->lay_updated) { - if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { + /* TODO(sergey): Why do we need armature here now but didn't need before? */ + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE, OB_ARMATURE)) { ob->recalc |= OB_RECALC_DATA; lib_id_recalc_tag(bmain, &ob->id); } @@ -2375,7 +2434,7 @@ void DAG_on_visible_update(Main *bmain, const bool do_time) lib_id_recalc_tag(bmain, &ob->id); } if (ob->dup_group) - dag_group_on_visible_update(ob->dup_group); + dag_group_on_visible_update(scene, ob->dup_group); } } @@ -2609,7 +2668,12 @@ void DAG_ids_flush_tagged(Main *bmain) ListBase *lbarray[MAX_LIBARRAY]; int a; bool do_flush = false; - + + if (!DEG_depsgraph_use_legacy()) { + DEG_ids_flush_tagged(bmain); + return; + } + /* get list of visible scenes and layers */ dag_current_scene_layers(bmain, &listbase); @@ -2653,6 +2717,11 @@ void DAG_ids_check_recalc(Main *bmain, Scene *scene, bool time) int a; bool updated = false; + if (!DEG_depsgraph_use_legacy()) { + DEG_ids_check_recalc(bmain, scene, time); + return; + } + /* loop over all ID types */ a = set_listbasepointers(bmain, lbarray); @@ -2769,6 +2838,11 @@ void DAG_ids_clear_recalc(Main *bmain) void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag) { + if (!DEG_depsgraph_use_legacy()) { + DEG_id_tag_update_ex(bmain, id, flag); + return; + } + if (id == NULL) return; if (G.debug & G_DEBUG_DEPSGRAPH) { @@ -3160,6 +3234,10 @@ short DAG_get_eval_flags_for_object(Scene *scene, void *object) { DagNode *node; + if (!DEG_depsgraph_use_legacy()) { + return DEG_get_eval_flags_for_id(scene->depsgraph, (ID*)object); + } + if (scene->theDag == NULL) { /* Happens when converting objects to mesh from a python script * after modifying scene graph. @@ -3198,3 +3276,286 @@ bool DAG_is_acyclic(Scene *scene) { return scene->theDag->is_acyclic; } + +#else + +/* ********************************************************************* + * Stubs to avoid linking issues and make sure legacy crap is not used * + * ********************************************************************* + */ + +DagNodeQueue *queue_create(int UNUSED(slots)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); + return NULL; +} + +void queue_raz(DagNodeQueue *UNUSED(queue)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); +} + +void queue_delete(DagNodeQueue *UNUSED(queue)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); +} + +void push_queue(DagNodeQueue *UNUSED(queue), DagNode *UNUSED(node)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); +} + +void push_stack(DagNodeQueue *UNUSED(queue), DagNode *UNUSED(node)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); +} + +DagNode *pop_queue(DagNodeQueue *UNUSED(queue)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); + return NULL; +} + +DagNode *get_top_node_queue(DagNodeQueue *UNUSED(queue)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); + return NULL; +} + +DagForest *dag_init(void) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); + return NULL; +} + +DagForest *build_dag(Main *UNUSED(bmain), + Scene *UNUSED(sce), + short UNUSED(mask)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); + return NULL; +} + +void free_forest(DagForest *UNUSED(Dag)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); +} + +DagNode *dag_find_node(DagForest *UNUSED(forest), void *UNUSED(fob)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); + return NULL; +} + +DagNode *dag_add_node(DagForest *UNUSED(forest), void *UNUSED(fob)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); + return NULL; +} + +DagNode *dag_get_node(DagForest *UNUSED(forest), void *UNUSED(fob)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); + return NULL; +} + +DagNode *dag_get_sub_node(DagForest *UNUSED(forest), void *UNUSED(fob)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); + return NULL; +} + +void dag_add_relation(DagForest *UNUSED(forest), + DagNode *UNUSED(fob1), + DagNode *UNUSED(fob2), + short UNUSED(rel), + const char *UNUSED(name)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); +} + +/* debug test functions */ + +void graph_print_queue(DagNodeQueue *UNUSED(nqueue)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); +} + +void graph_print_queue_dist(DagNodeQueue *UNUSED(nqueue)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); +} + +void graph_print_adj_list(DagForest *UNUSED(dag)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); +} + +void DAG_scene_flush_update(Main *UNUSED(bmain), + Scene *UNUSED(sce), + unsigned int UNUSED(lay), + const short UNUSED(time)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); +} + +void DAG_scene_update_flags(Main *UNUSED(bmain), + Scene *UNUSED(scene), + unsigned int UNUSED(lay), + const bool UNUSED(do_time), + const bool UNUSED(do_invisible_flush)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); +} + +/* ******************* DAG FOR ARMATURE POSE ***************** */ + +void DAG_pose_sort(Object *UNUSED(ob)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); +} + +/* ************************ DAG FOR THREADED UPDATE ********************* */ + +void DAG_threaded_update_begin(Scene *UNUSED(scene), + void (*func)(void *node, void *user_data), + void *UNUSED(user_data)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); + (void)func; +} + +void DAG_threaded_update_handle_node_updated(void *UNUSED(node_v), + void (*func)(void *node, void *user_data), + void *UNUSED(user_data)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); + (void)func; +} + +/* ************************ DAG querying ********************* */ + +Object *DAG_get_node_object(void *UNUSED(node_v)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); + return NULL; +} + +const char *DAG_get_node_name(Scene *UNUSED(scene), void *UNUSED(node_v)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); + return "INVALID"; +} + +bool DAG_is_acyclic(Scene *UNUSED(scene)) +{ + BLI_assert(!"Should not be used with new dependnecy graph"); + return false; +} + +/* ************************************ + * This functions are to be supported * + * ************************************ + */ + +void DAG_init(void) +{ + DEG_register_node_types(); +} + +void DAG_exit(void) +{ + DEG_free_node_types(); +} + +/* ************************ API *********************** */ + +void DAG_editors_update_cb(DEG_EditorUpdateIDCb id_func, + DEG_EditorUpdateSceneCb scene_func) +{ + DEG_editors_set_update_cb(id_func, scene_func); +} + +/* Tag all relations for update. */ +void DAG_relations_tag_update(Main *bmain) +{ + DEG_relations_tag_update(bmain); +} + +/* Rebuild dependency graph only for a given scene. */ +void DAG_scene_relations_rebuild(Main *bmain, Scene *scene) +{ + DEG_scene_relations_rebuild(bmain, scene); +} + +/* Create dependency graph if it was cleared or didn't exist yet. */ +void DAG_scene_relations_update(Main *bmain, Scene *scene) +{ + DEG_scene_relations_update(bmain, scene); +} + +void DAG_scene_relations_validate(Main *bmain, Scene *scene) +{ + DEG_debug_scene_relations_validate(bmain, scene); +} + +void DAG_scene_free(Scene *scene) +{ + DEG_scene_graph_free(scene); +} + +void DAG_on_visible_update(Main *bmain, const bool do_time) +{ + DEG_on_visible_update(bmain, do_time); +} + +void DAG_ids_check_recalc(Main *bmain, Scene *scene, bool time) +{ + DEG_ids_check_recalc(bmain, scene, time); +} + +void DAG_id_tag_update(ID *id, short flag) +{ + DEG_id_tag_update_ex(G.main, id, flag); +} + +void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag) +{ + DEG_id_tag_update_ex(bmain, id, flag); +} + +void DAG_id_type_tag(Main *bmain, short idtype) +{ + DEG_id_type_tag(bmain, idtype); +} + +int DAG_id_type_tagged(Main *bmain, short idtype) +{ + return DEG_id_type_tagged(bmain, idtype); +} + +void DAG_ids_clear_recalc(Main *bmain) +{ + DEG_ids_clear_recalc(bmain); +} + +short DAG_get_eval_flags_for_object(Scene *scene, void *object) +{ + return DEG_get_eval_flags_for_id(scene->depsgraph, (ID*)object); +} + +void DAG_ids_flush_tagged(Main *bmain) +{ + DEG_ids_flush_tagged(bmain); +} + +/* ************************ DAG DEBUGGING ********************* */ + +void DAG_print_dependencies(Main *UNUSED(bmain), + Scene *scene, + Object *UNUSED(ob)) +{ + DEG_debug_graphviz(scene->depsgraph, stdout, "Depsgraph", false); +} + +#endif diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index ce118fe9fde..543d2de939a 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -115,6 +115,8 @@ #include "BKE_texture.h" #include "BKE_world.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #ifdef WITH_PYTHON @@ -1081,8 +1083,7 @@ void BKE_libblock_free_us(Main *bmain, void *idv) /* test users */ Main *BKE_main_new(void) { Main *bmain = MEM_callocN(sizeof(Main), "new main"); - bmain->eval_ctx = MEM_callocN(sizeof(EvaluationContext), - "EvaluationContext"); + bmain->eval_ctx = DEG_evaluation_context_new(DAG_EVAL_VIEWPORT); bmain->lock = MEM_mallocN(sizeof(SpinLock), "main lock"); BLI_spin_init((SpinLock *)bmain->lock); return bmain; @@ -1149,7 +1150,7 @@ void BKE_main_free(Main *mainvar) BLI_spin_end((SpinLock *)mainvar->lock); MEM_freeN(mainvar->lock); - MEM_freeN(mainvar->eval_ctx); + DEG_evaluation_context_free(mainvar->eval_ctx); MEM_freeN(mainvar); } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 735e4358cb8..37a98eae58b 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -61,6 +61,7 @@ #include "BKE_object.h" #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" enum { MESHCMP_DVERT_WEIGHTMISMATCH = 1, @@ -2397,8 +2398,8 @@ Mesh *BKE_mesh_new_from_object( * only contains for_render flag. As soon as CoW is * implemented, this is to be rethinked. */ - EvaluationContext eval_ctx = {0}; - eval_ctx.mode = DAG_EVAL_RENDER; + EvaluationContext eval_ctx; + DEG_evaluation_context_init(&eval_ctx, DAG_EVAL_RENDER); BKE_displist_make_mball_forRender(&eval_ctx, sce, ob, &disp); BKE_mesh_from_metaball(&disp, tmpmesh); BKE_displist_free(&disp); diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 76c20adf8c5..972a93b4a35 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -57,6 +57,8 @@ #include "BKE_material.h" #include "BKE_image.h" +#include "DEG_depsgraph.h" + #ifdef WITH_LEGACY_DEPSGRAPH # define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH) printf #else diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index f810630c83b..3d87279e054 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -89,6 +89,8 @@ #include "BKE_unit.h" #include "BKE_world.h" +#include "DEG_depsgraph.h" + #include "RE_engine.h" #include "PIL_time.h" @@ -193,6 +195,7 @@ Scene *BKE_scene_copy(Scene *sce, int type) scen->ed = NULL; scen->theDag = NULL; + scen->depsgraph = NULL; scen->obedit = NULL; scen->stats = NULL; scen->fps_info = NULL; @@ -431,6 +434,8 @@ void BKE_scene_free(Scene *sce) } DAG_scene_free(sce); + if (sce->depsgraph) + DEG_graph_free(sce->depsgraph); if (sce->nodetree) { ntreeFreeTree(sce->nodetree); @@ -1167,6 +1172,7 @@ void BKE_scene_frame_set(struct Scene *scene, double cfra) scene->r.cfra = (int)intpart; } +#ifdef WITH_LEGACY_DEPSGRAPH /* drivers support/hacks * - this method is called from scene_update_tagged_recursive(), so gets included in viewport + render * - these are always run since the depsgraph can't handle non-object data @@ -1267,6 +1273,7 @@ static void scene_depsgraph_hack(EvaluationContext *eval_ctx, Scene *scene, Scen } } } +#endif /* WITH_LEGACY_DEPSGRAPH */ /* That's like really a bummer, because currently animation data for armatures * might want to use pose, and pose might be missing on the object. @@ -1318,7 +1325,12 @@ static void scene_do_rb_simulation_recursive(Scene *scene, float ctime) * would pollute STDERR with whole bunch of timing information which then * could be parsed and nicely visualized. */ -#undef DETAILED_ANALYSIS_OUTPUT +#ifdef WITH_LEGACY_DEPSGRAPH +# undef DETAILED_ANALYSIS_OUTPUT +#else +/* ALWAYS KEEY DISABLED! */ +# undef DETAILED_ANALYSIS_OUTPUT +#endif /* Mballs evaluation uses BKE_scene_base_iter_next which calls * duplilist for all objects in the scene. This leads to conflict @@ -1330,6 +1342,7 @@ static void scene_do_rb_simulation_recursive(Scene *scene, float ctime) */ #define MBALL_SINGLETHREAD_HACK +#ifdef WITH_LEGACY_DEPSGRAPH typedef struct StatisicsEntry { struct StatisicsEntry *next, *prev; Object *object; @@ -1619,6 +1632,7 @@ static void scene_update_tagged_recursive(EvaluationContext *eval_ctx, Main *bma BKE_mask_update_scene(bmain, scene); } +#endif /* WITH_LEGACY_DEPSGRAPH */ static bool check_rendered_viewport_visible(Main *bmain) { @@ -1670,13 +1684,26 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene) void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *scene) { Scene *sce_iter; - +#ifdef WITH_LEGACY_DEPSGRAPH + bool use_new_eval = !DEG_depsgraph_use_legacy(); +#endif + /* keep this first */ BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_PRE); /* (re-)build dependency graph if needed */ - for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) + for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) { DAG_scene_relations_update(bmain, sce_iter); + /* Uncomment this to check if graph was properly tagged for update. */ +#if 0 +#ifdef WITH_LEGACY_DEPSGRAPH + if (use_new_eval) +#endif + { + DAG_scene_relations_validate(bmain, sce_iter); + } +#endif + } /* flush editing data if needed */ prepare_mesh_for_viewport_render(bmain, scene); @@ -1697,7 +1724,17 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc * * in the future this should handle updates for all datablocks, not * only objects and scenes. - brecht */ - scene_update_tagged_recursive(eval_ctx, bmain, scene, scene); +#ifdef WITH_LEGACY_DEPSGRAPH + if (use_new_eval) { + DEG_evaluate_on_refresh(eval_ctx, scene->depsgraph, scene); + } + else { + scene_update_tagged_recursive(eval_ctx, bmain, scene, scene); + } +#else + DEG_evaluate_on_refresh(eval_ctx, bmain, scene->depsgraph, scene); +#endif + /* update sound system animation (TODO, move to depsgraph) */ BKE_sound_update_scene(bmain, scene); @@ -1715,7 +1752,8 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc * Need to do this so changing material settings from the graph/dopesheet * will update stuff in the viewport. */ - if (DAG_id_type_tagged(bmain, ID_MA)) { +#ifdef WITH_LEGACY_DEPSGRAPH + if (!use_new_eval && DAG_id_type_tagged(bmain, ID_MA)) { Material *material; float ctime = BKE_scene_frame_get(scene); @@ -1730,7 +1768,7 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc } /* Also do the same for node trees. */ - if (DAG_id_type_tagged(bmain, ID_NT)) { + if (!use_new_eval && DAG_id_type_tagged(bmain, ID_NT)) { float ctime = BKE_scene_frame_get(scene); FOREACH_NODETREE(bmain, ntree, id) @@ -1741,9 +1779,12 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc } FOREACH_NODETREE_END } +#endif /* notify editors and python about recalc */ BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_POST); + + /* Inform editors about possible changes. */ DAG_ids_check_recalc(bmain, scene, false); /* clear recalc flags */ @@ -1763,6 +1804,12 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, #ifdef DETAILED_ANALYSIS_OUTPUT double start_time = PIL_check_seconds_timer(); #endif +#ifdef WITH_LEGACY_DEPSGRAPH + bool use_new_eval = !DEG_depsgraph_use_legacy(); +#else + /* TODO(sergey): Pass to evaluation routines instead of storing layer in the graph? */ + (void) do_invisible_flush; +#endif /* keep this first */ BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_PRE); @@ -1772,12 +1819,16 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, * call this at the start so modifiers with textures don't lag 1 frame */ BKE_image_update_frame(bmain, sce->r.cfra); +#ifdef WITH_LEGACY_DEPSGRAPH /* rebuild rigid body worlds before doing the actual frame update * this needs to be done on start frame but animation playback usually starts one frame later * we need to do it here to avoid rebuilding the world on every simulation change, which can be very expensive */ - scene_rebuild_rbw_recursive(sce, ctime); - + if (!use_new_eval) { + scene_rebuild_rbw_recursive(sce, ctime); + } +#endif + BKE_sound_set_cfra(sce->r.cfra); /* clear animation overrides */ @@ -1786,14 +1837,18 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, for (sce_iter = sce; sce_iter; sce_iter = sce_iter->set) DAG_scene_relations_update(bmain, sce_iter); - /* flush recalc flags to dependencies, if we were only changing a frame - * this would not be necessary, but if a user or a script has modified - * some datablock before BKE_scene_update_tagged was called, we need the flush */ - DAG_ids_flush_tagged(bmain); +#ifdef WITH_LEGACY_DEPSGRAPH + if (!use_new_eval) { + /* flush recalc flags to dependencies, if we were only changing a frame + * this would not be necessary, but if a user or a script has modified + * some datablock before BKE_scene_update_tagged was called, we need the flush */ + DAG_ids_flush_tagged(bmain); - /* Following 2 functions are recursive - * so don't call within 'scene_update_tagged_recursive' */ - DAG_scene_update_flags(bmain, sce, lay, true, do_invisible_flush); // only stuff that moves or needs display still + /* Following 2 functions are recursive + * so don't call within 'scene_update_tagged_recursive' */ + DAG_scene_update_flags(bmain, sce, lay, true, do_invisible_flush); // only stuff that moves or needs display still + } +#endif BKE_mask_evaluate_all_masks(bmain, ctime, true); @@ -1807,8 +1862,12 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, * can be overridden by settings from Scene, which owns the Texture through a hierarchy * such as Scene->World->MTex/Texture) can still get correctly overridden. */ - BKE_animsys_evaluate_all_animation(bmain, sce, ctime); - /*...done with recursive funcs */ +#ifdef WITH_LEGACY_DEPSGRAPH + if (!use_new_eval) { + BKE_animsys_evaluate_all_animation(bmain, sce, ctime); + /*...done with recursive funcs */ + } +#endif /* clear "LIB_DOIT" flag from all materials, to prevent infinite recursion problems later * when trying to find materials with drivers that need evaluating [#32017] @@ -1818,19 +1877,38 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, /* run rigidbody sim */ /* NOTE: current position is so that rigidbody sim affects other objects, might change in the future */ - scene_do_rb_simulation_recursive(sce, ctime); - +#ifdef WITH_LEGACY_DEPSGRAPH + if (!use_new_eval) { + scene_do_rb_simulation_recursive(sce, ctime); + } +#endif + /* BKE_object_handle_update() on all objects, groups and sets */ - scene_update_tagged_recursive(eval_ctx, bmain, sce, sce); +#ifdef WITH_LEGACY_DEPSGRAPH + if (use_new_eval) { + DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay); + } + else { + scene_update_tagged_recursive(eval_ctx, bmain, sce, sce); + } +#else + DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay); +#endif + /* update sound system animation (TODO, move to depsgraph) */ BKE_sound_update_scene(bmain, sce); - scene_depsgraph_hack(eval_ctx, sce, sce); +#ifdef WITH_LEGACY_DEPSGRAPH + if (!use_new_eval) { + scene_depsgraph_hack(eval_ctx, sce, sce); + } +#endif /* notify editors and python about recalc */ BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_SCENE_UPDATE_POST); BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_POST); + /* Inform editors about possible changes. */ DAG_ids_check_recalc(bmain, sce, true); /* clear recalc flags */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 6634767d412..c736e54c4e9 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5567,6 +5567,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) SceneRenderLayer *srl; sce->theDag = NULL; + sce->depsgraph = NULL; sce->obedit = NULL; sce->stats = NULL; sce->fps_info = NULL; diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt new file mode 100644 index 00000000000..014bcb40163 --- /dev/null +++ b/source/blender/depsgraph/CMakeLists.txt @@ -0,0 +1,116 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2014, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Joshua Leung, Lukas Toenne +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . + ./intern + ./util + ../blenkernel + ../blenlib + ../bmesh + ../makesdna + ../makesrna + ../modifiers + ../windowmanager + ../../../intern/atomic + ../../../intern/guardedalloc +) + +set(INC_SYS +) + +set(SRC + intern/depsgraph.cc + intern/depsnode.cc + intern/depsnode_component.cc + intern/depsnode_operation.cc + intern/depsgraph_build.cc + intern/depsgraph_build_nodes.cc + intern/depsgraph_build_relations.cc + intern/depsgraph_debug.cc + intern/depsgraph_eval.cc + intern/depsgraph_query.cc + intern/depsgraph_queue.cc + intern/depsgraph_tag.cc + intern/depsgraph_type_defines.cc + util/depsgraph_util_cycle.cc + util/depsgraph_util_pchanmap.cc + util/depsgraph_util_transitive.cc + + DEG_depsgraph.h + DEG_depsgraph_build.h + DEG_depsgraph_debug.h + DEG_depsgraph_query.h + intern/depsgraph.h + intern/depsnode.h + intern/depsnode_component.h + intern/depsnode_operation.h + intern/depsnode_opcodes.h + intern/depsgraph_build.h + intern/depsgraph_debug.h + intern/depsgraph_intern.h + intern/depsgraph_queue.h + intern/depsgraph_types.h + + util/depsgraph_util_cycle.h + util/depsgraph_util_function.h + util/depsgraph_util_hash.h + util/depsgraph_util_map.h + util/depsgraph_util_pchanmap.h + util/depsgraph_util_set.h + util/depsgraph_util_transitive.h +) + +TEST_UNORDERED_MAP_SUPPORT() +if(HAVE_STD_UNORDERED_MAP_HEADER) + if(HAVE_UNORDERED_MAP_IN_STD_NAMESPACE) + add_definitions(-DDEG_STD_UNORDERED_MAP) + else() + if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE) + add_definitions(-DDEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) + else() + add_definitions(-DDEG_NO_UNORDERED_MAP) + message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)") + endif() + endif() +else() + if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE) + add_definitions(-DDEG_TR1_UNORDERED_MAP) + else() + add_definitions(-DDEG_NO_UNORDERED_MAP) + message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)") + endif() +endif() + +if(WITH_LEGACY_DEPSGRAPH) + add_definitions(-DWITH_LEGACY_DEPSGRAPH) +endif() + +if(WITH_BOOST) + list(APPEND INC_SYS ${BOOST_INCLUDE_DIR}) + add_definitions(-DHAVE_BOOST_FUNCTION_BINDINGS) +endif() + +blender_add_lib(bf_depsgraph "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h new file mode 100644 index 00000000000..9fc50476e47 --- /dev/null +++ b/source/blender/depsgraph/DEG_depsgraph.h @@ -0,0 +1,210 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + * + * Public API for Depsgraph + */ + +#ifndef __DEG_DEPSGRAPH_H__ +#define __DEG_DEPSGRAPH_H__ + +/* Dependency Graph + * + * The dependency graph tracks relations between various pieces of data in + * a Blender file, but mainly just those which make up scene data. It is used + * to determine the set of operations need to ensure that all data has been + * correctly evaluated in response to changes, based on dependencies and visibility + * of affected data. + * + * + * Evaluation Engine + * + * The evaluation takes the operation-nodes the Depsgraph has tagged for updating, + * and schedules them up for being evaluated/executed such that the all dependency + * relationship constraints are satisfied. + */ + +/* ************************************************* */ +/* Forward-defined typedefs for core types + * - These are used in all depsgraph code and by all callers of Depsgraph API... + */ + +/* Dependency Graph */ +typedef struct Depsgraph Depsgraph; + +/* ------------------------------------------------ */ + +struct EvaluationContext; +struct Main; + +struct PointerRNA; +struct PropertyRNA; + +#ifdef __cplusplus +extern "C" { +#endif + +bool DEG_depsgraph_use_legacy(void); +void DEG_depsgraph_switch_to_legacy(void); +void DEG_depsgraph_switch_to_new(void); + +/* ************************************************ */ +/* Depsgraph API */ + +/* CRUD ------------------------------------------- */ + +// Get main depsgraph instance from context! + +/* Create new Depsgraph instance */ +// TODO: what args are needed here? What's the building-graph entry point? +Depsgraph *DEG_graph_new(void); + +/* Free Depsgraph itself and all its data */ +void DEG_graph_free(Depsgraph *graph); + +/* Node Types Registry ---------------------------- */ + +/* Register all node types */ +void DEG_register_node_types(void); + +/* Free node type registry on exit */ +void DEG_free_node_types(void); + +/* Update Tagging -------------------------------- */ + +/* Tag node(s) associated with states such as time and visibility */ +void DEG_scene_update_flags(Depsgraph *graph, const bool do_time); + +/* Update dependency graph when visible scenes/layers changes. */ +void DEG_graph_on_visible_update(struct Main *bmain, struct Scene *scene); + +/* Update all dependency graphs when visible scenes/layers changes. */ +void DEG_on_visible_update(struct Main *bmain, const bool do_time); + +/* Tag node(s) associated with changed data for later updates */ +void DEG_graph_id_tag_update(struct Main *bmain, + Depsgraph *graph, + struct ID *id); +void DEG_graph_data_tag_update(Depsgraph *graph, const struct PointerRNA *ptr); +void DEG_graph_property_tag_update(Depsgraph *graph, const struct PointerRNA *ptr, const struct PropertyRNA *prop); + +/* Tag given ID for an update in all the dependency graphs. */ +void DEG_id_tag_update(struct ID *id, short flag); +void DEG_id_tag_update_ex(struct Main *bmain, + struct ID *id, + short flag); + +/* Tag given ID type for update. + * + * Used by all sort of render engines to quickly check if + * IDs of a given type need to be checked for update. + */ +void DEG_id_type_tag(struct Main *bmain, short idtype); + +void DEG_ids_clear_recalc(struct Main *bmain); + +/* Update Flushing ------------------------------- */ + +/* Flush updates */ +void DEG_graph_flush_updates(struct Main *bmain, Depsgraph *graph); + +/* Flush updates for all IDs */ +void DEG_ids_flush_tagged(struct Main *bmain); + +/* Check if something was changed in the database and inform + * editors about this. + */ +void DEG_ids_check_recalc(struct Main *bmain, + struct Scene *scene, + bool time); + +/* Clear all update tags + * - For aborted updates, or after successful evaluation + */ +void DEG_graph_clear_tags(Depsgraph *graph); + +/* ************************************************ */ +/* Evaluation Engine API */ + +/* Evaluation Context ---------------------------- */ + +/* Create new evaluation context. */ +struct EvaluationContext *DEG_evaluation_context_new(int mode); + +/* Initialize evaluation context. + * Used by the areas which currently overrides the context or doesn't have + * access to a proper one. + */ +void DEG_evaluation_context_init(struct EvaluationContext *eval_ctx, int mode); + +/* Free evaluation context. */ +void DEG_evaluation_context_free(struct EvaluationContext *eval_ctx); + +/* Graph Evaluation ----------------------------- */ + +/* Frame changed recalculation entry point + * < context_type: context to perform evaluation for + * < ctime: (frame) new frame to evaluate values on + */ +void DEG_evaluate_on_framechange(struct EvaluationContext *eval_ctx, + struct Main *bmain, + Depsgraph *graph, + float ctime, + const int layer); + +/* Data changed recalculation entry point. + * < context_type: context to perform evaluation for + * < layers: visible layers bitmask to update the graph for + */ +void DEG_evaluate_on_refresh_ex(struct EvaluationContext *eval_ctx, + Depsgraph *graph, + const int layers); + +/* Data changed recalculation entry point. + * < context_type: context to perform evaluation for + */ +void DEG_evaluate_on_refresh(struct EvaluationContext *eval_ctx, + Depsgraph *graph, + struct Scene *scene); + +/* Editors Integration -------------------------- */ + +/* Mechanism to allow editors to be informed of depsgraph updates, + * to do their own updates based on changes. + */ + +typedef void (*DEG_EditorUpdateIDCb)(struct Main *bmain, struct ID *id); +typedef void (*DEG_EditorUpdateSceneCb)(struct Main *bmain, + struct Scene *scene, + int updated); + +/* Set callbacks which are being called when depsgraph changes. */ +void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func, + DEG_EditorUpdateSceneCb scene_func); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __DEG_DEPSGRAPH_H__ */ diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h new file mode 100644 index 00000000000..08b83ac2ea1 --- /dev/null +++ b/source/blender/depsgraph/DEG_depsgraph_build.h @@ -0,0 +1,117 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): Lukas Toenne + * + * ***** END GPL LICENSE BLOCK ***** + * + * Public API for Depsgraph + */ + +#ifndef __DEG_DEPSGRAPH_BUILD_H__ +#define __DEG_DEPSGRAPH_BUILD_H__ + +/* ************************************************* */ + +/* Dependency Graph */ +struct Depsgraph; + +/* ------------------------------------------------ */ + +struct Main; +struct Scene; + +struct PointerRNA; +struct PropertyRNA; + +#ifdef __cplusplus +extern "C" { +#endif + +/* Graph Building -------------------------------- */ + +/* Build depsgraph for the given scene, and dump results in given graph container */ +void DEG_graph_build_from_scene(struct Depsgraph *graph, struct Main *bmain, struct Scene *scene); + +/* Tag relations from the given graph for update. */ +void DEG_graph_tag_relations_update(struct Depsgraph *graph); + +/* Tag all relations in the database for update.*/ +void DEG_relations_tag_update(struct Main *bmain); + +/* Create new graph if didn't exist yet, + * or update relations if graph was tagged for update. + */ +void DEG_scene_relations_update(struct Main *bmain, struct Scene *scene); + +/* Rebuild dependency graph only for a given scene. */ +void DEG_scene_relations_rebuild(struct Main *bmain, + struct Scene *scene); + +/* Delete scene graph. */ +void DEG_scene_graph_free(struct Scene *scene); + +/* Add Dependencies ----------------------------- */ + +/* Handle for components to define their dependencies from callbacks. + * This is generated by the depsgraph and passed to dependency callbacks + * as a symbolic reference to the current DepsNode. + * All relations will be defined in reference to that node. + */ +struct DepsNodeHandle; + +struct Object; + +typedef enum eDepsSceneComponentType { + DEG_SCENE_COMP_PARAMETERS, /* Parameters Component - Default when nothing else fits (i.e. just SDNA property setting) */ + DEG_SCENE_COMP_ANIMATION, /* Animation Component */ // XXX: merge in with parameters? + DEG_SCENE_COMP_SEQUENCER, /* Sequencer Component (Scene Only) */ +} eDepsSceneComponentType; + +typedef enum eDepsObjectComponentType { + DEG_OB_COMP_PARAMETERS, /* Parameters Component - Default when nothing else fits (i.e. just SDNA property setting) */ + DEG_OB_COMP_PROXY, /* Generic "Proxy-Inherit" Component */ // XXX: Also for instancing of subgraphs? + DEG_OB_COMP_ANIMATION, /* Animation Component */ // XXX: merge in with parameters? + DEG_OB_COMP_TRANSFORM, /* Transform Component (Parenting/Constraints) */ + DEG_OB_COMP_GEOMETRY, /* Geometry Component (DerivedMesh/Displist) */ + + /* Evaluation-Related Outer Types (with Subdata) */ + DEG_OB_COMP_EVAL_POSE, /* Pose Component - Owner/Container of Bones Eval */ + DEG_OB_COMP_BONE, /* Bone Component - Child/Subcomponent of Pose */ + + DEG_OB_COMP_EVAL_PARTICLES, /* Particle Systems Component */ + DEG_OB_COMP_SHADING, /* Material Shading Component */ +} eDepsObjectComponentType; + +void DEG_add_scene_relation(struct DepsNodeHandle *node, struct Scene *scene, eDepsSceneComponentType component, const char *description); +void DEG_add_object_relation(struct DepsNodeHandle *node, struct Object *ob, eDepsObjectComponentType component, const char *description); +void DEG_add_bone_relation(struct DepsNodeHandle *handle, struct Object *ob, const char *bone_name, eDepsObjectComponentType component, const char *description); + +/* TODO(sergey): Remove once all geometry update is granular. */ +void DEG_add_special_eval_flag(struct Depsgraph *graph, struct ID *id, short flag); + +/* ************************************************ */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __DEG_DEPSGRAPH_BUILD_H__ */ diff --git a/source/blender/depsgraph/DEG_depsgraph_debug.h b/source/blender/depsgraph/DEG_depsgraph_debug.h new file mode 100644 index 00000000000..60e9a021854 --- /dev/null +++ b/source/blender/depsgraph/DEG_depsgraph_debug.h @@ -0,0 +1,107 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2014 Blender Foundation. + * All rights reserved. + * + * Original Author: Lukas Toenne + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + * + * Public API for Querying and Filtering Depsgraph + */ + +#ifndef __DEG_DEPSGRAPH_DEBUG_H__ +#define __DEG_DEPSGRAPH_DEBUG_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct DepsgraphSettings; +struct GHash; +struct ID; + +struct Depsgraph; +struct DepsNode; +struct DepsRelation; + +/* ************************************************ */ +/* Statistics */ + +typedef struct DepsgraphStatsTimes { + float duration_last; +} DepsgraphStatsTimes; + +typedef struct DepsgraphStatsComponent { + struct DepsgraphStatsComponent *next, *prev; + + char name[64]; + DepsgraphStatsTimes times; +} DepsgraphStatsComponent; + +typedef struct DepsgraphStatsID { + struct ID *id; + + DepsgraphStatsTimes times; + ListBase components; +} DepsgraphStatsID; + +typedef struct DepsgraphStats { + struct GHash *id_stats; +} DepsgraphStats; + +struct DepsgraphStats *DEG_stats(void); + +void DEG_stats_verify(void); + +struct DepsgraphStatsID *DEG_stats_id(struct ID *id); + +/* ------------------------------------------------ */ + +void DEG_stats_simple(const struct Depsgraph *graph, + size_t *r_outer, + size_t *r_operations, + size_t *r_relations); + +/* ************************************************ */ +/* Diagram-Based Graph Debugging */ + +void DEG_debug_graphviz(const struct Depsgraph *graph, FILE *stream, const char *label, bool show_eval); + +/* ************************************************ */ + +/* Compare two dependency graphs. */ +bool DEG_debug_compare(const struct Depsgraph *graph1, + const struct Depsgraph *graph2); + +/* Check that dependnecies in the graph are really up to date. */ +bool DEG_debug_scene_relations_validate(struct Main *bmain, + struct Scene *scene); + + +/* Perform consistency check on the graph. */ +bool DEG_debug_consistency_check(struct Depsgraph *graph); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __DEG_DEPSGRAPH_DEBUG_H__ */ diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h new file mode 100644 index 00000000000..000497cfac9 --- /dev/null +++ b/source/blender/depsgraph/DEG_depsgraph_query.h @@ -0,0 +1,191 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + * + * Public API for Querying and Filtering Depsgraph + */ + +#ifndef __DEG_DEPSGRAPH_QUERY_H__ +#define __DEG_DEPSGRAPH_QUERY_H__ + +struct ListBase; +struct ID; + +struct Depsgraph; +struct DepsNode; +struct DepsRelation; + +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************ */ +/* Type Defines */ + +/* FilterPredicate Callback + * + * Defines a callback function which can be supplied to check whether a + * node is relevant or not. + * + * < graph: Depsgraph that we're traversing + * < node: The node to check + * < userdata: FilterPredicate state data (as needed) + * > returns: True if node is relevant + */ +typedef bool (*DEG_FilterPredicate)(const struct Depsgraph *graph, const struct DepsNode *node, void *userdata); + + +/* Node Operation + * + * Performs some action on the given node, provided that the node was + * deemed to be relevant to operate on. + * + * < graph: Depsgraph that we're traversing + * < node: The node to perform operation on/with + * < userdata: Node Operation's state data (as needed) + * > returns: True if traversal should be aborted at this point + */ +typedef bool (*DEG_NodeOperation)(const struct Depsgraph *graph, struct DepsNode *node, void *userdata); + +/* ************************************************ */ +/* Low-Level Filtering API */ + +/* Create a filtered copy of the given graph which contains only the + * nodes which fulfill the criteria specified using the FilterPredicate + * passed in. + * + * < graph: The graph to be copied and filtered + * < filter: FilterPredicate used to check which nodes should be included + * (If null, full graph is copied as-is) + * < userdata: State data for filter (as necessary) + * + * > returns: a full copy of all the relevant nodes - the matching subgraph + */ +// XXX: is there any need for extra settings/options for how the filtering goes? +Depsgraph *DEG_graph_filter(const struct Depsgraph *graph, DEG_FilterPredicate *filter, void *userdata); + + +/* Traverse nodes in graph which are deemed relevant, + * performing the provided operation on the nodes. + * + * < graph: The graph to perform operations on + * < filter: FilterPredicate used to check which nodes should be included + * (If null, all nodes are considered valid targets) + * < filter_data: Custom state data for FilterPredicate + * (Note: This can be the same as op_data, where appropriate) + * < op: NodeOperation to perform on each node + * (If null, no graph traversal is performed for efficiency) + * < op_data: Custom state data for NodeOperation + * (Note: This can be the same as filter_data, where appropriate) + */ +void DEG_graph_traverse(const struct Depsgraph *graph, + DEG_FilterPredicate *filter, void *filter_data, + DEG_NodeOperation *op, void *op_data); + +/* ************************************************ */ +/* Node-Based Operations */ +// XXX: do we want to be able to attach conditional requirements here? + +/* Find an (outer) node matching given conditions + * ! Assumes that there will only be one such node, or that only the first one matters + * + * < graph: a dependency graph which may or may not contain a node matching these requirements + * < query: query conditions for the criteria that the node must satisfy + */ +//DepsNode *DEG_node_find(const Depsgraph *graph, DEG_QueryConditions *query); + +/* Topology Queries (Direct) ---------------------- */ + +/* Get list of nodes which directly depend on given node + * + * > result: list to write results to + * < node: the node to find the children/dependents of + */ +void DEG_node_get_children(struct ListBase *result, const struct DepsNode *node); + + +/* Get list of nodes which given node directly depends on + * + * > result: list to write results to + * < node: the node to find the dependencies of + */ +void DEG_node_get_dependencies(struct ListBase *result, const struct DepsNode *node); + + +/* Topology Queries (Subgraph) -------------------- */ +// XXX: given that subgraphs potentially involve many interconnected nodes, we currently +// just spit out a copy of the subgraph which matches. This works well for the cases +// where these are used - mostly for efficient updating of subsets of the nodes. + +// XXX: allow supplying a filter predicate to provide further filtering/pruning? + + +/* Get all descendants of a node + * + * That is, get the subgraph / subset of nodes which are dependent + * on the results of the given node. + */ +Depsgraph *DEG_node_get_descendants(const struct Depsgraph *graph, const struct DepsNode *node); + + +/* Get all ancestors of a node + * + * That is, get the subgraph / subset of nodes which the given node + * is dependent on in order to be evaluated. + */ +Depsgraph *DEG_node_get_ancestors(const struct Depsgraph *graph, const struct DepsNode *node); + +/* ************************************************ */ +/* Higher-Level Queries */ + +/* Get ID-blocks which would be affected if specified ID is modified + * < only_direct: True = Only ID-blocks with direct relationships to ID-block will be returned + * + * > result: (LinkData : ID) a list of ID-blocks matching the specified criteria + * > returns: number of matching ID-blocks + */ +size_t DEG_query_affected_ids(struct ListBase *result, const struct ID *id, const bool only_direct); + + +/* Get ID-blocks which are needed to update/evaluate specified ID + * < only_direct: True = Only ID-blocks with direct relationships to ID-block will be returned + * + * > result: (LinkData : ID) a list of ID-blocks matching the specified criteria + * > returns: number of matching ID-blocks + */ +size_t DEG_query_required_ids(struct ListBase *result, const struct ID *id, const bool only_direct); + +/* ************************************************ */ + +/* Check if given ID type was tagged for update. */ +bool DEG_id_type_tagged(struct Main *bmain, short idtype); + +/* Get additional evaluation flags for the given ID. */ +short DEG_get_eval_flags_for_id(struct Depsgraph *graph, struct ID *id); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __DEG_DEPSGRAPH_QUERY_H__ */ diff --git a/source/blender/depsgraph/SConscript b/source/blender/depsgraph/SConscript new file mode 100644 index 00000000000..dd0552e19a2 --- /dev/null +++ b/source/blender/depsgraph/SConscript @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2013, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Nathan Letwory, Joshua Leung. +# +# ***** END GPL LICENSE BLOCK ***** + +Import('env') + +sources = env.Glob('intern/*.cc') + env.Glob('util/*.cc') + +incs = [ + '.', + './intern', + './util', + '#/intern/atomic', + '#/intern/guardedalloc', + '../bmesh', + '../blenlib', + '../blenkernel', + '../makesdna', + '../makesrna', + '../modifiers', + '../windowmanager', + ] + +defs = [] + +if env['WITH_BF_BOOST']: + incs.append(env['BF_BOOST_INC']) + defs.append('HAVE_BOOST_FUNCTION_BINDINGS') + +if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): + incs.append(env['BF_PTHREADS_INC']) + + +if env['WITH_UNORDERED_MAP_SUPPORT']: + if env['UNORDERED_MAP_HEADER'] == 'unordered_map': + if env['UNORDERED_MAP_NAMESPACE'] == 'std': + defs.append('DEG_STD_UNORDERED_MAP') + elif env['UNORDERED_MAP_NAMESPACE'] == 'std::tr1': + defs.append('DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE') + elif env['UNORDERED_MAP_NAMESPACE'] == 'std::tr1': + defs.append('DEG_TR1_UNORDERED_MAP') +else: + print("-- Replacing unordered_map/set with map/set (warning: slower!)") + defs.append('DEG_NO_UNORDERED_MAP') + +if env['WITH_BF_LEGACY_DEPSGRAPH']: + defs.append('WITH_LEGACY_DEPSGRAPH') + +env.BlenderLib(libname='bf_depsgraph', sources=sources, + includes=incs, defines=defs, + libtype=['core', 'player'], priority=[200, 40]) diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc new file mode 100644 index 00000000000..c519f1d498e --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -0,0 +1,469 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + * + * Core routines for how the Depsgraph works + */ + +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" + +extern "C" { +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_constraint_types.h" +#include "DNA_key_types.h" +#include "DNA_object_types.h" +#include "DNA_sequence_types.h" + +#include "RNA_access.h" +} + +#include "DEG_depsgraph.h" +#include "depsgraph.h" /* own include */ +#include "depsnode.h" +#include "depsnode_operation.h" +#include "depsnode_component.h" +#include "depsgraph_intern.h" + +static DEG_EditorUpdateIDCb deg_editor_update_id_cb = NULL; +static DEG_EditorUpdateSceneCb deg_editor_update_scene_cb = NULL; + +Depsgraph::Depsgraph() + : root_node(NULL), + need_update(false), + layers((1 << 20) - 1) +{ + BLI_spin_init(&lock); +} + +Depsgraph::~Depsgraph() +{ + /* Free root node - it won't have been freed yet... */ + clear_id_nodes(); + clear_subgraph_nodes(); + if (this->root_node != NULL) { + OBJECT_GUARDED_DELETE(this->root_node, RootDepsNode); + } + BLI_spin_end(&lock); +} + +/* Query Conditions from RNA ----------------------- */ + +static bool pointer_to_id_node_criteria(const PointerRNA *ptr, + const PropertyRNA *prop, + ID **id) +{ + if (!ptr->type) + return false; + + if (!prop) { + if (RNA_struct_is_ID(ptr->type)) { + *id = (ID *)ptr->data; + return true; + } + } + + return false; +} + +static bool pointer_to_component_node_criteria(const PointerRNA *ptr, + const PropertyRNA *prop, + ID **id, + eDepsNode_Type *type, + string *subdata) +{ + if (!ptr->type) + return false; + + /* Set default values for returns. */ + *id = (ID *)ptr->id.data; /* For obvious reasons... */ + *subdata = ""; /* Default to no subdata (e.g. bone) name + * lookup in most cases. */ + + /* Handling of commonly known scenarios... */ + if (ptr->type == &RNA_PoseBone) { + bPoseChannel *pchan = (bPoseChannel *)ptr->data; + + /* Bone - generally, we just want the bone component... */ + *type = DEPSNODE_TYPE_BONE; + *subdata = pchan->name; + + return true; + } + else if (ptr->type == &RNA_Bone) { + Bone *bone = (Bone *)ptr->data; + + /* armature-level bone, but it ends up going to bone component anyway */ + // TODO: the ID in thise case will end up being bArmature, not Object as needed! + *type = DEPSNODE_TYPE_BONE; + *subdata = bone->name; + //*id = ... + + return true; + } + else if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) { + Object *ob = (Object *)ptr->id.data; + bConstraint *con = (bConstraint *)ptr->data; + + /* object or bone? */ + if (BLI_findindex(&ob->constraints, con) != -1) { + /* object transform */ + // XXX: for now, we can't address the specific constraint or the constraint stack... + *type = DEPSNODE_TYPE_TRANSFORM; + return true; + } + else if (ob->pose) { + bPoseChannel *pchan; + for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) { + if (BLI_findindex(&pchan->constraints, con) != -1) { + /* bone transforms */ + *type = DEPSNODE_TYPE_BONE; + *subdata = pchan->name; + return true; + } + } + } + } + else if (RNA_struct_is_a(ptr->type, &RNA_Modifier)) { + //ModifierData *md = (ModifierData *)ptr->data; + + /* Modifier */ + /* NOTE: subdata is not the same as "operation name", + * so although we have unique ops for modifiers, + * we can't lump them together + */ + *type = DEPSNODE_TYPE_BONE; + //*subdata = md->name; + + return true; + } + else if (ptr->type == &RNA_Object) { + //Object *ob = (Object *)ptr->data; + + /* Transforms props? */ + if (prop) { + const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop); + + if (strstr(prop_identifier, "location") || + strstr(prop_identifier, "rotation") || + strstr(prop_identifier, "scale")) + { + *type = DEPSNODE_TYPE_TRANSFORM; + return true; + } + } + // ... + } + else if (ptr->type == &RNA_ShapeKey) { + Key *key = (Key *)ptr->id.data; + + /* ShapeKeys are currently handled as geometry on the geometry that owns it */ + *id = key->from; // XXX + *type = DEPSNODE_TYPE_PARAMETERS; + + return true; + } + else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) { + Sequence *seq = (Sequence *)ptr->data; + /* Sequencer strip */ + *type = DEPSNODE_TYPE_SEQUENCER; + *subdata = seq->name; // xxx? + return true; + } + + if (prop) { + /* All unknown data effectively falls under "parameter evaluation" */ + *type = DEPSNODE_TYPE_PARAMETERS; + return true; + } + + return false; +} + +/* Convenience wrapper to find node given just pointer + property. */ +DepsNode *Depsgraph::find_node_from_pointer(const PointerRNA *ptr, + const PropertyRNA *prop) const +{ + ID *id; + eDepsNode_Type type; + string name; + + /* Get querying conditions. */ + if (pointer_to_id_node_criteria(ptr, prop, &id)) { + return find_id_node(id); + } + else if (pointer_to_component_node_criteria(ptr, prop, &id, &type, &name)) { + IDDepsNode *id_node = find_id_node(id); + if (id_node) + return id_node->find_component(type, name); + } + + return NULL; +} + +/* Node Management ---------------------------- */ + +RootDepsNode *Depsgraph::add_root_node() +{ + if (!root_node) { + DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_ROOT); + root_node = (RootDepsNode *)factory->create_node(NULL, "", "Root (Scene)"); + } + return root_node; +} + +TimeSourceDepsNode *Depsgraph::find_time_source(const ID *id) const +{ + /* Search for one attached to a particular ID? */ + if (id) { + /* Check if it was added as a component + * (as may be done for subgraphs needing timeoffset). + */ + IDDepsNode *id_node = find_id_node(id); + if (id_node) { + // XXX: review this +// return id_node->find_component(DEPSNODE_TYPE_TIMESOURCE); + } + BLI_assert(!"Not implemented yet"); + } + else { + /* Use "official" timesource. */ + return root_node->time_source; + } + return NULL; +} + +SubgraphDepsNode *Depsgraph::add_subgraph_node(const ID *id) +{ + DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_SUBGRAPH); + SubgraphDepsNode *subgraph_node = + (SubgraphDepsNode *)factory->create_node(id, "", id->name + 2); + + /* Add to subnodes list. */ + this->subgraphs.insert(subgraph_node); + + /* if there's an ID associated, add to ID-nodes lookup too */ + if (id) { +#if 0 + /* XXX subgraph node is NOT a true IDDepsNode - what is this supposed to do? */ + // TODO: what to do if subgraph's ID has already been added? + BLI_assert(!graph->find_id_node(id)); + graph->id_hash[id] = this; +#endif + } + + return subgraph_node; +} + +void Depsgraph::remove_subgraph_node(SubgraphDepsNode *subgraph_node) +{ + subgraphs.erase(subgraph_node); + OBJECT_GUARDED_DELETE(subgraph_node, SubgraphDepsNode); +} + +void Depsgraph::clear_subgraph_nodes() +{ + for (Subgraphs::iterator it = subgraphs.begin(); + it != subgraphs.end(); + ++it) + { + SubgraphDepsNode *subgraph_node = *it; + OBJECT_GUARDED_DELETE(subgraph_node, SubgraphDepsNode); + } + subgraphs.clear(); +} + +IDDepsNode *Depsgraph::find_id_node(const ID *id) const +{ + IDNodeMap::const_iterator it = this->id_hash.find(id); + return it != this->id_hash.end() ? it->second : NULL; +} + +IDDepsNode *Depsgraph::add_id_node(ID *id, const string &name) +{ + IDDepsNode *id_node = find_id_node(id); + if (!id_node) { + DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_ID_REF); + id_node = (IDDepsNode *)factory->create_node(id, "", name); + id->flag |= LIB_DOIT; + /* register */ + this->id_hash[id] = id_node; + } + return id_node; +} + +void Depsgraph::remove_id_node(const ID *id) +{ + IDDepsNode *id_node = find_id_node(id); + if (id_node) { + /* unregister */ + this->id_hash.erase(id); + OBJECT_GUARDED_DELETE(id_node, IDDepsNode); + } +} + +void Depsgraph::clear_id_nodes() +{ + for (IDNodeMap::const_iterator it = id_hash.begin(); + it != id_hash.end(); + ++it) + { + IDDepsNode *id_node = it->second; + OBJECT_GUARDED_DELETE(id_node, IDDepsNode); + } + id_hash.clear(); +} + +/* Add new relationship between two nodes. */ +DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from, + OperationDepsNode *to, + eDepsRelation_Type type, + const char *description) +{ + /* Create new relation, and add it to the graph. */ + DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, type, description); + return rel; +} + +/* Add new relation between two nodes */ +DepsRelation *Depsgraph::add_new_relation(DepsNode *from, DepsNode *to, + eDepsRelation_Type type, + const char *description) +{ + /* Create new relation, and add it to the graph. */ + DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, type, description); + return rel; +} + +/* ************************ */ +/* Relationships Management */ + +DepsRelation::DepsRelation(DepsNode *from, + DepsNode *to, + eDepsRelation_Type type, + const char *description) + : from(from), + to(to), + name(description), + type(type), + flag(0) +{ +#ifndef NDEBUG +/* + for (OperationDepsNode::Relations::const_iterator it = from->outlinks.begin(); + it != from->outlinks.end(); + ++it) + { + DepsRelation *rel = *it; + if (rel->from == from && + rel->to == to && + rel->type == type && + rel->name == description) + { + BLI_assert(!"Duplicated relation, should not happen!"); + } + } +*/ +#endif + + /* Hook it up to the nodes which use it. */ + from->outlinks.insert(this); + to->inlinks.insert(this); +} + +DepsRelation::~DepsRelation() +{ + /* Sanity check. */ + BLI_assert(this->from && this->to); + /* Remove it from the nodes that use it. */ + this->from->outlinks.erase(this); + this->to->inlinks.erase(this); +} + +/* Low level tagging -------------------------------------- */ + +/* Tag a specific node as needing updates. */ +void Depsgraph::add_entry_tag(OperationDepsNode *node) +{ + /* Sanity check. */ + if (!node) + return; + + /* Add to graph-level set of directly modified nodes to start searching from. + * NOTE: this is necessary since we have several thousand nodes to play with... + */ + this->entry_tags.insert(node); +} + +void Depsgraph::clear_all_nodes() +{ + clear_id_nodes(); + clear_subgraph_nodes(); + id_hash.clear(); + if (this->root_node) { + OBJECT_GUARDED_DELETE(this->root_node, RootDepsNode); + root_node = NULL; + } +} + +/* **************** */ +/* Public Graph API */ + +/* Initialize a new Depsgraph */ +Depsgraph *DEG_graph_new() +{ + return OBJECT_GUARDED_NEW(Depsgraph); +} + +/* Free graph's contents and graph itself */ +void DEG_graph_free(Depsgraph *graph) +{ + OBJECT_GUARDED_DELETE(graph, Depsgraph); +} + +/* Set callbacks which are being called when depsgraph changes. */ +void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func, + DEG_EditorUpdateSceneCb scene_func) +{ + deg_editor_update_id_cb = id_func; + deg_editor_update_scene_cb = scene_func; +} + +void deg_editors_id_update(Main *bmain, ID *id) +{ + if (deg_editor_update_id_cb != NULL) { + deg_editor_update_id_cb(bmain, id); + } +} + +void deg_editors_scene_update(Main *bmain, Scene *scene, bool updated) +{ + if (deg_editor_update_scene_cb != NULL) { + deg_editor_update_scene_cb(bmain, scene, updated); + } +} diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h new file mode 100644 index 00000000000..8ce73626c13 --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -0,0 +1,220 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + * + * Datatypes for internal use in the Depsgraph + * + * All of these datatypes are only really used within the "core" depsgraph. + * In particular, node types declared here form the structure of operations + * in the graph. + */ + +#ifndef __DEPSGRAPH_H__ +#define __DEPSGRAPH_H__ + +#include "BLI_threads.h" /* for SpinLock */ + +#include "depsgraph_types.h" + +#include "depsgraph_util_map.h" +#include "depsgraph_util_set.h" + +struct PointerRNA; +struct PropertyRNA; + +struct DepsNode; +struct RootDepsNode; +struct TimeSourceDepsNode; +struct IDDepsNode; +struct SubgraphDepsNode; +struct ComponentDepsNode; +struct OperationDepsNode; + +/* *************************** */ +/* Relationships Between Nodes */ + +/* Settings/Tags on Relationship */ +typedef enum eDepsRelation_Flag { + /* "touched" tag is used when filtering, to know which to collect */ + DEPSREL_FLAG_TEMP_TAG = (1 << 0), + + /* "cyclic" link - when detecting cycles, this relationship was the one + * which triggers a cyclic relationship to exist in the graph + */ + DEPSREL_FLAG_CYCLIC = (1 << 1), +} eDepsRelation_Flag; + +/* B depends on A (A -> B) */ +struct DepsRelation { + /* the nodes in the relationship (since this is shared between the nodes) */ + DepsNode *from; /* A */ + DepsNode *to; /* B */ + + /* relationship attributes */ + const char* name; /* label for debugging */ + + eDepsRelation_Type type; /* type */ + int flag; /* (eDepsRelation_Flag) */ + + DepsRelation(DepsNode *from, + DepsNode *to, + eDepsRelation_Type type, + const char *description); + + ~DepsRelation(); +}; + +/* ********* */ +/* Depsgraph */ + +/* Dependency Graph object */ +struct Depsgraph { + typedef unordered_map IDNodeMap; + typedef unordered_set Subgraphs; + typedef unordered_set EntryTags; + typedef vector OperationNodes; + + Depsgraph(); + ~Depsgraph(); + + /** + * Find node which matches the specified description. + * + * \param id: ID block that is associated with this + * \param subdata: identifier used for sub-ID data (e.g. bone) + * \param type: type of node we're dealing with + * \param name: custom identifier assigned to node + * + * \return A node matching the required characteristics if it exists + * or NULL if no such node exists in the graph. + */ + DepsNode *find_node(const ID *id, + eDepsNode_Type type, + const string &subdata, + const string &name); + + /** + * Convenience wrapper to find node given just pointer + property. + * + * \param ptr: pointer to the data that node will represent + * \param prop: optional property affected - providing this effectively results in inner nodes being returned + * + * \return A node matching the required characteristics if it exists + * or NULL if no such node exists in the graph + */ + DepsNode *find_node_from_pointer(const PointerRNA *ptr, const PropertyRNA *prop) const; + + RootDepsNode *add_root_node(); + + TimeSourceDepsNode *find_time_source(const ID *id = NULL) const; + + SubgraphDepsNode *add_subgraph_node(const ID *id); + void remove_subgraph_node(SubgraphDepsNode *subgraph_node); + void clear_subgraph_nodes(); + + IDDepsNode *find_id_node(const ID *id) const; + IDDepsNode *add_id_node(ID *id, const string &name = ""); + void remove_id_node(const ID *id); + void clear_id_nodes(); + + /* Add new relationship between two nodes. */ + DepsRelation *add_new_relation(OperationDepsNode *from, + OperationDepsNode *to, + eDepsRelation_Type type, + const char *description); + + DepsRelation *add_new_relation(DepsNode *from, + DepsNode *to, + eDepsRelation_Type type, + const char *description); + + /* Tag a specific node as needing updates. */ + void add_entry_tag(OperationDepsNode *node); + + /* Clear storage used by all nodes. */ + void clear_all_nodes(); + + /* Core Graph Functionality ........... */ + + /* mapping from ID blocks to nodes representing these blocks + * (for quick lookups). */ + IDNodeMap id_hash; + + /* "root" node - the one where all evaluation enters from. */ + RootDepsNode *root_node; + + /* Subgraphs referenced in tree. */ + Subgraphs subgraphs; + + /* Indicates whether relations needs to be updated. */ + bool need_update; + + /* Quick-Access Temp Data ............. */ + + /* Nodes which have been tagged as "directly modified". */ + EntryTags entry_tags; + + /* Convenience Data ................... */ + + /* XXX: should be collected after building (if actually needed?) */ + /* All operation nodes, sorted in order of single-thread traversal order. */ + OperationNodes operations; + + /* Spin lock for threading-critical operations. + * Mainly used by graph evaluation. + */ + SpinLock lock; + + /* Layers Visibility .................. */ + + /* Visible layers bitfield, used for skipping invisible objects updates. */ + int layers; + + // XXX: additional stuff like eval contexts, mempools for allocating nodes from, etc. +}; + +/** + * Helper macros for interating over set of relationship links + * incident on each node. + * + * \note it is safe to perform removal operations here... + * + * relations_set[in]: (DepsNode::Relations) set of relationships (in/out links) + * relation[out]: (DepsRelation *) identifier where DepsRelation that we're + * currently accessing comes up + */ +#define DEPSNODE_RELATIONS_ITER_BEGIN(relations_set_, relation_) \ + { \ + OperationDepsNode::Relations::const_iterator __rel_iter = relations_set_.begin(); \ + while (__rel_iter != relations_set_.end()) { \ + DepsRelation *relation_ = *__rel_iter; \ + ++__rel_iter; \ + + /* ... code for iterator body can be written here ... */ + +#define DEPSNODE_RELATIONS_ITER_END \ + } \ + } ((void)0) + +#endif /* __DEPSGRAPH_H__ */ diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc new file mode 100644 index 00000000000..b5e09db6507 --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -0,0 +1,365 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013) + * + * ***** END GPL LICENSE BLOCK ***** + * + * Methods for constructing depsgraph + */ + +#include + +#include "MEM_guardedalloc.h" + +extern "C" { +#include "BLI_blenlib.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "DNA_action_types.h" +#include "DNA_anim_types.h" +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_constraint_types.h" +#include "DNA_curve_types.h" +#include "DNA_effect_types.h" +#include "DNA_group_types.h" +#include "DNA_key_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meta_types.h" +#include "DNA_node_types.h" +#include "DNA_particle_types.h" +#include "DNA_object_types.h" +#include "DNA_rigidbody_types.h" +#include "DNA_scene_types.h" +#include "DNA_texture_types.h" +#include "DNA_world_types.h" + +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_animsys.h" +#include "BKE_constraint.h" +#include "BKE_curve.h" +#include "BKE_effect.h" +#include "BKE_fcurve.h" +#include "BKE_group.h" +#include "BKE_key.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_mball.h" +#include "BKE_modifier.h" +#include "BKE_node.h" +#include "BKE_object.h" +#include "BKE_particle.h" +#include "BKE_rigidbody.h" +#include "BKE_sound.h" +#include "BKE_texture.h" +#include "BKE_tracking.h" +#include "BKE_world.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_debug.h" +#include "DEG_depsgraph_build.h" + +#include "RNA_access.h" +#include "RNA_types.h" +} /* extern "C" */ + +#include "depsnode.h" +#include "depsnode_component.h" +#include "depsgraph_debug.h" +#include "depsnode_operation.h" +#include "depsgraph_types.h" +#include "depsgraph_build.h" +#include "depsgraph_intern.h" + +#include "depsgraph_util_cycle.h" +#include "depsgraph_util_transitive.h" + +/* ****************** */ +/* External Build API */ + +static eDepsNode_Type deg_build_scene_component_type(eDepsSceneComponentType component) +{ + switch (component) { + case DEG_SCENE_COMP_PARAMETERS: return DEPSNODE_TYPE_PARAMETERS; + case DEG_SCENE_COMP_ANIMATION: return DEPSNODE_TYPE_ANIMATION; + case DEG_SCENE_COMP_SEQUENCER: return DEPSNODE_TYPE_SEQUENCER; + } + return DEPSNODE_TYPE_UNDEFINED; +} + +static eDepsNode_Type deg_build_object_component_type(eDepsObjectComponentType component) +{ + switch (component) { + case DEG_OB_COMP_PARAMETERS: return DEPSNODE_TYPE_PARAMETERS; + case DEG_OB_COMP_PROXY: return DEPSNODE_TYPE_PROXY; + case DEG_OB_COMP_ANIMATION: return DEPSNODE_TYPE_ANIMATION; + case DEG_OB_COMP_TRANSFORM: return DEPSNODE_TYPE_TRANSFORM; + case DEG_OB_COMP_GEOMETRY: return DEPSNODE_TYPE_GEOMETRY; + case DEG_OB_COMP_EVAL_POSE: return DEPSNODE_TYPE_EVAL_POSE; + case DEG_OB_COMP_BONE: return DEPSNODE_TYPE_BONE; + case DEG_OB_COMP_EVAL_PARTICLES: return DEPSNODE_TYPE_EVAL_PARTICLES; + case DEG_OB_COMP_SHADING: return DEPSNODE_TYPE_SHADING; + } + return DEPSNODE_TYPE_UNDEFINED; +} + +void DEG_add_scene_relation(DepsNodeHandle *handle, struct Scene *scene, eDepsSceneComponentType component, const char *description) +{ + eDepsNode_Type type = deg_build_scene_component_type(component); + ComponentKey comp_key(&scene->id, type); + handle->builder->add_node_handle_relation(comp_key, handle, DEPSREL_TYPE_GEOMETRY_EVAL, description); +} + +void DEG_add_object_relation(DepsNodeHandle *handle, struct Object *ob, eDepsObjectComponentType component, const char *description) +{ + eDepsNode_Type type = deg_build_object_component_type(component); + ComponentKey comp_key(&ob->id, type); + handle->builder->add_node_handle_relation(comp_key, handle, DEPSREL_TYPE_GEOMETRY_EVAL, description); +} + +void DEG_add_bone_relation(DepsNodeHandle *handle, struct Object *ob, const char *bone_name, eDepsObjectComponentType component, const char *description) +{ + eDepsNode_Type type = deg_build_object_component_type(component); + ComponentKey comp_key(&ob->id, type, bone_name); + + // XXX: "Geometry Eval" might not always be true, but this only gets called from modifier building now + handle->builder->add_node_handle_relation(comp_key, handle, DEPSREL_TYPE_GEOMETRY_EVAL, description); +} + +void DEG_add_special_eval_flag(Depsgraph *graph, ID *id, short flag) +{ + if (graph == NULL) { + BLI_assert(!"Graph should always be valid"); + return; + } + IDDepsNode *id_node = graph->find_id_node(id); + if (id_node == NULL) { + BLI_assert(!"ID should always be valid"); + return; + } + id_node->eval_flags |= flag; +} + +/* ********************** */ +/* Utilities for Builders */ + +/* Get unique identifier for FCurves and Drivers */ +string deg_fcurve_id_name(const FCurve *fcu) +{ + char index_buf[32]; + sprintf(index_buf, "[%d]", fcu->array_index); + + return string(fcu->rna_path) + index_buf; +} + +static void deg_graph_build_finalize(Depsgraph *graph) +{ + std::stack stack; + + for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin(); + it_op != graph->operations.end(); + ++it_op) + { + OperationDepsNode *node = *it_op; + node->done = 0; + node->num_links_pending = 0; + for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin(); + it_rel != node->inlinks.end(); + ++it_rel) + { + DepsRelation *rel = *it_rel; + if (rel->from->type == DEPSNODE_TYPE_OPERATION && + (rel->flag & DEPSREL_FLAG_CYCLIC) == 0) { + ++node->num_links_pending; + } + } + if (node->num_links_pending == 0) { + stack.push(node); + } + IDDepsNode *id_node = node->owner->owner; + id_node->id->flag |= LIB_DOIT; + } + + while (!stack.empty()) { + OperationDepsNode *node = stack.top(); + if (node->done == 0 && node->outlinks.size() != 0) { + for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin(); + it_rel != node->outlinks.end(); + ++it_rel) + { + DepsRelation *rel = *it_rel; + if (rel->to->type == DEPSNODE_TYPE_OPERATION) { + OperationDepsNode *to = (OperationDepsNode *)rel->to; + if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) { + BLI_assert(to->num_links_pending > 0); + --to->num_links_pending; + } + if (to->num_links_pending == 0) { + stack.push(to); + } + } + } + node->done = 1; + } + else { + stack.pop(); + IDDepsNode *id_node = node->owner->owner; + for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin(); + it_rel != node->outlinks.end(); + ++it_rel) + { + DepsRelation *rel = *it_rel; + if (rel->to->type == DEPSNODE_TYPE_OPERATION) { + OperationDepsNode *to = (OperationDepsNode *)rel->to; + IDDepsNode *id_to = to->owner->owner; + id_node->layers |= id_to->layers; + } + } + + /* Re-tag ID for update if it was tagged before the relations + * update tag. + */ + ID *id = id_node->id; + if (id->flag & LIB_ID_RECALC_ALL && + id->flag & LIB_DOIT) + { + id_node->tag_update(graph); + id->flag &= ~LIB_DOIT; + } + } + } +} + +/* ******************** */ +/* Graph Building API's */ + +/* Build depsgraph for the given scene, and dump results in given graph container */ +// XXX: assume that this is called from outside, given the current scene as the "main" scene +void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene) +{ + /* 1) Generate all the nodes in the graph first */ + DepsgraphNodeBuilder node_builder(bmain, graph); + /* create root node for scene first + * - this way it should be the first in the graph, + * reflecting its role as the entrypoint + */ + node_builder.add_root_node(); + node_builder.build_scene(bmain, scene); + + /* 2) Hook up relationships between operations - to determine evaluation order */ + DepsgraphRelationBuilder relation_builder(graph); + /* hook scene up to the root node as entrypoint to graph */ + /* XXX what does this relation actually mean? + * it doesnt add any operations anyway and is not clear what part of the scene is to be connected. + */ + //relation_builder.add_relation(RootKey(), IDKey(scene), DEPSREL_TYPE_ROOT_TO_ACTIVE, "Root to Active Scene"); + relation_builder.build_scene(bmain, scene); + + /* Detect and solve cycles. */ + deg_graph_detect_cycles(graph); + + /* 3) Simplify the graph by removing redundant relations (to optimise traversal later) */ + // TODO: it would be useful to have an option to disable this in cases where it is causing trouble + if (G.debug_value == 799) { + deg_graph_transitive_reduction(graph); + } + + /* 4) Flush visibility layer and re-schedule nodes for update. */ + deg_graph_build_finalize(graph); + +#if 0 + if (!DEG_debug_consistency_check(graph)) { + printf("Consistency validation failed, ABORTING!\n"); + abort(); + } +#endif +} + +/* Tag graph relations for update. */ +void DEG_graph_tag_relations_update(Depsgraph *graph) +{ + graph->need_update = true; +} + +/* Tag all relations for update. */ +void DEG_relations_tag_update(Main *bmain) +{ + for (Scene *scene = (Scene *)bmain->scene.first; + scene != NULL; + scene = (Scene *)scene->id.next) + { + if (scene->depsgraph != NULL) { + DEG_graph_tag_relations_update(scene->depsgraph); + } + } +} + +/* Create new graph if didn't exist yet, + * or update relations if graph was tagged for update. + */ +void DEG_scene_relations_update(Main *bmain, Scene *scene) +{ + if (scene->depsgraph == NULL) { + /* Rebuild graph from scratch and exit. */ + scene->depsgraph = DEG_graph_new(); + DEG_graph_build_from_scene(scene->depsgraph, bmain, scene); + return; + } + + Depsgraph *graph = scene->depsgraph; + if (!graph->need_update) { + /* Graph is up to date, nothing to do. */ + return; + } + + /* Clear all previous nodes and operations. */ + graph->clear_all_nodes(); + graph->operations.clear(); + graph->entry_tags.clear(); + + /* Build new nodes and relations. */ + DEG_graph_build_from_scene(graph, bmain, scene); + + graph->need_update = false; +} + +/* Rebuild dependency graph only for a given scene. */ +void DEG_scene_relations_rebuild(Main *bmain, Scene *scene) +{ + if (scene->depsgraph != NULL) { + DEG_graph_tag_relations_update(scene->depsgraph); + } + DEG_scene_relations_update(bmain, scene); +} + +void DEG_scene_graph_free(Scene *scene) +{ + if (scene->depsgraph) { + DEG_graph_free(scene->depsgraph); + scene->depsgraph = NULL; + } +} diff --git a/source/blender/depsgraph/intern/depsgraph_build.h b/source/blender/depsgraph/intern/depsgraph_build.h new file mode 100644 index 00000000000..84c09b81508 --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph_build.h @@ -0,0 +1,404 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Lukas Toenne + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __DEPSGRAPH_BUILD_H__ +#define __DEPSGRAPH_BUILD_H__ + +struct Base; +struct bGPdata; +struct ListBase; +struct GHash; +struct ID; +struct FCurve; +struct Group; +struct Key; +struct Main; +struct Material; +struct MTex; +struct bNodeTree; +struct Object; +struct bPoseChannel; +struct bConstraint; +struct Scene; +struct Tex; +struct World; + +struct PropertyRNA; + +struct Depsgraph; +struct DepsNode; +struct DepsNodeHandle; +struct RootDepsNode; +struct SubgraphDepsNode; +struct IDDepsNode; +struct TimeSourceDepsNode; +struct ComponentDepsNode; +struct OperationDepsNode; +struct RootPChanMap; + +struct DepsgraphNodeBuilder { + DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph); + ~DepsgraphNodeBuilder(); + + RootDepsNode *add_root_node(); + IDDepsNode *add_id_node(ID *id); + TimeSourceDepsNode *add_time_source(ID *id); + + ComponentDepsNode *add_component_node(ID *id, eDepsNode_Type comp_type, const string &comp_name = ""); + + OperationDepsNode *add_operation_node(ComponentDepsNode *comp_node, eDepsOperation_Type optype, + DepsEvalOperationCb op, eDepsOperation_Code opcode, const string &description = ""); + OperationDepsNode *add_operation_node(ID *id, eDepsNode_Type comp_type, const string &comp_name, eDepsOperation_Type optype, + DepsEvalOperationCb op, eDepsOperation_Code opcode, const string &description = ""); + OperationDepsNode *add_operation_node(ID *id, eDepsNode_Type comp_type, eDepsOperation_Type optype, + DepsEvalOperationCb op, eDepsOperation_Code opcode, const string &description = "") + { + return add_operation_node(id, comp_type, "", optype, op, opcode, description); + } + + bool has_operation_node(ID *id, eDepsNode_Type comp_type, const string &comp_name, + eDepsOperation_Code opcode, const string &description = ""); + + OperationDepsNode *find_operation_node(ID *id, + eDepsNode_Type comp_type, + const string &comp_name, + eDepsOperation_Code opcode, + const string &description = ""); + + OperationDepsNode *find_operation_node(ID *id, + eDepsNode_Type comp_type, + eDepsOperation_Code opcode, + const string &description = "") + { + return find_operation_node(id, comp_type, "", opcode, description); + } + + void build_scene(Main *bmain, Scene *scene); + SubgraphDepsNode *build_subgraph(Group *group); + void build_group(Scene *scene, Base *base, Group *group); + void build_object(Scene *scene, Base *base, Object *ob); + void build_object_transform(Scene *scene, Object *ob); + void build_object_constraints(Scene *scene, Object *ob); + void build_pose_constraints(Object *ob, bPoseChannel *pchan); + void build_rigidbody(Scene *scene); + void build_particles(Object *ob); + void build_animdata(ID *id); + OperationDepsNode *build_driver(ID *id, FCurve *fcurve); + void build_ik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con); + void build_splineik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con); + void build_rig(Scene *scene, Object *ob); + void build_proxy_rig(Object *ob); + void build_shapekeys(Key *key); + void build_obdata_geom(Scene *scene, Object *ob); + void build_camera(Object *ob); + void build_lamp(Object *ob); + void build_nodetree(DepsNode *owner_node, bNodeTree *ntree); + void build_material(DepsNode *owner_node, Material *ma); + void build_texture(DepsNode *owner_node, Tex *tex); + void build_texture_stack(DepsNode *owner_node, MTex **texture_stack); + void build_world(World *world); + void build_compositor(Scene *scene); + void build_gpencil(bGPdata *gpd); + +private: + Main *m_bmain; + Depsgraph *m_graph; +}; + +struct RootKey +{ + RootKey() {} +}; + +struct TimeSourceKey +{ + TimeSourceKey() : id(NULL) {} + TimeSourceKey(ID *id) : id(id) {} + + string identifier() const + { + return string("TimeSourceKey"); + } + + ID *id; +}; + +struct ComponentKey +{ + ComponentKey() : + id(NULL), type(DEPSNODE_TYPE_UNDEFINED), name("") + {} + ComponentKey(ID *id, eDepsNode_Type type, const string &name = "") : + id(id), type(type), name(name) + {} + + string identifier() const + { + const char *idname = (id) ? id->name : ""; + + char typebuf[5]; + sprintf(typebuf, "%d", type); + + return string("ComponentKey(") + idname + ", " + typebuf + ", '" + name + "')"; + } + + ID *id; + eDepsNode_Type type; + string name; +}; + +struct OperationKey +{ + OperationKey() : + id(NULL), component_type(DEPSNODE_TYPE_UNDEFINED), component_name(""), opcode(DEG_OPCODE_OPERATION), name("") + {} + + OperationKey(ID *id, eDepsNode_Type component_type, const string &name) : + id(id), component_type(component_type), component_name(""), opcode(DEG_OPCODE_OPERATION), name(name) + {} + OperationKey(ID *id, eDepsNode_Type component_type, const string &component_name, const string &name) : + id(id), component_type(component_type), component_name(component_name), opcode(DEG_OPCODE_OPERATION), name(name) + {} + + OperationKey(ID *id, eDepsNode_Type component_type, eDepsOperation_Code opcode) : + id(id), component_type(component_type), component_name(""), opcode(opcode), name("") + {} + OperationKey(ID *id, eDepsNode_Type component_type, const string &component_name, eDepsOperation_Code opcode) : + id(id), component_type(component_type), component_name(component_name), opcode(opcode), name("") + {} + + OperationKey(ID *id, eDepsNode_Type component_type, eDepsOperation_Code opcode, const string &name) : + id(id), component_type(component_type), component_name(""), opcode(opcode), name(name) + {} + OperationKey(ID *id, eDepsNode_Type component_type, const string &component_name, eDepsOperation_Code opcode, const string &name) : + id(id), component_type(component_type), component_name(component_name), opcode(opcode), name(name) + {} + + string identifier() const + { + char typebuf[5]; + sprintf(typebuf, "%d", component_type); + + return string("OperationKey(") + "t: " + typebuf + ", cn: '" + component_name + "', c: " + DEG_OPNAMES[opcode] + ", n: '" + name + "')"; + } + + + ID *id; + eDepsNode_Type component_type; + string component_name; + eDepsOperation_Code opcode; + string name; +}; + +struct RNAPathKey +{ + // Note: see depsgraph_build.cpp for implementation + RNAPathKey(ID *id, const string &path); + + RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop) : + id(id), ptr(ptr), prop(prop) + {} + + string identifier() const + { + const char *id_name = (id) ? id->name : ""; + const char *prop_name = (prop) ? RNA_property_identifier(prop) : ""; + + return string("RnaPathKey(") + "id: " + id_name + ", prop: " + prop_name + "')"; + } + + + ID *id; + PointerRNA ptr; + PropertyRNA *prop; +}; + +struct DepsgraphRelationBuilder +{ + DepsgraphRelationBuilder(Depsgraph *graph); + + template + void add_relation(const KeyFrom &key_from, const KeyTo &key_to, + eDepsRelation_Type type, const char *description); + + template + void add_relation(const TimeSourceKey &key_from, const KeyTo &key_to, + eDepsRelation_Type type, const char *description); + + template + void add_node_handle_relation(const KeyType &key_from, const DepsNodeHandle *handle, + eDepsRelation_Type type, const char *description); + + void build_scene(Main *bmain, Scene *scene); + void build_group(Main *bmain, Scene *scene, Object *object, Group *group); + void build_object(Main *bmain, Scene *scene, Object *ob); + void build_object_parent(Object *ob); + void build_constraints(Scene *scene, ID *id, eDepsNode_Type component_type, const char *component_subdata, + ListBase *constraints, RootPChanMap *root_map); + void build_animdata(ID *id); + void build_driver(ID *id, FCurve *fcurve); + void build_world(World *world); + void build_rigidbody(Scene *scene); + void build_particles(Scene *scene, Object *ob); + void build_ik_pose(Object *ob, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map); + void build_splineik_pose(Object *ob, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map); + void build_rig(Scene *scene, Object *ob); + void build_proxy_rig(Object *ob); + void build_shapekeys(ID *obdata, Key *key); + void build_obdata_geom(Main *bmain, Scene *scene, Object *ob); + void build_camera(Object *ob); + void build_lamp(Object *ob); + void build_nodetree(ID *owner, bNodeTree *ntree); + void build_material(ID *owner, Material *ma); + void build_texture(ID *owner, Tex *tex); + void build_texture_stack(ID *owner, MTex **texture_stack); + void build_compositor(Scene *scene); + void build_gpencil(ID *owner, bGPdata *gpd); + +protected: + RootDepsNode *find_node(const RootKey &key) const; + TimeSourceDepsNode *find_node(const TimeSourceKey &key) const; + ComponentDepsNode *find_node(const ComponentKey &key) const; + OperationDepsNode *find_node(const OperationKey &key) const; + DepsNode *find_node(const RNAPathKey &key) const; + OperationDepsNode *has_node(const OperationKey &key) const; + + void add_time_relation(TimeSourceDepsNode *timesrc, DepsNode *node_to, const char *description); + void add_operation_relation(OperationDepsNode *node_from, OperationDepsNode *node_to, + eDepsRelation_Type type, const char *description); + + template + DepsNodeHandle create_node_handle(const KeyType &key, const string &default_name = ""); + + bool needs_animdata_node(ID *id); + +private: + Depsgraph *m_graph; +}; + +struct DepsNodeHandle +{ + DepsNodeHandle(DepsgraphRelationBuilder *builder, OperationDepsNode *node, const string &default_name = "") : + builder(builder), + node(node), + default_name(default_name) + { + BLI_assert(node != NULL); + } + + DepsgraphRelationBuilder *builder; + OperationDepsNode *node; + const string &default_name; +}; + +/* Utilities for Builders ----------------------------------------------------- */ + +/* Get unique identifier for FCurves and Drivers */ +string deg_fcurve_id_name(const FCurve *fcu); + +template +void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from, + const KeyTo &key_to, + eDepsRelation_Type type, + const char *description) +{ + DepsNode *node_from = find_node(key_from); + DepsNode *node_to = find_node(key_to); + OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL; + OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL; + if (op_from && op_to) { + add_operation_relation(op_from, op_to, type, description); + } + else { + if (!op_from) { + /* XXX TODO handle as error or report if needed */ + fprintf(stderr, "add_relation(%d, %s) - Could not find op_from (%s)\n", + type, description, key_from.identifier().c_str()); + } + else { + fprintf(stderr, "add_relation(%d, %s) - Failed, but op_from (%s) was ok\n", + type, description, key_from.identifier().c_str()); + } + if (!op_to) { + /* XXX TODO handle as error or report if needed */ + fprintf(stderr, "add_relation(%d, %s) - Could not find op_to (%s)\n", + type, description, key_to.identifier().c_str()); + } + else { + fprintf(stderr, "add_relation(%d, %s) - Failed, but op_to (%s) was ok\n", + type, description, key_to.identifier().c_str()); + } + } +} + +template +void DepsgraphRelationBuilder::add_relation(const TimeSourceKey &key_from, + const KeyTo &key_to, + eDepsRelation_Type type, + const char *description) +{ + (void)type; /* Ignored in release builds. */ + BLI_assert(type == DEPSREL_TYPE_TIME); + TimeSourceDepsNode *time_from = find_node(key_from); + DepsNode *node_to = find_node(key_to); + OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL; + if (time_from && op_to) { + add_time_relation(time_from, op_to, description); + } + else { + } +} + +template +void DepsgraphRelationBuilder::add_node_handle_relation(const KeyType &key_from, + const DepsNodeHandle *handle, + eDepsRelation_Type type, + const char *description) +{ + DepsNode *node_from = find_node(key_from); + OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL; + OperationDepsNode *op_to = handle->node->get_entry_operation(); + if (op_from && op_to) { + add_operation_relation(op_from, op_to, type, description); + } + else { + if (!op_from) { + /* XXX TODO handle as error or report if needed */ + } + if (!op_to) { + /* XXX TODO handle as error or report if needed */ + } + } +} + +template +DepsNodeHandle DepsgraphRelationBuilder::create_node_handle(const KeyType &key, + const string &default_name) +{ + return DepsNodeHandle(this, find_node(key), default_name); +} + +#endif /* __DEPSGRAPH_BUILD_H__ */ diff --git a/source/blender/depsgraph/intern/depsgraph_build_nodes.cc b/source/blender/depsgraph/intern/depsgraph_build_nodes.cc new file mode 100644 index 00000000000..a55fb900551 --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph_build_nodes.cc @@ -0,0 +1,1199 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013) + * + * ***** END GPL LICENSE BLOCK ***** + * + * Methods for constructing depsgraph's nodes + */ + + +#include +#include +#include + +#include "MEM_guardedalloc.h" + +extern "C" { +#include "BLI_blenlib.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "DNA_action_types.h" +#include "DNA_anim_types.h" +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_constraint_types.h" +#include "DNA_curve_types.h" +#include "DNA_effect_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_group_types.h" +#include "DNA_key_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meta_types.h" +#include "DNA_node_types.h" +#include "DNA_particle_types.h" +#include "DNA_object_types.h" +#include "DNA_rigidbody_types.h" +#include "DNA_scene_types.h" +#include "DNA_texture_types.h" +#include "DNA_world_types.h" + +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_animsys.h" +#include "BKE_constraint.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_effect.h" +#include "BKE_fcurve.h" +#include "BKE_idcode.h" +#include "BKE_group.h" +#include "BKE_key.h" +#include "BKE_lattice.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_mesh.h" +#include "BKE_mball.h" +#include "BKE_modifier.h" +#include "BKE_node.h" +#include "BKE_object.h" +#include "BKE_particle.h" +#include "BKE_rigidbody.h" +#include "BKE_sound.h" +#include "BKE_texture.h" +#include "BKE_tracking.h" +#include "BKE_world.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + +#include "RNA_access.h" +#include "RNA_types.h" +} /* extern "C" */ + +#include "depsnode.h" +#include "depsnode_component.h" +#include "depsnode_operation.h" +#include "depsgraph_types.h" +#include "depsgraph_build.h" +#include "depsgraph_intern.h" + +/* ************ */ +/* Node Builder */ + +/* **** General purpose functions **** */ + +DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph) : + m_bmain(bmain), + m_graph(graph) +{ +} + +DepsgraphNodeBuilder::~DepsgraphNodeBuilder() +{ +} + +RootDepsNode *DepsgraphNodeBuilder::add_root_node() +{ + return m_graph->add_root_node(); +} + +IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id) +{ + const char *idtype_name = BKE_idcode_to_name(GS(id->name)); + return m_graph->add_id_node(id, string(id->name+2) + "[" + idtype_name + "]"); +} + +TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source(ID *id) +{ + /* determine which node to attach timesource to */ + if (id) { +#if 0 /* XXX TODO */ + /* get ID node */ + IDDepsNode id_node = m_graph->find_id_node(id); + + /* depends on what this is... */ + switch (GS(id->name)) { + case ID_SCE: /* Scene - Usually sequencer strip causing time remapping... */ + { + // TODO... + } + break; + + case ID_GR: /* Group */ + { + // TODO... + } + break; + + // XXX: time source... + + default: /* Unhandled */ + printf("%s(): Unhandled ID - %s \n", __func__, id->name); + break; + } +#endif + } + else { + /* root-node */ + RootDepsNode *root_node = m_graph->root_node; + if (root_node) { + return root_node->add_time_source("Time Source"); + } + } + + return NULL; +} + +ComponentDepsNode *DepsgraphNodeBuilder::add_component_node( + ID *id, + eDepsNode_Type comp_type, + const string &comp_name) +{ + IDDepsNode *id_node = add_id_node(id); + ComponentDepsNode *comp_node = id_node->add_component(comp_type, comp_name); + comp_node->owner = id_node; + return comp_node; +} + +OperationDepsNode *DepsgraphNodeBuilder::add_operation_node( + ComponentDepsNode *comp_node, + eDepsOperation_Type optype, + DepsEvalOperationCb op, + eDepsOperation_Code opcode, + const string &description) +{ + OperationDepsNode *op_node = comp_node->has_operation(opcode, description); + if (op_node == NULL) { + op_node = comp_node->add_operation(optype, op, opcode, description); + m_graph->operations.push_back(op_node); + } + else { + fprintf(stderr, "add_operation: Operation already exists - %s has %s at %p\n", + comp_node->identifier().c_str(), + op_node->identifier().c_str(), + op_node); + BLI_assert(!"Should not happen!"); + } + return op_node; +} + +OperationDepsNode *DepsgraphNodeBuilder::add_operation_node( + ID *id, + eDepsNode_Type comp_type, + const string &comp_name, + eDepsOperation_Type optype, + DepsEvalOperationCb op, + eDepsOperation_Code opcode, + const string &description) +{ + ComponentDepsNode *comp_node = add_component_node(id, comp_type, comp_name); + return add_operation_node(comp_node, optype, op, opcode, description); +} + +bool DepsgraphNodeBuilder::has_operation_node(ID *id, + eDepsNode_Type comp_type, + const string &comp_name, + eDepsOperation_Code opcode, + const string &description) +{ + return find_operation_node(id, comp_type, comp_name, opcode, description) != NULL; +} + +OperationDepsNode *DepsgraphNodeBuilder::find_operation_node( + ID *id, + eDepsNode_Type comp_type, + const string &comp_name, + eDepsOperation_Code opcode, + const string &description) +{ + ComponentDepsNode *comp_node = add_component_node(id, comp_type, comp_name); + return comp_node->has_operation(opcode, description); +} + + +/* **** Build functions for entity nodes **** */ + +void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene) +{ + /* LIB_DOIT is used to indicate whether node for given ID was already + * created or not. This flag is being set in add_id_node(), so functions + * shouldn't bother with setting it, they only might query this flag when + * needed. + */ + BKE_main_id_tag_all(bmain, false); + + /* scene ID block */ + add_id_node(&scene->id); + + /* timesource */ + add_time_source(NULL); + + /* build subgraph for set, and link this in... */ + // XXX: depending on how this goes, that scene itself could probably store its + // own little partial depsgraph? + if (scene->set) { + build_scene(bmain, scene->set); + } + + /* scene objects */ + for (Base *base = (Base *)scene->base.first; base; base = base->next) { + Object *ob = base->object; + + /* object itself */ + build_object(scene, base, ob); + + /* object that this is a proxy for */ + // XXX: the way that proxies work needs to be completely reviewed! + if (ob->proxy) { + build_object(scene, base, ob->proxy); + } + + /* Object dupligroup. */ + if (ob->dup_group) { + build_group(scene, base, ob->dup_group); + } + } + + /* rigidbody */ + if (scene->rigidbody_world) { + build_rigidbody(scene); + } + + /* scene's animation and drivers */ + if (scene->adt) { + build_animdata(&scene->id); + } + + /* world */ + if (scene->world) { + build_world(scene->world); + } + + /* compo nodes */ + if (scene->nodetree) { + build_compositor(scene); + } + + /* sequencer */ + // XXX... + + /* grease pencil */ + if (scene->gpd) { + build_gpencil(scene->gpd); + } +} + +void DepsgraphNodeBuilder::build_group(Scene *scene, + Base *base, + Group *group) +{ + ID *group_id = &group->id; + if (group_id->flag & LIB_DOIT) { + return; + } + group_id->flag |= LIB_DOIT; + + for (GroupObject *go = (GroupObject *)group->gobject.first; + go != NULL; + go = go->next) + { + build_object(scene, base, go->ob); + } +} + +SubgraphDepsNode *DepsgraphNodeBuilder::build_subgraph(Group *group) +{ + /* sanity checks */ + if (!group) + return NULL; + + /* create new subgraph's data */ + Depsgraph *subgraph = DEG_graph_new(); + + DepsgraphNodeBuilder subgraph_builder(m_bmain, subgraph); + + /* add group objects */ + for (GroupObject *go = (GroupObject *)group->gobject.first; + go != NULL; + go = go->next) + { + /*Object *ob = go->ob;*/ + + /* Each "group object" is effectively a separate instance of the underlying + * object data. When the group is evaluated, the transform results and/or + * some other attributes end up getting overridden by the group + */ + } + + /* create a node for representing subgraph */ + SubgraphDepsNode *subgraph_node = m_graph->add_subgraph_node(&group->id); + subgraph_node->graph = subgraph; + + /* make a copy of the data this node will need? */ + // XXX: do we do this now, or later? + // TODO: need API function which queries graph's ID's hash, and duplicates those blocks thoroughly with all outside links removed... + + return subgraph_node; +} + +void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) +{ + if (ob->id.flag & LIB_DOIT) { + IDDepsNode *id_node = m_graph->find_id_node(&ob->id); + id_node->layers = base->lay; + return; + } + + IDDepsNode *id_node = add_id_node(&ob->id); + id_node->layers = base->lay; + + /* standard components */ + build_object_transform(scene, ob); + + + /* object data */ + if (ob->data) { + /* type-specific data... */ + switch (ob->type) { + case OB_MESH: /* Geometry */ + case OB_CURVE: + case OB_FONT: + case OB_SURF: + case OB_MBALL: + case OB_LATTICE: + { + /* TODO(sergey): This way using this object's + * properties as driver target works fine. + * + * Does this depend on other nodes? + */ + add_operation_node(&ob->id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_POST, NULL, + DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); + + build_obdata_geom(scene, ob); + /* TODO(sergey): Only for until we support granular + * update of curves. + */ + if (ob->type == OB_FONT) { + Curve *curve = (Curve *)ob->data; + if (curve->textoncurve) { + id_node->eval_flags |= DAG_EVAL_NEED_CURVE_PATH; + } + } + } + break; + + case OB_ARMATURE: /* Pose */ + if (ob->id.lib != NULL && ob->proxy_from != NULL) { + build_proxy_rig(ob); + } + else { + build_rig(scene, ob); + } + break; + + case OB_LAMP: /* Lamp */ + build_lamp(ob); + break; + + case OB_CAMERA: /* Camera */ + build_camera(ob); + break; + + default: + { + ID *obdata = (ID *)ob->data; + if ((obdata->flag & LIB_DOIT) == 0) { + build_animdata(obdata); + } + break; + } + } + } + + /* Build animation data, + * + * Do it now because it's possible object data will affect + * on object's level animation, for example in case of rebuilding + * pose for proxy. + */ + build_animdata(&ob->id); + + /* particle systems */ + if (ob->particlesystem.first) { + build_particles(ob); + } + + /* grease pencil */ + if (ob->gpd) { + build_gpencil(ob->gpd); + } +} + +void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob) +{ + /* local transforms (from transform channels - loc/rot/scale + deltas) */ + add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM, + DEPSOP_TYPE_INIT, function_bind(BKE_object_eval_local_transform, _1, scene, ob), + DEG_OPCODE_TRANSFORM_LOCAL); + + /* object parent */ + if (ob->parent) { + add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM, + DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_parent, _1, scene, ob), + DEG_OPCODE_TRANSFORM_PARENT); + } + + /* object constraints */ + if (ob->constraints.first) { + build_object_constraints(scene, ob); + } + + /* Temporary uber-update node, which does everything. + * It is for the being we're porting old dependencies into the new system. + * We'll get rid of this node as soon as all the granular update functions + * are filled in. + * + * TODO(sergey): Get rid of this node. + */ + add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM, + DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_uber_transform, _1, scene, ob), + DEG_OPCODE_OBJECT_UBEREVAL); + + /* object transform is done */ + add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM, + DEPSOP_TYPE_POST, function_bind(BKE_object_eval_done, _1, ob), + DEG_OPCODE_TRANSFORM_FINAL); +} + +/** + * Constraints Graph Notes + * + * For constraints, we currently only add a operation node to the Transform + * or Bone components (depending on whichever type of owner we have). + * This represents the entire constraints stack, which is for now just + * executed as a single monolithic block. At least initially, this should + * be sufficient for ensuring that the porting/refactoring process remains + * manageable. + * + * However, when the time comes for developing "node-based" constraints, + * we'll need to split this up into pre/post nodes for "constraint stack + * evaluation" + operation nodes for each constraint (i.e. the contents + * of the loop body used in the current "solve_constraints()" operation). + * + * -- Aligorith, August 2013 + */ +void DepsgraphNodeBuilder::build_object_constraints(Scene *scene, Object *ob) +{ + /* create node for constraint stack */ + add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM, + DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_constraints, _1, scene, ob), + DEG_OPCODE_TRANSFORM_CONSTRAINTS); +} + +void DepsgraphNodeBuilder::build_pose_constraints(Object *ob, bPoseChannel *pchan) +{ + /* create node for constraint stack */ + add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, + DEPSOP_TYPE_EXEC, function_bind(BKE_pose_constraints_evaluate, _1, ob, pchan), + DEG_OPCODE_BONE_CONSTRAINTS); +} + +/** + * Build graph nodes for AnimData block + * \param scene_node: Scene that ID-block this lives on belongs to + * \param id: ID-Block which hosts the AnimData + */ +void DepsgraphNodeBuilder::build_animdata(ID *id) +{ + AnimData *adt = BKE_animdata_from_id(id); + + if (adt == NULL) + return; + + /* animation */ + if (adt->action || adt->nla_tracks.first || adt->drivers.first) { + // XXX: Hook up specific update callbacks for special properties which may need it... + + /* actions and NLA - as a single unit for now, as it gets complicated to schedule otherwise */ + if ((adt->action) || (adt->nla_tracks.first)) { + /* create the node */ + add_operation_node(id, DEPSNODE_TYPE_ANIMATION, + DEPSOP_TYPE_EXEC, function_bind(BKE_animsys_eval_animdata, _1, id), + DEG_OPCODE_ANIMATION, id->name); + + // TODO: for each channel affected, we might also want to add some support for running RNA update callbacks on them + // (which will be needed for proper handling of drivers later) + } + + /* drivers */ + for (FCurve *fcu = (FCurve *)adt->drivers.first; fcu; fcu = fcu->next) { + /* create driver */ + build_driver(id, fcu); + } + } +} + +/** + * Build graph node(s) for Driver + * \param id: ID-Block that driver is attached to + * \param fcu: Driver-FCurve + */ +OperationDepsNode *DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcu) +{ + ChannelDriver *driver = fcu->driver; + + /* Create data node for this driver */ + /* TODO(sergey): Avoid creating same operation multiple times, + * in the future we need to avoid lookup of the operation as well + * and use some tagging magic instead. + */ + OperationDepsNode *driver_op = find_operation_node(id, + DEPSNODE_TYPE_PARAMETERS, + DEG_OPCODE_DRIVER, + deg_fcurve_id_name(fcu)); + + if (driver_op == NULL) { + driver_op = add_operation_node(id, DEPSNODE_TYPE_PARAMETERS, + DEPSOP_TYPE_EXEC, function_bind(BKE_animsys_eval_driver, _1, id, fcu), + DEG_OPCODE_DRIVER, deg_fcurve_id_name(fcu)); + } + + /* tag "scripted expression" drivers as needing Python (due to GIL issues, etc.) */ + if (driver->type == DRIVER_TYPE_PYTHON) { + driver_op->flag |= DEPSOP_FLAG_USES_PYTHON; + } + + /* return driver node created */ + return driver_op; +} + +/* Recursively build graph for world */ +void DepsgraphNodeBuilder::build_world(World *world) +{ + ID *world_id = &world->id; + if (world_id->flag & LIB_DOIT) { + return; + } + + /* world itself */ + IDDepsNode *world_node = add_id_node(world_id); /* world shading/params? */ + + build_animdata(world_id); + + /* TODO: other settings? */ + + /* textures */ + build_texture_stack(world_node, world->mtex); + + /* world's nodetree */ + if (world->nodetree) { + build_nodetree(world_node, world->nodetree); + } +} + +/* Rigidbody Simulation - Scene Level */ +void DepsgraphNodeBuilder::build_rigidbody(Scene *scene) +{ + RigidBodyWorld *rbw = scene->rigidbody_world; + + /** + * Rigidbody Simulation Nodes + * ========================== + * + * There are 3 nodes related to Rigidbody Simulation: + * 1) "Initialize/Rebuild World" - this is called sparingly, only when the simulation + * needs to be rebuilt (mainly after file reload, or moving back to start frame) + * 2) "Do Simulation" - perform a simulation step - interleaved between the evaluation + * steps for clusters of objects (i.e. between those affected and/or not affected by + * the sim for instance) + * + * 3) "Pull Results" - grab the specific transforms applied for a specific object - + * performed as part of object's transform-stack building + */ + + /* create nodes ------------------------------------------------------------------------ */ + /* XXX: is this the right component, or do we want to use another one instead? */ + + /* init/rebuild operation */ + /*OperationDepsNode *init_node =*/ add_operation_node(&scene->id, DEPSNODE_TYPE_TRANSFORM, + DEPSOP_TYPE_REBUILD, function_bind(BKE_rigidbody_rebuild_sim, _1, scene), + DEG_OPCODE_RIGIDBODY_REBUILD); + + /* do-sim operation */ + // XXX: what happens if we need to split into several groups? + OperationDepsNode *sim_node = add_operation_node(&scene->id, DEPSNODE_TYPE_TRANSFORM, + DEPSOP_TYPE_SIM, function_bind(BKE_rigidbody_eval_simulation, _1, scene), + DEG_OPCODE_RIGIDBODY_SIM); + + /* XXX: For now, the sim node is the only one that really matters here. If any other + * sims get added later, we may have to remove these hacks... + */ + sim_node->owner->entry_operation = sim_node; + sim_node->owner->exit_operation = sim_node; + + + /* objects - simulation participants */ + if (rbw->group) { + for (GroupObject *go = (GroupObject *)rbw->group->gobject.first; go; go = go->next) { + Object *ob = go->ob; + + if (!ob || (ob->type != OB_MESH)) + continue; + + /* 2) create operation for flushing results */ + /* object's transform component - where the rigidbody operation lives */ + add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM, + DEPSOP_TYPE_EXEC, function_bind(BKE_rigidbody_object_sync_transforms, _1, scene, ob), + DEG_OPCODE_TRANSFORM_RIGIDBODY); + } + } +} + +void DepsgraphNodeBuilder::build_particles(Object *ob) +{ + /** + * Particle Systems Nodes + * ====================== + * + * There are two types of nodes associated with representing + * particle systems: + * 1) Component (EVAL_PARTICLES) - This is the particle-system + * evaluation context for an object. It acts as the container + * for all the nodes associated with a particular set of particle + * systems. + * 2) Particle System Eval Operation - This operation node acts as a + * blackbox evaluation step for one particle system referenced by + * the particle systems stack. All dependencies link to this operation. + */ + + /* component for all particle systems */ + ComponentDepsNode *psys_comp = add_component_node(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES); + + /* particle systems */ + for (ParticleSystem *psys = (ParticleSystem *)ob->particlesystem.first; psys; psys = psys->next) { + ParticleSettings *part = psys->part; + + /* particle settings */ + // XXX: what if this is used more than once! + build_animdata(&part->id); + + /* this particle system */ + // TODO: for now, this will just be a placeholder "ubereval" node + add_operation_node(psys_comp, + DEPSOP_TYPE_EXEC, function_bind(BKE_particle_system_eval, _1, ob, psys), + DEG_OPCODE_PSYS_EVAL, + psys->name); + } + + /* pointcache */ + // TODO... +} + +/* IK Solver Eval Steps */ +void DepsgraphNodeBuilder::build_ik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con) +{ + bKinematicConstraint *data = (bKinematicConstraint *)con->data; + + /* Find the chain's root. */ + bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data); + + if (has_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, + DEG_OPCODE_POSE_IK_SOLVER)) + { + return; + } + + /* Operation node for evaluating/running IK Solver. */ + add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, + DEPSOP_TYPE_SIM, function_bind(BKE_pose_iktree_evaluate, _1, scene, ob, rootchan), + DEG_OPCODE_POSE_IK_SOLVER); +} + +/* Spline IK Eval Steps */ +void DepsgraphNodeBuilder::build_splineik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con) +{ + bSplineIKConstraint *data = (bSplineIKConstraint *)con->data; + + /* Find the chain's root. */ + bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data); + + /* Operation node for evaluating/running Spline IK Solver. + * Store the "root bone" of this chain in the solver, so it knows where to start. + */ + add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, + DEPSOP_TYPE_SIM, function_bind(BKE_pose_splineik_evaluate, _1, scene, ob, rootchan), + DEG_OPCODE_POSE_SPLINE_IK_SOLVER); +} + +/* Pose/Armature Bones Graph */ +void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob) +{ + bArmature *arm = (bArmature *)ob->data; + + /* animation and/or drivers linking posebones to base-armature used to define them + * NOTE: AnimData here is really used to control animated deform properties, + * which ideally should be able to be unique across different instances. + * Eventually, we need some type of proxy/isolation mechanism in-between here + * to ensure that we can use same rig multiple times in same scene... + */ + build_animdata(&arm->id); + + /* Rebuild pose if not up to date. */ + if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) { + BKE_pose_rebuild(ob, arm); + /* XXX: Without this animation gets lost in certain circumstances + * after loading file. Need to investigate further since it does + * not happen with simple scenes.. + */ + if (ob->adt) { + ob->adt->recalc |= ADT_RECALC_ANIM; + } + } + + /** + * Pose Rig Graph + * ============== + * + * Pose Component: + * - Mainly used for referencing Bone components. + * - This is where the evaluation operations for init/exec/cleanup + * (ik) solvers live, and are later hooked up (so that they can be + * interleaved during runtime) with bone-operations they depend on/affect. + * - init_pose_eval() and cleanup_pose_eval() are absolute first and last + * steps of pose eval process. ALL bone operations must be performed + * between these two... + * + * Bone Component: + * - Used for representing each bone within the rig + * - Acts to encapsulate the evaluation operations (base matrix + parenting, + * and constraint stack) so that they can be easily found. + * - Everything else which depends on bone-results hook up to the component only + * so that we can redirect those to point at either the the post-IK/ + * post-constraint/post-matrix steps, as needed. + */ + + /* pose eval context */ + add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, + DEPSOP_TYPE_INIT, function_bind(BKE_pose_eval_init, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_INIT); + + add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, + DEPSOP_TYPE_POST, function_bind(BKE_pose_eval_flush, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_DONE); + + /* bones */ + for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) { + /* node for bone eval */ + add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, + DEPSOP_TYPE_INIT, NULL, // XXX: BKE_pose_eval_bone_local + DEG_OPCODE_BONE_LOCAL); + + add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, + DEPSOP_TYPE_EXEC, function_bind(BKE_pose_eval_bone, _1, scene, ob, pchan), // XXX: BKE_pose_eval_bone_pose + DEG_OPCODE_BONE_POSE_PARENT); + + add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, + DEPSOP_TYPE_OUT, NULL, /* NOTE: dedicated noop for easier relationship construction */ + DEG_OPCODE_BONE_READY); + + add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, + DEPSOP_TYPE_POST, function_bind(BKE_pose_bone_done, _1, pchan), + DEG_OPCODE_BONE_DONE); + + /* constraints */ + if (pchan->constraints.first != NULL) { + build_pose_constraints(ob, pchan); + } + + /** + * IK Solvers... + * + * - These require separate processing steps are pose-level + * to be executed between chains of bones (i.e. once the + * base transforms of a bunch of bones is done) + * + * Unsolved Issues: + * - Care is needed to ensure that multi-headed trees work out the same as in ik-tree building + * - Animated chain-lengths are a problem... + */ + for (bConstraint *con = (bConstraint *)pchan->constraints.first; con; con = con->next) { + switch (con->type) { + case CONSTRAINT_TYPE_KINEMATIC: + build_ik_pose(scene, ob, pchan, con); + break; + + case CONSTRAINT_TYPE_SPLINEIK: + build_splineik_pose(scene, ob, pchan, con); + break; + + default: + break; + } + } + } +} + +void DepsgraphNodeBuilder::build_proxy_rig(Object *ob) +{ + ID *obdata = (ID *)ob->data; + build_animdata(obdata); + + add_operation_node(&ob->id, + DEPSNODE_TYPE_EVAL_POSE, + DEPSOP_TYPE_INIT, + function_bind(BKE_pose_eval_proxy_copy, _1, ob), + DEG_OPCODE_POSE_INIT); + + for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; + pchan != NULL; + pchan = pchan->next) + { + add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, + DEPSOP_TYPE_INIT, NULL, + DEG_OPCODE_BONE_LOCAL); + + add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, + DEPSOP_TYPE_EXEC, NULL, + DEG_OPCODE_BONE_READY); + + add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, + DEPSOP_TYPE_POST, NULL, + DEG_OPCODE_BONE_DONE); + } + + add_operation_node(&ob->id, + DEPSNODE_TYPE_EVAL_POSE, + DEPSOP_TYPE_POST, + NULL, + DEG_OPCODE_POSE_DONE); +} + +/* Shapekeys */ +void DepsgraphNodeBuilder::build_shapekeys(Key *key) +{ + build_animdata(&key->id); +} + +/* ObData Geometry Evaluation */ +// XXX: what happens if the datablock is shared! +void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob) +{ + ID *obdata = (ID *)ob->data; + + /* Temporary uber-update node, which does everything. + * It is for the being we're porting old dependencies into the new system. + * We'll get rid of this node as soon as all the granular update functions + * are filled in. + * + * TODO(sergey): Get rid of this node. + */ + add_operation_node(&ob->id, DEPSNODE_TYPE_GEOMETRY, + DEPSOP_TYPE_POST, function_bind(BKE_object_eval_uber_data, _1, scene, ob), + DEG_OPCODE_GEOMETRY_UBEREVAL); + + add_operation_node(&ob->id, DEPSNODE_TYPE_GEOMETRY, + DEPSOP_TYPE_INIT, NULL, + DEG_OPCODE_PLACEHOLDER, "Eval Init"); + + // TODO: "Done" operation + + /* ShapeKeys */ + Key *key = BKE_key_from_object(ob); + if (key) + build_shapekeys(key); + + /* Modifiers */ + if (ob->modifiers.first) { + ModifierData *md; + + for (md = (ModifierData *)ob->modifiers.first; md; md = md->next) { + add_operation_node(&ob->id, DEPSNODE_TYPE_GEOMETRY, + DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_modifier, _1, scene, ob, md), + DEG_OPCODE_GEOMETRY_MODIFIER, md->name); + } + } + + /* materials */ + if (ob->totcol) { + int a; + + for (a = 1; a <= ob->totcol; a++) { + Material *ma = give_current_material(ob, a); + + if (ma) { + // XXX?! + ComponentDepsNode *geom_node = add_component_node(&ob->id, DEPSNODE_TYPE_GEOMETRY); + build_material(geom_node, ma); + } + } + } + + /* geometry collision */ + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_LATTICE)) { + // add geometry collider relations + } + + if (obdata->flag & LIB_DOIT) { + return; + } + + build_animdata(obdata); + + /* nodes for result of obdata's evaluation, and geometry evaluation on object */ + switch (ob->type) { + case OB_MESH: + { + //Mesh *me = (Mesh *)ob->data; + + /* evaluation operations */ + add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY, + DEPSOP_TYPE_INIT, function_bind(BKE_mesh_eval_geometry, _1, (Mesh *)obdata), + DEG_OPCODE_PLACEHOLDER, "Geometry Eval"); + } + break; + + case OB_MBALL: + { + Object *mom = BKE_mball_basis_find(scene, ob); + + /* motherball - mom depends on children! */ + if (mom == ob) { + /* metaball evaluation operations */ + /* NOTE: only the motherball gets evaluated! */ + add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY, + DEPSOP_TYPE_INIT, function_bind(BKE_mball_eval_geometry, _1, (MetaBall *)obdata), + DEG_OPCODE_PLACEHOLDER, "Geometry Eval"); + } + } + break; + + case OB_CURVE: + case OB_FONT: + { + /* curve evaluation operations */ + /* - calculate curve geometry (including path) */ + add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY, + DEPSOP_TYPE_INIT, function_bind(BKE_curve_eval_geometry, _1, (Curve *)obdata), + DEG_OPCODE_PLACEHOLDER, "Geometry Eval"); + + /* - calculate curve path - this is used by constraints, etc. */ + add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY, + DEPSOP_TYPE_EXEC, function_bind(BKE_curve_eval_path, _1, (Curve *)obdata), + DEG_OPCODE_GEOMETRY_PATH, "Path"); + } + break; + + case OB_SURF: /* Nurbs Surface */ + { + /* nurbs evaluation operations */ + add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY, + DEPSOP_TYPE_INIT, function_bind(BKE_curve_eval_geometry, _1, (Curve *)obdata), + DEG_OPCODE_PLACEHOLDER, "Geometry Eval"); + } + break; + + case OB_LATTICE: /* Lattice */ + { + /* lattice evaluation operations */ + add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY, + DEPSOP_TYPE_INIT, function_bind(BKE_lattice_eval_geometry, _1, (Lattice *)obdata), + DEG_OPCODE_PLACEHOLDER, "Geometry Eval"); + } + break; + } + + add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY, + DEPSOP_TYPE_POST, NULL, + DEG_OPCODE_PLACEHOLDER, "Eval Done"); + + /* Parameters for driver sources. */ + add_operation_node(obdata, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL, + DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); +} + +/* Cameras */ +void DepsgraphNodeBuilder::build_camera(Object *ob) +{ + /* TODO: Link scene-camera links in somehow... */ + Camera *cam = (Camera *)ob->data; + ID *camera_id = &cam->id; + if (camera_id->flag & LIB_DOIT) { + return; + } + + build_animdata(&cam->id); + + add_operation_node(camera_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL, + DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); + + if (cam->dof_ob != NULL) { + /* TODO(sergey): For now parametrs are on object level. */ + add_operation_node(&ob->id, DEPSNODE_TYPE_PARAMETERS, + DEPSOP_TYPE_EXEC, NULL, + DEG_OPCODE_PLACEHOLDER, + "Camera DOF"); + } +} + +/* Lamps */ +void DepsgraphNodeBuilder::build_lamp(Object *ob) +{ + Lamp *la = (Lamp *)ob->data; + ID *lamp_id = &la->id; + if (lamp_id->flag & LIB_DOIT) { + return; + } + + build_animdata(&la->id); + + /* node for obdata */ + ComponentDepsNode *param_node = add_component_node(lamp_id, DEPSNODE_TYPE_PARAMETERS); + + /* TODO(sergey): Is it really how we're supposed to work with drivers? */ + add_operation_node(lamp_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL, + DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); + + /* lamp's nodetree */ + if (la->nodetree) { + build_nodetree(param_node, la->nodetree); + } + + /* textures */ + build_texture_stack(param_node, la->mtex); +} + +void DepsgraphNodeBuilder::build_nodetree(DepsNode *owner_node, bNodeTree *ntree) +{ + if (!ntree) + return; + + /* nodetree itself */ + ID *ntree_id = &ntree->id; + + build_animdata(ntree_id); + + /* Parameters for drivers. */ + add_operation_node(ntree_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL, + DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); + + /* nodetree's nodes... */ + for (bNode *bnode = (bNode *)ntree->nodes.first; bnode; bnode = bnode->next) { + if (bnode->id) { + if (GS(bnode->id->name) == ID_MA) { + build_material(owner_node, (Material *)bnode->id); + } + else if (bnode->type == ID_TE) { + build_texture(owner_node, (Tex *)bnode->id); + } + else if (bnode->type == NODE_GROUP) { + bNodeTree *ntree = (bNodeTree *)bnode->id; + if ((ntree_id->flag & LIB_DOIT) == 0) { + build_nodetree(owner_node, ntree); + } + } + } + } + + // TODO: link from nodetree to owner_component? +} + +/* Recursively build graph for material */ +void DepsgraphNodeBuilder::build_material(DepsNode *owner_node, Material *ma) +{ + ID *ma_id = &ma->id; + if (ma_id->flag & LIB_DOIT) { + return; + } + + /* material itself */ + add_id_node(ma_id); + + add_operation_node(ma_id, DEPSNODE_TYPE_SHADING, + DEPSOP_TYPE_EXEC, NULL, + DEG_OPCODE_PLACEHOLDER, "Material Update"); + + /* material animation */ + build_animdata(ma_id); + + /* textures */ + build_texture_stack(owner_node, ma->mtex); + + /* material's nodetree */ + build_nodetree(owner_node, ma->nodetree); +} + +/* Texture-stack attached to some shading datablock */ +void DepsgraphNodeBuilder::build_texture_stack(DepsNode *owner_node, MTex **texture_stack) +{ + int i; + + /* for now assume that all texture-stacks have same number of max items */ + for (i = 0; i < MAX_MTEX; i++) { + MTex *mtex = texture_stack[i]; + if (mtex && mtex->tex) + build_texture(owner_node, mtex->tex); + } +} + +/* Recursively build graph for texture */ +void DepsgraphNodeBuilder::build_texture(DepsNode *owner_node, Tex *tex) +{ + ID *tex_id = &tex->id; + if (tex_id->flag & LIB_DOIT) { + return; + } + tex_id->flag |= LIB_DOIT; + /* texture itself */ + build_animdata(tex_id); + /* texture's nodetree */ + build_nodetree(owner_node, tex->nodetree); +} + +void DepsgraphNodeBuilder::build_compositor(Scene *scene) +{ + /* For now, just a plain wrapper? */ + // TODO: create compositing component? + // XXX: component type undefined! + //graph->get_node(&scene->id, NULL, DEPSNODE_TYPE_COMPOSITING, NULL); + + /* for now, nodetrees are just parameters; compositing occurs in internals of renderer... */ + ComponentDepsNode *owner_node = add_component_node(&scene->id, DEPSNODE_TYPE_PARAMETERS); + build_nodetree(owner_node, scene->nodetree); +} + +void DepsgraphNodeBuilder::build_gpencil(bGPdata *gpd) +{ + ID *gpd_id = &gpd->id; + + /* gpencil itself */ + // XXX: what about multiple users of same datablock? This should only get added once + add_id_node(gpd_id); + + /* The main reason Grease Pencil is included here is because the animation (and drivers) + * need to be hosted somewhere... + */ + build_animdata(gpd_id); +} diff --git a/source/blender/depsgraph/intern/depsgraph_build_relations.cc b/source/blender/depsgraph/intern/depsgraph_build_relations.cc new file mode 100644 index 00000000000..300ed07de56 --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph_build_relations.cc @@ -0,0 +1,1815 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013) + * + * ***** END GPL LICENSE BLOCK ***** + * + * Methods for constructing depsgraph + */ + +#include +#include +#include + +#include "MEM_guardedalloc.h" + +extern "C" { +#include "BLI_blenlib.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "DNA_action_types.h" +#include "DNA_anim_types.h" +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_constraint_types.h" +#include "DNA_curve_types.h" +#include "DNA_effect_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_group_types.h" +#include "DNA_key_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meta_types.h" +#include "DNA_node_types.h" +#include "DNA_particle_types.h" +#include "DNA_object_types.h" +#include "DNA_rigidbody_types.h" +#include "DNA_scene_types.h" +#include "DNA_texture_types.h" +#include "DNA_world_types.h" + +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_animsys.h" +#include "BKE_constraint.h" +#include "BKE_curve.h" +#include "BKE_effect.h" +#include "BKE_fcurve.h" +#include "BKE_group.h" +#include "BKE_key.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_mball.h" +#include "BKE_modifier.h" +#include "BKE_node.h" +#include "BKE_object.h" +#include "BKE_particle.h" +#include "BKE_rigidbody.h" +#include "BKE_sound.h" +#include "BKE_texture.h" +#include "BKE_tracking.h" +#include "BKE_world.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + +#include "RNA_access.h" +#include "RNA_types.h" +} /* extern "C" */ + +#include "depsnode.h" +#include "depsnode_component.h" +#include "depsnode_operation.h" +#include "depsgraph_build.h" +#include "depsgraph_debug.h" +#include "depsgraph_intern.h" +#include "depsgraph_types.h" + +#include "depsgraph_util_pchanmap.h" + +/* ***************** */ +/* Relations Builder */ + +/* **** General purpose functions **** */ + +RNAPathKey::RNAPathKey(ID *id, const string &path) : + id(id) +{ + /* create ID pointer for root of path lookup */ + PointerRNA id_ptr; + RNA_id_pointer_create(id, &id_ptr); + /* try to resolve path... */ + if (!RNA_path_resolve(&id_ptr, path.c_str(), &this->ptr, &this->prop)) { + this->ptr = PointerRNA_NULL; + this->prop = NULL; + } +} + +DepsgraphRelationBuilder::DepsgraphRelationBuilder(Depsgraph *graph) : + m_graph(graph) +{ +} + +RootDepsNode *DepsgraphRelationBuilder::find_node(const RootKey &key) const +{ + (void)key; + BLI_assert(!"Doesn't seem to be correct"); + return m_graph->root_node; +} + +TimeSourceDepsNode *DepsgraphRelationBuilder::find_node( + const TimeSourceKey &key) const +{ + if (key.id) { + /* XXX TODO */ + return NULL; + } + else { + return m_graph->root_node->time_source; + } +} + +ComponentDepsNode *DepsgraphRelationBuilder::find_node( + const ComponentKey &key) const +{ + IDDepsNode *id_node = m_graph->find_id_node(key.id); + if (!id_node) { + fprintf(stderr, "find_node component: Could not find ID %s\n", + (key.id != NULL) ? key.id->name : ""); + return NULL; + } + + ComponentDepsNode *node = id_node->find_component(key.type, key.name); + return node; +} + +OperationDepsNode *DepsgraphRelationBuilder::find_node( + const OperationKey &key) const +{ + IDDepsNode *id_node = m_graph->find_id_node(key.id); + if (!id_node) { + fprintf(stderr, "find_node operation: Could not find ID\n"); + return NULL; + } + + ComponentDepsNode *comp_node = id_node->find_component(key.component_type, + key.component_name); + if (!comp_node) { + fprintf(stderr, "find_node operation: Could not find component\n"); + return NULL; + } + + OperationDepsNode *op_node = comp_node->find_operation(key.opcode, key.name); + if (!op_node) { + fprintf(stderr, "find_node_operation: Failed for (%s, '%s')\n", + DEG_OPNAMES[key.opcode], key.name.c_str()); + } + return op_node; +} + +DepsNode *DepsgraphRelationBuilder::find_node(const RNAPathKey &key) const +{ + return m_graph->find_node_from_pointer(&key.ptr, key.prop); +} + +OperationDepsNode *DepsgraphRelationBuilder::has_node( + const OperationKey &key) const +{ + IDDepsNode *id_node = m_graph->find_id_node(key.id); + if (!id_node) { + return NULL; + } + ComponentDepsNode *comp_node = id_node->find_component(key.component_type, + key.component_name); + if (!comp_node) { + return NULL; + } + return comp_node->has_operation(key.opcode, key.name); +} + +void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc, + DepsNode *node_to, + const char *description) +{ + if (timesrc && node_to) { + m_graph->add_new_relation(timesrc, node_to, DEPSREL_TYPE_TIME, description); + } + else { + DEG_DEBUG_PRINTF("add_time_relation(%p = %s, %p = %s, %s) Failed\n", + timesrc, (timesrc) ? timesrc->identifier().c_str() : "", + node_to, (node_to) ? node_to->identifier().c_str() : "", + description); + } +} + +void DepsgraphRelationBuilder::add_operation_relation( + OperationDepsNode *node_from, + OperationDepsNode *node_to, + eDepsRelation_Type type, + const char *description) +{ + if (node_from && node_to) { + m_graph->add_new_relation(node_from, node_to, type, description); + } + else { + DEG_DEBUG_PRINTF("add_operation_relation(%p = %s, %p = %s, %d, %s) Failed\n", + node_from, (node_from) ? node_from->identifier().c_str() : "", + node_to, (node_to) ? node_to->identifier().c_str() : "", + type, description); + } +} + +/* **** Functions to build relations between entities **** */ + +void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene) +{ + /* LIB_DOIT is used to indicate whether node for given ID was already + * created or not. + */ + BKE_main_id_tag_all(bmain, false); + + if (scene->set) { + // TODO: link set to scene, especially our timesource... + } + + /* scene objects */ + for (Base *base = (Base *)scene->base.first; base; base = base->next) { + Object *ob = base->object; + + /* object itself */ + build_object(bmain, scene, ob); + + /* object that this is a proxy for */ + if (ob->proxy) { + build_object(bmain, scene, ob->proxy); + /* TODO(sergey): This is an inverted relation, matches old depsgraph + * behavior and need to be investigated if it still need to be inverted. + */ + ComponentKey ob_pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE); + ComponentKey proxy_pose_key(&ob->proxy->id, DEPSNODE_TYPE_EVAL_POSE); + add_relation(ob_pose_key, proxy_pose_key, DEPSREL_TYPE_TRANSFORM, "Proxy"); + } + + /* Object dupligroup. */ + if (ob->dup_group) { + build_group(bmain, scene, ob, ob->dup_group); + } + } + + /* rigidbody */ + if (scene->rigidbody_world) { + build_rigidbody(scene); + } + + /* scene's animation and drivers */ + if (scene->adt) { + build_animdata(&scene->id); + } + + /* world */ + if (scene->world) { + build_world(scene->world); + } + + /* compo nodes */ + if (scene->nodetree) { + build_compositor(scene); + } + + /* grease pencil */ + if (scene->gpd) { + build_gpencil(&scene->id, scene->gpd); + } +} + +void DepsgraphRelationBuilder::build_group(Main *bmain, + Scene *scene, + Object *object, + Group *group) +{ + ID *group_id = &group->id; + bool group_done = (group_id->flag & LIB_DOIT) != 0; + OperationKey object_local_transform_key(&object->id, + DEPSNODE_TYPE_TRANSFORM, + DEG_OPCODE_TRANSFORM_LOCAL); + for (GroupObject *go = (GroupObject *)group->gobject.first; + go != NULL; + go = go->next) + { + if (!group_done) { + build_object(bmain, scene, go->ob); + } + ComponentKey dupli_transform_key(&go->ob->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(dupli_transform_key, + object_local_transform_key, + DEPSREL_TYPE_TRANSFORM, + "Dupligroup"); + } + group_id->flag |= LIB_DOIT; +} + +void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *ob) +{ + if (ob->id.flag & LIB_DOIT) { + return; + } + + /* Object Transforms */ + eDepsOperation_Code base_op = (ob->parent) ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL; + OperationKey base_op_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, base_op); + + OperationKey local_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL); + OperationKey parent_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT); + OperationKey final_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); + + OperationKey ob_ubereval_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_OBJECT_UBEREVAL); + + /* parenting */ + if (ob->parent) { + /* parent relationship */ + build_object_parent(ob); + + /* local -> parent */ + add_relation(local_transform_key, parent_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "[ObLocal -> ObParent]"); + } + + /* object constraints */ + if (ob->constraints.first) { + OperationKey constraint_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_CONSTRAINTS); + + /* constraint relations */ + // TODO: provide base op + // XXX: this is broken + build_constraints(scene, &ob->id, DEPSNODE_TYPE_TRANSFORM, "", &ob->constraints, NULL); + + /* operation order */ + add_relation(base_op_key, constraint_key, DEPSREL_TYPE_COMPONENT_ORDER, "[ObBase-> Constraint Stack]"); + add_relation(constraint_key, final_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "[ObConstraints -> Done]"); + + // XXX + add_relation(constraint_key, ob_ubereval_key, DEPSREL_TYPE_COMPONENT_ORDER, "Temp Ubereval"); + add_relation(ob_ubereval_key, final_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "Temp Ubereval"); + } + else { + /* operation order */ + add_relation(base_op_key, final_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "Object Transform"); + + // XXX + add_relation(base_op_key, ob_ubereval_key, DEPSREL_TYPE_COMPONENT_ORDER, "Temp Ubereval"); + add_relation(ob_ubereval_key, final_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "Temp Ubereval"); + } + + + /* AnimData */ + build_animdata(&ob->id); + + // XXX: This should be hooked up by the build_animdata code + if (ob->adt && (ob->adt->action || ob->adt->nla_tracks.first)) { + ComponentKey adt_key(&ob->id, DEPSNODE_TYPE_ANIMATION); + add_relation(adt_key, local_transform_key, DEPSREL_TYPE_OPERATION, "Object Animation"); + } + + + /* object data */ + if (ob->data) { + ID *obdata_id = (ID *)ob->data; + + /* ob data animation */ + build_animdata(obdata_id); + + /* type-specific data... */ + switch (ob->type) { + case OB_MESH: /* Geometry */ + case OB_CURVE: + case OB_FONT: + case OB_SURF: + case OB_MBALL: + case OB_LATTICE: + { + build_obdata_geom(bmain, scene, ob); + } + break; + + + case OB_ARMATURE: /* Pose */ + if (ob->id.lib != NULL && ob->proxy_from != NULL) { + build_proxy_rig(ob); + } + else { + build_rig(scene, ob); + } + break; + + case OB_LAMP: /* Lamp */ + build_lamp(ob); + break; + + case OB_CAMERA: /* Camera */ + build_camera(ob); + break; + } + } + + /* particle systems */ + if (ob->particlesystem.first) { + build_particles(scene, ob); + } + + /* grease pencil */ + if (ob->gpd) { + build_gpencil(&ob->id, ob->gpd); + } +} + +void DepsgraphRelationBuilder::build_object_parent(Object *ob) +{ + /* XXX: for now, need to use the component key (not just direct to the parent op), or else the matrix doesn't get reset */ + // XXX: @sergey - it would be good if we got that backwards flushing working when tagging for updates + //OperationKey ob_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT); + ComponentKey ob_key(&ob->id, DEPSNODE_TYPE_TRANSFORM); + + /* type-specific links */ + switch (ob->partype) { + case PARSKEL: /* Armature Deform (Virtual Modifier) */ + { + ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(parent_key, ob_key, DEPSREL_TYPE_STANDARD, "Armature Deform Parent"); + } + break; + + case PARVERT1: /* Vertex Parent */ + case PARVERT3: + { + ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(parent_key, ob_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Vertex Parent"); + /* XXX not sure what this is for or how you could be done properly - lukas */ + //parent_node->customdata_mask |= CD_MASK_ORIGINDEX; + + ComponentKey transform_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(transform_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Vertex Parent TFM"); + } + break; + + case PARBONE: /* Bone Parent */ + { + ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_BONE, ob->parsubstr); + add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Bone Parent"); + } + break; + + default: + { + if (ob->parent->type == OB_LATTICE) { + /* Lattice Deform Parent - Virtual Modifier */ + // XXX: no virtual modifiers should be left! + ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM); + ComponentKey geom_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY); + + add_relation(parent_key, ob_key, DEPSREL_TYPE_STANDARD, "Lattice Deform Parent"); + add_relation(geom_key, ob_key, DEPSREL_TYPE_STANDARD, "Lattice Deform Parent Geom"); + } + else if (ob->parent->type == OB_CURVE) { + Curve *cu = (Curve *)ob->parent->data; + + if (cu->flag & CU_PATH) { + /* Follow Path */ + ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Curve Follow Parent"); + + ComponentKey transform_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(transform_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Curve Follow TFM"); + } + else { + /* Standard Parent */ + ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Curve Parent"); + } + } + else { + /* Standard Parent */ + ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Parent"); + } + } + break; + } + + /* exception case: parent is duplivert */ + if ((ob->type == OB_MBALL) && (ob->parent->transflag & OB_DUPLIVERTS)) { + //dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Duplivert"); + } +} + +void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode_Type component_type, const char *component_subdata, + ListBase *constraints, RootPChanMap *root_map) +{ + OperationKey constraint_op_key(id, component_type, component_subdata, + (component_type == DEPSNODE_TYPE_BONE) ? DEG_OPCODE_BONE_CONSTRAINTS : DEG_OPCODE_TRANSFORM_CONSTRAINTS); + + /* add dependencies for each constraint in turn */ + for (bConstraint *con = (bConstraint *)constraints->first; con; con = con->next) { + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + + /* invalid constraint type... */ + if (cti == NULL) + continue; + + /* special case for camera tracking -- it doesn't use targets to define relations */ + // TODO: we can now represent dependencies in a much richer manner, so review how this is done... + if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { + bool depends_on_camera = false; + + if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) { + bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data; + + if (((data->clip) || (data->flag & FOLLOWTRACK_ACTIVECLIP)) && data->track[0]) + depends_on_camera = true; + + if (data->depth_ob) { + // DAG_RL_DATA_OB | DAG_RL_OB_OB + ComponentKey depth_key(&data->depth_ob->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(depth_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + } + } + else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) { + depends_on_camera = true; + } + + if (depends_on_camera && scene->camera) { + // DAG_RL_DATA_OB | DAG_RL_OB_OB + ComponentKey camera_key(&scene->camera->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(camera_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + } + + /* tracker <-> constraints */ + // FIXME: actually motionclip dependency on results of motionclip block here... + //dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation"); + } + else if (cti->get_constraint_targets) { + ListBase targets = {NULL, NULL}; + cti->get_constraint_targets(con, &targets); + + for (bConstraintTarget *ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) { + if (!ct->tar) + continue; + + if (ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK)) { + /* ignore IK constraints - these are handled separately (on pose level) */ + } + else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) { + /* these constraints require path geometry data... */ + ComponentKey target_key(&ct->tar->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(target_key, constraint_op_key, DEPSREL_TYPE_GEOMETRY_EVAL, cti->name); // XXX: type = geom_transform + // TODO: path dependency + } + else if ((ct->tar->type == OB_ARMATURE) && (ct->subtarget[0])) { + /* bone */ + if (&ct->tar->id == id) { + /* same armature */ + eDepsOperation_Code target_key_opcode; + + /* Using "done" here breaks in-chain deps, while using "ready" here breaks most production rigs instead... + * So, we do a compromise here, and only do this when an IK chain conflict may occur + */ + if (root_map->has_common_root(component_subdata, ct->subtarget)) { + target_key_opcode = DEG_OPCODE_BONE_READY; + } + else { + target_key_opcode = DEG_OPCODE_BONE_DONE; + } + + OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_BONE, ct->subtarget, target_key_opcode); + add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + } + else { + /* different armature - we can safely use the result of that */ + OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_BONE, ct->subtarget, DEG_OPCODE_BONE_DONE); + add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + } + } + else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) { + /* vertex group */ + /* NOTE: for now, we don't need to represent vertex groups separately... */ + ComponentKey target_key(&ct->tar->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(target_key, constraint_op_key, DEPSREL_TYPE_GEOMETRY_EVAL, cti->name); + + if (ct->tar->type == OB_MESH) { + //node2->customdata_mask |= CD_MASK_MDEFORMVERT; + } + } + else if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) { + /* Constraints which requires the target object surface. */ + ComponentKey target_key(&ct->tar->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + + /* NOTE: obdata eval now doesn't necessarily depend on the object's transform... */ + ComponentKey target_transform_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(target_transform_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + } + else { + /* standard object relation */ + // TODO: loc vs rot vs scale? + if (&ct->tar->id == id) { + /* Constraint targetting own object: + * - This case is fine IFF we're dealing with a bone constraint pointing to + * its own armature. In that case, it's just transform -> bone. + * - If however it is a real self targetting case, just make it depend on the + * previous constraint (or the pre-constraint state)... + */ + if ((ct->tar->type == OB_ARMATURE) && (component_type == DEPSNODE_TYPE_BONE)) { + OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); + add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + } + else { + OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL); + add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + } + } + else { + /* normal object dependency */ + OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); + add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + } + } + + /* Constraints which needs world's matrix for transform. + * TODO(sergey): More constraints here? + */ + if (ELEM(con->type, + CONSTRAINT_TYPE_ROTLIKE, + CONSTRAINT_TYPE_SIZELIKE, + CONSTRAINT_TYPE_LOCLIKE, + CONSTRAINT_TYPE_TRANSLIKE)) + { + /* TODO(sergey): Add used space check. */ + ComponentKey target_transform_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(target_transform_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + } + + } + + if (cti->flush_constraint_targets) + cti->flush_constraint_targets(con, &targets, 1); + } + } +} + +void DepsgraphRelationBuilder::build_animdata(ID *id) +{ + AnimData *adt = BKE_animdata_from_id(id); + + if (adt == NULL) + return; + + ComponentKey adt_key(id, DEPSNODE_TYPE_ANIMATION); + + /* animation */ + if (adt->action || adt->nla_tracks.first) { + /* wire up dependency to time source */ + TimeSourceKey time_src_key; + add_relation(time_src_key, adt_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Animation]"); + + // XXX: Hook up specific update callbacks for special properties which may need it... + + // XXX: animdata "hierarchy" - top-level overrides need to go after lower-down + } + + /* drivers */ + for (FCurve *fcu = (FCurve *)adt->drivers.first; fcu; fcu = fcu->next) { + OperationKey driver_key(id, DEPSNODE_TYPE_PARAMETERS, DEG_OPCODE_DRIVER, deg_fcurve_id_name(fcu)); + + /* create the driver's relations to targets */ + build_driver(id, fcu); + + /* prevent driver from occurring before own animation... */ + if (adt->action || adt->nla_tracks.first) { + add_relation(adt_key, driver_key, DEPSREL_TYPE_OPERATION, + "[AnimData Before Drivers]"); + } + } +} + +void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) +{ + ChannelDriver *driver = fcu->driver; + OperationKey driver_key(id, DEPSNODE_TYPE_PARAMETERS, DEG_OPCODE_DRIVER, deg_fcurve_id_name(fcu)); + bPoseChannel *pchan = NULL; + + /* create dependency between driver and data affected by it */ + /* - direct property relationship... */ + //RNAPathKey affected_key(id, fcu->rna_path); + //add_relation(driver_key, affected_key, DEPSREL_TYPE_DRIVER, "[Driver -> Data] DepsRel"); + + /* driver -> data components (for interleaved evaluation - bones/constraints/modifiers) */ + // XXX: this probably should probably be moved out into a separate function + if (strstr(fcu->rna_path, "pose.bones[") != NULL) { + /* interleaved drivers during bone eval */ + // TODO: ideally, if this is for a constraint, it goes to said constraint + Object *ob = (Object *)id; + char *bone_name; + + bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); + pchan = BKE_pose_channel_find_name(ob->pose, bone_name); + + if (bone_name) { + MEM_freeN(bone_name); + bone_name = NULL; + } + + if (pchan) { + OperationKey bone_key(id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); + add_relation(driver_key, bone_key, DEPSREL_TYPE_DRIVER, "[Driver -> Bone]"); + } + else { + fprintf(stderr, + "Couldn't find bone name for driver path - '%s'\n", + fcu->rna_path); + } + } + else if (GS(id->name) == ID_AR && strstr(fcu->rna_path, "bones[")) { + /* drivers on armature-level bone settings (i.e. bbone stuff), + * which will affect the evaluation of corresponding pose bones + */ + IDDepsNode *arm_node = m_graph->find_id_node(id); + char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "bones["); + + if (arm_node && bone_name) { + /* find objects which use this, and make their eval callbacks depend on this */ + DEPSNODE_RELATIONS_ITER_BEGIN(arm_node->outlinks, rel) + { + IDDepsNode *to_node = (IDDepsNode *)rel->to; + + /* we only care about objects with pose data which use this... */ + if (GS(to_node->id->name) == ID_OB) { + Object *ob = (Object *)to_node->id; + bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name); // NOTE: ob->pose may be NULL + + if (pchan) { + OperationKey bone_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); + add_relation(driver_key, bone_key, DEPSREL_TYPE_DRIVER, "[Arm Bone -> Driver -> Bone]"); + } + } + } + DEPSNODE_RELATIONS_ITER_END; + + /* free temp data */ + MEM_freeN(bone_name); + bone_name = NULL; + } + else { + fprintf(stderr, + "Couldn't find armature bone name for driver path - '%s'\n", + fcu->rna_path); + } + } + else if (GS(id->name) == ID_OB && strstr(fcu->rna_path, "modifiers[")) { + /* modifier driver - connect directly to the modifier */ + char *modifier_name = BLI_str_quoted_substrN(fcu->rna_path, "modifiers["); + if (modifier_name) { + OperationKey modifier_key(id, + DEPSNODE_TYPE_GEOMETRY, + DEG_OPCODE_GEOMETRY_MODIFIER, + modifier_name); + if (has_node(modifier_key)) { + add_relation(driver_key, modifier_key, DEPSREL_TYPE_DRIVER, "[Driver -> Modifier]"); + } + else { + printf("Unexisting driver RNA path: %s\n", fcu->rna_path); + } + + MEM_freeN(modifier_name); + } + } + else if (GS(id->name) == ID_KE && strstr(fcu->rna_path, "key_blocks[")) { + /* shape key driver - hook into the base geometry operation */ + // XXX: double check where this points + Key *shape_key = (Key *)id; + + ComponentKey geometry_key(shape_key->from, DEPSNODE_TYPE_GEOMETRY); + add_relation(driver_key, geometry_key, DEPSREL_TYPE_DRIVER, "[Driver -> ShapeKey Geom]"); + } + else { + if (GS(id->name) == ID_OB) { + /* assume that driver affects a transform... */ + OperationKey local_transform_key(id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL); + add_relation(driver_key, local_transform_key, DEPSREL_TYPE_OPERATION, "[Driver -> Transform]"); + } + } + + /* ensure that affected prop's update callbacks will be triggered once done */ + // TODO: implement this once the functionality to add these links exists in RNA + // XXX: the data itself could also set this, if it were to be truly initialised later? + + /* loop over variables to get the target relationships */ + for (DriverVar *dvar = (DriverVar *)driver->variables.first; dvar; dvar = dvar->next) { + /* only used targets */ + DRIVER_TARGETS_USED_LOOPER(dvar) + { + if (dtar->id == NULL) + continue; + + /* special handling for directly-named bones */ + if ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (dtar->pchan_name[0])) { + Object *ob = (Object *)dtar->id; + bPoseChannel *target_pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); + if (target_pchan != NULL) { + /* get node associated with bone */ + // XXX: watch the space! + /* Some cases can't use final bone transform, for example: + * - Driving the bone with itself (addressed here) + * - Relations inside an IK chain (TODO?) + */ + if (dtar->id == id && + pchan != NULL && + STREQ(pchan->name, target_pchan->name)) + { + continue; + } + OperationKey target_key(dtar->id, DEPSNODE_TYPE_BONE, target_pchan->name, DEG_OPCODE_BONE_DONE); + add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[Bone Target -> Driver]"); + } + } + else if (dtar->flag & DTAR_FLAG_STRUCT_REF) { + /* get node associated with the object's transforms */ + OperationKey target_key(dtar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); + add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[Target -> Driver]"); + } + else if (dtar->rna_path && strstr(dtar->rna_path, "pose.bones[")) { + /* workaround for ensuring that local bone transforms don't end up + * having to wait for pose eval to finish (to prevent cycles) + */ + Object *ob = (Object *)dtar->id; + char *bone_name = BLI_str_quoted_substrN(dtar->rna_path, "pose.bones["); + bPoseChannel *target_pchan = BKE_pose_channel_find_name(ob->pose, bone_name); + if (bone_name) { + MEM_freeN(bone_name); + bone_name = NULL; + } + if (target_pchan) { + if (dtar->id == id && + pchan != NULL && + STREQ(pchan->name, target_pchan->name)) + { + continue; + } + OperationKey bone_key(dtar->id, DEPSNODE_TYPE_BONE, target_pchan->name, DEG_OPCODE_BONE_LOCAL); + add_relation(bone_key, driver_key, DEPSREL_TYPE_DRIVER, "[RNA Bone -> Driver]"); + } + } + else { + /* resolve path to get node */ + RNAPathKey target_key(dtar->id, dtar->rna_path ? dtar->rna_path : ""); + add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[RNA Target -> Driver]"); + } + } + DRIVER_TARGETS_LOOPER_END + } +} + +void DepsgraphRelationBuilder::build_world(World *world) +{ + ID *world_id = &world->id; + if (world_id->flag & LIB_DOIT) { + return; + } + world_id->flag |= LIB_DOIT; + + build_animdata(world_id); + + /* TODO: other settings? */ + + /* textures */ + build_texture_stack(world_id, world->mtex); + + /* world's nodetree */ + build_nodetree(world_id, world->nodetree); +} + +void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) +{ + RigidBodyWorld *rbw = scene->rigidbody_world; + + OperationKey init_key(&scene->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_REBUILD); + OperationKey sim_key(&scene->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_SIM); + + /* rel between the two sim-nodes */ + add_relation(init_key, sim_key, DEPSREL_TYPE_OPERATION, "Rigidbody [Init -> SimStep]"); + + /* set up dependencies between these operations and other builtin nodes --------------- */ + + /* time dependency */ + TimeSourceKey time_src_key; + add_relation(time_src_key, init_key, DEPSREL_TYPE_TIME, "TimeSrc -> Rigidbody Reset/Rebuild (Optional)"); + add_relation(time_src_key, sim_key, DEPSREL_TYPE_TIME, "TimeSrc -> Rigidbody Sim Step"); + + /* objects - simulation participants */ + if (rbw->group) { + for (GroupObject *go = (GroupObject *)rbw->group->gobject.first; go; go = go->next) { + Object *ob = go->ob; + if (!ob || ob->type != OB_MESH) + continue; + + /* hook up evaluation order... + * 1) flushing rigidbody results follows base transforms being applied + * 2) rigidbody flushing can only be performed after simulation has been run + * + * 3) simulation needs to know base transforms to figure out what to do + * XXX: there's probably a difference between passive and active + * - passive don't change, so may need to know full transform... + */ + OperationKey rbo_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY); + + eDepsOperation_Code trans_opcode = ob->parent ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL; + OperationKey trans_op(&ob->id, DEPSNODE_TYPE_TRANSFORM, trans_opcode); + + add_relation(trans_op, rbo_key, DEPSREL_TYPE_OPERATION, "Base Ob Transform -> RBO Sync"); + add_relation(sim_key, rbo_key, DEPSREL_TYPE_COMPONENT_ORDER, "Rigidbody Sim Eval -> RBO Sync"); + + /* if constraints exist, those depend on the result of the rigidbody sim + * - This allows constraints to modify the result of the sim (i.e. clamping) + * while still allowing the sim to depend on some changes to the objects. + * Also, since constraints are hooked up to the final nodes, this link + * means that we can also fit in there too... + * - Later, it might be good to include a constraint in the stack allowing us + * to control whether rigidbody eval gets interleaved into the constraint stack + */ + if (ob->constraints.first) { + OperationKey constraint_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_CONSTRAINTS); + add_relation(rbo_key, constraint_key, DEPSREL_TYPE_COMPONENT_ORDER, "RBO Sync -> Ob Constraints"); + } + else { + /* final object transform depends on rigidbody */ + OperationKey done_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); + add_relation(rbo_key, done_key, DEPSREL_TYPE_COMPONENT_ORDER, "RBO Sync -> Done"); + + // XXX: ubereval will be removed eventually, but we still need it in the meantime + OperationKey uber_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_OBJECT_UBEREVAL); + add_relation(rbo_key, uber_key, DEPSREL_TYPE_COMPONENT_ORDER, "RBO Sync -> Uber (Temp)"); + } + + + /* needed to get correct base values */ + add_relation(trans_op, sim_key, DEPSREL_TYPE_OPERATION, "Base Ob Transform -> Rigidbody Sim Eval"); + } + } + + /* constraints */ + if (rbw->constraints) { + for (GroupObject *go = (GroupObject *)rbw->constraints->gobject.first; go; go = go->next) { + Object *ob = go->ob; + if (!ob || !ob->rigidbody_constraint) + continue; + + RigidBodyCon *rbc = ob->rigidbody_constraint; + + /* final result of the constraint object's transform controls how the + * constraint affects the physics sim for these objects + */ + ComponentKey trans_key(&ob->id, DEPSNODE_TYPE_TRANSFORM); + OperationKey ob1_key(&rbc->ob1->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY); + OperationKey ob2_key(&rbc->ob2->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY); + + /* - constrained-objects sync depends on the constraint-holder */ + add_relation(trans_key, ob1_key, DEPSREL_TYPE_TRANSFORM, "RigidBodyConstraint -> RBC.Object_1"); + add_relation(trans_key, ob2_key, DEPSREL_TYPE_TRANSFORM, "RigidBodyConstraint -> RBC.Object_2"); + + /* - ensure that sim depends on this constraint's transform */ + add_relation(trans_key, sim_key, DEPSREL_TYPE_TRANSFORM, "RigidBodyConstraint Transform -> RB Simulation"); + } + } +} + +void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob) +{ + /* particle systems */ + for (ParticleSystem *psys = (ParticleSystem *)ob->particlesystem.first; psys; psys = psys->next) { + ParticleSettings *part = psys->part; + + /* particle settings */ + build_animdata(&part->id); + + /* this particle system */ + OperationKey psys_key(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, psys->name); + + /* XXX: if particle system is later re-enabled, we must do full rebuild? */ + if (!psys_check_enabled(ob, psys)) + continue; + +#if 0 + if (ELEM(part->phystype, PART_PHYS_KEYED, PART_PHYS_BOIDS)) { + ParticleTarget *pt; + + for (pt = psys->targets.first; pt; pt = pt->next) { + if (pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys - 1)) { + node2 = dag_get_node(dag, pt->ob); + dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Targets"); + } + } + } + + if (part->ren_as == PART_DRAW_OB && part->dup_ob) { + node2 = dag_get_node(dag, part->dup_ob); + /* note that this relation actually runs in the wrong direction, the problem + * is that dupli system all have this (due to parenting), and the render + * engine instancing assumes particular ordering of objects in list */ + dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualization"); + if (part->dup_ob->type == OB_MBALL) + dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualization"); + } + + if (part->ren_as == PART_DRAW_GR && part->dup_group) { + for (go = part->dup_group->gobject.first; go; go = go->next) { + node2 = dag_get_node(dag, go->ob); + dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Particle Group Visualization"); + } + } +#endif + + /* effectors */ + ListBase *effectors = pdInitEffectors(scene, ob, psys, part->effector_weights, false); + + if (effectors) { + for (EffectorCache *eff = (EffectorCache *)effectors->first; eff; eff = eff->next) { + if (eff->psys) { + // XXX: DAG_RL_DATA_DATA | DAG_RL_OB_DATA + ComponentKey eff_key(&eff->ob->id, DEPSNODE_TYPE_GEOMETRY); // xxx: particles instead? + add_relation(eff_key, psys_key, DEPSREL_TYPE_STANDARD, "Particle Field"); + } + } + } + + pdEndEffectors(&effectors); + + /* boids */ + if (part->boids) { + BoidRule *rule = NULL; + BoidState *state = NULL; + + for (state = (BoidState *)part->boids->states.first; state; state = state->next) { + for (rule = (BoidRule *)state->rules.first; rule; rule = rule->next) { + Object *ruleob = NULL; + if (rule->type == eBoidRuleType_Avoid) + ruleob = ((BoidRuleGoalAvoid *)rule)->ob; + else if (rule->type == eBoidRuleType_FollowLeader) + ruleob = ((BoidRuleFollowLeader *)rule)->ob; + + if (ruleob) { + ComponentKey ruleob_key(&ruleob->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(ruleob_key, psys_key, DEPSREL_TYPE_TRANSFORM, "Boid Rule"); + } + } + } + } + } + + /* pointcache */ + // TODO... +} + +/* IK Solver Eval Steps */ +void DepsgraphRelationBuilder::build_ik_pose(Object *ob, + bPoseChannel *pchan, + bConstraint *con, + RootPChanMap *root_map) +{ + bKinematicConstraint *data = (bKinematicConstraint *)con->data; + + /* attach owner to IK Solver too + * - assume that owner is always part of chain + * - see notes on direction of rel below... + */ + bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data); + OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER); + + /* IK target */ + // XXX: this should get handled as part of the constraint code + if (data->tar != NULL) { + /* TODO(sergey): For until we'll store partial matricies in the depsgraph, + * we create dependency between target object and pose eval component. + * + * This way we ensuring the whole subtree is updated from scratch without + * need of intermediate matricies. This is an overkill, but good enough for + * testing IK solver. + */ + // FIXME: geometry targets... + ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE); + if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) { + /* TODO(sergey): This is only for until granular update stores intermediate result. */ + if (data->tar != ob) { + /* different armature - can just read the results */ + ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget); + add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name); + } + else { + /* same armature - we'll use the ready state only, just in case this bone is in the chain we're solving */ + OperationKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget, DEG_OPCODE_BONE_DONE); + add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name); + } + } + else if (ELEM(data->tar->type, OB_MESH, OB_LATTICE) && (data->subtarget[0])) { + /* vertex group target */ + /* NOTE: for now, we don't need to represent vertex groups separately... */ + ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name); + + if (data->tar->type == OB_MESH) { + //node2->customdata_mask |= CD_MASK_MDEFORMVERT; + } + } + else { + /* Standard Object Target */ + ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name); + } + + if ((data->tar == ob) && (data->subtarget[0])) { + /* Prevent target's constraints from linking to anything from same + * chain that it controls. + */ + root_map->add_bone(data->subtarget, rootchan->name); + } + } + + /* Pole Target */ + // XXX: this should get handled as part of the constraint code + if (data->poletar != NULL) { + if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) { + // XXX: same armature issues - ready vs done? + ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_BONE, data->subtarget); + add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name); + } + else if (ELEM(data->poletar->type, OB_MESH, OB_LATTICE) && (data->subtarget[0])) { + /* vertex group target */ + /* NOTE: for now, we don't need to represent vertex groups separately... */ + ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name); + + if (data->poletar->type == OB_MESH) { + //node2->customdata_mask |= CD_MASK_MDEFORMVERT; + } + } + else { + ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name); + } + } + + DEG_DEBUG_PRINTF("\nStarting IK Build: pchan = %s, target = (%s, %s), segcount = %d\n", + pchan->name, data->tar->id.name, data->subtarget, data->rootbone); + + bPoseChannel *parchan = pchan; + /* exclude tip from chain? */ + if (!(data->flag & CONSTRAINT_IK_TIP)) { + OperationKey tip_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, + parchan->name, DEG_OPCODE_BONE_LOCAL); + add_relation(solver_key, tip_transforms_key, + DEPSREL_TYPE_TRANSFORM, "IK Solver Result"); + parchan = pchan->parent; + } + + root_map->add_bone(parchan->name, rootchan->name); + + OperationKey parchan_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, + parchan->name, DEG_OPCODE_BONE_READY); + add_relation(parchan_transforms_key, solver_key, + DEPSREL_TYPE_TRANSFORM, "IK Solver Owner"); + + /* Walk to the chain's root */ + //size_t segcount = 0; + int segcount = 0; + + while (parchan) { + /* Make IK-solver dependent on this bone's result, + * since it can only run after the standard results + * of the bone are know. Validate links step on the + * bone will ensure that users of this bone only + * grab the result with IK solver results... + */ + if (parchan != pchan) { + OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY); + add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Parent"); + + OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); + add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result"); + } + parchan->flag |= POSE_DONE; + + OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); + add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "IK Solver Result"); + + root_map->add_bone(parchan->name, rootchan->name); + + /* continue up chain, until we reach target number of items... */ + DEG_DEBUG_PRINTF(" %d = %s\n", segcount, parchan->name); + segcount++; + if ((segcount == data->rootbone) || (segcount > 255)) break; /* 255 is weak */ + + parchan = parchan->parent; + } + + OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); + add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link"); +} + +/* Spline IK Eval Steps */ +void DepsgraphRelationBuilder::build_splineik_pose(Object *ob, + bPoseChannel *pchan, + bConstraint *con, + RootPChanMap *root_map) +{ + bSplineIKConstraint *data = (bSplineIKConstraint *)con->data; + bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data); + OperationKey transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); + OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER); + + /* attach owner to IK Solver too + * - assume that owner is always part of chain + * - see notes on direction of rel below... + */ + add_relation(transforms_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Owner"); + + /* attach path dependency to solver */ + if (data->tar) { + /* TODO(sergey): For until we'll store partial matricies in the depsgraph, + * we create dependency between target object and pose eval component. + * See IK pose for a bit more information. + */ + // TODO: the bigggest point here is that we need the curve PATH and not just the general geometry... + ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY); + ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE); + add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM,"[Curve.Path -> Spline IK] DepsRel"); + } + + pchan->flag |= POSE_DONE; + OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); + add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Result"); + + root_map->add_bone(pchan->name, rootchan->name); + + /* Walk to the chain's root */ + //size_t segcount = 0; + int segcount = 0; + + for (bPoseChannel *parchan = pchan->parent; parchan; parchan = parchan->parent) { + /* Make Spline IK solver dependent on this bone's result, + * since it can only run after the standard results + * of the bone are know. Validate links step on the + * bone will ensure that users of this bone only + * grab the result with IK solver results... + */ + if (parchan != pchan) { + OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY); + add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Update"); + + OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); + add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result"); + } + parchan->flag |= POSE_DONE; + + OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); + add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Result"); + + root_map->add_bone(parchan->name, rootchan->name); + + /* continue up chain, until we reach target number of items... */ + segcount++; + if ((segcount == data->chainlen) || (segcount > 255)) break; /* 255 is weak */ + } + + OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); + add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link"); +} + +/* Pose/Armature Bones Graph */ +void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob) +{ + /* Armature-Data */ + // TODO: selection status? + + /* attach links between pose operations */ + OperationKey init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT); + OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); + + add_relation(init_key, flush_key, DEPSREL_TYPE_COMPONENT_ORDER, "[Pose Init -> Pose Cleanup]"); + + if (ob->adt && (ob->adt->action || ob->adt->nla_tracks.first)) { + ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION); + add_relation(animation_key, init_key, DEPSREL_TYPE_OPERATION, "Rig Animation"); + } + + /* IK Solvers... + * - These require separate processing steps are pose-level + * to be executed between chains of bones (i.e. once the + * base transforms of a bunch of bones is done) + * + * - We build relations for these before the dependencies + * between ops in the same component as it is necessary + * to check whether such bones are in the same IK chain + * (or else we get weird issues with either in-chain + * references, or with bones being parented to IK'd bones) + * + * Unsolved Issues: + * - Care is needed to ensure that multi-headed trees work out the same as in ik-tree building + * - Animated chain-lengths are a problem... + */ + RootPChanMap root_map; + bool pose_depends_on_local_transform = false; + for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) { + for (bConstraint *con = (bConstraint *)pchan->constraints.first; con; con = con->next) { + switch (con->type) { + case CONSTRAINT_TYPE_KINEMATIC: + build_ik_pose(ob, pchan, con, &root_map); + pose_depends_on_local_transform = true; + break; + + case CONSTRAINT_TYPE_SPLINEIK: + build_splineik_pose(ob, pchan, con, &root_map); + pose_depends_on_local_transform = true; + break; + + /* Constraints which needs world's matrix for transform. + * TODO(sergey): More constraints here? + */ + case CONSTRAINT_TYPE_ROTLIKE: + case CONSTRAINT_TYPE_SIZELIKE: + case CONSTRAINT_TYPE_LOCLIKE: + case CONSTRAINT_TYPE_TRANSLIKE: + /* TODO(sergey): Add used space check. */ + pose_depends_on_local_transform = true; + break; + + default: + break; + } + } + } + //root_map.print_debug(); + + if (pose_depends_on_local_transform) { + /* TODO(sergey): Once partial updates are possible use relation between + * object transform and solver itself in it's build function. + */ + ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE); + ComponentKey local_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(local_transform_key, pose_key, DEPSREL_TYPE_TRANSFORM, "Local Transforms"); + } + + + /* links between operations for each bone */ + for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) { + OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); + OperationKey bone_pose_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT); + OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); + OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); + + pchan->flag &= ~POSE_DONE; + + /* pose init to bone local */ + add_relation(init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "PoseEval Source-Bone Link"); + + /* local to pose parenting operation */ + add_relation(bone_local_key, bone_pose_key, DEPSREL_TYPE_OPERATION, "Bone Local - PoseSpace Link"); + + /* parent relation */ + if (pchan->parent != NULL) { + eDepsOperation_Code parent_key_opcode; + + /* NOTE: this difference in handling allows us to prevent lockups while ensuring correct poses for separate chains */ + if (root_map.has_common_root(pchan->name, pchan->parent->name)) { + parent_key_opcode = DEG_OPCODE_BONE_READY; + } + else { + parent_key_opcode = DEG_OPCODE_BONE_DONE; + } + + OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->parent->name, parent_key_opcode); + add_relation(parent_key, bone_pose_key, DEPSREL_TYPE_TRANSFORM, "[Parent Bone -> Child Bone]"); + } + + /* constraints */ + if (pchan->constraints.first != NULL) { + /* constraints stack and constraint dependencies */ + build_constraints(scene, &ob->id, DEPSNODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map); + + /* pose -> constraints */ + OperationKey constraints_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS); + add_relation(bone_pose_key, constraints_key, DEPSREL_TYPE_OPERATION, "Constraints Stack"); + + /* constraints -> ready */ + // TODO: when constraint stack is exploded, this step should occur before the first IK solver + add_relation(constraints_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Constraints -> Ready"); + } + else { + /* pose -> ready */ + add_relation(bone_pose_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Pose -> Ready"); + } + + /* bone ready -> done + * NOTE: For bones without IK, this is all that's needed. + * For IK chains however, an additional rel is created from IK to done, + * with transitive reduction removing this one... + */ + add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done"); + + /* assume that all bones must be done for the pose to be ready (for deformers) */ + add_relation(bone_done_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link"); + } +} + +void DepsgraphRelationBuilder::build_proxy_rig(Object *ob) +{ + OperationKey pose_init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT); + OperationKey pose_done_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); + for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; + pchan != NULL; + pchan = pchan->next) + { + OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); + OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); + OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); + add_relation(pose_init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "Pose Init -> Bone Local"); + add_relation(bone_local_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Local -> Ready"); + add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done"); + add_relation(bone_done_key, pose_done_key, DEPSREL_TYPE_OPERATION, "Bone Done -> Pose Done"); + } +} + +/* Shapekeys */ +void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key) +{ + ComponentKey obdata_key(obdata, DEPSNODE_TYPE_GEOMETRY); + + /* attach animdata to geometry */ + build_animdata(&key->id); + + if (key->adt) { + // TODO: this should really be handled in build_animdata, since many of these cases will need it + if (key->adt->action || key->adt->nla_tracks.first) { + ComponentKey adt_key(&key->id, DEPSNODE_TYPE_ANIMATION); + add_relation(adt_key, obdata_key, DEPSREL_TYPE_OPERATION, "Animation"); + } + + /* NOTE: individual shapekey drivers are handled above already */ + } + + /* attach to geometry */ + // XXX: aren't shapekeys now done as a pseudo-modifier on object? + //ComponentKey key_key(&key->id, DEPSNODE_TYPE_GEOMETRY); // FIXME: this doesn't exist + //add_relation(key_key, obdata_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Shapekeys"); +} + +/** + * ObData Geometry Evaluation + * ========================== + * + * The evaluation of geometry on objects is as follows: + * - The actual evaluated of the derived geometry (e.g. DerivedMesh, DispList, etc.) + * occurs in the Geometry component of the object which references this. This includes + * modifiers, and the temporary "ubereval" for geometry. + * - Therefore, each user of a piece of shared geometry data ends up evaluating its own + * version of the stuff, complete with whatever modifiers it may use. + * + * - The datablocks for the geometry data - "obdata" (e.g. ID_ME, ID_CU, ID_LT, etc.) are used for + * 1) calculating the bounding boxes of the geometry data, + * 2) aggregating inward links from other objects (e.g. for text on curve, etc.) + * and also for the links coming from the shapekey datablocks + * - Animation/Drivers affecting the parameters of the geometry are made to trigger + * updates on the obdata geometry component, which then trigger downstream + * re-evaluation of the individual instances of this geometry. + */ +// TODO: Materials and lighting should probably get their own component, instead of being lumped under geometry? +void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Object *ob) +{ + ID *obdata = (ID *)ob->data; + + /* Init operation of object-level geometry evaluation. */ + OperationKey geom_init_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Init"); + + /* get nodes for result of obdata's evaluation, and geometry evaluation on object */ + ComponentKey obdata_geom_key(obdata, DEPSNODE_TYPE_GEOMETRY); + ComponentKey geom_key(&ob->id, DEPSNODE_TYPE_GEOMETRY); + + /* link components to each other */ + add_relation(obdata_geom_key, geom_key, DEPSREL_TYPE_DATABLOCK, "Object Geometry Base Data"); + + /* Modifiers */ + if (ob->modifiers.first) { + ModifierData *md; + OperationKey prev_mod_key; + + for (md = (ModifierData *)ob->modifiers.first; md; md = md->next) { + const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type); + OperationKey mod_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_MODIFIER, md->name); + + if (md->prev) { + /* Stack relation: modifier depends on previous modifier in the stack */ + add_relation(prev_mod_key, mod_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Modifier Stack"); + } + else { + /* Stack relation: first modifier depends on the geometry. */ + add_relation(geom_init_key, mod_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Modifier Stack"); + } + + if (mti->updateDepsgraph) { + DepsNodeHandle handle = create_node_handle(mod_key); + mti->updateDepsgraph(md, bmain, scene, ob, &handle); + } + + if (BKE_object_modifier_use_time(ob, md)) { + TimeSourceKey time_src_key; + add_relation(time_src_key, mod_key, DEPSREL_TYPE_TIME, "Time Source"); + } + + prev_mod_key = mod_key; + } + } + + /* materials */ + if (ob->totcol) { + int a; + + for (a = 1; a <= ob->totcol; a++) { + Material *ma = give_current_material(ob, a); + + if (ma) + build_material(&ob->id, ma); + } + } + + /* geometry collision */ + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_LATTICE)) { + // add geometry collider relations + } + + /* Make sure uber update is the last in the dependencies. + * + * TODO(sergey): Get rid of this node. + */ + if (ob->type != OB_ARMATURE) { + /* Armatures does no longer require uber node. */ + OperationKey obdata_ubereval_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL); + if (ob->modifiers.last) { + ModifierData *md = (ModifierData *)ob->modifiers.last; + OperationKey mod_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_MODIFIER, md->name); + add_relation(mod_key, obdata_ubereval_key, DEPSREL_TYPE_OPERATION, "Object Geometry UberEval"); + } + else { + add_relation(geom_init_key, obdata_ubereval_key, DEPSREL_TYPE_OPERATION, "Object Geometry UberEval"); + } + } + + if (obdata->flag & LIB_DOIT) { + return; + } + obdata->flag |= LIB_DOIT; + + /* Link object data evaluation node to exit operation. */ + OperationKey obdata_geom_eval_key(obdata, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Geometry Eval"); + OperationKey obdata_geom_done_key(obdata, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Done"); + add_relation(obdata_geom_eval_key, obdata_geom_done_key, DEPSREL_TYPE_DATABLOCK, "ObData Geom Eval Done"); + + /* type-specific node/links */ + switch (ob->type) { + case OB_MESH: + break; + + case OB_MBALL: + { + Object *mom = BKE_mball_basis_find(scene, ob); + + /* motherball - mom depends on children! */ + if (mom != ob) { + /* non-motherball -> cannot be directly evaluated! */ + ComponentKey mom_key(&mom->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(geom_key, mom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Metaball Motherball"); + } + } + break; + + case OB_CURVE: + case OB_FONT: + { + Curve *cu = (Curve *)obdata; + + /* curve's dependencies */ + // XXX: these needs geom data, but where is geom stored? + if (cu->bevobj) { + ComponentKey bevob_key(&cu->bevobj->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(bevob_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Curve Bevel"); + } + if (cu->taperobj) { + ComponentKey taperob_key(&cu->taperobj->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(taperob_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Curve Taper"); + } + if (ob->type == OB_FONT) { + if (cu->textoncurve) { + ComponentKey textoncurve_key(&cu->taperobj->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(textoncurve_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Text on Curve"); + } + } + } + break; + + case OB_SURF: /* Nurbs Surface */ + { + } + break; + + case OB_LATTICE: /* Lattice */ + { + } + break; + } + + /* ShapeKeys */ + Key *key = BKE_key_from_object(ob); + if (key) { + build_shapekeys(obdata, key); + } + + if (needs_animdata_node(obdata)) { + ComponentKey animation_key(obdata, DEPSNODE_TYPE_ANIMATION); + ComponentKey parameters_key(obdata, DEPSNODE_TYPE_PARAMETERS); + add_relation(animation_key, parameters_key, + DEPSREL_TYPE_COMPONENT_ORDER, "Geom Parameters"); + } +} + +/* Cameras */ +// TODO: Link scene-camera links in somehow... +void DepsgraphRelationBuilder::build_camera(Object *ob) +{ + Camera *cam = (Camera *)ob->data; + ID *camera_id = &cam->id; + if (camera_id->flag & LIB_DOIT) { + return; + } + camera_id->flag |= LIB_DOIT; + + ComponentKey parameters_key(camera_id, DEPSNODE_TYPE_PARAMETERS); + + if (needs_animdata_node(camera_id)) { + ComponentKey animation_key(camera_id, DEPSNODE_TYPE_ANIMATION); + add_relation(animation_key, parameters_key, + DEPSREL_TYPE_COMPONENT_ORDER, "Camera Parameters"); + } + + /* DOF */ + if (cam->dof_ob) { + ComponentKey ob_param_key(&ob->id, DEPSNODE_TYPE_PARAMETERS); + ComponentKey dof_ob_key(&cam->dof_ob->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(dof_ob_key, ob_param_key, DEPSREL_TYPE_TRANSFORM, "Camera DOF"); + } +} + +/* Lamps */ +void DepsgraphRelationBuilder::build_lamp(Object *ob) +{ + Lamp *la = (Lamp *)ob->data; + ID *lamp_id = &la->id; + if (lamp_id->flag & LIB_DOIT) { + return; + } + lamp_id->flag |= LIB_DOIT; + + ComponentKey parameters_key(lamp_id, DEPSNODE_TYPE_PARAMETERS); + + if (needs_animdata_node(lamp_id)) { + ComponentKey animation_key(lamp_id, DEPSNODE_TYPE_ANIMATION); + add_relation(animation_key, parameters_key, + DEPSREL_TYPE_COMPONENT_ORDER, "Lamp Parameters"); + } + + /* lamp's nodetree */ + if (la->nodetree) { + build_nodetree(lamp_id, la->nodetree); + ComponentKey nodetree_key(&la->nodetree->id, DEPSNODE_TYPE_PARAMETERS); + add_relation(nodetree_key, parameters_key, + DEPSREL_TYPE_COMPONENT_ORDER, "NTree->Lamp Parameters"); + } + + /* textures */ + build_texture_stack(lamp_id, la->mtex); +} + +void DepsgraphRelationBuilder::build_nodetree(ID *owner, bNodeTree *ntree) +{ + if (!ntree) + return; + + ID *ntree_id = &ntree->id; + + build_animdata(ntree_id); + + /* nodetree's nodes... */ + for (bNode *bnode = (bNode *)ntree->nodes.first; bnode; bnode = bnode->next) { + if (bnode->id) { + if (GS(bnode->id->name) == ID_MA) { + build_material(owner, (Material *)bnode->id); + } + else if (bnode->type == ID_TE) { + build_texture(owner, (Tex *)bnode->id); + } + else if (bnode->type == NODE_GROUP) { + bNodeTree *ntree = (bNodeTree *)bnode->id; + if ((ntree_id->flag & LIB_DOIT) == 0) { + build_nodetree(owner, ntree); + ntree_id->flag |= LIB_DOIT; + } + } + } + } + + if (needs_animdata_node(ntree_id)) { + ComponentKey parameters_key(ntree_id, DEPSNODE_TYPE_PARAMETERS); + ComponentKey animation_key(ntree_id, DEPSNODE_TYPE_ANIMATION); + add_relation(animation_key, parameters_key, + DEPSREL_TYPE_COMPONENT_ORDER, "NTree Parameters"); + } + + // TODO: link from nodetree to owner_component? +} + +/* Recursively build graph for material */ +void DepsgraphRelationBuilder::build_material(ID *owner, Material *ma) +{ + ID *ma_id = &ma->id; + if (ma_id->flag & LIB_DOIT) { + return; + } + ma_id->flag |= LIB_DOIT; + + /* animation */ + build_animdata(ma_id); + + /* textures */ + build_texture_stack(owner, ma->mtex); + + /* material's nodetree */ + build_nodetree(owner, ma->nodetree); +} + +/* Recursively build graph for texture */ +void DepsgraphRelationBuilder::build_texture(ID *owner, Tex *tex) +{ + ID *tex_id = &tex->id; + if (tex_id->flag & LIB_DOIT) { + return; + } + tex_id->flag |= LIB_DOIT; + + /* texture itself */ + build_animdata(tex_id); + + /* texture's nodetree */ + build_nodetree(owner, tex->nodetree); +} + +/* Texture-stack attached to some shading datablock */ +void DepsgraphRelationBuilder::build_texture_stack(ID *owner, MTex **texture_stack) +{ + int i; + + /* for now assume that all texture-stacks have same number of max items */ + for (i = 0; i < MAX_MTEX; i++) { + MTex *mtex = texture_stack[i]; + if (mtex && mtex->tex) + build_texture(owner, mtex->tex); + } +} + +void DepsgraphRelationBuilder::build_compositor(Scene *scene) +{ + /* For now, just a plain wrapper? */ + build_nodetree(&scene->id, scene->nodetree); +} + +void DepsgraphRelationBuilder::build_gpencil(ID *UNUSED(owner), bGPdata *gpd) +{ + /* animation */ + build_animdata(&gpd->id); + + // TODO: parent object (when that feature is implemented) +} + +bool DepsgraphRelationBuilder::needs_animdata_node(ID *id) +{ + AnimData *adt = BKE_animdata_from_id(id); + if (adt != NULL) { + return adt->action != NULL; + } + return false; +} + diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc new file mode 100644 index 00000000000..c876640b462 --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph_debug.cc @@ -0,0 +1,1187 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2014 Blender Foundation. + * All rights reserved. + * + * Original Author: Lukas Toenne + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + * + * Implementation of tools for debugging the depsgraph + */ + +//#include +#include + +extern "C" { +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_ghash.h" +#include "BLI_string.h" + +#include "DNA_scene_types.h" +#include "DNA_userdef_types.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_debug.h" +#include "DEG_depsgraph_build.h" + +#include "WM_api.h" +#include "WM_types.h" +} /* extern "C" */ + +#include "depsgraph_debug.h" +#include "depsnode.h" +#include "depsnode_component.h" +#include "depsnode_operation.h" +#include "depsgraph_intern.h" + +/* ****************** */ +/* Graphviz Debugging */ + +static SpinLock lock; + +#define NL "\r\n" + +/* Only one should be enabled, defines whether graphviz nodes + * get colored by individual types or classes. + */ +#define COLOR_SCHEME_NODE_CLASS 1 +//#define COLOR_SCHEME_NODE_TYPE 2 + +static const char *deg_debug_graphviz_fontname = "helvetica"; +static float deg_debug_graphviz_graph_label_size = 20.0f; +static float deg_debug_graphviz_node_label_size = 14.0f; +static const int deg_debug_max_colors = 12; +#if 0 +static const char *deg_debug_colors_dark[] = { + "#6e8997", "#144f77", "#76945b", + "#216a1d", "#a76665", "#971112", + "#a87f49", "#0a9540", "#86768e", + "#462866", "#a9a965", "#753b1a", +}; +#endif +#ifdef COLOR_SCHEME_NODE_TYPE +static const char *deg_debug_colors[] = { + "#a6cee3", "#1f78b4", "#b2df8a", + "#33a02c", "#fb9a99", "#e31a1c", + "#fdbf6f", "#ff7f00", "#cab2d6", + "#6a3d9a", "#ffff99", "#b15928", +}; +#endif +static const char *deg_debug_colors_light[] = { + "#8dd3c7", "#ffffb3", "#bebada", + "#fb8072", "#80b1d3", "#fdb462", + "#b3de69", "#fccde5", "#d9d9d9", + "#bc80bd", "#ccebc5", "#ffed6f", +}; + +#ifdef COLOR_SCHEME_NODE_TYPE +static const int deg_debug_node_type_color_map[][2] = { + {DEPSNODE_TYPE_ROOT, 0}, + {DEPSNODE_TYPE_TIMESOURCE, 1}, + {DEPSNODE_TYPE_ID_REF, 2}, + {DEPSNODE_TYPE_SUBGRAPH, 3}, + + /* Outer Types */ + {DEPSNODE_TYPE_PARAMETERS, 4}, + {DEPSNODE_TYPE_PROXY, 5}, + {DEPSNODE_TYPE_ANIMATION, 6}, + {DEPSNODE_TYPE_TRANSFORM, 7}, + {DEPSNODE_TYPE_GEOMETRY, 8}, + {DEPSNODE_TYPE_SEQUENCER, 9}, + {DEPSNODE_TYPE_SHADING, 10}, + {-1, 0} +}; +#endif + +#if 0 /* unused */ +static const int deg_debug_relation_type_color_map[][2] = { + {DEPSREL_TYPE_STANDARD, 0}, + {DEPSREL_TYPE_ROOT_TO_ACTIVE, 1}, + {DEPSREL_TYPE_DATABLOCK, 2}, + {DEPSREL_TYPE_TIME, 3}, + {DEPSREL_TYPE_COMPONENT_ORDER, 4}, + {DEPSREL_TYPE_OPERATION, 5}, + {DEPSREL_TYPE_DRIVER, 6}, + {DEPSREL_TYPE_DRIVER_TARGET, 7}, + {DEPSREL_TYPE_TRANSFORM, 8}, + {DEPSREL_TYPE_GEOMETRY_EVAL, 9}, + {DEPSREL_TYPE_UPDATE, 10}, + {DEPSREL_TYPE_UPDATE_UI, 11}, + {-1, 0} +}; +#endif + +static int deg_debug_node_color_index(const DepsNode *node) +{ +#ifdef COLOR_SCHEME_NODE_CLASS + /* Some special types. */ + switch (node->type) { + case DEPSNODE_TYPE_ID_REF: + return 5; + case DEPSNODE_TYPE_OPERATION: + { + OperationDepsNode *op_node = (OperationDepsNode *)node; + if (op_node->is_noop()) + return 8; + } + + default: + break; + } + /* Do others based on class. */ + switch (node->tclass) { + case DEPSNODE_CLASS_OPERATION: + return 4; + case DEPSNODE_CLASS_COMPONENT: + return 1; + default: + return 9; + } +#endif + +#ifdef COLOR_SCHEME_NODE_TYPE + const int (*pair)[2]; + for (pair = deg_debug_node_type_color_map; (*pair)[0] >= 0; ++pair) { + if ((*pair)[0] == node->type) { + return (*pair)[1]; + } + } + return -1; +#endif +} + +struct DebugContext { + FILE *file; + bool show_tags; + bool show_eval_priority; +}; + +static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...) ATTR_PRINTF_FORMAT(2, 3); +static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vfprintf(ctx.file, fmt, args); + va_end(args); +} + +static void deg_debug_graphviz_legend_color(const DebugContext &ctx, + const char *name, + const char *color) +{ + deg_debug_fprintf(ctx, ""); + deg_debug_fprintf(ctx, "%s", name); + deg_debug_fprintf(ctx, "", color); + deg_debug_fprintf(ctx, "" NL); +} + +#if 0 +static void deg_debug_graphviz_legend_line(const DebugContext &ctx, + const char *name, + const char *color, + const char *style) +{ + /* XXX TODO */ + deg_debug_fprintf(ctx, "" NL); +} + +static void deg_debug_graphviz_legend_cluster(const DebugContext &ctx, + const char *name, + const char *color, + const char *style) +{ + deg_debug_fprintf(ctx, ""); + deg_debug_fprintf(ctx, "%s", name); + deg_debug_fprintf(ctx, ""); + deg_debug_fprintf(ctx, "", color); + deg_debug_fprintf(ctx, "
"); + deg_debug_fprintf(ctx, "" NL); +} +#endif + +static void deg_debug_graphviz_legend(const DebugContext &ctx) +{ + deg_debug_fprintf(ctx, "{" NL); + deg_debug_fprintf(ctx, "rank = sink;" NL); + deg_debug_fprintf(ctx, "Legend [shape=none, margin=0, label=<" NL); + deg_debug_fprintf(ctx, " " NL); + deg_debug_fprintf(ctx, "" NL); + +#ifdef COLOR_SCHEME_NODE_CLASS + const char **colors = deg_debug_colors_light; + deg_debug_graphviz_legend_color(ctx, "Operation", colors[4]); + deg_debug_graphviz_legend_color(ctx, "Component", colors[1]); + deg_debug_graphviz_legend_color(ctx, "ID Node", colors[5]); + deg_debug_graphviz_legend_color(ctx, "NOOP", colors[8]); +#endif + +#ifdef COLOR_SCHEME_NODE_TYPE + const int (*pair)[2]; + for (pair = deg_debug_node_type_color_map; (*pair)[0] >= 0; ++pair) { + DepsNodeFactory *nti = DEG_get_node_factory((eDepsNode_Type)(*pair)[0]); + deg_debug_graphviz_legend_color(ctx, + nti->tname().c_str(), + deg_debug_colors_light[(*pair)[1] % deg_debug_max_colors]); + } +#endif + + deg_debug_fprintf(ctx, "
Legend
" NL); + deg_debug_fprintf(ctx, ">" NL); + deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname); + deg_debug_fprintf(ctx, "];" NL); + deg_debug_fprintf(ctx, "}" NL); +} + +#if 0 /* unused */ +static int deg_debug_relation_type_color_index(eDepsRelation_Type type) +{ + const int (*pair)[2]; + for (pair = deg_debug_relation_type_color_map; (*pair)[0] >= 0; ++pair) { + if ((*pair)[0] == type) { + return (*pair)[1]; + } + } + return -1; +} +#endif + +static void deg_debug_graphviz_node_color(const DebugContext &ctx, + const DepsNode *node) +{ + const char *color_default = "black"; + const char *color_modified = "orangered4"; + const char *color_update = "dodgerblue3"; + const char *color = color_default; + if (ctx.show_tags) { + if (node->tclass == DEPSNODE_CLASS_OPERATION) { + OperationDepsNode *op_node = (OperationDepsNode *)node; + if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) { + color = color_modified; + } + else if (op_node->flag & DEPSOP_FLAG_NEEDS_UPDATE) { + color = color_update; + } + } + } + deg_debug_fprintf(ctx, "\"%s\"", color); +} + +static void deg_debug_graphviz_node_penwidth(const DebugContext &ctx, + const DepsNode *node) +{ + float penwidth_default = 1.0f; + float penwidth_modified = 4.0f; + float penwidth_update = 4.0f; + float penwidth = penwidth_default; + if (ctx.show_tags) { + if (node->tclass == DEPSNODE_CLASS_OPERATION) { + OperationDepsNode *op_node = (OperationDepsNode *)node; + if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) { + penwidth = penwidth_modified; + } + else if (op_node->flag & DEPSOP_FLAG_NEEDS_UPDATE) { + penwidth = penwidth_update; + } + } + } + deg_debug_fprintf(ctx, "\"%f\"", penwidth); +} + +static void deg_debug_graphviz_node_fillcolor(const DebugContext &ctx, + const DepsNode *node) +{ + const char *defaultcolor = "gainsboro"; + int color_index = deg_debug_node_color_index(node); + const char *fillcolor = color_index < 0 ? defaultcolor : deg_debug_colors_light[color_index % deg_debug_max_colors]; + deg_debug_fprintf(ctx, "\"%s\"", fillcolor); +} + +#if 0 /* implementation using stripes, a bit too noisy ... */ +static void deg_debug_graphviz_node_fillcolor(const DebugContext &ctx, + const DepsNode *node) +{ + const char *defaultcolor = "gainsboro"; + const char *color_needs_update = "orange"; + const int num_stripes = 10; + int color_index = deg_debug_node_color_index(node); + const char *base_color = color_index < 0 ? defaultcolor : deg_debug_colors_light[color_index % deg_debug_max_colors]; + if (ctx.show_tags && + (node->flag & (DEPSNODE_FLAG_DIRECTLY_MODIFIED | DEPSNODE_FLAG_NEEDS_UPDATE))) { + deg_debug_fprintf(ctx, "\""); + for (int i = 0; i < num_stripes; ++i) { + if (i > 0) { + deg_debug_fprintf(ctx, ":"); + } + deg_debug_fprintf(ctx, "%s:%s", base_color, color_needs_update); + } + deg_debug_fprintf(ctx, "\""); + } + else { + deg_debug_fprintf(ctx, "\"%s\"", base_color); + } +} +#endif + +static void deg_debug_graphviz_relation_color(const DebugContext &ctx, + const DepsRelation *UNUSED(rel)) +{ + const char *defaultcolor = "black"; +#if 0 /* disabled for now, edge colors are hardly distinguishable */ + int color = deg_debug_relation_type_color_index(rel->type); + if (color < 0) { + deg_debug_fprintf(ctx, "%s", defaultcolor); + } + else { + deg_debug_fprintf(ctx, "\"%s\"", deg_debug_colors_dark[color % deg_debug_max_colors]); + } +#else + deg_debug_fprintf(ctx, "%s", defaultcolor); +#endif +} + +static void deg_debug_graphviz_node_style(const DebugContext &ctx, const DepsNode *node) +{ + const char *base_style = "filled"; /* default style */ + if (ctx.show_tags) { + if (node->tclass == DEPSNODE_CLASS_OPERATION) { + OperationDepsNode *op_node = (OperationDepsNode *)node; + if (op_node->flag & (DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE)) { + base_style = "striped"; + } + } + } + switch (node->tclass) { + case DEPSNODE_CLASS_GENERIC: + deg_debug_fprintf(ctx, "\"%s\"", base_style); + break; + case DEPSNODE_CLASS_COMPONENT: + deg_debug_fprintf(ctx, "\"%s\"", base_style); + break; + case DEPSNODE_CLASS_OPERATION: + deg_debug_fprintf(ctx, "\"%s,rounded\"", base_style); + break; + } +} + +static void deg_debug_graphviz_node_single(const DebugContext &ctx, + const DepsNode *node) +{ + const char *shape = "box"; + string name = node->identifier(); + float priority = -1.0f; + if (node->type == DEPSNODE_TYPE_ID_REF) { + IDDepsNode *id_node = (IDDepsNode *)node; + char buf[256]; + BLI_snprintf(buf, sizeof(buf), " (Layers: %d)", id_node->layers); + name += buf; + } + if (ctx.show_eval_priority && node->tclass == DEPSNODE_CLASS_OPERATION) { + priority = ((OperationDepsNode *)node)->eval_priority; + } + deg_debug_fprintf(ctx, "// %s\n", name.c_str()); + deg_debug_fprintf(ctx, "\"node_%p\"", node); + deg_debug_fprintf(ctx, "["); +// deg_debug_fprintf(ctx, "label=<%s>", name); + if (priority >= 0.0f) { + deg_debug_fprintf(ctx, "label=<%s
(%.2f)>", + name.c_str(), + priority); + } + else { + deg_debug_fprintf(ctx, "label=<%s>", name.c_str()); + } + deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname); + deg_debug_fprintf(ctx, ",fontsize=%f", deg_debug_graphviz_node_label_size); + deg_debug_fprintf(ctx, ",shape=%s", shape); + deg_debug_fprintf(ctx, ",style="); deg_debug_graphviz_node_style(ctx, node); + deg_debug_fprintf(ctx, ",color="); deg_debug_graphviz_node_color(ctx, node); + deg_debug_fprintf(ctx, ",fillcolor="); deg_debug_graphviz_node_fillcolor(ctx, node); + deg_debug_fprintf(ctx, ",penwidth="); deg_debug_graphviz_node_penwidth(ctx, node); + deg_debug_fprintf(ctx, "];" NL); + deg_debug_fprintf(ctx, NL); +} + +static void deg_debug_graphviz_node_cluster_begin(const DebugContext &ctx, + const DepsNode *node) +{ + string name = node->identifier().c_str(); + if (node->type == DEPSNODE_TYPE_ID_REF) { + IDDepsNode *id_node = (IDDepsNode *)node; + char buf[256]; + BLI_snprintf(buf, sizeof(buf), " (Layers: %d)", id_node->layers); + name += buf; + } + deg_debug_fprintf(ctx, "// %s\n", name.c_str()); + deg_debug_fprintf(ctx, "subgraph \"cluster_%p\" {" NL, node); +// deg_debug_fprintf(ctx, "label=<%s>;" NL, name); + deg_debug_fprintf(ctx, "label=<%s>;" NL, name.c_str()); + deg_debug_fprintf(ctx, "fontname=\"%s\";" NL, deg_debug_graphviz_fontname); + deg_debug_fprintf(ctx, "fontsize=%f;" NL, deg_debug_graphviz_node_label_size); + deg_debug_fprintf(ctx, "style="); deg_debug_graphviz_node_style(ctx, node); deg_debug_fprintf(ctx, ";" NL); + deg_debug_fprintf(ctx, "color="); deg_debug_graphviz_node_color(ctx, node); deg_debug_fprintf(ctx, ";" NL); + deg_debug_fprintf(ctx, "fillcolor="); deg_debug_graphviz_node_fillcolor(ctx, node); deg_debug_fprintf(ctx, ";" NL); + deg_debug_fprintf(ctx, "penwidth="); deg_debug_graphviz_node_penwidth(ctx, node); deg_debug_fprintf(ctx, ";" NL); + /* dummy node, so we can add edges between clusters */ + deg_debug_fprintf(ctx, "\"node_%p\"", node); + deg_debug_fprintf(ctx, "["); + deg_debug_fprintf(ctx, "shape=%s", "point"); + deg_debug_fprintf(ctx, ",style=%s", "invis"); + deg_debug_fprintf(ctx, "];" NL); + deg_debug_fprintf(ctx, NL); +} + +static void deg_debug_graphviz_node_cluster_end(const DebugContext &ctx) +{ + deg_debug_fprintf(ctx, "}" NL); + deg_debug_fprintf(ctx, NL); +} + +static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx, + const Depsgraph *graph); +static void deg_debug_graphviz_graph_relations(const DebugContext &ctx, + const Depsgraph *graph); + +static void deg_debug_graphviz_node(const DebugContext &ctx, + const DepsNode *node) +{ + switch (node->type) { + case DEPSNODE_TYPE_ID_REF: + { + const IDDepsNode *id_node = (const IDDepsNode *)node; + if (id_node->components.empty()) { + deg_debug_graphviz_node_single(ctx, node); + } + else { + deg_debug_graphviz_node_cluster_begin(ctx, node); + for (IDDepsNode::ComponentMap::const_iterator it = id_node->components.begin(); + it != id_node->components.end(); + ++it) + { + const ComponentDepsNode *comp = it->second; + deg_debug_graphviz_node(ctx, comp); + } + deg_debug_graphviz_node_cluster_end(ctx); + } + break; + } + case DEPSNODE_TYPE_SUBGRAPH: + { + SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node; + if (sub_node->graph) { + deg_debug_graphviz_node_cluster_begin(ctx, node); + deg_debug_graphviz_graph_nodes(ctx, sub_node->graph); + deg_debug_graphviz_node_cluster_end(ctx); + } + else { + deg_debug_graphviz_node_single(ctx, node); + } + break; + } + case DEPSNODE_TYPE_PARAMETERS: + case DEPSNODE_TYPE_ANIMATION: + case DEPSNODE_TYPE_TRANSFORM: + case DEPSNODE_TYPE_PROXY: + case DEPSNODE_TYPE_GEOMETRY: + case DEPSNODE_TYPE_SEQUENCER: + case DEPSNODE_TYPE_EVAL_POSE: + case DEPSNODE_TYPE_BONE: + case DEPSNODE_TYPE_SHADING: + { + ComponentDepsNode *comp_node = (ComponentDepsNode *)node; + if (!comp_node->operations.empty()) { + deg_debug_graphviz_node_cluster_begin(ctx, node); + for (ComponentDepsNode::OperationMap::const_iterator it = comp_node->operations.begin(); + it != comp_node->operations.end(); + ++it) + { + const DepsNode *op_node = it->second; + deg_debug_graphviz_node(ctx, op_node); + } + deg_debug_graphviz_node_cluster_end(ctx); + } + else { + deg_debug_graphviz_node_single(ctx, node); + } + break; + } + default: + deg_debug_graphviz_node_single(ctx, node); + break; + } +} + +static bool deg_debug_graphviz_is_cluster(const DepsNode *node) +{ + switch (node->type) { + case DEPSNODE_TYPE_ID_REF: + { + const IDDepsNode *id_node = (const IDDepsNode *)node; + return !id_node->components.empty(); + } + case DEPSNODE_TYPE_SUBGRAPH: + { + SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node; + return sub_node->graph != NULL; + } + case DEPSNODE_TYPE_PARAMETERS: + case DEPSNODE_TYPE_ANIMATION: + case DEPSNODE_TYPE_TRANSFORM: + case DEPSNODE_TYPE_PROXY: + case DEPSNODE_TYPE_GEOMETRY: + case DEPSNODE_TYPE_SEQUENCER: + case DEPSNODE_TYPE_EVAL_POSE: + case DEPSNODE_TYPE_BONE: + { + ComponentDepsNode *comp_node = (ComponentDepsNode *)node; + return !comp_node->operations.empty(); + } + default: + return false; + } +} + +static bool deg_debug_graphviz_is_owner(const DepsNode *node, + const DepsNode *other) +{ + switch (node->tclass) { + case DEPSNODE_CLASS_COMPONENT: + { + ComponentDepsNode *comp_node = (ComponentDepsNode *)node; + if (comp_node->owner == other) + return true; + break; + } + case DEPSNODE_CLASS_OPERATION: + { + OperationDepsNode *op_node = (OperationDepsNode *)node; + if (op_node->owner == other) + return true; + else if (op_node->owner->owner == other) + return true; + break; + } + default: break; + } + return false; +} + +static void deg_debug_graphviz_node_relations(const DebugContext &ctx, + const DepsNode *node) +{ + DEPSNODE_RELATIONS_ITER_BEGIN(node->inlinks, rel) + { + const DepsNode *tail = rel->to; /* same as node */ + const DepsNode *head = rel->from; + deg_debug_fprintf(ctx, "// %s -> %s\n", + head->identifier().c_str(), + tail->identifier().c_str()); + deg_debug_fprintf(ctx, "\"node_%p\"", head); + deg_debug_fprintf(ctx, " -> "); + deg_debug_fprintf(ctx, "\"node_%p\"", tail); + + deg_debug_fprintf(ctx, "["); + deg_debug_fprintf(ctx, "label=\"%s\"", rel->name); + deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname); + deg_debug_fprintf(ctx, ",color="); deg_debug_graphviz_relation_color(ctx, rel); + /* NOTE: edge from node to own cluster is not possible and gives graphviz + * warning, avoid this here by just linking directly to the invisible + * placeholder node + */ + if (deg_debug_graphviz_is_cluster(tail) && !deg_debug_graphviz_is_owner(head, tail)) { + deg_debug_fprintf(ctx, ",ltail=\"cluster_%p\"", tail); + } + if (deg_debug_graphviz_is_cluster(head) && !deg_debug_graphviz_is_owner(tail, head)) { + deg_debug_fprintf(ctx, ",lhead=\"cluster_%p\"", head); + } + deg_debug_fprintf(ctx, "];" NL); + deg_debug_fprintf(ctx, NL); + } + DEPSNODE_RELATIONS_ITER_END; + +#if 0 + if (node->tclass == DEPSNODE_CLASS_COMPONENT) { + const ComponentDepsNode *comp_node = (const ComponentDepsNode *)node; + for (ComponentDepsNode::OperationMap::const_iterator it = comp_node->operations.begin(); + it != comp_node->operations.end(); + ++it) + { + OperationDepsNode *op_node = it->second; + deg_debug_graphviz_node_relations(ctx, op_node); + } + } + else if (node->type == DEPSNODE_TYPE_ID_REF) { + const IDDepsNode *id_node = (const IDDepsNode *)node; + for (IDDepsNode::ComponentMap::const_iterator it = id_node->components.begin(); + it != id_node->components.end(); + ++it) + { + const ComponentDepsNode *comp = it->second; + deg_debug_graphviz_node_relations(ctx, comp); + } + } + else if (node->type == DEPSNODE_TYPE_SUBGRAPH) { + SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node; + if (sub_node->graph) { + deg_debug_graphviz_graph_relations(ctx, sub_node->graph); + } + } +#endif +} + +static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx, + const Depsgraph *graph) +{ + if (graph->root_node) { + deg_debug_graphviz_node(ctx, graph->root_node); + } + for (Depsgraph::IDNodeMap::const_iterator it = graph->id_hash.begin(); + it != graph->id_hash.end(); + ++it) + { + DepsNode *node = it->second; + deg_debug_graphviz_node(ctx, node); + } + TimeSourceDepsNode *time_source = graph->find_time_source(NULL); + if (time_source != NULL) { + deg_debug_graphviz_node(ctx, time_source); + } +} + +static void deg_debug_graphviz_graph_relations(const DebugContext &ctx, + const Depsgraph *graph) +{ +#if 0 + if (graph->root_node) { + deg_debug_graphviz_node_relations(ctx, graph->root_node); + } + for (Depsgraph::IDNodeMap::const_iterator it = graph->id_hash.begin(); + it != graph->id_hash.end(); + ++it) + { + DepsNode *id_node = it->second; + deg_debug_graphviz_node_relations(ctx, id_node); + } +#else + /* XXX not in use yet */ +// for (Depsgraph::OperationNodes::const_iterator it = graph->all_opnodes.begin(); +// it != graph->all_opnodes.end(); +// ++it) +// { +// OperationDepsNode *op_node = *it; +// deg_debug_graphviz_node_relations(ctx, op_node); +// } + for (Depsgraph::IDNodeMap::const_iterator it = graph->id_hash.begin(); + it != graph->id_hash.end(); + ++it) + { + IDDepsNode *id_node = it->second; + for (IDDepsNode::ComponentMap::const_iterator it = id_node->components.begin(); + it != id_node->components.end(); + ++it) + { + ComponentDepsNode *comp_node = it->second; + for (ComponentDepsNode::OperationMap::const_iterator it = comp_node->operations.begin(); + it != comp_node->operations.end(); + ++it) + { + OperationDepsNode *op_node = it->second; + deg_debug_graphviz_node_relations(ctx, op_node); + } + } + } + + TimeSourceDepsNode *time_source = graph->find_time_source(NULL); + if (time_source != NULL) { + deg_debug_graphviz_node_relations(ctx, time_source); + } +#endif +} + +void DEG_debug_graphviz(const Depsgraph *graph, FILE *f, const char *label, bool show_eval) +{ +#if 0 /* generate shaded color set */ + static char colors[][3] = {{0xa6, 0xce, 0xe3},{0x1f, 0x78, 0xb4},{0xb2, 0xdf, 0x8a},{0x33, 0xa0, 0x2c}, + {0xfb, 0x9a, 0x99},{0xe3, 0x1a, 0x1c},{0xfd, 0xbf, 0x6f},{0xff, 0x7f, 0x00}, + {0xca, 0xb2, 0xd6},{0x6a, 0x3d, 0x9a},{0xff, 0xff, 0x99},{0xb1, 0x59, 0x28}}; + int i; + const float factor = 0.666f; + for (i=0; i < 12; ++i) + printf("\"#%x%x%x\"\n", (char)(colors[i][0] * factor), (char)(colors[i][1] * factor), (char)(colors[i][2] * factor)); +#endif + + if (!graph) { + return; + } + + DebugContext ctx; + ctx.file = f; + ctx.show_tags = show_eval; + ctx.show_eval_priority = show_eval; + + deg_debug_fprintf(ctx, "digraph depgraph {" NL); + deg_debug_fprintf(ctx, "rankdir=LR;" NL); + deg_debug_fprintf(ctx, "graph ["); + deg_debug_fprintf(ctx, "compound=true"); + deg_debug_fprintf(ctx, ",labelloc=\"t\""); + deg_debug_fprintf(ctx, ",fontsize=%f", deg_debug_graphviz_graph_label_size); + deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname); + deg_debug_fprintf(ctx, ",label=\"%s\"", label); + deg_debug_fprintf(ctx, ",splines=ortho"); + deg_debug_fprintf(ctx, ",overlap=scalexy"); // XXX: only when using neato + deg_debug_fprintf(ctx, "];" NL); + + deg_debug_graphviz_graph_nodes(ctx, graph); + deg_debug_graphviz_graph_relations(ctx, graph); + + deg_debug_graphviz_legend(ctx); + + deg_debug_fprintf(ctx, "}" NL); +} + +#undef NL + +/* ************************************************ */ + +static string get_component_name(eDepsNode_Type type, const string &name = "") +{ + DepsNodeFactory *factory = DEG_get_node_factory(type); + if (name.empty()) { + return string(factory->tname()); + } + else { + return string(factory->tname()) + " | " + name; + } +} + +static void times_clear(DepsgraphStatsTimes ×) +{ + times.duration_last = 0.0f; +} + +static void times_add(DepsgraphStatsTimes ×, float time) +{ + times.duration_last += time; +} + +void DepsgraphDebug::eval_begin(const EvaluationContext *UNUSED(eval_ctx)) +{ + /* TODO(sergey): Stats are currently globally disabled. */ + /* verify_stats(); */ + reset_stats(); +} + +void DepsgraphDebug::eval_end(const EvaluationContext *UNUSED(eval_ctx)) +{ + WM_main_add_notifier(NC_SPACE | ND_SPACE_INFO_REPORT, NULL); +} + +void DepsgraphDebug::eval_step(const EvaluationContext *UNUSED(eval_ctx), + const char *message) +{ +#ifdef DEG_DEBUG_BUILD + if (deg_debug_eval_cb) + deg_debug_eval_cb(deg_debug_eval_userdata, message); +#else + (void)message; /* Ignored. */ +#endif +} + +void DepsgraphDebug::task_started(Depsgraph *graph, + const OperationDepsNode *node) +{ + if (stats) { + BLI_spin_lock(&graph->lock); + + ComponentDepsNode *comp = node->owner; + ID *id = comp->owner->id; + + DepsgraphStatsID *id_stats = get_id_stats(id, true); + times_clear(id_stats->times); + + /* XXX TODO use something like: if (id->flag & ID_DEG_DETAILS) {...} */ + if (0) { + /* XXX component name usage needs cleanup! currently mixes identifier and description strings! */ + DepsgraphStatsComponent *comp_stats = get_component_stats(id, get_component_name(comp->type, comp->name), true); + times_clear(comp_stats->times); + } + + BLI_spin_unlock(&graph->lock); + } +} + +void DepsgraphDebug::task_completed(Depsgraph *graph, + const OperationDepsNode *node, + double time) +{ + if (stats) { + BLI_spin_lock(&graph->lock); + + ComponentDepsNode *comp = node->owner; + ID *id = comp->owner->id; + + DepsgraphStatsID *id_stats = get_id_stats(id, true); + times_add(id_stats->times, time); + + /* XXX TODO use something like: if (id->flag & ID_DEG_DETAILS) {...} */ + if (0) { + /* XXX component name usage needs cleanup! currently mixes identifier and description strings! */ + DepsgraphStatsComponent *comp_stats = get_component_stats(id, get_component_name(comp->type, comp->name), true); + times_add(comp_stats->times, time); + } + + BLI_spin_unlock(&graph->lock); + } +} + +/* ********** */ +/* Statistics */ + +DepsgraphStats *DepsgraphDebug::stats = NULL; + +/* GHash callback */ +static void deg_id_stats_free(void *val) +{ + DepsgraphStatsID *id_stats = (DepsgraphStatsID *)val; + + if (id_stats) { + BLI_freelistN(&id_stats->components); + MEM_freeN(id_stats); + } +} + +void DepsgraphDebug::stats_init() +{ + if (!stats) { + stats = (DepsgraphStats *)MEM_callocN(sizeof(DepsgraphStats), "Depsgraph Stats"); + stats->id_stats = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "Depsgraph ID Stats Hash"); + } +} + +void DepsgraphDebug::stats_free() +{ + if (stats) { + BLI_ghash_free(stats->id_stats, NULL, deg_id_stats_free); + MEM_freeN(stats); + stats = NULL; + } +} + +void DepsgraphDebug::verify_stats() +{ + stats_init(); +} + +void DepsgraphDebug::reset_stats() +{ + if (!stats) { + return; + } + + /* XXX this doesn't work, will immediately clear all info, + * since most depsgraph updates have none or very few updates to handle. + * + * Could consider clearing only zero-user ID blocks here + */ +// BLI_ghash_clear(stats->id_stats, NULL, deg_id_stats_free); +} + +DepsgraphStatsID *DepsgraphDebug::get_id_stats(ID *id, bool create) +{ + DepsgraphStatsID *id_stats = (DepsgraphStatsID *)BLI_ghash_lookup(stats->id_stats, id); + + if (!id_stats && create) { + id_stats = (DepsgraphStatsID *)MEM_callocN(sizeof(DepsgraphStatsID), "Depsgraph ID Stats"); + id_stats->id = id; + + BLI_ghash_insert(stats->id_stats, id, id_stats); + } + + return id_stats; +} + +DepsgraphStatsComponent *DepsgraphDebug::get_component_stats(DepsgraphStatsID *id_stats, + const string &name, + bool create) +{ + DepsgraphStatsComponent *comp_stats; + for (comp_stats = (DepsgraphStatsComponent *)id_stats->components.first; + comp_stats != NULL; + comp_stats = comp_stats->next) { + if (STREQ(comp_stats->name, name.c_str())) + break; + } + if (!comp_stats && create) { + comp_stats = (DepsgraphStatsComponent *)MEM_callocN(sizeof(DepsgraphStatsComponent), "Depsgraph Component Stats"); + BLI_strncpy(comp_stats->name, name.c_str(), sizeof(comp_stats->name)); + BLI_addtail(&id_stats->components, comp_stats); + } + return comp_stats; +} + +/* ------------------------------------------------ */ + +DepsgraphStats *DEG_stats(void) +{ + return DepsgraphDebug::stats; +} + +void DEG_stats_verify() +{ + DepsgraphDebug::verify_stats(); +} + +DepsgraphStatsID *DEG_stats_id(ID *id) +{ + if (!DepsgraphDebug::stats) { + return NULL; + } + return DepsgraphDebug::get_id_stats(id, false); +} + +bool DEG_debug_compare(const struct Depsgraph *graph1, + const struct Depsgraph *graph2) +{ + BLI_assert(graph1 != NULL); + BLI_assert(graph2 != NULL); + if (graph1->operations.size() != graph2->operations.size()) { + return false; + } + /* TODO(sergey): Currently we only do real stupid check, + * which is fast but which isn't 100% reliable. + * + * Would be cool to make it more robust, but it's good enough + * for now. Also, proper graph check is actually NP-complex + * problem.. + */ + return true; +} + +bool DEG_debug_scene_relations_validate(Main *bmain, + Scene *scene) +{ + Depsgraph *depsgraph = DEG_graph_new(); + bool valid = true; + DEG_graph_build_from_scene(depsgraph, bmain, scene); + if (!DEG_debug_compare(depsgraph, scene->depsgraph)) { + fprintf(stderr, "ERROR! Depsgraph wasn't tagged for update when it should have!\n"); + BLI_assert(!"This should not happen!"); + valid = false; + } + DEG_graph_free(depsgraph); + return valid; +} + +bool DEG_debug_consistency_check(Depsgraph *graph) +{ + /* Validate links exists in both directions. */ + for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin(); + it_op != graph->operations.end(); + ++it_op) + { + OperationDepsNode *node = *it_op; + for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin(); + it_rel != node->outlinks.end(); + ++it_rel) + { + DepsRelation *rel = *it_rel; + + int counter1 = 0; + for (OperationDepsNode::Relations::const_iterator tmp_rel = node->outlinks.begin(); + tmp_rel != node->outlinks.end(); + ++tmp_rel) + { + if (*tmp_rel == rel) { + ++counter1; + } + } + + int counter2 = 0; + for (OperationDepsNode::Relations::const_iterator tmp_rel = rel->to->inlinks.begin(); + tmp_rel != rel->to->inlinks.end(); + ++tmp_rel) + { + if (*tmp_rel == rel) { + ++counter2; + } + } + + if (counter1 != counter2) { + printf("Relation exists in outgoing direction but not in incoming (%d vs. %d).\n", + counter1, counter2); + return false; + } + } + } + + for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin(); + it_op != graph->operations.end(); + ++it_op) + { + OperationDepsNode *node = *it_op; + for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin(); + it_rel != node->inlinks.end(); + ++it_rel) + { + DepsRelation *rel = *it_rel; + + int counter1 = 0; + for (OperationDepsNode::Relations::const_iterator tmp_rel = node->inlinks.begin(); + tmp_rel != node->inlinks.end(); + ++tmp_rel) + { + if (*tmp_rel == rel) { + ++counter1; + } + } + + int counter2 = 0; + for (OperationDepsNode::Relations::const_iterator tmp_rel = rel->from->outlinks.begin(); + tmp_rel != rel->from->outlinks.end(); + ++tmp_rel) + { + if (*tmp_rel == rel) { + ++counter2; + } + } + + if (counter1 != counter2) { + printf("Relation exists in incoming direction but not in outcoming (%d vs. %d).\n", + counter1, counter2); + } + } + } + + /* Validate node valency calculated in both directions. */ + for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin(); + it_op != graph->operations.end(); + ++it_op) + { + OperationDepsNode *node = *it_op; + node->num_links_pending = 0; + node->done = 0; + } + + for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin(); + it_op != graph->operations.end(); + ++it_op) + { + OperationDepsNode *node = *it_op; + if (node->done) { + printf("Node %s is twice in the operations!\n", + node->identifier().c_str()); + return false; + } + for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin(); + it_rel != node->outlinks.end(); + ++it_rel) + { + DepsRelation *rel = *it_rel; + if (rel->to->type == DEPSNODE_TYPE_OPERATION) { + OperationDepsNode *to = (OperationDepsNode *)rel->to; + BLI_assert(to->num_links_pending < to->inlinks.size()); + ++to->num_links_pending; + } + } + node->done = 1; + } + + for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin(); + it_op != graph->operations.end(); + ++it_op) + { + OperationDepsNode *node = *it_op; + int num_links_pending = 0; + for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin(); + it_rel != node->inlinks.end(); + ++it_rel) + { + DepsRelation *rel = *it_rel; + if (rel->from->type == DEPSNODE_TYPE_OPERATION) { + ++num_links_pending; + } + } + if (node->num_links_pending != num_links_pending) { + printf("Valency mismatch: %s, %u != %d\n", + node->identifier().c_str(), + node->num_links_pending, num_links_pending); + printf("Number of inlinks: %d\n", (int)node->inlinks.size()); + return false; + } + } + return true; +} + +/* ------------------------------------------------ */ + +/** + * Obtain simple statistics about the complexity of the depsgraph + * \param[out] r_outer The number of outer nodes in the graph + * \param[out] r_operations The number of operation nodes in the graph + * \param[out] r_relations The number of relations between (executable) nodes in the graph + */ +void DEG_stats_simple(const Depsgraph *graph, size_t *r_outer, + size_t *r_operations, size_t *r_relations) +{ + /* number of operations */ + if (r_operations) { + /* All operations should be in this list, allowing us to count the total + * number of nodes. + */ + *r_operations = graph->operations.size(); + } + + /* Count number of outer nodes and/or relations between these. */ + if (r_outer || r_relations) { + size_t tot_outer = 0; + size_t tot_rels = 0; + + for (Depsgraph::IDNodeMap::const_iterator it = graph->id_hash.begin(); + it != graph->id_hash.end(); + ++it) + { + IDDepsNode *id_node = it->second; + tot_outer++; + for (IDDepsNode::ComponentMap::const_iterator it = id_node->components.begin(); + it != id_node->components.end(); + ++it) + { + ComponentDepsNode *comp_node = it->second; + tot_outer++; + for (ComponentDepsNode::OperationMap::const_iterator it = comp_node->operations.begin(); + it != comp_node->operations.end(); + ++it) + { + OperationDepsNode *op_node = it->second; + tot_rels += op_node->inlinks.size(); + } + } + } + + TimeSourceDepsNode *time_source = graph->find_time_source(NULL); + if (time_source != NULL) { + tot_rels += time_source->inlinks.size(); + } + + if (r_relations) *r_relations = tot_rels; + if (r_outer) *r_outer = tot_outer; + } +} + diff --git a/source/blender/depsgraph/intern/depsgraph_debug.h b/source/blender/depsgraph/intern/depsgraph_debug.h new file mode 100644 index 00000000000..aed36f6add6 --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph_debug.h @@ -0,0 +1,83 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __DEPSGRAPH_DEBUG_H__ +#define __DEPSGRAPH_DEBUG_H__ + +#include "depsgraph_types.h" + +extern "C" { +#include "BKE_global.h" +} + +struct DepsgraphStats; +struct DepsgraphStatsID; +struct DepsgraphStatsComponent; +struct DepsgraphSettings; +struct EvaluationContext; +struct OperationDepsNode; + +struct Depsgraph; + +struct DepsgraphDebug { + static DepsgraphStats *stats; + + static void stats_init(); + static void stats_free(); + + static void verify_stats(); + static void reset_stats(); + + static void eval_begin(const EvaluationContext *eval_ctx); + static void eval_end(const EvaluationContext *eval_ctx); + static void eval_step(const EvaluationContext *eval_ctx, + const char *message); + + static void task_started(Depsgraph *graph, const OperationDepsNode *node); + static void task_completed(Depsgraph *graph, + const OperationDepsNode *node, + double time); + + static DepsgraphStatsID *get_id_stats(ID *id, bool create); + static DepsgraphStatsComponent *get_component_stats(DepsgraphStatsID *id_stats, + const string &name, + bool create); + static DepsgraphStatsComponent *get_component_stats(ID *id, + const string &name, + bool create) + { + return get_component_stats(get_id_stats(id, create), name, create); + } +}; + +#define DEG_DEBUG_PRINTF(...) \ + { \ + if (G.debug & G_DEBUG_DEPSGRAPH) { \ + fprintf(stderr, __VA_ARGS__); \ + } \ + } \ + +#endif /* __DEPSGRAPH_DEBUG_H__ */ diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc new file mode 100644 index 00000000000..11fd02376a3 --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph_eval.cc @@ -0,0 +1,386 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + * + * Evaluation engine entrypoints for Depsgraph Engine + */ + +#include "MEM_guardedalloc.h" + +#include "PIL_time.h" + +extern "C" { +#include "BLI_utildefines.h" +#include "BLI_task.h" + +#include "BKE_depsgraph.h" +#include "BKE_scene.h" + +#include "DEG_depsgraph.h" +} /* extern "C" */ + +#include "atomic_ops.h" + +#include "depsgraph.h" +#include "depsnode.h" +#include "depsnode_component.h" +#include "depsnode_operation.h" +#include "depsgraph_debug.h" + +#ifdef WITH_LEGACY_DEPSGRAPH +static bool use_legacy_depsgraph = true; +#endif + +bool DEG_depsgraph_use_legacy(void) +{ +#ifdef DISABLE_NEW_DEPSGRAPH + return true; +#elif defined(WITH_LEGACY_DEPSGRAPH) + return use_legacy_depsgraph; +#else + BLI_assert(!"Should not be used with new depsgraph"); + return false; +#endif +} + +void DEG_depsgraph_switch_to_legacy(void) +{ +#ifdef WITH_LEGACY_DEPSGRAPH + use_legacy_depsgraph = true; +#else + BLI_assert(!"Should not be used with new depsgraph"); +#endif +} + +void DEG_depsgraph_switch_to_new(void) +{ +#ifdef WITH_LEGACY_DEPSGRAPH + use_legacy_depsgraph = false; +#else + BLI_assert(!"Should not be used with new depsgraph"); +#endif +} + +/* ****************** */ +/* Evaluation Context */ + +/* Create new evaluation context. */ +EvaluationContext *DEG_evaluation_context_new(int mode) +{ + EvaluationContext *eval_ctx = + (EvaluationContext *)MEM_callocN(sizeof(EvaluationContext), + "EvaluationContext"); + eval_ctx->mode = mode; + return eval_ctx; +} + +/** + * Initialize evaluation context. + * Used by the areas which currently overrides the context or doesn't have + * access to a proper one. + */ +void DEG_evaluation_context_init(EvaluationContext *eval_ctx, int mode) +{ + eval_ctx->mode = mode; +} + +/* Free evaluation context. */ +void DEG_evaluation_context_free(EvaluationContext *eval_ctx) +{ + MEM_freeN(eval_ctx); +} + +/* ********************** */ +/* Evaluation Entrypoints */ + +/* Forward declarations. */ +static void schedule_children(TaskPool *pool, + Depsgraph *graph, + OperationDepsNode *node, + const int layers); + +struct DepsgraphEvalState { + EvaluationContext *eval_ctx; + Depsgraph *graph; + int layers; +}; + +static void deg_task_run_func(TaskPool *pool, + void *taskdata, + int UNUSED(threadid)) +{ + DepsgraphEvalState *state = (DepsgraphEvalState *)BLI_task_pool_userdata(pool); + OperationDepsNode *node = (OperationDepsNode *)taskdata; + + if (!node->is_noop()) { + /* Get context. */ + // TODO: who initialises this? "Init" operations aren't able to initialise it!!! + /* TODO(sergey): Wedon't use component contexts at this moment. */ + /* ComponentDepsNode *comp = node->owner; */ + BLI_assert(node->owner != NULL); + + /* Take note of current time. */ + double start_time = PIL_check_seconds_timer(); + DepsgraphDebug::task_started(state->graph, node); + + /* Should only be the case for NOOPs, which never get to this point. */ + BLI_assert(node->evaluate); + + /* Perform operation. */ + node->evaluate(state->eval_ctx); + + /* Note how long this took. */ + double end_time = PIL_check_seconds_timer(); + DepsgraphDebug::task_completed(state->graph, + node, + end_time - start_time); + } + + schedule_children(pool, state->graph, node, state->layers); +} + +static void calculate_pending_parents(Depsgraph *graph, int layers) +{ + for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin(); + it_op != graph->operations.end(); + ++it_op) + { + OperationDepsNode *node = *it_op; + IDDepsNode *id_node = node->owner->owner; + + node->num_links_pending = 0; + node->scheduled = false; + + /* count number of inputs that need updates */ + if ((id_node->layers & layers) != 0 && + (node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0) + { + for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin(); + it_rel != node->inlinks.end(); + ++it_rel) + { + DepsRelation *rel = *it_rel; + if (rel->from->type == DEPSNODE_TYPE_OPERATION && + (rel->flag & DEPSREL_FLAG_CYCLIC) == 0) + { + OperationDepsNode *from = (OperationDepsNode *)rel->from; + IDDepsNode *id_from_node = from->owner->owner; + if ((id_from_node->layers & layers) != 0 && + (from->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0) + { + ++node->num_links_pending; + } + } + } + } + } +} + +static void calculate_eval_priority(OperationDepsNode *node) +{ + if (node->done) { + return; + } + node->done = 1; + + if (node->flag & DEPSOP_FLAG_NEEDS_UPDATE) { + /* XXX standard cost of a node, could be estimated somewhat later on */ + const float cost = 1.0f; + /* NOOP nodes have no cost */ + node->eval_priority = node->is_noop() ? cost : 0.0f; + + for (OperationDepsNode::Relations::const_iterator it = node->outlinks.begin(); + it != node->outlinks.end(); + ++it) + { + DepsRelation *rel = *it; + OperationDepsNode *to = (OperationDepsNode *)rel->to; + BLI_assert(to->type == DEPSNODE_TYPE_OPERATION); + calculate_eval_priority(to); + node->eval_priority += to->eval_priority; + } + } + else { + node->eval_priority = 0.0f; + } +} + +static void schedule_graph(TaskPool *pool, + Depsgraph *graph, + const int layers) +{ + BLI_spin_lock(&graph->lock); + for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin(); + it != graph->operations.end(); + ++it) + { + OperationDepsNode *node = *it; + IDDepsNode *id_node = node->owner->owner; + if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) && + node->num_links_pending == 0 && + (id_node->layers & layers) != 0) + { + BLI_task_pool_push(pool, deg_task_run_func, node, false, TASK_PRIORITY_LOW); + node->scheduled = true; + } + } + BLI_spin_unlock(&graph->lock); +} + +static void schedule_children(TaskPool *pool, + Depsgraph *graph, + OperationDepsNode *node, + const int layers) +{ + for (OperationDepsNode::Relations::const_iterator it = node->outlinks.begin(); + it != node->outlinks.end(); + ++it) + { + DepsRelation *rel = *it; + OperationDepsNode *child = (OperationDepsNode *)rel->to; + BLI_assert(child->type == DEPSNODE_TYPE_OPERATION); + + if (child->scheduled) { + /* Happens when having cyclic dependencies. */ + continue; + } + + IDDepsNode *id_child = child->owner->owner; + if ((id_child->layers & layers) != 0 && + (child->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0) + { + if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) { + BLI_assert(child->num_links_pending > 0); + atomic_sub_uint32(&child->num_links_pending, 1); + } + + if (child->num_links_pending == 0) { + BLI_spin_lock(&graph->lock); + bool need_schedule = !child->scheduled; + child->scheduled = true; + BLI_spin_unlock(&graph->lock); + + if (need_schedule) { + BLI_task_pool_push(pool, deg_task_run_func, child, false, TASK_PRIORITY_LOW); + } + } + } + } +} + +/** + * Evaluate all nodes tagged for updating, + * \warning This is usually done as part of main loop, but may also be + * called from frame-change update. + * + * \note Time sources should be all valid! + */ +void DEG_evaluate_on_refresh_ex(EvaluationContext *eval_ctx, + Depsgraph *graph, + const int layers) +{ + /* Generate base evaluation context, upon which all the others are derived. */ + // TODO: this needs both main and scene access... + + /* Nothing to update, early out. */ + if (graph->entry_tags.size() == 0) { + return; + } + + /* Set time for the current graph evaluation context. */ + TimeSourceDepsNode *time_src = graph->find_time_source(); + eval_ctx->ctime = time_src->cfra; + + /* XXX could use a separate pool for each eval context */ + DepsgraphEvalState state; + state.eval_ctx = eval_ctx; + state.graph = graph; + state.layers = layers; + + TaskScheduler *task_scheduler = BLI_task_scheduler_get(); + TaskPool *task_pool = BLI_task_pool_create(task_scheduler, &state); + + calculate_pending_parents(graph, layers); + + /* Clear tags. */ + for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin(); + it != graph->operations.end(); + ++it) + { + OperationDepsNode *node = *it; + node->done = 0; + } + + /* Calculate priority for operation nodes. */ + for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin(); + it != graph->operations.end(); + ++it) + { + OperationDepsNode *node = *it; + calculate_eval_priority(node); + } + + DepsgraphDebug::eval_begin(eval_ctx); + + schedule_graph(task_pool, graph, layers); + + BLI_task_pool_work_and_wait(task_pool); + BLI_task_pool_free(task_pool); + + DepsgraphDebug::eval_end(eval_ctx); + + /* Clear any uncleared tags - just in case. */ + DEG_graph_clear_tags(graph); +} + +/* Evaluate all nodes tagged for updating. */ +void DEG_evaluate_on_refresh(EvaluationContext *eval_ctx, + Depsgraph *graph, + Scene *scene) +{ + /* Update time on primary timesource. */ + TimeSourceDepsNode *tsrc = graph->find_time_source(); + tsrc->cfra = BKE_scene_frame_get(scene);; + + DEG_evaluate_on_refresh_ex(eval_ctx, graph, graph->layers); +} + +/* Frame-change happened for root scene that graph belongs to. */ +void DEG_evaluate_on_framechange(EvaluationContext *eval_ctx, + Main *bmain, + Depsgraph *graph, + float ctime, + const int layers) +{ + /* Update time on primary timesource. */ + TimeSourceDepsNode *tsrc = graph->find_time_source(); + tsrc->cfra = ctime; + + tsrc->tag_update(graph); + + DEG_graph_flush_updates(bmain, graph); + + /* Perform recalculation updates. */ + DEG_evaluate_on_refresh_ex(eval_ctx, graph, layers); +} diff --git a/source/blender/depsgraph/intern/depsgraph_intern.h b/source/blender/depsgraph/intern/depsgraph_intern.h new file mode 100644 index 00000000000..70d452bf221 --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph_intern.h @@ -0,0 +1,164 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + * + * API's for internal use in the Depsgraph + * - Also, defines for "Node Type Info" + */ + +#ifndef __DEPSGRAPH_INTERN_H__ +#define __DEPSGRAPH_INTERN_H__ + +#include + +#include "MEM_guardedalloc.h" + +#include "depsgraph.h" +#include "depsnode.h" + +struct Main; +struct Group; +struct Scene; + +/* Graph Building ======================================================== */ + +/** + * Build depsgraph for the given group, and dump results in given graph container + * This is usually used for building subgraphs for groups to use... + */ +void DEG_graph_build_from_group(Depsgraph *graph, struct Main *bmain, struct Group *group); + +/* Build subgraph for group */ +DepsNode *DEG_graph_build_group_subgraph(Depsgraph *graph_main, struct Main *bmain, struct Group *group); + +/* Graph Copying ========================================================= */ +/* (Part of the Filtering API) */ + +/** + * Depsgraph Copying Context (dcc) + * + * Keeps track of node relationships/links/etc. during the copy + * operation so that they can be safely remapped... + */ +typedef struct DepsgraphCopyContext { + struct GHash *nodes_hash; /* mapping from src node to dst node */ + struct GHash *rels_hash; // XXX: same for relationships? + + // XXX: filtering criteria... +} DepsgraphCopyContext; + +/* Internal Filtering API ---------------------------------------------- */ + +/* Create filtering context */ +// XXX: needs params for conditions? +DepsgraphCopyContext *DEG_filter_init(void); + +/* Free filtering context once filtering is done */ +void DEG_filter_cleanup(DepsgraphCopyContext *dcc); + + +/* Data Copy Operations ------------------------------------------------ */ + +/** + * Make a (deep) copy of provided node and it's little subgraph + * \warning Newly created node is not added to the existing graph + * \param dcc: Context info for helping resolve links + */ +DepsNode *DEG_copy_node(DepsgraphCopyContext *dcc, const DepsNode *src); + +/* Node Types Handling ================================================= */ + +/* "Typeinfo" for Node Types ------------------------------------------- */ + +/* Typeinfo Struct (nti) */ +struct DepsNodeFactory { + virtual eDepsNode_Type type() const = 0; + virtual eDepsNode_Class tclass() const = 0; + virtual const char *tname() const = 0; + + virtual DepsNode *create_node(const ID *id, const string &subdata, const string &name) const = 0; + virtual DepsNode *copy_node(DepsgraphCopyContext *dcc, const DepsNode *copy) const = 0; +}; + +template +struct DepsNodeFactoryImpl : public DepsNodeFactory { + eDepsNode_Type type() const { return NodeType::typeinfo.type; } + eDepsNode_Class tclass() const { return NodeType::typeinfo.tclass; } + const char *tname() const { return NodeType::typeinfo.tname; } + + DepsNode *create_node(const ID *id, const string &subdata, const string &name) const + { + DepsNode *node = OBJECT_GUARDED_NEW(NodeType); + + /* populate base node settings */ + node->type = type(); + node->tclass = tclass(); + + if (!name.empty()) + /* set name if provided ... */ + node->name = name; + else + /* ... otherwise use default type name */ + node->name = tname(); + + node->init(id, subdata); + + return node; + } + + virtual DepsNode *copy_node(DepsgraphCopyContext *dcc, const DepsNode *copy) const + { + BLI_assert(copy->type == type()); + DepsNode *node = OBJECT_GUARDED_NEW(NodeType); + + /* populate base node settings */ + node->type = type(); + node->tclass = tclass(); + // XXX: need to review the name here, as we can't have exact duplicates... + node->name = copy->name; + + node->copy(dcc, static_cast(copy)); + + return node; + } +}; + +/* Typeinfo Management -------------------------------------------------- */ + +/* Register typeinfo */ +void DEG_register_node_typeinfo(DepsNodeFactory *factory); + +/* Get typeinfo for specified type */ +DepsNodeFactory *DEG_get_node_factory(const eDepsNode_Type type); + +/* Get typeinfo for provided node */ +DepsNodeFactory *DEG_node_get_factory(const DepsNode *node); + +/* Editors Integration -------------------------------------------------- */ + +void deg_editors_id_update(struct Main *bmain, struct ID *id); + +void deg_editors_scene_update(struct Main *bmain, struct Scene *scene, bool updated); + +#endif /* __DEPSGRAPH_INTERN_H__ */ diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc new file mode 100644 index 00000000000..aa6f5ef3ea1 --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph_query.cc @@ -0,0 +1,213 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + * + * Implementation of Querying and Filtering API's + */ + +#include "MEM_guardedalloc.h" + +extern "C" { +#include "BLI_utildefines.h" +#include "BLI_ghash.h" + +#include "BKE_main.h" + +#include "DEG_depsgraph_query.h" +} /* extern "C" */ + +#include "depsgraph_queue.h" +#include "depsnode.h" +#include "depsnode_operation.h" +#include "depsgraph_intern.h" + +/* ************************* */ +/* Low-Level Graph Traversal */ + +#if 0 +/* Prepare for graph traversal, by tagging nodes, etc. */ +static void DEG_graph_traverse_begin(Depsgraph * /*graph*/) +{ + /* go over all nodes, initialising the valence counts */ + // XXX: this will end up being O(|V|), which is bad when we're just updating a few nodes... +} + +/* Perform a traversal of graph from given starting node (in execution order) */ +// TODO: additional flags for controlling the process? +void DEG_graph_traverse_from_node(Depsgraph *graph, OperationDepsNode *start_node, + DEG_FilterPredicate filter, void *filter_data, + DEG_NodeOperation op, void *operation_data) +{ + DepsgraphQueue *q; + + /* sanity checks */ + if (ELEM(NULL, graph, start_node, op)) + return; + + /* add node as starting node to be evaluated, with value of 0 */ + q = DEG_queue_new(); + + start_node->num_links_pending = 0; + DEG_queue_push(q, start_node, 0.0f); + + /* while we still have nodes in the queue, grab and work on next one */ + do { + /* grab item at front of queue */ + // XXX: in practice, we may need to wait until one becomes available... + OperationDepsNode *node = (OperationDepsNode *)DEG_queue_pop(q); + + /* perform operation on node */ + op(graph, node, operation_data); + + /* schedule up operations which depend on this */ + DEPSNODE_RELATIONS_ITER_BEGIN(node->outlinks, rel) + { + /* ensure that relationship is not tagged for ignoring (i.e. cyclic, etc.) */ + // TODO: cyclic refs should probably all get clustered towards the end, so that we can just stop on the first one + if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) { + OperationDepsNode *child_node = (OperationDepsNode *)rel->to; + + /* only visit node if the filtering function agrees */ + if ((filter == NULL) || filter(graph, child_node, filter_data)) { + /* schedule up node... */ + child_node->num_links_pending--; + DEG_queue_push(q, child_node, (float)child_node->num_links_pending); + } + } + } + DEPSNODE_RELATIONS_ITER_END; + } while (DEG_queue_is_empty(q) == false); + + /* cleanup */ + DEG_queue_free(q); +} +#endif + +/* ************************************************************** */ +/* Filtering API - Basically, making a copy of the existing graph */ + +/* Create filtering context */ +// TODO: allow passing in a number of criteria? +DepsgraphCopyContext *DEG_filter_init() +{ + DepsgraphCopyContext *dcc = (DepsgraphCopyContext *)MEM_callocN(sizeof(DepsgraphCopyContext), "DepsgraphCopyContext"); + + /* init hashes for easy lookups */ + dcc->nodes_hash = BLI_ghash_ptr_new("Depsgraph Filter NodeHash"); + dcc->rels_hash = BLI_ghash_ptr_new("Depsgraph Filter Relationship Hash"); // XXX? + + /* store filtering criteria? */ + // xxx... + + return dcc; +} + +/* Cleanup filtering context */ +void DEG_filter_cleanup(DepsgraphCopyContext *dcc) +{ + /* sanity check */ + if (dcc == NULL) + return; + + /* free hashes - contents are weren't copied, so are ok... */ + BLI_ghash_free(dcc->nodes_hash, NULL, NULL); + BLI_ghash_free(dcc->rels_hash, NULL, NULL); + + /* clear filtering criteria */ + // ... + + /* free dcc itself */ + MEM_freeN(dcc); +} + +/* -------------------------------------------------- */ + +/* Create a copy of provided node */ +// FIXME: the handling of sub-nodes and links will need to be subject to filtering options... +// XXX: perhaps this really shouldn't be exposed, as it will just be a sub-step of the evaluation process? +DepsNode *DEG_copy_node(DepsgraphCopyContext *dcc, const DepsNode *src) +{ + /* sanity check */ + if (src == NULL) + return NULL; + + DepsNodeFactory *factory = DEG_get_node_factory(src->type); + BLI_assert(factory != NULL); + DepsNode *dst = factory->copy_node(dcc, src); + + /* add this node-pair to the hash... */ + BLI_ghash_insert(dcc->nodes_hash, (DepsNode *)src, dst); + +#if 0 /* XXX TODO */ + /* now, fix up any links in standard "node header" (i.e. DepsNode struct, that all + * all others are derived from) that are now corrupt + */ + { + /* relationships to other nodes... */ + // FIXME: how to handle links? We may only have partial set of all nodes still? + // XXX: the exact details of how to handle this are really part of the querying API... + + // XXX: BUT, for copying subgraphs, we'll need to define an API for doing this stuff anyways + // (i.e. for resolving and patching over links that exist within subtree...) + dst->inlinks.clear(); + dst->outlinks.clear(); + + /* clear traversal data */ + dst->num_links_pending = 0; + dst->lasttime = 0; + } + + /* fix links */ + // XXX... +#endif + + /* return copied node */ + return dst; +} + +bool DEG_id_type_tagged(Main *bmain, short idtype) +{ + return bmain->id_tag_update[((unsigned char *)&idtype)[0]] != 0; +} + +short DEG_get_eval_flags_for_id(Depsgraph *graph, ID *id) +{ + if (graph == NULL) { + /* Happens when converting objects to mesh from a python script + * after modifying scene graph. + * + * Currently harmless because it's only called for temporary + * objects which are out of the DAG anyway. + */ + return 0; + } + + IDDepsNode *id_node = graph->find_id_node(id); + if (id_node == NULL) { + /* TODO(sergey): Does it mean we need to check set scene? */ + return 0; + } + + return id_node->eval_flags; +} diff --git a/source/blender/depsgraph/intern/depsgraph_queue.cc b/source/blender/depsgraph/intern/depsgraph_queue.cc new file mode 100644 index 00000000000..45290c50706 --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph_queue.cc @@ -0,0 +1,173 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + * + * Implementation of special queue type for use in Depsgraph traversals + */ + +#include + +#include "MEM_guardedalloc.h" + +extern "C" { +#include "BLI_utildefines.h" +#include "BLI_heap.h" +#include "BLI_ghash.h" +} /* extern "C" */ + +#include "depsgraph_queue.h" + +/* ****************************** */ +/* Depsgraph Queue implementation */ + +/* Data Management ----------------------------------------- */ + +DepsgraphQueue *DEG_queue_new(void) +{ + DepsgraphQueue *q = (DepsgraphQueue *)MEM_callocN(sizeof(DepsgraphQueue), "DEG_queue_new()"); + + /* init data structures for use here */ + q->pending_heap = BLI_heap_new(); + q->pending_hash = BLI_ghash_ptr_new("DEG Queue Pending Hash"); + + q->ready_heap = BLI_heap_new(); + + /* init settings */ + q->idx = 0; + q->tot = 0; + + /* return queue */ + return q; +} + +void DEG_queue_free(DepsgraphQueue *q) +{ + /* free data structures */ + BLI_assert(BLI_heap_size(q->pending_heap) == 0); + BLI_assert(BLI_heap_size(q->ready_heap) == 0); + BLI_assert(BLI_ghash_size(q->pending_hash) == 0); + + BLI_heap_free(q->pending_heap, NULL); + BLI_heap_free(q->ready_heap, NULL); + BLI_ghash_free(q->pending_hash, NULL, NULL); + + /* free queue itself */ + MEM_freeN(q); +} + +/* Statistics --------------------------------------------- */ + +/* Get the number of nodes which are we should visit, but are not able to yet */ +size_t DEG_queue_num_pending(DepsgraphQueue *q) +{ + return BLI_heap_size(q->pending_heap); +} + +/* Get the number of nodes which are now ready to be visited */ +size_t DEG_queue_num_ready(DepsgraphQueue *q) +{ + return BLI_heap_size(q->ready_heap); +} + +/* Get total size of queue */ +size_t DEG_queue_size(DepsgraphQueue *q) +{ + return DEG_queue_num_pending(q) + DEG_queue_num_ready(q); +} + +/* Check if queue has any items in it (still passing through) */ +bool DEG_queue_is_empty(DepsgraphQueue *q) +{ + return DEG_queue_size(q) == 0; +} + +/* Queue Operations --------------------------------------- */ + +/** + * Add DepsNode to the queue + * \param dnode: ``(DepsNode *)`` node to add to the queue + * Each node is only added once to the queue; Subsequent pushes + * merely update its status (e.g. moving it from "pending" to "ready") + * \param cost: new "num_links_pending" count for node *after* it has encountered + * via an outlink from the node currently being visited + * (i.e. we're one of the dependencies which may now be able to be processed) + */ +void DEG_queue_push(DepsgraphQueue *q, void *dnode, float cost) +{ + HeapNode *hnode = NULL; + + /* Shortcut: Directly add to ready if node isn't waiting on anything now... */ + if (cost == 0) { + /* node is now ready to be visited - schedule it up for such */ + if (BLI_ghash_haskey(q->pending_hash, dnode)) { + /* remove from pending queue - we're moving it to the scheduling queue */ + hnode = (HeapNode *)BLI_ghash_lookup(q->pending_hash, dnode); + BLI_heap_remove(q->pending_heap, hnode); + + BLI_ghash_remove(q->pending_hash, dnode, NULL, NULL); + } + + /* schedule up node using latest count (of ready nodes) */ + BLI_heap_insert(q->ready_heap, (float)q->idx, dnode); + q->idx++; + } + else { + /* node is still waiting on some other ancestors, + * so add it to the pending heap in the meantime... + */ + // XXX: is this even necessary now? + if (BLI_ghash_haskey(q->pending_hash, dnode)) { + /* just update cost on pending node */ + hnode = (HeapNode *)BLI_ghash_lookup(q->pending_hash, dnode); + BLI_heap_remove(q->pending_heap, hnode); + BLI_heap_insert(q->pending_heap, cost, hnode); + } + else { + /* add new node to pending queue, and increase size of overall queue */ + hnode = BLI_heap_insert(q->pending_heap, cost, dnode); + q->tot++; + } + } +} + +/* Grab a "ready" node from the queue */ +void *DEG_queue_pop(DepsgraphQueue *q) +{ + /* sanity check: if there are no "ready" nodes, + * start pulling from "pending" to keep things moving, + * but throw a warning so that we know that something's up here... + */ + if (BLI_heap_is_empty(q->ready_heap)) { + // XXX: this should never happen + // XXX: if/when it does happen, we may want instead to just wait until something pops up here... + printf("DepsgraphHeap Warning: No more ready nodes available. Trying from pending (idx = %d, tot = %d, pending = %d, ready = %d)\n", + (int)q->idx, (int)q->tot, (int)DEG_queue_num_pending(q), (int)DEG_queue_num_ready(q)); + + return BLI_heap_popmin(q->pending_heap); + } + else { + /* only grab "ready" nodes */ + return BLI_heap_popmin(q->ready_heap); + } +} diff --git a/source/blender/depsgraph/intern/depsgraph_queue.h b/source/blender/depsgraph/intern/depsgraph_queue.h new file mode 100644 index 00000000000..bd294d4655e --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph_queue.h @@ -0,0 +1,87 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + * + * Defines for special queue type for use in Depsgraph traversals + */ + +#ifndef __DEPSGRAPH_QUEUE_H__ +#define __DEPSGRAPH_QUEUE_H__ + +struct DepsNode; + +struct Heap; +struct GHash; + +/* *********************************************** */ +/* Dependency Graph Traversal Queue + * + * There are two parts to this: + * a) "Pending" Nodes - This part contains the set of nodes + * which are related to those which have been visited + * previously, but are not yet ready to actually be visited. + * b) "Scheduled" Nodes - These are the nodes whose ancestors + * have all been evaluated already, which means that any + * or all of them can be picked (in practically in order) to + * be visited immediately. + * + * Internally, the queue makes sure that each node in the graph + * only gets added to the queue once. This is because there can + * be multiple inlinks to each node given the way that the relations + * work. + */ + +/* Depsgraph Queue Type */ +typedef struct DepsgraphQueue { + /* Pending */ + struct Heap *pending_heap; /* (valence:int, DepsNode*) */ + struct GHash *pending_hash; /* (DepsNode* : HeapNode*>) */ + + /* Ready to be visited - fifo */ + struct Heap *ready_heap; /* (idx:int, DepsNode*) */ + + /* Size/Order counts */ + size_t idx; /* total number of nodes which are/have been ready so far (including those already visited) */ + size_t tot; /* total number of nodes which have passed through queue; mainly for debug */ +} DepsgraphQueue; + +/* ************************** */ +/* Depsgraph Queue Operations */ + +/* Data management */ +DepsgraphQueue *DEG_queue_new(void); +void DEG_queue_free(DepsgraphQueue *q); + +/* Statistics */ +size_t DEG_queue_num_pending(DepsgraphQueue *q); +size_t DEG_queue_num_ready(DepsgraphQueue *q); + +size_t DEG_queue_size(DepsgraphQueue *q); +bool DEG_queue_is_empty(DepsgraphQueue *q); + +/* Operations */ +void DEG_queue_push(DepsgraphQueue *q, void *dnode, float cost = 0.0f); +void *DEG_queue_pop(DepsgraphQueue *q); + +#endif /* DEPSGRAPH_QUEUE_H */ diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc new file mode 100644 index 00000000000..2f8cdfc1fd5 --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -0,0 +1,490 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + * + * Core routines for how the Depsgraph works + */ + +#include +#include +#include + +extern "C" { +#include "BLI_utildefines.h" + +#include "DNA_object_types.h" +#include "DNA_particle_types.h" +#include "DNA_screen_types.h" +#include "DNA_windowmanager_types.h" + +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_node.h" + +#define new new_ +#include "BKE_screen.h" +#undef new + +#include "DEG_depsgraph.h" +} /* extern "C" */ + +#include "depsgraph_debug.h" +#include "depsnode.h" +#include "depsnode_component.h" +#include "depsnode_operation.h" +#include "depsgraph_intern.h" + +/* *********************** */ +/* Update Tagging/Flushing */ + +/* Data-Based Tagging ------------------------------- */ + +static void lib_id_recalc_tag(Main *bmain, ID *id) +{ + id->flag |= LIB_ID_RECALC; + DEG_id_type_tag(bmain, GS(id->name)); +} + +static void lib_id_recalc_data_tag(Main *bmain, ID *id) +{ + id->flag |= LIB_ID_RECALC_DATA; + DEG_id_type_tag(bmain, GS(id->name)); +} + +static void lib_id_recalc_tag_flag(Main *bmain, ID *id, int flag) +{ + if (flag) { + /* This bit of code ensures legacy object->recalc flags + * are still filled in the same way as it was expected + * with the old dependency graph. + * + * This is because some areas like motion paths and likely + * some other physics baking process are doing manual scene + * update on all the frames, trying to minimize number of + * updates. + * + * But this flag will also let us to re-construct entry + * nodes for update after relations update and after layer + * visibility changes. + */ + short idtype = GS(id->name); + if (idtype == ID_OB) { + Object *object = (Object *)id; + object->recalc |= (flag & OB_RECALC_ALL); + } + + if (flag & OB_RECALC_OB) + lib_id_recalc_tag(bmain, id); + if (flag & (OB_RECALC_DATA | PSYS_RECALC)) + lib_id_recalc_data_tag(bmain, id); + } + else { + lib_id_recalc_tag(bmain, id); + } +} + +/* Tag all nodes in ID-block for update. + * This is a crude measure, but is most convenient for old code. + */ +void DEG_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id) +{ + IDDepsNode *node = graph->find_id_node(id); + lib_id_recalc_tag(bmain, id); + if (node != NULL) { + node->tag_update(graph); + } +} + +/* Tag nodes related to a specific piece of data */ +void DEG_graph_data_tag_update(Depsgraph *graph, const PointerRNA *ptr) +{ + DepsNode *node = graph->find_node_from_pointer(ptr, NULL); + if (node) { + node->tag_update(graph); + } + else { + printf("Missing node in %s\n", __func__); + BLI_assert(!"Shouldn't happens since it'll miss crucial update."); + } +} + +/* Tag nodes related to a specific property. */ +void DEG_graph_property_tag_update(Depsgraph *graph, + const PointerRNA *ptr, + const PropertyRNA *prop) +{ + DepsNode *node = graph->find_node_from_pointer(ptr, prop); + if (node) { + node->tag_update(graph); + } + else { + printf("Missing node in %s\n", __func__); + BLI_assert(!"Shouldn't happens since it'll miss crucial update."); + } +} + +/* Tag given ID for an update in all the dependency graphs. */ +void DEG_id_tag_update(ID *id, short flag) +{ + DEG_id_tag_update_ex(G.main, id, flag); +} + +void DEG_id_tag_update_ex(Main *bmain, ID *id, short flag) +{ + if(id == NULL) { + /* Ideally should not happen, but old depsgraph allowed this. */ + return; + } + DEG_DEBUG_PRINTF("%s: id=%s flag=%d\n", __func__, id->name, flag); + lib_id_recalc_tag_flag(bmain, id, flag); + for (Scene *scene = (Scene *)bmain->scene.first; + scene != NULL; + scene = (Scene *)scene->id.next) + { + if (scene->depsgraph) { + Depsgraph *graph = scene->depsgraph; + if (flag == 0) { + /* TODO(sergey): Currently blender is still tagging IDs + * for recalc just using flag=0. This isn't totally correct + * but we'd better deal with such cases and don't fail. + */ + DEG_graph_id_tag_update(bmain, graph, id); + continue; + } + if (flag & OB_RECALC_DATA && GS(id->name) == ID_OB) { + Object *object = (Object*)id; + if (object->data != NULL) { + DEG_graph_id_tag_update(bmain, + graph, + (ID*)object->data); + } + } + if (flag & (OB_RECALC_OB|OB_RECALC_DATA)) { + DEG_graph_id_tag_update(bmain, graph, id); + } + } + } +} + +/* Tag given ID type for update. */ +void DEG_id_type_tag(Main *bmain, short idtype) +{ + if (idtype == ID_NT) { + /* Stupid workaround so parent datablocks of nested nodetree get looped + * over when we loop over tagged datablock types. + */ + DEG_id_type_tag(bmain, ID_MA); + DEG_id_type_tag(bmain, ID_TE); + DEG_id_type_tag(bmain, ID_LA); + DEG_id_type_tag(bmain, ID_WO); + DEG_id_type_tag(bmain, ID_SCE); + } + /* We tag based on first ID type character to avoid + * looping over all ID's in case there are no tags. + */ + bmain->id_tag_update[((unsigned char *)&idtype)[0]] = 1; +} + +/* Update Flushing ---------------------------------- */ + +/* FIFO queue for tagged nodes that need flushing */ +/* XXX This may get a dedicated implementation later if needed - lukas */ +typedef std::queue FlushQueue; + +/* Flush updates from tagged nodes outwards until all affected nodes are tagged. */ +void DEG_graph_flush_updates(Main *bmain, Depsgraph *graph) +{ + /* sanity check */ + if (graph == NULL) + return; + + /* Nothing to update, early out. */ + if (graph->entry_tags.size() == 0) { + return; + } + + /* TODO(sergey): With a bit of flag magic we can get rid of this + * extra loop. + */ + for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin(); + it != graph->operations.end(); + ++it) + { + OperationDepsNode *node = *it; + node->scheduled = false; + } + + FlushQueue queue; + /* Starting from the tagged "entry" nodes, flush outwards... */ + /* NOTE: Also need to ensure that for each of these, there is a path back to + * root, or else they won't be done. + * NOTE: Count how many nodes we need to handle - entry nodes may be + * component nodes which don't count for this purpose! + */ + for (Depsgraph::EntryTags::const_iterator it = graph->entry_tags.begin(); + it != graph->entry_tags.end(); + ++it) + { + OperationDepsNode *node = *it; + IDDepsNode *id_node = node->owner->owner; + queue.push(node); + deg_editors_id_update(bmain, id_node->id); + node->scheduled = true; + } + + while (!queue.empty()) { + OperationDepsNode *node = queue.front(); + queue.pop(); + + IDDepsNode *id_node = node->owner->owner; + lib_id_recalc_tag(bmain, id_node->id); + /* TODO(sergey): For until we've got proper data nodes in the graph. */ + lib_id_recalc_data_tag(bmain, id_node->id); + + ID *id = id_node->id; + /* This code is used to preserve those areas which does direct + * object update, + * + * Plus it ensures visibility changes and relations and layers + * visibility update has proper flags to work with. + */ + if (GS(id->name) == ID_OB) { + Object *object = (Object *)id; + ComponentDepsNode *comp_node = node->owner; + if (comp_node->type == DEPSNODE_TYPE_ANIMATION) { + object->recalc |= OB_RECALC_TIME; + } + else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) { + object->recalc |= OB_RECALC_OB; + } + else { + object->recalc |= OB_RECALC_DATA; + } + } + + /* Flush to nodes along links... */ + for (OperationDepsNode::Relations::const_iterator it = node->outlinks.begin(); + it != node->outlinks.end(); + ++it) + { + DepsRelation *rel = *it; + OperationDepsNode *to_node = (OperationDepsNode *)rel->to; + if (to_node->scheduled == false) { + to_node->flag |= DEPSOP_FLAG_NEEDS_UPDATE; + queue.push(to_node); + to_node->scheduled = true; + deg_editors_id_update(bmain, id_node->id); + } + } + + /* TODO(sergey): For until incremental updates are possible + * witin a component at least we tag the whole component + * for update. + */ + for (ComponentDepsNode::OperationMap::iterator it = node->owner->operations.begin(); + it != node->owner->operations.end(); + ++it) + { + OperationDepsNode *op = it->second; + op->flag |= DEPSOP_FLAG_NEEDS_UPDATE; + } + } +} + +/* Recursively push updates out to all nodes dependent on this, + * until all affected are tagged and/or scheduled up for eval + */ +void DEG_ids_flush_tagged(Main *bmain) +{ + for (Scene *scene = (Scene*)bmain->scene.first; + scene != NULL; + scene = (Scene*)scene->id.next) + { + /* TODO(sergey): Only visible scenes? */ + if (scene->depsgraph != NULL) { + DEG_graph_flush_updates(bmain, scene->depsgraph); + } + } +} + +/* Clear tags from all operation nodes. */ +void DEG_graph_clear_tags(Depsgraph *graph) +{ + /* Go over all operation nodes, clearing tags. */ + for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin(); + it != graph->operations.end(); + ++it) + { + OperationDepsNode *node = *it; + + /* Clear node's "pending update" settings. */ + node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE); + /* Reset so that it can be bumped up again. */ + node->num_links_pending = 0; + node->scheduled = false; + } + + /* Clear any entry tags which haven't been flushed. */ + graph->entry_tags.clear(); +} + +/* Update dependency graph when visible scenes/layers changes. */ +void DEG_graph_on_visible_update(Main *bmain, Scene *scene) +{ + Depsgraph *graph = scene->depsgraph; + wmWindowManager *wm = (wmWindowManager *)bmain->wm.first; + int old_layers = graph->layers; + if (wm != NULL) { + BKE_main_id_flag_listbase(&bmain->scene, LIB_DOIT, true); + graph->layers = 0; + for (wmWindow *win = (wmWindow *)wm->windows.first; + win != NULL; + win = (wmWindow *)win->next) + { + Scene *scene = win->screen->scene; + if (scene->id.flag & LIB_DOIT) { + graph->layers |= BKE_screen_visible_layers(win->screen, scene); + scene->id.flag &= ~LIB_DOIT; + } + } + } + else { + /* All the layers for background render for now. */ + graph->layers = (1 << 20) - 1; + } + if (old_layers != graph->layers) { + /* Tag all objects which becomes visible (or which becomes needed for dependencies) + * for recalc. + * + * This is mainly needed on file load only, after that updates of invisible objects + * will be stored in the pending list. + */ + for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin(); + it != graph->operations.end(); + ++it) + { + OperationDepsNode *node = *it; + IDDepsNode *id_node = node->owner->owner; + ID *id = id_node->id; + if ((id->flag & LIB_ID_RECALC_ALL) != 0 || + (id_node->layers & scene->lay_updated) == 0) + { + id_node->tag_update(graph); + } + /* A bit of magic: if object->recalc is set it means somebody tagged + * it for update. If corresponding ID recalc flags are zero it means + * graph has been evaluated after that and the recalc was skipped + * because of visibility check. + */ + if (GS(id->name) == ID_OB) { + Object *object = (Object *)id; + if ((id->flag & LIB_ID_RECALC_ALL) == 0 && + (object->recalc & OB_RECALC_ALL) != 0) + { + id_node->tag_update(graph); + ComponentDepsNode *anim_comp = + id_node->find_component(DEPSNODE_TYPE_ANIMATION); + if (anim_comp != NULL && object->recalc & OB_RECALC_TIME) { + anim_comp->tag_update(graph); + } + } + } + } + } + scene->lay_updated |= graph->layers; +} + +void DEG_on_visible_update(Main *bmain, const bool UNUSED(do_time)) +{ + for (Scene *scene = (Scene*)bmain->scene.first; + scene != NULL; + scene = (Scene*)scene->id.next) + { + if (scene->depsgraph != NULL) { + DEG_graph_on_visible_update(bmain, scene); + } + } +} + +/* Check if something was changed in the database and inform + * editors about this. + */ +void DEG_ids_check_recalc(Main *bmain, Scene *scene, bool time) +{ + ListBase *lbarray[MAX_LIBARRAY]; + int a; + bool updated = false; + + /* Loop over all ID types. */ + a = set_listbasepointers(bmain, lbarray); + while (a--) { + ListBase *lb = lbarray[a]; + ID *id = (ID*)lb->first; + + /* We tag based on first ID type character to avoid + * looping over all ID's in case there are no tags. + */ + if (id && bmain->id_tag_update[(unsigned char)id->name[0]]) { + updated = true; + break; + } + } + + deg_editors_scene_update(bmain, scene, (updated || time)); +} + +void DEG_ids_clear_recalc(Main *bmain) +{ + ListBase *lbarray[MAX_LIBARRAY]; + bNodeTree *ntree; + int a; + + /* TODO(sergey): Re-implement POST_UPDATE_HANDLER_WORKAROUND using entry_tags + * and id_tags storage from the new dependency graph. + */ + + /* Loop over all ID types. */ + a = set_listbasepointers(bmain, lbarray); + while (a--) { + ListBase *lb = lbarray[a]; + ID *id = (ID *)lb->first; + + /* We tag based on first ID type character to avoid + * looping over all ID's in case there are no tags. + */ + if (id && bmain->id_tag_update[(unsigned char)id->name[0]]) { + for (; id; id = (ID *)id->next) { + id->flag &= ~(LIB_ID_RECALC | LIB_ID_RECALC_DATA); + + /* Some ID's contain semi-datablock nodetree */ + ntree = ntreeFromID(id); + if (ntree != NULL) { + ntree->id.flag &= ~(LIB_ID_RECALC | LIB_ID_RECALC_DATA); + } + } + } + } + + memset(bmain->id_tag_update, 0, sizeof(bmain->id_tag_update)); +} diff --git a/source/blender/depsgraph/intern/depsgraph_type_defines.cc b/source/blender/depsgraph/intern/depsgraph_type_defines.cc new file mode 100644 index 00000000000..67c632d4125 --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph_type_defines.cc @@ -0,0 +1,98 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + * + * Defines and code for core node types + */ + +extern "C" { +#include "BLI_utildefines.h" +#include "BLI_ghash.h" + +#include "DEG_depsgraph.h" +} /* extern "C" */ + +#include "depsgraph_intern.h" +#include "depsnode.h" +#include "depsnode_component.h" +#include "depsnode_operation.h" + +/* ************ */ +/* External API */ + +/* Global type registry */ + +/** + * \note For now, this is a hashtable not array, since the core node types + * currently do not have contiguous ID values. Using a hash here gives us + * more flexibility, albeit using more memory and also sacrificing a little + * speed. Later on, when things stabilise we may turn this back to an array + * since there are only just a few node types that an array would cope fine... + */ +static GHash *_depsnode_typeinfo_registry = NULL; + +/* Registration ------------------------------------------- */ + +/* Register node type */ +void DEG_register_node_typeinfo(DepsNodeFactory *factory) +{ + BLI_assert(factory != NULL); + BLI_ghash_insert(_depsnode_typeinfo_registry, SET_INT_IN_POINTER(factory->type()), factory); +} + +/* Register all node types */ +void DEG_register_node_types(void) +{ + /* initialise registry */ + _depsnode_typeinfo_registry = BLI_ghash_int_new("Depsgraph Node Type Registry"); + + /* register node types */ + DEG_register_base_depsnodes(); + DEG_register_component_depsnodes(); + DEG_register_operation_depsnodes(); +} + +/* Free registry on exit */ +void DEG_free_node_types(void) +{ + BLI_ghash_free(_depsnode_typeinfo_registry, NULL, NULL); +} + +/* Getters ------------------------------------------------- */ + +/* Get typeinfo for specified type */ +DepsNodeFactory *DEG_get_node_factory(const eDepsNode_Type type) +{ + /* look up type - at worst, it doesn't exist in table yet, and we fail */ + return (DepsNodeFactory *)BLI_ghash_lookup(_depsnode_typeinfo_registry, SET_INT_IN_POINTER(type)); +} + +/* Get typeinfo for provided node */ +DepsNodeFactory *DEG_node_get_factory(const DepsNode *node) +{ + if (!node) + return NULL; + + return DEG_get_node_factory(node->type); +} diff --git a/source/blender/depsgraph/intern/depsgraph_types.h b/source/blender/depsgraph/intern/depsgraph_types.h new file mode 100644 index 00000000000..2a84f4587af --- /dev/null +++ b/source/blender/depsgraph/intern/depsgraph_types.h @@ -0,0 +1,169 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + * + * Datatypes for internal use in the Depsgraph + * + * All of these datatypes are only really used within the "core" depsgraph. + * In particular, node types declared here form the structure of operations + * in the graph. + */ + +#ifndef __DEPSGRAPH_TYPES_H__ +#define __DEPSGRAPH_TYPES_H__ + +#include "depsgraph_util_function.h" + +/* TODO(sergey): Ideally we'll just use char* and statically allocated strings + * to avoid any possible overhead caused by string (re)allocation/formatting. + */ +#include +#include + +using std::string; +using std::vector; + +struct bAction; +struct ChannelDriver; +struct ModifierData; +struct PointerRNA; +struct EvaluationContext; +struct FCurve; + +/* Evaluation Operation for atomic operation */ +// XXX: move this to another header that can be exposed? +typedef function DepsEvalOperationCb; + +/* Metatype of Nodes - The general "level" in the graph structure the node serves */ +typedef enum eDepsNode_Class { + DEPSNODE_CLASS_GENERIC = 0, /* Types generally unassociated with user-visible entities, but needed for graph functioning */ + + DEPSNODE_CLASS_COMPONENT = 1, /* [Outer Node] An "aspect" of evaluating/updating an ID-Block, requiring certain types of evaluation behaviours */ + DEPSNODE_CLASS_OPERATION = 2, /* [Inner Node] A glorified function-pointer/callback for scheduling up evaluation operations for components, subject to relationship requirements */ +} eDepsNode_Class; + +/* Types of Nodes */ +typedef enum eDepsNode_Type { + DEPSNODE_TYPE_UNDEFINED = -1, /* fallback type for invalid return value */ + + DEPSNODE_TYPE_OPERATION = 0, /* Inner Node (Operation) */ + + /* Generic Types */ + DEPSNODE_TYPE_ROOT = 1, /* "Current Scene" - basically whatever kicks off the evaluation process */ + DEPSNODE_TYPE_TIMESOURCE = 2, /* Time-Source */ + + DEPSNODE_TYPE_ID_REF = 3, /* ID-Block reference - used as landmarks/collection point for components, but not usually part of main graph */ + DEPSNODE_TYPE_SUBGRAPH = 4, /* Isolated sub-graph - used for keeping instanced data separate from instances using them */ + + /* Outer Types */ + DEPSNODE_TYPE_PARAMETERS = 11, /* Parameters Component - Default when nothing else fits (i.e. just SDNA property setting) */ + DEPSNODE_TYPE_PROXY = 12, /* Generic "Proxy-Inherit" Component */ // XXX: Also for instancing of subgraphs? + DEPSNODE_TYPE_ANIMATION = 13, /* Animation Component */ // XXX: merge in with parameters? + DEPSNODE_TYPE_TRANSFORM = 14, /* Transform Component (Parenting/Constraints) */ + DEPSNODE_TYPE_GEOMETRY = 15, /* Geometry Component (DerivedMesh/Displist) */ + DEPSNODE_TYPE_SEQUENCER = 16, /* Sequencer Component (Scene Only) */ + + /* Evaluation-Related Outer Types (with Subdata) */ + DEPSNODE_TYPE_EVAL_POSE = 21, /* Pose Component - Owner/Container of Bones Eval */ + DEPSNODE_TYPE_BONE = 22, /* Bone Component - Child/Subcomponent of Pose */ + + DEPSNODE_TYPE_EVAL_PARTICLES = 23, /* Particle Systems Component */ + DEPSNODE_TYPE_SHADING = 24, /* Material Shading Component */ +} eDepsNode_Type; + +/* Identifiers for common operations (as an enum) */ +typedef enum eDepsOperation_Code { +#define DEF_DEG_OPCODE(label) DEG_OPCODE_##label, +#include "depsnode_opcodes.h" +#undef DEF_DEG_OPCODE +} eDepsOperation_Code; + +/* String defines for these opcodes, defined in depsnode_operation.cpp */ +extern const char *DEG_OPNAMES[]; + + +/* Type of operation */ +typedef enum eDepsOperation_Type { + /* Primary operation types */ + DEPSOP_TYPE_INIT = 0, /* initialise evaluation data */ + DEPSOP_TYPE_EXEC = 1, /* standard evaluation step */ + DEPSOP_TYPE_POST = 2, /* cleanup evaluation data + flush results */ + + /* Additional operation types */ + DEPSOP_TYPE_OUT = 3, /* indicator for outputting a temporary result that other components can use */ // XXX? + DEPSOP_TYPE_SIM = 4, /* indicator for things like IK Solvers and Rigidbody Sim steps which modify final results of separate entities at once */ + DEPSOP_TYPE_REBUILD = 5, /* rebuild internal evaluation data - used for Rigidbody Reset and Armature Rebuild-On-Load */ +} eDepsOperation_Type; + +/* Types of relationships between nodes + * + * This is used to provide additional hints to use when filtering + * the graph, so that we can go without doing more extensive + * data-level checks... + */ +typedef enum eDepsRelation_Type { + /* reationship type unknown/irrelevant */ + DEPSREL_TYPE_STANDARD = 0, + + /* root -> active scene or entity (screen, image, etc.) */ + DEPSREL_TYPE_ROOT_TO_ACTIVE, + + /* general datablock dependency */ + DEPSREL_TYPE_DATABLOCK, + + /* time dependency */ + DEPSREL_TYPE_TIME, + + /* component depends on results of another */ + DEPSREL_TYPE_COMPONENT_ORDER, + + /* relationship is just used to enforce ordering of operations + * (e.g. "init()" callback done before "exec() and "cleanup()") + */ + DEPSREL_TYPE_OPERATION, + + /* relationship results from a property driver affecting property */ + DEPSREL_TYPE_DRIVER, + + /* relationship is something driver depends on */ + DEPSREL_TYPE_DRIVER_TARGET, + + /* relationship is used for transform stack + * (e.g. parenting, user transforms, constraints) + */ + DEPSREL_TYPE_TRANSFORM, + + /* relationship is used for geometry evaluation + * (e.g. metaball "motherball" or modifiers) + */ + DEPSREL_TYPE_GEOMETRY_EVAL, + + /* relationship is used to trigger a post-change validity updates */ + DEPSREL_TYPE_UPDATE, + + /* relationship is used to trigger editor/screen updates */ + DEPSREL_TYPE_UPDATE_UI, +} eDepsRelation_Type; + +#endif /* __DEPSGRAPH_TYPES_H__ */ diff --git a/source/blender/depsgraph/intern/depsnode.cc b/source/blender/depsgraph/intern/depsnode.cc new file mode 100644 index 00000000000..8d21f6e0034 --- /dev/null +++ b/source/blender/depsgraph/intern/depsnode.cc @@ -0,0 +1,308 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include + +#include "BLI_utildefines.h" + +extern "C" { +#include "DNA_ID.h" +#include "DNA_anim_types.h" + +#include "BKE_animsys.h" + +#include "DEG_depsgraph.h" +} + +#include "depsnode.h" /* own include */ +#include "depsnode_component.h" +#include "depsnode_operation.h" +#include "depsgraph_intern.h" + +/* *************** */ +/* Node Management */ + +/* Add ------------------------------------------------ */ + +DepsNode::TypeInfo::TypeInfo(eDepsNode_Type type, const char *tname) +{ + this->type = type; + if (type == DEPSNODE_TYPE_OPERATION) + this->tclass = DEPSNODE_CLASS_OPERATION; + else if (type < DEPSNODE_TYPE_PARAMETERS) + this->tclass = DEPSNODE_CLASS_GENERIC; + else + this->tclass = DEPSNODE_CLASS_COMPONENT; + this->tname = tname; +} + +DepsNode::DepsNode() +{ + this->name[0] = '\0'; +} + +DepsNode::~DepsNode() +{ + /* free links + * note: deleting relations will remove them from the node relations set, + * but only touch the same position as we are using here, which is safe. + */ + DEPSNODE_RELATIONS_ITER_BEGIN(this->inlinks, rel) + { + OBJECT_GUARDED_DELETE(rel, DepsRelation); + } + DEPSNODE_RELATIONS_ITER_END; + + DEPSNODE_RELATIONS_ITER_BEGIN(this->outlinks, rel) + { + OBJECT_GUARDED_DELETE(rel, DepsRelation); + } + DEPSNODE_RELATIONS_ITER_END; +} + + +/* Generic identifier for Depsgraph Nodes. */ +string DepsNode::identifier() const +{ + char typebuf[7]; + sprintf(typebuf, "(%d)", type); + + return string(typebuf) + " : " + name; +} + +/* ************* */ +/* Generic Nodes */ + +/* Time Source Node ============================================== */ + +void TimeSourceDepsNode::tag_update(Depsgraph *graph) +{ + for (DepsNode::Relations::const_iterator it = outlinks.begin(); + it != outlinks.end(); + ++it) + { + DepsRelation *rel = *it; + DepsNode *node = rel->to; + node->tag_update(graph); + } +} + + +/* Root Node ============================================== */ + +RootDepsNode::~RootDepsNode() +{ + OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode); +} + +TimeSourceDepsNode *RootDepsNode::add_time_source(const string &name) +{ + if (!time_source) { + DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_TIMESOURCE); + time_source = (TimeSourceDepsNode *)factory->create_node(NULL, "", name); + /*time_source->owner = this;*/ // XXX + } + return time_source; +} + +DEG_DEPSNODE_DEFINE(RootDepsNode, DEPSNODE_TYPE_ROOT, "Root DepsNode"); +static DepsNodeFactoryImpl DNTI_ROOT; + +/* Time Source Node ======================================= */ + +DEG_DEPSNODE_DEFINE(TimeSourceDepsNode, DEPSNODE_TYPE_TIMESOURCE, "Time Source"); +static DepsNodeFactoryImpl DNTI_TIMESOURCE; + +/* ID Node ================================================ */ + +/* Initialize 'id' node - from pointer data given. */ +void IDDepsNode::init(const ID *id, const string &UNUSED(subdata)) +{ + /* Store ID-pointer. */ + BLI_assert(id != NULL); + this->id = (ID *)id; + this->layers = (1 << 20) - 1; + this->eval_flags = 0; + + /* NOTE: components themselves are created if/when needed. + * This prevents problems with components getting added + * twice if an ID-Ref needs to be created to house it... + */ +} + +/* Free 'id' node. */ +IDDepsNode::~IDDepsNode() +{ + clear_components(); +} + +/* Copy 'id' node. */ +void IDDepsNode::copy(DepsgraphCopyContext *dcc, const IDDepsNode *src) +{ + (void)src; /* Ignored. */ + /* Iterate over items in original hash, adding them to new hash. */ + for (IDDepsNode::ComponentMap::const_iterator it = this->components.begin(); + it != this->components.end(); + ++it) + { + /* Get current mapping. */ + ComponentIDKey c_key = it->first; + DepsNode *old_component = it->second; + + /* Make a copy of component. */ + ComponentDepsNode *component = (ComponentDepsNode *)DEG_copy_node(dcc, old_component); + + /* Add new node to hash... */ + this->components[c_key] = component; + } + + // TODO: perform a second loop to fix up links? + BLI_assert(!"Not expected to be used"); +} + +ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type, + const string &name) const +{ + ComponentIDKey key(type, name); + ComponentMap::const_iterator it = components.find(key); + return it != components.end() ? it->second : NULL; +} + +ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type, + const string &name) +{ + ComponentIDKey key(type, name); + ComponentDepsNode *comp_node = find_component(type, name); + if (!comp_node) { + DepsNodeFactory *factory = DEG_get_node_factory(type); + comp_node = (ComponentDepsNode *)factory->create_node(this->id, "", name); + + /* Register. */ + this->components[key] = comp_node; + comp_node->owner = this; + } + return comp_node; +} + +void IDDepsNode::remove_component(eDepsNode_Type type, const string &name) +{ + ComponentIDKey key(type, name); + ComponentDepsNode *comp_node = find_component(type, name); + if (comp_node) { + /* Unregister. */ + this->components.erase(key); + OBJECT_GUARDED_DELETE(comp_node, ComponentDepsNode); + } +} + +void IDDepsNode::clear_components() +{ + for (ComponentMap::const_iterator it = components.begin(); + it != components.end(); + ++it) + { + ComponentDepsNode *comp_node = it->second; + OBJECT_GUARDED_DELETE(comp_node, ComponentDepsNode); + } + components.clear(); +} + +void IDDepsNode::tag_update(Depsgraph *graph) +{ + for (ComponentMap::const_iterator it = components.begin(); + it != components.end(); + ++it) + { + ComponentDepsNode *comp_node = it->second; + /* TODO(sergey): What about drievrs? */ + bool do_component_tag = comp_node->type != DEPSNODE_TYPE_ANIMATION; + if (comp_node->type == DEPSNODE_TYPE_ANIMATION) { + AnimData *adt = BKE_animdata_from_id(id); + BLI_assert(adt != NULL); + if (adt->recalc & ADT_RECALC_ANIM) { + do_component_tag = true; + } + } + if (do_component_tag) { + comp_node->tag_update(graph); + } + } +} + +DEG_DEPSNODE_DEFINE(IDDepsNode, DEPSNODE_TYPE_ID_REF, "ID Node"); +static DepsNodeFactoryImpl DNTI_ID_REF; + +/* Subgraph Node ========================================== */ + +/* Initialize 'subgraph' node - from pointer data given. */ +void SubgraphDepsNode::init(const ID *id, const string &UNUSED(subdata)) +{ + /* Store ID-ref if provided. */ + this->root_id = (ID *)id; + + /* NOTE: graph will need to be added manually, + * as we don't have any way of passing this down. + */ +} + +/* Free 'subgraph' node */ +SubgraphDepsNode::~SubgraphDepsNode() +{ + /* Only free if graph not shared, of if this node is the first + * reference to it... + */ + // XXX: prune these flags a bit... + if ((this->flag & SUBGRAPH_FLAG_FIRSTREF) || !(this->flag & SUBGRAPH_FLAG_SHARED)) { + /* Free the referenced graph. */ + DEG_graph_free(this->graph); + this->graph = NULL; + } +} + +/* Copy 'subgraph' node - Assume that the subgraph doesn't get copied for now... */ +void SubgraphDepsNode::copy(DepsgraphCopyContext * /*dcc*/, + const SubgraphDepsNode * /*src*/) +{ + //const SubgraphDepsNode *src_node = (const SubgraphDepsNode *)src; + //SubgraphDepsNode *dst_node = (SubgraphDepsNode *)dst; + + /* for now, subgraph itself isn't copied... */ + BLI_assert(!"Not expected to be used"); +} + +DEG_DEPSNODE_DEFINE(SubgraphDepsNode, DEPSNODE_TYPE_SUBGRAPH, "Subgraph Node"); +static DepsNodeFactoryImpl DNTI_SUBGRAPH; + + +void DEG_register_base_depsnodes() +{ + DEG_register_node_typeinfo(&DNTI_ROOT); + DEG_register_node_typeinfo(&DNTI_TIMESOURCE); + + DEG_register_node_typeinfo(&DNTI_ID_REF); + DEG_register_node_typeinfo(&DNTI_SUBGRAPH); +} diff --git a/source/blender/depsgraph/intern/depsnode.h b/source/blender/depsgraph/intern/depsnode.h new file mode 100644 index 00000000000..067bd771e87 --- /dev/null +++ b/source/blender/depsgraph/intern/depsnode.h @@ -0,0 +1,243 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __DEPSNODE_H__ +#define __DEPSNODE_H__ + +#include "depsgraph_types.h" + +#include "depsgraph_util_hash.h" +#include "depsgraph_util_map.h" +#include "depsgraph_util_set.h" + +struct ID; +struct Scene; + +struct Depsgraph; +struct DepsRelation; +struct DepsgraphCopyContext; +struct OperationDepsNode; + +/* *********************************** */ +/* Base-Defines for Nodes in Depsgraph */ + +/* All nodes in Depsgraph are descended from this. */ +struct DepsNode { + /* Helper class for static typeinfo in subclasses. */ + struct TypeInfo { + TypeInfo(eDepsNode_Type type, const char *tname); + + eDepsNode_Type type; + eDepsNode_Class tclass; + const char *tname; + }; + + /* Identifier - mainly for debugging purposes. */ + string name; + + /* Structural type of node. */ + eDepsNode_Type type; + + /* Type of data/behaviour represented by node... */ + eDepsNode_Class tclass; + + /* Relationships between nodes + * The reason why all depsgraph nodes are descended from this type (apart + * from basic serialization benefits - from the typeinfo) is that we can have + * relationships between these nodes! + */ + typedef unordered_set Relations; + + /* Nodes which this one depends on. */ + Relations inlinks; + + /* Nodes which depend on this one. */ + Relations outlinks; + + /* Generic tag for traversal algorithms */ + int done; + + /* Methods. */ + + DepsNode(); + virtual ~DepsNode(); + + virtual string identifier() const; + string full_identifier() const; + + virtual void init(const ID * /*id*/, + const string &/*subdata*/) {} + virtual void copy(DepsgraphCopyContext * /*dcc*/, + const DepsNode * /*src*/) {} + + virtual void tag_update(Depsgraph * /*graph*/) {} + + virtual OperationDepsNode *get_entry_operation() { return NULL; } + virtual OperationDepsNode *get_exit_operation() { return NULL; } +}; + +/* Macros for common static typeinfo. */ +#define DEG_DEPSNODE_DECLARE \ + static const DepsNode::TypeInfo typeinfo +#define DEG_DEPSNODE_DEFINE(NodeType, type_, tname_) \ + const DepsNode::TypeInfo NodeType::typeinfo = DepsNode::TypeInfo(type_, tname_) + +/* Generic Nodes ======================= */ + +struct ComponentDepsNode; +struct IDDepsNode; + +/* Time Source Node. */ +struct TimeSourceDepsNode : public DepsNode { + /* New "current time". */ + float cfra; + + /* time-offset relative to the "official" time source that this one has. */ + float offset; + + // TODO: evaluate() operation needed + + void tag_update(Depsgraph *graph); + + DEG_DEPSNODE_DECLARE; +}; + +/* Root Node. */ +struct RootDepsNode : public DepsNode { + ~RootDepsNode(); + + TimeSourceDepsNode *add_time_source(const string &name = ""); + + /* scene that this corresponds to */ + Scene *scene; + + /* Entrypoint node for time-changed. */ + TimeSourceDepsNode *time_source; + + DEG_DEPSNODE_DECLARE; +}; + +/* ID-Block Reference */ +struct IDDepsNode : public DepsNode { + struct ComponentIDKey { + ComponentIDKey(eDepsNode_Type type, const string &name = "") + : type(type), name(name) {} + + bool operator== (const ComponentIDKey &other) const + { + return type == other.type && name == other.name; + } + + eDepsNode_Type type; + string name; + }; + + /* XXX can't specialize std::hash for this purpose, because ComponentIDKey is + * a nested type ... + * + * http://stackoverflow.com/a/951245 + */ + struct component_key_hash { + bool operator() (const ComponentIDKey &key) const + { + return hash_combine(hash()(key.type), hash()(key.name)); + } + }; + + typedef unordered_map ComponentMap; + + void init(const ID *id, const string &subdata); + void copy(DepsgraphCopyContext *dcc, const IDDepsNode *src); + ~IDDepsNode(); + + ComponentDepsNode *find_component(eDepsNode_Type type, + const string &name = "") const; + ComponentDepsNode *add_component(eDepsNode_Type type, + const string &name = ""); + void remove_component(eDepsNode_Type type, const string &name = ""); + void clear_components(); + + void tag_update(Depsgraph *graph); + + /* ID Block referenced. */ + ID *id; + + /* Hash to make it faster to look up components. */ + ComponentMap components; + + /* Layers of this node with accumulated layers of it's output relations. */ + int layers; + + /* Additional flags needed for scene evaluation. + * TODO(sergey): Only needed for until really granual updates + * of all the entities. + */ + int eval_flags; + + DEG_DEPSNODE_DECLARE; +}; + +/* Subgraph Reference. */ +struct SubgraphDepsNode : public DepsNode { + void init(const ID *id, const string &subdata); + void copy(DepsgraphCopyContext *dcc, const SubgraphDepsNode *src); + ~SubgraphDepsNode(); + + /* Instanced graph. */ + Depsgraph *graph; + + /* ID-block at root of subgraph (if applicable). */ + ID *root_id; + + /* Number of nodes which use/reference this subgraph - if just 1, it may be + * possible to merge into main, + */ + size_t num_users; + + /* (eSubgraphRef_Flag) assorted settings for subgraph node. */ + int flag; + + DEG_DEPSNODE_DECLARE; +}; + +/* Flags for subgraph node */ +typedef enum eSubgraphRef_Flag { + /* Subgraph referenced is shared with another reference, so shouldn't + * free on exit. + */ + SUBGRAPH_FLAG_SHARED = (1 << 0), + + /* Node is first reference to subgraph, so it can be freed when we are + * removed. + */ + SUBGRAPH_FLAG_FIRSTREF = (1 << 1), +} eSubgraphRef_Flag; + +void DEG_register_base_depsnodes(); + +#endif /* __DEPSNODE_H__ */ diff --git a/source/blender/depsgraph/intern/depsnode_component.cc b/source/blender/depsgraph/intern/depsnode_component.cc new file mode 100644 index 00000000000..969b0891e15 --- /dev/null +++ b/source/blender/depsgraph/intern/depsnode_component.cc @@ -0,0 +1,314 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include + +extern "C" { +#include "BLI_utildefines.h" + +#include "DNA_object_types.h" + +#include "BKE_action.h" +} /* extern "C" */ + +#include "depsnode_component.h" /* own include */ +#include "depsnode_operation.h" +#include "depsgraph_intern.h" + +/* *********** */ +/* Outer Nodes */ + +/* Standard Component Methods ============================= */ + +ComponentDepsNode::ComponentDepsNode() : + entry_operation(NULL), + exit_operation(NULL) +{ +} + +/* Initialize 'component' node - from pointer data given */ +void ComponentDepsNode::init(const ID * /*id*/, + const string & /*subdata*/) +{ + /* hook up eval context? */ + // XXX: maybe this needs a special API? +} + +/* Copy 'component' node */ +void ComponentDepsNode::copy(DepsgraphCopyContext * /*dcc*/, + const ComponentDepsNode * /*src*/) +{ +#if 0 // XXX: remove all this + /* duplicate list of operation nodes */ + this->operations.clear(); + + for (OperationMap::const_iterator it = src->operations.begin(); it != src->operations.end(); ++it) { + const string &pchan_name = it->first; + OperationDepsNode *src_op = it->second; + + /* recursive copy */ + DepsNodeFactory *factory = DEG_node_get_factory(src_op); + OperationDepsNode *dst_op = (OperationDepsNode *)factory->copy_node(dcc, src_op); + this->operations[pchan_name] = dst_op; + + /* fix links... */ + // ... + } + + /* copy evaluation contexts */ + // +#endif + BLI_assert(!"Not expected to be called"); +} + +/* Free 'component' node */ +ComponentDepsNode::~ComponentDepsNode() +{ + clear_operations(); +} + +string ComponentDepsNode::identifier() const +{ + string &idname = this->owner->name; + + char typebuf[7]; + sprintf(typebuf, "(%d)", type); + + return string(typebuf) + name + " : " + idname; +} + +OperationDepsNode *ComponentDepsNode::find_operation(OperationIDKey key) const +{ + OperationMap::const_iterator it = this->operations.find(key); + + if (it != this->operations.end()) { + return it->second; + } + else { + fprintf(stderr, "%s: find_operation(%s) failed\n", + this->identifier().c_str(), key.identifier().c_str()); + BLI_assert(!"Request for non-existing operation, should not happen"); + return NULL; + } +} + +OperationDepsNode *ComponentDepsNode::find_operation(eDepsOperation_Code opcode, const string &name) const +{ + OperationIDKey key(opcode, name); + return find_operation(key); +} + +OperationDepsNode *ComponentDepsNode::has_operation(OperationIDKey key) const +{ + OperationMap::const_iterator it = this->operations.find(key); + if (it != this->operations.end()) { + return it->second; + } + return NULL; +} + +OperationDepsNode *ComponentDepsNode::has_operation(eDepsOperation_Code opcode, + const string &name) const +{ + OperationIDKey key(opcode, name); + return has_operation(key); +} + +OperationDepsNode *ComponentDepsNode::add_operation(eDepsOperation_Type optype, DepsEvalOperationCb op, eDepsOperation_Code opcode, const string &name) +{ + OperationDepsNode *op_node = has_operation(opcode, name); + if (!op_node) { + DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_OPERATION); + op_node = (OperationDepsNode *)factory->create_node(this->owner->id, "", name); + + /* register opnode in this component's operation set */ + OperationIDKey key(opcode, name); + this->operations[key] = op_node; + + /* set as entry/exit node of component (if appropriate) */ + if (optype == DEPSOP_TYPE_INIT) { + BLI_assert(this->entry_operation == NULL); + this->entry_operation = op_node; + } + else if (optype == DEPSOP_TYPE_POST) { + // XXX: review whether DEPSOP_TYPE_OUT is better than DEPSOP_TYPE_POST, or maybe have both? + BLI_assert(this->exit_operation == NULL); + this->exit_operation = op_node; + } + + /* set backlink */ + op_node->owner = this; + } + else { + fprintf(stderr, "add_operation: Operation already exists - %s has %s at %p\n", + this->identifier().c_str(), op_node->identifier().c_str(), op_node); + BLI_assert(!"Should not happen!"); + } + + /* attach extra data */ + op_node->evaluate = op; + op_node->optype = optype; + op_node->opcode = opcode; + op_node->name = name; + + return op_node; +} + +void ComponentDepsNode::remove_operation(eDepsOperation_Code opcode, const string &name) +{ + OperationDepsNode *op_node = find_operation(opcode, name); + if (op_node) { + /* unregister */ + this->operations.erase(OperationIDKey(opcode, name)); + OBJECT_GUARDED_DELETE(op_node, OperationDepsNode); + } +} + +void ComponentDepsNode::clear_operations() +{ + for (OperationMap::const_iterator it = operations.begin(); it != operations.end(); ++it) { + OperationDepsNode *op_node = it->second; + OBJECT_GUARDED_DELETE(op_node, OperationDepsNode); + } + operations.clear(); +} + +void ComponentDepsNode::tag_update(Depsgraph *graph) +{ + OperationDepsNode *entry_op = get_entry_operation(); + if (entry_op != NULL && entry_op->flag & DEPSOP_FLAG_NEEDS_UPDATE) { + return; + } + for (OperationMap::const_iterator it = operations.begin(); it != operations.end(); ++it) { + OperationDepsNode *op_node = it->second; + op_node->tag_update(graph); + } +} + +OperationDepsNode *ComponentDepsNode::get_entry_operation() +{ + if (entry_operation) + return entry_operation; + else if (operations.size() == 1) + return operations.begin()->second; + return NULL; +} + +OperationDepsNode *ComponentDepsNode::get_exit_operation() +{ + if (exit_operation) + return exit_operation; + else if (operations.size() == 1) + return operations.begin()->second; + return NULL; +} + +/* Parameter Component Defines ============================ */ + +DEG_DEPSNODE_DEFINE(ParametersComponentDepsNode, DEPSNODE_TYPE_PARAMETERS, "Parameters Component"); +static DepsNodeFactoryImpl DNTI_PARAMETERS; + +/* Animation Component Defines ============================ */ + +DEG_DEPSNODE_DEFINE(AnimationComponentDepsNode, DEPSNODE_TYPE_ANIMATION, "Animation Component"); +static DepsNodeFactoryImpl DNTI_ANIMATION; + +/* Transform Component Defines ============================ */ + +DEG_DEPSNODE_DEFINE(TransformComponentDepsNode, DEPSNODE_TYPE_TRANSFORM, "Transform Component"); +static DepsNodeFactoryImpl DNTI_TRANSFORM; + +/* Proxy Component Defines ================================ */ + +DEG_DEPSNODE_DEFINE(ProxyComponentDepsNode, DEPSNODE_TYPE_PROXY, "Proxy Component"); +static DepsNodeFactoryImpl DNTI_PROXY; + +/* Geometry Component Defines ============================= */ + +DEG_DEPSNODE_DEFINE(GeometryComponentDepsNode, DEPSNODE_TYPE_GEOMETRY, "Geometry Component"); +static DepsNodeFactoryImpl DNTI_GEOMETRY; + +/* Sequencer Component Defines ============================ */ + +DEG_DEPSNODE_DEFINE(SequencerComponentDepsNode, DEPSNODE_TYPE_SEQUENCER, "Sequencer Component"); +static DepsNodeFactoryImpl DNTI_SEQUENCER; + +/* Pose Component ========================================= */ + +DEG_DEPSNODE_DEFINE(PoseComponentDepsNode, DEPSNODE_TYPE_EVAL_POSE, "Pose Eval Component"); +static DepsNodeFactoryImpl DNTI_EVAL_POSE; + +/* Bone Component ========================================= */ + +/* Initialize 'bone component' node - from pointer data given */ +void BoneComponentDepsNode::init(const ID *id, const string &subdata) +{ + /* generic component-node... */ + ComponentDepsNode::init(id, subdata); + + /* name of component comes is bone name */ + /* TODO(sergey): This sets name to an empty string because subdata is + * empty. Is it a bug? + */ + //this->name = subdata; + + /* bone-specific node data */ + Object *ob = (Object *)id; + this->pchan = BKE_pose_channel_find_name(ob->pose, subdata.c_str()); +} + +DEG_DEPSNODE_DEFINE(BoneComponentDepsNode, DEPSNODE_TYPE_BONE, "Bone Component"); +static DepsNodeFactoryImpl DNTI_BONE; + +/* Particles Component Defines ============================ */ + +DEG_DEPSNODE_DEFINE(ParticlesComponentDepsNode, DEPSNODE_TYPE_EVAL_PARTICLES, "Particles Component"); +static DepsNodeFactoryImpl DNTI_EVAL_PARTICLES; + +/* Shading Component Defines ============================ */ + +DEG_DEPSNODE_DEFINE(ShadingComponentDepsNode, DEPSNODE_TYPE_SHADING, "Shading Component"); +static DepsNodeFactoryImpl DNTI_SHADING; + + +/* Node Types Register =================================== */ + +void DEG_register_component_depsnodes() +{ + DEG_register_node_typeinfo(&DNTI_PARAMETERS); + DEG_register_node_typeinfo(&DNTI_PROXY); + DEG_register_node_typeinfo(&DNTI_ANIMATION); + DEG_register_node_typeinfo(&DNTI_TRANSFORM); + DEG_register_node_typeinfo(&DNTI_GEOMETRY); + DEG_register_node_typeinfo(&DNTI_SEQUENCER); + + DEG_register_node_typeinfo(&DNTI_EVAL_POSE); + DEG_register_node_typeinfo(&DNTI_BONE); + + DEG_register_node_typeinfo(&DNTI_EVAL_PARTICLES); + DEG_register_node_typeinfo(&DNTI_SHADING); +} diff --git a/source/blender/depsgraph/intern/depsnode_component.h b/source/blender/depsgraph/intern/depsnode_component.h new file mode 100644 index 00000000000..06a18b60abb --- /dev/null +++ b/source/blender/depsgraph/intern/depsnode_component.h @@ -0,0 +1,197 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __DEPSNODE_COMPONENT_H__ +#define __DEPSNODE_COMPONENT_H__ + +#include "depsnode.h" + +#include "depsgraph_util_hash.h" +#include "depsgraph_util_map.h" +#include "depsgraph_util_set.h" + +struct ID; +struct bPoseChannel; + +struct Depsgraph; +struct DepsgraphCopyContext; +struct EvaluationContext; +struct OperationDepsNode; +struct BoneComponentDepsNode; + + +/* ID Component - Base type for all components */ +struct ComponentDepsNode : public DepsNode { + /* Key used to look up operations within a component */ + struct OperationIDKey + { + eDepsOperation_Code opcode; + string name; + + + OperationIDKey() : + opcode(DEG_OPCODE_OPERATION), name("") + {} + OperationIDKey(eDepsOperation_Code opcode) : + opcode(opcode), name("") + {} + OperationIDKey(eDepsOperation_Code opcode, const string &name) : + opcode(opcode), name(name) + {} + + string identifier() const + { + char codebuf[5]; + sprintf(codebuf, "%d", opcode); + + return string("OperationIDKey(") + codebuf + ", " + name + ")"; + } + + bool operator==(const OperationIDKey &other) const + { + return (opcode == other.opcode) && (name == other.name); + } + }; + + /* XXX can't specialize std::hash for this purpose, because ComponentKey is a nested type ... + * http://stackoverflow.com/a/951245 + */ + struct operation_key_hash { + bool operator() (const OperationIDKey &key) const + { + return hash_combine(hash()(key.opcode), hash()(key.name)); + } + }; + + /* Typedef for container of operations */ + typedef unordered_map OperationMap; + + + ComponentDepsNode(); + ~ComponentDepsNode(); + + void init(const ID *id, const string &subdata); + void copy(DepsgraphCopyContext *dcc, const ComponentDepsNode *src); + + string identifier() const; + + /* Find an existing operation, will throw an assert() if it does not exist. */ + OperationDepsNode *find_operation(OperationIDKey key) const; + OperationDepsNode *find_operation(eDepsOperation_Code opcode, const string &name) const; + + /* Check operation exists and return it. */ + OperationDepsNode *has_operation(OperationIDKey key) const; + OperationDepsNode *has_operation(eDepsOperation_Code opcode, const string &name) const; + + /** + * Create a new node for representing an operation and add this to graph + * \warning If an existing node is found, it will be modified. This helps when node may + * have been partially created earlier (e.g. parent ref before parent item is added) + * + * \param type: Operation node type (corresponding to context/component that it operates in) + * \param optype: Role that operation plays within component (i.e. where in eval process) + * \param op: The operation to perform + * \param name: Identifier for operation - used to find/locate it again + */ + OperationDepsNode *add_operation(eDepsOperation_Type optype, DepsEvalOperationCb op, eDepsOperation_Code opcode, const string &name); + + void remove_operation(eDepsOperation_Code opcode, const string &name); + void clear_operations(); + + void tag_update(Depsgraph *graph); + + /* Evaluation Context Management .................. */ + + /* Initialize component's evaluation context used for the specified purpose */ + virtual bool eval_context_init(EvaluationContext * /*eval_ctx*/) { return false; } + /* Free data in component's evaluation context which is used for the specified purpose + * NOTE: this does not free the actual context in question + */ + virtual void eval_context_free(EvaluationContext * /*eval_ctx*/) {} + + OperationDepsNode *get_entry_operation(); + OperationDepsNode *get_exit_operation(); + + IDDepsNode *owner; + + OperationMap operations; /* inner nodes for this component */ + OperationDepsNode *entry_operation; + OperationDepsNode *exit_operation; + + // XXX: a poll() callback to check if component's first node can be started? +}; + +/* ---------------------------------------- */ + +struct ParametersComponentDepsNode : public ComponentDepsNode { + DEG_DEPSNODE_DECLARE; +}; + +struct AnimationComponentDepsNode : public ComponentDepsNode { + DEG_DEPSNODE_DECLARE; +}; + +struct TransformComponentDepsNode : public ComponentDepsNode { + DEG_DEPSNODE_DECLARE; +}; + +struct ProxyComponentDepsNode : public ComponentDepsNode { + DEG_DEPSNODE_DECLARE; +}; + +struct GeometryComponentDepsNode : public ComponentDepsNode { + DEG_DEPSNODE_DECLARE; +}; + +struct SequencerComponentDepsNode : public ComponentDepsNode { + DEG_DEPSNODE_DECLARE; +}; + +struct PoseComponentDepsNode : public ComponentDepsNode { + DEG_DEPSNODE_DECLARE; +}; + +/* Bone Component */ +struct BoneComponentDepsNode : public ComponentDepsNode { + void init(const ID *id, const string &subdata); + + struct bPoseChannel *pchan; /* the bone that this component represents */ + + DEG_DEPSNODE_DECLARE; +}; + +struct ParticlesComponentDepsNode : public ComponentDepsNode { + DEG_DEPSNODE_DECLARE; +}; + +struct ShadingComponentDepsNode : public ComponentDepsNode { + DEG_DEPSNODE_DECLARE; +}; + + +void DEG_register_component_depsnodes(); + +#endif /* __DEPSNODE_COMPONENT_H__ */ diff --git a/source/blender/depsgraph/intern/depsnode_opcodes.h b/source/blender/depsgraph/intern/depsnode_opcodes.h new file mode 100644 index 00000000000..48db2b79e66 --- /dev/null +++ b/source/blender/depsgraph/intern/depsnode_opcodes.h @@ -0,0 +1,141 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2014 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/* == OpCodes for OperationDepsNodes == + * This file defines all the "operation codes" (opcodes) used to identify + * common operation node types. The intention of these defines is to have + * a fast and reliable way of identifying the relevant nodes within a component + * without having to use fragile dynamic strings. + * + * This file is meant to be used like UI_icons.h. That is, before including + * the file, the host file must define the DEG_OPCODE(_label) macro, which + * is responsible for converting the define into whatever form is suitable. + * Therefore, it intentionally doesn't have header guards. + */ + + +/* Example macro define: */ +/* #define DEF_DEG_OPCODE(label) DEG_OPCODE_##label, */ + +/* Generic Operations ------------------------------ */ + +/* Placeholder for operations which don't need special mention */ +DEF_DEG_OPCODE(OPERATION) + +// XXX: Placeholder while porting depsgraph code +DEF_DEG_OPCODE(PLACEHOLDER) + +DEF_DEG_OPCODE(NOOP) + +/* Animation, Drivers, etc. ------------------------ */ + +/* NLA + Action */ +DEF_DEG_OPCODE(ANIMATION) + +/* Driver */ +DEF_DEG_OPCODE(DRIVER) + +/* Proxy Inherit? */ +//DEF_DEG_OPCODE(PROXY) + +/* Transform --------------------------------------- */ + +/* Transform entry point - local transforms only */ +DEF_DEG_OPCODE(TRANSFORM_LOCAL) + +/* Parenting */ +DEF_DEG_OPCODE(TRANSFORM_PARENT) + +/* Constraints */ +DEF_DEG_OPCODE(TRANSFORM_CONSTRAINTS) +//DEF_DEG_OPCODE(TRANSFORM_CONSTRAINTS_INIT) +//DEF_DEG_OPCODE(TRANSFORM_CONSTRAINT) +//DEF_DEG_OPCODE(TRANSFORM_CONSTRAINTS_DONE) + +/* Rigidbody Sim - Perform Sim */ +DEF_DEG_OPCODE(RIGIDBODY_REBUILD) +DEF_DEG_OPCODE(RIGIDBODY_SIM) + +/* Rigidbody Sim - Copy Results to Object */ +DEF_DEG_OPCODE(TRANSFORM_RIGIDBODY) + +/* Transform exitpoint */ +DEF_DEG_OPCODE(TRANSFORM_FINAL) + +/* XXX: ubereval is for temporary porting purposes only */ +DEF_DEG_OPCODE(OBJECT_UBEREVAL) + +/* Geometry ---------------------------------------- */ + +/* XXX: Placeholder - UberEval */ +DEF_DEG_OPCODE(GEOMETRY_UBEREVAL) + +/* Modifier */ +DEF_DEG_OPCODE(GEOMETRY_MODIFIER) + +/* Curve Objects - Path Calculation (used for path-following tools) */ +DEF_DEG_OPCODE(GEOMETRY_PATH) + +/* Pose -------------------------------------------- */ + +/* Init IK Trees, etc. */ +DEF_DEG_OPCODE(POSE_INIT) + +/* Free IK Trees + Compute Deform Matrices */ +DEF_DEG_OPCODE(POSE_DONE) + +/* IK/Spline Solvers */ +DEF_DEG_OPCODE(POSE_IK_SOLVER) +DEF_DEG_OPCODE(POSE_SPLINE_IK_SOLVER) + +/* Bone -------------------------------------------- */ + +/* Bone local transforms - Entrypoint */ +DEF_DEG_OPCODE(BONE_LOCAL) + +/* Pose-space conversion (includes parent + restpose) */ +DEF_DEG_OPCODE(BONE_POSE_PARENT) + +/* Constraints */ +DEF_DEG_OPCODE(BONE_CONSTRAINTS) +//DEF_DEG_OPCODE(BONE_CONSTRAINTS_INIT) +//DEF_DEG_OPCODE(BONE_CONSTRAINT) +//DEF_DEG_OPCODE(BONE_CONSTRAINTS_DONE) + +/* Bone transforms are ready + * - "READY" This (internal) noop is used to signal that all pre-IK operations are done. + * Its role is to help mediate situations where cyclic relations may otherwise form + * (i.e. one bone in chain targetting another in same chain) + * - "DONE" This noop is used to signal that the bone's final pose transform can be read by others + */ +// TODO: deform mats could get calculated in the final_transform ops... +DEF_DEG_OPCODE(BONE_READY) +DEF_DEG_OPCODE(BONE_DONE) + +/* Particles --------------------------------------- */ + +/* XXX: placeholder - Particle System eval */ +DEF_DEG_OPCODE(PSYS_EVAL) diff --git a/source/blender/depsgraph/intern/depsnode_operation.cc b/source/blender/depsgraph/intern/depsnode_operation.cc new file mode 100644 index 00000000000..de8755f7ae9 --- /dev/null +++ b/source/blender/depsgraph/intern/depsnode_operation.cc @@ -0,0 +1,100 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "MEM_guardedalloc.h" + +extern "C" { +#include "BLI_utildefines.h" +} /* extern "C" */ + +#include "depsnode_operation.h" /* own include */ +#include "depsnode_component.h" +#include "depsgraph.h" +#include "depsgraph_intern.h" + +/* ******************************************************************* */ +/* OpNode Identifiers Array - Exported to other depsgraph files too... */ + +/* identifiers for operations */ +const char *DEG_OPNAMES[] = { +#define DEF_DEG_OPCODE(label) #label, +#include "depsnode_opcodes.h" +#undef DEF_DEG_OPCODE + + "" +}; + +/* *********** */ +/* Inner Nodes */ + +OperationDepsNode::OperationDepsNode() : + eval_priority(0.0f), + flag(0) +{ +} + +OperationDepsNode::~OperationDepsNode() +{ +} + +string OperationDepsNode::identifier() const +{ + BLI_assert((opcode > 0) && (opcode < ARRAY_SIZE(DEG_OPNAMES))); + return string(DEG_OPNAMES[opcode]) + "(" + name + ")"; +} + +/* Full node identifier, including owner name. + * used for logging and debug prints. + */ +string OperationDepsNode::full_identifier() const +{ + string owner_str = ""; + if (owner->type == DEPSNODE_TYPE_BONE) { + owner_str = owner->owner->name + "." + owner->name; + } + else { + owner_str = owner->owner->name; + } + return owner_str + "." + identifier(); +} + +void OperationDepsNode::tag_update(Depsgraph *graph) +{ + if (flag & DEPSOP_FLAG_NEEDS_UPDATE) { + return; + } + /* Tag for update, but also note that this was the source of an update. */ + flag |= (DEPSOP_FLAG_NEEDS_UPDATE | DEPSOP_FLAG_DIRECTLY_MODIFIED); + graph->add_entry_tag(this); +} + +DEG_DEPSNODE_DEFINE(OperationDepsNode, DEPSNODE_TYPE_OPERATION, "Operation"); +static DepsNodeFactoryImpl DNTI_OPERATION; + +void DEG_register_operation_depsnodes() +{ + DEG_register_node_typeinfo(&DNTI_OPERATION); +} diff --git a/source/blender/depsgraph/intern/depsnode_operation.h b/source/blender/depsgraph/intern/depsnode_operation.h new file mode 100644 index 00000000000..2b70ff0a8dc --- /dev/null +++ b/source/blender/depsgraph/intern/depsnode_operation.h @@ -0,0 +1,86 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Original Author: Joshua Leung + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __DEPSNODE_OPERATION_H__ +#define __DEPSNODE_OPERATION_H__ + +#include "depsnode.h" + +struct ID; + +struct Depsgraph; +struct DepsgraphCopyContext; + +/* Flags for Depsgraph Nodes */ +typedef enum eDepsOperation_Flag { + /* node needs to be updated */ + DEPSOP_FLAG_NEEDS_UPDATE = (1 << 0), + + /* node was directly modified, causing need for update */ + /* XXX: intention is to make it easier to tell when we just need to take subgraphs */ + DEPSOP_FLAG_DIRECTLY_MODIFIED = (1 << 1), + + /* Operation is evaluated using CPython; has GIL and security implications... */ + DEPSOP_FLAG_USES_PYTHON = (1 << 2), +} eDepsOperation_Flag; + +/* Atomic Operation - Base type for all operations */ +struct OperationDepsNode : public DepsNode { + + + OperationDepsNode(); + ~OperationDepsNode(); + + string identifier() const; + string full_identifier() const; + + void tag_update(Depsgraph *graph); + + bool is_noop() const { return (bool)evaluate == false; } + + OperationDepsNode *get_entry_operation() { return this; } + OperationDepsNode *get_exit_operation() { return this; } + + ComponentDepsNode *owner; /* component that contains the operation */ + + DepsEvalOperationCb evaluate; /* callback for operation */ + + + uint32_t num_links_pending; /* how many inlinks are we still waiting on before we can be evaluated... */ + float eval_priority; + bool scheduled; + + short optype; /* (eDepsOperation_Type) stage of evaluation */ + int opcode; /* (eDepsOperation_Code) identifier for the operation being performed */ + + int flag; /* (eDepsOperation_Flag) extra settings affecting evaluation */ + + DEG_DEPSNODE_DECLARE; +}; + +void DEG_register_operation_depsnodes(); + +#endif /* __DEPSNODE_OPERATION_H__ */ diff --git a/source/blender/depsgraph/util/depsgraph_util_cycle.cc b/source/blender/depsgraph/util/depsgraph_util_cycle.cc new file mode 100644 index 00000000000..5a171d190cd --- /dev/null +++ b/source/blender/depsgraph/util/depsgraph_util_cycle.cc @@ -0,0 +1,134 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Sergey Sharybin + */ + +#include +#include +#include + +extern "C" { +#include "BLI_utildefines.h" + +#include "DNA_ID.h" + +#include "RNA_access.h" +#include "RNA_types.h" +} + +#include "depsgraph_util_cycle.h" +#include "depsgraph.h" +#include "depsnode.h" +#include "depsnode_component.h" +#include "depsnode_operation.h" + +struct StackEntry { + OperationDepsNode *node; + StackEntry *from; + DepsRelation *via_relation; +}; + +void deg_graph_detect_cycles(Depsgraph *graph) +{ + /* Not is not visited at all during traversal. */ + const int NODE_NOT_VISITED = 0; + /* Node has been visited during traversal and not in current stack. */ + const int NODE_VISITED = 1; + /* Node has been visited during traversal and is in current stack. */ + const int NODE_IN_STACK = 2; + + std::stack traversal_stack; + for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin(); + it_op != graph->operations.end(); + ++it_op) + { + OperationDepsNode *node = *it_op; + bool has_inlinks = false; + for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin(); + it_rel != node->inlinks.end(); + ++it_rel) + { + DepsRelation *rel = *it_rel; + if (rel->from->type == DEPSNODE_TYPE_OPERATION) { + has_inlinks = true; + } + } + if (has_inlinks == false) { + StackEntry entry; + entry.node = node; + entry.from = NULL; + entry.via_relation = NULL; + traversal_stack.push(entry); + node->done = NODE_IN_STACK; + } + else { + node->done = NODE_NOT_VISITED; + } + } + + while (!traversal_stack.empty()) { + StackEntry &entry = traversal_stack.top(); + OperationDepsNode *node = entry.node; + bool all_child_traversed = true; + for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin(); + it_rel != node->outlinks.end(); + ++it_rel) + { + DepsRelation *rel = *it_rel; + if (rel->to->type == DEPSNODE_TYPE_OPERATION) { + OperationDepsNode *to = (OperationDepsNode *)rel->to; + if (to->done == NODE_IN_STACK) { + printf("Dependency cycle detected:\n"); + printf(" '%s' depends on '%s' through '%s'\n", + to->full_identifier().c_str(), + node->full_identifier().c_str(), + rel->name); + + StackEntry *current = &entry; + while (current->node != to) { + BLI_assert(current != NULL); + printf(" '%s' depends on '%s' through '%s'\n", + current->node->full_identifier().c_str(), + current->from->node->full_identifier().c_str(), + current->via_relation->name); + current = current->from; + } + /* TODO(sergey): So called roussian rlette cycle solver. */ + rel->flag |= DEPSREL_FLAG_CYCLIC; + } + else if (to->done == NODE_NOT_VISITED) { + StackEntry new_entry; + new_entry.node = to; + new_entry.from = &entry; + new_entry.via_relation = rel; + traversal_stack.push(new_entry); + to->done = NODE_IN_STACK; + all_child_traversed = false; + break; + } + } + } + if (all_child_traversed) { + node->done = NODE_VISITED; + traversal_stack.pop(); + } + } +} diff --git a/source/blender/depsgraph/util/depsgraph_util_cycle.h b/source/blender/depsgraph/util/depsgraph_util_cycle.h new file mode 100644 index 00000000000..f827d85c16a --- /dev/null +++ b/source/blender/depsgraph/util/depsgraph_util_cycle.h @@ -0,0 +1,31 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Sergey Sharybin + */ + +#ifndef __DEPSGRAPH_UTIL_CYCLE_H__ +#define __DEPSGRAPH_UTIL_CYCLE_H__ + +struct Depsgraph; + +void deg_graph_detect_cycles(Depsgraph *graph); + +#endif /* __DEPSGRAPH_UTIL_CYCLE_H__ */ diff --git a/source/blender/depsgraph/util/depsgraph_util_function.h b/source/blender/depsgraph/util/depsgraph_util_function.h new file mode 100644 index 00000000000..f62efd76267 --- /dev/null +++ b/source/blender/depsgraph/util/depsgraph_util_function.h @@ -0,0 +1,106 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2014 Blender Foundation. + * All rights reserved. + * + * Original Author: Lukas Toenne + * Contributor(s): + */ + +#ifndef __DEPSGRAPH_UTIL_FUNCTION_H__ +#define __DEPSGRAPH_UTIL_FUNCTION_H__ + +#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800) + +#include + +using std::function; +using namespace std::placeholders; +#define function_bind std::bind + +#elif defined(HAVE_BOOST_FUNCTION_BINDINGS) + +#include +#include + +using boost::function; +#define function_bind boost::bind + +#else + +#pragma message("No available function binding implementation. Using stub instead, disabling new depsgraph") + +#ifndef WITH_LEGACY_DEPSGRAPH +# error "Unable to build new depsgraph and legacy one is disabled." +#endif + +#define DISABLE_NEW_DEPSGRAPH + +#include + +template +class function { +public: + function() {}; + function(void *) {} + operator bool() const { return false; } + bool operator== (void*) { return false; } + + template + void operator() (T1) { + BLI_assert(!"Should not be used"); + } +}; + +class Wrap { +public: + Wrap() {} + template + Wrap(T /*arg*/) {} +}; + +template +void *function_bind(T func, + Wrap arg1 = Wrap(), + Wrap arg2 = Wrap(), + Wrap arg3 = Wrap(), + Wrap arg4 = Wrap(), + Wrap arg5 = Wrap(), + Wrap arg6 = Wrap(), + Wrap arg7 = Wrap()) +{ + BLI_assert(!"Should not be used"); + (void)func; + (void)arg1; + (void)arg2; + (void)arg3; + (void)arg4; + (void)arg5; + (void)arg6; + (void)arg7; + return NULL; +} + +#define _1 Wrap() +#define _2 Wrap() +#define _3 Wrap() +#define _4 Wrap() + +#endif + +#endif /* __DEPSGRAPH_UTIL_SET_H__ */ diff --git a/source/blender/depsgraph/util/depsgraph_util_hash.h b/source/blender/depsgraph/util/depsgraph_util_hash.h new file mode 100644 index 00000000000..0f5a85b3526 --- /dev/null +++ b/source/blender/depsgraph/util/depsgraph_util_hash.h @@ -0,0 +1,66 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2014 Blender Foundation. + * All rights reserved. + * + * Original Author: Brecht van Lommel + * Contributor(s): Lukas Toenne + */ + +#ifndef __DEPSGRAPH_UTIL_HASH_H__ +#define __DEPSGRAPH_UTIL_HASH_H__ + +#if defined(DEG_NO_UNORDERED_MAP) +# define DEG_HASH_NAMESPACE_BEGIN +# define DEG_HASH_NAMESPACE_END +#endif + +#if defined(DEG_TR1_UNORDERED_MAP) +# include +# define DEG_HASH_NAMESPACE_BEGIN namespace std { namespace tr1 { +# define DEG_HASH_NAMESPACE_END } } +using std::tr1::hash; +#endif + +#if defined(DEG_STD_UNORDERED_MAP) +# include +# define DEG_HASH_NAMESPACE_BEGIN namespace std { +# define DEG_HASH_NAMESPACE_END } +using std::hash; +#endif + +#if defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) +# include +# define DEG_HASH_NAMESPACE_BEGIN namespace std { namespace tr1 { +# define DEG_HASH_NAMESPACE_END } } +using std::tr1::hash; +#endif + +#if !defined(DEG_NO_UNORDERED_MAP) && !defined(DEG_TR1_UNORDERED_MAP) && \ + !defined(DEG_STD_UNORDERED_MAP) && !defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT +# error One of: DEG_NO_UNORDERED_MAP, DEG_TR1_UNORDERED_MAP,\ + DEG_STD_UNORDERED_MAP, DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT +#endif + +/* XXX this might require 2 different variants for sizeof(size_t) (32 vs 64 bit) */ +inline size_t hash_combine(size_t hash_a, size_t hash_b) +{ + return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2)); +} + +#endif /* __DEPSGRAPH_UTIL_HASH_H__ */ diff --git a/source/blender/depsgraph/util/depsgraph_util_map.h b/source/blender/depsgraph/util/depsgraph_util_map.h new file mode 100644 index 00000000000..2951641431b --- /dev/null +++ b/source/blender/depsgraph/util/depsgraph_util_map.h @@ -0,0 +1,61 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2014 Blender Foundation. + * All rights reserved. + * + * Original Author: Brecht van Lommel + * Contributor(s): Lukas Toenne + */ + +#ifndef __DEPSGRAPH_UTIL_MAP_H__ +#define __DEPSGRAPH_UTIL_MAP_H__ + +#include + +#include "depsgraph_util_hash.h" + +using std::map; +using std::pair; + +#if defined(DEG_NO_UNORDERED_MAP) +# include +typedef std::map unordered_map; +#endif + +#if defined(DEG_TR1_UNORDERED_MAP) +# include +using std::tr1::unordered_map; +#endif + +#if defined(DEG_STD_UNORDERED_MAP) +# include +using std::unordered_map; +#endif + +#if defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) +# include +using std::tr1::unordered_map; +#endif + +#if !defined(DEG_NO_UNORDERED_MAP) && !defined(DEG_TR1_UNORDERED_MAP) && \ + !defined(DEG_STD_UNORDERED_MAP) && !defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT +# error One of: DEG_NO_UNORDERED_MAP, DEG_TR1_UNORDERED_MAP,\ + DEG_STD_UNORDERED_MAP, DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT +#endif + +#endif /* __DEPSGRAPH_UTIL_MAP_H__ */ diff --git a/source/blender/depsgraph/util/depsgraph_util_pchanmap.cc b/source/blender/depsgraph/util/depsgraph_util_pchanmap.cc new file mode 100644 index 00000000000..36bd72108ed --- /dev/null +++ b/source/blender/depsgraph/util/depsgraph_util_pchanmap.cc @@ -0,0 +1,132 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015 Blender Foundation. + * All rights reserved. + * + * Original Author: Sergey Sharybin + * Contributor(s): Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "depsgraph_util_pchanmap.h" + +#include +#include + +extern "C" { +#include "BLI_utildefines.h" +#include "BLI_ghash.h" +} + +static void free_rootpchanmap_valueset(void *val) +{ + /* Just need to free the set itself - the names stored are all references. */ + GSet *values = (GSet *)val; + BLI_gset_free(values, NULL); +} + +RootPChanMap::RootPChanMap() +{ + /* Just create empty map. */ + m_map = BLI_ghash_str_new("RootPChanMap"); +} + +RootPChanMap::~RootPChanMap() +{ + /* Free the map, and all the value sets. */ + BLI_ghash_free(m_map, NULL, free_rootpchanmap_valueset); +} + +/* Debug contents of map */ +void RootPChanMap::print_debug() +{ + GHashIterator it1; + GSetIterator it2; + + printf("Root PChan Map:\n"); + GHASH_ITER(it1, m_map) { + const char *item = (const char *)BLI_ghashIterator_getKey(&it1); + GSet *values = (GSet *)BLI_ghashIterator_getValue(&it1); + + printf(" %s : { ", item); + GSET_ITER(it2, values) { + const char *val = (const char *)BLI_gsetIterator_getKey(&it2); + printf("%s, ", val); + } + printf("}\n"); + } +} + +/* Add a mapping. */ +void RootPChanMap::add_bone(const char *bone, const char *root) +{ + if (BLI_ghash_haskey(m_map, bone)) { + /* Add new entry, but only add the root if it doesn't already + * exist in there. + */ + GSet *values = (GSet *)BLI_ghash_lookup(m_map, bone); + BLI_gset_add(values, (void *)root); + } + else { + /* Create new set and mapping. */ + GSet *values = BLI_gset_new(BLI_ghashutil_strhash_p, + BLI_ghashutil_strcmp, + "RootPChanMap Value Set"); + BLI_ghash_insert(m_map, (void *)bone, (void *)values); + + /* Add new entry now. */ + BLI_gset_insert(values, (void *)root); + } +} + +/* Check if there's a common root bone between two bones. */ +bool RootPChanMap::has_common_root(const char *bone1, const char *bone2) +{ + /* Ensure that both are in the map... */ + if (BLI_ghash_haskey(m_map, bone1) == false) { + //fprintf("RootPChanMap: bone1 '%s' not found (%s => %s)\n", bone1, bone1, bone2); + //print_debug(); + return false; + } + + if (BLI_ghash_haskey(m_map, bone2) == false) { + //fprintf("RootPChanMap: bone2 '%s' not found (%s => %s)\n", bone2, bone1, bone2); + //print_debug(); + return false; + } + + GSet *bone1_roots = (GSet *)BLI_ghash_lookup(m_map, (void *)bone1); + GSet *bone2_roots = (GSet *)BLI_ghash_lookup(m_map, (void *)bone2); + + GSetIterator it1, it2; + GSET_ITER(it1, bone1_roots) { + GSET_ITER(it2, bone2_roots) { + const char *v1 = (const char *)BLI_gsetIterator_getKey(&it1); + const char *v2 = (const char *)BLI_gsetIterator_getKey(&it2); + + if (strcmp(v1, v2) == 0) { + //fprintf("RootPchanMap: %s in common for %s => %s\n", v1, bone1, bone2); + return true; + } + } + } + + //fprintf("RootPChanMap: No common root found (%s => %s)\n", bone1, bone2); + return false; +} diff --git a/source/blender/depsgraph/util/depsgraph_util_pchanmap.h b/source/blender/depsgraph/util/depsgraph_util_pchanmap.h new file mode 100644 index 00000000000..5d27d84c0da --- /dev/null +++ b/source/blender/depsgraph/util/depsgraph_util_pchanmap.h @@ -0,0 +1,55 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015 Blender Foundation. + * All rights reserved. + * + * Original Author: Sergey Sharybin + * Contributor(s): Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef ___DEPSGRAPH_UTIL_PCHANMAP_H__ +#define ___DEPSGRAPH_UTIL_PCHANMAP_H__ + +struct RootPChanMap { + /* ctor and dtor - Create and free the internal map respectively. */ + RootPChanMap(); + ~RootPChanMap(); + + /* Debug contents of map. */ + void print_debug(); + + /* Add a mapping. */ + void add_bone(const char *bone, const char *root); + + /* Check if there's a common root bone between two bones. */ + bool has_common_root(const char *bone1, const char *bone2); + +private: + /* The actual map: + * - Keys are "strings" (const char *) - not dynamically allocated. + * - Values are "sets" (const char *) - not dynamically allocated. + * + * We don't use the C++ maps here, as it's more convenient to use + * Blender's GHash and be able to compare by-value instead of by-ref. + */ + struct GHash *m_map; +}; + +#endif /* __DEPSGRAPH_UTIL_PCHANMAP_H__ */ diff --git a/source/blender/depsgraph/util/depsgraph_util_set.h b/source/blender/depsgraph/util/depsgraph_util_set.h new file mode 100644 index 00000000000..09fa5313920 --- /dev/null +++ b/source/blender/depsgraph/util/depsgraph_util_set.h @@ -0,0 +1,60 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2014 Blender Foundation. + * All rights reserved. + * + * Original Author: Brecht van Lommel + * Contributor(s): Lukas Toenne + */ + +#ifndef __DEPSGRAPH_UTIL_SET_H__ +#define __DEPSGRAPH_UTIL_SET_H__ + +#include + +#include "depsgraph_util_hash.h" + +using std::set; + +#if defined(DEG_NO_UNORDERED_MAP) +# include +typedef std::set unordered_set; +#endif + +#if defined(DEG_TR1_UNORDERED_MAP) +# include +using std::tr1::unordered_set; +#endif + +#if defined(DEG_STD_UNORDERED_MAP) +# include +using std::unordered_set; +#endif + +#if defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) +# include +using std::tr1::unordered_set; +#endif + +#if !defined(DEG_NO_UNORDERED_MAP) && !defined(DEG_TR1_UNORDERED_MAP) && \ + !defined(DEG_STD_UNORDERED_MAP) && !defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT +# error One of: DEG_NO_UNORDERED_MAP, DEG_TR1_UNORDERED_MAP,\ + DEG_STD_UNORDERED_MAP, DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT +#endif + +#endif /* __DEPSGRAPH_UTIL_SET_H__ */ diff --git a/source/blender/depsgraph/util/depsgraph_util_transitive.cc b/source/blender/depsgraph/util/depsgraph_util_transitive.cc new file mode 100644 index 00000000000..9411d013c44 --- /dev/null +++ b/source/blender/depsgraph/util/depsgraph_util_transitive.cc @@ -0,0 +1,133 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Lukas Toenne + * Sergey Sharybin, + */ + +extern "C" { +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" + +#include "DNA_ID.h" + +#include "RNA_access.h" +#include "RNA_types.h" +} + +#include "depsgraph_util_transitive.h" +#include "depsgraph.h" +#include "depsnode.h" +#include "depsnode_component.h" +#include "depsnode_operation.h" + +/* -------------------------------------------------- */ + +/* Performs a transitive reduction to remove redundant relations. + * http://en.wikipedia.org/wiki/Transitive_reduction + * + * XXX The current implementation is somewhat naive and has O(V*E) worst case + * runtime. + * A more optimized algorithm can be implemented later, e.g. + * + * http://www.sciencedirect.com/science/article/pii/0304397588900321/pdf?md5=3391e309b708b6f9cdedcd08f84f4afc&pid=1-s2.0-0304397588900321-main.pdf + * + * Care has to be taken to make sure the algorithm can handle the cyclic case + * too! (unless we can to prevent this case early on). + */ + +enum { + OP_VISITED = 1, + OP_REACHABLE = 2, +}; + +static void deg_graph_tag_paths_recursive(DepsNode *node) +{ + if (node->done & OP_VISITED) + return; + node->done |= OP_VISITED; + + for (OperationDepsNode::Relations::const_iterator it = node->inlinks.begin(); + it != node->inlinks.end(); + ++it) + { + DepsRelation *rel = *it; + + deg_graph_tag_paths_recursive(rel->from); + /* Do this only in inlinks loop, so the target node does not get + * flagged. + */ + rel->from->done |= OP_REACHABLE; + } +} + +void deg_graph_transitive_reduction(Depsgraph *graph) +{ + for (Depsgraph::OperationNodes::const_iterator it_target = graph->operations.begin(); + it_target != graph->operations.end(); + ++it_target) + { + OperationDepsNode *target = *it_target; + + /* Clear tags. */ + for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin(); + it != graph->operations.end(); + ++it) + { + OperationDepsNode *node = *it; + node->done = 0; + } + + /* mark nodes from which we can reach the target + * start with children, so the target node and direct children are not + * flagged. + */ + target->done |= OP_VISITED; + for (OperationDepsNode::Relations::const_iterator it = target->inlinks.begin(); + it != target->inlinks.end(); + ++it) + { + DepsRelation *rel = *it; + + deg_graph_tag_paths_recursive(rel->from); + } + + /* Eemove redundant paths to the target. */ + for (DepsNode::Relations::const_iterator it_rel = target->inlinks.begin(); + it_rel != target->inlinks.end(); + ) + { + DepsRelation *rel = *it_rel; + /* Increment in advance, so we can safely remove the relation. */ + ++it_rel; + + if (rel->from->type == DEPSNODE_TYPE_TIMESOURCE) { + /* HACK: time source nodes don't get "done" flag set/cleared. */ + /* TODO: there will be other types in future, so iterators above + * need modifying. + */ + } + else if (rel->from->done & OP_REACHABLE) { + OBJECT_GUARDED_DELETE(rel, DepsRelation); + } + } + } +} diff --git a/source/blender/depsgraph/util/depsgraph_util_transitive.h b/source/blender/depsgraph/util/depsgraph_util_transitive.h new file mode 100644 index 00000000000..8995c18eca0 --- /dev/null +++ b/source/blender/depsgraph/util/depsgraph_util_transitive.h @@ -0,0 +1,32 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Lukas Toenne + * Sergey Sharybin, + */ + +#ifndef __DEPSGRAPH_UTIL_TRANSITIVE_H__ +#define __DEPSGRAPH_UTIL_TRANSITIVE_H__ + +struct Depsgraph; + +void deg_graph_transitive_reduction(Depsgraph *graph); + +#endif /* __DEPSGRAPH_UTIL_TRANSITIVE_H__ */ diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index ab69e67361d..d8d29d63686 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -30,6 +30,7 @@ set(INC ../../makesrna ../../render/extern/include ../../windowmanager + ../../depsgraph ../../../../intern/guardedalloc ../../../../intern/glew-mx ../../../../intern/smoke/extern diff --git a/source/blender/editors/space_view3d/SConscript b/source/blender/editors/space_view3d/SConscript index a21da940906..78f24948070 100644 --- a/source/blender/editors/space_view3d/SConscript +++ b/source/blender/editors/space_view3d/SConscript @@ -48,6 +48,7 @@ incs = [ '../../makesrna', '../../render/extern/include', '../../windowmanager', + '../../depsgraph', ] if env['WITH_BF_PYTHON']: diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index bd070ea25fb..096d9e8a40a 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -74,6 +74,8 @@ # include "BPY_extern.h" #endif +#include "DEG_depsgraph.h" + #include "view3d_intern.h" /* own include */ /* ******************** manage regions ********************* */ @@ -931,7 +933,8 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN (ob && (ob->mode == OB_MODE_TEXTURE_PAINT)) || (v3d->drawtype == OB_TEXTURE && (scene->gm.matmode == GAME_MAT_GLSL || - BKE_scene_use_new_shading_nodes(scene)))) + BKE_scene_use_new_shading_nodes(scene))) || + !DEG_depsgraph_use_legacy()) { ED_region_tag_redraw(ar); } @@ -954,7 +957,8 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN switch (wmn->data) { case ND_LIGHTING: if ((v3d->drawtype == OB_MATERIAL) || - (v3d->drawtype == OB_TEXTURE && (scene->gm.matmode == GAME_MAT_GLSL))) + (v3d->drawtype == OB_TEXTURE && (scene->gm.matmode == GAME_MAT_GLSL)) || + !DEG_depsgraph_use_legacy()) { ED_region_tag_redraw(ar); } diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index 0c360474b78..0bc38f81dd7 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -55,6 +55,10 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() +if(WITH_LEGACY_DEPSGRAPH) + add_definitions(-DWITH_LEGACY_DEPSGRAPH) +endif() + add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_transform "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/transform/SConscript b/source/blender/editors/transform/SConscript index e249856b747..1a2e9ab074a 100644 --- a/source/blender/editors/transform/SConscript +++ b/source/blender/editors/transform/SConscript @@ -50,4 +50,7 @@ defs = env['BF_GL_DEFINITIONS'] if env['WITH_BF_INTERNATIONAL']: defs.append('WITH_INTERNATIONAL') +if env['WITH_BF_LEGACY_DEPSGRAPH']: + defs.append('WITH_LEGACY_DEPSGRAPH') + env.BlenderLib ( 'bf_editors_transform', sources, incs, defs, libtype=['core'], priority=[40] ) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 9efbc1bc549..4da3fa8a959 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5362,7 +5362,9 @@ static void set_trans_object_base_flags(TransInfo *t) } /* all recalc flags get flushed to all layers, so a layer flip later on works fine */ +#ifdef WITH_LEGACY_DEPSGRAPH DAG_scene_flush_update(G.main, t->scene, -1, 0); +#endif /* and we store them temporal in base (only used for transform code) */ /* this because after doing updates, the object->recalc is cleared */ @@ -5439,7 +5441,9 @@ static int count_proportional_objects(TransInfo *t) /* all recalc flags get flushed to all layers, so a layer flip later on works fine */ DAG_scene_relations_update(G.main, t->scene); +#ifdef WITH_LEGACY_DEPSGRAPH DAG_scene_flush_update(G.main, t->scene, -1, 0); +#endif /* and we store them temporal in base (only used for transform code) */ /* this because after doing updates, the object->recalc is cleared */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index a40b8aff08e..fe346eecec5 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1401,6 +1401,7 @@ typedef struct Scene { void *fps_info; /* (runtime) info/cache used for presenting playback framerate info to the user */ /* none of the dependency graph vars is mean to be saved */ + struct Depsgraph *depsgraph; struct DagForest *theDag; short dagflags; short recalc; /* recalc = counterpart of ob->recalc */ diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript index e366c9bbe2b..f8eb2e1807c 100644 --- a/source/blender/makesrna/SConscript +++ b/source/blender/makesrna/SConscript @@ -47,6 +47,7 @@ incs = [ '../blenkernel', '../blenlib', '../bmesh', + '../depsgraph', '../editors/include', '../gpu', '../ikplugin', diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 69c5955c454..e878e0877d2 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -45,6 +45,7 @@ set(DEFSRC rna_context.c rna_controller.c rna_curve.c + rna_depsgraph.c rna_dynamicpaint.c rna_fcurve.c rna_fluidsim.c @@ -307,6 +308,7 @@ blender_include_dirs( ../../blenlib ../../bmesh ../../blenfont + ../../depsgraph ../../gpu ../../imbuf ../../ikplugin diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript index 3d190fc6a13..afa4ab3a67d 100644 --- a/source/blender/makesrna/intern/SConscript +++ b/source/blender/makesrna/intern/SConscript @@ -66,6 +66,7 @@ incs = [ '../../blenkernel', '../../blenlib', '../../bmesh', + '../../depsgraph', '../../editors/include', '../../gpu', '../../ikplugin', diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 829a70ef166..dfd0f13ec1a 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -3293,6 +3293,7 @@ static RNAProcessItem PROCESS_ITEMS[] = { {"rna_context.c", NULL, RNA_def_context}, {"rna_controller.c", "rna_controller_api.c", RNA_def_controller}, {"rna_curve.c", "rna_curve_api.c", RNA_def_curve}, + {"rna_depsgraph.c", NULL, RNA_def_depsgraph}, {"rna_dynamicpaint.c", NULL, RNA_def_dynamic_paint}, {"rna_fcurve.c", "rna_fcurve_api.c", RNA_def_fcurve}, {"rna_fluidsim.c", NULL, RNA_def_fluidsim}, diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c new file mode 100644 index 00000000000..8ac1e2acc60 --- /dev/null +++ b/source/blender/makesrna/intern/rna_depsgraph.c @@ -0,0 +1,112 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Foundation (2014). + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/makesrna/intern/rna_depsgraph.c + * \ingroup RNA + */ + +#include + +#include "BLI_utildefines.h" +#include "BLI_path_util.h" + +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" + +#include "DEG_depsgraph.h" + +#include "BKE_depsgraph.h" + +#ifdef RNA_RUNTIME + +#include "BKE_report.h" + +#include "DEG_depsgraph_debug.h" + +static void rna_Depsgraph_debug_graphviz(Depsgraph *graph, const char *filename) +{ + FILE *f = fopen(filename, "w"); + if (f == NULL) + return; + + DEG_debug_graphviz(graph, f, "Depsgraph", false); + + fclose(f); +} + +static void rna_Depsgraph_debug_rebuild(Depsgraph *UNUSED(graph), Main *bmain) +{ + Scene *sce; + DAG_relations_tag_update(bmain); + for (sce = bmain->scene.first; sce; sce = sce->id.next) { + DAG_scene_relations_rebuild(bmain, sce); + DEG_graph_on_visible_update(bmain, sce); + } +} + +static void rna_Depsgraph_debug_stats(Depsgraph *graph, ReportList *reports) +{ + size_t outer, ops, rels; + + DEG_stats_simple(graph, &outer, &ops, &rels); + + // XXX: report doesn't seem to work + printf("Approx %lu Operations, %lu Relations, %lu Outer Nodes\n", + ops, rels, outer); + + BKE_reportf(reports, RPT_WARNING, "Approx. %lu Operations, %lu Relations, %lu Outer Nodes", + ops, rels, outer); +} + +#else + +static void rna_def_depsgraph(BlenderRNA *brna) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + srna = RNA_def_struct(brna, "Depsgraph", NULL); + RNA_def_struct_ui_text(srna, "Dependency Graph", ""); + + func = RNA_def_function(srna, "debug_graphviz", "rna_Depsgraph_debug_graphviz"); + parm = RNA_def_string_file_path(func, "filename", NULL, FILE_MAX, "File Name", + "File in which to store graphviz debug output"); + RNA_def_property_flag(parm, PROP_REQUIRED); + + func = RNA_def_function(srna, "debug_rebuild", "rna_Depsgraph_debug_rebuild"); + RNA_def_function_flag(func, FUNC_USE_MAIN); + RNA_def_property_flag(parm, PROP_REQUIRED); + + func = RNA_def_function(srna, "debug_stats", "rna_Depsgraph_debug_stats"); + RNA_def_function_ui_description(func, "Report the number of elements in the Dependency Graph"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); +} + +void RNA_def_depsgraph(BlenderRNA *brna) +{ + rna_def_depsgraph(brna); +} + +#endif diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 01303225f38..eab14be9085 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -140,6 +140,7 @@ void RNA_def_constraint(struct BlenderRNA *brna); void RNA_def_context(struct BlenderRNA *brna); void RNA_def_controller(struct BlenderRNA *brna); void RNA_def_curve(struct BlenderRNA *brna); +void RNA_def_depsgraph(struct BlenderRNA *brna); void RNA_def_dynamic_paint(struct BlenderRNA *brna); void RNA_def_fluidsim(struct BlenderRNA *brna); void RNA_def_fcurve(struct BlenderRNA *brna); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 9fe44511c8c..2a3688c49f2 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -87,6 +87,8 @@ static EnumPropertyItem space_items[] = { #include "MEM_guardedalloc.h" +#include "DEG_depsgraph.h" + /* Convert a given matrix from a space to another (using the object and/or a bone as reference). */ static void rna_Scene_mat_convert_space(Object *ob, ReportList *reports, bPoseChannel *pchan, float *mat, float *mat_ret, int from, int to) @@ -191,8 +193,8 @@ static void dupli_render_particle_set(Scene *scene, Object *ob, int level, int e static void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce, int settings) { bool for_render = (settings == DAG_EVAL_RENDER); - EvaluationContext eval_ctx = {0}; - eval_ctx.mode = settings; + EvaluationContext eval_ctx; + DEG_evaluation_context_init(&eval_ctx, settings); if (!(ob->transflag & OB_DUPLI)) { BKE_report(reports, RPT_ERROR, "Object does not have duplis"); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index d7dfa827493..00114d1125c 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -6525,6 +6525,11 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_struct_type(prop, "ColorManagedSequencerColorspaceSettings"); RNA_def_property_ui_text(prop, "Sequencer Color Space Settings", "Settings of color space sequencer is working in"); + /* Dependency Graph */ + prop = RNA_def_property(srna, "depsgraph", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "Depsgraph"); + RNA_def_property_ui_text(prop, "Dependency Graph", "Dependencies in the scene data"); + /* Nestled Data */ /* *** Non-Animated *** */ RNA_define_animate_sdna(false); diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 1de3fc9eac0..fde0c773ef0 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -30,6 +30,7 @@ set(INC ../blenkernel ../blenlib ../blenfont + ../depsgraph ../makesdna ../makesrna ../bmesh diff --git a/source/blender/modifiers/SConscript b/source/blender/modifiers/SConscript index b4c8299250e..a7d17609ab7 100644 --- a/source/blender/modifiers/SConscript +++ b/source/blender/modifiers/SConscript @@ -40,6 +40,7 @@ incs = [ '../include', '../blenlib', '../blenfont', + '../depsgraph', '../makesdna', '../makesrna', '../blenkernel', diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 52a47c3e041..9ce31cebb66 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -115,6 +115,18 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + ArmatureModifierData *amd = (ArmatureModifierData *)md; + if (amd->object != NULL) { + DEG_add_object_relation(node, amd->object, DEG_OB_COMP_EVAL_POSE, "Armature Modifier"); + } +} + static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], @@ -208,6 +220,7 @@ ModifierTypeInfo modifierType_Armature = { /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 44660b15c3c..efb77f73ec9 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -135,6 +135,28 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *scene, + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + ArrayModifierData *amd = (ArrayModifierData *)md; + if (amd->start_cap != NULL) { + DEG_add_object_relation(node, amd->start_cap, DEG_OB_COMP_TRANSFORM, "Hook Modifier Start Cap"); + } + if (amd->end_cap != NULL) { + DEG_add_object_relation(node, amd->end_cap, DEG_OB_COMP_TRANSFORM, "Hook Modifier End Cap"); + } + if (amd->curve_ob) { + DEG_add_object_relation(node, amd->end_cap, DEG_OB_COMP_GEOMETRY, "Hook Modifier Curve"); + DEG_add_special_eval_flag(scene->depsgraph, &amd->curve_ob->id, DAG_EVAL_NEED_CURVE_PATH); + } + if (amd->offset_ob != NULL) { + DEG_add_object_relation(node, amd->offset_ob, DEG_OB_COMP_TRANSFORM, "Hook Modifier Offset"); + } +} + static float vertarray_size(const MVert *mvert, int numVerts, int axis) { int i; @@ -771,6 +793,7 @@ ModifierTypeInfo modifierType_Array = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index 1dca18dce37..c2b5a29939f 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -213,6 +213,7 @@ ModifierTypeInfo modifierType_Bevel = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index ee3bc7140a8..eb54a3c4e9c 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -89,6 +89,21 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *ob, + struct DepsNodeHandle *node) +{ + BooleanModifierData *bmd = (BooleanModifierData *)md; + if (bmd->object != NULL) { + DEG_add_object_relation(node, bmd->object, DEG_OB_COMP_TRANSFORM, "Boolean Modifier"); + DEG_add_object_relation(node, bmd->object, DEG_OB_COMP_GEOMETRY, "Boolean Modifier"); + } + /* We need own transformation as well. */ + DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Boolean Modifier"); +} + #ifdef WITH_MOD_BOOLEAN static DerivedMesh *get_quick_derivedMesh(DerivedMesh *derivedData, DerivedMesh *dm, int operation) { @@ -193,6 +208,7 @@ ModifierTypeInfo modifierType_Boolean = { /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index 96337c33373..507fad466a3 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -329,6 +329,7 @@ ModifierTypeInfo modifierType_Build = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c index 3bdc62e124c..7c3d65a5c9a 100644 --- a/source/blender/modifiers/intern/MOD_cast.c +++ b/source/blender/modifiers/intern/MOD_cast.c @@ -121,6 +121,18 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + CastModifierData *cmd = (CastModifierData *)md; + if (cmd->object != NULL) { + DEG_add_object_relation(node, cmd->object, DEG_OB_COMP_TRANSFORM, "Cast Modifier"); + } +} + static void sphere_do( CastModifierData *cmd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) @@ -500,6 +512,7 @@ ModifierTypeInfo modifierType_Cast = { /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 392112e4b4a..25fd54d1d3e 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -140,6 +140,27 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *scene, + Object *ob, + struct DepsNodeHandle *node) +{ + ClothModifierData *clmd = (ClothModifierData *)md; + if (clmd != NULL) { + Base *base; + for (base = scene->base.first; base; base = base->next) { + Object *ob1 = base->object; + if (ob1 != ob) { + CollisionModifierData *coll_clmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision); + if (coll_clmd) { + DEG_add_object_relation(node, ob1, DEG_OB_COMP_TRANSFORM, "Cloth Modifier"); + } + } + } + } +} + static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) { CustomDataMask dataMask = 0; @@ -251,6 +272,7 @@ ModifierTypeInfo modifierType_Cloth = { /* freeData */ freeData, /* isDisabled */ NULL, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index 130e332ef69..931f82c98e9 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -241,6 +241,7 @@ ModifierTypeInfo modifierType_Collision = { /* freeData */ freeData, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index 162f45b4e91..d5b4daca3b7 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -760,6 +760,7 @@ ModifierTypeInfo modifierType_CorrectiveSmooth = { /* freeData */ freeData, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index d53bac390a6..1488296caf9 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -45,6 +45,7 @@ #include "BKE_modifier.h" #include "depsgraph_private.h" +#include "DEG_depsgraph_build.h" static void initData(ModifierData *md) @@ -108,6 +109,25 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *scene, + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + CurveModifierData *cmd = (CurveModifierData *)md; + if (cmd->object != NULL) { + /* TODO(sergey): Need to do the same eval_flags trick for path + * as happening in legacy depsgraph callback. + */ + /* TODO(sergey): Currently path is evaluated as a part of modifier stack, + * might be changed in the future. + */ + DEG_add_object_relation(node, cmd->object, DEG_OB_COMP_GEOMETRY, "Curve Modifier"); + DEG_add_special_eval_flag(scene->depsgraph, &cmd->object->id, DAG_EVAL_NEED_CURVE_PATH); + } +} + static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], @@ -156,6 +176,7 @@ ModifierTypeInfo modifierType_Curve = { /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index d13ca6e5bb7..57d119f5481 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -147,6 +147,18 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + DataTransferModifierData *dtmd = (DataTransferModifierData *) md; + if (dtmd->ob_source != NULL) { + DEG_add_object_relation(node, dtmd->ob_source, DEG_OB_COMP_GEOMETRY, "DataTransfer Modifier"); + } +} + static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams)) { DataTransferModifierData *dtmd = (DataTransferModifierData *) md; @@ -235,6 +247,7 @@ ModifierTypeInfo modifierType_DataTransfer = { /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index 542c75f3276..7c13774ee99 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -224,6 +224,7 @@ ModifierTypeInfo modifierType_Decimate = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index e377445fed8..2921472fe99 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -171,6 +171,21 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *ob, + struct DepsNodeHandle *node) +{ + DisplaceModifierData *dmd = (DisplaceModifierData *)md; + if (dmd->map_object != NULL && dmd->texmapping == MOD_DISP_MAP_OBJECT) { + DEG_add_object_relation(node, dmd->map_object, DEG_OB_COMP_TRANSFORM, "Displace Modifier"); + } + if (dmd->texmapping == MOD_DISP_MAP_GLOBAL) { + DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Displace Modifier"); + } +} + /* dm must be a CDDerivedMesh */ static void displaceModifier_do( DisplaceModifierData *dmd, Object *ob, @@ -302,6 +317,7 @@ ModifierTypeInfo modifierType_Displace = { /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ dependsOnNormals, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index c6999468dc3..95bc4706dc9 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -38,6 +38,7 @@ #include "BKE_modifier.h" #include "depsgraph_private.h" +#include "DEG_depsgraph_build.h" static void initData(ModifierData *md) @@ -135,6 +136,26 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *scene, + Object *ob, + struct DepsNodeHandle *node) +{ + DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md; + /* Add relation from canvases to all brush objects. */ + if (pmd->canvas != NULL) { + Base *base = scene->base.first; + for (; base; base = base->next) { + DynamicPaintModifierData *pmd2 = + (DynamicPaintModifierData *)modifiers_findByType(base->object, eModifierType_DynamicPaint); + if (pmd2 && pmd2->brush && ob != base->object) { + DEG_add_object_relation(node, base->object, DEG_OB_COMP_TRANSFORM, "Dynamic Paint Brush"); + } + } + } +} + static bool dependsOnTime(ModifierData *UNUSED(md)) { return true; @@ -187,6 +208,7 @@ ModifierTypeInfo modifierType_DynamicPaint = { /* freeData */ freeData, /* isDisabled */ NULL, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index fa29921b325..4441edb299b 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -158,6 +158,7 @@ ModifierTypeInfo modifierType_EdgeSplit = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index 32a6303d19d..fa16ebbb5da 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -1058,6 +1058,7 @@ ModifierTypeInfo modifierType_Explode = { /* freeData */ freeData, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c index 9f05d357299..8d2774a346f 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim.c +++ b/source/blender/modifiers/intern/MOD_fluidsim.c @@ -44,6 +44,7 @@ #include "BKE_modifier.h" #include "depsgraph_private.h" +#include "DEG_depsgraph_build.h" #include "MOD_fluidsim_util.h" #include "MEM_guardedalloc.h" @@ -126,6 +127,32 @@ static void updateDepgraph( } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *scene, + Object *ob, + struct DepsNodeHandle *node) +{ + FluidsimModifierData *fluidmd = (FluidsimModifierData *) md; + if (fluidmd && fluidmd->fss) { + if (fluidmd->fss->type == OB_FLUIDSIM_DOMAIN) { + Base *base; + for (base = scene->base.first; base; base = base->next) { + Object *ob1 = base->object; + if (ob1 != ob) { + FluidsimModifierData *fluidmdtmp = + (FluidsimModifierData *)modifiers_findByType(ob1, eModifierType_Fluidsim); + + /* Only put dependencies from NON-DOMAIN fluids in here. */ + if (fluidmdtmp && fluidmdtmp->fss && (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN)) { + DEG_add_object_relation(node, ob1, DEG_OB_COMP_TRANSFORM, "Fluidsim Object"); + } + } + } + } + } +} + static bool dependsOnTime(ModifierData *UNUSED(md)) { return true; @@ -154,6 +181,7 @@ ModifierTypeInfo modifierType_Fluidsim = { /* freeData */ freeData, /* isDisabled */ NULL, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index 10223d3880e..3a10fabbb8e 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -129,6 +129,25 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + HookModifierData *hmd = (HookModifierData *)md; + if (hmd->object != NULL) { + if (hmd->subtarget[0]) { + /* TODO(sergey): Hpw do we add relation to bone here? */ + //DEG_add_object_relation(node, hmd->object, DEG_OB_COMP_EVAL_POSE, "Hook Modifier"); + DEG_add_bone_relation(node, hmd->object, hmd->subtarget, DEG_OB_COMP_BONE, "Hook Modifier"); + } + else { + DEG_add_object_relation(node, hmd->object, DEG_OB_COMP_TRANSFORM, "Hook Modifier"); + } + } +} + struct HookData_cb { float (*vertexCos)[3]; @@ -403,6 +422,7 @@ ModifierTypeInfo modifierType_Hook = { /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c index a4f6d005d94..c3cfafb7e27 100644 --- a/source/blender/modifiers/intern/MOD_laplaciandeform.c +++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c @@ -862,6 +862,7 @@ ModifierTypeInfo modifierType_LaplacianDeform = { /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index 93cd92196b2..a142d18a6d3 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -716,6 +716,7 @@ ModifierTypeInfo modifierType_LaplacianSmooth = { /* freeData */ NULL, /* isDisabled */ is_disabled, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c index 60caf523a97..b8975beaf83 100644 --- a/source/blender/modifiers/intern/MOD_lattice.c +++ b/source/blender/modifiers/intern/MOD_lattice.c @@ -107,6 +107,18 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + LatticeModifierData *lmd = (LatticeModifierData *)md; + if (lmd->object != NULL) { + DEG_add_object_relation(node, lmd->object, DEG_OB_COMP_GEOMETRY, "Lattice Modifier"); + } +} + static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], @@ -155,6 +167,7 @@ ModifierTypeInfo modifierType_Lattice = { /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c index e77225f3617..06fbab65d7b 100644 --- a/source/blender/modifiers/intern/MOD_mask.c +++ b/source/blender/modifiers/intern/MOD_mask.c @@ -50,6 +50,7 @@ #include "BKE_deform.h" #include "depsgraph_private.h" +#include "DEG_depsgraph_build.h" #include "BLI_strict_flags.h" @@ -94,6 +95,22 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + MaskModifierData *mmd = (MaskModifierData *)md; + if (mmd->ob_arm) { + bArmature *arm = (bArmature *)mmd->ob_arm->data; + /* Tag relationship in depsgraph, but also on the armature. */ + /* TODO(sergey): Is it a proper relation here? */ + DEG_add_object_relation(node, mmd->ob_arm, DEG_OB_COMP_TRANSFORM, "Mask Modifier"); + arm->flag |= ARM_HAS_VIZ_DEPS; + } +} + static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, ModifierApplyFlag UNUSED(flag)) @@ -385,6 +402,7 @@ ModifierTypeInfo modifierType_Mask = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index db50d49f790..92926ed9424 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -313,6 +313,7 @@ ModifierTypeInfo modifierType_MeshCache = { /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index 3ceed4a970d..22148d1f5ae 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -139,6 +139,19 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; + if (mmd->object != NULL) { + /* TODO(sergey): Do we need transform component here? */ + DEG_add_object_relation(node, mmd->object, DEG_OB_COMP_GEOMETRY, "Mesh Deform Modifier"); + } +} + static float meshdeform_dynamic_bind(MeshDeformModifierData *mmd, float (*dco)[3], float vec[3]) { MDefCell *cell; @@ -521,6 +534,7 @@ ModifierTypeInfo modifierType_MeshDeform = { /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index 73bc61e5519..d3080ca235a 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -43,7 +43,9 @@ #include "BKE_deform.h" #include "MEM_guardedalloc.h" + #include "depsgraph_private.h" +#include "DEG_depsgraph_build.h" static void initData(ModifierData *md) { @@ -88,6 +90,18 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + MirrorModifierData *mmd = (MirrorModifierData *)md; + if (mmd->mirror_ob != NULL) { + DEG_add_object_relation(node, mmd->mirror_ob, DEG_OB_COMP_TRANSFORM, "Mirror Modifier"); + } +} + static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, Object *ob, DerivedMesh *dm, @@ -361,6 +375,7 @@ ModifierTypeInfo modifierType_Mirror = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index 4754813a744..90ad1bdfdc2 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -162,6 +162,7 @@ ModifierTypeInfo modifierType_Multires = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_none.c b/source/blender/modifiers/intern/MOD_none.c index 579f65a9c50..d9d9ba2966d 100644 --- a/source/blender/modifiers/intern/MOD_none.c +++ b/source/blender/modifiers/intern/MOD_none.c @@ -68,6 +68,7 @@ ModifierTypeInfo modifierType_None = { /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 8315f61c132..87d75c6f1a7 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -481,6 +481,18 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + NormalEditModifierData *smd = (NormalEditModifierData *) md; + if (smd->target) { + DEG_add_object_relation(node, smd->target, DEG_OB_COMP_GEOMETRY, "NormalEdit Modifier"); + } +} + static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, ModifierApplyFlag UNUSED(flag)) { return normalEditModifier_do((NormalEditModifierData *)md, ob, dm); @@ -508,6 +520,7 @@ ModifierTypeInfo modifierType_NormalEdit = { /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index 4cbe0967b01..913c2f25c15 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -580,6 +580,7 @@ ModifierTypeInfo modifierType_Ocean = { /* freeData */ freeData, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index 29ba7dda5db..cb6234d50b7 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -51,7 +51,7 @@ #include "BKE_pointcache.h" #include "depsgraph_private.h" - +#include "DEG_depsgraph_build.h" static void initData(ModifierData *md) { @@ -127,6 +127,18 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md; + if (pimd->ob != NULL) { + DEG_add_object_relation(node, pimd->ob, DEG_OB_COMP_TRANSFORM, "Particle Instance Modifier"); + } +} + static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) { @@ -448,6 +460,7 @@ ModifierTypeInfo modifierType_ParticleInstance = { /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index 9860daeda4c..de1b11eddd9 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -206,6 +206,7 @@ ModifierTypeInfo modifierType_ParticleSystem = { /* freeData */ freeData, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c index 6d76dc51ac7..9df064db44d 100644 --- a/source/blender/modifiers/intern/MOD_remesh.c +++ b/source/blender/modifiers/intern/MOD_remesh.c @@ -232,6 +232,7 @@ ModifierTypeInfo modifierType_Remesh = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index a9160189a7b..4fa86527334 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -46,6 +46,8 @@ #include "BKE_cdderivedmesh.h" #include "depsgraph_private.h" +#include "DEG_depsgraph_build.h" + #include "MOD_modifiertypes.h" #include "MEM_guardedalloc.h" @@ -1074,6 +1076,18 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + ScrewModifierData *ltmd = (ScrewModifierData *)md; + if (ltmd->ob_axis != NULL) { + DEG_add_object_relation(node, ltmd->ob_axis, DEG_OB_COMP_TRANSFORM, "Screw Modifier"); + } +} + static void foreachObjectLink( ModifierData *md, Object *ob, void (*walk)(void *userData, Object *ob, Object **obpoin), @@ -1107,6 +1121,7 @@ ModifierTypeInfo modifierType_Screw = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c index f3327a03f2c..a543aac74b9 100644 --- a/source/blender/modifiers/intern/MOD_shapekey.c +++ b/source/blender/modifiers/intern/MOD_shapekey.c @@ -138,6 +138,7 @@ ModifierTypeInfo modifierType_ShapeKey = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c index fd583c43d6e..91be0c40059 100644 --- a/source/blender/modifiers/intern/MOD_shrinkwrap.c +++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c @@ -159,6 +159,23 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier"); } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md; + if (smd->target != NULL) { + DEG_add_object_relation(node, smd->target, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier"); + DEG_add_object_relation(node, smd->target, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier"); + } + if (smd->auxTarget != NULL) { + DEG_add_object_relation(node, smd->auxTarget, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier"); + DEG_add_object_relation(node, smd->auxTarget, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier"); + } +} + static bool dependsOnNormals(ModifierData *md) { ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md; @@ -191,6 +208,7 @@ ModifierTypeInfo modifierType_Shrinkwrap = { /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c index 0e1cb125a47..706a296f5a1 100644 --- a/source/blender/modifiers/intern/MOD_simpledeform.c +++ b/source/blender/modifiers/intern/MOD_simpledeform.c @@ -298,6 +298,18 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, dag_add_relation(forest, dag_get_node(forest, smd->origin), obNode, DAG_RL_OB_DATA, "SimpleDeform Modifier"); } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md; + if (smd->origin != NULL) { + DEG_add_object_relation(node, smd->origin, DEG_OB_COMP_TRANSFORM, "SimpleDeform Modifier"); + } +} + static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], @@ -362,6 +374,7 @@ ModifierTypeInfo modifierType_SimpleDeform = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 5ebb3f98f6c..6c096224b58 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -1937,6 +1937,7 @@ ModifierTypeInfo modifierType_Skin = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c index 74409498ca3..657c4e09d96 100644 --- a/source/blender/modifiers/intern/MOD_smoke.c +++ b/source/blender/modifiers/intern/MOD_smoke.c @@ -53,6 +53,7 @@ #include "BKE_smoke.h" #include "depsgraph_private.h" +#include "DEG_depsgraph_build.h" static void initData(ModifierData *md) { @@ -227,6 +228,111 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void update_depsgraph_flow_coll_object_new(struct DepsNodeHandle *node, + Object *object2) +{ + SmokeModifierData *smd; + if ((object2->id.flag & LIB_DOIT) == 0) { + return; + } + object2->id.flag &= ~LIB_DOIT; + smd = (SmokeModifierData *)modifiers_findByType(object2, eModifierType_Smoke); + if (smd && (((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) || + ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll))) + { + DEG_add_object_relation(node, object2, DEG_OB_COMP_TRANSFORM, "Smoke Flow/Coll"); + DEG_add_object_relation(node, object2, DEG_OB_COMP_GEOMETRY, "Smoke Flow/Coll"); + } + if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) { + GroupObject *go; + for (go = object2->dup_group->gobject.first; + go != NULL; + go = go->next) + { + if (go->ob == NULL) { + continue; + } + update_depsgraph_flow_coll_object_new(node, go->ob); + } + } +} + +static void update_depsgraph_field_source_object_new(struct DepsNodeHandle *node, + Object *object, + Object *object2) +{ + if ((object2->id.flag & LIB_DOIT) == 0) { + return; + } + object2->id.flag &= ~LIB_DOIT; + if (object2->pd && object2->pd->forcefield == PFIELD_SMOKEFLOW && object2->pd->f_source == object) { + DEG_add_object_relation(node, object2, DEG_OB_COMP_TRANSFORM, "Field Source Object"); + DEG_add_object_relation(node, object2, DEG_OB_COMP_GEOMETRY, "Field Source Object"); + } + if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) { + GroupObject *go; + for (go = object2->dup_group->gobject.first; + go != NULL; + go = go->next) + { + if (go->ob == NULL) { + continue; + } + update_depsgraph_field_source_object_new(node, object, go->ob); + } + } +} + +static void updateDepsgraph(ModifierData *md, + struct Main *bmain, + struct Scene *scene, + Object *ob, + struct DepsNodeHandle *node) +{ + SmokeModifierData *smd = (SmokeModifierData *)md; + Base *base; + if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) { + if (smd->domain->fluid_group || smd->domain->coll_group) { + GroupObject *go = NULL; + if (smd->domain->fluid_group != NULL) { + for (go = smd->domain->fluid_group->gobject.first; go; go = go->next) { + if (go->ob != NULL) { + SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke); + /* Check for initialized smoke object. */ + if (smd2 && (smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) { + DEG_add_object_relation(node, go->ob, DEG_OB_COMP_TRANSFORM, "Smoke Flow"); + } + } + } + } + if (smd->domain->coll_group != NULL) { + for (go = smd->domain->coll_group->gobject.first; go; go = go->next) { + if (go->ob != NULL) { + SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke); + /* Check for initialized smoke object. */ + if (smd2 && (smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll) { + DEG_add_object_relation(node, go->ob, DEG_OB_COMP_TRANSFORM, "Smoke Coll"); + } + } + } + } + } + else { + BKE_main_id_tag_listbase(&bmain->object, true); + base = scene->base.first; + for (; base; base = base->next) { + update_depsgraph_flow_coll_object_new(node, base->object); + } + } + /* add relation to all "smoke flow" force fields */ + base = scene->base.first; + BKE_main_id_tag_listbase(&bmain->object, true); + for (; base; base = base->next) { + update_depsgraph_field_source_object_new(node, ob, base->object); + } + } +} + static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { @@ -268,6 +374,7 @@ ModifierTypeInfo modifierType_Smoke = { /* freeData */ freeData, /* isDisabled */ NULL, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index d1ad8f1fcfc..d45c8528510 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -262,6 +262,7 @@ ModifierTypeInfo modifierType_Smooth = { /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c index 5f5347a46b0..d958badc33c 100644 --- a/source/blender/modifiers/intern/MOD_softbody.c +++ b/source/blender/modifiers/intern/MOD_softbody.c @@ -80,6 +80,7 @@ ModifierTypeInfo modifierType_Softbody = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index fdba8e54a98..ca2dcfec3a3 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -961,6 +961,7 @@ ModifierTypeInfo modifierType_Solidify = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index 7ada058d883..2a62a9e6081 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -159,6 +159,7 @@ ModifierTypeInfo modifierType_Subsurf = { /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c index 1c462f12f9f..3d998f2d95a 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -186,6 +186,7 @@ ModifierTypeInfo modifierType_Surface = { /* freeData */ freeData, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c index 592ab4194ec..194a46b6f28 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.c +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -119,6 +119,7 @@ ModifierTypeInfo modifierType_Triangulate = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h index 5a1f1fc876a..b74ff9c2a25 100644 --- a/source/blender/modifiers/intern/MOD_util.h +++ b/source/blender/modifiers/intern/MOD_util.h @@ -31,6 +31,8 @@ /* so modifier types match their defines */ #include "MOD_modifiertypes.h" +#include "DEG_depsgraph_build.h" + struct DerivedMesh; struct MDeformVert; struct ModifierData; diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 113f1654d02..1b1474ee666 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -51,7 +51,9 @@ #include "MOD_modifiertypes.h" #include "MEM_guardedalloc.h" + #include "depsgraph_private.h" +#include "DEG_depsgraph_build.h" static void initData(ModifierData *md) { @@ -122,6 +124,21 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + UVProjectModifierData *umd = (UVProjectModifierData *)md; + int i; + for (i = 0; i < umd->num_projectors; ++i) { + if (umd->projectors[i] != NULL) { + DEG_add_object_relation(node, umd->projectors[i], DEG_OB_COMP_TRANSFORM, "UV Project Modifier"); + } + } +} + typedef struct Projector { Object *ob; /* object this projector is derived from */ float projmat[4][4]; /* projection matrix */ @@ -369,6 +386,7 @@ ModifierTypeInfo modifierType_UVProject = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c index f41705d1aac..3c4ca66485d 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.c +++ b/source/blender/modifiers/intern/MOD_uvwarp.c @@ -229,6 +229,30 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, uv_warp_deps_object_bone(forest, obNode, umd->object_dst, umd->bone_dst); } +static void uv_warp_deps_object_bone_new(struct DepsNodeHandle *node, + Object *object, + const char *bonename) +{ + if (object != NULL) { + if (bonename[0]) + DEG_add_object_relation(node, object, DEG_OB_COMP_EVAL_POSE, "UVWarp Modifier"); + else + DEG_add_object_relation(node, object, DEG_OB_COMP_TRANSFORM, "UVWarp Modifier"); + } +} + +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + UVWarpModifierData *umd = (UVWarpModifierData *) md; + + uv_warp_deps_object_bone_new(node, umd->object_src, umd->bone_src); + uv_warp_deps_object_bone_new(node, umd->object_dst, umd->bone_dst); +} + ModifierTypeInfo modifierType_UVWarp = { /* name */ "UVWarp", /* structName */ "UVWarpModifierData", @@ -249,6 +273,7 @@ ModifierTypeInfo modifierType_UVWarp = { /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 9d496724ba1..ae2dbd4a37c 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -157,6 +157,22 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + WarpModifierData *wmd = (WarpModifierData *) md; + if (wmd->object_from != NULL && wmd->object_to != NULL) { + DEG_add_object_relation(node, wmd->object_from, DEG_OB_COMP_TRANSFORM, "Warp Modifier from"); + DEG_add_object_relation(node, wmd->object_to, DEG_OB_COMP_TRANSFORM, "Warp Modifier to"); + } + if ((wmd->texmapping == MOD_DISP_MAP_OBJECT) && wmd->map_object != NULL) { + DEG_add_object_relation(node, wmd->map_object, DEG_OB_COMP_TRANSFORM, "Warp Modifier map"); + } +} + static void warpModifier_do(WarpModifierData *wmd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { @@ -372,6 +388,7 @@ ModifierTypeInfo modifierType_Warp = { /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index 7fd830dabd4..5b98f221489 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -153,6 +153,21 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + struct DepsNodeHandle *node) +{ + WaveModifierData *wmd = (WaveModifierData *)md; + if (wmd->objectcenter != NULL) { + DEG_add_object_relation(node, wmd->objectcenter, DEG_OB_COMP_TRANSFORM, "Wave Modifier"); + } + if (wmd->map_object != NULL) { + DEG_add_object_relation(node, wmd->map_object, DEG_OB_COMP_TRANSFORM, "Wave Modifier"); + } +} + static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) { WaveModifierData *wmd = (WaveModifierData *)md; @@ -381,6 +396,7 @@ ModifierTypeInfo modifierType_Wave = { /* freeData */ freeData, /* isDisabled */ NULL, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index c4734ccd7a8..cba077a2f8d 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -46,6 +46,8 @@ #include "BKE_texture.h" /* Texture masking. */ #include "depsgraph_private.h" +#include "DEG_depsgraph_build.h" + #include "MEM_guardedalloc.h" #include "MOD_weightvg_util.h" @@ -162,6 +164,21 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, "WeightVGEdit Modifier"); } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *ob, + struct DepsNodeHandle *node) +{ + WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; + if (wmd->mask_tex_map_obj != NULL && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) { + DEG_add_object_relation(node, wmd->mask_tex_map_obj, DEG_OB_COMP_TRANSFORM, "WeightVGEdit Modifier"); + } + if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) { + DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "WeightVGEdit Modifier"); + } +} + static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams)) { WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md; @@ -292,6 +309,7 @@ ModifierTypeInfo modifierType_WeightVGEdit = { /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index 266cfcc59a6..3d60c4a8b8b 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -43,6 +43,8 @@ #include "BKE_texture.h" /* Texture masking. */ #include "depsgraph_private.h" +#include "DEG_depsgraph_build.h" + #include "MEM_guardedalloc.h" #include "MOD_weightvg_util.h" @@ -211,6 +213,21 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, "WeightVGMix Modifier"); } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *ob, + struct DepsNodeHandle *node) +{ + WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md; + if (wmd->mask_tex_map_obj != NULL && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) { + DEG_add_object_relation(node, wmd->mask_tex_map_obj, DEG_OB_COMP_TRANSFORM, "WeightVGMix Modifier"); + } + if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) { + DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "WeightVGMix Modifier"); + } +} + static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams)) { WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md; @@ -422,6 +439,7 @@ ModifierTypeInfo modifierType_WeightVGMix = { /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 390475b57f5..033516016d3 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -46,6 +46,8 @@ #include "BKE_texture.h" /* Texture masking. */ #include "depsgraph_private.h" +#include "DEG_depsgraph_build.h" + #include "MEM_guardedalloc.h" #include "MOD_weightvg_util.h" @@ -338,6 +340,24 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, "WeightVGProximity Modifier"); } +static void updateDepsgraph(ModifierData *md, + struct Main *UNUSED(bmain), + struct Scene *UNUSED(scene), + Object *ob, + struct DepsNodeHandle *node) +{ + WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *)md; + if (wmd->proximity_ob_target != NULL) { + DEG_add_object_relation(node, wmd->proximity_ob_target, DEG_OB_COMP_TRANSFORM, "WeightVGProximity Modifier"); + } + if (wmd->mask_tex_map_obj != NULL && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) { + DEG_add_object_relation(node, wmd->mask_tex_map_obj, DEG_OB_COMP_TRANSFORM, "WeightVGProximity Modifier"); + } + if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) { + DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "WeightVGProximity Modifier"); + } +} + static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams)) { WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md; @@ -566,6 +586,7 @@ ModifierTypeInfo modifierType_WeightVGProximity = { /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c index aa5e6116516..fe21757d5c2 100644 --- a/source/blender/modifiers/intern/MOD_wireframe.c +++ b/source/blender/modifiers/intern/MOD_wireframe.c @@ -133,6 +133,7 @@ ModifierTypeInfo modifierType_Wireframe = { /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ NULL, + /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, /* foreachObjectLink */ NULL, diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index 36b9f8ae362..4b54ddf7225 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -31,6 +31,7 @@ set(INC ../blenkernel ../blenlib ../imbuf + ../depsgraph ../makesdna ../makesrna ../physics diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript index 0cbf188525b..4a9f32bc1ac 100644 --- a/source/blender/render/SConscript +++ b/source/blender/render/SConscript @@ -38,6 +38,7 @@ incs = [ '../blenkernel', '../blenlib', '../imbuf', + '../depsgraph', '../makesdna', '../makesrna', '../physics', diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 7f08e576747..bdf67434725 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -84,6 +84,8 @@ # include "FRS_freestyle.h" #endif +#include "DEG_depsgraph.h" + /* internal */ #include "render_result.h" #include "render_types.h" @@ -467,8 +469,7 @@ Render *RE_NewRender(const char *name) BLI_strncpy(re->name, name, RE_MAXNAME); BLI_rw_mutex_init(&re->resultmutex); BLI_rw_mutex_init(&re->partsmutex); - re->eval_ctx = MEM_callocN(sizeof(EvaluationContext), "re->eval_ctx"); - re->eval_ctx->mode = DAG_EVAL_RENDER; + re->eval_ctx = DEG_evaluation_context_new(DAG_EVAL_RENDER); } RE_InitRenderCB(re); diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 25ee4f2ef21..1136524da04 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -106,6 +106,7 @@ endif() bf_intern_ghostndof3dconnexion bf_rna bf_blenkernel + bf_depsgraph bf_physics bf_intern_rigidbody bf_blenloader diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index c0b0c2eadb6..ffaf6f42b18 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -31,6 +31,7 @@ blender_include_dirs( ../blender/blenlib ../blender/blenkernel ../blender/blenloader + ../blender/depsgraph ../blender/editors/include ../blender/makesrna ../blender/imbuf diff --git a/source/creator/creator.c b/source/creator/creator.c index 721e43cda4d..e2d7bda3a21 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -93,6 +93,8 @@ #include "BKE_image.h" #include "BKE_particle.h" +#include "DEG_depsgraph.h" + #include "IMB_imbuf.h" /* for IMB_init */ #ifdef WITH_PYTHON @@ -357,6 +359,10 @@ static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data) printf("Other Options:\n"); BLI_argsPrintOtherDoc(ba); + printf("\n"); + printf("Experimental features:\n"); + BLI_argsPrintArgDoc(ba, "--enable-new-depsgraph"); + printf("Argument Parsing:\n"); printf("\targuments must be separated by white space. eg\n"); printf("\t\t\"blender -ba test.blend\"\n"); @@ -929,6 +935,12 @@ static int set_threads(int argc, const char **argv, void *UNUSED(data)) } } +static int depsgraph_use_new(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data)) +{ + DEG_depsgraph_switch_to_new(); + return 0; +} + static int set_verbosity(int argc, const char **argv, void *UNUSED(data)) { if (argc > 1) { @@ -1494,6 +1506,8 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle) BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph", "\n\tEnable debug messages from dependency graph", debug_mode_generic, (void *)G_DEBUG_DEPSGRAPH); BLI_argsAdd(ba, 1, NULL, "--debug-gpumem", "\n\tEnable GPU memory stats in status bar", debug_mode_generic, (void *)G_DEBUG_GPU_MEM); + BLI_argsAdd(ba, 1, NULL, "--enable-new-depsgraph", "\n\tUse new dependency graph", depsgraph_use_new, NULL); + BLI_argsAdd(ba, 1, NULL, "--verbose", "\n\tSet logging verbosity level.", set_verbosity, NULL); BLI_argsAdd(ba, 1, NULL, "--factory-startup", "\n\tSkip reading the "STRINGIFY (BLENDER_STARTUP_FILE)" in the users home directory", set_factory_startup, NULL); -- cgit v1.2.3 From 29529d2ac31a35f5cdd8c02e9c36cfcc1e0c7bc4 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 12 May 2015 16:24:22 +0500 Subject: ImBuf: Update stubs so strict compiler is happy about unused arguments Also use C++-style unused arguments tagging instead of legacy c-style. It's less annoying this way because does not require adding argument to two places of the function. --- .../blender/imbuf/intern/openexr/openexr_stub.cpp | 62 +++++++++++----------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/source/blender/imbuf/intern/openexr/openexr_stub.cpp b/source/blender/imbuf/intern/openexr/openexr_stub.cpp index c326efd2427..ace19165ef5 100644 --- a/source/blender/imbuf/intern/openexr/openexr_stub.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_stub.cpp @@ -31,55 +31,53 @@ #include "openexr_api.h" #include "openexr_multi.h" -#include "BLI_utildefines.h" /* UNUSED_VARS */ void *IMB_exr_get_handle (void) {return NULL;} -void *IMB_exr_get_handle_name (const char *name) {(void)name; return NULL;} -void IMB_exr_add_channel (void *handle, const char *layname, const char *passname, const char *view, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)passname; (void)xstride; (void)ystride; (void)rect; } +void *IMB_exr_get_handle_name (const char * /*name*/) { return NULL;} +void IMB_exr_add_channel (void * /*handle*/, const char * /*layname*/, const char * /*passname*/, const char * /*view*/, + int /*xstride*/, int /*ystride*/, float * /*rect*/) { } -int IMB_exr_begin_read (void *handle, const char *filename, int *width, int *height) { (void)handle; (void)filename; (void)width; (void)height; return 0;} -int IMB_exr_begin_write (void *handle, const char *filename, int width, int height, int compress) { (void)handle; (void)filename; (void)width; (void)height; (void)compress; return 0;} -void IMB_exrtile_begin_write (void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { (void)handle; (void)filename; (void)mipmap; (void)width; (void)height; (void)tilex; (void)tiley; } +int IMB_exr_begin_read (void * /*handle*/, const char * /*filename*/, int * /*width*/, int * /*height*/) { return 0;} +int IMB_exr_begin_write (void * /*handle*/, const char * /*filename*/, int /*width*/, int /*height*/, int /*compress*/) { return 0;} +void IMB_exrtile_begin_write (void * /*handle*/, const char * /*filename*/, int /*mipmap*/, int /*width*/, int /*height*/, int /*tilex*/, int /*tiley*/) { } -void IMB_exr_set_channel (void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)passname; (void)xstride; (void)ystride; (void)rect; } -float *IMB_exr_channel_rect (void *handle, const char *layname, const char *passname, const char *view) { (void)handle; (void)layname; (void)passname; (void)view; return NULL; } +void IMB_exr_set_channel (void * /*handle*/, const char * /*layname*/, const char * /*passname*/, int /*xstride*/, int /*ystride*/, float * /*rect*/) { } +float *IMB_exr_channel_rect (void * /*handle*/, const char * /*layname*/, const char * /*passname*/, const char * /*view*/) { return NULL; } -void IMB_exr_read_channels (void *handle) { (void)handle; } -void IMB_exr_write_channels (void *handle) { (void)handle; } -void IMB_exrtile_write_channels (void *handle, int partx, int party, int level, const char *viewname) { UNUSED_VARS(handle, partx, party, level, viewname); } -void IMB_exrmultiview_write_channels(void *handle, const char *viewname) { UNUSED_VARS(handle, viewname); } -void IMB_exr_clear_channels (void *handle) { (void)handle; } +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*/, int /*level*/, const char * /*viewname*/) { } +void IMB_exrmultiview_write_channels(void * /*handle*/, const char * /*viewname*/) { } +void IMB_exr_clear_channels (void * /*handle*/) { } void IMB_exr_multilayer_convert( - void *handle, void *base, - void * (*addview)(void *base, const char *str), - void * (*addlayer)(void *base, const char *str), - void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, - const char *chan_id, const char *view)) + void * /*handle*/, void * /*base*/, + void * (* /*addview*/)(void *base, const char *str), + void * (* /*addlayer*/)(void *base, const char *str), + void (* /*addpass*/)(void *base, void *lay, const char *str, float *rect, int totchan, + const char *chan_id, const char *view)) { - UNUSED_VARS(handle, base, addview, addlayer, addpass); } void IMB_exr_multiview_convert( - void *handle, void *base, - void (*addview)(void *base, const char *str), - void (*addbuffer)(void *base, const char *str, struct ImBuf *ibuf, const int frame), const int frame) + void * /*handle*/, void * /*base*/, + void (* /*addview*/)(void *base, const char *str), + void (* /*addbuffer*/)(void *base, const char *str, struct ImBuf *ibuf, const int frame), + const int /*frame*/) { - UNUSED_VARS(handle, base, addview, addbuffer, frame); } bool IMB_exr_multiview_save( - struct ImBuf *ibuf, const char *name, const int flags, const size_t totviews, - const char * (*getview)(void *base, size_t view_id), - struct ImBuf * (*getbuffer)(void *base, const size_t view_id)) + struct ImBuf * /*ibuf*/, const char * /*name*/, const int /*flags*/, const size_t /*totviews*/, + const char * (* /*getview*/)(void *base, size_t view_id), + struct ImBuf * (* /*getbuffer*/)(void *base, const size_t view_id)) { - UNUSED_VARS(ibuf, name, flags, totviews, getview, getbuffer); return false; } -void IMB_exr_close (void *handle) { (void)handle; } +void IMB_exr_close (void * /*handle*/) { } -void IMB_exr_add_view(void *handle, const char *name) { UNUSED_VARS(handle, name); } -int IMB_exr_split_token(const char *str, const char *end, const char **token) { UNUSED_VARS(str, end, token); return 1; } -bool IMB_exr_has_multilayer(void *handle) { UNUSED_VARS(handle); return false; } -bool IMB_exr_has_singlelayer_multiview(void *handle) { UNUSED_VARS(handle); return false; } +void IMB_exr_add_view(void * /*handle*/, const char * /*name*/) { } +int IMB_exr_split_token(const char * /*str*/, const char * /*end*/, const char ** /*token*/) { return 1; } +bool IMB_exr_has_multilayer(void * /*handle*/) { return false; } +bool IMB_exr_has_singlelayer_multiview(void * /*handle*/) { return false; } -- cgit v1.2.3 From 615a7aea5534e0730fa8bf0690d5e30a478aa1fe Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 12 May 2015 16:36:34 +0500 Subject: Depsgraph: Attempt to fix alignment issue on 32bit platforms --- source/blender/makesdna/DNA_scene_types.h | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index fe346eecec5..7ac00e16aff 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1402,6 +1402,7 @@ typedef struct Scene { /* none of the dependency graph vars is mean to be saved */ struct Depsgraph *depsgraph; + void *pad1; struct DagForest *theDag; short dagflags; short recalc; /* recalc = counterpart of ob->recalc */ -- cgit v1.2.3 From 909d3228b1d0254888d0c97d269e9ab2e315dba9 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Tue, 12 May 2015 13:24:47 +0200 Subject: BGE : Fix Bullet shape margin for triangle mesh static objects --- source/gameengine/Physics/Bullet/CcdPhysicsController.cpp | 1 + source/gameengine/Physics/Bullet/CcdPhysicsController.h | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index efa90657efc..ed23a454c92 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -2610,6 +2610,7 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin, b } btBvhTriangleMeshShape *unscaledShape = new btBvhTriangleMeshShape(m_triangleIndexVertexArray, true, useBvh); + unscaledShape->setMargin(margin); collisionShape = new btScaledBvhTriangleMeshShape(unscaledShape, btVector3(1.0f, 1.0f, 1.0f)); collisionShape->setMargin(margin); } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 625713d16e1..b1d38763fbb 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -657,8 +657,12 @@ protected: virtual void CalcXform() {} virtual void SetMargin(float margin) { - if (m_collisionShape) - m_collisionShape->setMargin(btScalar(margin)); + if (m_collisionShape) { + m_collisionShape->setMargin(margin); + // if the shape use a unscaled shape we have also to set the correct margin in it + if (m_collisionShape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) + ((btScaledBvhTriangleMeshShape *)m_collisionShape)->getChildShape()->setMargin(margin); + } } virtual float GetMargin() const { -- cgit v1.2.3 From 8697c19e91d128d91026ac043f2570583a689724 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 12 May 2015 16:40:22 +0500 Subject: Depsgraph: Don't use C++11 function binding with MSVC It has some weird incompatibility with the way how Boost and GCC C++11 function bindings works, resulting in compilation errors. --- source/blender/depsgraph/util/depsgraph_util_function.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/depsgraph/util/depsgraph_util_function.h b/source/blender/depsgraph/util/depsgraph_util_function.h index f62efd76267..0f5582812f1 100644 --- a/source/blender/depsgraph/util/depsgraph_util_function.h +++ b/source/blender/depsgraph/util/depsgraph_util_function.h @@ -25,7 +25,7 @@ #ifndef __DEPSGRAPH_UTIL_FUNCTION_H__ #define __DEPSGRAPH_UTIL_FUNCTION_H__ -#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800) +#if (__cplusplus > 199711L) #include -- cgit v1.2.3 From 7c2905b8ec6fb2a8f4929c1f0b631a8b9d391c03 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 12 May 2015 17:24:07 +0500 Subject: Fix T44398: Compositing displace node makes image fuzzy with zero displacement EWA filtering with zero derivatives is introducing some fuzzyness into the image. Currently solved by using regular sampling for cases when derivatives are zero, which should also make compo faster in that areas. Still need to look into checking if EWA filter can be tweaked in a way so no fuzzyness is introduced. --- source/blender/compositor/operations/COM_DisplaceOperation.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/source/blender/compositor/operations/COM_DisplaceOperation.cpp b/source/blender/compositor/operations/COM_DisplaceOperation.cpp index 643ecf9708c..e749157d330 100644 --- a/source/blender/compositor/operations/COM_DisplaceOperation.cpp +++ b/source/blender/compositor/operations/COM_DisplaceOperation.cpp @@ -55,9 +55,13 @@ void DisplaceOperation::executePixelSampled(float output[4], float x, float y, P float uv[2], deriv[2][2]; pixelTransform(xy, uv, deriv); - - /* EWA filtering (without nearest it gets blurry with NO distortion) */ - this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1], COM_PS_BILINEAR); + if(is_zero_v2(deriv[0]) && is_zero_v2(deriv[1])) { + this->m_inputColorProgram->readSampled(output, uv[0], uv[1], COM_PS_BILINEAR); + } + else { + /* EWA filtering (without nearest it gets blurry with NO distortion) */ + this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1], COM_PS_BILINEAR); + } } bool DisplaceOperation::read_displacement(float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v) -- cgit v1.2.3 From f0f481031cc5eb57e848ca11a6989565c74a0e56 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 12 May 2015 18:33:31 +0500 Subject: Fix T44616: Cycles crashes loading 42k by 21k textures Simple integer overflow issue. TODO(sergey): Check on CPU cubic sampling, it might also need size_t. --- intern/cycles/blender/blender_session.cpp | 23 +++++++++++++---------- intern/cycles/render/image.cpp | 29 ++++++++++++++++------------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 897514668f6..bb345e2b3cf 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -1020,18 +1020,19 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name, void *buil unsigned char *image_pixels; image_pixels = image_get_pixels_for_frame(b_image, frame); + size_t num_pixels = ((size_t)width) * height; if(image_pixels) { - memcpy(pixels, image_pixels, width * height * channels * sizeof(unsigned char)); + memcpy(pixels, image_pixels, num_pixels * channels * sizeof(unsigned char)); MEM_freeN(image_pixels); } else { if(channels == 1) { - memset(pixels, 0, width * height * sizeof(unsigned char)); + memset(pixels, 0, num_pixels * sizeof(unsigned char)); } else { unsigned char *cp = pixels; - for(int i = 0; i < width * height; i++, cp += channels) { + for(size_t i = 0; i < num_pixels; i++, cp += channels) { cp[0] = 255; cp[1] = 0; cp[2] = 255; @@ -1043,7 +1044,7 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name, void *buil /* premultiply, byte images are always straight for blender */ unsigned char *cp = pixels; - for(int i = 0; i < width * height; i++, cp += channels) { + for(size_t i = 0; i < num_pixels; i++, cp += channels) { cp[0] = (cp[0] * cp[3]) >> 8; cp[1] = (cp[1] * cp[3]) >> 8; cp[2] = (cp[2] * cp[3]) >> 8; @@ -1072,18 +1073,19 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void float *image_pixels; image_pixels = image_get_float_pixels_for_frame(b_image, frame); + size_t num_pixels = ((size_t)width) * height; if(image_pixels) { - memcpy(pixels, image_pixels, width * height * channels * sizeof(float)); + memcpy(pixels, image_pixels, num_pixels * channels * sizeof(float)); MEM_freeN(image_pixels); } else { if(channels == 1) { - memset(pixels, 0, width * height * sizeof(float)); + memset(pixels, 0, num_pixels * sizeof(float)); } else { float *fp = pixels; - for(int i = 0; i < width * height; i++, fp += channels) { + for(int i = 0; i < num_pixels; i++, fp += channels) { fp[0] = 1.0f; fp[1] = 0.0f; fp[2] = 1.0f; @@ -1109,11 +1111,12 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void int width = resolution.x * amplify; int height = resolution.y * amplify; int depth = resolution.z * amplify; + size_t num_pixels = ((size_t)width) * height * depth; if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) { SmokeDomainSettings_density_grid_get_length(&b_domain.ptr, &length); - if(length == width*height*depth) { + if(length == num_pixels) { SmokeDomainSettings_density_grid_get(&b_domain.ptr, pixels); return true; } @@ -1123,7 +1126,7 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void * as 1500..3000 K with the first part faded to zero density */ SmokeDomainSettings_flame_grid_get_length(&b_domain.ptr, &length); - if(length == width*height*depth) { + if(length == num_pixels) { SmokeDomainSettings_flame_grid_get(&b_domain.ptr, pixels); return true; } @@ -1132,7 +1135,7 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void /* the RGB is "premultiplied" by density for better interpolation results */ SmokeDomainSettings_color_grid_get_length(&b_domain.ptr, &length); - if(length == width*height*depth*4) { + if(length == num_pixels*4) { SmokeDomainSettings_color_grid_get(&b_domain.ptr, pixels); return true; } diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index f0608965d09..c62afcd7719 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -407,7 +407,7 @@ bool ImageManager::file_load_image(Image *img, device_vector& tex_img) int scanlinesize = width*components*sizeof(uchar); in->read_image(TypeDesc::UINT8, - (uchar*)pixels + (height-1)*scanlinesize, + (uchar*)pixels + (((size_t)height)-1)*scanlinesize, AutoStride, -scanlinesize, AutoStride); @@ -425,9 +425,10 @@ bool ImageManager::file_load_image(Image *img, device_vector& tex_img) builtin_image_pixels_cb(img->filename, img->builtin_data, pixels); } + size_t num_pixels = ((size_t)width) * height * depth; if(cmyk) { /* CMYK */ - for(int i = width*height*depth-1; i >= 0; i--) { + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255; pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255; pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255; @@ -436,7 +437,7 @@ bool ImageManager::file_load_image(Image *img, device_vector& tex_img) } else if(components == 2) { /* grayscale + alpha */ - for(int i = width*height*depth-1; i >= 0; i--) { + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { pixels[i*4+3] = pixels[i*2+1]; pixels[i*4+2] = pixels[i*2+0]; pixels[i*4+1] = pixels[i*2+0]; @@ -445,7 +446,7 @@ bool ImageManager::file_load_image(Image *img, device_vector& tex_img) } else if(components == 3) { /* RGB */ - for(int i = width*height*depth-1; i >= 0; i--) { + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { pixels[i*4+3] = 255; pixels[i*4+2] = pixels[i*3+2]; pixels[i*4+1] = pixels[i*3+1]; @@ -454,7 +455,7 @@ bool ImageManager::file_load_image(Image *img, device_vector& tex_img) } else if(components == 1) { /* grayscale */ - for(int i = width*height*depth-1; i >= 0; i--) { + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { pixels[i*4+3] = 255; pixels[i*4+2] = pixels[i]; pixels[i*4+1] = pixels[i]; @@ -463,7 +464,7 @@ bool ImageManager::file_load_image(Image *img, device_vector& tex_img) } if(img->use_alpha == false) { - for(int i = width*height*depth-1; i >= 0; i--) { + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { pixels[i*4+3] = 255; } } @@ -529,7 +530,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector& tex_ vector tmppixels; if(components > 4) { - tmppixels.resize(width*height*components); + tmppixels.resize(((size_t)width)*height*components); readpixels = &tmppixels[0]; } @@ -547,7 +548,8 @@ bool ImageManager::file_load_float_image(Image *img, device_vector& tex_ } if(components > 4) { - for(int i = width*height-1; i >= 0; i--) { + size_t dimensions = ((size_t)width)*height; + for(size_t i = dimensions-1, pixel = 0; pixel < dimensions; pixel++, i--) { pixels[i*4+3] = tmppixels[i*components+3]; pixels[i*4+2] = tmppixels[i*components+2]; pixels[i*4+1] = tmppixels[i*components+1]; @@ -566,9 +568,10 @@ bool ImageManager::file_load_float_image(Image *img, device_vector& tex_ builtin_image_float_pixels_cb(img->filename, img->builtin_data, pixels); } + size_t num_pixels = ((size_t)width) * height * depth; if(cmyk) { /* CMYK */ - for(int i = width*height*depth-1; i >= 0; i--) { + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { pixels[i*4+3] = 255; pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255; pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255; @@ -577,7 +580,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector& tex_ } else if(components == 2) { /* grayscale + alpha */ - for(int i = width*height*depth-1; i >= 0; i--) { + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { pixels[i*4+3] = pixels[i*2+1]; pixels[i*4+2] = pixels[i*2+0]; pixels[i*4+1] = pixels[i*2+0]; @@ -586,7 +589,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector& tex_ } else if(components == 3) { /* RGB */ - for(int i = width*height*depth-1; i >= 0; i--) { + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { pixels[i*4+3] = 1.0f; pixels[i*4+2] = pixels[i*3+2]; pixels[i*4+1] = pixels[i*3+1]; @@ -595,7 +598,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector& tex_ } else if(components == 1) { /* grayscale */ - for(int i = width*height*depth-1; i >= 0; i--) { + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { pixels[i*4+3] = 1.0f; pixels[i*4+2] = pixels[i]; pixels[i*4+1] = pixels[i]; @@ -604,7 +607,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector& tex_ } if(img->use_alpha == false) { - for(int i = width*height*depth-1; i >= 0; i--) { + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { pixels[i*4+3] = 1.0f; } } -- cgit v1.2.3 From 15016e14977abdf350c7b452d0333e98e75d5426 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Tue, 12 May 2015 11:36:52 -0300 Subject: small cleanup on render_result_new() (making the duplicate code more like the original one) --- source/blender/render/intern/source/render_result.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 019484f7ed2..525c035b13d 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -562,7 +562,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf RenderView *rv; SceneRenderLayer *srl; int rectx, recty; - int nr, i; + int nr; rectx = BLI_rcti_size_x(partrct); recty = BLI_rcti_size_y(partrct); @@ -728,15 +728,11 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf if (strcmp(view, viewname) != 0) continue; - if (rr->do_exr_tile) { + if (rr->do_exr_tile) IMB_exr_add_view(rl->exrhandle, view); - for (i=0; i < 4; i++) - IMB_exr_add_channel(rl->exrhandle, rl->name, name_from_passtype(SCE_PASS_COMBINED, i), view, 0, 0, NULL); - } - else { - render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view); - } + /* a renderlayer should always have a Combined pass */ + render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view); } /* note, this has to be in sync with scene.c */ -- cgit v1.2.3 From f0974530068d1c04285010673e6512e29c674227 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 12 May 2015 19:52:42 +0500 Subject: Fix missing define in blenloader It caused blender versions compiled with scons not having proper build date/hash stored in the .blend file. --- source/blender/blenloader/SConscript | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/blender/blenloader/SConscript b/source/blender/blenloader/SConscript index bd002e59fa4..31dfc71ac73 100644 --- a/source/blender/blenloader/SConscript +++ b/source/blender/blenloader/SConscript @@ -43,11 +43,14 @@ incs = [ env['BF_ZLIB_INC'], ] +defs = [] + +if env['BF_BUILDINFO']: + defs.append('WITH_BUILDINFO') + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): incs.append(env['BF_PTHREADS_INC']) -defs = [] - if env['WITH_BF_INTERNATIONAL']: defs.append('WITH_INTERNATIONAL') -- cgit v1.2.3 From b01dd748b6a69ddda5687338d9755238beeb8440 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 28 Apr 2015 19:41:06 +0200 Subject: Dyntopo PBVH build optimization: Optimize the full rebuild case for now (though same code can be adapted to partial redraws) Main changes here: * Calculate bounding centroid for faces only once (instead of every intermediate node) * Faces do not get added to GSets immediately, instead we track a face array which has faces that belong in a node in consecutive order. Nodes just keep accounting of start and length in the array. * Due to faces not being added to GSets, we can skip doing cleanup of GSets and readdition for each intermediate node and instead only add the faces to the final leafs node GSets when those nodes are created. Results: For a 1.9 million face test model, PBVH generation time (roughly measured by undoing) is dropped from 6 seconds to about 4 seconds. Still too high, but still a nice improvement. TODO: Thread some parts. Unfortunately threading the GSet assignment part might not help much since we'd need a lot of locking to avoid collisions with node assignments, especially for unique vertices. --- source/blender/blenkernel/intern/pbvh_bmesh.c | 272 +++++++++++++++++++++++--- 1 file changed, 247 insertions(+), 25 deletions(-) diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 02b8cdba05b..a6e0ca31cf7 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -29,6 +29,7 @@ #include "BLI_ghash.h" #include "BLI_heap.h" #include "BLI_math.h" +#include "BLI_memarena.h" #include "BKE_ccg.h" #include "BKE_DerivedMesh.h" @@ -1415,28 +1416,211 @@ void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode) } } -/***************************** Public API *****************************/ +typedef struct FastNodeBuildInfo { + int totface; /* number of faces */ + int start; /* start of faces in array */ + struct FastNodeBuildInfo *child1; + struct FastNodeBuildInfo *child2; +} FastNodeBuildInfo; -static void pbvh_bmesh_node_layers_reset(PBVH *bvh) +/* Recursively split the node if it exceeds the leaf_limit. This function is multithreadabe since each invocation applies + * to a sub part of the arrays */ +static void pbvh_bmesh_node_limit_ensure_fast(PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array, FastNodeBuildInfo *node, MemArena *arena) { BMFace *f; - BMVert *v; - BMIter iter; - BMesh *bm = bvh->bm; - int cd_vert_node_offset = bvh->cd_vert_node_offset; - int cd_face_node_offset = bvh->cd_face_node_offset; + BB cb; + BBC *bbc; + float mid; + int axis, i; + int end; + FastNodeBuildInfo *child1, *child2; + int num_child1, num_child2; + BMFace *tmp; - /* clear the elements of the node information */ - BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) { - BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, DYNTOPO_NODE_NONE); + if (node->totface <= bvh->leaf_limit) { + return; } - BM_ITER_MESH(f, &iter, bm, BM_FACES_OF_MESH) { - BM_ELEM_CD_SET_INT(f, cd_face_node_offset, DYNTOPO_NODE_NONE); + /* Calculate bounding box around primitive centroids */ + BB_reset(&cb); + for (i = 0; i < node->totface; i++) { + f = nodeinfo[i + node->start]; + bbc = &bbc_array[BM_elem_index_get(f)]; + + BB_expand(&cb, bbc->bcentroid); + } + + /* initialize the children */ + + /* Find widest axis and its midpoint */ + axis = BB_widest_axis(&cb); + mid = (cb.bmax[axis] + cb.bmin[axis]) * 0.5f; + + num_child1 = 0, num_child2 = 0; + + /* split vertices along the middle line */ + end = node->start + node->totface; + for (i = node->start; i < end - num_child2; i++) { + f = nodeinfo[i]; + bbc = &bbc_array[BM_elem_index_get(f)]; + + if (bbc->bcentroid[axis] > mid) { + int i_iter = end - num_child2 - 1; + int candidate = -1; + /* found a face that should be part of another node, look for a face to substitute with */ + + for (;i_iter > i; i_iter--) { + BMFace *f_iter = nodeinfo[i_iter]; + const BBC *bbc_iter = &bbc_array[BM_elem_index_get(f_iter)]; + if (bbc_iter->bcentroid[axis] <= mid) { + candidate = i_iter; + break; + } + else { + num_child2++; + } + } + + if (candidate != -1) { + tmp = nodeinfo[i]; + nodeinfo[i] = nodeinfo[candidate]; + nodeinfo[candidate] = tmp; + /* increase both counts */ + num_child1++; + num_child2++; + } + else { + /* not finding candidate means second half of array part is full of + * second node parts, just increase the number of child nodes for it */ + num_child2++; + } + } + else { + num_child1++; + } + } + + /* ensure at least one child in each node */ + if (num_child2 == 0) { + num_child2++; + num_child1--; + } + else if (num_child1 == 0) { + num_child1++; + num_child2--; + } + + /* at this point, faces should have been split along the array range sequencially, each sequencial + * part belonging to one node only */ + BLI_assert((num_child1 + num_child2) == node->totface); + + node->child1 = child1 = BLI_memarena_alloc(arena, sizeof(FastNodeBuildInfo)); + node->child2 = child2 = BLI_memarena_alloc(arena, sizeof(FastNodeBuildInfo)); + + child1->totface = num_child1; + child1->start = node->start; + child2->totface = num_child2; + child2->start = node->start + num_child1; + child1->child1 = child1->child2 = child2->child1 = child2->child2 = NULL; + + pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, child1, arena); + pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, child2, arena); + + return; +} + +static void pbvh_bmesh_create_nodes_fast_recursive(PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array, FastNodeBuildInfo *node, int node_index) +{ + PBVHNode *n = bvh->nodes + node_index; + /* two cases, node does not have children or does have children */ + if (node->child1) { + int children_offset = bvh->totnode; + + n->children_offset = children_offset; + pbvh_grow_nodes(bvh, bvh->totnode + 2); + pbvh_bmesh_create_nodes_fast_recursive(bvh, nodeinfo, bbc_array, node->child1, children_offset); + pbvh_bmesh_create_nodes_fast_recursive(bvh, nodeinfo, bbc_array, node->child2, children_offset + 1); + + n = &bvh->nodes[node_index]; + + /* Update bounding box */ + BB_reset(&n->vb); + BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset].vb); + BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset + 1].vb); + n->orig_vb = n->vb; + } + else { + /* node does not have children so it's a leaf node, populate with faces and tag accordingly + * this is an expensive part but it's not so easily threadable due to vertex node indices */ + const int cd_vert_node_offset = bvh->cd_vert_node_offset; + const int cd_face_node_offset = bvh->cd_face_node_offset; + + bool has_visible = false; + int i, end; + BMFace *f; + BMLoop *l_iter; + BMLoop *l_first; + BMVert *v; + BBC *bbc; + + n->flag = PBVH_Leaf; + n->bm_faces = BLI_gset_ptr_new_ex("bm_faces", node->totface); + + /* Create vert hash sets */ + n->bm_unique_verts = BLI_gset_ptr_new("bm_unique_verts"); + n->bm_other_verts = BLI_gset_ptr_new("bm_other_verts"); + + BB_reset(&n->vb); + + end = node->start + node->totface; + + for (i = node->start; i < end; i++) { + f = nodeinfo[i]; + bbc = &bbc_array[BM_elem_index_get(f)]; + + /* Update ownership of faces */ + BLI_gset_insert(n->bm_faces, f); + BM_ELEM_CD_SET_INT(f, cd_face_node_offset, node_index); + + /* Update vertices */ + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + v = l_iter->v; + if (!BLI_gset_haskey(n->bm_unique_verts, v)) { + if (BM_ELEM_CD_GET_INT(v, cd_vert_node_offset) != DYNTOPO_NODE_NONE) { + BLI_gset_add(n->bm_other_verts, v); + } + else { + BLI_gset_insert(n->bm_unique_verts, v); + BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, node_index); + } + } + /* Update node bounding box */ + } while ((l_iter = l_iter->next) != l_first); + + if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) + has_visible = true; + + BB_expand_with_bb(&n->vb, (BB *)bbc); + } + + BLI_assert(n->vb.bmin[0] <= n->vb.bmax[0] && + n->vb.bmin[1] <= n->vb.bmax[1] && + n->vb.bmin[2] <= n->vb.bmax[2]); + + n->orig_vb = n->vb; + + /* Build GPU buffers for new node and update vertex normals */ + BKE_pbvh_node_mark_rebuild_draw(n); + + BKE_pbvh_node_fully_hidden_set(n, !has_visible); + n->flag |= PBVH_UpdateNormals; } } +/***************************** Public API *****************************/ + /* Build a PBVH from a BMesh */ void BKE_pbvh_build_bmesh( PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log, @@ -1444,8 +1628,13 @@ void BKE_pbvh_build_bmesh( { BMIter iter; BMFace *f; - PBVHNode *n; - int node_index = 0; + BMVert *v; + int i; + /* bounding box array of all faces, no need to recalculate every time */ + BBC *bbc_array; + BMFace **nodeinfo; + FastNodeBuildInfo rootnode = {0}; + MemArena *arena; bvh->cd_vert_node_offset = cd_vert_node_offset; bvh->cd_face_node_offset = cd_face_node_offset; @@ -1462,21 +1651,54 @@ void BKE_pbvh_build_bmesh( if (smooth_shading) bvh->flags |= PBVH_DYNTOPO_SMOOTH_SHADING; - pbvh_bmesh_node_layers_reset(bvh); + /* calculate all bounding boxes once for all faces */ + bbc_array = MEM_mallocN(sizeof(BBC) * bm->totface, "BBC"); + nodeinfo = MEM_mallocN(sizeof(*nodeinfo) * bm->totface, "nodeinfo"); + arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "fast PBVH node storage"); + + BM_ITER_MESH_INDEX(f, &iter, bm, BM_FACES_OF_MESH, i) { + BBC *bbc = &bbc_array[i]; + BMLoop *l_iter; + BMLoop *l_first; + + BB_reset((BB *)bbc); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BB_expand((BB *)bbc, l_iter->v->co); + } while ((l_iter = l_iter->next) != l_first); + BBC_update_centroid(bbc); + + /* so we can do direct lookups on 'bbc_array' */ + BM_elem_index_set(f, i); /* set_dirty! */ + nodeinfo[i] = f; + BM_ELEM_CD_SET_INT(f, cd_face_node_offset, DYNTOPO_NODE_NONE); + } + + BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, DYNTOPO_NODE_NONE); + } + + /* likely this is already dirty */ + bm->elem_index_dirty |= BM_FACE; + + /* setup root node */ + rootnode.totface = bm->totface; + + /* start recursion, assign faces to nodes accordingly */ + pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, &rootnode, arena); + + /* we now have all faces assigned to a node, next we need to assign those to the gsets of the nodes */ /* Start with all faces in the root node */ - n = bvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode"); + bvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode"); bvh->totnode = 1; - n->flag = PBVH_Leaf; - n->bm_faces = BLI_gset_ptr_new_ex("bm_faces", bvh->bm->totface); - BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) { - BLI_gset_insert(n->bm_faces, f); - } - /* Recursively split the node until it is under the limit; if no - * splitting occurs then finalize the existing leaf node */ - if (!pbvh_bmesh_node_limit_ensure(bvh, node_index)) - pbvh_bmesh_node_finalize(bvh, 0, cd_vert_node_offset, cd_face_node_offset); + /* take root node and visit and populate children recursively */ + pbvh_bmesh_create_nodes_fast_recursive(bvh, nodeinfo, bbc_array, &rootnode, 0); + + BLI_memarena_free(arena); + MEM_freeN(bbc_array); + MEM_freeN(nodeinfo); } /* Collapse short edges, subdivide long edges */ -- cgit v1.2.3 From 3160740421cfef1cee61478baadddd256af2dfca Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 May 2015 05:25:26 +1000 Subject: Fix T40762: Python can't access macro values --- source/blender/makesrna/intern/rna_wm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 3b8ddd011c0..4446f5d9a2b 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -1501,6 +1501,11 @@ static void rna_def_operator(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL | PROP_ENUM_FLAG); RNA_def_property_ui_text(prop, "Options", "Options for this operator type"); + prop = RNA_def_property(srna, "macros", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "macro", NULL); + RNA_def_property_struct_type(prop, "Macro"); + RNA_def_property_ui_text(prop, "Macros", ""); + RNA_api_operator(srna); srna = RNA_def_struct(brna, "OperatorProperties", NULL); -- cgit v1.2.3 From e4cd4c383f13eb9705d9f5d3536c0b2b72e727bd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 May 2015 06:10:49 +1000 Subject: Cleanup: style --- source/blender/blenkernel/BKE_armature.h | 10 ++++++---- source/blender/blenkernel/intern/armature.c | 10 ++++++---- source/blender/blenkernel/intern/armature_update.c | 2 +- source/blender/blenkernel/intern/curve.c | 2 +- source/blender/blenkernel/intern/depsgraph.c | 4 ++-- source/blender/blenkernel/intern/object_update.c | 4 ++-- .../operations/COM_DisplaceOperation.cpp | 2 +- source/blender/depsgraph/intern/depsgraph.h | 2 +- source/blender/depsgraph/intern/depsgraph_build.cc | 7 ++++--- .../depsgraph/intern/depsgraph_build_nodes.cc | 14 +++++++------- .../depsgraph/intern/depsgraph_build_relations.cc | 22 +++++++++++----------- source/blender/depsgraph/intern/depsgraph_debug.cc | 10 ++++++---- source/blender/depsgraph/intern/depsgraph_tag.cc | 20 ++++++++++---------- source/blender/depsgraph/intern/depsgraph_types.h | 2 +- source/blender/depsgraph/intern/depsnode.h | 2 +- .../depsgraph/util/depsgraph_util_function.h | 2 +- .../depsgraph/util/depsgraph_util_pchanmap.h | 4 ++-- source/blender/editors/interface/interface.c | 3 ++- 18 files changed, 65 insertions(+), 57 deletions(-) diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 5bdf360ded2..a834a83ca00 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -148,10 +148,12 @@ struct bPose; struct bSplineIKConstraint; struct EvaluationContext; -struct bPoseChannel *BKE_armature_ik_solver_find_root(struct bPoseChannel *pchan, - struct bKinematicConstraint *data); -struct bPoseChannel* BKE_armature_splineik_solver_find_root(struct bPoseChannel *pchan, - struct bSplineIKConstraint *data); +struct bPoseChannel *BKE_armature_ik_solver_find_root( + struct bPoseChannel *pchan, + struct bKinematicConstraint *data); +struct bPoseChannel *BKE_armature_splineik_solver_find_root( + struct bPoseChannel *pchan, + struct bSplineIKConstraint *data); void BKE_pose_splineik_init_tree(struct Scene *scene, struct Object *ob, float ctime); void BKE_splineik_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan_root, float ctime); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 498609e62ea..27d3d1c50fb 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2221,8 +2221,9 @@ BoundBox *BKE_armature_boundbox_get(Object *ob) /************** Graph evaluation ********************/ -bPoseChannel *BKE_armature_ik_solver_find_root(bPoseChannel *pchan, - bKinematicConstraint *data) +bPoseChannel *BKE_armature_ik_solver_find_root( + bPoseChannel *pchan, + bKinematicConstraint *data) { bPoseChannel *rootchan = pchan; if (!(data->flag & CONSTRAINT_IK_TIP)) { @@ -2243,8 +2244,9 @@ bPoseChannel *BKE_armature_ik_solver_find_root(bPoseChannel *pchan, return rootchan; } -bPoseChannel* BKE_armature_splineik_solver_find_root(bPoseChannel *pchan, - bSplineIKConstraint *data) +bPoseChannel *BKE_armature_splineik_solver_find_root( + bPoseChannel *pchan, + bSplineIKConstraint *data) { bPoseChannel *rootchan = pchan; int segcount = 0; diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index aa36036ed6a..ceda9f056bb 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -629,7 +629,7 @@ void BKE_pose_constraints_evaluate(EvaluationContext *UNUSED(eval_ctx), Object *ob, bPoseChannel *pchan) { - Scene *scene = (Scene*)G.main->scene.first; + Scene *scene = G.main->scene.first; DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, pchan->name); if (pchan->flag & POSE_IKTREE || pchan->flag & POSE_IKSPLINE) { /* IK are being solved separately/ */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index c95b0055683..c01b3431d09 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1394,7 +1394,7 @@ void BKE_curve_forward_diff_tangent_bezier(float q0, float q1, float q2, float q rt0 = 3.0f * (q1 - q0); rt1 = f * (3.0f * (q3 - q0) + 9.0f * (q1 - q2)); - rt2 = 6.0f * (q0 + q2)- 12.0f * q1; + rt2 = 6.0f * (q0 + q2) - 12.0f * q1; q0 = rt0; q1 = f * (rt1 + rt2); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 9ee9f3d57af..2fd53045e29 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -3235,7 +3235,7 @@ short DAG_get_eval_flags_for_object(Scene *scene, void *object) DagNode *node; if (!DEG_depsgraph_use_legacy()) { - return DEG_get_eval_flags_for_id(scene->depsgraph, (ID*)object); + return DEG_get_eval_flags_for_id(scene->depsgraph, (ID *)object); } if (scene->theDag == NULL) { @@ -3541,7 +3541,7 @@ void DAG_ids_clear_recalc(Main *bmain) short DAG_get_eval_flags_for_object(Scene *scene, void *object) { - return DEG_get_eval_flags_for_id(scene->depsgraph, (ID*)object); + return DEG_get_eval_flags_for_id(scene->depsgraph, (ID *)object); } void DAG_ids_flush_tagged(Main *bmain) diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 972a93b4a35..46d68e7ccab 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -322,7 +322,7 @@ void BKE_object_eval_uber_transform(EvaluationContext *UNUSED(eval_ctx), copy_m4_m4(ob->obmat, ob->proxy_from->obmat); } - ob->recalc &= ~(OB_RECALC_OB|OB_RECALC_TIME); + ob->recalc &= ~(OB_RECALC_OB | OB_RECALC_TIME); if (ob->data == NULL) { ob->recalc &= ~OB_RECALC_DATA; } @@ -336,5 +336,5 @@ void BKE_object_eval_uber_data(EvaluationContext *eval_ctx, BLI_assert(ob->type != OB_ARMATURE); BKE_object_handle_data_update(eval_ctx, scene, ob); - ob->recalc &= ~(OB_RECALC_DATA|OB_RECALC_TIME); + ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME); } diff --git a/source/blender/compositor/operations/COM_DisplaceOperation.cpp b/source/blender/compositor/operations/COM_DisplaceOperation.cpp index e749157d330..6dfef8a0a11 100644 --- a/source/blender/compositor/operations/COM_DisplaceOperation.cpp +++ b/source/blender/compositor/operations/COM_DisplaceOperation.cpp @@ -55,7 +55,7 @@ void DisplaceOperation::executePixelSampled(float output[4], float x, float y, P float uv[2], deriv[2][2]; pixelTransform(xy, uv, deriv); - if(is_zero_v2(deriv[0]) && is_zero_v2(deriv[1])) { + if (is_zero_v2(deriv[0]) && is_zero_v2(deriv[1])) { this->m_inputColorProgram->readSampled(output, uv[0], uv[1], COM_PS_BILINEAR); } else { diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index 8ce73626c13..0232410b958 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -72,7 +72,7 @@ struct DepsRelation { DepsNode *to; /* B */ /* relationship attributes */ - const char* name; /* label for debugging */ + const char *name; /* label for debugging */ eDepsRelation_Type type; /* type */ int flag; /* (eDepsRelation_Flag) */ diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index b5e09db6507..15b8cc0fb3a 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -178,7 +178,7 @@ string deg_fcurve_id_name(const FCurve *fcu) static void deg_graph_build_finalize(Depsgraph *graph) { - std::stack stack; + std::stack stack; for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin(); it_op != graph->operations.end(); @@ -192,8 +192,9 @@ static void deg_graph_build_finalize(Depsgraph *graph) ++it_rel) { DepsRelation *rel = *it_rel; - if (rel->from->type == DEPSNODE_TYPE_OPERATION && - (rel->flag & DEPSREL_FLAG_CYCLIC) == 0) { + if ((rel->from->type == DEPSNODE_TYPE_OPERATION) && + (rel->flag & DEPSREL_FLAG_CYCLIC) == 0) + { ++node->num_links_pending; } } diff --git a/source/blender/depsgraph/intern/depsgraph_build_nodes.cc b/source/blender/depsgraph/intern/depsgraph_build_nodes.cc index a55fb900551..02538d92480 100644 --- a/source/blender/depsgraph/intern/depsgraph_build_nodes.cc +++ b/source/blender/depsgraph/intern/depsgraph_build_nodes.cc @@ -124,7 +124,7 @@ RootDepsNode *DepsgraphNodeBuilder::add_root_node() IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id) { const char *idtype_name = BKE_idcode_to_name(GS(id->name)); - return m_graph->add_id_node(id, string(id->name+2) + "[" + idtype_name + "]"); + return m_graph->add_id_node(id, string(id->name + 2) + "[" + idtype_name + "]"); } TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source(ID *id) @@ -404,8 +404,8 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) id_node->eval_flags |= DAG_EVAL_NEED_CURVE_PATH; } } + break; } - break; case OB_ARMATURE: /* Pose */ if (ob->id.lib != NULL && ob->proxy_from != NULL) { @@ -972,8 +972,8 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob) add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY, DEPSOP_TYPE_INIT, function_bind(BKE_mesh_eval_geometry, _1, (Mesh *)obdata), DEG_OPCODE_PLACEHOLDER, "Geometry Eval"); + break; } - break; case OB_MBALL: { @@ -987,8 +987,8 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob) DEPSOP_TYPE_INIT, function_bind(BKE_mball_eval_geometry, _1, (MetaBall *)obdata), DEG_OPCODE_PLACEHOLDER, "Geometry Eval"); } + break; } - break; case OB_CURVE: case OB_FONT: @@ -1003,8 +1003,8 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob) add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY, DEPSOP_TYPE_EXEC, function_bind(BKE_curve_eval_path, _1, (Curve *)obdata), DEG_OPCODE_GEOMETRY_PATH, "Path"); + break; } - break; case OB_SURF: /* Nurbs Surface */ { @@ -1012,8 +1012,8 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob) add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY, DEPSOP_TYPE_INIT, function_bind(BKE_curve_eval_geometry, _1, (Curve *)obdata), DEG_OPCODE_PLACEHOLDER, "Geometry Eval"); + break; } - break; case OB_LATTICE: /* Lattice */ { @@ -1021,8 +1021,8 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob) add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY, DEPSOP_TYPE_INIT, function_bind(BKE_lattice_eval_geometry, _1, (Lattice *)obdata), DEG_OPCODE_PLACEHOLDER, "Geometry Eval"); + break; } - break; } add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY, diff --git a/source/blender/depsgraph/intern/depsgraph_build_relations.cc b/source/blender/depsgraph/intern/depsgraph_build_relations.cc index 300ed07de56..b9248318814 100644 --- a/source/blender/depsgraph/intern/depsgraph_build_relations.cc +++ b/source/blender/depsgraph/intern/depsgraph_build_relations.cc @@ -399,8 +399,8 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o case OB_LATTICE: { build_obdata_geom(bmain, scene, ob); + break; } - break; case OB_ARMATURE: /* Pose */ @@ -446,8 +446,8 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob) { ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM); add_relation(parent_key, ob_key, DEPSREL_TYPE_STANDARD, "Armature Deform Parent"); + break; } - break; case PARVERT1: /* Vertex Parent */ case PARVERT3: @@ -459,15 +459,15 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob) ComponentKey transform_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM); add_relation(transform_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Vertex Parent TFM"); + break; } - break; case PARBONE: /* Bone Parent */ { ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_BONE, ob->parsubstr); add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Bone Parent"); + break; } - break; default: { @@ -502,8 +502,8 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob) ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM); add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Parent"); } + break; } - break; } /* exception case: parent is duplivert */ @@ -696,7 +696,7 @@ void DepsgraphRelationBuilder::build_animdata(ID *id) /* prevent driver from occurring before own animation... */ if (adt->action || adt->nla_tracks.first) { add_relation(adt_key, driver_key, DEPSREL_TYPE_OPERATION, - "[AnimData Before Drivers]"); + "[AnimData Before Drivers]"); } } } @@ -1249,7 +1249,7 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob, // TODO: the bigggest point here is that we need the curve PATH and not just the general geometry... ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY); ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE); - add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM,"[Curve.Path -> Spline IK] DepsRel"); + add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, "[Curve.Path -> Spline IK] DepsRel"); } pchan->flag |= POSE_DONE; @@ -1595,8 +1595,8 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje ComponentKey mom_key(&mom->id, DEPSNODE_TYPE_GEOMETRY); add_relation(geom_key, mom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Metaball Motherball"); } + break; } - break; case OB_CURVE: case OB_FONT: @@ -1619,18 +1619,18 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje add_relation(textoncurve_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Text on Curve"); } } + break; } - break; case OB_SURF: /* Nurbs Surface */ { + break; } - break; case OB_LATTICE: /* Lattice */ { + break; } - break; } /* ShapeKeys */ diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc index c876640b462..7c044980d7f 100644 --- a/source/blender/depsgraph/intern/depsgraph_debug.cc +++ b/source/blender/depsgraph/intern/depsgraph_debug.cc @@ -917,14 +917,16 @@ DepsgraphStatsID *DepsgraphDebug::get_id_stats(ID *id, bool create) return id_stats; } -DepsgraphStatsComponent *DepsgraphDebug::get_component_stats(DepsgraphStatsID *id_stats, - const string &name, - bool create) +DepsgraphStatsComponent *DepsgraphDebug::get_component_stats( + DepsgraphStatsID *id_stats, + const string &name, + bool create) { DepsgraphStatsComponent *comp_stats; for (comp_stats = (DepsgraphStatsComponent *)id_stats->components.first; comp_stats != NULL; - comp_stats = comp_stats->next) { + comp_stats = comp_stats->next) + { if (STREQ(comp_stats->name, name.c_str())) break; } diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 2f8cdfc1fd5..8549fce6aed 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -152,7 +152,7 @@ void DEG_id_tag_update(ID *id, short flag) void DEG_id_tag_update_ex(Main *bmain, ID *id, short flag) { - if(id == NULL) { + if (id == NULL) { /* Ideally should not happen, but old depsgraph allowed this. */ return; } @@ -173,14 +173,14 @@ void DEG_id_tag_update_ex(Main *bmain, ID *id, short flag) continue; } if (flag & OB_RECALC_DATA && GS(id->name) == ID_OB) { - Object *object = (Object*)id; + Object *object = (Object *)id; if (object->data != NULL) { DEG_graph_id_tag_update(bmain, graph, - (ID*)object->data); + (ID *)object->data); } } - if (flag & (OB_RECALC_OB|OB_RECALC_DATA)) { + if (flag & (OB_RECALC_OB | OB_RECALC_DATA)) { DEG_graph_id_tag_update(bmain, graph, id); } } @@ -210,7 +210,7 @@ void DEG_id_type_tag(Main *bmain, short idtype) /* FIFO queue for tagged nodes that need flushing */ /* XXX This may get a dedicated implementation later if needed - lukas */ -typedef std::queue FlushQueue; +typedef std::queue FlushQueue; /* Flush updates from tagged nodes outwards until all affected nodes are tagged. */ void DEG_graph_flush_updates(Main *bmain, Depsgraph *graph) @@ -317,9 +317,9 @@ void DEG_graph_flush_updates(Main *bmain, Depsgraph *graph) */ void DEG_ids_flush_tagged(Main *bmain) { - for (Scene *scene = (Scene*)bmain->scene.first; + for (Scene *scene = (Scene *)bmain->scene.first; scene != NULL; - scene = (Scene*)scene->id.next) + scene = (Scene *)scene->id.next) { /* TODO(sergey): Only visible scenes? */ if (scene->depsgraph != NULL) { @@ -417,9 +417,9 @@ void DEG_graph_on_visible_update(Main *bmain, Scene *scene) void DEG_on_visible_update(Main *bmain, const bool UNUSED(do_time)) { - for (Scene *scene = (Scene*)bmain->scene.first; + for (Scene *scene = (Scene *)bmain->scene.first; scene != NULL; - scene = (Scene*)scene->id.next) + scene = (Scene *)scene->id.next) { if (scene->depsgraph != NULL) { DEG_graph_on_visible_update(bmain, scene); @@ -440,7 +440,7 @@ void DEG_ids_check_recalc(Main *bmain, Scene *scene, bool time) a = set_listbasepointers(bmain, lbarray); while (a--) { ListBase *lb = lbarray[a]; - ID *id = (ID*)lb->first; + ID *id = (ID *)lb->first; /* We tag based on first ID type character to avoid * looping over all ID's in case there are no tags. diff --git a/source/blender/depsgraph/intern/depsgraph_types.h b/source/blender/depsgraph/intern/depsgraph_types.h index 2a84f4587af..713fec8965d 100644 --- a/source/blender/depsgraph/intern/depsgraph_types.h +++ b/source/blender/depsgraph/intern/depsgraph_types.h @@ -53,7 +53,7 @@ struct FCurve; /* Evaluation Operation for atomic operation */ // XXX: move this to another header that can be exposed? -typedef function DepsEvalOperationCb; +typedef function DepsEvalOperationCb; /* Metatype of Nodes - The general "level" in the graph structure the node serves */ typedef enum eDepsNode_Class { diff --git a/source/blender/depsgraph/intern/depsnode.h b/source/blender/depsgraph/intern/depsnode.h index 067bd771e87..993bb6971e7 100644 --- a/source/blender/depsgraph/intern/depsnode.h +++ b/source/blender/depsgraph/intern/depsnode.h @@ -168,7 +168,7 @@ struct IDDepsNode : public DepsNode { }; typedef unordered_map ComponentMap; void init(const ID *id, const string &subdata); diff --git a/source/blender/depsgraph/util/depsgraph_util_function.h b/source/blender/depsgraph/util/depsgraph_util_function.h index 0f5582812f1..976a9d6cc2b 100644 --- a/source/blender/depsgraph/util/depsgraph_util_function.h +++ b/source/blender/depsgraph/util/depsgraph_util_function.h @@ -59,7 +59,7 @@ public: function() {}; function(void *) {} operator bool() const { return false; } - bool operator== (void*) { return false; } + bool operator== (void *) { return false; } template void operator() (T1) { diff --git a/source/blender/depsgraph/util/depsgraph_util_pchanmap.h b/source/blender/depsgraph/util/depsgraph_util_pchanmap.h index 5d27d84c0da..82ec8654bc5 100644 --- a/source/blender/depsgraph/util/depsgraph_util_pchanmap.h +++ b/source/blender/depsgraph/util/depsgraph_util_pchanmap.h @@ -24,8 +24,8 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifndef ___DEPSGRAPH_UTIL_PCHANMAP_H__ -#define ___DEPSGRAPH_UTIL_PCHANMAP_H__ +#ifndef __DEPSGRAPH_UTIL_PCHANMAP_H__ +#define __DEPSGRAPH_UTIL_PCHANMAP_H__ struct RootPChanMap { /* ctor and dtor - Create and free the internal map respectively. */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index a9cc926b275..6d1d51eae0e 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -3237,7 +3237,8 @@ static uiBut *ui_def_but( return but; } -void ui_def_but_icon(uiBut *but, const int icon, const int flag) { +void ui_def_but_icon(uiBut *but, const int icon, const int flag) +{ if (icon) { ui_icon_ensure_deferred(but->block->evil_C, icon, (flag & UI_BUT_ICON_PREVIEW) != 0); } -- cgit v1.2.3 From 3e519860e5f0aa6a5cd1a1b71f9b07119e59593e Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Tue, 12 May 2015 18:18:57 -0300 Subject: Fix T44684 Compositor backdrop isn't updating correctly --- source/blender/blenkernel/intern/image.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 29576e4f1f6..f6513a3e016 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2398,6 +2398,7 @@ static void image_viewer_create_views(const RenderData *rd, Image *ima) void BKE_image_verify_viewer_views(const RenderData *rd, Image *ima, ImageUser *iuser) { bool do_reset; + const bool is_multiview = (rd->scemode & R_MULTIVIEW) != 0; BLI_lock_thread(LOCK_DRAW_IMAGE); @@ -2413,7 +2414,9 @@ void BKE_image_verify_viewer_views(const RenderData *rd, Image *ima, ImageUser * /* see if all scene render views are in the image view list */ do_reset = (BKE_scene_multiview_num_views_get(rd) != BLI_listbase_count(&ima->views)); - if (!do_reset) { + + /* multiview also needs to be sure all the views are synced */ + if (is_multiview && !do_reset) { SceneRenderView *srv; ImageView *iv; -- cgit v1.2.3 From ee3dde2d49983906ce7c5fb7d5802aea20ffb3ba Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 May 2015 07:23:03 +1000 Subject: UI: ObData support for copy-to-selected Now multi-object editing works for obdata too. --- source/blender/editors/interface/interface_ops.c | 47 ++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 892bbd8ea97..e0adc391a24 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -33,6 +33,7 @@ #include "DNA_screen_types.h" #include "DNA_text_types.h" /* for UI_OT_reports_to_text */ +#include "DNA_object_types.h" /* for OB_DATA_SUPPORT_ID */ #include "BLI_blenlib.h" #include "BLI_math_color.h" @@ -57,6 +58,7 @@ #include "WM_types.h" #include "ED_paint.h" +#include "ED_object.h" /* only for UI_OT_editsource */ #include "ED_screen.h" @@ -285,6 +287,51 @@ bool UI_context_copy_to_selected_list( *r_use_path_from_id = true; *r_path = RNA_path_from_ID_to_property(ptr, prop); } + else if (OB_DATA_SUPPORT_ID(GS(id->name))) { + /* check we're using the active object */ + + Object *ob = ED_object_context(C); + if (ob && ob->data == id) { + const short id_code = GS(id->name); + ListBase lb = CTX_data_collection_get(C, "selected_editable_objects"); + char *path = RNA_path_from_ID_to_property(ptr, prop); + + if (path) { + char *path_tmp; + path_tmp = path; + path = BLI_sprintfN("data%s%s", path[0] == '[' ? "" : ".", path); + MEM_freeN(path_tmp); + } + + /* de-duplicate obdata */ + if (!BLI_listbase_is_empty(&lb)) { + CollectionPointerLink *link, *link_next; + + for (link = lb.first; link; link = link->next) { + Object *ob = link->ptr.id.data; + if (ob->data) { + ID *id = ob->data; + id->flag |= LIB_DOIT; + } + } + + for (link = lb.first; link; link = link_next) { + Object *ob = link->ptr.id.data; + ID *id = ob->data; + link_next = link->next; + if ((id == NULL) || (id->flag & LIB_DOIT) == 0 || (GS(id->name) != id_code)) { + BLI_remlink(&lb, link); + MEM_freeN(link); + } + id->flag &= ~LIB_DOIT; + } + } + + *r_lb = lb; + *r_path = path; + } + + } else if (GS(id->name) == ID_SCE) { /* Sequencer's ID is scene :/ */ /* Try to recursively find an RNA_Sequence ancestor, to handle situations like T41062... */ -- cgit v1.2.3 From b3334d936f9e840d79fe224a71110302fc8cbee9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 May 2015 07:36:43 +1000 Subject: Edit last commit, redundant 'data' in RNA path --- source/blender/editors/interface/interface_ops.c | 68 +++++++++++------------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index e0adc391a24..7c4ee7b6649 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -58,7 +58,6 @@ #include "WM_types.h" #include "ED_paint.h" -#include "ED_object.h" /* only for UI_OT_editsource */ #include "ED_screen.h" @@ -289,48 +288,45 @@ bool UI_context_copy_to_selected_list( } else if (OB_DATA_SUPPORT_ID(GS(id->name))) { /* check we're using the active object */ - - Object *ob = ED_object_context(C); - if (ob && ob->data == id) { - const short id_code = GS(id->name); - ListBase lb = CTX_data_collection_get(C, "selected_editable_objects"); - char *path = RNA_path_from_ID_to_property(ptr, prop); - - if (path) { - char *path_tmp; - path_tmp = path; - path = BLI_sprintfN("data%s%s", path[0] == '[' ? "" : ".", path); - MEM_freeN(path_tmp); + const short id_code = GS(id->name); + ListBase lb = CTX_data_collection_get(C, "selected_editable_objects"); + char *path = RNA_path_from_ID_to_property(ptr, prop); + + /* de-duplicate obdata */ + if (!BLI_listbase_is_empty(&lb)) { + CollectionPointerLink *link, *link_next; + + for (link = lb.first; link; link = link->next) { + Object *ob = link->ptr.id.data; + if (ob->data) { + ID *id_data = ob->data; + id_data->flag |= LIB_DOIT; + } } - /* de-duplicate obdata */ - if (!BLI_listbase_is_empty(&lb)) { - CollectionPointerLink *link, *link_next; - - for (link = lb.first; link; link = link->next) { - Object *ob = link->ptr.id.data; - if (ob->data) { - ID *id = ob->data; - id->flag |= LIB_DOIT; - } + for (link = lb.first; link; link = link_next) { + Object *ob = link->ptr.id.data; + ID *id_data = ob->data; + link_next = link->next; + + if ((id_data == NULL) || + (id_data->flag & LIB_DOIT) == 0 || + (id_data->lib) || + (GS(id_data->name) != id_code)) + { + BLI_remlink(&lb, link); + MEM_freeN(link); } - - for (link = lb.first; link; link = link_next) { - Object *ob = link->ptr.id.data; - ID *id = ob->data; - link_next = link->next; - if ((id == NULL) || (id->flag & LIB_DOIT) == 0 || (GS(id->name) != id_code)) { - BLI_remlink(&lb, link); - MEM_freeN(link); - } - id->flag &= ~LIB_DOIT; + else { + /* avoid prepending 'data' to the path */ + RNA_id_pointer_create(id_data, &link->ptr); } + id_data->flag &= ~LIB_DOIT; } - - *r_lb = lb; - *r_path = path; } + *r_lb = lb; + *r_path = path; } else if (GS(id->name) == ID_SCE) { /* Sequencer's ID is scene :/ */ -- cgit v1.2.3 From 274b0838c7cd0f73e866b36456f5a88d710a5776 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Tue, 12 May 2015 18:43:07 -0300 Subject: Multi-View: return correct number of views when rendering only one of the stereo pairs Without this fix ViewerNode would continously trash the views/buffer when disabling either stereo eye. --- source/blender/blenkernel/intern/scene.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 3d87279e054..d3337f02f11 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -2213,11 +2213,13 @@ size_t BKE_scene_multiview_num_views_get(const RenderData *rd) return 1; if (rd->views_format == SCE_VIEWS_FORMAT_STEREO_3D) { - if (BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name))) { + srv = BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name)); + if ((srv && srv->viewflag & SCE_VIEW_DISABLE) == 0) { totviews++; } - if (BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name))) { + srv = BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name)); + if ((srv && srv->viewflag & SCE_VIEW_DISABLE) == 0) { totviews++; } } -- cgit v1.2.3 From bbadc3aecd72b617d9678fdfc1541fc38e7e8a33 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 May 2015 09:22:42 +1000 Subject: UI: nodes support for multi-value-editing --- source/blender/editors/interface/interface_ops.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 7c4ee7b6649..d13078f6cf2 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -278,6 +278,14 @@ bool UI_context_copy_to_selected_list( else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) { *r_lb = CTX_data_collection_get(C, "selected_editable_sequences"); } + else if (RNA_struct_is_a(ptr->type, &RNA_Node)) { + *r_lb = CTX_data_collection_get(C, "selected_nodes"); + } + else if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) { + if ((*r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node)) != NULL) { + *r_lb = CTX_data_collection_get(C, "selected_nodes"); + } + } else if (ptr->id.data) { ID *id = ptr->id.data; -- cgit v1.2.3 From 91ec8d8d1ebbcfb00fa6eb711513a98238903d70 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 May 2015 09:43:06 +1000 Subject: UI: multi-value-editing, copy value when typed in --- .../blender/editors/interface/interface_handlers.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index cfa31c8ef35..8e3cc08feee 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -176,6 +176,11 @@ typedef struct uiSelectContextStore { int elems_len; bool do_free; bool is_enabled; + /* When set, simply copy values (don't apply difference). + * Rules are: + * - dragging numbers uses delta. + * - typing in values will assign to all. */ + bool is_copy; } uiSelectContextStore; static bool ui_selectcontext_begin( @@ -1433,6 +1438,7 @@ static void ui_selectcontext_apply( PropertyRNA *lprop = but->rnaprop; int index = but->rnaindex; int i; + const bool use_delta = (selctx_data->is_copy == false); union { bool b; @@ -1444,10 +1450,10 @@ static void ui_selectcontext_apply( const int rna_type = RNA_property_type(prop); if (rna_type == PROP_FLOAT) { - delta.f = value - value_orig; + delta.f = use_delta ? (value - value_orig) : value; } else if (rna_type == PROP_INT) { - delta.i = (int)value - (int)value_orig; + delta.i = use_delta ? ((int)value - (int)value_orig) : (int)value; } else if (rna_type == PROP_ENUM) { delta.i = RNA_property_enum_get(&but->rnapoin, prop); /* not a delta infact */ @@ -1466,10 +1472,10 @@ static void ui_selectcontext_apply( PointerRNA lptr = other->ptr; if (is_array) { if (rna_type == PROP_FLOAT) { - RNA_property_float_set_index(&lptr, lprop, index, other->val_f + delta.f); + RNA_property_float_set_index(&lptr, lprop, index, use_delta ? (other->val_f + delta.f) : delta.f); } else if (rna_type == PROP_INT) { - RNA_property_int_set_index(&lptr, lprop, index, other->val_i + delta.i); + RNA_property_int_set_index(&lptr, lprop, index, use_delta ? (other->val_i + delta.i) : delta.i); } else if (rna_type == PROP_BOOLEAN) { RNA_property_boolean_set_index(&lptr, lprop, index, delta.b); @@ -1477,10 +1483,10 @@ static void ui_selectcontext_apply( } else { if (rna_type == PROP_FLOAT) { - RNA_property_float_set(&lptr, lprop, other->val_f + delta.f); + RNA_property_float_set(&lptr, lprop, use_delta ? (other->val_f + delta.f) : delta.f); } else if (rna_type == PROP_INT) { - RNA_property_int_set(&lptr, lprop, other->val_i + delta.i); + RNA_property_int_set(&lptr, lprop, use_delta ? (other->val_i + delta.i) : delta.i); } else if (rna_type == PROP_BOOLEAN) { RNA_property_boolean_set(&lptr, lprop, delta.b); @@ -2820,6 +2826,8 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) if (is_num_but) { if (IS_ALLSELECT_EVENT(win->eventstate)) { data->select_others.is_enabled = true; + data->select_others.is_copy = true; + } } #endif -- cgit v1.2.3 From 898b6491ed979ab5a59af25f5fb06841e8df59e5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 May 2015 09:58:05 +1000 Subject: UI: multi-value-edit, tint button while editing Currently re-uses node-flag (which is only used to tint color too) --- .../blender/editors/interface/interface_handlers.c | 27 ++++++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 8e3cc08feee..036e2ba9911 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -185,12 +185,17 @@ typedef struct uiSelectContextStore { static bool ui_selectcontext_begin( bContext *C, uiBut *but, struct uiSelectContextStore *selctx_data); +static void ui_selectcontext_end( + uiBut *but, uiSelectContextStore *selctx_data); static void ui_selectcontext_apply( bContext *C, uiBut *but, struct uiSelectContextStore *selctx_data, const double value, const double value_orig); #define IS_ALLSELECT_EVENT(event) ((event)->alt != 0) +/* just show a tinted color so users know its activated */ +#define UI_BUT_IS_SELECT_CONTEXT UI_BUT_NODE_ACTIVE + #endif /* USE_ALLSELECT */ @@ -1426,9 +1431,25 @@ finally: /* caller can clear */ selctx_data->do_free = true; + if (success) { + but->flag |= UI_BUT_IS_SELECT_CONTEXT; + } + return success; } +static void ui_selectcontext_end( + uiBut *but, uiSelectContextStore *selctx_data) +{ + if (selctx_data->do_free) { + if (selctx_data->elems) { + MEM_freeN(selctx_data->elems); + } + } + + but->flag &= ~UI_BUT_IS_SELECT_CONTEXT; +} + static void ui_selectcontext_apply( bContext *C, uiBut *but, uiSelectContextStore *selctx_data, const double value, const double value_orig) @@ -7606,11 +7627,7 @@ static void button_activate_exit( MEM_freeN(data->origstr); #ifdef USE_ALLSELECT - if (data->select_others.do_free) { - if (data->select_others.elems) { - MEM_freeN(data->select_others.elems); - } - } + ui_selectcontext_end(but, &data->select_others); #endif /* redraw (data is but->active!) */ -- cgit v1.2.3 From 08bbea9362c35073dadf82993e17a152fea6f640 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 May 2015 10:32:30 +1000 Subject: UI: multi-value-edit, distable alt+lmb on sliders --- source/blender/editors/interface/interface_handlers.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 036e2ba9911..d77cf8658fd 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -4373,6 +4373,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); retval = WM_UI_HANDLER_BREAK; } +#ifndef USE_ALLSELECT /* alt-click on sides to get "arrows" like in UI_BTYPE_NUM buttons, and match wheel usage above */ else if (event->type == LEFTMOUSE && event->alt) { int halfpos = BLI_rctf_cent_x(&but->rect); @@ -4382,6 +4383,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton else mx = but->rect.xmax; } +#endif else if (event->type == LEFTMOUSE) { data->dragstartx = mx; data->draglastx = mx; -- cgit v1.2.3 From abb80abf8add3e42d1edcce03c60e6e1eacdb14a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 May 2015 10:56:40 +1000 Subject: UI: check visible layers when reading context This resolves a problem where selected items edited for multi-value-editig could include objects not in any visible views (unlocked layers, local view... etc). --- source/blender/blenkernel/BKE_screen.h | 2 ++ source/blender/blenkernel/intern/screen.c | 17 +++++++++++++++++ source/blender/editors/screen/screen_context.c | 25 +++++++++++++++++++++---- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index c584051708b..48616418e67 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -293,6 +293,8 @@ unsigned int BKE_screen_view3d_layer_active_ex( unsigned int BKE_screen_view3d_layer_active( const struct View3D *v3d, const struct Scene *scene) ATTR_NONNULL(2); +unsigned int BKE_screen_view3d_layer_all(const struct bScreen *sc) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); + void BKE_screen_view3d_sync(struct View3D *v3d, struct Scene *scene); void BKE_screen_view3d_scene_sync(struct bScreen *sc); void BKE_screen_view3d_main_sync(ListBase *screen_lb, struct Scene *scene); diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 840e1f99f84..4125a35cb33 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -518,6 +518,23 @@ unsigned int BKE_screen_view3d_layer_active(const struct View3D *v3d, const stru return BKE_screen_view3d_layer_active_ex(v3d, scene, true); } +/** + * Accumulate all visible layers on this screen. + */ +unsigned int BKE_screen_view3d_layer_all(const bScreen *sc) +{ + const ScrArea *sa; + unsigned int lay = 0; + for (sa = sc->areabase.first; sa; sa = sa->next) { + if (sa->spacetype == SPACE_VIEW3D) { + View3D *v3d = sa->spacedata.first; + lay |= v3d->lay; + } + } + + return lay; +} + void BKE_screen_view3d_sync(View3D *v3d, struct Scene *scene) { int bit; diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index fc4ee47b568..87c0ce398e5 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -47,6 +47,7 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_gpencil.h" +#include "BKE_screen.h" #include "BKE_sequencer.h" #include "RNA_access.h" @@ -59,6 +60,18 @@ #include "screen_intern.h" +static unsigned int context_layers(bScreen *sc, Scene *scene, ScrArea *sa_ctx) +{ + /* needed for 'USE_ALLSELECT' define, otherwise we end up editing off-screen layers. */ + if (sc && sa_ctx && (sa_ctx->spacetype == SPACE_BUTS)) { + const unsigned int lay = BKE_screen_view3d_layer_all(sc); + if (lay) { + return lay; + } + } + return scene->lay; +} + const char *screen_context_dir[] = { "scene", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases", "selected_objects", "selected_bases", @@ -101,10 +114,11 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult return 1; } else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) { + const unsigned int lay = context_layers(sc, scene, sa); int visible_objects = CTX_data_equals(member, "visible_objects"); for (base = scene->base.first; base; base = base->next) { - if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & scene->lay)) { + if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & lay)) { if (visible_objects) CTX_data_id_list_add(result, &base->object->id); else @@ -115,10 +129,11 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult return 1; } else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) { + const unsigned int lay = context_layers(sc, scene, sa); int selectable_objects = CTX_data_equals(member, "selectable_objects"); for (base = scene->base.first; base; base = base->next) { - if (base->lay & scene->lay) { + if (base->lay & lay) { if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) { if (selectable_objects) CTX_data_id_list_add(result, &base->object->id); @@ -131,10 +146,11 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult return 1; } else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) { + const unsigned int lay = context_layers(sc, scene, sa); int selected_objects = CTX_data_equals(member, "selected_objects"); for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & scene->lay)) { + if ((base->flag & SELECT) && (base->lay & lay)) { if (selected_objects) CTX_data_id_list_add(result, &base->object->id); else @@ -145,10 +161,11 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult return 1; } else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) { + const unsigned int lay = context_layers(sc, scene, sa); int selected_editable_objects = CTX_data_equals(member, "selected_editable_objects"); for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & scene->lay)) { + if ((base->flag & SELECT) && (base->lay & lay)) { if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { if (0 == BKE_object_is_libdata(base->object)) { if (selected_editable_objects) -- cgit v1.2.3 From c78df8f9ee9cff5f2c217035327a4888085b1d35 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Wed, 13 May 2015 01:00:03 -0300 Subject: Duplicate Render->RenderData.views for thread safety (as we do for layers) This fixes nothing at the moment, but better safe than sorry since there are still a few strange multiview issues around. --- source/blender/render/intern/source/convertblender.c | 4 +++- source/blender/render/intern/source/envmap.c | 1 + source/blender/render/intern/source/external_engine.c | 1 + source/blender/render/intern/source/pipeline.c | 9 ++++++++- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 87c886929d6..06028870a3f 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -5852,9 +5852,11 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, /* renderdata setup and exceptions */ BLI_freelistN(&re->r.layers); + BLI_freelistN(&re->r.views); re->r = scene->r; BLI_duplicatelist(&re->r.layers, &scene->r.layers); - + BLI_duplicatelist(&re->r.views, &scene->r.views); + RE_init_threadcount(re); re->flag |= R_BAKING; diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index ed3033d8393..23d021db848 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -141,6 +141,7 @@ static Render *envmap_render_copy(Render *re, EnvMap *env) envre->r = re->r; envre->r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR); BLI_listbase_clear(&envre->r.layers); + BLI_listbase_clear(&envre->r.views); envre->r.filtertype = 0; envre->r.tilex = envre->r.xsch / 2; envre->r.tiley = envre->r.ysch / 2; diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 653af7460f9..e44dacaaad3 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -454,6 +454,7 @@ void RE_bake_engine_set_engine_parameters(Render *re, Main *bmain, Scene *scene) * but it potentially leaves unfreed memory blocks * not sure how to fix this yet -- dfelinto */ BLI_listbase_clear(&re->r.layers); + BLI_listbase_clear(&re->r.views); } bool RE_bake_has_engine(Render *re) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index bdf67434725..3d61cd43dba 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -509,7 +509,8 @@ void RE_FreeRender(Render *re) BLI_rw_mutex_end(&re->partsmutex); BLI_freelistN(&re->r.layers); - + BLI_freelistN(&re->r.views); + /* main dbase can already be invalid now, some database-free code checks it */ re->main = NULL; re->scene = NULL; @@ -656,8 +657,10 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, /* copy render data and render layers for thread safety */ BLI_freelistN(&re->r.layers); + BLI_freelistN(&re->r.views); re->r = *rd; BLI_duplicatelist(&re->r.layers, &rd->layers); + BLI_duplicatelist(&re->r.views, &rd->views); if (source) { /* reuse border flags from source renderer */ @@ -866,6 +869,10 @@ void render_update_anim_renderdata(Render *re, RenderData *rd) /* render layers */ BLI_freelistN(&re->r.layers); BLI_duplicatelist(&re->r.layers, &rd->layers); + + /* render views */ + BLI_freelistN(&re->r.views); + BLI_duplicatelist(&re->r.views, &rd->views); } void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend) -- cgit v1.2.3 From 7742a8f09c1a631adbbd87a407d55420f775fa4e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 May 2015 12:49:33 +1000 Subject: Cleanup: reduce scope for win32, Linux vars --- source/blender/blenkernel/intern/appdir.c | 35 +++++++++++++++++-------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 4c7cda95ad1..e4ed8c3ef73 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -514,31 +514,34 @@ const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, con */ static void bli_where_am_i(char *fullname, const size_t maxlen, const char *name) { - const char *path = NULL; - #ifdef WITH_BINRELOC /* linux uses binreloc since argv[0] is not reliable, call br_init( NULL ) first */ - path = br_find_exe(NULL); - if (path) { - BLI_strncpy(fullname, path, maxlen); - free((void *)path); - return; + { + const char *path = NULL; + path = br_find_exe(NULL); + if (path) { + BLI_strncpy(fullname, path, maxlen); + free((void *)path); + return; + } } #endif #ifdef _WIN32 - wchar_t *fullname_16 = MEM_mallocN(maxlen * sizeof(wchar_t), "ProgramPath"); - if (GetModuleFileNameW(0, fullname_16, maxlen)) { - conv_utf_16_to_8(fullname_16, fullname, maxlen); - if (!BLI_exists(fullname)) { - printf("path can't be found: \"%.*s\"\n", (int)maxlen, fullname); - MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK); + { + wchar_t *fullname_16 = MEM_mallocN(maxlen * sizeof(wchar_t), "ProgramPath"); + if (GetModuleFileNameW(0, fullname_16, maxlen)) { + conv_utf_16_to_8(fullname_16, fullname, maxlen); + if (!BLI_exists(fullname)) { + printf("path can't be found: \"%.*s\"\n", (int)maxlen, fullname); + MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK); + } + MEM_freeN(fullname_16); + return; } + MEM_freeN(fullname_16); - return; } - - MEM_freeN(fullname_16); #endif /* unix and non linux */ -- cgit v1.2.3 From 7969b238dbfd697a2590d654090080c862346d76 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 May 2015 16:01:43 +1000 Subject: Fix T39775: Skin modifier crash --- source/blender/modifiers/intern/MOD_skin.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 6c096224b58..1b8b29666e2 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -104,6 +104,9 @@ typedef struct Frame { /* Merge to target frame/corner (no merge if frame is null) */ struct Frame *frame; int corner; + /* checked to avoid chaining. + * (merging when we're already been referenced), see T39775 */ + unsigned int is_target : 1; } merge[4]; /* For hull frames, whether each vertex is detached or not */ @@ -363,7 +366,7 @@ static void merge_frame_corners(Frame **frames, int totframe) /* Compare with each corner of all other frames... */ for (l = 0; l < 4; l++) { - if (frames[k]->merge[l].frame) + if (frames[k]->merge[l].frame || frames[k]->merge[l].is_target) continue; /* Some additional concerns that could be checked @@ -393,6 +396,7 @@ static void merge_frame_corners(Frame **frames, int totframe) frames[k]->merge[l].frame = frames[i]; frames[k]->merge[l].corner = j; + frames[i]->merge[j].is_target = true; /* Can't merge another corner into the same * frame corner, so move on to frame k+1 */ -- cgit v1.2.3 From 3e782756e386d036edce24d11ee092695b283cda Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 May 2015 17:48:54 +1000 Subject: Project Paint: simplify uv bleed factor calc --- source/blender/editors/sculpt_paint/paint_image_proj.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 00fac6b1c8e..400202ab61a 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -2742,7 +2742,7 @@ static void project_paint_face_init( int fidx1, fidx2; /* face edge pairs - loop throuh these ((0,1), (1,2), (2,3), (3,0)) or ((0,1), (1,2), (2,0)) for a tri */ float seam_subsection[4][2]; - float fac1, fac2, ftot; + float fac1, fac2; if (outset_uv[0][0] == FLT_MAX) /* first time initialize */ uv_image_outset(tf_uv_pxoffset, outset_uv, ps->seam_bleed_px, ibuf->x, ibuf->y, mf->v4 != 0, (ps->faceWindingFlags[face_index] & PROJ_FACE_WINDING_CW) == 0); @@ -2776,17 +2776,14 @@ static void project_paint_face_init( if ((face_seam_flag & (1 << fidx1)) && /* 1< PROJ_FACE_SEAM# */ line_clip_rect2f(bucket_bounds, vCoSS[fidx1], vCoSS[fidx2], bucket_clip_edges[0], bucket_clip_edges[1])) { - - ftot = len_v2v2(vCoSS[fidx1], vCoSS[fidx2]); /* screenspace edge length */ - - if (ftot > 0.0f) { /* avoid div by zero */ + if (len_squared_v2v2(vCoSS[fidx1], vCoSS[fidx2]) > FLT_EPSILON) { /* avoid div by zero */ if (mf->v4) { if (fidx1 == 2 || fidx2 == 2) side = 1; else side = 0; } - fac1 = len_v2v2(vCoSS[fidx1], bucket_clip_edges[0]) / ftot; - fac2 = len_v2v2(vCoSS[fidx1], bucket_clip_edges[1]) / ftot; + fac1 = line_point_factor_v2(bucket_clip_edges[0], vCoSS[fidx1], vCoSS[fidx2]); + fac2 = line_point_factor_v2(bucket_clip_edges[1], vCoSS[fidx1], vCoSS[fidx2]); interp_v2_v2v2(seam_subsection[0], tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2], fac1); interp_v2_v2v2(seam_subsection[1], tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2], fac2); -- cgit v1.2.3 From a050d6063c78004de8b4b5945cb03bb43d84c8de Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 May 2015 18:04:46 +1000 Subject: Project Paint: resolve ugly bleed artifacts Use the bilinear reverse to find the pixel to bleed from. Was using pixel space which didn't work well. --- source/blender/blenlib/BLI_math_geom.h | 1 + source/blender/blenlib/intern/math_geom.c | 37 ++++++++++++++++++++++ .../editors/sculpt_paint/paint_image_proj.c | 7 ++-- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 4f7a3310ee6..4a75e83316e 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -259,6 +259,7 @@ void resolve_tri_uv_v3(float r_uv[2], const float st[3], const float st0[3], con void resolve_quad_uv_v2(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]); void resolve_quad_uv_v2_deriv(float r_uv[2], float r_deriv[2][2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]); +float resolve_quad_u_v2(const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]); /* use to find the point of a UV on a face */ void interp_bilinear_quad_v3(float data[4][3], float u, float v, float res[3]); diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index ba1f4480659..82062e80ae8 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -3101,6 +3101,43 @@ void resolve_quad_uv_v2_deriv(float r_uv[2], float r_deriv[2][2], } } +/* a version of resolve_quad_uv_v2 that only calculates the 'u' */ +float resolve_quad_u_v2( + const float st[2], + const float st0[2], const float st1[2], const float st2[2], const float st3[2]) +{ + const double signed_area = (st0[0] * st1[1] - st0[1] * st1[0]) + (st1[0] * st2[1] - st1[1] * st2[0]) + + (st2[0] * st3[1] - st2[1] * st3[0]) + (st3[0] * st0[1] - st3[1] * st0[0]); + + /* X is 2D cross product (determinant) + * A = (p0 - p) X (p0 - p3)*/ + const double a = (st0[0] - st[0]) * (st0[1] - st3[1]) - (st0[1] - st[1]) * (st0[0] - st3[0]); + + /* B = ( (p0 - p) X (p1 - p2) + (p1 - p) X (p0 - p3) ) / 2 */ + const double b = 0.5 * (double)(((st0[0] - st[0]) * (st1[1] - st2[1]) - (st0[1] - st[1]) * (st1[0] - st2[0])) + + ((st1[0] - st[0]) * (st0[1] - st3[1]) - (st1[1] - st[1]) * (st0[0] - st3[0]))); + + /* C = (p1-p) X (p1-p2) */ + const double fC = (st1[0] - st[0]) * (st1[1] - st2[1]) - (st1[1] - st[1]) * (st1[0] - st2[0]); + double denom = a - 2 * b + fC; + + if (IS_ZERO(denom) != 0) { + const double fDen = a - fC; + if (IS_ZERO(fDen) == 0) + return (float)(a / fDen); + else + return 0.0f; + } + else { + const double desc_sq = b * b - a * fC; + const double desc = sqrt(desc_sq < 0.0 ? 0.0 : desc_sq); + const double s = signed_area > 0 ? (-1.0) : 1.0; + + return (float)(((a - b) + s * desc) / denom); + } +} + + #undef IS_ZERO /* reverse of the functions above */ diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 400202ab61a..8bf4395add2 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -2825,11 +2825,8 @@ static void project_paint_face_init( /* Since this is a seam we need to work out where on the line this pixel is */ //fac = line_point_factor_v2(uv, uv_seam_quad[0], uv_seam_quad[1]); - - fac = line_point_factor_v2(uv, seam_subsection[0], seam_subsection[1]); - if (fac < 0.0f) { copy_v3_v3(pixelScreenCo, edge_verts_inset_clip[0]); } - else if (fac > 1.0f) { copy_v3_v3(pixelScreenCo, edge_verts_inset_clip[1]); } - else { interp_v3_v3v3(pixelScreenCo, edge_verts_inset_clip[0], edge_verts_inset_clip[1], fac); } + fac = resolve_quad_u_v2(uv, UNPACK4(seam_subsection)); + interp_v3_v3v3(pixelScreenCo, edge_verts_inset_clip[0], edge_verts_inset_clip[1], fac); if (!is_ortho) { pixelScreenCo[3] = 1.0f; -- cgit v1.2.3 From 1a0fb7e9ae8889905173a7deb0a7b1ca990fc34d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 May 2015 18:26:56 +1000 Subject: Project Paint: enable old bleed UV calculation Was disabled because other values weren't quite right. --- source/blender/editors/sculpt_paint/paint_image_proj.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 8bf4395add2..29236859d16 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -2841,10 +2841,11 @@ static void project_paint_face_init( { /* Only bother calculating the weights if we intersect */ if (ps->do_mask_normal || ps->dm_mtface_clone) { -#if 1 + float uv_fac; +#if 0 /* get the UV on the line since we want to copy the pixels from there for bleeding */ float uv_close[2]; - float uv_fac = closest_to_line_v2(uv_close, uv, tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2]); + uv_fac = closest_to_line_v2(uv_close, uv, tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2]); if (uv_fac < 0.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx1]); else if (uv_fac > 1.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx2]); @@ -2854,7 +2855,7 @@ static void project_paint_face_init( else { barycentric_weights_v2(tf_uv_pxoffset[0], tf_uv_pxoffset[1], tf_uv_pxoffset[2], uv_close, w); } -#else /* this is buggy with quads, don't use for now */ +#else /* Cheat, we know where we are along the edge so work out the weights from that */ uv_fac = fac1 + (uv_fac * (fac2 - fac1)); -- cgit v1.2.3 From ae9e38c5adc60347e127c9f4c5ee5436b611b48f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 13 May 2015 14:05:31 +0500 Subject: Fix T44689: New Depsgraph crash Simple highschool rated issue -- uninitialized variable :) --- source/blender/depsgraph/intern/depsnode.cc | 4 ++++ source/blender/depsgraph/intern/depsnode.h | 1 + 2 files changed, 5 insertions(+) diff --git a/source/blender/depsgraph/intern/depsnode.cc b/source/blender/depsgraph/intern/depsnode.cc index 8d21f6e0034..866e9115648 100644 --- a/source/blender/depsgraph/intern/depsnode.cc +++ b/source/blender/depsgraph/intern/depsnode.cc @@ -114,6 +114,10 @@ void TimeSourceDepsNode::tag_update(Depsgraph *graph) /* Root Node ============================================== */ +RootDepsNode::RootDepsNode() : time_source(NULL) +{ +} + RootDepsNode::~RootDepsNode() { OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode); diff --git a/source/blender/depsgraph/intern/depsnode.h b/source/blender/depsgraph/intern/depsnode.h index 993bb6971e7..84554aef7ea 100644 --- a/source/blender/depsgraph/intern/depsnode.h +++ b/source/blender/depsgraph/intern/depsnode.h @@ -127,6 +127,7 @@ struct TimeSourceDepsNode : public DepsNode { /* Root Node. */ struct RootDepsNode : public DepsNode { + RootDepsNode(); ~RootDepsNode(); TimeSourceDepsNode *add_time_source(const string &name = ""); -- cgit v1.2.3 From 38eab96f9b725bc9d068a46fa3aa982aa0d7e726 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 13 May 2015 14:28:24 +0500 Subject: Fix T44683: Unable to mute movie clip when using stabilized display --- source/blender/editors/space_clip/clip_draw.c | 34 +++++++++++++-------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index d0210025183..ce248f1eb10 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -1694,29 +1694,29 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar) } if (sc->flag & SC_SHOW_STABLE) { + float translation[2]; + float aspect = clip->tracking.camera.pixel_aspect; float smat[4][4], ismat[4][4]; - ibuf = ED_space_clip_get_stable_buffer(sc, sc->loc, &sc->scale, &sc->angle); - - if (ibuf) { - float translation[2]; - float aspect = clip->tracking.camera.pixel_aspect; + if ((sc->flag & SC_MUTE_FOOTAGE) == 0) { + ibuf = ED_space_clip_get_stable_buffer(sc, sc->loc, + &sc->scale, &sc->angle); + } - if (width != ibuf->x) - mul_v2_v2fl(translation, sc->loc, (float)width / ibuf->x); - else - copy_v2_v2(translation, sc->loc); + if (ibuf != NULL && width != ibuf->x) + mul_v2_v2fl(translation, sc->loc, (float)width / ibuf->x); + else + copy_v2_v2(translation, sc->loc); - BKE_tracking_stabilization_data_to_mat4(width, height, aspect, - translation, sc->scale, sc->angle, sc->stabmat); + BKE_tracking_stabilization_data_to_mat4(width, height, aspect, translation, + sc->scale, sc->angle, sc->stabmat); - unit_m4(smat); - smat[0][0] = 1.0f / width; - smat[1][1] = 1.0f / height; - invert_m4_m4(ismat, smat); + unit_m4(smat); + smat[0][0] = 1.0f / width; + smat[1][1] = 1.0f / height; + invert_m4_m4(ismat, smat); - mul_m4_series(sc->unistabmat, smat, sc->stabmat, ismat); - } + mul_m4_series(sc->unistabmat, smat, sc->stabmat, ismat); } else if ((sc->flag & SC_MUTE_FOOTAGE) == 0) { ibuf = ED_space_clip_get_buffer(sc); -- cgit v1.2.3 From 0d64e26740a7f0b6052e386e9a9ad2e88d4a4058 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 13 May 2015 15:55:32 +0500 Subject: Clip editor: Deselecting with shift-LMB does not work in graph view --- source/blender/editors/space_clip/clip_graph_ops.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index 2a2f15c94bb..9011f08e165 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -200,10 +200,18 @@ static bool mouse_select_knot(bContext *C, float co[2], bool extend) toggle_selection_cb); } - if (userdata.coord == 0) - userdata.marker->flag |= MARKER_GRAPH_SEL_X; - else - userdata.marker->flag |= MARKER_GRAPH_SEL_Y; + if (userdata.coord == 0) { + if (extend && (userdata.marker->flag & MARKER_GRAPH_SEL_X) != 0) + userdata.marker->flag &= ~MARKER_GRAPH_SEL_X; + else + userdata.marker->flag |= MARKER_GRAPH_SEL_X; + } + else { + if (extend && (userdata.marker->flag & MARKER_GRAPH_SEL_Y) != 0) + userdata.marker->flag &= ~MARKER_GRAPH_SEL_Y; + else + userdata.marker->flag |= MARKER_GRAPH_SEL_Y; + } return true; } -- cgit v1.2.3 From 730e61b446879f71eae7267de42026069a53d66f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 13 May 2015 16:11:26 +0500 Subject: Clip editor: Selecting curves in graph view always extends tracks selection Was actually an old TODO, hopefully solved now in a way so everyone is happy. --- source/blender/editors/space_clip/clip_graph_ops.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index 9011f08e165..e781d199d35 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -246,10 +246,12 @@ static bool mouse_select_curve(bContext *C, float co[2], bool extend) else if (act_track != userdata.track) { SelectUserData selectdata = {SEL_DESELECT}; MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); - ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); tracking->act_track = userdata.track; - BKE_tracking_track_select(tracksbase, userdata.track, TRACK_AREA_ALL, true); + if ((sc->flag & SC_SHOW_GRAPH_SEL_ONLY) == 0) { + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); + BKE_tracking_track_select(tracksbase, userdata.track, TRACK_AREA_ALL, false); + } /* deselect all knots on newly selected curve */ clip_graph_tracking_iterate(sc, -- cgit v1.2.3 From 0a6e32173eaeaf35d194a8787458cb05194854a2 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Wed, 13 May 2015 16:04:43 +0200 Subject: Cleanup / Cycles: De-Duplicate Portal data fetch and side check. --- intern/cycles/kernel/kernel_light.h | 51 ++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 704fb49efc9..39839472737 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -249,6 +249,25 @@ float background_map_pdf(KernelGlobals *kg, float3 direction) return (cdf_u.x * cdf_v.x)/(M_2PI_F * M_PI_F * sin_theta * denom); } +ccl_device_inline bool background_portal_data_fetch_and_check_side(KernelGlobals *kg, + float3 P, + int index, + float3 *lightpos, + float3 *dir) +{ + float4 data0 = kernel_tex_fetch(__light_data, (index + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 0); + float4 data3 = kernel_tex_fetch(__light_data, (index + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 3); + + *lightpos = make_float3(data0.y, data0.z, data0.w); + *dir = make_float3(data3.y, data3.z, data3.w); + + /* Check whether portal is on the right side. */ + if(dot(*dir, P - *lightpos) > 1e-5f) + return true; + + return false; +} + ccl_device float background_portal_pdf(KernelGlobals *kg, float3 P, float3 direction, @@ -261,19 +280,9 @@ ccl_device float background_portal_pdf(KernelGlobals *kg, if(p == ignore_portal) continue; - /* TODO(sergey): Consider moving portal data fetch to a - * dedicated function. - */ - float4 data0 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 0); - float4 data3 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 3); - - float3 lightpos = make_float3(data0.y, data0.z, data0.w); - float3 dir = make_float3(data3.y, data3.z, data3.w); - - if(dot(dir, P - lightpos) <= 1e-5f) { - /* P is on the wrong side or too close. */ + float3 lightpos, dir; + if(!background_portal_data_fetch_and_check_side(kg, P, p, &lightpos, &dir)) continue; - } if(is_possible) { /* There's a portal that could be sampled from this position. */ @@ -310,13 +319,8 @@ ccl_device int background_num_possible_portals(KernelGlobals *kg, float3 P) { int num_possible_portals = 0; for(int p = 0; p < kernel_data.integrator.num_portals; p++) { - float4 data0 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 0); - float4 data3 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 3); - float3 lightpos = make_float3(data0.y, data0.z, data0.w); - float3 dir = make_float3(data3.y, data3.z, data3.w); - - /* Check whether portal is on the right side. */ - if(dot(dir, P - lightpos) > 1e-5f) + float3 lightpos, dir; + if(background_portal_data_fetch_and_check_side(kg, P, p, &lightpos, &dir)) num_possible_portals++; } return num_possible_portals; @@ -340,13 +344,8 @@ ccl_device float3 background_portal_sample(KernelGlobals *kg, */ for(int p = 0; p < kernel_data.integrator.num_portals; p++) { /* Search for the sampled portal. */ - float4 data0 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 0); - float4 data3 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 3); - float3 lightpos = make_float3(data0.y, data0.z, data0.w); - float3 dir = make_float3(data3.y, data3.z, data3.w); - - /* Check whether portal is on the right side. */ - if(dot(dir, P - lightpos) <= 1e-5f) + float3 lightpos, dir; + if(!background_portal_data_fetch_and_check_side(kg, P, p, &lightpos, &dir)) continue; if(portal == 0) { -- cgit v1.2.3 From 51a6bc8faa2994f6fea6cfa3f6fe7ac6662efee6 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 13 May 2015 19:09:07 +0500 Subject: Cycles: Inline sizeof of elements needed for the split kernel No need to store them in the class, they're unlikely to be changed and if they do change we're in big trouble anyway. More appropriate approach would be then to typedef this things in kernel_types.h, but still use inlined sizeof(), --- intern/cycles/device/device_opencl.cpp | 60 +++++++++++----------------------- 1 file changed, 19 insertions(+), 41 deletions(-) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 5657e3a5992..46d6706d5d1 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -1620,18 +1620,6 @@ public: /* Flag to make sceneintersect and lampemission kernel use queues. */ cl_mem use_queues_flag; - /* Required-memory size. */ - size_t throughput_size; - size_t L_transparent_size; - size_t rayState_size; - size_t hostRayState_size; - size_t work_element_size; - size_t ISLamp_size; - - /* Sizes of memory required for shadow blocked function. */ - size_t AOAlpha_size; - size_t AOBSDF_size; - /* Amount of memory in output buffer associated with one pixel/thread. */ size_t per_thread_output_buffer_size; @@ -1786,18 +1774,6 @@ public: per_sample_output_buffers = NULL; - /* Initialize required memory size. */ - throughput_size = sizeof(float3); - L_transparent_size = sizeof(float); - rayState_size = sizeof(char); - hostRayState_size = sizeof(char); - work_element_size = sizeof(unsigned int); - ISLamp_size = sizeof(int); - - /* Initialize sizes of memory required for shadow blocked function. */ - AOAlpha_size = sizeof(float3); - AOBSDF_size = sizeof(float3); - per_thread_output_buffer_size = 0; hostRayStateArray = NULL; PathIteration_times = PATH_ITER_INC_FACTOR; @@ -2203,10 +2179,6 @@ public: assert(max_render_feasible_tile_size.x % SPLIT_KERNEL_LOCAL_SIZE_X == 0); assert(max_render_feasible_tile_size.y % SPLIT_KERNEL_LOCAL_SIZE_Y == 0); - /* ray_state and hostRayStateArray should be of same size. */ - assert(hostRayState_size == rayState_size); - assert(rayState_size == 1); - size_t global_size[2]; size_t local_size[2] = {SPLIT_KERNEL_LOCAL_SIZE_X, SPLIT_KERNEL_LOCAL_SIZE_Y}; @@ -2340,17 +2312,17 @@ public: * the kernels. */ rng_coop = mem_alloc(num_global_elements * sizeof(RNG)); - throughput_coop = mem_alloc(num_global_elements * throughput_size); - L_transparent_coop = mem_alloc(num_global_elements * L_transparent_size); + throughput_coop = mem_alloc(num_global_elements * sizeof(float3)); + L_transparent_coop = mem_alloc(num_global_elements * sizeof(float)); PathRadiance_coop = mem_alloc(num_global_elements * sizeof(PathRadiance)); Ray_coop = mem_alloc(num_global_elements * sizeof(Ray)); PathState_coop = mem_alloc(num_global_elements * sizeof(PathState)); Intersection_coop = mem_alloc(num_global_elements * sizeof(Intersection)); - AOAlpha_coop = mem_alloc(num_global_elements * AOAlpha_size); - AOBSDF_coop = mem_alloc(num_global_elements * AOBSDF_size); + AOAlpha_coop = mem_alloc(num_global_elements * sizeof(float3)); + AOBSDF_coop = mem_alloc(num_global_elements * sizeof(float3)); AOLightRay_coop = mem_alloc(num_global_elements * sizeof(Ray)); BSDFEval_coop = mem_alloc(num_global_elements * sizeof(BsdfEval)); - ISLamp_coop = mem_alloc(num_global_elements * ISLamp_size); + ISLamp_coop = mem_alloc(num_global_elements * sizeof(int)); LightRay_coop = mem_alloc(num_global_elements * sizeof(Ray)); Intersection_coop_AO = mem_alloc(num_global_elements * sizeof(Intersection)); Intersection_coop_DL = mem_alloc(num_global_elements * sizeof(Intersection)); @@ -2359,13 +2331,13 @@ public: debugdata_coop = mem_alloc(num_global_elements * sizeof(DebugData)); #endif - ray_state = mem_alloc(num_global_elements * rayState_size); + ray_state = mem_alloc(num_global_elements * sizeof(char)); - hostRayStateArray = (char *)calloc(num_global_elements, hostRayState_size); + hostRayStateArray = (char *)calloc(num_global_elements, sizeof(char)); assert(hostRayStateArray != NULL && "Can't create hostRayStateArray memory"); Queue_data = mem_alloc(num_global_elements * (NUM_QUEUES * sizeof(int)+sizeof(int))); - work_array = mem_alloc(num_global_elements * work_element_size); + work_array = mem_alloc(num_global_elements * sizeof(unsigned int)); per_sample_output_buffers = mem_alloc(num_global_elements * per_thread_output_buffer_size); } @@ -2885,16 +2857,22 @@ public: */ shaderdata_volume = get_shader_data_size(shader_closure_size); size_t retval = sizeof(RNG) - + throughput_size + L_transparent_size - + rayState_size + work_element_size - + ISLamp_size + sizeof(PathRadiance) + sizeof(Ray) + sizeof(PathState) + + sizeof(float3) /* Throughput size */ + + sizeof(float) /* L transparent size */ + + sizeof(char) /* Ray state size */ + + sizeof(unsigned int) /* Work element size */ + + sizeof(int) /* ISLamp_size */ + + sizeof(PathRadiance) + sizeof(Ray) + sizeof(PathState) + sizeof(Intersection) /* Overall isect */ + sizeof(Intersection) /* Instersection_coop_AO */ + sizeof(Intersection) /* Intersection coop DL */ + shaderdata_volume /* Overall ShaderData */ + (shaderdata_volume * 2) /* ShaderData : DL and shadow */ - + sizeof(Ray) + sizeof(BsdfEval) + AOAlpha_size + AOBSDF_size + sizeof(Ray) - + (sizeof(int)* NUM_QUEUES) + + sizeof(Ray) + sizeof(BsdfEval) + + sizeof(float3) /* AOAlpha size */ + + sizeof(float3) /* AOBSDF size */ + + sizeof(Ray) + + (sizeof(int) * NUM_QUEUES) + per_thread_output_buffer_size; return retval; } -- cgit v1.2.3 From 93867ae549f54cf98451c0a72e0843fc7b1c62bc Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 13 May 2015 19:29:19 +0500 Subject: Cycles: Cleanup: use generic utility function to set kernel arguments --- intern/cycles/device/device_opencl.cpp | 91 ++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 46d6706d5d1..f2ac5fcc00b 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -39,8 +39,6 @@ CCL_NAMESPACE_BEGIN #define CL_MEM_PTR(p) ((cl_mem)(uintptr_t)(p)) -#define KERNEL_APPEND_ARG(kernel_name, arg) \ - opencl_assert(clSetKernelArg(kernel_name, narg++, sizeof(arg), (void*)&arg)) /* Macro declarations used with split kernel */ @@ -1008,29 +1006,30 @@ public: cl_int d_offset = task.offset; cl_int d_stride = task.stride; - /* sample arguments */ - cl_uint narg = 0; - cl_kernel ckFilmConvertKernel = (rgba_byte)? ckFilmConvertByteKernel: ckFilmConvertHalfFloatKernel; - /* TODO : Make the kernel launch similar to Cuda */ - KERNEL_APPEND_ARG(ckFilmConvertKernel, d_data); - KERNEL_APPEND_ARG(ckFilmConvertKernel, d_rgba); - KERNEL_APPEND_ARG(ckFilmConvertKernel, d_buffer); + cl_uint start_arg_index = + kernel_set_args(ckFilmConvertKernel, + 0, + d_data, + d_rgba, + d_buffer); #define KERNEL_TEX(type, ttype, name) \ - set_kernel_arg_mem(ckFilmConvertKernel, &narg, #name); + set_kernel_arg_mem(ckFilmConvertKernel, &start_arg_index, #name); #include "kernel_textures.h" #undef KERNEL_TEX - KERNEL_APPEND_ARG(ckFilmConvertKernel, d_sample_scale); - KERNEL_APPEND_ARG(ckFilmConvertKernel, d_x); - KERNEL_APPEND_ARG(ckFilmConvertKernel, d_y); - KERNEL_APPEND_ARG(ckFilmConvertKernel, d_w); - KERNEL_APPEND_ARG(ckFilmConvertKernel, d_h); - KERNEL_APPEND_ARG(ckFilmConvertKernel, d_offset); - KERNEL_APPEND_ARG(ckFilmConvertKernel, d_stride); + start_arg_index += kernel_set_args(ckFilmConvertKernel, + start_arg_index, + d_sample_scale, + d_x, + d_y, + d_w, + d_h, + d_offset, + d_stride); enqueue_kernel(ckFilmConvertKernel, d_w, d_h); } @@ -1046,9 +1045,6 @@ public: cl_int d_shader_w = task.shader_w; cl_int d_offset = task.offset; - /* sample arguments */ - cl_uint narg = 0; - cl_kernel kernel; if(task.shader_eval_type >= SHADER_EVAL_BAKE) @@ -1063,21 +1059,25 @@ public: cl_int d_sample = sample; - /* TODO : Make the kernel launch similar to Cuda */ - KERNEL_APPEND_ARG(kernel, d_data); - KERNEL_APPEND_ARG(kernel, d_input); - KERNEL_APPEND_ARG(kernel, d_output); + cl_uint start_arg_index = + kernel_set_args(kernel, + 0, + d_data, + d_input, + d_output); #define KERNEL_TEX(type, ttype, name) \ - set_kernel_arg_mem(kernel, &narg, #name); + set_kernel_arg_mem(kernel, &start_arg_index, #name); #include "kernel_textures.h" #undef KERNEL_TEX - KERNEL_APPEND_ARG(kernel, d_shader_eval_type); - KERNEL_APPEND_ARG(kernel, d_shader_x); - KERNEL_APPEND_ARG(kernel, d_shader_w); - KERNEL_APPEND_ARG(kernel, d_offset); - KERNEL_APPEND_ARG(kernel, d_sample); + start_arg_index += kernel_set_args(kernel, + start_arg_index, + d_shader_eval_type, + d_shader_x, + d_shader_w, + d_offset, + d_sample); enqueue_kernel(kernel, task.shader_w, 1); @@ -1361,25 +1361,28 @@ public: /* Sample arguments. */ cl_int d_sample = sample; - cl_uint narg = 0; - /* TODO : Make the kernel launch similar to Cuda. */ - KERNEL_APPEND_ARG(ckPathTraceKernel, d_data); - KERNEL_APPEND_ARG(ckPathTraceKernel, d_buffer); - KERNEL_APPEND_ARG(ckPathTraceKernel, d_rng_state); + cl_uint start_arg_index = + kernel_set_args(ckPathTraceKernel, + 0, + d_data, + d_buffer, + d_rng_state); #define KERNEL_TEX(type, ttype, name) \ - set_kernel_arg_mem(ckPathTraceKernel, &narg, #name); + set_kernel_arg_mem(ckPathTraceKernel, &start_arg_index, #name); #include "kernel_textures.h" #undef KERNEL_TEX - KERNEL_APPEND_ARG(ckPathTraceKernel, d_sample); - KERNEL_APPEND_ARG(ckPathTraceKernel, d_x); - KERNEL_APPEND_ARG(ckPathTraceKernel, d_y); - KERNEL_APPEND_ARG(ckPathTraceKernel, d_w); - KERNEL_APPEND_ARG(ckPathTraceKernel, d_h); - KERNEL_APPEND_ARG(ckPathTraceKernel, d_offset); - KERNEL_APPEND_ARG(ckPathTraceKernel, d_stride); + start_arg_index += kernel_set_args(ckPathTraceKernel, + start_arg_index, + d_sample, + d_x, + d_y, + d_w, + d_h, + d_offset, + d_stride); enqueue_kernel(ckPathTraceKernel, d_w, d_h); } @@ -2384,8 +2387,8 @@ public: start_arg_index += kernel_set_args(ckPathTraceKernel_data_init, -#ifdef __RAY_DIFFERENTIALS__ start_arg_index, +#ifdef __RAY_DIFFERENTIALS__ dP_sd, dP_sd_DL_shadow, dI_sd, -- cgit v1.2.3 From fc31bae66fdf0daa14da2eb81ba537f2ff325a96 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Wed, 13 May 2015 19:54:20 +0200 Subject: Cleanup: Avoid temp variable in portal sampling code. --- intern/cycles/kernel/kernel_light.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 39839472737..1badbc3b9f7 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -355,16 +355,14 @@ ccl_device float3 background_portal_sample(KernelGlobals *kg, float3 axisu = make_float3(data1.y, data1.z, data1.w); float3 axisv = make_float3(data2.y, data2.z, data2.w); - float3 lightPoint = lightpos; - - *pdf = area_light_sample(P, &lightPoint, + *pdf = area_light_sample(P, &lightpos, axisu, axisv, randu, randv, true); *pdf /= num_possible; *sampled_portal = p; - return normalize(lightPoint - P); + return normalize(lightpos - P); } portal--; -- cgit v1.2.3 From da1038c768557c88d29ce74a98026ca4915ab2c3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 14 May 2015 06:23:41 +1000 Subject: UI: Copy to selected nodes now filtered by type Was needed because sockets are very generic type which would match on unrelated values. --- source/blender/editors/interface/interface_ops.c | 48 +++++++++++++++++++++--- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index d13078f6cf2..643397b5a5c 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -44,6 +44,7 @@ #include "BKE_context.h" #include "BKE_screen.h" #include "BKE_global.h" +#include "BKE_node.h" #include "BKE_text.h" /* for UI_OT_reports_to_text */ #include "BKE_report.h" @@ -278,13 +279,48 @@ bool UI_context_copy_to_selected_list( else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) { *r_lb = CTX_data_collection_get(C, "selected_editable_sequences"); } - else if (RNA_struct_is_a(ptr->type, &RNA_Node)) { - *r_lb = CTX_data_collection_get(C, "selected_nodes"); - } - else if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) { - if ((*r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node)) != NULL) { - *r_lb = CTX_data_collection_get(C, "selected_nodes"); + else if (RNA_struct_is_a(ptr->type, &RNA_Node) || + RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) + { + ListBase lb = {NULL, NULL}; + char *path = NULL; + bNode *node = NULL; + + /* Get the node we're editing */ + if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) { + bNodeTree *ntree = ptr->id.data; + bNodeSocket *sock = ptr->data; + if (nodeFindNode(ntree, sock, &node, NULL)) { + if ((path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node)) != NULL) { + /* we're good! */ + } + else { + node = NULL; + } + } + } + else { + node = ptr->data; + } + + /* Now filter by type */ + if (node) { + CollectionPointerLink *link, *link_next; + lb = CTX_data_collection_get(C, "selected_nodes"); + + for (link = lb.first; link; link = link_next) { + bNode *node_data = link->ptr.data; + link_next = link->next; + + if (node_data->type != node->type) { + BLI_remlink(&lb, link); + MEM_freeN(link); + } + } } + + *r_lb = lb; + *r_path = path; } else if (ptr->id.data) { ID *id = ptr->id.data; -- cgit v1.2.3 From 67eb2c7897188c2e5134ea7df7bdc26e08fa5a7a Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Thu, 14 May 2015 01:08:45 +0200 Subject: Cycles: Remove Emission shaders from the graph if color or strength is 0. --- intern/cycles/render/graph.cpp | 15 +++++++++++++++ intern/cycles/render/graph.h | 1 + intern/cycles/render/nodes.cpp | 2 ++ 3 files changed, 18 insertions(+) diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index ab89ee3ae37..9adf6b4b1ed 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -404,6 +404,21 @@ void ShaderGraph::remove_unneeded_nodes() } } } + else if(node->special_type == SHADER_SPECIAL_TYPE_EMISSION) { + EmissionNode *em = static_cast(node); + + if(em->outputs[0]->links.size()) { + /* Black color or zero strength, remove node */ + if((!em->inputs[0]->link && em->inputs[0]->value == make_float3(0.0f, 0.0f, 0.0f)) || + (!em->inputs[1]->link && em->inputs[1]->value.x == 0.0f)) { + vector inputs = em->outputs[0]->links; + + relink(em->inputs, inputs, NULL); + removed[em->id] = true; + any_node_removed = true; + } + } + } else if(node->special_type == SHADER_SPECIAL_TYPE_MIX_CLOSURE) { MixClosureNode *mix = static_cast(node); diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index e6271009999..1a17909bddc 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -83,6 +83,7 @@ enum ShaderNodeSpecialType { SHADER_SPECIAL_TYPE_BACKGROUND, SHADER_SPECIAL_TYPE_IMAGE_SLOT, SHADER_SPECIAL_TYPE_CLOSURE, + SHADER_SPECIAL_TYPE_EMISSION, }; /* Enum diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 7eaecc2751c..430c059d686 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1923,6 +1923,8 @@ bool SubsurfaceScatteringNode::has_bssrdf_bump() EmissionNode::EmissionNode() : ShaderNode("emission") { + special_type = SHADER_SPECIAL_TYPE_EMISSION; + add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); add_input("Strength", SHADER_SOCKET_FLOAT, 10.0f); add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); -- cgit v1.2.3 From 0e80eb82e0667aa9b64d5a5e3e34c84d1d9957a3 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Thu, 14 May 2015 01:11:43 +0200 Subject: Cycles: Resize light_data after possible light removal. --- intern/cycles/render/light.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 817e1f5806c..1b7aa0ef52e 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -545,8 +545,6 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce if(scene->lights.size() == 0) return; - float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE); - /* remove background light? */ if(!(device->info.advanced_shading)) { foreach(Light *light, scene->lights) { @@ -557,6 +555,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce } } + float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE); int light_index = 0; foreach(Light *light, scene->lights) { -- cgit v1.2.3 From 9207c8d669319d6c09e8498703cd8192e90496c6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 14 May 2015 13:03:24 +1000 Subject: Fix project paint worldspace coord calc from seam Surprising this worked at all, would show errors with non-flat-quads. --- .../blender/editors/sculpt_paint/paint_image_proj.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 29236859d16..330b93b96b9 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -2534,8 +2534,6 @@ static void project_paint_face_init( int has_x_isect = 0, has_isect = 0; /* for early loop exit */ - int i1, i2, i3; - float uv_clip[8][2]; int uv_clip_tot; const bool is_ortho = ps->is_ortho; @@ -2584,6 +2582,8 @@ static void project_paint_face_init( } do { + int i1, i2, i3; + if (side == 1) { i1 = 0; i2 = 2; i3 = 3; } @@ -2778,7 +2778,7 @@ static void project_paint_face_init( { if (len_squared_v2v2(vCoSS[fidx1], vCoSS[fidx2]) > FLT_EPSILON) { /* avoid div by zero */ if (mf->v4) { - if (fidx1 == 2 || fidx2 == 2) side = 1; + if (fidx1 == 3 || fidx2 == 3) side = 1; else side = 0; } @@ -2841,14 +2841,11 @@ static void project_paint_face_init( { /* Only bother calculating the weights if we intersect */ if (ps->do_mask_normal || ps->dm_mtface_clone) { - float uv_fac; + const float uv_fac = fac1 + (fac * (fac2 - fac1)); #if 0 /* get the UV on the line since we want to copy the pixels from there for bleeding */ float uv_close[2]; - uv_fac = closest_to_line_v2(uv_close, uv, tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2]); - if (uv_fac < 0.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx1]); - else if (uv_fac > 1.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx2]); - + interp_v2_v2v2(uv_close, tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2], uv_fac); if (side) { barycentric_weights_v2(tf_uv_pxoffset[0], tf_uv_pxoffset[2], tf_uv_pxoffset[3], uv_close, w); } @@ -2858,8 +2855,6 @@ static void project_paint_face_init( #else /* Cheat, we know where we are along the edge so work out the weights from that */ - uv_fac = fac1 + (uv_fac * (fac2 - fac1)); - w[0] = w[1] = w[2] = 0.0; if (side) { w[fidx1 ? fidx1 - 1 : 0] = 1.0f - uv_fac; @@ -2874,8 +2869,8 @@ static void project_paint_face_init( /* a pity we need to get the worldspace pixel location here */ if (do_clip || do_3d_mapping) { - if (side) interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w); - else interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w); + if (side) interp_v3_v3v3v3(wco, vCo[0], vCo[2], vCo[3], w); + else interp_v3_v3v3v3(wco, vCo[0], vCo[1], vCo[2], w); if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, true)) { continue; /* Watch out that no code below this needs to run */ -- cgit v1.2.3 From 434086dc53aa03205714bb0415550bb158edcf43 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 14 May 2015 13:13:13 +1000 Subject: install_deps.sh: correct typo --- build_files/build_environment/install_deps.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index ea60eb39e0b..0873263368d 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -1374,7 +1374,7 @@ EOF cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst" cmake_d="$cmake_d -D LLVM_ENABLE_FFI=ON" cmake_d="$cmake_d -D LLVM_TARGETS_TO_BUILD=X86" - cmake_d="$cmake_d -D -DLLVM_ENABLE_TERMINFO=OFF" + cmake_d="$cmake_d -D LLVM_ENABLE_TERMINFO=OFF" if [ -d $_FFI_INCLUDE_DIR ]; then cmake_d="$cmake_d -D FFI_INCLUDE_DIR=$_FFI_INCLUDE_DIR" -- cgit v1.2.3 From 687f6a9752fd2009f67dd0b66208777cd203bde1 Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Thu, 14 May 2015 09:40:03 +0200 Subject: BGE: Code Cleanup: LOD hysteresis calculation * Cleanup duplicated code. * Remove unnecessary "this->" Reviewers: kupoman, lordloki Reviewed By: kupoman, lordloki Differential Revision: https://developer.blender.org/D1293 --- source/gameengine/Ketsji/KX_GameObject.cpp | 90 ++++++++++++++++-------------- 1 file changed, 48 insertions(+), 42 deletions(-) diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 44d9bfa0cf4..14a7324d2b9 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -806,68 +806,74 @@ void KX_GameObject::AddLodMesh(RAS_MeshObject* mesh) m_lodmeshes.push_back(mesh); } + +static float calcHysteresis(KX_Scene *kxscene, LodLevel *lod) +{ + float hystvariance = 0.0f; + + if (!kxscene->IsActivedLodHysteresis()) + return hystvariance; + + short hysteresis = 0; + // if exists, LoD level hysteresis will override scene hysteresis + if (lod->next->flags & OB_LOD_USE_HYST) + hysteresis = lod->next->obhysteresis; + else + hysteresis = kxscene->GetLodHysteresisValue(); + + return hystvariance = MT_abs(lod->next->distance - lod->distance) * hysteresis / 100; +} + void KX_GameObject::UpdateLod(MT_Vector3 &cam_pos) { // Handle dupligroups - if (this->m_pInstanceObjects) { - KX_GameObject * instob; - int count = this->m_pInstanceObjects->GetCount(); + if (m_pInstanceObjects) { + KX_GameObject *instob; + int count = m_pInstanceObjects->GetCount(); for (int i = 0; i < count; i++) { - instob = (KX_GameObject*)this->m_pInstanceObjects->GetValue(i); + instob = (KX_GameObject*)m_pInstanceObjects->GetValue(i); instob->UpdateLod(cam_pos); } } - if (this->m_lodmeshes.empty()) return; + if (m_lodmeshes.empty()) + return; - MT_Vector3 delta = this->NodeGetWorldPosition() - cam_pos; + MT_Vector3 delta = NodeGetWorldPosition() - cam_pos; float distance2 = delta.length2(); int level = 0; - Object *bob = this->GetBlenderObject(); - LodLevel *lod = (LodLevel*) bob->lodlevels.first; - KX_Scene *kxscene = this->GetScene(); + float hystvariance = 0.0f; + Object *bob = GetBlenderObject(); + LodLevel *lod = (LodLevel *)bob->lodlevels.first; + KX_Scene *kxscene = GetScene(); for (; lod; lod = lod->next, level++) { - if (!lod->source || lod->source->type != OB_MESH) level--; - if (!lod->next) break; - if (level == (this->m_previousLodLevel) || (level == (this->m_previousLodLevel + 1))) { - short hysteresis = 0; - if (kxscene->IsActivedLodHysteresis()) { - // if exists, LoD level hysteresis will override scene hysteresis - if (lod->next->flags & OB_LOD_USE_HYST) { - hysteresis = lod->next->obhysteresis; - } - else { - hysteresis = kxscene->GetLodHysteresisValue(); - } - } - float hystvariance = MT_abs(lod->next->distance - lod->distance) * hysteresis / 100; - if ((lod->next->distance + hystvariance) * (lod->next->distance + hystvariance) > distance2) + if (!lod->source || lod->source->type != OB_MESH) + level--; + + if (!lod->next) + break; + + if (level == m_previousLodLevel || level == (m_previousLodLevel + 1)) { + hystvariance = calcHysteresis(kxscene, lod); + float newdistance = lod->next->distance + hystvariance; + if (newdistance * newdistance > distance2) break; } - else if (level == (this->m_previousLodLevel - 1)) { - short hysteresis = 0; - if (kxscene->IsActivedLodHysteresis()) { - // if exists, LoD level hysteresis will override scene hysteresis - if (lod->next->flags & OB_LOD_USE_HYST) { - hysteresis = lod->next->obhysteresis; - } - else { - hysteresis = kxscene->GetLodHysteresisValue(); - } - } - float hystvariance = MT_abs(lod->next->distance - lod->distance) * hysteresis / 100; - if ((lod->next->distance - hystvariance) * (lod->next->distance - hystvariance) > distance2) + else if (level == (m_previousLodLevel - 1)) { + hystvariance = calcHysteresis(kxscene, lod); + float newdistance = lod->next->distance - hystvariance; + if (newdistance * newdistance > distance2) break; } } - RAS_MeshObject *mesh = this->m_lodmeshes[level]; - this->m_currentLodLevel = level; - if (mesh != this->m_meshes[0]) { - this->m_previousLodLevel = level; - this->GetScene()->ReplaceMesh(this, mesh, true, false); + RAS_MeshObject *mesh = m_lodmeshes[level]; + m_currentLodLevel = level; + if (mesh != m_meshes[0]) { + m_previousLodLevel = level; + GetScene()->ReplaceMesh(this, mesh, true, false); } } -- cgit v1.2.3 From 8bf9e1412fac3312cfdf22869312caf32f99c4c2 Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Thu, 14 May 2015 09:45:51 +0200 Subject: BGE: Fix: Double jumps are not working with character motion actuator The actual character motion actuator triggers every frame the jump method. Adding an edge detection to trigger the jump method. Reviewers: lordloki, sybren, moguri Reviewed By: moguri Differential Revision: https://developer.blender.org/D1220 --- source/gameengine/Ketsji/KX_ObjectActuator.cpp | 11 ++++++++--- source/gameengine/Ketsji/KX_ObjectActuator.h | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index f65b0ac0f4f..c987ebbdd85 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -140,6 +140,7 @@ bool KX_ObjectActuator::Update() m_angular_damping_active = false; m_error_accumulator.setValue(0.0,0.0,0.0); m_previous_error.setValue(0.0,0.0,0.0); + m_jumping = false; return false; } else if (parent) @@ -247,10 +248,14 @@ bool KX_ObjectActuator::Update() { parent->ApplyRotation(m_drot,(m_bitLocalFlag.DRot) != 0); } - if (m_bitLocalFlag.CharacterJump) - { - character->Jump(); + if (m_bitLocalFlag.CharacterJump) { + if (!m_jumping) { + character->Jump(); + m_jumping = true; + } + else if (character->OnGround()) + m_jumping = false; } } else { diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h index 1f2453e3700..b5622d97611 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.h +++ b/source/gameengine/Ketsji/KX_ObjectActuator.h @@ -116,7 +116,8 @@ class KX_ObjectActuator : public SCA_IActuator bool m_active_combined_velocity; bool m_linear_damping_active; bool m_angular_damping_active; - + bool m_jumping; + public: enum KX_OBJECT_ACT_VEC_TYPE { KX_OBJECT_ACT_NODEF = 0, -- cgit v1.2.3 From 057a8c625038ba9b22b01ebbd7bce9940479c034 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 14 May 2015 12:48:47 +0200 Subject: Add clear seams to uv editor --- release/scripts/startup/bl_ui/space_image.py | 3 ++- source/blender/editors/uvedit/uvedit_ops.c | 12 +++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index bd48116e8b5..40da82d44b5 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -336,7 +336,8 @@ class IMAGE_MT_uvs(Menu): layout.operator("uv.average_islands_scale") layout.operator("uv.minimize_stretch") layout.operator("uv.stitch") - layout.operator("uv.mark_seam") + layout.operator("uv.mark_seam").clear = False + layout.operator("uv.mark_seam", text="Clear Seam").clear = True layout.operator("uv.seams_from_islands") layout.operator("mesh.faces_mirror_uv") diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 37070a37c05..a5c5a015c72 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -4142,7 +4142,7 @@ static void UV_OT_seams_from_islands(wmOperatorType *ot) RNA_def_boolean(ot->srna, "mark_sharp", 0, "Mark Sharp", "Mark boundary edges as sharp"); } -static int uv_mark_seam_exec(bContext *C, wmOperator *UNUSED(op)) +static int uv_mark_seam_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_edit_object(C); Scene *scene = CTX_data_scene(C); @@ -4152,13 +4152,17 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *UNUSED(op)) BMFace *efa; BMLoop *loop; BMIter iter, liter; + bool clear = RNA_boolean_get(op->ptr, "clear"); const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_edge_select_test(scene, loop, cd_loop_uv_offset)) { - BM_elem_flag_enable(loop->e, BM_ELEM_SEAM); + if (clear) + BM_elem_flag_disable(loop->e, BM_ELEM_SEAM); + else + BM_elem_flag_enable(loop->e, BM_ELEM_SEAM); } } } @@ -4177,7 +4181,7 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *UNUSED(op)) static void UV_OT_mark_seam(wmOperatorType *ot) { /* identifiers */ - ot->name = "Mark Seams"; + ot->name = "Mark Seam"; ot->description = "Mark selected UV edges as seams"; ot->idname = "UV_OT_mark_seam"; @@ -4187,6 +4191,8 @@ static void UV_OT_mark_seam(wmOperatorType *ot) /* api callbacks */ ot->exec = uv_mark_seam_exec; ot->poll = ED_operator_uvedit; + + RNA_def_boolean(ot->srna, "clear", false, "Clear Seams", "Clear instead of marking seams"); } -- cgit v1.2.3 From 7aa74dfe5e1af9cf6dd3c6a5f2b3a3fadfcd2a36 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 14 May 2015 14:01:33 +0200 Subject: Radial operator: Percentage properties use interaction like factors with number feedback and easier way to go predict lower percentages. --- source/blender/windowmanager/intern/wm_operators.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 07d0bd0b62f..e8782a744bf 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3850,7 +3850,7 @@ void WM_OT_straightline_gesture(wmOperatorType *ot) #define WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE (35 * U.pixelsize) #define WM_RADIAL_CONTROL_DISPLAY_WIDTH (WM_RADIAL_CONTROL_DISPLAY_SIZE - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE) #define WM_RADIAL_CONTROL_HEADER_LENGTH 180 -#define WM_RADIAL_MAX_STR 6 +#define WM_RADIAL_MAX_STR 10 typedef struct { PropertyType type; @@ -3896,10 +3896,12 @@ static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *e switch (rc->subtype) { case PROP_NONE: case PROP_DISTANCE: - case PROP_PERCENTAGE: case PROP_PIXEL: d[0] = rc->initial_value * U.pixelsize; break; + case PROP_PERCENTAGE: + d[0] = (100.0f - rc->initial_value) / 100.0f * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; + break; case PROP_FACTOR: d[0] = (1 - rc->initial_value) * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; break; @@ -4005,13 +4007,21 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd switch (rc->subtype) { case PROP_NONE: case PROP_DISTANCE: - case PROP_PERCENTAGE: case PROP_PIXEL: r1 = rc->current_value * U.pixelsize; r2 = rc->initial_value * U.pixelsize; tex_radius = r1; alpha = 0.75; break; + case PROP_PERCENTAGE: + r1 = (100.0f - rc->current_value) / 100.0f * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; + r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; + rmin = WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; + BLI_snprintf(str, WM_RADIAL_MAX_STR, "%3.1f%%", rc->current_value); + strdrawlen = BLI_strlen_utf8(str); + tex_radius = r1; + alpha = 0.75; + break; case PROP_FACTOR: r1 = (1 - rc->current_value) * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; @@ -4446,12 +4456,15 @@ static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *even switch (rc->subtype) { case PROP_NONE: case PROP_DISTANCE: - case PROP_PERCENTAGE: case PROP_PIXEL: new_value = dist; if (snap) new_value = ((int)new_value + 5) / 10 * 10; new_value /= U.pixelsize; break; + case PROP_PERCENTAGE: + new_value = ((WM_RADIAL_CONTROL_DISPLAY_SIZE - dist) / WM_RADIAL_CONTROL_DISPLAY_WIDTH) * 100.0f; + if (snap) new_value = ((int)(new_value + 2.5)) / 5 * 5; + break; case PROP_FACTOR: new_value = (WM_RADIAL_CONTROL_DISPLAY_SIZE - dist) / WM_RADIAL_CONTROL_DISPLAY_WIDTH; if (snap) new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f; -- cgit v1.2.3 From 1ccc417477f4b629557708ebdb456b374e8a33f2 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 14 May 2015 14:16:28 +0200 Subject: Invert value calculation for percentages it makes more sense that way --- source/blender/windowmanager/intern/wm_operators.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index e8782a744bf..6820493132b 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3900,7 +3900,7 @@ static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *e d[0] = rc->initial_value * U.pixelsize; break; case PROP_PERCENTAGE: - d[0] = (100.0f - rc->initial_value) / 100.0f * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; + d[0] = (rc->initial_value) / 100.0f * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; break; case PROP_FACTOR: d[0] = (1 - rc->initial_value) * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; @@ -4014,7 +4014,7 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd alpha = 0.75; break; case PROP_PERCENTAGE: - r1 = (100.0f - rc->current_value) / 100.0f * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; + r1 = rc->current_value / 100.0f * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; r2 = tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; rmin = WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; BLI_snprintf(str, WM_RADIAL_MAX_STR, "%3.1f%%", rc->current_value); @@ -4462,7 +4462,7 @@ static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *even new_value /= U.pixelsize; break; case PROP_PERCENTAGE: - new_value = ((WM_RADIAL_CONTROL_DISPLAY_SIZE - dist) / WM_RADIAL_CONTROL_DISPLAY_WIDTH) * 100.0f; + new_value = ((dist - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE) / WM_RADIAL_CONTROL_DISPLAY_WIDTH) * 100.0f; if (snap) new_value = ((int)(new_value + 2.5)) / 5 * 5; break; case PROP_FACTOR: -- cgit v1.2.3 From e7f2aec81bb752a5bc8f1474a4733a8d31fdd821 Mon Sep 17 00:00:00 2001 From: Thomas Szepe Date: Thu, 14 May 2015 15:23:42 +0200 Subject: BGE: Add 'Lock Translation' for dynamic objects The XYZ translation lock was missing for dynamic object. Reviewed By: panzergame --- release/scripts/startup/bl_ui/properties_game.py | 2 +- source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py index 33b19eb0752..6fb172bf1e3 100644 --- a/release/scripts/startup/bl_ui/properties_game.py +++ b/release/scripts/startup/bl_ui/properties_game.py @@ -100,7 +100,6 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel): sub.prop(game, "damping", text="Translation", slider=True) sub.prop(game, "rotation_damping", text="Rotation", slider=True) - if physics_type == 'RIGID_BODY': layout.separator() split = layout.split() @@ -111,6 +110,7 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel): col.prop(game, "lock_location_y", text="Y") col.prop(game, "lock_location_z", text="Z") + if physics_type == 'RIGID_BODY': col = split.column() col.label(text="Lock Rotation:") col.prop(game, "lock_rotation_x", text="X") diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index dcc67205713..3670d79a01e 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -3535,9 +3535,10 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject if (rbody) { + rbody->setLinearFactor(ci.m_linearFactor); + if (isbulletrigidbody) { - rbody->setLinearFactor(ci.m_linearFactor); rbody->setAngularFactor(ci.m_angularFactor); } -- cgit v1.2.3 From 79aa50dc5340329676ddecda8d3d7bdb33ca643b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 14 May 2015 17:33:37 +0500 Subject: Cycles: Enable hair for split kernels when using Intel or NVidia drivers Apart from simply enabling this features needed changes to the code were done. Technical change, replacing SD access from "simple" structure to SOA. --- intern/cycles/kernel/geom/geom_curve.h | 92 +++++++++++++++++----------------- intern/cycles/kernel/kernel_types.h | 2 + 2 files changed, 48 insertions(+), 46 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h index ec6c790d9f7..9653ad8f1bb 100644 --- a/intern/cycles/kernel/geom/geom_curve.h +++ b/intern/cycles/kernel/geom/geom_curve.h @@ -32,22 +32,22 @@ ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, if(dy) *dy = 0.0f; #endif - return kernel_tex_fetch(__attributes_float, offset + sd->prim); + return kernel_tex_fetch(__attributes_float, offset + ccl_fetch(sd, prim)); } else if(elem == ATTR_ELEMENT_CURVE_KEY || elem == ATTR_ELEMENT_CURVE_KEY_MOTION) { - float4 curvedata = kernel_tex_fetch(__curves, sd->prim); - int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type); + float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim)); + int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type)); int k1 = k0 + 1; float f0 = kernel_tex_fetch(__attributes_float, offset + k0); float f1 = kernel_tex_fetch(__attributes_float, offset + k1); #ifdef __RAY_DIFFERENTIALS__ - if(dx) *dx = sd->du.dx*(f1 - f0); + if(dx) *dx = ccl_fetch(sd, du).dx*(f1 - f0); if(dy) *dy = 0.0f; #endif - return (1.0f - sd->u)*f0 + sd->u*f1; + return (1.0f - ccl_fetch(sd, u))*f0 + ccl_fetch(sd, u)*f1; } else { #ifdef __RAY_DIFFERENTIALS__ @@ -71,22 +71,22 @@ ccl_device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f); #endif - return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim)); + return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + ccl_fetch(sd, prim))); } else if(elem == ATTR_ELEMENT_CURVE_KEY || elem == ATTR_ELEMENT_CURVE_KEY_MOTION) { - float4 curvedata = kernel_tex_fetch(__curves, sd->prim); - int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type); + float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim)); + int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type)); int k1 = k0 + 1; float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k0)); float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k1)); #ifdef __RAY_DIFFERENTIALS__ - if(dx) *dx = sd->du.dx*(f1 - f0); + if(dx) *dx = ccl_fetch(sd, du).dx*(f1 - f0); if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f); #endif - return (1.0f - sd->u)*f0 + sd->u*f1; + return (1.0f - ccl_fetch(sd, u))*f0 + ccl_fetch(sd, u)*f1; } else { #ifdef __RAY_DIFFERENTIALS__ @@ -104,22 +104,22 @@ ccl_device float curve_thickness(KernelGlobals *kg, ShaderData *sd) { float r = 0.0f; - if(sd->type & PRIMITIVE_ALL_CURVE) { - float4 curvedata = kernel_tex_fetch(__curves, sd->prim); - int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type); + if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) { + float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim)); + int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type)); int k1 = k0 + 1; float4 P_curve[2]; - if(sd->type & PRIMITIVE_CURVE) { + if(ccl_fetch(sd, type) & PRIMITIVE_CURVE) { P_curve[0]= kernel_tex_fetch(__curve_keys, k0); P_curve[1]= kernel_tex_fetch(__curve_keys, k1); } else { - motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve); + motion_curve_keys(kg, ccl_fetch(sd, object), ccl_fetch(sd, prim), ccl_fetch(sd, time), k0, k1, P_curve); } - r = (P_curve[1].w - P_curve[0].w) * sd->u + P_curve[0].w; + r = (P_curve[1].w - P_curve[0].w) * ccl_fetch(sd, u) + P_curve[0].w; } return r*2.0f; @@ -130,8 +130,8 @@ ccl_device float curve_thickness(KernelGlobals *kg, ShaderData *sd) ccl_device float3 curve_motion_center_location(KernelGlobals *kg, ShaderData *sd) { - float4 curvedata = kernel_tex_fetch(__curves, sd->prim); - int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type); + float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim)); + int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type)); int k1 = k0 + 1; float4 P_curve[2]; @@ -139,7 +139,7 @@ ccl_device float3 curve_motion_center_location(KernelGlobals *kg, ShaderData *sd P_curve[0]= kernel_tex_fetch(__curve_keys, k0); P_curve[1]= kernel_tex_fetch(__curve_keys, k1); - return float4_to_float3(P_curve[1]) * sd->u + float4_to_float3(P_curve[0]) * (1.0f - sd->u); + return float4_to_float3(P_curve[1]) * ccl_fetch(sd, u) + float4_to_float3(P_curve[0]) * (1.0f - ccl_fetch(sd, u)); } /* Curve tangent normal */ @@ -148,14 +148,14 @@ ccl_device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd) { float3 tgN = make_float3(0.0f,0.0f,0.0f); - if(sd->type & PRIMITIVE_ALL_CURVE) { + if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) { - tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) / len_squared(sd->dPdu))); + tgN = -(-ccl_fetch(sd, I) - ccl_fetch(sd, dPdu) * (dot(ccl_fetch(sd, dPdu),-ccl_fetch(sd, I)) / len_squared(ccl_fetch(sd, dPdu)))); tgN = normalize(tgN); /* need to find suitable scaled gd for corrected normal */ #if 0 - tgN = normalize(tgN - gd * sd->dPdu); + tgN = normalize(tgN - gd * ccl_fetch(sd, dPdu)); #endif } @@ -890,7 +890,7 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con if(isect->object != OBJECT_NONE) { #ifdef __OBJECT_MOTION__ - Transform tfm = sd->ob_itfm; + Transform tfm = ccl_fetch(sd, ob_itfm); #else Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM); #endif @@ -903,7 +903,7 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con int prim = kernel_tex_fetch(__prim_index, isect->prim); float4 v00 = kernel_tex_fetch(__curves, prim); - int k0 = __float_as_int(v00.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type); + int k0 = __float_as_int(v00.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type)); int k1 = k0 + 1; float3 tg; @@ -914,14 +914,14 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con float4 P_curve[4]; - if(sd->type & PRIMITIVE_CURVE) { + if(ccl_fetch(sd, type) & PRIMITIVE_CURVE) { P_curve[0] = kernel_tex_fetch(__curve_keys, ka); P_curve[1] = kernel_tex_fetch(__curve_keys, k0); P_curve[2] = kernel_tex_fetch(__curve_keys, k1); P_curve[3] = kernel_tex_fetch(__curve_keys, kb); } else { - motion_cardinal_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve); + motion_cardinal_curve_keys(kg, ccl_fetch(sd, object), ccl_fetch(sd, prim), ccl_fetch(sd, time), ka, k0, k1, kb, P_curve); } float3 p[4]; @@ -933,43 +933,43 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con P = P + D*t; #ifdef __UV__ - sd->u = isect->u; - sd->v = 0.0f; + ccl_fetch(sd, u) = isect->u; + ccl_fetch(sd, v) = 0.0f; #endif tg = normalize(curvetangent(isect->u, p[0], p[1], p[2], p[3])); if(kernel_data.curve.curveflags & CURVE_KN_RIBBONS) { - sd->Ng = normalize(-(D - tg * (dot(tg, D)))); + ccl_fetch(sd, Ng) = normalize(-(D - tg * (dot(tg, D)))); } else { /* direction from inside to surface of curve */ float3 p_curr = curvepoint(isect->u, p[0], p[1], p[2], p[3]); - sd->Ng = normalize(P - p_curr); + ccl_fetch(sd, Ng) = normalize(P - p_curr); /* adjustment for changing radius */ float gd = isect->v; if(gd != 0.0f) { - sd->Ng = sd->Ng - gd * tg; - sd->Ng = normalize(sd->Ng); + ccl_fetch(sd, Ng) = ccl_fetch(sd, Ng) - gd * tg; + ccl_fetch(sd, Ng) = normalize(ccl_fetch(sd, Ng)); } } /* todo: sometimes the normal is still so that this is detected as * backfacing even if cull backfaces is enabled */ - sd->N = sd->Ng; + ccl_fetch(sd, N) = ccl_fetch(sd, Ng); } else { float4 P_curve[2]; - if(sd->type & PRIMITIVE_CURVE) { + if(ccl_fetch(sd, type) & PRIMITIVE_CURVE) { P_curve[0]= kernel_tex_fetch(__curve_keys, k0); P_curve[1]= kernel_tex_fetch(__curve_keys, k1); } else { - motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve); + motion_curve_keys(kg, ccl_fetch(sd, object), ccl_fetch(sd, prim), ccl_fetch(sd, time), k0, k1, P_curve); } float l = 1.0f; @@ -980,39 +980,39 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con float3 dif = P - float4_to_float3(P_curve[0]); #ifdef __UV__ - sd->u = dot(dif,tg)/l; - sd->v = 0.0f; + ccl_fetch(sd, u) = dot(dif,tg)/l; + ccl_fetch(sd, v) = 0.0f; #endif if(flag & CURVE_KN_TRUETANGENTGNORMAL) { - sd->Ng = -(D - tg * dot(tg, D)); - sd->Ng = normalize(sd->Ng); + ccl_fetch(sd, Ng) = -(D - tg * dot(tg, D)); + ccl_fetch(sd, Ng) = normalize(ccl_fetch(sd, Ng)); } else { float gd = isect->v; /* direction from inside to surface of curve */ - sd->Ng = (dif - tg * sd->u * l) / (P_curve[0].w + sd->u * l * gd); + ccl_fetch(sd, Ng) = (dif - tg * ccl_fetch(sd, u) * l) / (P_curve[0].w + ccl_fetch(sd, u) * l * gd); /* adjustment for changing radius */ if(gd != 0.0f) { - sd->Ng = sd->Ng - gd * tg; - sd->Ng = normalize(sd->Ng); + ccl_fetch(sd, Ng) = ccl_fetch(sd, Ng) - gd * tg; + ccl_fetch(sd, Ng) = normalize(ccl_fetch(sd, Ng)); } } - sd->N = sd->Ng; + ccl_fetch(sd, N) = ccl_fetch(sd, Ng); } #ifdef __DPDU__ /* dPdu/dPdv */ - sd->dPdu = tg; - sd->dPdv = cross(tg, sd->Ng); + ccl_fetch(sd, dPdu) = tg; + ccl_fetch(sd, dPdv) = cross(tg, ccl_fetch(sd, Ng)); #endif if(isect->object != OBJECT_NONE) { #ifdef __OBJECT_MOTION__ - Transform tfm = sd->ob_tfm; + Transform tfm = ccl_fetch(sd, ob_tfm); #else Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM); #endif diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index d8c47e48702..473e6bb2af5 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -109,6 +109,7 @@ CCL_NAMESPACE_BEGIN # define __BACKGROUND_MIS__ # define __LAMP_MIS__ # define __AO__ +# define __HAIR__ # endif #endif @@ -148,6 +149,7 @@ CCL_NAMESPACE_BEGIN # define __BACKGROUND_MIS__ # define __LAMP_MIS__ # define __AO__ +# define __HAIR__ # endif #endif -- cgit v1.2.3 From 33439626f12f84c0f0cc588644d8bf0fce86573a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 14 May 2015 18:19:21 +0500 Subject: Cycles: Add transformation functions with specified addrspace This is required for OpenCL prior to 2.0 and those functions will become handy when working on camera/motion blur support in split kernel. --- intern/cycles/util/util_transform.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index 1829ad29df3..0b87db0a379 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -462,6 +462,37 @@ Transform transform_from_viewplane(BoundBox2D& viewplane); #endif +/* TODO(sergey): This is only for until we've got OpenCL 2.0 + * on all devices we consider supported. It'll be replaced with + * generic address space. + */ + +#ifdef __KERNEL_OPENCL__ + +#define OPENCL_TRANSFORM_ADDRSPACE_GLUE(a, b) a ## b +#define OPENCL_TRANSFORM_ADDRSPACE_DECLARE(function) \ +ccl_device_inline float3 OPENCL_TRANSFORM_ADDRSPACE_GLUE(function, _addrspace)( \ + ccl_addr_space const Transform *t, const float3 a) \ +{ \ + Transform private_tfm = *t; \ + return function(&private_tfm, a); \ +} + +OPENCL_TRANSFORM_ADDRSPACE_DECLARE(transform_point) +OPENCL_TRANSFORM_ADDRSPACE_DECLARE(transform_direction) +OPENCL_TRANSFORM_ADDRSPACE_DECLARE(transform_direction_transposed) + +# undef OPENCL_TRANSFORM_ADDRSPACE_DECLARE +# undef OPENCL_TRANSFORM_ADDRSPACE_GLUE +# define transform_point_auto transform_point_addrspace +# define transform_direction_auto transform_direction_addrspace +# define transform_direction_transposed_auto transform_direction_transposed_addrspace +#else +# define transform_point_auto transform_point +# define transform_direction_auto transform_direction +# define transform_direction_transposed_auto transform_direction_transposed +#endif + CCL_NAMESPACE_END #endif /* __UTIL_TRANSFORM_H__ */ -- cgit v1.2.3 From 5a63edb92952aac9b754baffc99a91b975959576 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 14 May 2015 18:35:12 +0500 Subject: Cycles: Use special _auto versions of transform function in motion blur code Doing this as a separate commit so it's easier to revert in the future, once OpenCL 2.0 is becoming our requirement. --- intern/cycles/kernel/geom/geom_object.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h index d75a9bb15ba..2fc137880e8 100644 --- a/intern/cycles/kernel/geom/geom_object.h +++ b/intern/cycles/kernel/geom/geom_object.h @@ -123,7 +123,7 @@ ccl_device_inline Transform object_fetch_transform_motion_test(KernelGlobals *kg ccl_device_inline void object_position_transform(KernelGlobals *kg, const ShaderData *sd, float3 *P) { #ifdef __OBJECT_MOTION__ - *P = transform_point(&ccl_fetch(sd, ob_tfm), *P); + *P = transform_point_auto(&ccl_fetch(sd, ob_tfm), *P); #else Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM); *P = transform_point(&tfm, *P); @@ -135,7 +135,7 @@ ccl_device_inline void object_position_transform(KernelGlobals *kg, const Shader ccl_device_inline void object_inverse_position_transform(KernelGlobals *kg, const ShaderData *sd, float3 *P) { #ifdef __OBJECT_MOTION__ - *P = transform_point(&ccl_fetch(sd, ob_itfm), *P); + *P = transform_point_auto(&ccl_fetch(sd, ob_itfm), *P); #else Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_INVERSE_TRANSFORM); *P = transform_point(&tfm, *P); @@ -147,7 +147,7 @@ ccl_device_inline void object_inverse_position_transform(KernelGlobals *kg, cons ccl_device_inline void object_inverse_normal_transform(KernelGlobals *kg, const ShaderData *sd, float3 *N) { #ifdef __OBJECT_MOTION__ - *N = normalize(transform_direction_transposed(&ccl_fetch(sd, ob_tfm), *N)); + *N = normalize(transform_direction_transposed_auto(&ccl_fetch(sd, ob_tfm), *N)); #else Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM); *N = normalize(transform_direction_transposed(&tfm, *N)); @@ -159,7 +159,7 @@ ccl_device_inline void object_inverse_normal_transform(KernelGlobals *kg, const ccl_device_inline void object_normal_transform(KernelGlobals *kg, const ShaderData *sd, float3 *N) { #ifdef __OBJECT_MOTION__ - *N = normalize(transform_direction_transposed(&ccl_fetch(sd, ob_itfm), *N)); + *N = normalize(transform_direction_transposed_auto(&ccl_fetch(sd, ob_itfm), *N)); #else Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_INVERSE_TRANSFORM); *N = normalize(transform_direction_transposed(&tfm, *N)); @@ -171,7 +171,7 @@ ccl_device_inline void object_normal_transform(KernelGlobals *kg, const ShaderDa ccl_device_inline void object_dir_transform(KernelGlobals *kg, const ShaderData *sd, float3 *D) { #ifdef __OBJECT_MOTION__ - *D = transform_direction(&ccl_fetch(sd, ob_tfm), *D); + *D = transform_direction_auto(&ccl_fetch(sd, ob_tfm), *D); #else Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM); *D = transform_direction(&tfm, *D); @@ -183,7 +183,7 @@ ccl_device_inline void object_dir_transform(KernelGlobals *kg, const ShaderData ccl_device_inline void object_inverse_dir_transform(KernelGlobals *kg, const ShaderData *sd, float3 *D) { #ifdef __OBJECT_MOTION__ - *D = transform_direction(&ccl_fetch(sd, ob_itfm), *D); + *D = transform_direction_auto(&ccl_fetch(sd, ob_itfm), *D); #else Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_INVERSE_TRANSFORM); *D = transform_direction(&tfm, *D); -- cgit v1.2.3 From 3d3d805b64590268510dcb95753aabf50e28acad Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 14 May 2015 18:46:26 +0500 Subject: Cycles: Prepare code for OpenCL camera/motion blur The kernels are now compiling just fine, but there're some issues during rendering. This is still to be investigated. --- intern/cycles/kernel/geom/geom_motion_triangle.h | 8 ++++---- intern/cycles/kernel/geom/geom_object.h | 4 ++-- intern/cycles/kernel/geom/geom_triangle_intersect.h | 8 ++++---- intern/cycles/kernel/kernel_direct_lighting.cl | 7 ++++--- intern/cycles/kernel/kernel_shader.h | 10 +++++----- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_motion_triangle.h b/intern/cycles/kernel/geom/geom_motion_triangle.h index 4ea9e4714c4..86f93f242a1 100644 --- a/intern/cycles/kernel/geom/geom_motion_triangle.h +++ b/intern/cycles/kernel/geom/geom_motion_triangle.h @@ -134,7 +134,7 @@ ccl_device_inline float3 motion_triangle_refine(KernelGlobals *kg, ShaderData *s return P; } #ifdef __OBJECT_MOTION__ - Transform tfm = sd->ob_itfm; + Transform tfm = ccl_fetch(sd, ob_itfm); #else Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM); #endif @@ -161,7 +161,7 @@ ccl_device_inline float3 motion_triangle_refine(KernelGlobals *kg, ShaderData *s if(isect->object != OBJECT_NONE) { #ifdef __OBJECT_MOTION__ - Transform tfm = sd->ob_tfm; + Transform tfm = ccl_fetch(sd, ob_tfm); #else Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM); #endif @@ -187,7 +187,7 @@ ccl_device_inline float3 motion_triangle_refine_subsurface(KernelGlobals *kg, Sh #ifdef __INTERSECTION_REFINE__ if(isect->object != OBJECT_NONE) { #ifdef __OBJECT_MOTION__ - Transform tfm = sd->ob_itfm; + Transform tfm = ccl_fetch(sd, ob_itfm); #else Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM); #endif @@ -213,7 +213,7 @@ ccl_device_inline float3 motion_triangle_refine_subsurface(KernelGlobals *kg, Sh if(isect->object != OBJECT_NONE) { #ifdef __OBJECT_MOTION__ - Transform tfm = sd->ob_tfm; + Transform tfm = ccl_fetch(sd, ob_tfm); #else Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM); #endif diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h index 2fc137880e8..9d0a008fff1 100644 --- a/intern/cycles/kernel/geom/geom_object.h +++ b/intern/cycles/kernel/geom/geom_object.h @@ -453,7 +453,7 @@ ccl_device_inline void bvh_instance_pop_factor(KernelGlobals *kg, int object, co #ifdef __OBJECT_MOTION__ /* Transform ray into object space to enter motion blurred object in BVH */ -ccl_device_inline void bvh_instance_motion_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float *t, Transform *tfm) +ccl_device_inline void bvh_instance_motion_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, ccl_addr_space float *t, Transform *tfm) { Transform itfm; *tfm = object_fetch_transform_motion_test(kg, object, ray->time, &itfm); @@ -497,7 +497,7 @@ ccl_device_inline void qbvh_instance_motion_push(KernelGlobals *kg, int object, /* Transorm ray to exit motion blurred object in BVH */ -ccl_device_inline void bvh_instance_motion_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float *t, Transform *tfm) +ccl_device_inline void bvh_instance_motion_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, ccl_addr_space float *t, Transform *tfm) { if(*t != FLT_MAX) *t *= len(transform_direction(tfm, 1.0f/(*idir))); diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index 3990bae5478..0ea30eb7f13 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -306,7 +306,7 @@ ccl_device_inline float3 triangle_refine(KernelGlobals *kg, return P; } #ifdef __OBJECT_MOTION__ - Transform tfm = sd->ob_itfm; + Transform tfm = ccl_fetch(sd, ob_itfm); #else Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM); #endif @@ -332,7 +332,7 @@ ccl_device_inline float3 triangle_refine(KernelGlobals *kg, if(isect->object != OBJECT_NONE) { #ifdef __OBJECT_MOTION__ - Transform tfm = sd->ob_tfm; + Transform tfm = ccl_fetch(sd, ob_tfm); #else Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM); #endif @@ -361,7 +361,7 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg, #ifdef __INTERSECTION_REFINE__ if(isect->object != OBJECT_NONE) { #ifdef __OBJECT_MOTION__ - Transform tfm = sd->ob_itfm; + Transform tfm = ccl_fetch(sd, ob_itfm); #else Transform tfm = object_fetch_transform(kg, isect->object, @@ -389,7 +389,7 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg, if(isect->object != OBJECT_NONE) { #ifdef __OBJECT_MOTION__ - Transform tfm = sd->ob_tfm; + Transform tfm = ccl_fetch(sd, ob_tfm); #else Transform tfm = object_fetch_transform(kg, isect->object, diff --git a/intern/cycles/kernel/kernel_direct_lighting.cl b/intern/cycles/kernel/kernel_direct_lighting.cl index 8bdc7dc0fd1..f874122c508 100644 --- a/intern/cycles/kernel/kernel_direct_lighting.cl +++ b/intern/cycles/kernel/kernel_direct_lighting.cl @@ -105,13 +105,14 @@ __kernel void kernel_ocl_path_trace_direct_lighting( float light_u, light_v; path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v); -#ifdef __OBJECT_MOTION__ - light_ray.time = sd->time; -#endif LightSample ls; light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls); Ray light_ray; +#ifdef __OBJECT_MOTION__ + light_ray.time = ccl_fetch(sd, time); +#endif + BsdfEval L_light; bool is_lamp; if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce, sd_DL)) { diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index a12419624c3..1d94de87385 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -37,13 +37,13 @@ CCL_NAMESPACE_BEGIN #ifdef __OBJECT_MOTION__ ccl_device void shader_setup_object_transforms(KernelGlobals *kg, ShaderData *sd, float time) { - if(sd->flag & SD_OBJECT_MOTION) { - sd->ob_tfm = object_fetch_transform_motion(kg, sd->object, time); - sd->ob_itfm = transform_quick_inverse(sd->ob_tfm); + if(ccl_fetch(sd, flag) & SD_OBJECT_MOTION) { + ccl_fetch(sd, ob_tfm) = object_fetch_transform_motion(kg, ccl_fetch(sd, object), time); + ccl_fetch(sd, ob_itfm) = transform_quick_inverse(ccl_fetch(sd, ob_tfm)); } else { - sd->ob_tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); - sd->ob_itfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM); + ccl_fetch(sd, ob_tfm) = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM); + ccl_fetch(sd, ob_itfm) = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_INVERSE_TRANSFORM); } } #endif -- cgit v1.2.3 From 0a60c7d8eebeda18a66229cf5f4de0f37d2522d2 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 14 May 2015 19:08:13 +0500 Subject: Cycles: Fix missing camera-in-volume update when using certain render layers configurations --- intern/cycles/render/camera.cpp | 5 ++++- intern/cycles/render/camera.h | 1 + intern/cycles/render/object.cpp | 2 ++ intern/cycles/render/shader.cpp | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 8a4eaf63414..89505221862 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -80,6 +80,7 @@ Camera::Camera() need_update = true; need_device_update = true; + need_flags_update = true; previous_need_motion = -1; } @@ -171,6 +172,7 @@ void Camera::update() need_update = false; need_device_update = true; + need_flags_update = true; } void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) @@ -288,7 +290,7 @@ void Camera::device_update_volume(Device * /*device*/, DeviceScene *dscene, Scene *scene) { - if(!need_device_update) { + if(!need_device_update && !need_flags_update) { return; } KernelCamera *kcam = &dscene->data.cam; @@ -304,6 +306,7 @@ void Camera::device_update_volume(Device * /*device*/, } } need_device_update = false; + need_flags_update = false; } void Camera::device_free(Device * /*device*/, DeviceScene * /*dscene*/) diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 00387bcb7b1..3efbe904e2f 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -105,6 +105,7 @@ public: /* update */ bool need_update; bool need_device_update; + bool need_flags_update; int previous_need_motion; /* functions */ diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 6650b42d39c..da9bc23ccc4 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "camera.h" #include "device.h" #include "light.h" #include "mesh.h" @@ -192,6 +193,7 @@ void Object::tag_update(Scene *scene) } } + scene->camera->need_flags_update = true; scene->curve_system_manager->need_update = true; scene->mesh_manager->need_update = true; scene->object_manager->need_update = true; diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 2eaba3fa786..667279360c3 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -15,6 +15,7 @@ */ #include "background.h" +#include "camera.h" #include "device.h" #include "graph.h" #include "light.h" -- cgit v1.2.3 From 5c3426638389e25e96a17f4efdf7efdf0dfaed2d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 14 May 2015 23:35:19 +0500 Subject: Cycles: Enable camera motion blur in split kernel for Intel/NVidia It's good for testing and seems to work quite reliably here. This probably not totally cheap in terms of performance, but this we could solve quite easily by selective kernel compilation once other things are tested/proved to be reliable. --- intern/cycles/kernel/kernel_types.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 473e6bb2af5..7108d7b6ed9 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -110,6 +110,7 @@ CCL_NAMESPACE_BEGIN # define __LAMP_MIS__ # define __AO__ # define __HAIR__ +# define __CAMERA_MOTION__ # endif #endif @@ -150,6 +151,7 @@ CCL_NAMESPACE_BEGIN # define __LAMP_MIS__ # define __AO__ # define __HAIR__ +# define __CAMERA_MOTION__ # endif #endif -- cgit v1.2.3 From f6c6dd44de766725e4409b8cae357817661b91fe Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 14 May 2015 23:44:19 +0500 Subject: Cycles: Remove meaningless ifdef checks for features in device_opencl This file was actually checking for features enabled on CPU and surely all of them were enabled, so removing them does not cause any difference. ideally we'll need to do runtime feature detection and just pass some stuff as NULL to the kernel, or maybe also have variadic kernel entry points which is also possible quite easily. --- intern/cycles/device/device_opencl.cpp | 42 +++++++++++++++++--------------- intern/cycles/kernel/kernel_data_init.cl | 9 ++++--- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index f2ac5fcc00b..9153aa32e60 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -1569,16 +1569,17 @@ public: cl_mem ray_depth_sd_DL_shadow; cl_mem transparent_depth_sd; cl_mem transparent_depth_sd_DL_shadow; -#ifdef __RAY_DIFFERENTIALS__ + + /* Ray differentials. */ cl_mem dP_sd, dI_sd; cl_mem dP_sd_DL_shadow, dI_sd_DL_shadow; cl_mem du_sd, dv_sd; cl_mem du_sd_DL_shadow, dv_sd_DL_shadow; -#endif -#ifdef __DPDU__ + + /* Dp/Du */ cl_mem dPdu_sd, dPdv_sd; cl_mem dPdu_sd_DL_shadow, dPdv_sd_DL_shadow; -#endif + cl_mem closure_sd; cl_mem closure_sd_DL_shadow; cl_mem num_closure_sd; @@ -1719,7 +1720,8 @@ public: ray_depth_sd_DL_shadow = NULL; transparent_depth_sd = NULL; transparent_depth_sd_DL_shadow = NULL; -#ifdef __RAY_DIFFERENTIALS__ + + /* Ray differentials. */ dP_sd = NULL; dI_sd = NULL; dP_sd_DL_shadow = NULL; @@ -1728,13 +1730,13 @@ public: dv_sd = NULL; du_sd_DL_shadow = NULL; dv_sd_DL_shadow = NULL; -#endif -#ifdef __DPDU__ + + /* Dp/Du */ dPdu_sd = NULL; dPdv_sd = NULL; dPdu_sd_DL_shadow = NULL; dPdv_sd_DL_shadow = NULL; -#endif + closure_sd = NULL; closure_sd_DL_shadow = NULL; num_closure_sd = NULL; @@ -2088,7 +2090,8 @@ public: release_mem_object_safe(ray_depth_sd_DL_shadow); release_mem_object_safe(transparent_depth_sd); release_mem_object_safe(transparent_depth_sd_DL_shadow); -#ifdef __RAY_DIFFERENTIALS__ + + /* Ray differentials. */ release_mem_object_safe(dP_sd); release_mem_object_safe(dP_sd_DL_shadow); release_mem_object_safe(dI_sd); @@ -2097,13 +2100,13 @@ public: release_mem_object_safe(du_sd_DL_shadow); release_mem_object_safe(dv_sd); release_mem_object_safe(dv_sd_DL_shadow); -#endif -#ifdef __DPDU__ + + /* Dp/Du */ release_mem_object_safe(dPdu_sd); release_mem_object_safe(dPdu_sd_DL_shadow); release_mem_object_safe(dPdv_sd); release_mem_object_safe(dPdv_sd_DL_shadow); -#endif + release_mem_object_safe(closure_sd); release_mem_object_safe(closure_sd_DL_shadow); release_mem_object_safe(num_closure_sd); @@ -2283,7 +2286,7 @@ public: transparent_depth_sd = mem_alloc(num_global_elements * sizeof(int)); transparent_depth_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(int)); -#ifdef __RAY_DIFFERENTIALS__ + /* Ray differentials. */ dP_sd = mem_alloc(num_global_elements * sizeof(differential3)); dP_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(differential3)); dI_sd = mem_alloc(num_global_elements * sizeof(differential3)); @@ -2292,14 +2295,13 @@ public: du_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(differential)); dv_sd = mem_alloc(num_global_elements * sizeof(differential)); dv_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(differential)); -#endif -#ifdef __DPDU__ + /* Dp/Du */ dPdu_sd = mem_alloc(num_global_elements * sizeof(float3)); dPdu_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3)); dPdv_sd = mem_alloc(num_global_elements * sizeof(float3)); dPdv_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3)); -#endif + closure_sd = mem_alloc(num_global_elements * ShaderClosure_size); closure_sd_DL_shadow = mem_alloc(num_global_elements * 2 * ShaderClosure_size); num_closure_sd = mem_alloc(num_global_elements * sizeof(int)); @@ -2388,7 +2390,7 @@ public: start_arg_index += kernel_set_args(ckPathTraceKernel_data_init, start_arg_index, -#ifdef __RAY_DIFFERENTIALS__ + /* Ray differentials. */ dP_sd, dP_sd_DL_shadow, dI_sd, @@ -2397,13 +2399,13 @@ public: du_sd_DL_shadow, dv_sd, dv_sd_DL_shadow, -#endif -#ifdef __DPDU__ + + /* Dp/Du */ dPdu_sd, dPdu_sd_DL_shadow, dPdv_sd, dPdv_sd_DL_shadow, -#endif + closure_sd, closure_sd_DL_shadow, num_closure_sd, diff --git a/intern/cycles/kernel/kernel_data_init.cl b/intern/cycles/kernel/kernel_data_init.cl index dbf9e62ccbf..7982573b9e1 100644 --- a/intern/cycles/kernel/kernel_data_init.cl +++ b/intern/cycles/kernel/kernel_data_init.cl @@ -100,7 +100,8 @@ __kernel void kernel_ocl_path_trace_data_initialization( ccl_global int *transparent_depth_sd, ccl_global int *transparent_depth_sd_DL_shadow, - #ifdef __RAY_DIFFERENTIALS__ + + /* Ray differentials. */ ccl_global differential3 *dP_sd, ccl_global differential3 *dP_sd_DL_shadow, @@ -112,14 +113,14 @@ __kernel void kernel_ocl_path_trace_data_initialization( ccl_global differential *dv_sd, ccl_global differential *dv_sd_DL_shadow, - #endif - #ifdef __DPDU__ + + /* Dp/Du */ ccl_global float3 *dPdu_sd, ccl_global float3 *dPdu_sd_DL_shadow, ccl_global float3 *dPdv_sd, ccl_global float3 *dPdv_sd_DL_shadow, - #endif + ShaderClosure *closure_sd, ShaderClosure *closure_sd_DL_shadow, -- cgit v1.2.3 From 03565218d5a85f06a26a1ac95e70991613faaf2a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 May 2015 00:42:05 +0500 Subject: Cycles: Various fixes Some stupid fixes like spaces around operator and missing semicolon, plus fix for wrong detecting of ShaderData SOA size. Thar was harmless since there's only one closure array, but still better to fix this. --- intern/cycles/device/device_opencl.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 9153aa32e60..81edd25f958 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -1867,7 +1867,7 @@ public: size_t get_shader_closure_size(int max_closure) { - return (sizeof(ShaderClosure)* max_closure); + return (sizeof(ShaderClosure) * max_closure); } size_t get_shader_data_size(size_t shader_closure_size) @@ -1900,10 +1900,8 @@ public: { size_t shader_soa_size = 0; -#define SD_VAR(type, what) \ - shader_soa_size += sizeof(void *); -#define SD_CLOSURE_VAR(type, what, max_closure) - shader_soa_size += sizeof(void *); +#define SD_VAR(type, what) shader_soa_size += sizeof(void *); +#define SD_CLOSURE_VAR(type, what, max_closure) shader_soa_size += sizeof(void *); #include "kernel_shaderdata_vars.h" #undef SD_VAR #undef SD_CLOSURE_VAR @@ -2215,7 +2213,7 @@ public: */ if(num_parallel_samples >= 64) { /* TODO(sergey): Could use generic round-up here. */ - num_parallel_samples = (num_parallel_samples / 64) * 64 + num_parallel_samples = (num_parallel_samples / 64) * 64; } assert(num_parallel_samples != 0); -- cgit v1.2.3 From 3c10ec96b5ec1c705362ccdaeaac8007050d081f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 May 2015 00:48:12 +0500 Subject: Cycles: Enable object motion blur on Intel OpenCL platform This required allocating some memory related on object transform needed by ShaderData and currently it is done for all the platforms. Since we're targeting full feature-complete platforms this is rather acceptable at this point and in the future we'll do selective NO_HAIR/NO_SSS/NO_BLUR kernels. This is experimental still and in fact there're some major issues on NVidia platform and it's not really clear if it's a bug in compiler, some uninitizlied variable or other kind of issue. --- intern/cycles/device/device_opencl.cpp | 46 +++++++++++++++++++++++++++++--- intern/cycles/kernel/kernel_data_init.cl | 15 +++++++++++ intern/cycles/kernel/kernel_types.h | 16 +---------- 3 files changed, 58 insertions(+), 19 deletions(-) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 81edd25f958..d27cf8d13c9 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -1580,6 +1580,10 @@ public: cl_mem dPdu_sd, dPdv_sd; cl_mem dPdu_sd_DL_shadow, dPdv_sd_DL_shadow; + /* Object motion. */ + cl_mem ob_tfm_sd, ob_itfm_sd; + cl_mem ob_tfm_sd_DL_shadow, ob_itfm_sd_DL_shadow; + cl_mem closure_sd; cl_mem closure_sd_DL_shadow; cl_mem num_closure_sd; @@ -1737,6 +1741,12 @@ public: dPdu_sd_DL_shadow = NULL; dPdv_sd_DL_shadow = NULL; + /* Object motion. */ + ob_tfm_sd = NULL; + ob_itfm_sd = NULL; + ob_tfm_sd_DL_shadow = NULL; + ob_itfm_sd_DL_shadow = NULL; + closure_sd = NULL; closure_sd_DL_shadow = NULL; num_closure_sd = NULL; @@ -2105,6 +2115,13 @@ public: release_mem_object_safe(dPdv_sd); release_mem_object_safe(dPdv_sd_DL_shadow); + /* Object motion. */ + release_mem_object_safe(ob_tfm_sd); + release_mem_object_safe(ob_itfm_sd); + + release_mem_object_safe(ob_tfm_sd_DL_shadow); + release_mem_object_safe(ob_itfm_sd_DL_shadow); + release_mem_object_safe(closure_sd); release_mem_object_safe(closure_sd_DL_shadow); release_mem_object_safe(num_closure_sd); @@ -2300,6 +2317,12 @@ public: dPdv_sd = mem_alloc(num_global_elements * sizeof(float3)); dPdv_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(float3)); + /* Object motion. */ + ob_tfm_sd = mem_alloc(num_global_elements * sizeof(Transform)); + ob_tfm_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(Transform)); + ob_itfm_sd = mem_alloc(num_global_elements * sizeof(float3)); + ob_itfm_sd_DL_shadow = mem_alloc(num_global_elements * 2 * sizeof(Transform)); + closure_sd = mem_alloc(num_global_elements * ShaderClosure_size); closure_sd_DL_shadow = mem_alloc(num_global_elements * 2 * ShaderClosure_size); num_closure_sd = mem_alloc(num_global_elements * sizeof(int)); @@ -2385,10 +2408,10 @@ public: transparent_depth_sd, transparent_depth_sd_DL_shadow); + /* Ray differentials. */ start_arg_index += kernel_set_args(ckPathTraceKernel_data_init, start_arg_index, - /* Ray differentials. */ dP_sd, dP_sd_DL_shadow, dI_sd, @@ -2396,14 +2419,29 @@ public: du_sd, du_sd_DL_shadow, dv_sd, - dv_sd_DL_shadow, + dv_sd_DL_shadow); - /* Dp/Du */ + /* Dp/Du */ + start_arg_index += + kernel_set_args(ckPathTraceKernel_data_init, + start_arg_index, dPdu_sd, dPdu_sd_DL_shadow, dPdv_sd, - dPdv_sd_DL_shadow, + dPdv_sd_DL_shadow); + + /* Object motion. */ + start_arg_index += + kernel_set_args(ckPathTraceKernel_data_init, + start_arg_index, + ob_tfm_sd, + ob_tfm_sd_DL_shadow, + ob_itfm_sd, + ob_itfm_sd_DL_shadow); + start_arg_index += + kernel_set_args(ckPathTraceKernel_data_init, + start_arg_index, closure_sd, closure_sd_DL_shadow, num_closure_sd, diff --git a/intern/cycles/kernel/kernel_data_init.cl b/intern/cycles/kernel/kernel_data_init.cl index 7982573b9e1..4c5f08639dd 100644 --- a/intern/cycles/kernel/kernel_data_init.cl +++ b/intern/cycles/kernel/kernel_data_init.cl @@ -121,6 +121,13 @@ __kernel void kernel_ocl_path_trace_data_initialization( ccl_global float3 *dPdv_sd, ccl_global float3 *dPdv_sd_DL_shadow, + /* Object motion. */ + ccl_global Transform *ob_tfm_sd, + ccl_global Transform *ob_tfm_sd_DL_shadow, + + ccl_global Transform *ob_itfm_sd, + ccl_global Transform *ob_itfm_sd_DL_shadow, + ShaderClosure *closure_sd, ShaderClosure *closure_sd_DL_shadow, @@ -249,6 +256,14 @@ __kernel void kernel_ocl_path_trace_data_initialization( #endif #endif +#ifdef __OBJECT_MOTION__ + sd->ob_tfm = ob_tfm_sd; + sd_DL_shadow->ob_tfm = ob_tfm_sd_DL_shadow; + + sd->ob_itfm = ob_itfm_sd; + sd_DL_shadow->ob_itfm = ob_itfm_sd_DL_shadow; +#endif + sd->closure = closure_sd; sd_DL_shadow->closure = closure_sd_DL_shadow; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 7108d7b6ed9..8f91937ac33 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -138,21 +138,7 @@ CCL_NAMESPACE_BEGIN #ifdef __KERNEL_OPENCL_INTEL_CPU__ #define __CL_USE_NATIVE__ #define __KERNEL_SHADING__ -/* TODO(sergey): Advanced shading code still requires work - * for split kernel. - */ -# ifndef __SPLIT_KERNEL__ -# define __KERNEL_ADV_SHADING__ -# else -# define __MULTI_CLOSURE__ -# define __TRANSPARENT_SHADOWS__ -# define __PASSES__ -# define __BACKGROUND_MIS__ -# define __LAMP_MIS__ -# define __AO__ -# define __HAIR__ -# define __CAMERA_MOTION__ -# endif +#define __KERNEL_ADV_SHADING__ #endif #endif // __KERNEL_OPENCL__ -- cgit v1.2.3 From 7549ec7301cf051931878180eba52da16bc4c4ad Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Thu, 14 May 2015 23:58:08 +0200 Subject: Fix some issues found by Coverity Scan Some of them are just brain dead code, some are potential bugs. --- .../blender/editors/animation/anim_channels_edit.c | 2 +- .../blender/editors/interface/interface_handlers.c | 3 +++ source/blender/editors/interface/interface_panel.c | 1 - .../blender/editors/interface/interface_regions.c | 3 ++- source/blender/editors/interface/interface_style.c | 6 ++++- .../editors/interface/interface_templates.c | 1 - source/blender/editors/screen/area.c | 28 +++++++++++++--------- source/blender/editors/screen/screen_edit.c | 4 +++- source/blender/editors/space_file/filelist.c | 4 ++-- source/blender/editors/space_view3d/view3d_draw.c | 3 +++ .../editors/transform/transform_manipulator.c | 2 -- .../blender/windowmanager/intern/wm_event_system.c | 4 ++-- source/blender/windowmanager/intern/wm_keymap.c | 2 +- 13 files changed, 39 insertions(+), 24 deletions(-) diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index fd7551abab3..d08a32c6e6b 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -3055,7 +3055,7 @@ static bool select_anim_channel_keys(bAnimContext *ac, int channel_index, bool e ANIM_animdata_freelist(&anim_data); /* F-Curve may not have any keyframes */ - if (fcu->bezt) { + if (fcu && fcu->bezt) { BezTriple *bezt; if (!extend) { diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index d77cf8658fd..7e970a13e03 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -9077,6 +9077,9 @@ static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPo block = ar->uiblocks.first; but = ui_but_find_active_in_region(ar); + + BLI_assert(but); + data = but->active; submenu = data->menu; diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 95fca10d60b..4b0585c34b3 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -1215,7 +1215,6 @@ static void ui_panel_drag_collapse(bContext *C, uiPanelDragCollapseHandle *dragc rect.ymin = rect.ymax; rect.ymax = rect.ymin + PNL_HEADER; if (pa->flag & PNL_CLOSEDX) { - rect.xmin = rect.xmin; rect.xmax = rect.xmin + PNL_HEADER; } diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 9f5aa37351a..4b90abed82b 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1427,7 +1427,8 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, if (down || top) { if (dir1 == UI_DIR_UP && top == 0) dir1 = UI_DIR_DOWN; if (dir1 == UI_DIR_DOWN && down == 0) dir1 = UI_DIR_UP; - if (dir2 == UI_DIR_UP && top == 0) dir2 = UI_DIR_DOWN; + /* dir2 is never set to UI_DIR_UP here */ +// if (dir2 == UI_DIR_UP && top == 0) dir2 = UI_DIR_DOWN; if (dir2 == UI_DIR_DOWN && down == 0) dir2 = UI_DIR_UP; } diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c index 2f46c0906ae..4b683f3fcc2 100644 --- a/source/blender/editors/interface/interface_style.c +++ b/source/blender/editors/interface/interface_style.c @@ -323,10 +323,14 @@ void UI_fontstyle_draw_simple_backdrop( /* XXX: read a style configure */ uiStyle *UI_style_get(void) { +#if 0 uiStyle *style = NULL; /* offset is two struct uiStyle pointers */ - /* style = BLI_findstring(&U.uistyles, "Unifont Style", sizeof(style) * 2) */; + style = BLI_findstring(&U.uistyles, "Unifont Style", sizeof(style) * 2); return (style != NULL) ? style : U.uistyles.first; +#else + return U.uistyles.first; +#endif } /* for drawing, scaled with DPI setting */ diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index ccbd30d1230..2cab1aea83f 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -3214,7 +3214,6 @@ void uiTemplateList( /* add scrollbar */ if (len > layoutdata.visual_items) { - col = uiLayoutColumn(row, false); uiDefButI(block, UI_BTYPE_SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height, &ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height, dyn_data->visual_height, 0, ""); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 3a4034d9074..7fe6518134e 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1263,16 +1263,22 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti if (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) { ar->winrct = *remainder; - if (alignment == RGN_ALIGN_TOP) - ar->winrct.ymin = ar->winrct.ymax; - else if (alignment == RGN_ALIGN_BOTTOM) - ar->winrct.ymax = ar->winrct.ymin; - else if (alignment == RGN_ALIGN_RIGHT) - ar->winrct.xmin = ar->winrct.xmax; - else if (alignment == RGN_ALIGN_LEFT) - ar->winrct.xmax = ar->winrct.xmin; - else /* prevent winrct to be valid */ - ar->winrct.xmax = ar->winrct.xmin; + switch (alignment) { + case RGN_ALIGN_TOP: + ar->winrct.ymin = ar->winrct.ymax; + break; + case RGN_ALIGN_BOTTOM: + ar->winrct.ymax = ar->winrct.ymin; + break; + case RGN_ALIGN_RIGHT: + ar->winrct.xmin = ar->winrct.xmax; + break; + case RGN_ALIGN_LEFT: + default: + /* prevent winrct to be valid */ + ar->winrct.xmax = ar->winrct.xmin; + break; + } } /* restore prev-split exception */ @@ -2161,7 +2167,7 @@ static void metadata_draw_imbuf(ImBuf *ibuf, rctf rect, int fontid, const bool i static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top) { - char str[MAX_METADATA_STR]; + char str[MAX_METADATA_STR] = ""; short i, count = 0; const float height = BLF_height_max(fontid) + 0.1f * U.widget_unit; diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 3d76070f197..d9bd9cc4f51 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1748,7 +1748,9 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type) newsa = sa; } } - + + BLI_assert(newsa); + if (sa && (sa->spacetype != type)) { newsa->flag |= AREA_FLAG_TEMP_TYPE; } diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 2853ee9c053..af65149ff9c 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -1234,7 +1234,7 @@ static void filelist_from_main(struct FileList *filelist) files = filelist->filelist; - if (!filelist->filter_data.hide_parent) { + if (files && !filelist->filter_data.hide_parent) { memset(&(filelist->filelist[0]), 0, sizeof(struct direntry)); filelist->filelist[0].relname = BLI_strdup(FILENAME_PARENT); filelist->filelist[0].type |= S_IFDIR; @@ -1246,7 +1246,7 @@ static void filelist_from_main(struct FileList *filelist) for (id = lb->first; id; id = id->next) { ok = 1; if (ok) { - if (!filelist->filter_data.hide_dot || id->name[2] != '.') { + if (files && (!filelist->filter_data.hide_dot || id->name[2] != '.')) { memset(files, 0, sizeof(struct direntry)); if (id->lib == NULL) { files->relname = BLI_strdup(id->name + 2); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 57b417ef1d7..fb0f437884a 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -3262,6 +3262,9 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in GPUOffScreen *ofs; bool draw_sky = (alpha_mode == R_ADDSKY) && v3d && (v3d->flag3 & V3D_SHOW_WORLD); + if (UNLIKELY(v3d == NULL)) + return NULL; + /* state changes make normal drawing go weird otherwise */ glPushAttrib(GL_LIGHTING_BIT); diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index ae8cbc721e3..b55a5ffbdbb 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -1056,8 +1056,6 @@ static void draw_manipulator_rotate( glRotatef(90.0, 1.0, 0.0, 0.0); postOrtho(ortho); } - - if (arcs) glDisable(GL_CLIP_PLANE0); } // donut arcs if (arcs) { diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 69bee8bab80..42fc0267625 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1173,7 +1173,7 @@ static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA CTX_wm_operator_poll_msg_set(C, NULL); /* dummie test */ - if (ot && C) { + if (ot) { wmWindow *window = CTX_wm_window(C); switch (context) { @@ -2434,7 +2434,7 @@ void wm_event_do_handlers(bContext *C) /* XXX hrmf, this gives reliable previous mouse coord for area change, feels bad? * doing it on ghost queue gives errors when mousemoves go over area borders */ - if (doit && win->screen && win->screen->subwinactive != win->screen->mainwin) { + if (doit && win->screen->subwinactive != win->screen->mainwin) { win->eventstate->prevx = event->x; win->eventstate->prevy = event->y; //printf("win->eventstate->prev = %d %d\n", event->x, event->y); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 0ee1f9f7eeb..c765587b7cb 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -546,7 +546,7 @@ static void wm_keymap_diff(wmKeyMap *diff_km, wmKeyMap *from_km, wmKeyMap *to_km if (to_kmi) { orig_kmi = WM_keymap_item_find_id(orig_km, kmi->id); - if (!orig_kmi) + if (!orig_kmi && addon_km) orig_kmi = wm_keymap_find_item_equals(addon_km, kmi); if (orig_kmi) { -- cgit v1.2.3 From a92d8a34a82550fff5032bb224dbe355ecdb75c4 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 15 May 2015 01:25:03 +0200 Subject: Add material reorder buttons for Cycles as well --- intern/cycles/blender/addon/ui.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index b5ce5a4e3cd..d24099b92a5 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -552,11 +552,16 @@ class Cycles_PT_context_material(CyclesButtonsPanel, Panel): ob = context.object slot = context.material_slot space = context.space_data + is_sortable = len(ob.material_slots) > 1 if ob: + rows = 1 + if (is_sortable): + rows = 4 + row = layout.row() - row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=1) + row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows) col = row.column(align=True) col.operator("object.material_slot_add", icon='ZOOMIN', text="") @@ -564,6 +569,12 @@ class Cycles_PT_context_material(CyclesButtonsPanel, Panel): col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="") + if is_sortable: + col.separator() + + col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP' + col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN' + if ob.mode == 'EDIT': row = layout.row(align=True) row.operator("object.material_slot_assign", text="Assign") -- cgit v1.2.3 From bc371030a719725797f91c4808837258f28a986d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 15 May 2015 10:55:22 +1000 Subject: BMesh: rename loop walker -> edgeloop --- source/blender/bmesh/intern/bmesh_walkers.h | 2 +- source/blender/bmesh/intern/bmesh_walkers_impl.c | 26 +++++++++++----------- .../blender/bmesh/intern/bmesh_walkers_private.h | 4 ++-- source/blender/editors/mesh/editmesh_select.c | 8 +++---- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_walkers.h b/source/blender/bmesh/intern/bmesh_walkers.h index e84880dc61e..00217dd7a5e 100644 --- a/source/blender/bmesh/intern/bmesh_walkers.h +++ b/source/blender/bmesh/intern/bmesh_walkers.h @@ -110,7 +110,7 @@ void BMW_reset(BMWalker *walker); enum { BMW_VERT_SHELL, BMW_FACE_SHELL, - BMW_LOOP, + BMW_EDGELOOP, BMW_FACELOOP, BMW_EDGERING, BMW_EDGEBOUNDARY, diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index b7bf80b0e3f..6cdabe61bfb 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -543,9 +543,9 @@ static bool bm_edge_is_single(BMEdge *e) (BM_edge_is_boundary(e->l->next->e) || BM_edge_is_boundary(e->l->prev->e))); } -static void bmw_LoopWalker_begin(BMWalker *walker, void *data) +static void bmw_EdgeLoopWalker_begin(BMWalker *walker, void *data) { - BMwLoopWalker *lwalk = NULL, owalk, *owalk_pt; + BMwEdgeLoopWalker *lwalk = NULL, owalk, *owalk_pt; BMEdge *e = data; BMVert *v; const int vert_edge_count[2] = { @@ -593,7 +593,7 @@ static void bmw_LoopWalker_begin(BMWalker *walker, void *data) /* rewind */ while ((owalk_pt = BMW_current_state(walker))) { - owalk = *((BMwLoopWalker *)owalk_pt); + owalk = *((BMwEdgeLoopWalker *)owalk_pt); BMW_walk(walker); } @@ -606,16 +606,16 @@ static void bmw_LoopWalker_begin(BMWalker *walker, void *data) BLI_gset_insert(walker->visit_set, owalk.cur); } -static void *bmw_LoopWalker_yield(BMWalker *walker) +static void *bmw_EdgeLoopWalker_yield(BMWalker *walker) { - BMwLoopWalker *lwalk = BMW_current_state(walker); + BMwEdgeLoopWalker *lwalk = BMW_current_state(walker); return lwalk->cur; } -static void *bmw_LoopWalker_step(BMWalker *walker) +static void *bmw_EdgeLoopWalker_step(BMWalker *walker) { - BMwLoopWalker *lwalk, owalk; + BMwEdgeLoopWalker *lwalk, owalk; BMEdge *e, *nexte = NULL; BMLoop *l; BMVert *v; @@ -1278,12 +1278,12 @@ static BMWalker bmw_IslandWalker_Type = { BM_EDGE | BM_FACE, /* valid restrict masks */ }; -static BMWalker bmw_LoopWalker_Type = { +static BMWalker bmw_EdgeLoopWalker_Type = { BM_EDGE, - bmw_LoopWalker_begin, - bmw_LoopWalker_step, - bmw_LoopWalker_yield, - sizeof(BMwLoopWalker), + bmw_EdgeLoopWalker_begin, + bmw_EdgeLoopWalker_step, + bmw_EdgeLoopWalker_yield, + sizeof(BMwEdgeLoopWalker), BMW_DEPTH_FIRST, 0, /* valid restrict masks */ /* could add flags here but so far none are used */ }; @@ -1341,7 +1341,7 @@ static BMWalker bmw_ConnectedVertexWalker_Type = { BMWalker *bm_walker_types[] = { &bmw_VertShellWalker_Type, /* BMW_VERT_SHELL */ &bmw_FaceShellWalker_Type, /* BMW_FACE_SHELL */ - &bmw_LoopWalker_Type, /* BMW_LOOP */ + &bmw_EdgeLoopWalker_Type, /* BMW_EDGELOOP */ &bmw_FaceLoopWalker_Type, /* BMW_FACELOOP */ &bmw_EdgeringWalker_Type, /* BMW_EDGERING */ &bmw_EdgeboundaryWalker_Type, /* BMW_EDGEBOUNDARY */ diff --git a/source/blender/bmesh/intern/bmesh_walkers_private.h b/source/blender/bmesh/intern/bmesh_walkers_private.h index 82d1e760db7..629f4f09c92 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_private.h +++ b/source/blender/bmesh/intern/bmesh_walkers_private.h @@ -57,14 +57,14 @@ typedef struct BMwIslandWalker { BMFace *cur; } BMwIslandWalker; -typedef struct BMwLoopWalker { +typedef struct BMwEdgeLoopWalker { BMwGenericWalker header; BMEdge *cur, *start; BMVert *lastv, *startv; BMFace *f_hub; bool is_boundary; /* boundary looping changes behavior */ bool is_single; /* single means the edge verts are only connected to 1 face */ -} BMwLoopWalker; +} BMwEdgeLoopWalker; typedef struct BMwFaceLoopWalker { BMwGenericWalker header; diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 4ce493def5b..0a712a218b1 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -1454,7 +1454,7 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op) else { for (edindex = 0; edindex < totedgesel; edindex += 1) { eed = edarray[edindex]; - walker_select(em, BMW_LOOP, eed, true); + walker_select(em, BMW_EDGELOOP, eed, true); } EDBM_selectmode_flush(em); } @@ -1512,12 +1512,12 @@ static void mouse_mesh_loop_edge(BMEditMesh *em, BMEdge *eed, bool select, bool { bool edge_boundary = false; - /* cycle between BMW_LOOP / BMW_EDGEBOUNDARY */ + /* cycle between BMW_EDGELOOP / BMW_EDGEBOUNDARY */ if (select_cycle && BM_edge_is_boundary(eed)) { int tot[2]; /* if the loops selected toggle the boundaries */ - walker_select_count(em, BMW_LOOP, eed, select, false, + walker_select_count(em, BMW_EDGELOOP, eed, select, false, &tot[0], &tot[1]); if (tot[select] == 0) { edge_boundary = true; @@ -1539,7 +1539,7 @@ static void mouse_mesh_loop_edge(BMEditMesh *em, BMEdge *eed, bool select, bool walker_select(em, BMW_EDGEBOUNDARY, eed, select); } else { - walker_select(em, BMW_LOOP, eed, select); + walker_select(em, BMW_EDGELOOP, eed, select); } } -- cgit v1.2.3 From cfe54245a8c37bbd9b5df3ad0d972e59d70d6906 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 15 May 2015 11:29:34 +1000 Subject: Correct recent cleanup Removed call which was still needed --- source/blender/editors/interface/interface_regions.c | 2 +- source/blender/editors/interface/interface_templates.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 4b90abed82b..3f0dac5f872 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1427,7 +1427,7 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, if (down || top) { if (dir1 == UI_DIR_UP && top == 0) dir1 = UI_DIR_DOWN; if (dir1 == UI_DIR_DOWN && down == 0) dir1 = UI_DIR_UP; - /* dir2 is never set to UI_DIR_UP here */ + BLI_assert(dir2 != UI_DIR_UP); // if (dir2 == UI_DIR_UP && top == 0) dir2 = UI_DIR_DOWN; if (dir2 == UI_DIR_DOWN && down == 0) dir2 = UI_DIR_UP; } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 2cab1aea83f..20ce18b2817 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -3214,6 +3214,7 @@ void uiTemplateList( /* add scrollbar */ if (len > layoutdata.visual_items) { + /* col = */ uiLayoutColumn(row, false); uiDefButI(block, UI_BTYPE_SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height, &ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height, dyn_data->visual_height, 0, ""); -- cgit v1.2.3 From 547b676181190fed662cef78615957be10b8b0b1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 15 May 2015 17:07:57 +1000 Subject: BMesh: add loop-shell walker --- source/blender/bmesh/intern/bmesh_walkers.h | 6 + source/blender/bmesh/intern/bmesh_walkers_impl.c | 126 +++++++++++++++++++++ .../blender/bmesh/intern/bmesh_walkers_private.h | 5 + 3 files changed, 137 insertions(+) diff --git a/source/blender/bmesh/intern/bmesh_walkers.h b/source/blender/bmesh/intern/bmesh_walkers.h index 00217dd7a5e..1877611d580 100644 --- a/source/blender/bmesh/intern/bmesh_walkers.h +++ b/source/blender/bmesh/intern/bmesh_walkers.h @@ -93,6 +93,11 @@ void BMW_state_remove(BMWalker *walker); void *BMW_walk(BMWalker *walker); void BMW_reset(BMWalker *walker); +#define BMW_ITER(ele, walker, data) \ + for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMW_begin(walker, (BM_CHECK_TYPE_ELEM(data), data)); \ + ele; \ + BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMW_step(walker)) + /* * example of usage, walking over an island of tool flagged faces: * @@ -109,6 +114,7 @@ void BMW_reset(BMWalker *walker); enum { BMW_VERT_SHELL, + BMW_LOOP_SHELL, BMW_FACE_SHELL, BMW_EDGELOOP, BMW_FACELOOP, diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index 6cdabe61bfb..1fbfbba5c5e 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -223,6 +223,121 @@ static void *bmw_VertShellWalker_step(BMWalker *walker) /** \} */ +/** \name LoopShell Walker + * \{ + * + * Starts at any element on the mesh and walks over the 'shell' it belongs + * to via visiting connected loops. + * + * \note this is mainly useful to loop over a shell delimited by edges. + */ +static void bmw_LoopShellWalker_visitLoop(BMWalker *walker, BMLoop *l) +{ + BMwLoopShellWalker *shellWalk = NULL; + + if (BLI_gset_haskey(walker->visit_set, l)) { + return; + } + + shellWalk = BMW_state_add(walker); + shellWalk->curloop = l; + BLI_gset_insert(walker->visit_set, l); +} + +static void bmw_LoopShellWalker_begin(BMWalker *walker, void *data) +{ + BMIter iter; + BMHeader *h = data; + + if (UNLIKELY(h == NULL)) { + return; + } + + switch (h->htype) { + case BM_LOOP: + { + /* starting the walk at a vert, add all the edges + * to the worklist */ + BMLoop *l = (BMLoop *)h; + bmw_LoopShellWalker_visitLoop(walker, l); + break; + } + + case BM_VERT: + { + BMVert *v = (BMVert *)h; + BMLoop *l; + BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { + bmw_LoopShellWalker_visitLoop(walker, l); + } + break; + } + case BM_EDGE: + { + BMEdge *e = (BMEdge *)h; + BMLoop *l; + BM_ITER_ELEM (l, &iter, e, BM_LOOPS_OF_EDGE) { + bmw_LoopShellWalker_visitLoop(walker, l); + } + break; + } + case BM_FACE: + { + BMFace *f = (BMFace *)h; + BMLoop *l = BM_FACE_FIRST_LOOP(f); + /* walker will handle other loops within the face */ + bmw_LoopShellWalker_visitLoop(walker, l); + break; + } + default: + BLI_assert(0); + } +} + +static void *bmw_LoopShellWalker_yield(BMWalker *walker) +{ + BMwLoopShellWalker *shellWalk = BMW_current_state(walker); + return shellWalk->curloop; +} + +static void *bmw_LoopShellWalker_step(BMWalker *walker) +{ + BMwLoopShellWalker *swalk, owalk; + BMLoop *l; + int i; + BMEdge *e_edj_pair[2]; + + BMW_state_remove_r(walker, &owalk); + swalk = &owalk; + + l = swalk->curloop; + bmw_LoopShellWalker_visitLoop(walker, l->next); + bmw_LoopShellWalker_visitLoop(walker, l->prev); + + e_edj_pair[0] = l->e; + e_edj_pair[1] = l->prev->e; + + for (i = 0; i < 2; i++) { + BMEdge *e = e_edj_pair[i]; + if (bmw_mask_check_edge(walker, e)) { + BMLoop *l_iter, *l_first; + + l_iter = l_first = e->l; + do { + BMLoop *l_radial = (l_iter->v == l->v) ? l_iter : l_iter->next; + BLI_assert(l_radial->v == l->v); + if (l != l_radial) { + bmw_LoopShellWalker_visitLoop(walker, l_radial); + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + } + + return l; +} + +/** \} */ + /** \name FaceShell Walker * \{ @@ -1248,6 +1363,16 @@ static BMWalker bmw_VertShellWalker_Type = { BM_EDGE, /* valid restrict masks */ }; +static BMWalker bmw_LoopShellWalker_Type = { + BM_LOOP | BM_VERT | BM_EDGE, + bmw_LoopShellWalker_begin, + bmw_LoopShellWalker_step, + bmw_LoopShellWalker_yield, + sizeof(BMwLoopShellWalker), + BMW_BREADTH_FIRST, + BM_EDGE, /* valid restrict masks */ +}; + static BMWalker bmw_FaceShellWalker_Type = { BM_EDGE, bmw_FaceShellWalker_begin, @@ -1340,6 +1465,7 @@ static BMWalker bmw_ConnectedVertexWalker_Type = { BMWalker *bm_walker_types[] = { &bmw_VertShellWalker_Type, /* BMW_VERT_SHELL */ + &bmw_LoopShellWalker_Type, /* BMW_LOOP_SHELL */ &bmw_FaceShellWalker_Type, /* BMW_FACE_SHELL */ &bmw_EdgeLoopWalker_Type, /* BMW_EDGELOOP */ &bmw_FaceLoopWalker_Type, /* BMW_FACELOOP */ diff --git a/source/blender/bmesh/intern/bmesh_walkers_private.h b/source/blender/bmesh/intern/bmesh_walkers_private.h index 629f4f09c92..826d2eef1af 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_private.h +++ b/source/blender/bmesh/intern/bmesh_walkers_private.h @@ -45,6 +45,11 @@ typedef struct BMwShellWalker { BMEdge *curedge; } BMwShellWalker; +typedef struct BMwLoopShellWalker { + BMwGenericWalker header; + BMLoop *curloop; +} BMwLoopShellWalker; + typedef struct BMwIslandboundWalker { BMwGenericWalker header; BMLoop *base; -- cgit v1.2.3 From ba9dbaae648ed9d73d8516495829661cb91f77ff Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 15 May 2015 17:08:27 +1000 Subject: Fix T42510: Limit by seams fails in edge/vert mode --- source/blender/editors/mesh/editmesh_select.c | 128 ++++++++++++++++++++------ 1 file changed, 100 insertions(+), 28 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 0a712a218b1..93aad7fdfb7 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2353,7 +2353,6 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm = em->bm; BMIter iter; - BMEdge *e; BMWalker walker; int limit; @@ -2362,63 +2361,136 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) limit = RNA_boolean_get(op->ptr, "limit"); - if (em->selectmode == SCE_SELECT_FACE) { - BMFace *efa; + if (limit) { + BMEdge *e; + /* grr, shouldn't need to alloc BMO flags here */ + BM_mesh_elem_toolflags_ensure(bm); + if (em->selectmode == SCE_SELECT_FACE) { + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + const bool is_walk_ok = ( + BM_elem_flag_test(e, BM_ELEM_SEAM) == 0); - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_elem_flag_set(efa, BM_ELEM_TAG, BM_elem_flag_test(efa, BM_ELEM_SELECT)); + BMO_elem_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok); + } } - - if (limit) { - /* grr, shouldn't need to alloc BMO flags here */ - BM_mesh_elem_toolflags_ensure(bm); + else { + /* don't delimit selected edges in vert/edge mode */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - BMO_elem_flag_set(bm, e, BMO_ELE_TAG, !BM_elem_flag_test(e, BM_ELEM_SEAM)); + const bool is_walk_ok = ( + BM_elem_flag_test(e, BM_ELEM_SEAM) == 0 || + BM_elem_flag_test(e, BM_ELEM_SELECT)); + + BMO_elem_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok); } } + } - BMW_init(&walker, bm, BMW_ISLAND, + if (em->selectmode & SCE_SELECT_VERTEX) { + BMVert *v; + + BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { + BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT)); + } + + BMW_init(&walker, em->bm, limit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, BMW_MASK_NOP, limit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - for (efa = BMW_begin(&walker, efa); efa; efa = BMW_step(&walker)) { - BM_face_select_set(bm, efa, true); - BM_elem_flag_disable(efa, BM_ELEM_TAG); + if (limit) { + BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + BMLoop *l_walk; + BMW_ITER (l_walk, &walker, v) { + BM_vert_select_set(em->bm, l_walk->v, true); + BM_elem_flag_disable(l_walk->v, BM_ELEM_TAG); + } } } } + else { + BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + BMEdge *e_walk; + BMW_ITER (e_walk, &walker, v) { + BM_edge_select_set(em->bm, e_walk, true); + BM_elem_flag_disable(e_walk, BM_ELEM_TAG); + } + } + } + } + BMW_end(&walker); + EDBM_selectmode_flush(em); + } + else if (em->selectmode & SCE_SELECT_EDGE) { + BMEdge *e; + + BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { + BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT)); + } + + BMW_init(&walker, em->bm, limit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, + BMW_MASK_NOP, limit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, + BMW_FLAG_TEST_HIDDEN, + BMW_NIL_LAY); + if (limit) { - BM_mesh_elem_toolflags_clear(bm); + BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + BMLoop *l_walk; + BMW_ITER (l_walk, &walker, e) { + BM_edge_select_set(em->bm, l_walk->e, true); + BM_edge_select_set(em->bm, l_walk->prev->e, true); + BM_elem_flag_disable(l_walk->e, BM_ELEM_TAG); + } + } + } + } + else { + BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + BMEdge *e_walk; + BMW_ITER (e_walk, &walker, e) { + BM_edge_select_set(em->bm, e_walk, true); + BM_elem_flag_disable(e_walk, BM_ELEM_TAG); + } + } + } } + + BMW_end(&walker); + + EDBM_selectmode_flush(em); } else { - BMVert *v; + BMFace *f; - BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { - BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT)); + BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_set(f, BM_ELEM_TAG, BM_elem_flag_test(f, BM_ELEM_SELECT)); } - BMW_init(&walker, em->bm, BMW_VERT_SHELL, - BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP, + BMW_init(&walker, bm, BMW_ISLAND, + BMW_MASK_NOP, limit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(v, BM_ELEM_TAG)) { - for (e = BMW_begin(&walker, v); e; e = BMW_step(&walker)) { - BM_edge_select_set(em->bm, e, true); - BM_elem_flag_disable(e, BM_ELEM_TAG); + BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(f, BM_ELEM_TAG)) { + BMFace *f_walk; + BMW_ITER (f_walk, &walker, f) { + BM_face_select_set(bm, f_walk, true); + BM_elem_flag_disable(f_walk, BM_ELEM_TAG); } } } + BMW_end(&walker); + } - EDBM_selectmode_flush(em); + if (limit) { + BM_mesh_elem_toolflags_clear(bm); } WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit); -- cgit v1.2.3 From 03f9d5a4cf65ddd517b1d6a41528cff69b22cf81 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 May 2015 12:03:08 +0500 Subject: Cycles: Cleanup, move build options string calculation into the device class This way it's easier to access platform name, device ID and other stuff which might be needed to define build options. --- intern/cycles/device/device_opencl.cpp | 72 ++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index d27cf8d13c9..76821e8c021 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -102,37 +102,6 @@ static bool opencl_kernel_use_advanced_shading(const string& platform) return false; } -static string opencl_kernel_build_options(const string& platform, const string *debug_src = NULL) -{ - string build_options = " -cl-fast-relaxed-math "; - - if(platform == "NVIDIA CUDA") - build_options += "-D__KERNEL_OPENCL_NVIDIA__ -cl-nv-maxrregcount=32 -cl-nv-verbose "; - - else if(platform == "Apple") - build_options += "-D__KERNEL_OPENCL_APPLE__ "; - - else if(platform == "AMD Accelerated Parallel Processing") - build_options += "-D__KERNEL_OPENCL_AMD__ "; - - else if(platform == "Intel(R) OpenCL") { - build_options += "-D__KERNEL_OPENCL_INTEL_CPU__ "; - - /* options for gdb source level kernel debugging. this segfaults on linux currently */ - if(opencl_kernel_use_debug() && debug_src) - build_options += "-g -s \"" + *debug_src + "\" "; - } - - if(opencl_kernel_use_debug()) - build_options += "-D__KERNEL_OPENCL_DEBUG__ "; - -#ifdef WITH_CYCLES_DEBUG - build_options += "-D__KERNEL_DEBUG__ "; -#endif - - return build_options; -} - /* thread safe cache for contexts and programs */ class OpenCLCache { @@ -657,7 +626,7 @@ public: const string *debug_src = NULL) { string build_options; - build_options = opencl_kernel_build_options(platform_name, debug_src) + custom_kernel_build_options; + build_options = kernel_build_options(debug_src) + custom_kernel_build_options; ciErr = clBuildProgram(*kernel_program, 0, NULL, build_options.c_str(), NULL, NULL); @@ -731,7 +700,7 @@ public: md5.append((uint8_t*)name, strlen(name)); md5.append((uint8_t*)driver, strlen(driver)); - string options = opencl_kernel_build_options(platform_name); + string options = kernel_build_options(); options += kernel_custom_build_options; md5.append((uint8_t*)options.c_str(), options.size()); @@ -1119,6 +1088,43 @@ public: virtual void thread_run(DeviceTask * /*task*/) = 0; protected: + + string kernel_build_options(const string *debug_src = NULL) + { + string build_options = " -cl-fast-relaxed-math "; + + if(platform_name == "NVIDIA CUDA") { + build_options += "-D__KERNEL_OPENCL_NVIDIA__ " + "-cl-nv-maxrregcount=32 " + "-cl-nv-verbose "; + } + + else if(platform_name == "Apple") + build_options += "-D__KERNEL_OPENCL_APPLE__ "; + + else if(platform_name == "AMD Accelerated Parallel Processing") + build_options += "-D__KERNEL_OPENCL_AMD__ "; + + else if(platform_name == "Intel(R) OpenCL") { + build_options += "-D__KERNEL_OPENCL_INTEL_CPU__ "; + + /* Options for gdb source level kernel debugging. + * this segfaults on linux currently. + */ + if(opencl_kernel_use_debug() && debug_src) + build_options += "-g -s \"" + *debug_src + "\" "; + } + + if(opencl_kernel_use_debug()) + build_options += "-D__KERNEL_OPENCL_DEBUG__ "; + +#ifdef WITH_CYCLES_DEBUG + build_options += "-D__KERNEL_DEBUG__ "; +#endif + + return build_options; + } + class ArgumentWrapper { public: ArgumentWrapper() : size(0), pointer(NULL) {} -- cgit v1.2.3 From 650fbd09f7c3d85719aad89d5a50080a56fc4c49 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 May 2015 12:05:28 +0500 Subject: OpenCL wrangler: Add some of the extension defines --- extern/clew/include/clew.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/extern/clew/include/clew.h b/extern/clew/include/clew.h index 328fd52857a..1b72f813c9f 100644 --- a/extern/clew/include/clew.h +++ b/extern/clew/include/clew.h @@ -2751,6 +2751,30 @@ CLEW_FUN_EXPORT PFNCLGETGLCONTEXTINFOKHR __clewGetGLContextInfoKH #endif #define clGetGLContextInfoKHR CLEW_GET_FUN(__clewGetGLContextInfoKHR ) +/* cl_ext */ + +/****************************************** + * cl_nv_device_attribute_query extension * + ******************************************/ +/* cl_nv_device_attribute_query extension - no extension #define since it has no functions */ +#define CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV 0x4000 +#define CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV 0x4001 +#define CL_DEVICE_REGISTERS_PER_BLOCK_NV 0x4002 +#define CL_DEVICE_WARP_SIZE_NV 0x4003 +#define CL_DEVICE_GPU_OVERLAP_NV 0x4004 +#define CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV 0x4005 +#define CL_DEVICE_INTEGRATED_MEMORY_NV 0x4006 + +/********************************* + * cl_amd_device_attribute_query * + *********************************/ +#define CL_DEVICE_PROFILING_TIMER_OFFSET_AMD 0x4036 + +/********************************* + * cl_arm_printf extension + *********************************/ +#define CL_PRINTF_CALLBACK_ARM 0x40B0 +#define CL_PRINTF_BUFFERSIZE_ARM 0x40B1 #define CLEW_SUCCESS 0 //!< Success error code #define CLEW_ERROR_OPEN_FAILED -1 //!< Error code for failing to open the dynamic library -- cgit v1.2.3 From 960d7df56f11cd8161bc7ba4478d5c6988c8232f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 May 2015 12:12:10 +0500 Subject: Cycles: Pass device compute capabilities to kernel via build options This way it's possible to do device-selective feature disabling/enabling. Currently only supported for NVidia devices via OpenCL extension. --- intern/cycles/device/device_opencl.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 76821e8c021..05c8530a7a7 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -1097,6 +1097,16 @@ protected: build_options += "-D__KERNEL_OPENCL_NVIDIA__ " "-cl-nv-maxrregcount=32 " "-cl-nv-verbose "; + + uint compute_capability_major, compute_capability_minor; + clGetDeviceInfo(cdDevice, CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV, + sizeof(cl_uint), &compute_capability_major, NULL); + clGetDeviceInfo(cdDevice, CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV, + sizeof(cl_uint), &compute_capability_minor, NULL); + + build_options += string_printf("-D__COMPUTE_CAPABILITY__=%d ", + compute_capability_major * 100 + + compute_capability_minor * 10); } else if(platform_name == "Apple") -- cgit v1.2.3 From c9e8888f877c7c4332d4d1a1dbb372a3e0b7f28a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 May 2015 12:30:04 +0500 Subject: Cycles: Disable bake OpenCL kernel for NVidia devices prior to sm_30 Driver fails to compile kernel in reasonable time for those devices here, so for easier testing of the OpenCL split kernel work disabling bake kernel for now. --- intern/cycles/kernel/kernel.cl | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/intern/cycles/kernel/kernel.cl b/intern/cycles/kernel/kernel.cl index 19e394936ee..cbc0592fe1f 100644 --- a/intern/cycles/kernel/kernel.cl +++ b/intern/cycles/kernel/kernel.cl @@ -102,8 +102,19 @@ __kernel void kernel_ocl_bake( int x = sx + get_global_id(0); - if(x < sx + sw) + if(x < sx + sw) { +#if defined(__KERNEL_OPENCL_NVIDIA__) && __COMPUTE_CAPABILITY__ < 300 + /* NVidia compiler is spending infinite amount of time trying + * to deal with kernel_bake_evaluate() on architectures prior + * to sm_30. + * For now we disable baking kernel for those devices, so at + * least rendering with split kernel could be compiled. + */ + output[x] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); +#else kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, x, offset, sample); +#endif + } } __kernel void kernel_ocl_convert_to_byte( -- cgit v1.2.3 From 2ab909a88c3e6503bb2505cf2ac573f1f3363faa Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 May 2015 12:45:41 +0500 Subject: Cycles: Make experimental kernel build option more generic Previously it was explicitly mentioning it's NVidia kernel related option, but in fact it's also handy for the OpenCL kernel. --- intern/cycles/device/device_cuda.cpp | 2 +- intern/cycles/kernel/CMakeLists.txt | 2 +- intern/cycles/kernel/SConscript | 2 +- intern/cycles/kernel/geom/geom_triangle_intersect.h | 2 +- intern/cycles/kernel/kernel_types.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 4b325947f0f..f050153d914 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -281,7 +281,7 @@ public: nvcc, major, minor, machine, kernel.c_str(), cubin.c_str(), include.c_str(), cuda_version); if(experimental) - command += " -D__KERNEL_CUDA_EXPERIMENTAL__"; + command += " -D__KERNEL_EXPERIMENTAL__"; if(getenv("CYCLES_CUDA_EXTRA_CFLAGS")) { command += string(" ") + getenv("CYCLES_CUDA_EXTRA_CFLAGS"); diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 85b2760073b..13eb5ca1e71 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -191,7 +191,7 @@ if(WITH_CYCLES_CUDA_BINARIES) macro(CYCLES_CUDA_KERNEL_ADD arch experimental) if(${experimental}) - set(cuda_extra_flags "-D__KERNEL_CUDA_EXPERIMENTAL__") + set(cuda_extra_flags "-D__KERNEL_EXPERIMENTAL__") set(cuda_cubin kernel_experimental_${arch}.cubin) else() set(cuda_extra_flags "") diff --git a/intern/cycles/kernel/SConscript b/intern/cycles/kernel/SConscript index c0d969e24ae..24cc4517eaf 100644 --- a/intern/cycles/kernel/SConscript +++ b/intern/cycles/kernel/SConscript @@ -87,7 +87,7 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']: last_cubin_file = None configs = (("kernel_%s.cubin", ''), - ("kernel_experimental_%s.cubin", ' -D__KERNEL_CUDA_EXPERIMENTAL__')) + ("kernel_experimental_%s.cubin", ' -D__KERNEL_EXPERIMENTAL__')) # add command for each cuda architecture for arch in cuda_archs: diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index 0ea30eb7f13..220169f56d3 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -50,7 +50,7 @@ typedef struct IsectPrecalc { } IsectPrecalc; /* Workaround for CUDA toolkit 6.5.16. */ -#if defined(__KERNEL_CPU__) || !defined(__KERNEL_CUDA_EXPERIMENTAL__) || __CUDA_ARCH__ < 500 +#if defined(__KERNEL_CPU__) || !defined(__KERNEL_EXPERIMENTAL__) || __CUDA_ARCH__ < 500 # if (defined(i386) || defined(_M_IX86)) ccl_device_noinline # else diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 8f91937ac33..72173b72df8 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -84,7 +84,7 @@ CCL_NAMESPACE_BEGIN #define __VOLUME_SCATTER__ /* Experimental on GPU */ -#ifdef __KERNEL_CUDA_EXPERIMENTAL__ +#ifdef __KERNEL_EXPERIMENTAL__ #define __SUBSURFACE__ #define __CMJ__ #endif -- cgit v1.2.3 From c2b9f784153f20b75444632ef3b57aa3b1597f31 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 May 2015 12:49:25 +0500 Subject: Cycles: Pass __KERNEL_EXPERIMENTAL__ to OpenCL split kernels Experimental feature set id currently unavailable for megakernel, it'll require some changes to the cache system to distinguish cached regular kernels from cached experimental kernels. Currently unused, but some features will be enabled soon. --- intern/cycles/device/device_opencl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 05c8530a7a7..75d08cb44b1 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -2000,6 +2000,9 @@ public: #ifdef __WORK_STEALING__ common_custom_build_options += "-D__WORK_STEALING__ "; #endif + if(requested_features.experimental) { + common_custom_build_options += "-D__KERNEL_EXPERIMENTAL__ "; + } #define LOAD_KERNEL(program, name) \ do { \ -- cgit v1.2.3 From c86a6f3efbffbf81b663eb1fb57b4736d8e906ee Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 May 2015 12:53:50 +0500 Subject: Cycles: Enable CMJ for Intel/NVidia experimental split kernels It is still disabled for AMD devices since can't test if it works fine on this hardware. --- intern/cycles/kernel/kernel_types.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 72173b72df8..769ffa87e4e 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -112,6 +112,9 @@ CCL_NAMESPACE_BEGIN # define __HAIR__ # define __CAMERA_MOTION__ # endif +# ifdef __KERNEL_EXPERIMENTAL__ +# define __CMJ__ +# endif #endif #ifdef __KERNEL_OPENCL_APPLE__ @@ -136,9 +139,12 @@ CCL_NAMESPACE_BEGIN #endif #ifdef __KERNEL_OPENCL_INTEL_CPU__ -#define __CL_USE_NATIVE__ -#define __KERNEL_SHADING__ -#define __KERNEL_ADV_SHADING__ +# define __CL_USE_NATIVE__ +# define __KERNEL_SHADING__ +# define __KERNEL_ADV_SHADING__ +# ifdef __KERNEL_EXPERIMENTAL__ +# define __CMJ__ +# endif #endif #endif // __KERNEL_OPENCL__ -- cgit v1.2.3 From e4c93dc7db9b50acf898b667c95b208856b80ea8 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 13 May 2015 20:30:53 +0200 Subject: Zoom to frame options, requested by the Hwoozeberry (dutch translation) team. There are 3 options here: 1) Keep range (previous behaviour) 2) Seconds - allows a specified offset in seconds around current frame 3) keyframes - zoom to include a number of keyframes around the cursor Options 2 and 3 have their own properties to tweak the behaviour and all options can be found in User Preferences->Interface under the 2D viewports section. Number 3 will probably need some refinement so commiting here for the hwoozeberry team to test first. --- release/scripts/startup/bl_ui/space_userpref.py | 5 + source/blender/editors/animation/anim_draw.c | 140 ++++++++++++++++++++++ source/blender/editors/include/ED_anim_api.h | 1 + source/blender/editors/include/UI_view2d.h | 1 - source/blender/editors/interface/view2d_ops.c | 15 --- source/blender/editors/space_action/action_edit.c | 2 +- source/blender/editors/space_graph/graph_edit.c | 2 +- source/blender/makesdna/DNA_userdef_types.h | 12 +- source/blender/makesrna/intern/rna_userdef.c | 27 ++++- 9 files changed, 184 insertions(+), 21 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 3b17e40c294..9b3a2b50121 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -200,6 +200,11 @@ class USERPREF_PT_interface(Panel): col.label(text="2D Viewports:") col.prop(view, "view2d_grid_spacing_min", text="Minimum Grid Spacing") col.prop(view, "timecode_style") + col.prop(view, "view_frame_type") + if (view.view_frame_type == 'SECONDS'): + col.prop(view, "view_frame_seconds") + elif (view.view_frame_type == 'KEYFRAMES'): + col.prop(view, "view_frame_keyframes") row.separator() row.separator() diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 54d371d8f50..7d669e8c93e 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -34,17 +34,25 @@ #include "DNA_scene_types.h" #include "DNA_space_types.h" #include "DNA_userdef_types.h" +#include "DNA_screen_types.h" +#include "DNA_object_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_mask_types.h" #include "BLI_math.h" #include "BLI_timecode.h" #include "BLI_utildefines.h" +#include "BLI_rect.h" +#include "BLI_dlrbTree.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_nla.h" +#include "BKE_mask.h" #include "ED_anim_api.h" #include "ED_keyframes_edit.h" +#include "ED_keyframes_draw.h" #include "RNA_access.h" @@ -381,4 +389,136 @@ float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag return 1.0f; } +static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prevfra) { + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_active_object(C); + bGPdata *gpd = CTX_data_gpencil_data(C); + Mask *mask = CTX_data_edit_mask(C); + bDopeSheet ads = {NULL}; + DLRBT_Tree keys; + ActKeyColumn *aknext, *akprev; + float cfranext, cfraprev; + bool donenext = false, doneprev = false; + int nextcount = 0, prevcount = 0; + + cfranext = cfraprev = (float)(CFRA); + + /* init binarytree-list for getting keyframes */ + BLI_dlrbTree_init(&keys); + + /* seed up dummy dopesheet context with flags to perform necessary filtering */ + if ((scene->flag & SCE_KEYS_NO_SELONLY) == 0) { + /* only selected channels are included */ + ads.filterflag |= ADS_FILTER_ONLYSEL; + } + + /* populate tree with keyframe nodes */ + scene_to_keylist(&ads, scene, &keys, NULL); + + if (ob) + ob_to_keylist(&ads, ob, &keys, NULL); + + gpencil_to_keylist(&ads, gpd, &keys); + + if (mask) { + MaskLayer *masklay = BKE_mask_layer_active(mask); + mask_to_keylist(&ads, masklay, &keys); + } + + /* build linked-list for searching */ + BLI_dlrbTree_linkedlist_sync(&keys); + + /* find matching keyframe in the right direction */ + do { + aknext = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfranext); + + if (aknext) { + if (CFRA == (int)aknext->cfra) { + /* make this the new starting point for the search and ignore */ + cfranext = aknext->cfra; + } + else { + /* this changes the frame, so set the frame and we're done */ + if (++nextcount == U.view_frame_keyframes) + donenext = true; + } + cfranext = aknext->cfra; + } + } while ((aknext != NULL) && (donenext == false)); + + do { + akprev = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfraprev); + + if (akprev) { + if (CFRA == (int)akprev->cfra) { + /* make this the new starting point for the search */ + } + else { + /* this changes the frame, so set the frame and we're done */ + if (++prevcount == U.view_frame_keyframes) + doneprev = true; + } + cfraprev = akprev->cfra; + } + } while ((akprev != NULL) && (doneprev == false)); + + /* free temp stuff */ + BLI_dlrbTree_free(&keys); + + /* any success? */ + if (doneprev || donenext) { + if (doneprev) + *prevfra = cfraprev; + else + *prevfra = CFRA - (cfranext - CFRA); + + if (donenext) + *nextfra = cfranext; + else + *nextfra = CFRA + (CFRA - cfraprev); + + return true; + } + + return false; +} + +void ANIM_center_frame(struct bContext *C, int smooth_viewtx) +{ + ARegion *ar = CTX_wm_region(C); + Scene *scene = CTX_data_scene(C); + float w = BLI_rctf_size_x(&ar->v2d.cur); + rctf newrct; + int nextfra, prevfra; + + switch (U.view_frame_type) { + case ZOOM_FRAME_MODE_SECONDS: + newrct.xmax = scene->r.cfra + U.view_frame_seconds * FPS + 1; + newrct.xmin = scene->r.cfra - U.view_frame_seconds * FPS - 1; + newrct.ymax = ar->v2d.cur.ymax; + newrct.ymin = ar->v2d.cur.ymin; + break; + + /* hardest case of all, look for all keyframes around frame and display those */ + case ZOOM_FRAME_MODE_KEYFRAMES: + if (find_prev_next_keyframes(C, &nextfra, &prevfra)) { + newrct.xmax = nextfra; + newrct.xmin = prevfra; + newrct.ymax = ar->v2d.cur.ymax; + newrct.ymin = ar->v2d.cur.ymin; + break; + } + /* else drop through, keep range instead */ + + case ZOOM_FRAME_MODE_KEEP_RANGE: + default: + newrct.xmax = scene->r.cfra + (w / 2); + newrct.xmin = scene->r.cfra - (w / 2); + newrct.ymax = ar->v2d.cur.ymax; + newrct.ymin = ar->v2d.cur.ymin; + break; + } + + UI_view2d_smooth_view(C, ar, &newrct, smooth_viewtx); +} /* *************************************************** */ diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 73f28986375..0f70bf3c745 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -659,6 +659,7 @@ void ANIM_list_elem_update(struct Scene *scene, bAnimListElem *ale); /* data -> channels syncing */ void ANIM_sync_animchannels_to_data(const struct bContext *C); +void ANIM_center_frame(struct bContext *C, int smooth_viewtx); /* ************************************************* */ /* OPERATORS */ diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 430093b641b..2c8f5f6590a 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -233,7 +233,6 @@ void ED_keymap_view2d(struct wmKeyConfig *keyconf); void UI_view2d_smooth_view(struct bContext *C, struct ARegion *ar, const struct rctf *cur, const int smooth_viewtx); -void UI_view2d_center_frame(struct bContext *C, int smooth_viewtx); #define UI_MARKER_MARGIN_Y (42 * UI_DPI_FAC) #endif /* __UI_VIEW2D_H__ */ diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 9fed02ee096..eafc5c1d24c 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -1468,21 +1468,6 @@ void UI_view2d_smooth_view( } } -void UI_view2d_center_frame(struct bContext *C, int smooth_viewtx) -{ - ARegion *ar = CTX_wm_region(C); - Scene *scene = CTX_data_scene(C); - float w = BLI_rctf_size_x(&ar->v2d.cur); - rctf newrct; - - newrct.xmax = scene->r.cfra + (w / 2); - newrct.xmin = scene->r.cfra - (w / 2); - newrct.ymax = ar->v2d.cur.ymax; - newrct.ymin = ar->v2d.cur.ymin; - - UI_view2d_smooth_view(C, ar, &newrct, smooth_viewtx); -} - /* only meant for timer usage */ static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index debe3cb9730..90c38426164 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -429,7 +429,7 @@ static int actkeys_viewsel_exec(bContext *C, wmOperator *UNUSED(op)) static int actkeys_view_frame_exec(bContext *C, wmOperator *op) { const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - UI_view2d_center_frame(C, smooth_viewtx); + ANIM_center_frame(C, smooth_viewtx); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index d450335d16a..a8cb4ce56ea 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -261,7 +261,7 @@ static int graphkeys_view_selected_exec(bContext *C, wmOperator *op) static int graphkeys_view_frame_exec(bContext *C, wmOperator *op) { const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - UI_view2d_center_frame(C, smooth_viewtx); + ANIM_center_frame(C, smooth_viewtx); return OPERATOR_FINISHED; } diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index e0b51a1b25b..af0c3bfbf0e 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -503,7 +503,10 @@ typedef struct UserDef { char ipo_new; /* interpolation mode for newly added F-Curves */ char keyhandles_new; /* handle types for newly added keyframes */ char gpu_select_method; - char pad1; + char view_frame_type; + + int view_frame_keyframes; /* number of keyframes to zoom around current frame */ + float view_frame_seconds; /* seconds to zoom around current frame */ short scrcastfps; /* frame rate for screencast to be played back */ short scrcastwait; /* milliseconds between screencast snapshots */ @@ -686,6 +689,13 @@ typedef enum eAutokey_Mode { AUTOKEY_MODE_EDITKEYS = 5 } eAutokey_Mode; +/* Zoom to frame mode */ +typedef enum eZoomFrame_Mode { + ZOOM_FRAME_MODE_KEEP_RANGE = 0, + ZOOM_FRAME_MODE_SECONDS = 1, + ZOOM_FRAME_MODE_KEYFRAMES = 2 +} eZoomFrame_Mode; + /* Auto-Keying flag * U.autokey_flag (not strictly used when autokeying only - is also used when keyframing these days) * note: AUTOKEY_FLAG_* is used with a macro, search for lines like IS_AUTOKEY_FLAG(INSERTAVAIL) diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index a441f2f57dc..82afcfdbf29 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3263,7 +3263,14 @@ static void rna_def_userdef_view(BlenderRNA *brna) "Direct conversion of frame numbers to seconds"}, {0, NULL, 0, NULL, NULL} }; - + + static EnumPropertyItem zoom_frame_modes[] = { + {ZOOM_FRAME_MODE_KEEP_RANGE, "KEEP_RANGE", 0, "Keep Range", ""}, + {ZOOM_FRAME_MODE_SECONDS, "SECONDS", 0, "Seconds", ""}, + {ZOOM_FRAME_MODE_KEYFRAMES, "KEYFRAMES", 0, "Keyframes", ""}, + {0, NULL, 0, NULL, NULL} + }; + PropertyRNA *prop; StructRNA *srna; @@ -3505,6 +3512,22 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_ui_text(prop, "TimeCode Style", "Format of Time Codes displayed when not displaying timing in terms of frames"); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "view_frame_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, zoom_frame_modes); + RNA_def_property_enum_sdna(prop, NULL, "view_frame_type"); + RNA_def_property_ui_text(prop, "Zoom To Frame Type", "How zooming to frame focuses around current frame"); + + prop = RNA_def_property(srna, "view_frame_keyframes", PROP_INT, PROP_NONE); + RNA_def_property_range(prop, 1, 500); + RNA_def_property_ui_text(prop, "Zoom Keyframes", + "Keyframes around cursor that we zoom around"); + + prop = RNA_def_property(srna, "view_frame_seconds", PROP_FLOAT, PROP_TIME); + RNA_def_property_range(prop, 0.0, 10000.0); + RNA_def_property_ui_text(prop, "Zoom Seconds", + "Seconds around cursor that we zoom around"); + } static void rna_def_userdef_edit(BlenderRNA *brna) @@ -3625,7 +3648,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_ui_text(prop, "New Interpolation Type", "Interpolation mode used for first keyframe on newly added F-Curves " "(subsequent keyframes take interpolation from preceding keyframe)"); - + prop = RNA_def_property(srna, "keyframe_new_handle_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, keyframe_handle_type_items); RNA_def_property_enum_sdna(prop, NULL, "keyhandles_new"); -- cgit v1.2.3 From 7c06190882a1fa985d6e6998daa2db1f7577aed4 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Fri, 15 May 2015 13:49:17 +0200 Subject: Cycles: Make animated seed a builtin feature. For animations, you often want an animated render seed (noise pattern). This could be done by e.g. setting a driver on the seed value. Now it's a little checkbox, that can be enabled. The animated seed is based on the current Blender frame and the seed value itself. Simply enabling it, will already result in an animated seed (different on each Blender frame), but it can be randomized further by setting a different seed value. Disabled per default, so no backward compatibility break. Differential Revision: https://developer.blender.org/D1285 --- intern/cycles/blender/addon/properties.py | 6 ++++++ intern/cycles/blender/addon/ui.py | 6 +++++- intern/cycles/blender/blender_sync.cpp | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 538876a71e2..16a807b3af5 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -394,6 +394,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): default=0, ) + cls.use_animated_seed = BoolProperty( + name="Use Animated Seed", + description="Use different seed values (and hence noise patterns) at different frames", + default=False, + ) + cls.sample_clamp_direct = FloatProperty( name="Clamp Direct", description="If non-zero, the maximum value for a direct sample, " diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index d24099b92a5..545d0b6c26c 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -135,7 +135,11 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel): col = split.column() sub = col.column(align=True) sub.label("Settings:") - sub.prop(cscene, "seed") + + seed_sub = sub.row(align=True) + seed_sub.prop(cscene, "seed") + seed_sub.prop(cscene, "use_animated_seed", text="", icon="TIME") + sub.prop(cscene, "sample_clamp_direct") sub.prop(cscene, "sample_clamp_indirect") diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 266e170fa8f..c5fb7925306 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -36,6 +36,7 @@ #include "util_debug.h" #include "util_foreach.h" #include "util_opengl.h" +#include "util_hash.h" CCL_NAMESPACE_BEGIN @@ -195,6 +196,9 @@ void BlenderSync::sync_integrator() integrator->filter_glossy = get_float(cscene, "blur_glossy"); integrator->seed = get_int(cscene, "seed"); + if(get_boolean(cscene, "use_animated_seed")) + integrator->seed = hash_int_2d(b_scene.frame_current(), get_int(cscene, "seed")); + integrator->sampling_pattern = (SamplingPattern)RNA_enum_get(&cscene, "sampling_pattern"); integrator->layer_flag = render_layer.layer; -- cgit v1.2.3 From 2fa4a48bcef05671890fafc3fe50a8fa619f0259 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Fri, 15 May 2015 14:50:46 +0200 Subject: BGE: Fix T44700 mesh without material in blenderplayer. If a mesh doesn't have a material we don't initialize the mSavedData in KX_BlenderMaterial to avoid crash. --- source/gameengine/Ketsji/KX_BlenderMaterial.cpp | 93 +++++++++++++++---------- 1 file changed, 57 insertions(+), 36 deletions(-) diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 7ec2673bf1f..8e534ee1821 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -96,18 +96,20 @@ void KX_BlenderMaterial::Initialize( ); Material *ma = data->material; - // Save material data to restore on exit - mSavedData.r = ma->r; - mSavedData.g = ma->g; - mSavedData.b = ma->b; - mSavedData.a = ma->alpha; - mSavedData.specr = ma->specr; - mSavedData.specg = ma->specg; - mSavedData.specb = ma->specb; - mSavedData.spec = ma->spec; - mSavedData.ref = ma->ref; - mSavedData.hardness = ma->har; - mSavedData.emit = ma->emit; + if (ma) { + // Save material data to restore on exit + mSavedData.r = ma->r; + mSavedData.g = ma->g; + mSavedData.b = ma->b; + mSavedData.a = ma->alpha; + mSavedData.specr = ma->specr; + mSavedData.specg = ma->specg; + mSavedData.specb = ma->specb; + mSavedData.spec = ma->spec; + mSavedData.ref = ma->ref; + mSavedData.hardness = ma->har; + mSavedData.emit = ma->emit; + } mMaterial = data; mShader = 0; @@ -140,18 +142,21 @@ void KX_BlenderMaterial::Initialize( KX_BlenderMaterial::~KX_BlenderMaterial() { Material *ma = mMaterial->material; - // Restore Blender material data - ma->r = mSavedData.r; - ma->g = mSavedData.g; - ma->b = mSavedData.b; - ma->alpha = mSavedData.a; - ma->specr = mSavedData.specr; - ma->specg = mSavedData.specg; - ma->specb = mSavedData.specb; - ma->spec = mSavedData.spec; - ma->ref = mSavedData.ref; - ma->har = mSavedData.hardness; - ma->emit = mSavedData.emit; + + if (ma) { + // Restore Blender material data + ma->r = mSavedData.r; + ma->g = mSavedData.g; + ma->b = mSavedData.b; + ma->alpha = mSavedData.a; + ma->specr = mSavedData.specr; + ma->specg = mSavedData.specg; + ma->specb = mSavedData.specb; + ma->spec = mSavedData.spec; + ma->ref = mSavedData.ref; + ma->har = mSavedData.hardness; + ma->emit = mSavedData.emit; + } // cleanup work if (mConstructed) @@ -823,18 +828,34 @@ void KX_BlenderMaterial::UpdateIPO( { // only works one deep now - // GLSL Multitexture Input - mMaterial->material->specr = mMaterial->speccolor[0] = (float)(specrgb)[0]; - mMaterial->material->specg = mMaterial->speccolor[1] = (float)(specrgb)[1]; - mMaterial->material->specb = mMaterial->speccolor[2] = (float)(specrgb)[2]; - mMaterial->material->r = mMaterial->matcolor[0] = (float)(rgba[0]); - mMaterial->material->g = mMaterial->matcolor[1] = (float)(rgba[1]); - mMaterial->material->b = mMaterial->matcolor[2] = (float)(rgba[2]); - mMaterial->material->alpha = mMaterial->alpha = (float)(rgba[3]); - mMaterial->material->har = mMaterial->hard = (float)(hard); - mMaterial->material->emit = mMaterial->emit = (float)(emit); - mMaterial->material->spec = mMaterial->spec_f = (float)(spec); - mMaterial->material->ref = mMaterial->ref = (float)(ref); + // Multitexture Input + mMaterial->speccolor[0] = (float)(specrgb)[0]; + mMaterial->speccolor[1] = (float)(specrgb)[1]; + mMaterial->speccolor[2] = (float)(specrgb)[2]; + mMaterial->matcolor[0] = (float)(rgba[0]); + mMaterial->matcolor[1] = (float)(rgba[1]); + mMaterial->matcolor[2] = (float)(rgba[2]); + mMaterial->alpha = (float)(rgba[3]); + mMaterial->hard = (float)(hard); + mMaterial->emit = (float)(emit); + mMaterial->spec_f = (float)(spec); + mMaterial->ref = (float)(ref); + + Material *ma = mMaterial->material; + if (ma) { + // GLSL Input + ma->specr = (float)(specrgb)[0]; + ma->specg = (float)(specrgb)[1]; + ma->specb = (float)(specrgb)[2]; + ma->r = (float)(rgba[0]); + ma->g = (float)(rgba[1]); + ma->b = (float)(rgba[2]); + ma->alpha = (float)(rgba[3]); + ma->har = (float)(hard); + ma->emit = (float)(emit); + ma->spec = (float)(spec); + ma->ref = (float)(ref); + } } void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val) -- cgit v1.2.3 From 31e96cbf96a2bd26b77a29bf4cd8475a53521539 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 15 May 2015 23:38:53 +1000 Subject: Cleanup: style, spelling --- intern/cycles/device/device_opencl.cpp | 8 ++++---- intern/cycles/kernel/kernel_types.h | 2 +- source/blender/blenkernel/intern/pbvh_bmesh.c | 4 ++-- source/blender/blenkernel/intern/subsurf_ccg.c | 2 +- source/blender/bmesh/intern/bmesh_core.c | 2 +- source/blender/depsgraph/intern/depsnode.h | 2 +- source/blender/editors/animation/anim_draw.c | 3 ++- source/blender/editors/space_node/node_draw.c | 2 +- 8 files changed, 13 insertions(+), 12 deletions(-) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 75d08cb44b1..f77b567a093 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -1104,7 +1104,7 @@ protected: clGetDeviceInfo(cdDevice, CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV, sizeof(cl_uint), &compute_capability_minor, NULL); - build_options += string_printf("-D__COMPUTE_CAPABILITY__=%d ", + build_options += string_printf("-D__COMPUTE_CAPABILITY__=%u ", compute_capability_major * 100 + compute_capability_minor * 10); } @@ -1449,7 +1449,7 @@ public: }; /* TODO(sergey): This is to keep tile split on OpenCL level working - * for now, since withotu this viewport render does not work as it + * for now, since without this view-port render does not work as it * should. * * Ideally it'll be done on the higher level, but we need to get ready @@ -1489,7 +1489,7 @@ public: buffers = tile.buffers; } - /* Split kernel is device global memory constained; + /* Split kernel is device global memory constrained; * hence split kernel cant render big tile size's in * one go. If the user sets a big tile size (big tile size * is a term relative to the available device global memory), @@ -1536,7 +1536,7 @@ public: /* Global memory variables [porting]; These memory is used for * co-operation between different kernels; Data written by one - * kernel will be avaible to another kernel via this global + * kernel will be available to another kernel via this global * memory. */ cl_mem rng_coop; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 769ffa87e4e..294a491c532 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -467,7 +467,7 @@ typedef struct differential { typedef struct Ray { /* TODO(sergey): This is only needed because current AMD - * compilet has hard time bulding the kernel with this + * compiler has hard time building the kernel with this * reshuffle. And at the same time reshuffle will cause * less optimal CPU code in certain places. * diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index a6e0ca31cf7..e631a4a365d 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -1510,8 +1510,8 @@ static void pbvh_bmesh_node_limit_ensure_fast(PBVH *bvh, BMFace **nodeinfo, BBC num_child2--; } - /* at this point, faces should have been split along the array range sequencially, each sequencial - * part belonging to one node only */ + /* at this point, faces should have been split along the array range sequentially, + * each sequential part belonging to one node only */ BLI_assert((num_child1 + num_child2) == node->totface); node->child1 = child1 = BLI_memarena_alloc(arena, sizeof(FastNodeBuildInfo)); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 68ef1565bd4..e4d178d0b5f 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -300,7 +300,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */ limit[0] = limit[1] = STD_UV_CONNECT_LIMIT; - /* previous behaviour here is without accounting for winding, however this causes stretching in + /* previous behavior here is without accounting for winding, however this causes stretching in * UV map in really simple cases with mirror + subsurf, see second part of T44530. Also, initially * intention is to treat merged vertices from mirror modifier as seams, see code below with ME_VERT_MERGED * This fixes a very old regression (2.49 was correct here) */ diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 2a69edd47b0..ee2ade51108 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -2633,7 +2633,7 @@ static void bmesh_edge_vert_swap__recursive(BMEdge *e, BMVert *v_dst, BMVert *v_ /** * This function assumes l_sep is apart of a larger fan which has already been - * isolated by calling bmesh_edge_separate to segragate it radially. + * isolated by calling bmesh_edge_separate to segregate it radially. */ BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep) { diff --git a/source/blender/depsgraph/intern/depsnode.h b/source/blender/depsgraph/intern/depsnode.h index 84554aef7ea..4f3dc3b7303 100644 --- a/source/blender/depsgraph/intern/depsnode.h +++ b/source/blender/depsgraph/intern/depsnode.h @@ -195,7 +195,7 @@ struct IDDepsNode : public DepsNode { int layers; /* Additional flags needed for scene evaluation. - * TODO(sergey): Only needed for until really granual updates + * TODO(sergey): Only needed for until really granular updates * of all the entities. */ int eval_flags; diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 7d669e8c93e..d5945425576 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -389,7 +389,8 @@ float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag return 1.0f; } -static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prevfra) { +static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prevfra) +{ Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); bGPdata *gpd = CTX_data_gpencil_data(C); diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index c89bf8dd13a..34efba00b86 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -125,7 +125,7 @@ void ED_node_tag_update_id(ID *id) return; /* TODO(sergey): With the new dependency graph it - * should be just enough to ony tag ntree itself, + * should be just enough to only tag ntree itself, * all the users of this tree will have update * flushed from the tree, */ -- cgit v1.2.3 From f4e8e70b5d77c9a6430f64bc223ab0a04b38f815 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 15 May 2015 16:00:36 +0200 Subject: Add really simple memory reduction scheme for internal animation player. Holds 30 frames in memory. Could make it check memory instead but that should suffice for now to make sure blender does not crash on me with movie files. Previously the system would load eveything in memory so something like playing caminandes in player would swap after 30 seconds in local computer. --- source/blender/windowmanager/intern/wm_playanim.c | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 061357c3906..66c502cba53 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -222,6 +222,9 @@ typedef struct PlayAnimPict { } PlayAnimPict; static struct ListBase picsbase = {NULL, NULL}; +/* frames in memory - store them here to for easy deallocation later */ +static struct ListBase inmempicsbase = {NULL, NULL}; +static int added_images = 0; static bool fromdisk = false; static double ptottime = 0.0, swaptime = 0.04; @@ -1130,10 +1133,33 @@ static char *wm_main_playanim_intern(int argc, const char **argv) } if (ibuf) { + LinkData *node; #ifdef USE_IMB_CACHE ps.picture->ibuf = ibuf; #endif + /* really basic memory conservation scheme. Keep frames in a fifo queue */ + node = inmempicsbase.last; + + while (added_images > 30) { + PlayAnimPict *pic = (PlayAnimPict *)node->data; + + if (pic->ibuf != ibuf) { + LinkData *node_tmp; + IMB_freeImBuf(pic->ibuf); + pic->ibuf = NULL; + node_tmp = node->prev; + BLI_freelinkN(&inmempicsbase, node); + added_images--; + node = node_tmp; + } + else { + node = node->prev; + } + } + + BLI_addhead(&inmempicsbase, BLI_genericNodeN(ps.picture)); + added_images++; BLI_strncpy(ibuf->name, ps.picture->name, sizeof(ibuf->name)); -- cgit v1.2.3 From 371e5f25a054759014efa27c6fe4d497854ed64e Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Fri, 15 May 2015 16:17:18 +0200 Subject: BGE: Cleanup : merge 3 loop in 1 in function DupliGroupRecurse. --- source/gameengine/Ketsji/KX_Scene.cpp | 39 ++++++++++++++--------------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index a460d9bd392..674f1e3c1b3 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -823,38 +823,29 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // the logic must be replicated first because we need // the new logic bricks before relinking vector::iterator git; - for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) - { - (*git)->ReParentLogic(); - } - - // relink any pointers as necessary, sort of a temporary solution - for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) - { + for (git = m_logicHierarchicalGameObjects.begin(); git != m_logicHierarchicalGameObjects.end()); ++git) { + KX_GameObject *gameobj = *git; + gameobj->ReParentLogic(); + + // relink any pointers as necessary, sort of a temporary solution // this will also relink the actuator to objects within the hierarchy - (*git)->Relink(&m_map_gameobject_to_replica); + gameobj->Relink(&m_map_gameobject_to_replica); // add the object in the layer of the parent - (*git)->SetLayer(groupobj->GetLayer()); - } + gameobj->SetLayer(groupobj->GetLayer()); - // replicate crosslinks etc. between logic bricks - for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) - { - ReplicateLogic((*git)); - } + // replicate crosslinks etc. between logic bricks + ReplicateLogic(gameobj); - // now look if object in the hierarchy have dupli group and recurse - for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) - { + // now look if object in the hierarchy have dupli group and recurse /* Replicate all constraints. */ - if ((*git)->GetPhysicsController()) { - (*git)->GetPhysicsController()->ReplicateConstraints((*git), m_logicHierarchicalGameObjects); - (*git)->ClearConstraints(); + if (gameobj->GetPhysicsController()) { + gameobj->GetPhysicsController()->ReplicateConstraints(gameobj, m_logicHierarchicalGameObjects); + gameobj->ClearConstraints(); } - if ((*git) != groupobj && (*git)->IsDupliGroup()) + if (gameobj != groupobj && gameobj->IsDupliGroup()) // can't instantiate group immediately as it destroys m_logicHierarchicalGameObjects - duplilist.push_back((*git)); + duplilist.push_back(gameobj); } for (git = duplilist.begin(); !(git == duplilist.end()); ++git) -- cgit v1.2.3 From 3d658bf7a7b81057f9b4477567158cbd50216517 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Fri, 15 May 2015 16:25:45 +0200 Subject: BGE: Fix stupid typo error in DupliGroupRecurse --- source/gameengine/Ketsji/KX_Scene.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 674f1e3c1b3..5ec1c2e2846 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -823,8 +823,9 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // the logic must be replicated first because we need // the new logic bricks before relinking vector::iterator git; - for (git = m_logicHierarchicalGameObjects.begin(); git != m_logicHierarchicalGameObjects.end()); ++git) { + for (git = m_logicHierarchicalGameObjects.begin(); git != m_logicHierarchicalGameObjects.end(); ++git) { KX_GameObject *gameobj = *git; + gameobj->ReParentLogic(); // relink any pointers as necessary, sort of a temporary solution -- cgit v1.2.3 From ce0d3112e40fe54bd56926b758cda4e502fb782a Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 15 May 2015 16:51:17 +0200 Subject: Scene audio naming cleanup: Remane sound_scene_handle to playback handle. sound_scene_handle was a part of scene so we could see code like scene- often in the same function. If I understand things correctly, in audaspace lingo, the playback_handle corresponds to a Reader while the scene_sound corresponds to a Factory. More cleanups will be done here later, but changing this now because my brain hurts trying to remember which is which... --- source/blender/blenkernel/intern/sound.c | 56 +++++++++++++++---------------- source/blender/makesdna/DNA_scene_types.h | 2 +- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 30c17773f7d..46a50917427 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -139,8 +139,8 @@ static void sound_sync_callback(void *data, int mode, float time) BKE_sound_play_scene(scene); else BKE_sound_stop_scene(scene); - if (scene->sound_scene_handle) - AUD_seek(scene->sound_scene_handle, time); + if (scene->playback_handle) + AUD_seek(scene->playback_handle, time); } scene = scene->id.next; } @@ -383,15 +383,15 @@ void BKE_sound_create_scene(struct Scene *scene) scene->sound_scene = AUD_createSequencer(FPS, scene->audio.flag & AUDIO_MUTE); AUD_updateSequencerData(scene->sound_scene, scene->audio.speed_of_sound, scene->audio.doppler_factor, scene->audio.distance_model); - scene->sound_scene_handle = NULL; + scene->playback_handle = NULL; scene->sound_scrub_handle = NULL; scene->speaker_handles = NULL; } void BKE_sound_destroy_scene(struct Scene *scene) { - if (scene->sound_scene_handle) - AUD_stop(scene->sound_scene_handle); + if (scene->playback_handle) + AUD_stop(scene->playback_handle); if (scene->sound_scrub_handle) AUD_stop(scene->sound_scrub_handle); if (scene->sound_scene) @@ -524,13 +524,13 @@ void BKE_sound_update_sequencer(struct Main *main, bSound *sound) static void sound_start_play_scene(struct Scene *scene) { - if (scene->sound_scene_handle) - AUD_stop(scene->sound_scene_handle); + if (scene->playback_handle) + AUD_stop(scene->playback_handle); AUD_setSequencerDeviceSpecs(scene->sound_scene); - if ((scene->sound_scene_handle = AUD_play(scene->sound_scene, 1))) - AUD_setLoop(scene->sound_scene_handle, -1); + if ((scene->playback_handle = AUD_play(scene->sound_scene, 1))) + AUD_setLoop(scene->playback_handle, -1); } void BKE_sound_play_scene(struct Scene *scene) @@ -540,20 +540,20 @@ void BKE_sound_play_scene(struct Scene *scene) AUD_lock(); - status = scene->sound_scene_handle ? AUD_getStatus(scene->sound_scene_handle) : AUD_STATUS_INVALID; + status = scene->playback_handle ? AUD_getStatus(scene->playback_handle) : AUD_STATUS_INVALID; if (status == AUD_STATUS_INVALID) { sound_start_play_scene(scene); - if (!scene->sound_scene_handle) { + if (!scene->playback_handle) { AUD_unlock(); return; } } if (status != AUD_STATUS_PLAYING) { - AUD_seek(scene->sound_scene_handle, cur_time); - AUD_resume(scene->sound_scene_handle); + AUD_seek(scene->playback_handle, cur_time); + AUD_resume(scene->playback_handle); } if (scene->audio.flag & AUDIO_SYNC) @@ -564,8 +564,8 @@ void BKE_sound_play_scene(struct Scene *scene) void BKE_sound_stop_scene(struct Scene *scene) { - if (scene->sound_scene_handle) { - AUD_pause(scene->sound_scene_handle); + if (scene->playback_handle) { + AUD_pause(scene->playback_handle); if (scene->audio.flag & AUDIO_SYNC) AUD_stopPlayback(); @@ -583,17 +583,17 @@ void BKE_sound_seek_scene(struct Main *bmain, struct Scene *scene) AUD_lock(); - status = scene->sound_scene_handle ? AUD_getStatus(scene->sound_scene_handle) : AUD_STATUS_INVALID; + status = scene->playback_handle ? AUD_getStatus(scene->playback_handle) : AUD_STATUS_INVALID; if (status == AUD_STATUS_INVALID) { sound_start_play_scene(scene); - if (!scene->sound_scene_handle) { + if (!scene->playback_handle) { AUD_unlock(); return; } - AUD_pause(scene->sound_scene_handle); + AUD_pause(scene->playback_handle); } animation_playing = 0; @@ -606,13 +606,13 @@ void BKE_sound_seek_scene(struct Main *bmain, struct Scene *scene) if (scene->audio.flag & AUDIO_SCRUB && !animation_playing) { if (scene->audio.flag & AUDIO_SYNC) { - AUD_seek(scene->sound_scene_handle, cur_time); - AUD_seekSequencer(scene->sound_scene_handle, cur_time); + AUD_seek(scene->playback_handle, cur_time); + AUD_seekSequencer(scene->playback_handle, cur_time); } else { - AUD_seek(scene->sound_scene_handle, cur_time); + AUD_seek(scene->playback_handle, cur_time); } - AUD_resume(scene->sound_scene_handle); + AUD_resume(scene->playback_handle); if (scene->sound_scrub_handle && AUD_getStatus(scene->sound_scrub_handle) != AUD_STATUS_INVALID) { AUD_seek(scene->sound_scrub_handle, 0); } @@ -620,16 +620,16 @@ void BKE_sound_seek_scene(struct Main *bmain, struct Scene *scene) if (scene->sound_scrub_handle) { AUD_stop(scene->sound_scrub_handle); } - scene->sound_scrub_handle = AUD_pauseAfter(scene->sound_scene_handle, one_frame); + scene->sound_scrub_handle = AUD_pauseAfter(scene->playback_handle, one_frame); } } else { if (scene->audio.flag & AUDIO_SYNC) { - AUD_seekSequencer(scene->sound_scene_handle, cur_time); + AUD_seekSequencer(scene->playback_handle, cur_time); } else { if (status == AUD_STATUS_PLAYING) { - AUD_seek(scene->sound_scene_handle, cur_time); + AUD_seek(scene->playback_handle, cur_time); } } } @@ -639,11 +639,11 @@ void BKE_sound_seek_scene(struct Main *bmain, struct Scene *scene) float BKE_sound_sync_scene(struct Scene *scene) { - if (scene->sound_scene_handle) { + if (scene->playback_handle) { if (scene->audio.flag & AUDIO_SYNC) - return AUD_getSequencerPosition(scene->sound_scene_handle); + return AUD_getSequencerPosition(scene->playback_handle); else - return AUD_getPosition(scene->sound_scene_handle); + return AUD_getPosition(scene->playback_handle); } return NAN_FLT; } diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 7ac00e16aff..ef0e98a14c9 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1394,7 +1394,7 @@ typedef struct Scene { ListBase transform_spaces; void *sound_scene; - void *sound_scene_handle; + void *playback_handle; void *sound_scrub_handle; void *speaker_handles; -- cgit v1.2.3 From 5dc22fbbfbed0e825faa8faab8bc5f32a6fdd829 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Fri, 15 May 2015 19:05:08 +0200 Subject: BGE: Fix T41299 Group API for child object in dupli instance group. --- source/gameengine/Ketsji/KX_Scene.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 5ec1c2e2846..8ed8ca6f148 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -809,13 +809,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // we can now add the graphic controller to the physic engine replica->ActivateGraphicController(true); - // set references for dupli-group - // groupobj holds a list of all objects, that belongs to this group - groupobj->AddInstanceObjects(replica); - - // every object gets the reference to its dupli-group object - replica->SetDupliGroupObject(groupobj); - // done with replica replica->Release(); } @@ -826,6 +819,14 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) for (git = m_logicHierarchicalGameObjects.begin(); git != m_logicHierarchicalGameObjects.end(); ++git) { KX_GameObject *gameobj = *git; + if (gameobj->GetBlenderGroupObject() == blgroupobj) { + // set references for dupli-group + // groupobj holds a list of all objects, that belongs to this group + groupobj->AddInstanceObjects(gameobj); + // every object gets the reference to its dupli-group object + gameobj->SetDupliGroupObject(groupobj); + } + gameobj->ReParentLogic(); // relink any pointers as necessary, sort of a temporary solution -- cgit v1.2.3 From 2d479421af7ea75d7f005aabaa909880043dbace Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 15 May 2015 15:52:24 +0200 Subject: Fix crasher in new lazy-rebuild outliner's treehash. treehash must always been checked before used! Reported on irc by sebastian_k and investigated by sergey, thanks! --- .../blender/blenkernel/intern/outliner_treehash.c | 22 ++++++++++++++++++++-- .../blender/editors/space_outliner/outliner_tree.c | 2 +- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/outliner_treehash.c b/source/blender/blenkernel/intern/outliner_treehash.c index 21664bfd285..f31ba34a984 100644 --- a/source/blender/blenkernel/intern/outliner_treehash.c +++ b/source/blender/blenkernel/intern/outliner_treehash.c @@ -102,6 +102,9 @@ static void fill_treehash(void *treehash, BLI_mempool *treestore) TreeStoreElem *tselem; BLI_mempool_iter iter; BLI_mempool_iternew(treestore, &iter); + + BLI_assert(treehash); + while ((tselem = BLI_mempool_iterstep(&iter))) { BKE_outliner_treehash_add_element(treehash, tselem); } @@ -121,6 +124,8 @@ static void free_treehash_group(void *key) void *BKE_outliner_treehash_rebuild_from_treestore(void *treehash, BLI_mempool *treestore) { + BLI_assert(treehash); + BLI_ghash_clear_ex(treehash, NULL, free_treehash_group, BLI_mempool_count(treestore)); fill_treehash(treehash, treestore); return treehash; @@ -144,12 +149,19 @@ static TseGroup *BKE_outliner_treehash_lookup_group(GHash *th, short type, short tse_template.type = type; tse_template.nr = type ? nr : 0; // we're picky! :) tse_template.id = id; + + BLI_assert(th); + return BLI_ghash_lookup(th, &tse_template); } TreeStoreElem *BKE_outliner_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id) { - TseGroup *group = BKE_outliner_treehash_lookup_group(treehash, type, nr, id); + TseGroup *group; + + BLI_assert(treehash); + + group = BKE_outliner_treehash_lookup_group(treehash, type, nr, id); if (group) { int i; for (i = 0; i < group->size; i++) { @@ -163,11 +175,17 @@ TreeStoreElem *BKE_outliner_treehash_lookup_unused(void *treehash, short type, s TreeStoreElem *BKE_outliner_treehash_lookup_any(void *treehash, short type, short nr, struct ID *id) { - TseGroup *group = BKE_outliner_treehash_lookup_group(treehash, type, nr, id); + TseGroup *group; + + BLI_assert(treehash); + + group = BKE_outliner_treehash_lookup_group(treehash, type, nr, id); return group ? group->elems[0] : NULL; } void BKE_outliner_treehash_free(void *treehash) { + BLI_assert(treehash); + BLI_ghash_free(treehash, NULL, free_treehash_group); } diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 728a7501d5b..d4bef06cca9 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -1580,7 +1580,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) else soops->search_flags &= ~SO_SEARCH_RECURSIVE; - if (soops->storeflag & SO_TREESTORE_REBUILD) { + if (soops->treehash && (soops->storeflag & SO_TREESTORE_REBUILD)) { soops->storeflag &= ~SO_TREESTORE_REBUILD; BKE_outliner_treehash_rebuild_from_treestore(soops->treehash, soops->treestore); } -- cgit v1.2.3 From 08f30ef31c21003685a816663f41834e4c7b56ad Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 15 May 2015 19:49:00 +0200 Subject: Fix T44724: missing menu entries for 'view fit' (F) in clip/image editors. --- release/scripts/startup/bl_ui/space_clip.py | 1 + release/scripts/startup/bl_ui/space_image.py | 1 + 2 files changed, 2 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 24b17b70493..f12f980e178 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -1147,6 +1147,7 @@ class CLIP_MT_view(Menu): layout.operator("clip.view_selected") layout.operator("clip.view_all") + layout.operator("clip.view_all", text="View Fit").fit_view = True layout.separator() layout.operator("clip.view_zoom_in") diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 40da82d44b5..8bff8c304a3 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -107,6 +107,7 @@ class IMAGE_MT_view(Menu): layout.operator("image.view_selected") layout.operator("image.view_all") + layout.operator("image.view_all", text="View Fit").fit_view = True layout.separator() -- cgit v1.2.3 From b931afe55e4f07e8d1d92cc2049467a96a0c5345 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 15 May 2015 20:12:25 +0200 Subject: Fix new 'custom previews/icons' py feature crashing in background mode. We want this even without UI, some scripts may use it in a background processing mode to avoid too heavy process in actual 'user' blender... --- source/blender/windowmanager/intern/wm_init_exit.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 77d3e3762a8..8778929ae08 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -179,10 +179,12 @@ void WM_init(bContext *C, int argc, const char **argv) GPU_set_linear_mipmap(true); GPU_set_anisotropic(U.anisotropic_filter); GPU_set_gpu_mipmapping(U.use_gpu_mipmap); - - UI_init(); } + /* Note: Currently only inits icons, which we now want in background mode too (scripts could use those in background + * processing...). In case we do more later, we may need to pass a 'background' flag. */ + UI_init(); + ED_spacemacros_init(); /* note: there is a bug where python needs initializing before loading the -- cgit v1.2.3 From 80c009721004b1d436c1892ed4705592c8dd63b0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 16 May 2015 06:18:04 +1000 Subject: Only initialize icons in background mode. Also enable this for headless builds too. Calling UI_icons_init would initialize matcaps, brushes etc... --- source/blender/editors/interface/interface_icons.c | 6 ++---- source/blender/windowmanager/intern/wm_init_exit.c | 13 ++++++++++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 7c05d5f4378..420af1e2e71 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -889,11 +889,9 @@ int UI_icon_get_height(int icon_id) void UI_icons_init(int first_dyn_id) { -#ifdef WITH_HEADLESS - (void)first_dyn_id; -#else - init_iconfile_list(&iconfilelist); BKE_icons_init(first_dyn_id); +#ifndef WITH_HEADLESS + init_iconfile_list(&iconfilelist); init_internal_icons(); init_brush_icons(); init_matcap_icons(); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 8778929ae08..c7544f21372 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -58,6 +58,7 @@ #include "BKE_screen.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" +#include "BKE_icons.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_mball_tessellate.h" @@ -179,11 +180,17 @@ void WM_init(bContext *C, int argc, const char **argv) GPU_set_linear_mipmap(true); GPU_set_anisotropic(U.anisotropic_filter); GPU_set_gpu_mipmapping(U.use_gpu_mipmap); + + UI_init(); + } + else { + /* Note: Currently only inits icons, which we now want in background mode too + * (scripts could use those in background processing...). + * In case we do more later, we may need to pass a 'background' flag. + * Called from 'UI_init' above */ + BKE_icons_init(1); } - /* Note: Currently only inits icons, which we now want in background mode too (scripts could use those in background - * processing...). In case we do more later, we may need to pass a 'background' flag. */ - UI_init(); ED_spacemacros_init(); -- cgit v1.2.3 From eeadd19eb583bd2ddf6716472aafb8ee7fb49df2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 16 May 2015 08:34:36 +1000 Subject: Cleanup: use define for playback frame limiter --- source/blender/windowmanager/intern/wm_playanim.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 66c502cba53..81e0b0e2605 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -71,6 +71,12 @@ #include "WM_api.h" /* only for WM_main_playanim */ +/* simple limiter to avoid flooding memory */ +#define USE_FRAME_CACHE_LIMIT +#ifdef USE_FRAME_CACHE_LIMIT +# define PLAY_FRAME_CACHE_MAX 30 +#endif + struct PlayState; static void playanim_window_zoom(struct PlayState *ps, const float zoom_offset); @@ -223,11 +229,14 @@ typedef struct PlayAnimPict { static struct ListBase picsbase = {NULL, NULL}; /* frames in memory - store them here to for easy deallocation later */ -static struct ListBase inmempicsbase = {NULL, NULL}; -static int added_images = 0; static bool fromdisk = false; static double ptottime = 0.0, swaptime = 0.04; +#ifdef USE_FRAME_CACHE_LIMIT +static struct ListBase inmempicsbase = {NULL, NULL}; +static int added_images = 0; +#endif + static PlayAnimPict *playanim_step(PlayAnimPict *playanim, int step) { if (step > 0) { @@ -1133,16 +1142,20 @@ static char *wm_main_playanim_intern(int argc, const char **argv) } if (ibuf) { +#ifdef USE_FRAME_CACHE_LIMIT LinkData *node; +#endif #ifdef USE_IMB_CACHE ps.picture->ibuf = ibuf; #endif + +#ifdef USE_FRAME_CACHE_LIMIT /* really basic memory conservation scheme. Keep frames in a fifo queue */ node = inmempicsbase.last; - while (added_images > 30) { - PlayAnimPict *pic = (PlayAnimPict *)node->data; + while (added_images > PLAY_FRAME_CACHE_MAX) { + PlayAnimPict *pic = node->data; if (pic->ibuf != ibuf) { LinkData *node_tmp; @@ -1160,6 +1173,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv) BLI_addhead(&inmempicsbase, BLI_genericNodeN(ps.picture)); added_images++; +#endif /* USE_FRAME_CACHE_LIMIT */ BLI_strncpy(ibuf->name, ps.picture->name, sizeof(ibuf->name)); -- cgit v1.2.3 From 1bb3d0d48540a6e818f1656258e7b02f4bb38571 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 16 May 2015 09:35:35 +1000 Subject: Select linked seam limit, now works for picking Second half of fix for also T42510 --- source/blender/editors/mesh/editmesh_select.c | 151 +++++++++++++++++--------- 1 file changed, 97 insertions(+), 54 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 93aad7fdfb7..f4f334fca8a 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2335,7 +2335,7 @@ bool EDBM_select_interior_faces(BMEditMesh *em) /************************ Select Linked Operator *************************/ -static void linked_limit_default(bContext *C, wmOperator *op) +static void select_linked_limit_default(bContext *C, wmOperator *op) { if (!RNA_struct_property_is_set(op->ptr, "limit")) { Object *obedit = CTX_data_edit_object(C); @@ -2347,6 +2347,42 @@ static void linked_limit_default(bContext *C, wmOperator *op) } } +static void select_linked_limit_begin(BMEditMesh *em) +{ + BMesh *bm = em->bm; + + BMIter iter; + BMEdge *e; + + /* grr, shouldn't need to alloc BMO flags here */ + BM_mesh_elem_toolflags_ensure(bm); + if (em->selectmode == SCE_SELECT_FACE) { + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + const bool is_walk_ok = ( + BM_elem_flag_test(e, BM_ELEM_SEAM) == 0); + + BMO_elem_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok); + } + } + else { + /* don't delimit selected edges in vert/edge mode */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + const bool is_walk_ok = ( + BM_elem_flag_test(e, BM_ELEM_SEAM) == 0 || + BM_elem_flag_test(e, BM_ELEM_SELECT)); + + BMO_elem_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok); + } + } +} + +static void select_linked_limit_end(BMEditMesh *em) +{ + BMesh *bm = em->bm; + + BM_mesh_elem_toolflags_clear(bm); +} + static int edbm_select_linked_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -2357,32 +2393,12 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) int limit; - linked_limit_default(C, op); + select_linked_limit_default(C, op); limit = RNA_boolean_get(op->ptr, "limit"); if (limit) { - BMEdge *e; - /* grr, shouldn't need to alloc BMO flags here */ - BM_mesh_elem_toolflags_ensure(bm); - if (em->selectmode == SCE_SELECT_FACE) { - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - const bool is_walk_ok = ( - BM_elem_flag_test(e, BM_ELEM_SEAM) == 0); - - BMO_elem_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok); - } - } - else { - /* don't delimit selected edges in vert/edge mode */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - const bool is_walk_ok = ( - BM_elem_flag_test(e, BM_ELEM_SEAM) == 0 || - BM_elem_flag_test(e, BM_ELEM_SELECT)); - - BMO_elem_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok); - } - } + select_linked_limit_begin(em); } if (em->selectmode & SCE_SELECT_VERTEX) { @@ -2490,7 +2506,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) } if (limit) { - BM_mesh_elem_toolflags_clear(bm); + select_linked_limit_end(em); } WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit); @@ -2523,13 +2539,13 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE BMWalker walker; BMEditMesh *em; BMVert *eve; - BMEdge *e, *eed; + BMEdge *eed; BMFace *efa; const bool sel = !RNA_boolean_get(op->ptr, "deselect"); int limit; - linked_limit_default(C, op); + select_linked_limit_default(C, op); limit = RNA_boolean_get(op->ptr, "limit"); @@ -2556,54 +2572,81 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE return OPERATOR_CANCELLED; } - if (em->selectmode == SCE_SELECT_FACE) { - BMIter iter; + if (limit) { + select_linked_limit_begin(em); + } - if (efa == NULL) - return OPERATOR_CANCELLED; + /* Note: logic closely matches 'edbm_select_linked_exec', keep in sync */ + + if ((em->selectmode & SCE_SELECT_VERTEX) && eve) { + + BMW_init(&walker, em->bm, limit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, + BMW_MASK_NOP, limit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, + BMW_FLAG_TEST_HIDDEN, + BMW_NIL_LAY); if (limit) { - /* grr, shouldn't need to alloc BMO flags here */ - BM_mesh_elem_toolflags_ensure(bm); - /* hflag no-seam --> bmo-tag */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - BMO_elem_flag_set(bm, e, BMO_ELE_TAG, !BM_elem_flag_test(e, BM_ELEM_SEAM)); + BMLoop *l_walk; + BMW_ITER (l_walk, &walker, eve) { + BM_vert_select_set(em->bm, l_walk->v, sel); + } + } + else { + BMEdge *e_walk; + BMW_ITER (e_walk, &walker, eve) { + BM_edge_select_set(em->bm, e_walk, sel); } } - /* walk */ - BMW_init(&walker, bm, BMW_ISLAND, + BMW_end(&walker); + + EDBM_selectmode_flush(em); + } + else if ((em->selectmode & SCE_SELECT_EDGE) && eed) { + + BMW_init(&walker, em->bm, limit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, BMW_MASK_NOP, limit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - for (efa = BMW_begin(&walker, efa); efa; efa = BMW_step(&walker)) { - BM_face_select_set(bm, efa, sel); + if (limit) { + BMLoop *l_walk; + BMW_ITER (l_walk, &walker, eed) { + BM_edge_select_set(em->bm, l_walk->e, sel); + BM_edge_select_set(em->bm, l_walk->prev->e, sel); + } } - BMW_end(&walker); - } - else { - if (efa) { - eed = BM_FACE_FIRST_LOOP(efa)->e; + else { + BMEdge *e_walk; + BMW_ITER (e_walk, &walker, eed) { + BM_edge_select_set(em->bm, e_walk, sel); + } } - else if (!eed) { - if (!eve || !eve->e) - return OPERATOR_CANCELLED; - eed = eve->e; - } + BMW_end(&walker); + + EDBM_selectmode_flush(em); + } + else if ((em->selectmode & SCE_SELECT_FACE) && efa) { - BMW_init(&walker, bm, BMW_VERT_SHELL, - BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP, + BMW_init(&walker, bm, BMW_ISLAND, + BMW_MASK_NOP, limit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - for (e = BMW_begin(&walker, eed->v1); e; e = BMW_step(&walker)) { - BM_edge_select_set(bm, e, sel); + { + BMFace *f_walk; + BMW_ITER (f_walk, &walker, efa) { + BM_face_select_set(bm, f_walk, sel); + BM_elem_flag_disable(f_walk, BM_ELEM_TAG); + } } + BMW_end(&walker); + } - EDBM_selectmode_flush(em); + if (limit) { + select_linked_limit_end(em); } WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit); -- cgit v1.2.3 From 5cc55486eee7ab5131750fae4a93b1472d1d5688 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 16 May 2015 10:15:48 +1000 Subject: BMesh: select linked, support other delimiters Use same options as limited dissolve (adds material & winding) --- source/blender/editors/mesh/editmesh_select.c | 121 +++++++++++++++++--------- 1 file changed, 80 insertions(+), 41 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index f4f334fca8a..288909e382f 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -53,6 +53,7 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "RNA_enum_types.h" #include "ED_mesh.h" #include "ED_screen.h" @@ -2335,19 +2336,55 @@ bool EDBM_select_interior_faces(BMEditMesh *em) /************************ Select Linked Operator *************************/ -static void select_linked_limit_default(bContext *C, wmOperator *op) +static void select_linked_delimit_default(bContext *C, wmOperator *op) { - if (!RNA_struct_property_is_set(op->ptr, "limit")) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "delimit"); + + if (!RNA_property_is_set(op->ptr, prop)) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); - if (em->selectmode == SCE_SELECT_FACE) - RNA_boolean_set(op->ptr, "limit", true); - else - RNA_boolean_set(op->ptr, "limit", false); + if (em->selectmode == SCE_SELECT_FACE) { + RNA_property_enum_set(op->ptr, prop, BMO_DELIM_SEAM); + } + else { + RNA_property_enum_set(op->ptr, prop, 0); + } } } -static void select_linked_limit_begin(BMEditMesh *em) + +static bool select_linked_delimit_test(BMEdge *e, int delimit) +{ + BLI_assert(delimit); + + if (delimit & BMO_DELIM_SEAM) { + if (BM_elem_flag_test(e, BM_ELEM_SEAM)) { + return true; + } + } + + if (delimit & BMO_DELIM_NORMAL) { + if (!BM_edge_is_contiguous(e)) { + return true; + } + } + + if (delimit & BMO_DELIM_MATERIAL) { + if (e->l && e->l->radial_next != e->l) { + const short mat_nr = e->l->f->mat_nr; + BMLoop *l_iter = e->l->radial_next; + do { + if (l_iter->f->mat_nr != mat_nr) { + return true; + } + } while ((l_iter = l_iter->radial_next) != e->l); + } + } + + return false; +} + +static void select_linked_delimit_begin(BMEditMesh *em, const int delimit) { BMesh *bm = em->bm; @@ -2359,7 +2396,7 @@ static void select_linked_limit_begin(BMEditMesh *em) if (em->selectmode == SCE_SELECT_FACE) { BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { const bool is_walk_ok = ( - BM_elem_flag_test(e, BM_ELEM_SEAM) == 0); + (select_linked_delimit_test(e, delimit) == false)); BMO_elem_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok); } @@ -2368,15 +2405,15 @@ static void select_linked_limit_begin(BMEditMesh *em) /* don't delimit selected edges in vert/edge mode */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { const bool is_walk_ok = ( - BM_elem_flag_test(e, BM_ELEM_SEAM) == 0 || - BM_elem_flag_test(e, BM_ELEM_SELECT)); + BM_elem_flag_test(e, BM_ELEM_SELECT) || + (select_linked_delimit_test(e, delimit) == false)); BMO_elem_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok); } } } -static void select_linked_limit_end(BMEditMesh *em) +static void select_linked_delimit_end(BMEditMesh *em) { BMesh *bm = em->bm; @@ -2391,14 +2428,14 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BMIter iter; BMWalker walker; - int limit; + int delimit; - select_linked_limit_default(C, op); + select_linked_delimit_default(C, op); - limit = RNA_boolean_get(op->ptr, "limit"); + delimit = RNA_enum_get(op->ptr, "delimit"); - if (limit) { - select_linked_limit_begin(em); + if (delimit) { + select_linked_delimit_begin(em, delimit); } if (em->selectmode & SCE_SELECT_VERTEX) { @@ -2408,12 +2445,12 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT)); } - BMW_init(&walker, em->bm, limit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, - BMW_MASK_NOP, limit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, + BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, + BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - if (limit) { + if (delimit) { BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_TAG)) { BMLoop *l_walk; @@ -2447,12 +2484,12 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT)); } - BMW_init(&walker, em->bm, limit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, - BMW_MASK_NOP, limit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, + BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, + BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - if (limit) { + if (delimit) { BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_TAG)) { BMLoop *l_walk; @@ -2488,7 +2525,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) } BMW_init(&walker, bm, BMW_ISLAND, - BMW_MASK_NOP, limit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, + BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); @@ -2505,8 +2542,8 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BMW_end(&walker); } - if (limit) { - select_linked_limit_end(em); + if (delimit) { + select_linked_delimit_end(em); } WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit); @@ -2528,7 +2565,8 @@ void MESH_OT_select_linked(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", ""); + RNA_def_enum_flag(ot->srna, "delimit", mesh_delimit_mode_items, 0, "Delimit", + "Delimit selected region"); } static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) @@ -2543,11 +2581,11 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE BMFace *efa; const bool sel = !RNA_boolean_get(op->ptr, "deselect"); - int limit; + int delimit; - select_linked_limit_default(C, op); + select_linked_delimit_default(C, op); - limit = RNA_boolean_get(op->ptr, "limit"); + delimit = RNA_enum_get(op->ptr, "delimit"); /* unified_finednearest needs ogl */ view3d_operator_needs_opengl(C); @@ -2572,20 +2610,20 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE return OPERATOR_CANCELLED; } - if (limit) { - select_linked_limit_begin(em); + if (delimit) { + select_linked_delimit_begin(em, delimit); } /* Note: logic closely matches 'edbm_select_linked_exec', keep in sync */ if ((em->selectmode & SCE_SELECT_VERTEX) && eve) { - BMW_init(&walker, em->bm, limit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, - BMW_MASK_NOP, limit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, + BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, + BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - if (limit) { + if (delimit) { BMLoop *l_walk; BMW_ITER (l_walk, &walker, eve) { BM_vert_select_set(em->bm, l_walk->v, sel); @@ -2604,12 +2642,12 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE } else if ((em->selectmode & SCE_SELECT_EDGE) && eed) { - BMW_init(&walker, em->bm, limit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, - BMW_MASK_NOP, limit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, + BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, + BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - if (limit) { + if (delimit) { BMLoop *l_walk; BMW_ITER (l_walk, &walker, eed) { BM_edge_select_set(em->bm, l_walk->e, sel); @@ -2630,7 +2668,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE else if ((em->selectmode & SCE_SELECT_FACE) && efa) { BMW_init(&walker, bm, BMW_ISLAND, - BMW_MASK_NOP, limit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, + BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); @@ -2645,8 +2683,8 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE BMW_end(&walker); } - if (limit) { - select_linked_limit_end(em); + if (delimit) { + select_linked_delimit_end(em); } WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit); @@ -2669,7 +2707,8 @@ void MESH_OT_select_linked_pick(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", ""); - RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", ""); + RNA_def_enum_flag(ot->srna, "delimit", mesh_delimit_mode_items, 0, "Delimit", + "Delimit selected region"); } -- cgit v1.2.3 From 05c4c2409ea4618704df28258866e39a8a53b3cb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 16 May 2015 10:18:38 +1000 Subject: BMesh: add sharp edge delimiter --- source/blender/bmesh/intern/bmesh_operator_api.h | 1 + source/blender/bmesh/tools/bmesh_decimate_dissolve.c | 6 ++++++ source/blender/editors/mesh/editmesh_select.c | 6 ++++++ source/blender/makesrna/intern/rna_mesh.c | 1 + 4 files changed, 14 insertions(+) diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index 96f954f8ee7..917b9a9dcf9 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -302,6 +302,7 @@ typedef enum { BMO_DELIM_NORMAL = 1 << 0, BMO_DELIM_MATERIAL = 1 << 1, BMO_DELIM_SEAM = 1 << 2, + BMO_DELIM_SHARP = 1 << 3, } BMO_Delimit; void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag); diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index 6d3b738a462..8a14291d3bc 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -74,6 +74,12 @@ static float bm_edge_calc_dissolve_error(const BMEdge *e, const BMO_Delimit deli goto fail; } + if ((delimit & BMO_DELIM_SHARP) && + (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0)) + { + goto fail; + } + if ((delimit & BMO_DELIM_MATERIAL) && (e->l->f->mat_nr != e->l->radial_next->f->mat_nr)) { diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 288909e382f..bf32008ee45 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2363,6 +2363,12 @@ static bool select_linked_delimit_test(BMEdge *e, int delimit) } } + if (delimit & BMO_DELIM_SHARP) { + if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0) { + return true; + } + } + if (delimit & BMO_DELIM_NORMAL) { if (!BM_edge_is_contiguous(e)) { return true; diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 400e98befd0..b5eb1a265b5 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -55,6 +55,7 @@ EnumPropertyItem mesh_delimit_mode_items[] = { {BMO_DELIM_NORMAL, "NORMAL", 0, "Normal", "Delimit by face directions"}, {BMO_DELIM_MATERIAL, "MATERIAL", 0, "Material", "Delimit by face material"}, {BMO_DELIM_SEAM, "SEAM", 0, "Seam", "Delimit by edge seams"}, + {BMO_DELIM_SHARP, "SHARP", 0, "Sharp", "Delimit by sharp edges"}, {0, NULL, 0, NULL, NULL}, }; -- cgit v1.2.3 From 3aa4a0e787993ddecaff30f36c502af20250837e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 16 May 2015 12:21:31 +1000 Subject: BMesh: add UV delimit for select-linked, dissolve --- source/blender/bmesh/intern/bmesh_operator_api.h | 1 + source/blender/bmesh/intern/bmesh_queries.c | 49 ++++++++++++++++++++ source/blender/bmesh/intern/bmesh_queries.h | 4 ++ source/blender/bmesh/tools/bmesh_decimate.h | 2 +- .../blender/bmesh/tools/bmesh_decimate_dissolve.c | 54 ++++++++++++++++++++-- source/blender/editors/mesh/editmesh_select.c | 31 +++++++++++-- source/blender/makesrna/intern/rna_mesh.c | 1 + 7 files changed, 133 insertions(+), 9 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index 917b9a9dcf9..3f7fb7b257d 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -303,6 +303,7 @@ typedef enum { BMO_DELIM_MATERIAL = 1 << 1, BMO_DELIM_SEAM = 1 << 2, BMO_DELIM_SHARP = 1 << 3, + BMO_DELIM_UV = 1 << 4, } BMO_Delimit; void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag); diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 9bc45025456..4fbba5af733 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -38,6 +38,8 @@ #include "BLI_linklist.h" #include "BLI_stackdefines.h" +#include "BKE_customdata.h" + #include "bmesh.h" #include "intern/bmesh_private.h" @@ -1039,6 +1041,53 @@ bool BM_edge_is_convex(const BMEdge *e) return true; } +/** + * Returms true when loop customdata is contiguous. + */ +bool BM_edge_is_contiguous_loop_cd( + const BMEdge *e, + const int cd_loop_type, const int cd_loop_offset) +{ + BLI_assert(cd_loop_offset != -1); + + if (e->l && e->l->radial_next != e->l) { + const BMLoop *l_base_v1 = e->l; + const BMLoop *l_base_v2 = e->l->next; + const void *l_base_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_base_v1, cd_loop_offset); + const void *l_base_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_base_v2, cd_loop_offset); + const BMLoop *l_iter = e->l->radial_next; + do { + const BMLoop *l_iter_v1; + const BMLoop *l_iter_v2; + const void *l_iter_cd_v1; + const void *l_iter_cd_v2; + + if (l_iter->v == l_base_v1->v) { + l_iter_v1 = l_iter; + l_iter_v2 = l_iter->next; + } + else { + l_iter_v1 = l_iter->next; + l_iter_v2 = l_iter; + } + BLI_assert((l_iter_v1->v == l_base_v1->v) && + (l_iter_v2->v == l_base_v2->v)); + + l_iter_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_iter_v1, cd_loop_offset); + l_iter_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_iter_v2, cd_loop_offset); + + + if ((CustomData_data_equals(cd_loop_type, l_base_cd_v1, l_iter_cd_v1) == 0) || + (CustomData_data_equals(cd_loop_type, l_base_cd_v2, l_iter_cd_v2) == 0)) + { + return false; + } + + } while ((l_iter = l_iter->radial_next) != e->l); + } + return true; +} + bool BM_vert_is_boundary(const BMVert *v) { if (v->e) { diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index f0a348db16a..d66bd00c2fc 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -91,6 +91,10 @@ bool BM_vert_is_boundary(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNUL BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool BM_edge_is_convex(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_edge_is_contiguous_loop_cd( + const BMEdge *e, + const int cd_loop_type, const int cd_loop_offset) + ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int BM_loop_region_loops_count_ex(BMLoop *l, int *r_loop_total) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); int BM_loop_region_loops_count(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); diff --git a/source/blender/bmesh/tools/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h index 1efa829c60d..17b55be52dc 100644 --- a/source/blender/bmesh/tools/bmesh_decimate.h +++ b/source/blender/bmesh/tools/bmesh_decimate.h @@ -34,7 +34,7 @@ void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations); void BM_mesh_decimate_dissolve_ex( BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, - const BMO_Delimit delimit, + BMO_Delimit delimit, BMVert **vinput_arr, const int vinput_len, BMEdge **einput_arr, const int einput_len, const short oflag_out); diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index 8a14291d3bc..986e4643201 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -32,6 +32,8 @@ #include "BLI_math.h" #include "BLI_heap.h" +#include "BKE_customdata.h" + #include "bmesh.h" #include "bmesh_decimate.h" /* own include */ @@ -59,7 +61,32 @@ static float bm_vert_edge_face_angle(BMVert *v) #undef ANGLE_TO_UNIT } -static float bm_edge_calc_dissolve_error(const BMEdge *e, const BMO_Delimit delimit) +struct DelimitData { + int cd_loop_type; + int cd_loop_size; + int cd_loop_offset; + int cd_loop_offset_end; +}; + +static bool bm_edge_is_contiguous_loop_cd_all( + const BMEdge *e, const struct DelimitData *delimit_data) +{ + int cd_loop_offset; + for (cd_loop_offset = delimit_data->cd_loop_offset; + cd_loop_offset < delimit_data->cd_loop_offset_end; + cd_loop_offset += delimit_data->cd_loop_size) + { + if (BM_edge_is_contiguous_loop_cd(e, delimit_data->cd_loop_type, cd_loop_offset) == false) { + return false; + } + } + + return true; +} + +static float bm_edge_calc_dissolve_error( + const BMEdge *e, const BMO_Delimit delimit, + const struct DelimitData *delimit_data) { const bool is_contig = BM_edge_is_contiguous(e); float angle; @@ -92,6 +119,11 @@ static float bm_edge_calc_dissolve_error(const BMEdge *e, const BMO_Delimit deli goto fail; } + if ((delimit & BMO_DELIM_UV) && + (bm_edge_is_contiguous_loop_cd_all(e, delimit_data) == 0)) { + goto fail; + } + angle = BM_edge_calc_face_angle(e); if (is_contig == false) { angle = (float)M_PI - angle; @@ -106,16 +138,30 @@ fail: void BM_mesh_decimate_dissolve_ex( BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, - const BMO_Delimit delimit, + BMO_Delimit delimit, BMVert **vinput_arr, const int vinput_len, BMEdge **einput_arr, const int einput_len, const short oflag_out) { + struct DelimitData delimit_data = {0}; const int eheap_table_len = do_dissolve_boundaries ? einput_len : max_ii(einput_len, vinput_len); void *_heap_table = MEM_mallocN(sizeof(HeapNode *) * eheap_table_len, __func__); int i; + if (delimit & BMO_DELIM_UV) { + const int layer_len = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV); + if (layer_len == 0) { + delimit &= ~BMO_DELIM_UV; + } + else { + delimit_data.cd_loop_type = CD_MLOOPUV; + delimit_data.cd_loop_size = CustomData_sizeof(delimit_data.cd_loop_type); + delimit_data.cd_loop_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, 0); + delimit_data.cd_loop_offset_end = delimit_data.cd_loop_size * layer_len; + } + } + /* --- first edges --- */ if (1) { BMEdge **earray; @@ -140,7 +186,7 @@ void BM_mesh_decimate_dissolve_ex( /* build heap */ for (i = 0; i < einput_len; i++) { BMEdge *e = einput_arr[i]; - const float cost = bm_edge_calc_dissolve_error(e, delimit); + const float cost = bm_edge_calc_dissolve_error(e, delimit, &delimit_data); eheap_table[i] = BLI_heap_insert(eheap, cost, e); BM_elem_index_set(e, i); /* set dirty */ } @@ -176,7 +222,7 @@ void BM_mesh_decimate_dissolve_ex( do { const int j = BM_elem_index_get(l_iter->e); if (j != -1 && eheap_table[j]) { - const float cost = bm_edge_calc_dissolve_error(l_iter->e, delimit); + const float cost = bm_edge_calc_dissolve_error(l_iter->e, delimit, &delimit_data); BLI_heap_remove(eheap, eheap_table[j]); eheap_table[j] = BLI_heap_insert(eheap, cost, l_iter->e); } diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index bf32008ee45..4abd0df7ce5 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2336,6 +2336,11 @@ bool EDBM_select_interior_faces(BMEditMesh *em) /************************ Select Linked Operator *************************/ +struct DelimitData { + int cd_loop_type; + int cd_loop_offset; +}; + static void select_linked_delimit_default(bContext *C, wmOperator *op) { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "delimit"); @@ -2353,7 +2358,9 @@ static void select_linked_delimit_default(bContext *C, wmOperator *op) } -static bool select_linked_delimit_test(BMEdge *e, int delimit) +static bool select_linked_delimit_test( + BMEdge *e, int delimit, + const struct DelimitData *delimit_data) { BLI_assert(delimit); @@ -2387,22 +2394,38 @@ static bool select_linked_delimit_test(BMEdge *e, int delimit) } } + if (delimit & BMO_DELIM_UV) { + if (BM_edge_is_contiguous_loop_cd(e, delimit_data->cd_loop_type, delimit_data->cd_loop_offset) == 0) { + return true; + } + } + return false; } -static void select_linked_delimit_begin(BMEditMesh *em, const int delimit) +static void select_linked_delimit_begin(BMEditMesh *em, int delimit) { + struct DelimitData delimit_data = {0}; + BMesh *bm = em->bm; BMIter iter; BMEdge *e; + if (delimit & BMO_DELIM_UV) { + delimit_data.cd_loop_type = CD_MLOOPUV; + delimit_data.cd_loop_offset = CustomData_get_offset(&bm->ldata, delimit_data.cd_loop_type); + if (delimit_data.cd_loop_offset == -1) { + delimit &= ~BMO_DELIM_UV; + } + } + /* grr, shouldn't need to alloc BMO flags here */ BM_mesh_elem_toolflags_ensure(bm); if (em->selectmode == SCE_SELECT_FACE) { BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { const bool is_walk_ok = ( - (select_linked_delimit_test(e, delimit) == false)); + (select_linked_delimit_test(e, delimit, &delimit_data) == false)); BMO_elem_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok); } @@ -2412,7 +2435,7 @@ static void select_linked_delimit_begin(BMEditMesh *em, const int delimit) BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { const bool is_walk_ok = ( BM_elem_flag_test(e, BM_ELEM_SELECT) || - (select_linked_delimit_test(e, delimit) == false)); + (select_linked_delimit_test(e, delimit, &delimit_data) == false)); BMO_elem_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok); } diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index b5eb1a265b5..9b25fbbaca3 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -56,6 +56,7 @@ EnumPropertyItem mesh_delimit_mode_items[] = { {BMO_DELIM_MATERIAL, "MATERIAL", 0, "Material", "Delimit by face material"}, {BMO_DELIM_SEAM, "SEAM", 0, "Seam", "Delimit by edge seams"}, {BMO_DELIM_SHARP, "SHARP", 0, "Sharp", "Delimit by sharp edges"}, + {BMO_DELIM_UV, "UV", 0, "UVs", "Delimit by UV coordinates"}, {0, NULL, 0, NULL, NULL}, }; -- cgit v1.2.3 From dddb4f655c554d4a476feb6cedcdfbf5863ca686 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 16 May 2015 20:53:35 +1000 Subject: BMesh: link-select-pick now supports redo Without this you can't change delimiter options without editing the keymap. --- source/blender/editors/mesh/editmesh_select.c | 201 ++++++++++++++++---------- 1 file changed, 126 insertions(+), 75 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 4abd0df7ce5..30b3d460c9e 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2341,23 +2341,6 @@ struct DelimitData { int cd_loop_offset; }; -static void select_linked_delimit_default(bContext *C, wmOperator *op) -{ - PropertyRNA *prop = RNA_struct_find_property(op->ptr, "delimit"); - - if (!RNA_property_is_set(op->ptr, prop)) { - Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = BKE_editmesh_from_object(obedit); - if (em->selectmode == SCE_SELECT_FACE) { - RNA_property_enum_set(op->ptr, prop, BMO_DELIM_SEAM); - } - else { - RNA_property_enum_set(op->ptr, prop, 0); - } - } -} - - static bool select_linked_delimit_test( BMEdge *e, int delimit, const struct DelimitData *delimit_data) @@ -2403,12 +2386,10 @@ static bool select_linked_delimit_test( return false; } -static void select_linked_delimit_begin(BMEditMesh *em, int delimit) +static void select_linked_delimit_begin(BMesh *bm, short selectmode, int delimit) { struct DelimitData delimit_data = {0}; - BMesh *bm = em->bm; - BMIter iter; BMEdge *e; @@ -2422,7 +2403,7 @@ static void select_linked_delimit_begin(BMEditMesh *em, int delimit) /* grr, shouldn't need to alloc BMO flags here */ BM_mesh_elem_toolflags_ensure(bm); - if (em->selectmode == SCE_SELECT_FACE) { + if (selectmode == SCE_SELECT_FACE) { BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { const bool is_walk_ok = ( (select_linked_delimit_test(e, delimit, &delimit_data) == false)); @@ -2457,14 +2438,10 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BMIter iter; BMWalker walker; - int delimit; - - select_linked_delimit_default(C, op); - - delimit = RNA_enum_get(op->ptr, "delimit"); + const int delimit = RNA_enum_get(op->ptr, "delimit"); if (delimit) { - select_linked_delimit_begin(em, delimit); + select_linked_delimit_begin(em->bm, em->selectmode, delimit); } if (em->selectmode & SCE_SELECT_VERTEX) { @@ -2594,60 +2571,29 @@ void MESH_OT_select_linked(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_enum_flag(ot->srna, "delimit", mesh_delimit_mode_items, 0, "Delimit", + RNA_def_enum_flag(ot->srna, "delimit", mesh_delimit_mode_items, BMO_DELIM_SEAM, "Delimit", "Delimit selected region"); } -static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op); + +static void edbm_select_linked_pick_ex( + BMEditMesh *em, + BMVert *eve, BMEdge *eed, BMFace *efa, + bool sel, int delimit) { - Object *obedit = CTX_data_edit_object(C); - ViewContext vc; - BMesh *bm; + BMesh *bm = em->bm; BMWalker walker; - BMEditMesh *em; - BMVert *eve; - BMEdge *eed; - BMFace *efa; - const bool sel = !RNA_boolean_get(op->ptr, "deselect"); - - int delimit; - select_linked_delimit_default(C, op); - - delimit = RNA_enum_get(op->ptr, "delimit"); - - /* unified_finednearest needs ogl */ - view3d_operator_needs_opengl(C); - - /* setup view context for argument to callbacks */ - em_setup_viewcontext(C, &vc); - em = vc.em; - - if (em->bm->totedge == 0) - return OPERATOR_CANCELLED; - - bm = em->bm; - - vc.mval[0] = event->mval[0]; - vc.mval[1] = event->mval[1]; - - /* return warning! */ - - if (unified_findnearest(&vc, &eve, &eed, &efa) == 0) { - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit); - - return OPERATOR_CANCELLED; - } - if (delimit) { - select_linked_delimit_begin(em, delimit); + select_linked_delimit_begin(bm, em->selectmode, delimit); } /* Note: logic closely matches 'edbm_select_linked_exec', keep in sync */ if ((em->selectmode & SCE_SELECT_VERTEX) && eve) { - BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, + BMW_init(&walker, bm, delimit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); @@ -2655,13 +2601,13 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE if (delimit) { BMLoop *l_walk; BMW_ITER (l_walk, &walker, eve) { - BM_vert_select_set(em->bm, l_walk->v, sel); + BM_vert_select_set(bm, l_walk->v, sel); } } else { BMEdge *e_walk; BMW_ITER (e_walk, &walker, eve) { - BM_edge_select_set(em->bm, e_walk, sel); + BM_edge_select_set(bm, e_walk, sel); } } @@ -2671,7 +2617,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE } else if ((em->selectmode & SCE_SELECT_EDGE) && eed) { - BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, + BMW_init(&walker, bm, delimit ? BMW_LOOP_SHELL : BMW_VERT_SHELL, BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); @@ -2679,14 +2625,14 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE if (delimit) { BMLoop *l_walk; BMW_ITER (l_walk, &walker, eed) { - BM_edge_select_set(em->bm, l_walk->e, sel); - BM_edge_select_set(em->bm, l_walk->prev->e, sel); + BM_edge_select_set(bm, l_walk->e, sel); + BM_edge_select_set(bm, l_walk->prev->e, sel); } } else { BMEdge *e_walk; BMW_ITER (e_walk, &walker, eed) { - BM_edge_select_set(em->bm, e_walk, sel); + BM_edge_select_set(bm, e_walk, sel); } } @@ -2715,6 +2661,104 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE if (delimit) { select_linked_delimit_end(em); } +} + +static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + Object *obedit = CTX_data_edit_object(C); + ViewContext vc; + BMEditMesh *em; + BMesh *bm; + BMVert *eve; + BMEdge *eed; + BMFace *efa; + const bool sel = !RNA_boolean_get(op->ptr, "deselect"); + const int delimit = RNA_enum_get(op->ptr, "delimit"); + int index; + + if (RNA_struct_property_is_set(op->ptr, "index")) { + return edbm_select_linked_pick_exec(C, op); + } + + /* unified_finednearest needs ogl */ + view3d_operator_needs_opengl(C); + + /* setup view context for argument to callbacks */ + em_setup_viewcontext(C, &vc); + em = vc.em; + bm = em->bm; + + if (bm->totedge == 0) { + return OPERATOR_CANCELLED; + } + + vc.mval[0] = event->mval[0]; + vc.mval[1] = event->mval[1]; + + /* return warning! */ + if (unified_findnearest(&vc, &eve, &eed, &efa) == 0) { + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit); + + return OPERATOR_CANCELLED; + } + + edbm_select_linked_pick_ex(em, eve, eed, efa, sel, delimit); + + /* to support redo */ + if ((em->selectmode & SCE_SELECT_VERTEX) && eve) { + BM_mesh_elem_index_ensure(bm, BM_VERT); + index = BM_elem_index_get(eve); + } + else if ((em->selectmode & SCE_SELECT_EDGE) && eed) { + BM_mesh_elem_index_ensure(bm, BM_EDGE); + index = BM_elem_index_get(eed) + bm->totvert; + } + else if ((em->selectmode & SCE_SELECT_FACE) && efa) { + BM_mesh_elem_index_ensure(bm, BM_FACE); + index = BM_elem_index_get(efa) + bm->totvert + bm->totedge; + } + else { + index = -1; + } + + RNA_int_set(op->ptr, "index", index); + + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit); + + return OPERATOR_FINISHED; +} + + +static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + int index; + BMVert *eve = NULL; + BMEdge *eed = NULL; + BMFace *efa = NULL; + const bool sel = !RNA_boolean_get(op->ptr, "deselect"); + const int delimit = RNA_enum_get(op->ptr, "delimit"); + + index = RNA_int_get(op->ptr, "index"); + if (index < 0 || index >= (bm->totvert + bm->totedge + bm->totface)) { + return OPERATOR_CANCELLED; + } + + if (index < bm->totvert) { + eve = BM_vert_at_index_find_or_table(bm, index); + } + else if (index < (bm->totvert + bm->totedge)) { + index -= bm->totvert; + eed = BM_edge_at_index_find_or_table(bm, index); + } + else if (index < (bm->totvert + bm->totedge + bm->totface)) { + index -= (bm->totvert + bm->totedge); + efa = BM_face_at_index_find_or_table(bm, index); + } + + edbm_select_linked_pick_ex(em, eve, eed, efa, sel, delimit); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit); @@ -2723,6 +2767,8 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE void MESH_OT_select_linked_pick(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Select Linked"; ot->idname = "MESH_OT_select_linked_pick"; @@ -2730,14 +2776,19 @@ void MESH_OT_select_linked_pick(wmOperatorType *ot) /* api callbacks */ ot->invoke = edbm_select_linked_pick_invoke; + ot->exec = edbm_select_linked_pick_exec; ot->poll = ED_operator_editmesh; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", ""); - RNA_def_enum_flag(ot->srna, "delimit", mesh_delimit_mode_items, 0, "Delimit", + RNA_def_enum_flag(ot->srna, "delimit", mesh_delimit_mode_items, BMO_DELIM_SEAM, "Delimit", "Delimit selected region"); + + /* use for redo */ + prop = RNA_def_int(ot->srna, "index", -1, 0, INT_MAX, "", "", 0, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -- cgit v1.2.3 From a49534ae486653ba802f8878a910d95d921a2a77 Mon Sep 17 00:00:00 2001 From: Ines Almeida Date: Sat, 16 May 2015 13:04:40 +0100 Subject: setting some RNA defaults for nodes --- source/blender/makesrna/intern/rna_nodetree.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index f1b12963c6a..d0cb0b990ef 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -3308,6 +3308,8 @@ static void def_sh_mapping(StructRNA *srna) {0, NULL, 0, NULL, NULL} }; + static float default_1[3] = {1.f, 1.f, 1.f}; + PropertyRNA *prop; RNA_def_struct_sdna_from(srna, "TexMapping", "storage"); @@ -3331,6 +3333,7 @@ static void def_sh_mapping(StructRNA *srna) prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "size"); + RNA_def_property_float_array_default(prop, default_1); RNA_def_property_flag(prop, PROP_PROPORTIONAL); RNA_def_property_ui_text(prop, "Scale", ""); RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); @@ -3342,6 +3345,7 @@ static void def_sh_mapping(StructRNA *srna) prop = RNA_def_property(srna, "max", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "max"); + RNA_def_property_float_array_default(prop, default_1); RNA_def_property_ui_text(prop, "Maximum", "Maximum value for clipping"); RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); @@ -3484,6 +3488,7 @@ static void def_sh_tex_environment(StructRNA *srna) prop = RNA_def_property(srna, "color_space", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_color_space_items); + RNA_def_property_enum_default(prop, SHD_COLORSPACE_COLOR); RNA_def_property_ui_text(prop, "Color Space", "Image file color space"); RNA_def_property_update(prop, 0, "rna_Node_update"); @@ -3549,6 +3554,7 @@ static void def_sh_tex_image(StructRNA *srna) prop = RNA_def_property(srna, "color_space", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_color_space_items); + RNA_def_property_enum_default(prop, SHD_COLORSPACE_COLOR); RNA_def_property_ui_text(prop, "Color Space", "Image file color space"); RNA_def_property_update(prop, 0, "rna_Node_update"); -- cgit v1.2.3 From 4c0f0eb33897464144735000837a99e86530e3cc Mon Sep 17 00:00:00 2001 From: Tamito Kajiyama Date: Sat, 16 May 2015 23:55:45 +0900 Subject: Fix T44691 Freestyle render crashes when Views is on (Blender Internal). In pipeline.c the function add_freestyle() was supposed to be called once per frame, but after the Multi-view merge the function are called as many as the number of views. There were however a few Freestyle parameters that have to be initialized per frame, and initializing one of the parameters for each view was causing double freeing of allocated memory which was enough to result in a crash. --- source/blender/freestyle/FRS_freestyle.h | 5 +- .../intern/blender_interface/FRS_freestyle.cpp | 10 ++- source/blender/render/intern/source/pipeline.c | 74 ++++++++++++++-------- 3 files changed, 57 insertions(+), 32 deletions(-) diff --git a/source/blender/freestyle/FRS_freestyle.h b/source/blender/freestyle/FRS_freestyle.h index 9766372507b..975b1212695 100644 --- a/source/blender/freestyle/FRS_freestyle.h +++ b/source/blender/freestyle/FRS_freestyle.h @@ -45,9 +45,10 @@ void FRS_initialize(void); void FRS_set_context(struct bContext *C); void FRS_read_file(struct bContext *C); int FRS_is_freestyle_enabled(struct SceneRenderLayer *srl); -void FRS_init_stroke_rendering(struct Render *re); +void FRS_init_stroke_renderer(struct Render *re); +void FRS_begin_stroke_rendering(struct Render *re); struct Render *FRS_do_stroke_rendering(struct Render *re, struct SceneRenderLayer *srl, int render); -void FRS_finish_stroke_rendering(struct Render *re); +void FRS_end_stroke_rendering(struct Render *re); void FRS_free_view_map_cache(void); void FRS_composite_result(struct Render *re, struct SceneRenderLayer *srl, struct Render *freestyle_render); void FRS_exit(void); diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 64c6bd33924..46724ff530a 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -576,7 +576,7 @@ int FRS_is_freestyle_enabled(SceneRenderLayer *srl) return (!(srl->layflag & SCE_LAY_DISABLE) && srl->layflag & SCE_LAY_FRS && displayed_layer_count(srl) > 0); } -void FRS_init_stroke_rendering(Render *re) +void FRS_init_stroke_renderer(Render *re) { if (G.debug & G_DEBUG_FREESTYLE) { cout << endl; @@ -586,11 +586,15 @@ void FRS_init_stroke_rendering(Render *re) } init_view(re); - init_camera(re); controller->ResetRenderCount(); } +void FRS_begin_stroke_rendering(Render *re) +{ + init_camera(re); +} + Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render) { Render *freestyle_render = NULL; @@ -645,7 +649,7 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render) return freestyle_render; } -void FRS_finish_stroke_rendering(Render * /*re*/) +void FRS_end_stroke_rendering(Render * /*re*/) { // clear canvas controller->Clear(); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 3d61cd43dba..9407412a6d0 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1377,6 +1377,7 @@ static void threaded_tile_processor(Render *re) } #ifdef WITH_FREESTYLE +static void init_freestyle(Render *re); static void add_freestyle(Render *re, int render); static void free_all_freestyle_renders(void); #endif @@ -1394,8 +1395,8 @@ void RE_TileProcessor(Render *re) /* Freestyle */ if (re->r.mode & R_EDGE_FRS) { if (!re->test_break(re->tbh)) { + init_freestyle(re); add_freestyle(re, 1); - free_all_freestyle_renders(); re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime; @@ -1430,6 +1431,12 @@ static void do_render_3d(Render *re) /* init main render result */ main_render_result_new(re); +#ifdef WITH_FREESTYLE + if (re->r.mode & R_EDGE_FRS) { + init_freestyle(re); + } +#endif + /* we need a new database for each view */ for (rv = re->result->views.first; rv; rv = rv->next) { RE_SetActiveRenderView(re, rv->name); @@ -2065,6 +2072,23 @@ static void render_composit_stats(void *UNUSED(arg), const char *str) } #ifdef WITH_FREESTYLE +/* init Freestyle renderer */ +static void init_freestyle(Render *re) +{ + re->freestyle_bmain = BKE_main_new(); + + /* We use the same window manager for freestyle bmain as + * real bmain uses. This is needed because freestyle's + * bmain could be used to tag scenes for update, which + * implies call of ED_render_scene_update in some cases + * and that function requires proper window manager + * to present (sergey) + */ + re->freestyle_bmain->wm = re->main->wm; + + FRS_init_stroke_renderer(re); +} + /* invokes Freestyle stroke rendering */ static void add_freestyle(Render *re, int render) { @@ -2075,18 +2099,7 @@ static void add_freestyle(Render *re, int render) actsrl = BLI_findlink(&re->r.layers, re->r.actlay); - re->freestyle_bmain = BKE_main_new(); - - /* We use the same window manager for freestyle bmain as - * real bmain uses. This is needed because freestyle's - * bmain could be used to tag scenes for update, which - * implies call of ED_render_scene_update in some cases - * and that function requires proper window manager - * to present (sergey) - */ - re->freestyle_bmain->wm = re->main->wm; - - FRS_init_stroke_rendering(re); + FRS_begin_stroke_rendering(re); for (srl = (SceneRenderLayer *)re->r.layers.first; srl; srl = srl->next) { if (do_link) { @@ -2102,7 +2115,7 @@ static void add_freestyle(Render *re, int render) } } - FRS_finish_stroke_rendering(re); + FRS_end_stroke_rendering(re); /* restore the global R value (invalidated by nested execution of the internal renderer) */ R = *re; @@ -2112,28 +2125,32 @@ static void add_freestyle(Render *re, int render) static void composite_freestyle_renders(Render *re, int sample) { Render *freestyle_render; + RenderView *rv; SceneRenderLayer *srl, *actsrl; LinkData *link; actsrl = BLI_findlink(&re->r.layers, re->r.actlay); link = (LinkData *)re->freestyle_renders.first; - for (srl= (SceneRenderLayer *)re->r.layers.first; srl; srl= srl->next) { - if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl) - continue; - if (FRS_is_freestyle_enabled(srl)) { - freestyle_render = (Render *)link->data; + for (rv = re->result->views.first; rv; rv = rv->next) { + for (srl = (SceneRenderLayer *)re->r.layers.first; srl; srl = srl->next) { + if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl) + continue; - /* may be NULL in case of empty render layer */ - if (freestyle_render) { - render_result_exr_file_read_sample(freestyle_render, sample); - FRS_composite_result(re, srl, freestyle_render); - RE_FreeRenderResult(freestyle_render->result); - freestyle_render->result = NULL; + if (FRS_is_freestyle_enabled(srl)) { + freestyle_render = (Render *)link->data; + + /* may be NULL in case of empty render layer */ + if (freestyle_render) { + render_result_exr_file_read_sample(freestyle_render, sample); + FRS_composite_result(re, srl, freestyle_render); + RE_FreeRenderResult(freestyle_render->result); + freestyle_render->result = NULL; + } } + link = link->next; } - link = link->next; } } @@ -2375,8 +2392,10 @@ void RE_MergeFullSample(Render *re, Main *bmain, Scene *sce, bNodeTree *ntree) re->display_clear(re->dch, re->result); #ifdef WITH_FREESTYLE - if (re->r.mode & R_EDGE_FRS) + if (re->r.mode & R_EDGE_FRS) { + init_freestyle(re); add_freestyle(re, 0); + } #endif do_merge_fullsample(re, ntree); @@ -3095,6 +3114,7 @@ void RE_RenderFreestyleExternal(Render *re) if (!re->test_break(re->tbh)) { RE_Database_FromScene(re, re->main, re->scene, re->lay, 1); RE_Database_Preprocess(re); + init_freestyle(re); add_freestyle(re, 1); RE_Database_Free(re); } -- cgit v1.2.3 From dcacc54e071fcd213f4d0704f6e99041637b8765 Mon Sep 17 00:00:00 2001 From: Tamito Kajiyama Date: Sat, 16 May 2015 23:57:37 +0900 Subject: Freestyle: Fix for stroke rendering performed with multi-views enabled. Per-view Freestyle stroke rendering needs to be done without multi-views. --- .../freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index cfa0c45b1e3..64ef49d74a3 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -94,7 +94,7 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str //freestyle_scene->r.maximsize = old_scene->r.maximsize; /* DEPRECATED */ freestyle_scene->r.ocres = old_scene->r.ocres; freestyle_scene->r.color_mgt_flag = 0; // old_scene->r.color_mgt_flag; - freestyle_scene->r.scemode = old_scene->r.scemode & ~(R_SINGLE_LAYER | R_NO_FRAME_UPDATE); + freestyle_scene->r.scemode = old_scene->r.scemode & ~(R_SINGLE_LAYER | R_NO_FRAME_UPDATE | R_MULTIVIEW); freestyle_scene->r.flag = old_scene->r.flag; freestyle_scene->r.threads = old_scene->r.threads; freestyle_scene->r.border.xmin = old_scene->r.border.xmin; -- cgit v1.2.3 From 6c15f3044be138d025b2ae5d6be56103a65b4fa0 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Sat, 16 May 2015 23:08:40 +0200 Subject: Yet another attempt to fix Intel case for T43987 --- source/blender/gpu/intern/gpu_extensions.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index c0178567466..976a65aff7c 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -263,11 +263,20 @@ void gpu_extensions_init(void) GG.dfdyfactors[0] = 1.0; GG.dfdyfactors[1] = -1.0; } - else if (GG.device == GPU_DEVICE_INTEL && GG.os == GPU_OS_WIN && - (strstr(version, "4.0.0 - Build 9.18.10.3165") || - strstr(version, "3.1.0 - Build 9.17.10.4101"))) { - GG.dfdyfactors[0] = -1.0; - GG.dfdyfactors[1] = 1.0; + else if (GG.device == GPU_DEVICE_INTEL && GG.os == GPU_OS_WIN) { + if (strstr(version, "4.0.0 - Build 9.18.10.3165")) + { + GG.dfdyfactors[0] = -1.0; + GG.dfdyfactors[1] = 1.0; + } + else if (strstr(version, "3.1.0 - Build 9.17.10.4101")) { + GG.dfdyfactors[0] = -1.0; + GG.dfdyfactors[1] = -1.0; + } + else { + GG.dfdyfactors[0] = 1.0; + GG.dfdyfactors[1] = 1.0; + } } else { GG.dfdyfactors[0] = 1.0; -- cgit v1.2.3 From 60f60ed49641fbe1950460b89fcd2b5c494f1437 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 May 2015 16:05:38 +1000 Subject: CMake: fixes for own checking script don't error if generated files are missing. --- build_files/cmake/cmake_consistency_check.py | 18 +++++++++++++++--- build_files/cmake/cmake_consistency_check_config.py | 3 +++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/build_files/cmake/cmake_consistency_check.py b/build_files/cmake/cmake_consistency_check.py index 0883bdbf2d7..1a366880315 100755 --- a/build_files/cmake/cmake_consistency_check.py +++ b/build_files/cmake/cmake_consistency_check.py @@ -28,7 +28,13 @@ if not sys.version.startswith("3"): sys.version.partition(" ")[0]) sys.exit(1) -from cmake_consistency_check_config import IGNORE, UTF8_CHECK, SOURCE_DIR +from cmake_consistency_check_config import ( + IGNORE, + UTF8_CHECK, + SOURCE_DIR, + BUILD_DIR, + ) + import os from os.path import join, dirname, normpath, splitext @@ -134,6 +140,7 @@ def cmake_get_src(f): if found: cmake_base = dirname(f) + cmake_base_bin = os.path.join(BUILD_DIR, os.path.relpath(cmake_base, SOURCE_DIR)) while it is not None: i += 1 @@ -154,6 +161,8 @@ def cmake_get_src(f): # replace dirs l = l.replace("${CMAKE_CURRENT_SOURCE_DIR}", cmake_base) + l = l.replace("${CMAKE_CURRENT_BINARY_DIR}", cmake_base_bin) + l = l.strip('"') if not l: pass @@ -193,7 +202,10 @@ def cmake_get_src(f): raise Exception("unknown file type - not c or h %s -> %s" % (f, new_file)) elif context_name == "INC": - if os.path.isdir(new_file): + if new_file.startswith(BUILD_DIR): + # assume generated path + pass + elif os.path.isdir(new_file): new_path_rel = os.path.relpath(new_file, cmake_base) if new_path_rel != l: @@ -246,7 +258,7 @@ print("\nChecking for missing references:") is_err = False errs = [] for f in (global_h | global_c): - if f.endswith("dna.c"): + if f.startswith(BUILD_DIR): continue if not os.path.exists(f): diff --git a/build_files/cmake/cmake_consistency_check_config.py b/build_files/cmake/cmake_consistency_check_config.py index 729eecce233..1f75b9884bc 100644 --- a/build_files/cmake/cmake_consistency_check_config.py +++ b/build_files/cmake/cmake_consistency_check_config.py @@ -74,3 +74,6 @@ IGNORE = ( UTF8_CHECK = True SOURCE_DIR = os.path.normpath(os.path.abspath(os.path.normpath(os.path.join(os.path.dirname(__file__), "..", "..")))) + +# doesn't have to exist, just use as reference +BUILD_DIR = os.path.normpath(os.path.abspath(os.path.normpath(os.path.join(SOURCE_DIR, "..", "build")))) -- cgit v1.2.3 From 6ba128129d871b656623ce231fd7cba7a4d7af1d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 May 2015 16:09:15 +1000 Subject: CMake: correct file listing --- source/blender/blenlib/CMakeLists.txt | 1 + source/blender/depsgraph/CMakeLists.txt | 8 +++++--- source/blender/editors/util/CMakeLists.txt | 1 + source/blender/makesdna/intern/CMakeLists.txt | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 797bdaa2ae4..e39202d35fd 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -155,6 +155,7 @@ set(SRC BLI_listbase.h BLI_math.h BLI_math_base.h + BLI_math_bits.h BLI_math_color.h BLI_math_color_blend.h BLI_math_geom.h diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt index 014bcb40163..dcdb14d0ba0 100644 --- a/source/blender/depsgraph/CMakeLists.txt +++ b/source/blender/depsgraph/CMakeLists.txt @@ -25,8 +25,8 @@ set(INC . - ./intern - ./util + intern + util ../blenkernel ../blenlib ../bmesh @@ -109,7 +109,9 @@ if(WITH_LEGACY_DEPSGRAPH) endif() if(WITH_BOOST) - list(APPEND INC_SYS ${BOOST_INCLUDE_DIR}) + list(APPEND INC_SYS + ${BOOST_INCLUDE_DIR} + ) add_definitions(-DHAVE_BOOST_FUNCTION_BINDINGS) endif() diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index d1495d85e64..47894e1bc1f 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -70,6 +70,7 @@ set(SRC ../include/ED_node.h ../include/ED_numinput.h ../include/ED_object.h + ../include/ED_outliner.h ../include/ED_paint.h ../include/ED_particle.h ../include/ED_physics.h diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt index 08d2f93866a..be097c0e51e 100644 --- a/source/blender/makesdna/intern/CMakeLists.txt +++ b/source/blender/makesdna/intern/CMakeLists.txt @@ -74,7 +74,7 @@ set(INC_SYS set(SRC dna_genfile.c - dna.c + ${CMAKE_CURRENT_BINARY_DIR}/dna.c ${SRC_DNA_INC} ) -- cgit v1.2.3 From daeb3069cfbc0e5997e6d850adc968d17864baba Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 May 2015 16:09:32 +1000 Subject: Cleanup: typos --- intern/cycles/device/device_opencl.cpp | 2 +- intern/cycles/kernel/kernel_types.h | 2 +- source/blender/depsgraph/intern/depsgraph.h | 2 +- source/blender/editors/interface/interface_handlers.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index f77b567a093..e329ee495c2 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -3327,7 +3327,7 @@ Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background) const bool force_split_kernel = getenv("CYCLES_OPENCL_SPLIT_KERNEL_TEST") != NULL; /* TODO(sergey): Replace string lookups with more enum-like API, - * similar to device/venfdor checks blender's gpu. + * similar to device/vendor checks blender's gpu. */ if(force_split_kernel || (platform_name == "AMD Accelerated Parallel Processing" && diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 294a491c532..68cf6674b9d 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -471,7 +471,7 @@ typedef struct Ray { * reshuffle. And at the same time reshuffle will cause * less optimal CPU code in certain places. * - * We'll get rid of this nasty eception once AMD compiler + * We'll get rid of this nasty exception once AMD compiler * is fixed. */ #ifndef __KERNEL_OPENCL_AMD__ diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index 0232410b958..c693f4aa3b0 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -195,7 +195,7 @@ struct Depsgraph { }; /** - * Helper macros for interating over set of relationship links + * Helper macros for iterating over set of relationship links * incident on each node. * * \note it is safe to perform removal operations here... diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 7e970a13e03..9db6ce77d76 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3470,8 +3470,8 @@ int ui_but_menu_direction(uiBut *but) } /** - * Hack for uiList UI_BTYPE_LISTROW buttons to "give" events to overlaying UI_BTYPE_TEXT buttons - * (cltr-clic rename feature & co). + * Hack for #uiList #UI_BTYPE_LISTROW buttons to "give" events to overlaying #UI_BTYPE_TEXT buttons + * (Ctrl-Click rename feature & co). */ static uiBut *ui_but_list_row_text_activate( bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event, -- cgit v1.2.3 From 02cbc3c1e0be505724eb79f15d75adf6089063fe Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 May 2015 16:47:44 +1000 Subject: Cleanup: indentation --- .../blenkernel/intern/particle_distribute.c | 2 +- source/blender/blenkernel/intern/pointcache.c | 2 +- source/blender/blenkernel/intern/softbody.c | 46 +++++++++++++--------- source/blender/bmesh/tools/bmesh_bisect_plane.c | 2 +- .../blender/bmesh/tools/bmesh_decimate_dissolve.c | 3 +- source/blender/editors/transform/transform_snap.c | 4 +- source/blender/render/intern/source/rayshade.c | 31 ++++++++------- 7 files changed, 51 insertions(+), 39 deletions(-) diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 28a2d0556d7..50634460028 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -332,7 +332,7 @@ static void init_mv_jit(float *jit, int num, int seed2, float amount) rng = BLI_rng_new(31415926 + num + seed2); x= 0; - num2 = 2 * num; + num2 = 2 * num; for (i=0; ipd && ob->pd->deflect) { #if 0 /* UNUSED */ @@ -1076,6 +1077,7 @@ static int sb_detect_aabb_collisionCached(float UNUSED(force[3]), unsigned int U } } /* if (ob->pd && ob->pd->deflect) */ BLI_ghashIterator_step(ihash); + } } /* while () */ BLI_ghashIterator_free(ihash); return deflected; @@ -1114,6 +1116,7 @@ static int sb_detect_face_pointCached(float face_v1[3], float face_v2[3], float ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash); ob = BLI_ghashIterator_getKey (ihash); + { /* only with deflecting set */ if (ob->pd && ob->pd->deflect) { MVert *mvert= NULL; @@ -1177,6 +1180,7 @@ static int sb_detect_face_pointCached(float face_v1[3], float face_v2[3], float } /* if (mvert) */ } /* if (ob->pd && ob->pd->deflect) */ BLI_ghashIterator_step(ihash); + } } /* while () */ BLI_ghashIterator_free(ihash); return deflected; @@ -1206,6 +1210,7 @@ static int sb_detect_face_collisionCached(float face_v1[3], float face_v2[3], fl ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash); ob = BLI_ghashIterator_getKey (ihash); + { /* only with deflecting set */ if (ob->pd && ob->pd->deflect) { MFace *mface= NULL; @@ -1315,6 +1320,7 @@ static int sb_detect_face_collisionCached(float face_v1[3], float face_v2[3], fl }/* while a */ } /* if (ob->pd && ob->pd->deflect) */ BLI_ghashIterator_step(ihash); + } } /* while () */ BLI_ghashIterator_free(ihash); return deflected; @@ -1434,6 +1440,7 @@ static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], fl ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash); ob = BLI_ghashIterator_getKey (ihash); + { /* only with deflecting set */ if (ob->pd && ob->pd->deflect) { MFace *mface= NULL; @@ -1555,6 +1562,7 @@ static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], fl }/* while a */ } /* if (ob->pd && ob->pd->deflect) */ BLI_ghashIterator_step(ihash); + } } /* while () */ BLI_ghashIterator_free(ihash); return deflected; @@ -1762,6 +1770,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash); ob = BLI_ghashIterator_getKey (ihash); + { /* only with deflecting set */ if (ob->pd && ob->pd->deflect) { MFace *mface= NULL; @@ -1799,7 +1808,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], else { /*aye that should be cached*/ printf("missing cache error\n"); - BLI_ghashIterator_step(ihash); + BLI_ghashIterator_step(ihash); continue; } @@ -1917,16 +1926,16 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], if (facedist > outerfacethickness*ff) force_mag_norm =(float)force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness); *damp=ob->pd->pdef_sbdamp; - if (facedist > 0.0f) { - *damp *= (1.0f - facedist/outerfacethickness); - Vec3PlusStVec(outerforceaccu, force_mag_norm, d_nvect); - deflected = 3; + if (facedist > 0.0f) { + *damp *= (1.0f - facedist/outerfacethickness); + Vec3PlusStVec(outerforceaccu, force_mag_norm, d_nvect); + deflected = 3; - } - else { - Vec3PlusStVec(innerforceaccu, force_mag_norm, d_nvect); - if (deflected < 2) deflected = 2; - } + } + else { + Vec3PlusStVec(innerforceaccu, force_mag_norm, d_nvect); + if (deflected < 2) deflected = 2; + } if ((mprevvert) && (*damp > 0.0f)) { choose_winner(ve, opco, nv1, nv3, nv4, vv1, vv3, vv4); @@ -1997,6 +2006,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], }/* while a */ } /* if (ob->pd && ob->pd->deflect) */ BLI_ghashIterator_step(ihash); + } } /* while () */ if (deflected == 1) { // no face but 'outer' edge cylinder sees vert @@ -2335,14 +2345,14 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, flo float kd = 1.0f; if (sb_deflect_face(ob, bp->pos, facenormal, defforce, &cf, timenow, vel, &intrusion)) { - if (intrusion < 0.0f) { - sb->scratch->flag |= SBF_DOFUZZY; - bp->loc_flag |= SBF_DOFUZZY; - bp->choke = sb->choke*0.01f; - } + if (intrusion < 0.0f) { + sb->scratch->flag |= SBF_DOFUZZY; + bp->loc_flag |= SBF_DOFUZZY; + bp->choke = sb->choke*0.01f; + } - sub_v3_v3v3(cfforce, bp->vec, vel); - Vec3PlusStVec(bp->force, -cf*50.0f, cfforce); + sub_v3_v3v3(cfforce, bp->vec, vel); + Vec3PlusStVec(bp->force, -cf*50.0f, cfforce); Vec3PlusStVec(bp->force, kd, defforce); } @@ -3484,7 +3494,7 @@ static void makelatticesprings(Lattice *lt, BodySpring *bs, int dostiff, Object bs->v1 = bpc; bs->v2 = bpc+dw+dv-1; bs->springtype=SB_BEND; - bs->len= globallen((bp+dw+dv-1)->vec, bp->vec, ob); + bs->len= globallen((bp+dw+dv-1)->vec, bp->vec, ob); bs++; } } diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c index e6e33c905da..fbcf573acd9 100644 --- a/source/blender/bmesh/tools/bmesh_bisect_plane.c +++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c @@ -106,7 +106,7 @@ static int bm_vert_sortval_cb(const void *v_a_v, const void *v_b_v) if (val_a > val_b) return 1; else if (val_a < val_b) return -1; - return 0; + else return 0; } diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index 986e4643201..a1460cec7d1 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -120,7 +120,8 @@ static float bm_edge_calc_dissolve_error( } if ((delimit & BMO_DELIM_UV) && - (bm_edge_is_contiguous_loop_cd_all(e, delimit_data) == 0)) { + (bm_edge_is_contiguous_loop_cd_all(e, delimit_data) == 0)) + { goto fail; } diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index e8a0f35c6b0..d9cc9588d49 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -953,9 +953,9 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) // last_p = LAST_SNAP_POINT; // } // else -// { + { last_p = t->tsnap.snapPoint; -// } + } for (p1 = depth_peels.first; p1; p1 = p1->next) { diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 065cdeab61c..88960b7a66d 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -306,22 +306,23 @@ static void makeraytree_single(Render *re) RayObject *raytree; RayFace *face = NULL; VlakPrimitive *vlakprimitive = NULL; - int faces = 0, obs = 0, special = 0; + int faces = 0, special = 0; - for (obi=re->instancetable.first; obi; obi=obi->next) - if (is_raytraceable(re, obi)) { - ObjectRen *obr = obi->obr; - obs++; - - if (has_special_rayobject(re, obi)) { - special++; - } - else { - int v; - for (v=0;vtotvlak;v++) { - VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); - if (is_raytraceable_vlr(re, vlr)) - faces++; + for (obi = re->instancetable.first; obi; obi = obi->next) { + if (is_raytraceable(re, obi)) { + ObjectRen *obr = obi->obr; + + if (has_special_rayobject(re, obi)) { + special++; + } + else { + int v; + for (v = 0;v < obr->totvlak; v++) { + VlakRen *vlr = obr->vlaknodes[v >> 8].vlak + (v&255); + if (is_raytraceable_vlr(re, vlr)) { + faces++; + } + } } } } -- cgit v1.2.3 From 847ec075eb52664a9943b35dda6eb80acfc4f1cf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 May 2015 17:17:31 +1000 Subject: Cleanup: pep8 --- doc/python_api/examples/bpy.ops.2.py | 2 +- doc/python_api/sphinx_doc_gen.py | 12 +++++++----- intern/cycles/blender/addon/__init__.py | 6 ++++-- intern/cycles/blender/addon/ui.py | 12 ++++++++---- release/scripts/modules/bpy/path.py | 3 ++- release/scripts/modules/bpy_extras/io_utils.py | 8 ++++++-- release/scripts/modules/bpy_extras/object_utils.py | 13 +++++++++---- release/scripts/modules/bpy_extras/view3d_utils.py | 10 ++++++---- release/scripts/startup/bl_operators/object_align.py | 5 ++++- release/scripts/startup/bl_ui/properties_game.py | 2 +- release/scripts/startup/bl_ui/space_filebrowser.py | 1 + 11 files changed, 49 insertions(+), 25 deletions(-) diff --git a/doc/python_api/examples/bpy.ops.2.py b/doc/python_api/examples/bpy.ops.2.py index 87a2022e526..dd88c73d5e9 100644 --- a/doc/python_api/examples/bpy.ops.2.py +++ b/doc/python_api/examples/bpy.ops.2.py @@ -1,6 +1,6 @@ +""" .. _operator-execution_context: -""" Execution Context ----------------- diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 72ddf251946..e5ce4c76142 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -455,9 +455,11 @@ ClassMethodDescriptorType = type(dict.__dict__['fromkeys']) MethodDescriptorType = type(dict.get) GetSetDescriptorType = type(int.real) StaticMethodType = type(staticmethod(lambda: None)) -from types import (MemberDescriptorType, - MethodType, - ) +from types import ( + MemberDescriptorType, + MethodType, + FunctionType, + ) _BPY_STRUCT_FAKE = "bpy_struct" _BPY_PROP_COLLECTION_FAKE = "bpy_prop_collection" @@ -869,7 +871,7 @@ def pymodule2sphinx(basepath, module_name, module, title): module_dir_value_type.sort(key=lambda triple: str(triple[2])) for attribute, value, value_type in module_dir_value_type: - if value_type == types.FunctionType: + if value_type == FunctionType: pyfunc2sphinx("", fw, module_name, None, attribute, value, is_class=False) elif value_type in {types.BuiltinMethodType, types.BuiltinFunctionType}: # both the same at the moment but to be future proof # note: can't get args from these, so dump the string as is @@ -939,7 +941,7 @@ def pymodule2sphinx(basepath, module_name, module, title): # needed for pure python classes for key, descr in descr_items: - if type(descr) == types.FunctionType: + if type(descr) == FunctionType: pyfunc2sphinx(" ", fw, module_name, type_name, key, descr, is_class=True) for key, descr in descr_items: diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index 9c78e0c9a62..0783c1c4cba 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -30,8 +30,10 @@ bl_info = { import bpy -from . import engine -from . import version_update +from . import ( + engine, + version_update, + ) class CyclesRender(bpy.types.RenderEngine): diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 545d0b6c26c..430c0a964b1 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -18,7 +18,11 @@ import bpy -from bpy.types import Panel, Menu, Operator, UIList +from bpy.types import ( + Panel, + Menu, + Operator, + ) class CYCLES_MT_sampling_presets(Menu): @@ -55,6 +59,7 @@ def use_cpu(context): return (device_type == 'NONE' or cscene.device == 'CPU') + def use_branched_path(context): cscene = context.scene.cycles device_type = context.user_preferences.system.compute_device_type @@ -442,7 +447,6 @@ class CyclesRender_PT_views(CyclesButtonsPanel, Panel): rd = scene.render rv = rd.views.active - layout.active = rd.use_multiview basic_stereo = (rd.views_format == 'STEREO_3D') @@ -518,12 +522,12 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel): sub = col.column(align=True) sub.label("Viewport:") subhq = sub.column() - subhq.active = hq_support; + subhq.active = hq_support subhq.prop(dof_options, "use_high_quality") sub.prop(dof_options, "fstop") if dof_options.use_high_quality and hq_support: sub.prop(dof_options, "blades") - + col = split.column() col.label("Aperture:") diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py index 0012083ba98..be38fefbd2a 100644 --- a/release/scripts/modules/bpy/path.py +++ b/release/scripts/modules/bpy/path.py @@ -226,7 +226,8 @@ def resolve_ncase(path): if _os.path.isdir(dirpath): try: files = _os.listdir(dirpath) - except PermissionError: # We might not have the permission to list dirpath... + except PermissionError: + # We might not have the permission to list dirpath... return path, False else: return path, False diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py index 32623e2bd25..65ccc3f8dc3 100644 --- a/release/scripts/modules/bpy_extras/io_utils.py +++ b/release/scripts/modules/bpy_extras/io_utils.py @@ -35,7 +35,11 @@ __all__ = ( ) import bpy -from bpy.props import StringProperty, BoolProperty, EnumProperty +from bpy.props import ( + StringProperty, + BoolProperty, + EnumProperty, + ) def _check_axis_conversion(op): @@ -368,7 +372,7 @@ def unpack_list(list_of_tuples): # same as above except that it adds 0 for triangle faces def unpack_face_list(list_of_tuples): - #allocate the entire list + # allocate the entire list flat_ls = [0] * (len(list_of_tuples) * 4) i = 0 diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py index 13ef86b23c0..16224144ee4 100644 --- a/release/scripts/modules/bpy_extras/object_utils.py +++ b/release/scripts/modules/bpy_extras/object_utils.py @@ -31,7 +31,10 @@ __all__ = ( import bpy -from bpy.props import BoolProperty, FloatVectorProperty +from bpy.props import ( + BoolProperty, + FloatVectorProperty, + ) def add_object_align_init(context, operator): @@ -171,7 +174,7 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name= obj_act.select = True scene.update() # apply location - #scene.objects.active = obj_new + # scene.objects.active = obj_new bpy.ops.object.join() # join into the active. if obdata: @@ -287,7 +290,8 @@ def world_to_camera_view(scene, obj, coord): Returns the camera space coords for a 3d point. (also known as: normalized device coordinates - NDC). - Where (0, 0) is the bottom left and (1, 1) is the top right of the camera frame. + Where (0, 0) is the bottom left and (1, 1) + is the top right of the camera frame. values outside 0-1 are also supported. A negative 'z' value means the point is behind the camera. @@ -300,7 +304,8 @@ def world_to_camera_view(scene, obj, coord): :type obj: :class:`bpy.types.Object` :arg coord: World space location. :type coord: :class:`mathutils.Vector` - :return: a vector where X and Y map to the view plane and Z is the depth on the view axis. + :return: a vector where X and Y map to the view plane and + Z is the depth on the view axis. :rtype: :class:`mathutils.Vector` """ from mathutils import Vector diff --git a/release/scripts/modules/bpy_extras/view3d_utils.py b/release/scripts/modules/bpy_extras/view3d_utils.py index b8f9bc730f7..4aa06262970 100644 --- a/release/scripts/modules/bpy_extras/view3d_utils.py +++ b/release/scripts/modules/bpy_extras/view3d_utils.py @@ -69,11 +69,13 @@ def region_2d_to_origin_3d(region, rv3d, coord, clamp=None): .. note:: - Orthographic views have a less obvious origin, the far clip is used to define the viewport near/far extents. - Since far clip can be a very large value, the result may give with numeric precision issues. + Orthographic views have a less obvious origin, + the far clip is used to define the viewport near/far extents. + Since far clip can be a very large value, + the result may give with numeric precision issues. - To avoid this problem, you can optionally clamp the far clip to a smaller value - based on the data you're operating on. + To avoid this problem, you can optionally clamp the far clip to a + smaller value based on the data you're operating on. :arg region: region of the 3D viewport, typically bpy.context.region. :type region: :class:`bpy.types.Region` diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py index 916a9f66915..7fb0924add5 100644 --- a/release/scripts/startup/bl_operators/object_align.py +++ b/release/scripts/startup/bl_operators/object_align.py @@ -340,7 +340,10 @@ def align_objects(context, return True -from bpy.props import EnumProperty, BoolProperty +from bpy.props import ( + EnumProperty, + BoolProperty + ) class AlignObjects(Operator): diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py index 6fb172bf1e3..ceeb45ac485 100644 --- a/release/scripts/startup/bl_ui/properties_game.py +++ b/release/scripts/startup/bl_ui/properties_game.py @@ -223,7 +223,7 @@ class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, Panel): row.prop(game, "collision_margin", text="Margin", slider=True) sub = row.row() - sub.active = game.physics_type not in {'SOFT_BODY', 'CHARACTER'} + sub.active = game.physics_type not in {'SOFT_BODY', 'CHARACTER'} sub.prop(game, "use_collision_compound", text="Compound") layout.separator() diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py index bcf0495d00f..0d900a41f25 100644 --- a/release/scripts/startup/bl_ui/space_filebrowser.py +++ b/release/scripts/startup/bl_ui/space_filebrowser.py @@ -128,6 +128,7 @@ class FILEBROWSER_PT_system_folders(Panel): row.template_list("FILEBROWSER_UL_dir", "system_folders", space, "system_folders", space, "system_folders_active", item_dyntip_propname="path", rows=1, maxrows=10) + class FILEBROWSER_PT_system_bookmarks(Panel): bl_space_type = 'FILE_BROWSER' bl_region_type = 'TOOLS' -- cgit v1.2.3 From f51fef63aab8b2bc16aefe5e42c4f6de8265ed98 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 May 2015 17:17:02 +1000 Subject: Fix own error deleting previews --- release/scripts/modules/bpy/utils/previews.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release/scripts/modules/bpy/utils/previews.py b/release/scripts/modules/bpy/utils/previews.py index bd6b6a0d304..965971139e4 100644 --- a/release/scripts/modules/bpy/utils/previews.py +++ b/release/scripts/modules/bpy/utils/previews.py @@ -112,7 +112,7 @@ class ImagePreviewCollection(dict): _uuid_open.remove(self._uuid) def __delitem__(self, key): - _utils_previews.release(self._gen_key(name)) + _utils_previews.release(self._gen_key(key)) super().__delitem__(key) def __repr__(self): @@ -145,6 +145,7 @@ def remove(pcoll): # don't complain about resources on exit (only unregister) import atexit + def exit_clear_warning(): del ImagePreviewCollection.__del__ -- cgit v1.2.3 From 347843f6fe5aad306935332756992f2f80fb5007 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sun, 17 May 2015 12:09:43 +0200 Subject: Cycles Standalone: Update help screen. --- intern/cycles/util/util_view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/util/util_view.cpp b/intern/cycles/util/util_view.cpp index e77ebb2fe3e..0c11316417b 100644 --- a/intern/cycles/util/util_view.cpp +++ b/intern/cycles/util/util_view.cpp @@ -98,7 +98,7 @@ void view_display_help() glColor3f(0.8f, 0.8f, 0.8f); view_display_text(x1+20, y2-20, "Cycles Renderer"); - view_display_text(x1+20, y2-40, "(C) 2011-2014 Blender Foundation"); + view_display_text(x1+20, y2-40, "(C) 2011-2015 Blender Foundation"); view_display_text(x1+20, y2-80, "Controls:"); view_display_text(x1+20, y2-100, "h: Info/Help"); view_display_text(x1+20, y2-120, "r: Reset"); -- cgit v1.2.3 From dad2850cc5aba2e7dd97ce86561fa4c753cc6fb0 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 17 May 2015 19:45:59 +1200 Subject: Numeric Input for Pose Breakdowner/Slide/Push Tools --- source/blender/editors/armature/pose_slide.c | 89 ++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 19 deletions(-) diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index ffb7b3e4a1a..1a1108a2b1c 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -43,6 +43,7 @@ #include "BKE_context.h" #include "BKE_object.h" #include "BKE_report.h" +#include "BKE_unit.h" #include "RNA_access.h" #include "RNA_define.h" @@ -53,6 +54,7 @@ #include "ED_armature.h" #include "ED_keyframes_draw.h" #include "ED_markers.h" +#include "ED_numinput.h" #include "ED_screen.h" #include "armature_intern.h" @@ -98,6 +100,8 @@ typedef struct tPoseSlideOp { int flag; /* unused for now, but can later get used for storing runtime settings.... */ float percentage; /* 0-1 value for determining the influence of whatever is relevant */ + + NumInput num; /* numeric input */ } tPoseSlideOp; /* Pose Sliding Modes */ @@ -154,6 +158,12 @@ static int pose_slide_init(bContext *C, wmOperator *op, short mode) */ BLI_dlrbTree_init(&pso->keys); + /* initialise numeric input */ + initNumInput(&pso->num); + pso->num.idx_max = 0; /* one axis */ + pso->num.val_flag[0] |= NUM_NO_NEGATIVE; + pso->num.unit_type[0] = B_UNIT_NONE; /* percentages don't have any units... */ + /* return status is whether we've got all the data we were requested to get */ return 1; } @@ -534,7 +544,7 @@ static void pose_slide_reset(tPoseSlideOp *pso) /* draw percentage indicator in header */ static void pose_slide_draw_status(tPoseSlideOp *pso) { - char status_str[32]; + char status_str[256]; char mode_str[32]; switch (pso->mode) { @@ -554,7 +564,18 @@ static void pose_slide_draw_status(tPoseSlideOp *pso) break; } - BLI_snprintf(status_str, sizeof(status_str), "%s: %d %%", mode_str, (int)(pso->percentage * 100.0f)); + if (hasNumInput(&pso->num)) { + Scene *scene = pso->scene; + char str_offs[NUM_STR_REP_LEN]; + + outputNumInput(&pso->num, str_offs, &scene->unit); + + BLI_snprintf(status_str, sizeof(status_str), "%s: %s", mode_str, str_offs); + } + else { + BLI_snprintf(status_str, sizeof(status_str), "%s: %d %%", mode_str, (int)(pso->percentage * 100.0f)); + } + ED_area_headerprint(pso->sa, status_str); } @@ -639,6 +660,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) { tPoseSlideOp *pso = op->customdata; wmWindow *win = CTX_wm_window(C); + const bool has_numinput = hasNumInput(&pso->num); switch (event->type) { case LEFTMOUSE: /* confirm */ @@ -678,25 +700,54 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) case MOUSEMOVE: /* calculate new position */ { - /* calculate percentage based on position of mouse (we only use x-axis for now. - * since this is more convenient for users to do), and store new percentage value - */ - pso->percentage = (event->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx); - RNA_float_set(op->ptr, "percentage", pso->percentage); - - /* update percentage indicator in header */ - pose_slide_draw_status(pso); - - /* reset transforms (to avoid accumulation errors) */ - pose_slide_reset(pso); - - /* apply... */ - pose_slide_apply(C, pso); + /* only handle mousemove if not doing numinput */ + if (has_numinput == false) { + /* calculate percentage based on position of mouse (we only use x-axis for now. + * since this is more convenient for users to do), and store new percentage value + */ + pso->percentage = (event->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx); + RNA_float_set(op->ptr, "percentage", pso->percentage); + + /* update percentage indicator in header */ + pose_slide_draw_status(pso); + + /* reset transforms (to avoid accumulation errors) */ + pose_slide_reset(pso); + + /* apply... */ + pose_slide_apply(C, pso); + } break; } - default: /* unhandled event (maybe it was some view manip? */ - /* allow to pass through */ - return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; + default: + if ((event->val == KM_PRESS) && handleNumInput(C, &pso->num, event)) { + float value; + + /* Grab percentage from numeric input, and store this new value for redo + * NOTE: users see ints, while internally we use a 0-1 float + */ + value = pso->percentage * 100.0f; + applyNumInput(&pso->num, &value); + + pso->percentage = value / 100.0f; + CLAMP(pso->percentage, 0.0f, 1.0f); + RNA_float_set(op->ptr, "percentage", pso->percentage); + + /* update percentage indicator in header */ + pose_slide_draw_status(pso); + + /* reset transforms (to avoid accumulation errors) */ + pose_slide_reset(pso); + + /* apply... */ + pose_slide_apply(C, pso); + break; + } + else { + /* unhandled event - maybe it was some view manip? */ + /* allow to pass through */ + return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; + } } /* still running... */ -- cgit v1.2.3 From effb9120613c06060c1103981dfe6d58df05933d Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sun, 17 May 2015 12:35:58 +0200 Subject: Cycles Standalone: Expose various light settings. --- intern/cycles/app/cycles_xml.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 1cfc8145b0f..02cf146c647 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -1034,13 +1034,28 @@ static void xml_read_light(const XMLReadState& state, pugi::xml_node node) xml_read_float(&light->sizev, node, "sizev"); xml_read_float3(&light->axisu, node, "axisu"); xml_read_float3(&light->axisv, node, "axisv"); - + + /* Portal? (Area light only) */ + xml_read_bool(&light->is_portal, node, "is_portal"); + /* Generic */ xml_read_float(&light->size, node, "size"); xml_read_float3(&light->dir, node, "dir"); xml_read_float3(&light->co, node, "P"); light->co = transform_point(&state.tfm, light->co); + /* Settings */ + xml_read_bool(&light->cast_shadow, node, "cast_shadow"); + xml_read_bool(&light->use_mis, node, "use_mis"); + xml_read_int(&light->samples, node, "samples"); + xml_read_int(&light->max_bounces, node, "max_bounces"); + + /* Ray Visibility */ + xml_read_bool(&light->use_diffuse, node, "use_diffuse"); + xml_read_bool(&light->use_glossy, node, "use_glossy"); + xml_read_bool(&light->use_transmission, node, "use_transmission"); + xml_read_bool(&light->use_scatter, node, "use_scatter"); + state.scene->lights.push_back(light); } -- cgit v1.2.3 From 4d45f479205d6712ea65f913c1e92bd8a97c260a Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 17 May 2015 12:44:18 +0200 Subject: Fix T44737: Missing 'Spin' op entry in surface (NURBS) tools/menu. --- release/scripts/startup/bl_ui/space_view3d.py | 1 + release/scripts/startup/bl_ui/space_view3d_toolbar.py | 1 + 2 files changed, 2 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index a4de4f858e7..cd2ec3e1eae 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -2485,6 +2485,7 @@ def draw_curve(self, context): layout.separator() layout.operator("curve.extrude_move") + layout.operator("curve.spin") layout.operator("curve.duplicate_move") layout.operator("curve.split") layout.operator("curve.separate") diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 1f7d5178665..c98bddc49e1 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -573,6 +573,7 @@ class VIEW3D_PT_tools_surfaceedit(View3DPanel, Panel): col = layout.column(align=True) col.label(text="Modeling:") col.operator("curve.extrude", text="Extrude") + col.operator("curve.spin") col.operator("curve.subdivide") col = layout.column(align=True) -- cgit v1.2.3 From 3b359f1feaa1b8784a6a5b1f1bd7d12a2d4acb20 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Sun, 17 May 2015 00:41:31 +0200 Subject: BGE: Fix T43761 No re-creation of display list after a mesh modification. I also removed unused flags in RAS_ListRasterizer.cpp. --- .../Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp | 6 +----- .../Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h | 9 +++------ 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp index b3da5e1f812..34184f73953 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp @@ -79,10 +79,6 @@ void RAS_ListSlot::RemoveList() void RAS_ListSlot::DrawList() { - if (m_flag &LIST_STREAM || m_flag& LIST_NOCREATE) { - RemoveList(); - return; - } if (m_flag &LIST_MODIFY) { if (m_flag &LIST_CREATE) { if (m_list == 0) { @@ -115,7 +111,7 @@ void RAS_ListSlot::SetModified(bool mod) if (mod && !(m_flag & LIST_MODIFY)) { spit("Modifying list (" << m_list << ")"); m_flag = m_flag &~ LIST_END; - m_flag |= LIST_STREAM; + m_flag |= LIST_MODIFY; } } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h index d394c72b2a2..5e1c662bc17 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h @@ -35,12 +35,9 @@ public: enum RAS_ListSlotFlags { LIST_CREATE =1, LIST_MODIFY =2, - LIST_STREAM =4, - LIST_NOCREATE =8, - LIST_BEGIN =16, - LIST_END =32, - LIST_REGEN =64, - LIST_DERIVEDMESH=128, + LIST_BEGIN =4, + LIST_END =8, + LIST_DERIVEDMESH=16, }; struct DerivedMesh; -- cgit v1.2.3 From b68fa820d6eae686b7c2d3d01bc8b24bdc2120ee Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 17 May 2015 13:43:48 +0200 Subject: Fix T44715: crash compositing with undefined node due to re-save in older version --- source/blender/compositor/intern/COM_Converter.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 9de22612bdc..9fa59be4a1c 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -137,6 +137,10 @@ Node *Converter::convert(bNode *b_node) { Node *node = NULL; + /* ignore undefined nodes with missing or invalid node data */ + if (!nodeIsRegistered(b_node)) + return NULL; + switch (b_node->type) { case CMP_NODE_COMPOSITE: node = new CompositorNode(b_node); -- cgit v1.2.3 From 30b45d5591fdd20e5cd5abd0cf3be62622c0b0db Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 May 2015 23:04:34 +1000 Subject: BMesh: don't check winding for uv-vert-map Made link-select separate front/back with projected UV's --- source/blender/blenkernel/BKE_mesh_mapping.h | 3 ++- source/blender/blenkernel/intern/mesh_mapping.c | 6 +++-- source/blender/blenkernel/intern/subsurf_ccg.c | 2 +- source/blender/editors/include/ED_mesh.h | 4 ++- source/blender/editors/mesh/editmesh_utils.c | 36 +++++++++++++++++-------- source/blender/editors/uvedit/uvedit_ops.c | 10 +++---- 6 files changed, 40 insertions(+), 21 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h index dcf5d2ed78d..a2f47858f90 100644 --- a/source/blender/blenkernel/BKE_mesh_mapping.h +++ b/source/blender/blenkernel/BKE_mesh_mapping.h @@ -102,7 +102,8 @@ typedef struct MeshElemMap { /* mapping */ UvVertMap *BKE_mesh_uv_vert_map_create( struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv, - unsigned int totpoly, unsigned int totvert, int selected, float *limit, bool use_winding); + unsigned int totpoly, unsigned int totvert, + const float limit[2], const bool selected, const bool use_winding); UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v); void BKE_mesh_uv_vert_map_free(UvVertMap *vmap); diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index e4a85eb399b..8b41aded3d9 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -54,8 +54,10 @@ /* this replaces the non bmesh function (in trunk) which takes MTFace's, if we ever need it back we could * but for now this replaces it because its unused. */ -UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv, - unsigned int totpoly, unsigned int totvert, int selected, float *limit, bool use_winding) +UvVertMap *BKE_mesh_uv_vert_map_create( + struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv, + unsigned int totpoly, unsigned int totvert, + const float limit[2], const bool selected, const bool use_winding) { UvVertMap *vmap; UvMapVert *buf; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index e4d178d0b5f..b6405913c2a 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -304,7 +304,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, * UV map in really simple cases with mirror + subsurf, see second part of T44530. Also, initially * intention is to treat merged vertices from mirror modifier as seams, see code below with ME_VERT_MERGED * This fixes a very old regression (2.49 was correct here) */ - vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, 0, limit, true); + vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, limit, false, true); if (!vmap) return 0; diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index ea544135d3b..3f16055e762 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -116,7 +116,9 @@ struct MTexPoly *EDBM_mtexpoly_active_get(struct BMEditMesh *em, struct BMFace * void BM_uv_vert_map_free(struct UvVertMap *vmap); struct UvMapVert *BM_uv_vert_map_at_index(struct UvVertMap *vmap, unsigned int v); -struct UvVertMap *BM_uv_vert_map_create(struct BMesh *bm, bool use_select, const float limit[2]); +struct UvVertMap *BM_uv_vert_map_create( + struct BMesh *bm, + const float limit[2], const bool use_select, const bool use_winding); void EDBM_flag_enable_all(struct BMEditMesh *em, const char hflag); void EDBM_flag_disable_all(struct BMEditMesh *em, const char hflag); diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 4706f0467fd..51b4d624f3c 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -614,7 +614,9 @@ void undo_push_mesh(bContext *C, const char *name) /** * Return a new UVVertMap from the editmesh */ -UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2]) +UvVertMap *BM_uv_vert_map_create( + BMesh *bm, + const float limit[2], const bool use_select, const bool use_winding) { BMVert *ev; BMFace *efa; @@ -628,7 +630,7 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2 unsigned int a; int totverts, i, totuv, totfaces; const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - bool *winding; + bool *winding = NULL; BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE); @@ -654,7 +656,9 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2 vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totverts, "UvMapVert_pt"); buf = vmap->buf = (UvMapVert *)MEM_callocN(sizeof(*vmap->buf) * totuv, "UvMapVert"); - winding = MEM_callocN(sizeof(*winding) * totfaces, "winding"); + if (use_winding) { + winding = MEM_callocN(sizeof(*winding) * totfaces, "winding"); + } if (!vmap->vert || !vmap->buf) { BKE_mesh_uv_vert_map_free(vmap); @@ -663,7 +667,11 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2 BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, a) { if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) { - float (*tf_uv)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa->len); + float (*tf_uv)[2]; + + if (use_winding) { + tf_uv = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa->len); + } BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i) { buf->tfindex = i; @@ -672,14 +680,17 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2 buf->next = vmap->vert[BM_elem_index_get(l->v)]; vmap->vert[BM_elem_index_get(l->v)] = buf; - - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - copy_v2_v2(tf_uv[i], luv->uv); - buf++; + + if (use_winding) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + copy_v2_v2(tf_uv[i], luv->uv); + } } - winding[a] = cross_poly_v2((const float (*)[2])tf_uv, efa->len) > 0; + if (use_winding) { + winding[a] = cross_poly_v2((const float (*)[2])tf_uv, efa->len) > 0; + } } } @@ -717,7 +728,7 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2 sub_v2_v2v2(uvdiff, uv2, uv); if (fabsf(uvdiff[0]) < limit[0] && fabsf(uvdiff[1]) < limit[1] && - winding[iterv->f] == winding[v->f]) + (!use_winding || winding[iterv->f] == winding[v->f])) { if (lastv) lastv->next = next; else vlist = next; @@ -737,7 +748,10 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2 vmap->vert[a] = newvlist; } - MEM_freeN(winding); + if (use_winding) { + MEM_freeN(winding); + } + BLI_buffer_free(&tf_uv_buf); return vmap; diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index a5c5a015c72..2e155e4c872 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -1028,7 +1028,7 @@ static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestH /* setup */ BM_mesh_elem_table_ensure(em->bm, BM_FACE); - vmap = BM_uv_vert_map_create(em->bm, 0, limit); + vmap = BM_uv_vert_map_create(em->bm, 0, limit, false); BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); @@ -1131,7 +1131,7 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */ - vmap = BM_uv_vert_map_create(em->bm, !select_faces, limit); + vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, false); if (vmap == NULL) return; @@ -2714,7 +2714,7 @@ static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object uvedit_pixel_to_float(sima, limit, 0.05); BM_mesh_elem_table_ensure(em->bm, BM_FACE); - vmap = BM_uv_vert_map_create(em->bm, 0, limit); + vmap = BM_uv_vert_map_create(em->bm, limit, false, false); if (vmap == NULL) { return; } @@ -2805,7 +2805,7 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object uvedit_pixel_to_float(sima, limit, 0.05); BM_mesh_elem_table_ensure(em->bm, BM_FACE); - vmap = BM_uv_vert_map_create(em->bm, 0, limit); + vmap = BM_uv_vert_map_create(em->bm, limit, false, false); if (vmap == NULL) { return; } @@ -4037,7 +4037,7 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op) /* This code sets editvert->tmp.l to the index. This will be useful later on. */ BM_mesh_elem_table_ensure(bm, BM_FACE); - vmap = BM_uv_vert_map_create(bm, 0, limit); + vmap = BM_uv_vert_map_create(bm, limit, false, false); BM_ITER_MESH (editedge, &iter, bm, BM_EDGES_OF_MESH) { /* flags to determine if we uv is separated from first editface match */ -- cgit v1.2.3 From 206f29c12c59f13f5815701dd7ceeee4ff8d3a64 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 18 May 2015 02:03:15 +1200 Subject: Fix T44685 - In grease pencil stroke editing, selecting points is offset by a few pixels The problem was that it was aborting too early after stumbling across a point which might fit within the bounds required. This commit improves the logic here to solve this and a few other little bugs like that. Disclaimer: There are still a few cases where it randomly ends up picking something way off. However, this only seems to occur very sporadically, so it's hard to say how bad the problem may be. --- source/blender/editors/gpencil/gpencil_select.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 9d0cb6d711a..1b66f366b70 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -775,6 +775,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) bGPDstroke *hit_stroke = NULL; bGPDspoint *hit_point = NULL; + int hit_distance = radius_squared; /* sanity checks */ if (sa == NULL) { @@ -797,7 +798,6 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) { bGPDspoint *pt; int i; - int hit_index = -1; /* firstly, check for hit-point */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { @@ -807,18 +807,19 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) /* do boundbox check first */ if (!ELEM(V2D_IS_CLIPPED, x0, x0)) { - /* only check if point is inside */ - if (((x0 - mx) * (x0 - mx) + (y0 - my) * (y0 - my)) <= radius_squared) { - hit_stroke = gps; - hit_point = pt; - break; + const int pt_distance = ((x0 - mx) * (x0 - mx) + (y0 - my) * (y0 - my)); + + /* check if point is inside */ + if (pt_distance <= radius_squared) { + /* only use this point if it is a better match than the current hit - T44685 */ + if (pt_distance < hit_distance) { + hit_stroke = gps; + hit_point = pt; + hit_distance = pt_distance; + } } } } - - /* skip to next stroke if nothing found */ - if (hit_index == -1) - continue; } CTX_DATA_END; -- cgit v1.2.3 From 2b9d806432db5f17244fcf859c2ec1441c2b3ff9 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 18 May 2015 02:25:32 +1200 Subject: Fix T44084 - Cursor gets reset after MMB scrolling in another area while in GPencil Continous Draw Mode --- source/blender/editors/gpencil/gpencil_paint.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index e902f9552b5..3d04375e00e 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1496,6 +1496,15 @@ static int gpencil_draw_init(bContext *C, wmOperator *op) /* ------------------------------- */ +/* ensure that the correct cursor icon is set */ +static void gpencil_draw_cursor_set(tGPsdata *p) +{ + if (p->paintmode == GP_PAINTMODE_ERASER) + WM_cursor_modal_set(p->win, BC_CROSSCURSOR); /* XXX need a better cursor */ + else + WM_cursor_modal_set(p->win, BC_PAINTBRUSHCURSOR); +} + /* update UI indicators of status, including cursor and header prints */ static void gpencil_draw_status_indicators(tGPsdata *p) { @@ -1736,7 +1745,6 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event) { tGPsdata *p = NULL; - wmWindow *win = CTX_wm_window(C); if (G.debug & G_DEBUG) printf("GPencil - Starting Drawing\n"); @@ -1762,11 +1770,11 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event gpencil_draw_toggle_eraser_cursor(C, p, true); } - /* set cursor */ - if (p->paintmode == GP_PAINTMODE_ERASER) - WM_cursor_modal_set(win, BC_CROSSCURSOR); /* XXX need a better cursor */ - else - WM_cursor_modal_set(win, BC_PAINTBRUSHCURSOR); + /* set cursor + * NOTE: This may change later (i.e. intentionally via brush toggle, + * or unintentionally if the user scrolls outside the area)... + */ + gpencil_draw_cursor_set(p); /* only start drawing immediately if we're allowed to do so... */ if (RNA_boolean_get(op->ptr, "wait_for_input") == false) { @@ -2095,9 +2103,11 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */ if (0 == gpencil_area_exists(C, p->sa)) estate = OPERATOR_CANCELLED; - else + else { /* update status indicators - cursor, header, etc. */ gpencil_draw_status_indicators(p); + gpencil_draw_cursor_set(p); /* cursor may have changed outside our control - T44084 */ + } /* process last operations before exiting */ switch (estate) { -- cgit v1.2.3 From a622cdaad818a8da11202a8e10450fb063ad5705 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 17 May 2015 19:27:48 +0500 Subject: Buildbot: Make sure files are readable by www group --- build_files/buildbot/master_unpack.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build_files/buildbot/master_unpack.py b/build_files/buildbot/master_unpack.py index 46131c5e1de..ec44705931c 100644 --- a/build_files/buildbot/master_unpack.py +++ b/build_files/buildbot/master_unpack.py @@ -124,10 +124,12 @@ else: directory = 'public_html/download' try: + filename = os.path.join(directory, packagename) zf = z.open(package) - f = file(os.path.join(directory, packagename), "wb") + f = file(filename, "wb") shutil.copyfileobj(zf, f) + os.chmod(filename, 0644) zf.close() z.close() -- cgit v1.2.3 From 48ed2b63090b9108e5902a2d1382b8a54025c1c0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 17 May 2015 15:37:42 +0200 Subject: UV editor: make Ctrl+E menu with mark/clear seam, instead of always marking. --- source/blender/editors/uvedit/uvedit_ops.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 2e155e4c872..3b2671361ee 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -53,6 +53,8 @@ #include "BLI_blenlib.h" #include "BLI_array.h" +#include "BLF_translation.h" + #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_depsgraph.h" @@ -80,6 +82,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "UI_interface.h" +#include "UI_resources.h" #include "UI_view2d.h" #include "uvedit_intern.h" @@ -4178,6 +4182,23 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int uv_mark_seam_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + uiPopupMenu *pup; + uiLayout *layout; + + pup = UI_popup_menu_begin(C, IFACE_("Edges"), ICON_NONE); + layout = UI_popup_menu_layout(pup); + + uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT); + uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Mark Seam"), ICON_NONE, op->type->idname, "clear", false); + uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Seam"), ICON_NONE, op->type->idname, "clear", true); + + UI_popup_menu_end(C, pup); + + return OPERATOR_INTERFACE; +} + static void UV_OT_mark_seam(wmOperatorType *ot) { /* identifiers */ @@ -4190,6 +4211,7 @@ static void UV_OT_mark_seam(wmOperatorType *ot) /* api callbacks */ ot->exec = uv_mark_seam_exec; + ot->invoke = uv_mark_seam_invoke; ot->poll = ED_operator_uvedit; RNA_def_boolean(ot->srna, "clear", false, "Clear Seams", "Clear instead of marking seams"); -- cgit v1.2.3 From 43ee3f4040a41c637b6eceda4c3aa1046f8a13a5 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 17 May 2015 15:43:42 +0200 Subject: Fix T44739: OS X RMB emulation giving wrong mouse button release event. --- .../blender/windowmanager/intern/wm_event_system.c | 43 ++++++++-------------- 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 42fc0267625..658fb317688 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2886,52 +2886,41 @@ static int convert_key(GHOST_TKey key) static void wm_eventemulation(wmEvent *event) { - /* Store last mmb event value to make emulation work when modifier keys are released first. */ - static int mmb_emulated = 0; /* this should be in a data structure somwhere */ + /* Store last mmb/rmb event value to make emulation work when modifier keys + * are released first. This really should be in a data structure somwhere. */ + static int emulating_event = EVENT_NONE; - /* middlemouse emulation */ + /* middlemouse and rightmouse emulation */ if (U.flag & USER_TWOBUTTONMOUSE) { if (event->type == LEFTMOUSE) { if (event->val == KM_PRESS && event->alt) { event->type = MIDDLEMOUSE; event->alt = 0; - mmb_emulated = 1; + emulating_event = MIDDLEMOUSE; } - else if (event->val == KM_RELEASE) { - /* only send middle-mouse release if emulated */ - if (mmb_emulated) { - event->type = MIDDLEMOUSE; - event->alt = 0; - } - mmb_emulated = 0; - } - } - - } - #ifdef __APPLE__ - - /* rightmouse emulation */ - if (U.flag & USER_TWOBUTTONMOUSE) { - if (event->type == LEFTMOUSE) { - - if (event->val == KM_PRESS && event->oskey) { + else if (event->val == KM_PRESS && event->oskey) { event->type = RIGHTMOUSE; event->oskey = 0; - mmb_emulated = 1; + emulating_event = RIGHTMOUSE; } +#endif else if (event->val == KM_RELEASE) { - if (mmb_emulated) { - event->oskey = RIGHTMOUSE; + /* only send middle-mouse release if emulated */ + if (emulating_event == MIDDLEMOUSE) { + event->type = MIDDLEMOUSE; event->alt = 0; } - mmb_emulated = 0; + else if (emulating_event == RIGHTMOUSE) { + event->type = RIGHTMOUSE; + event->oskey = 0; + } + emulating_event = EVENT_NONE; } } } -#endif /* numpad emulation */ if (U.flag & USER_NONUMPAD) { -- cgit v1.2.3 From 3cff7768d5e919b60b42bac2182ff0efb130d720 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 17 May 2015 17:25:57 +0200 Subject: Fix T44718: Cycles GLSL not working for NURBS objects. --- source/blender/editors/space_view3d/drawobject.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 5b2ac50216a..25557af5ddb 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -301,11 +301,12 @@ bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt) if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) return true; - if (BKE_scene_use_new_shading_nodes(scene)) + if (v3d->drawtype == OB_TEXTURE) + return (scene->gm.matmode == GAME_MAT_GLSL && !BKE_scene_use_new_shading_nodes(scene)); + else if (v3d->drawtype == OB_MATERIAL && dt > OB_SOLID) + return true; + else return false; - - return ((scene->gm.matmode == GAME_MAT_GLSL && v3d->drawtype == OB_TEXTURE) || - (v3d->drawtype == OB_MATERIAL)) && (dt > OB_SOLID); } static bool check_alpha_pass(Base *base) -- cgit v1.2.3 From 4139686817501a4c22149b3ef8f9b4807f5053d6 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 17 May 2015 18:18:04 +0200 Subject: Fix T44713: GLSL and BI inconsistency converting color to float node socket. --- source/blender/gpu/intern/gpu_codegen.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index e92b58932a3..90e4ce69394 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -311,18 +311,16 @@ static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *t BLI_dynstr_append(ds, name); } else if (to == GPU_FLOAT) { - if (from == GPU_VEC4) - BLI_dynstr_appendf(ds, "dot(%s.rgb, vec3(0.35, 0.45, 0.2))", name); - else if (from == GPU_VEC3) - BLI_dynstr_appendf(ds, "dot(%s, vec3(0.33))", name); + if (from == GPU_VEC4 || from == GPU_VEC3) + BLI_dynstr_appendf(ds, "(%s.r + %s.g + %s.b) / 3.0", name, name, name); else if (from == GPU_VEC2) BLI_dynstr_appendf(ds, "%s.r", name); } else if (to == GPU_VEC2) { if (from == GPU_VEC4) - BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.35, 0.45, 0.2)), %s.a)", name, name); + BLI_dynstr_appendf(ds, "vec2((%s.r + %s.g + %s.b) / 3.0, %s.a)", name, name, name, name); else if (from == GPU_VEC3) - BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.33)), 1.0)", name); + BLI_dynstr_appendf(ds, "vec2((%s.r + %s.g + %s.b) / 3.0, 1.0)", name, name, name); else if (from == GPU_FLOAT) BLI_dynstr_appendf(ds, "vec2(%s, 1.0)", name); } -- cgit v1.2.3 From 14c2bc53c0b4e02ac64c91908ba92d156c52023e Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sun, 17 May 2015 18:32:31 +0200 Subject: Cleanup: Typos, typos everywhere. :D --- intern/cycles/device/device_opencl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index e329ee495c2..5c480d98711 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -3338,14 +3338,14 @@ Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background) return new OpenCLDeviceSplitKernel(info, stats, background); } else { /* For any other device, take megakernel path. */ - VLOG(1) << "Using megekernel"; + VLOG(1) << "Using mega kernel"; return new OpenCLDeviceMegaKernel(info, stats, background); } } else { /* If we can't retrieve platform and device type information for some * reason, we default to megakernel path. */ - VLOG(1) << "Failed to rertieve platform or device, using megakernel"; + VLOG(1) << "Failed to retrieve platform or device, using mega kernel"; return new OpenCLDeviceMegaKernel(info, stats, background); } } -- cgit v1.2.3 From dae566894ae6908dfa3babc42f1c595b3acf0771 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sun, 17 May 2015 18:46:25 +0200 Subject: Cycles / OpenCL: Enable Camera Motion and Hair for AMD. Only enabled for the Experimental kernel though, so the feature set must be changed in the UI to use the features. --- intern/cycles/kernel/kernel_types.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 68cf6674b9d..54b78dec54d 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -96,7 +96,7 @@ CCL_NAMESPACE_BEGIN /* keep __KERNEL_ADV_SHADING__ in sync with opencl_kernel_use_advanced_shading! */ #ifdef __KERNEL_OPENCL_NVIDIA__ -#define __KERNEL_SHADING__ +# define __KERNEL_SHADING__ /* TODO(sergey): Advanced shading code still requires work * for split kernel. */ @@ -118,24 +118,24 @@ CCL_NAMESPACE_BEGIN #endif #ifdef __KERNEL_OPENCL_APPLE__ -#define __KERNEL_SHADING__ +# define __KERNEL_SHADING__ //#define __KERNEL_ADV_SHADING__ #endif #ifdef __KERNEL_OPENCL_AMD__ -#define __CL_USE_NATIVE__ -#define __KERNEL_SHADING__ -//__KERNEL_ADV_SHADING__ -#define __MULTI_CLOSURE__ -//#define __TRANSPARENT_SHADOWS__ -#define __PASSES__ -#define __BACKGROUND_MIS__ -#define __LAMP_MIS__ -#define __AO__ -//#define __CAMERA_MOTION__ +# define __CL_USE_NATIVE__ +# define __KERNEL_SHADING__ +# define __MULTI_CLOSURE__ +# define __PASSES__ +# define __BACKGROUND_MIS__ +# define __LAMP_MIS__ +# define __AO__ +# ifdef __KERNEL_EXPERIMENTAL__ +# define __CAMERA_MOTION__ +# define __HAIR__ +# endif //#define __OBJECT_MOTION__ -//#define __HAIR__ -//end __KERNEL_ADV_SHADING__ +//#define __TRANSPARENT_SHADOWS__ #endif #ifdef __KERNEL_OPENCL_INTEL_CPU__ -- cgit v1.2.3 From 105b87a3f729bd8b006404abc90d157dcb931ae2 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sun, 17 May 2015 19:29:33 +0200 Subject: Cycles: Enable advanced shading on AMD / OpenCL. That is needed for Motion Blur and Render Passes to work properly. I hope there are no nasty side effects, but we need to test this. --- intern/cycles/device/device_opencl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 5c480d98711..5ebde5d99a4 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -95,7 +95,7 @@ static bool opencl_kernel_use_advanced_shading(const string& platform) else if(platform == "Apple") return false; else if(platform == "AMD Accelerated Parallel Processing") - return false; + return true; else if(platform == "Intel(R) OpenCL") return true; -- cgit v1.2.3 From d1230ca7239e2eba4c0bf4b78aa234c27fcc2e38 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Sun, 17 May 2015 19:46:56 +0200 Subject: Fix Node Editor using wrong snap element menu when called from shortcut Kudos to @kopias for notifying me :) --- source/blender/editors/transform/transform_ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index fdb9d51602d..b54b8a251ae 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -1119,7 +1119,7 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, KM_SHIFT, 0); RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_snap"); kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); - RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_element"); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_node_element"); break; case SPACE_SEQ: WM_keymap_add_item(keymap, OP_SEQ_SLIDE, GKEY, KM_PRESS, 0, 0); -- cgit v1.2.3 From 0b5bf9d419407adfb3c7e1daca5c5b643da29231 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Sat, 16 May 2015 21:04:14 +0200 Subject: BGE: Fix T42244 LibLoad crash with logic brick KX_TouchSensor I remove duplicate and wrong code which treat the special case of KX_TouchSensor. And Also the re-conversion of linked logic brick. --- source/gameengine/Ketsji/KX_Scene.cpp | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 8ed8ca6f148..25755f7127b 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -1892,15 +1892,6 @@ static void MergeScene_LogicBrick(SCA_ILogicBrick* brick, KX_Scene *from, KX_Sce brick->Replace_IScene(to); brick->Replace_NetworkScene(to->GetNetworkScene()); - /* near sensors have physics controllers */ - KX_TouchSensor *touch_sensor = dynamic_cast(brick); - if (touch_sensor) { - KX_TouchEventManager *tmgr = (KX_TouchEventManager*)from->GetLogicManager()->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); - touch_sensor->UnregisterSumo(tmgr); - touch_sensor->GetPhysicsController()->SetPhysicsEnvironment(to->GetPhysicsEnvironment()); - touch_sensor->RegisterSumo(tmgr); - } - // If we end up replacing a KX_TouchEventManager, we need to make sure // physics controllers are properly in place. In other words, do this // after merging physics controllers! @@ -1959,17 +1950,6 @@ static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene { SCA_IController *cont= *itc; MergeScene_LogicBrick(cont, from, to); - - vector linkedsensors = cont->GetLinkedSensors(); - vector linkedactuators = cont->GetLinkedActuators(); - - for (vector::iterator ita = linkedactuators.begin();!(ita==linkedactuators.end());++ita) { - MergeScene_LogicBrick(*ita, from, to); - } - - for (vector::iterator its = linkedsensors.begin();!(its==linkedsensors.end());++its) { - MergeScene_LogicBrick(*its, from, to); - } } } -- cgit v1.2.3 From 3ed009af96b158d8da1e55f50e6924cc747a6e7a Mon Sep 17 00:00:00 2001 From: Martijn Berger Date: Sun, 17 May 2015 23:41:38 +0200 Subject: Change behavior of cycles xml to conform the spec: "Each XML document has exactly one single root element" --- intern/cycles/app/cycles_xml.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 02cf146c647..53262b93dd0 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -1199,7 +1199,8 @@ static void xml_read_include(const XMLReadState& state, const string& src) XMLReadState substate = state; substate.base = path_dirname(path); - xml_read_scene(substate, doc); + pugi::xml_node cycles = doc.child("cycles"); + xml_read_scene(substate, cycles); } else { fprintf(stderr, "%s read error: %s\n", src.c_str(), parse_result.description()); -- cgit v1.2.3 From 29aae4db38772cb5544a5e9998922facf951b89e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 18 May 2015 09:12:26 +1000 Subject: UI: errors in buttons now show in info report Mistakes in button expressions were previously only printed to the console. --- source/blender/editors/interface/interface.c | 1 + source/blender/python/generic/py_capi_utils.c | 28 ++++++++++++++ source/blender/python/generic/py_capi_utils.h | 1 + source/blender/python/intern/bpy_interface.c | 2 +- source/blender/python/intern/bpy_util.c | 43 +++++++++++++++------- source/blender/python/intern/bpy_util.h | 3 +- source/blender/windowmanager/WM_api.h | 1 + .../blender/windowmanager/intern/wm_event_system.c | 33 +++++++++++------ 8 files changed, 85 insertions(+), 27 deletions(-) diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 6d1d51eae0e..1eadd259295 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2315,6 +2315,7 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) double value; if (ui_but_string_set_eval_num(C, but, str, &value) == false) { + WM_report_banner_show(C); return false; } diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 92ac82508e5..6443c65a50a 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -478,6 +478,34 @@ error_cleanup: } #endif +PyObject *PyC_ExceptionBuffer_Simple(void) +{ + PyObject *string_io_buf; + + PyObject *error_type, *error_value, *error_traceback; + + if (!PyErr_Occurred()) + return NULL; + + PyErr_Fetch(&error_type, &error_value, &error_traceback); + + if (error_value == NULL) { + return NULL; + } + + string_io_buf = PyObject_Str(error_value); + /* Python does this too */ + if (UNLIKELY(string_io_buf == NULL)) { + string_io_buf = PyUnicode_FromFormat( + "", Py_TYPE(error_value)->tp_name); + } + + PyErr_Restore(error_type, error_value, error_traceback); + + PyErr_Print(); + PyErr_Clear(); + return string_io_buf; +} /* string conversion, escape non-unicode chars, coerce must be set to NULL */ const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce) diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h index 398d7da9179..ab630d1d203 100644 --- a/source/blender/python/generic/py_capi_utils.h +++ b/source/blender/python/generic/py_capi_utils.h @@ -32,6 +32,7 @@ void PyC_ObSpit(const char *name, PyObject *var); void PyC_LineSpit(void); void PyC_StackSpit(void); PyObject * PyC_ExceptionBuffer(void); +PyObject * PyC_ExceptionBuffer_Simple(void); PyObject * PyC_Object_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...); PyObject * PyC_FrozenSetFromStrings(const char **strings); PyObject * PyC_Err_Format_Prefix(PyObject *exception_type_prefix, const char *format, ...); diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index ca61ba99f9f..4be63042c1e 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -595,7 +595,7 @@ int BPY_button_exec(bContext *C, const char *expr, double *value, const bool ver if (error_ret) { if (verbose) { - BPy_errors_to_report(CTX_wm_reports(C)); + BPy_errors_to_report_ex(CTX_wm_reports(C), false, false); } else { PyErr_Clear(); diff --git a/source/blender/python/intern/bpy_util.c b/source/blender/python/intern/bpy_util.c index 93183a4f320..6e26104ea2a 100644 --- a/source/blender/python/intern/bpy_util.c +++ b/source/blender/python/intern/bpy_util.c @@ -82,10 +82,9 @@ short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool } -short BPy_errors_to_report(ReportList *reports) +bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const bool use_location) { PyObject *pystring; - PyObject *pystring_format = NULL; /* workaround, see below */ const char *cstring; const char *filename; @@ -101,31 +100,49 @@ short BPy_errors_to_report(ReportList *reports) return 1; } - pystring = PyC_ExceptionBuffer(); + if (use_full) { + pystring = PyC_ExceptionBuffer(); + } + else { + pystring = PyC_ExceptionBuffer_Simple(); + } if (pystring == NULL) { BKE_report(reports, RPT_ERROR, "Unknown py-exception, could not convert"); return 0; } - - PyC_FileAndNum(&filename, &lineno); - if (filename == NULL) - filename = ""; - + cstring = _PyUnicode_AsString(pystring); + if (use_location) { + PyObject *pystring_format; /* workaround, see below */ + + PyC_FileAndNum(&filename, &lineno); + if (filename == NULL) { + filename = ""; + } + #if 0 /* ARG!. workaround for a bug in blenders use of vsnprintf */ - BKE_reportf(reports, RPT_ERROR, "%s\nlocation: %s:%d\n", cstring, filename, lineno); + BKE_reportf(reports, RPT_ERROR, "%s\nlocation: %s:%d\n", cstring, filename, lineno); #else - pystring_format = PyUnicode_FromFormat(TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno); - cstring = _PyUnicode_AsString(pystring_format); - BKE_report(reports, RPT_ERROR, cstring); + pystring_format = PyUnicode_FromFormat(TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno); + cstring = _PyUnicode_AsString(pystring_format); + BKE_report(reports, RPT_ERROR, cstring); + Py_DECREF(pystring_format); /* workaround */ #endif + } + else { + BKE_report(reports, RPT_ERROR, cstring); + } /* not exactly needed. just for testing */ fprintf(stderr, TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno); Py_DECREF(pystring); - Py_DECREF(pystring_format); /* workaround */ return 1; } + +bool BPy_errors_to_report(ReportList *reports) +{ + return BPy_errors_to_report_ex(reports, true, true); +} \ No newline at end of file diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h index d19696aa230..1ae00a7fb02 100644 --- a/source/blender/python/intern/bpy_util.h +++ b/source/blender/python/intern/bpy_util.h @@ -40,7 +40,8 @@ char *BPy_enum_as_string(struct EnumPropertyItem *item); /* error reporting */ short BPy_reports_to_error(struct ReportList *reports, PyObject *exception, const bool clear); -short BPy_errors_to_report(struct ReportList *reports); +bool BPy_errors_to_report_ex(struct ReportList *reports, const bool use_full, const bool use_location); +bool BPy_errors_to_report(struct ReportList *reports); /* TODO - find a better solution! */ struct bContext *BPy_GetContext(void); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index d4148a56dd2..2131d5aae4a 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -178,6 +178,7 @@ void WM_main_remove_notifier_reference(const void *reference); void WM_main_remove_editor_id_reference(const struct ID *id); /* reports */ +void WM_report_banner_show(const struct bContext *C); void WM_report(const struct bContext *C, ReportType type, const char *message); void WM_reportf(const struct bContext *C, ReportType type, const char *format, ...) ATTR_PRINTF_FORMAT(3, 4); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 658fb317688..85b94363616 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -587,26 +587,35 @@ void WM_event_print(const wmEvent *event) #endif /* NDEBUG */ +/** + * Show the report in the info header. + */ +void WM_report_banner_show(const bContext *C) +{ + wmWindowManager *wm = CTX_wm_manager(C); + ReportList *wm_reports = CTX_wm_reports(C); + ReportTimerInfo *rti; + + /* After adding reports to the global list, reset the report timer. */ + WM_event_remove_timer(wm, NULL, wm_reports->reporttimer); + + /* Records time since last report was added */ + wm_reports->reporttimer = WM_event_add_timer(wm, CTX_wm_window(C), TIMERREPORT, 0.05); + + rti = MEM_callocN(sizeof(ReportTimerInfo), "ReportTimerInfo"); + wm_reports->reporttimer->customdata = rti; +} + static void wm_add_reports(const bContext *C, ReportList *reports) { /* if the caller owns them, handle this */ if (reports->list.first && (reports->flag & RPT_OP_HOLD) == 0) { - - wmWindowManager *wm = CTX_wm_manager(C); ReportList *wm_reports = CTX_wm_reports(C); - ReportTimerInfo *rti; /* add reports to the global list, otherwise they are not seen */ BLI_movelisttolist(&wm_reports->list, &reports->list); - - /* After adding reports to the global list, reset the report timer. */ - WM_event_remove_timer(wm, NULL, wm_reports->reporttimer); - - /* Records time since last report was added */ - wm_reports->reporttimer = WM_event_add_timer(wm, CTX_wm_window(C), TIMERREPORT, 0.05); - - rti = MEM_callocN(sizeof(ReportTimerInfo), "ReportTimerInfo"); - wm_reports->reporttimer->customdata = rti; + + WM_report_banner_show(C); } } -- cgit v1.2.3 From 88acb3c599b31d37375c325c47cc9264ad700720 Mon Sep 17 00:00:00 2001 From: "Sv. Lockal" Date: Mon, 18 May 2015 11:37:19 +1000 Subject: Fix T44707: cycles border render regression --- intern/cycles/device/device.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index a9e4284f35f..d69244a07bd 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -163,7 +163,7 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dx, int d /* fallback for old graphics cards that don't support GLSL, half float, * and non-power-of-two textures */ glPixelZoom((float)width/(float)w, (float)height/(float)h); - glRasterPos2f(0, dy); + glRasterPos2f(dx, dy); uint8_t *pixels = (uint8_t*)rgba.data_pointer; -- cgit v1.2.3 From 662746fdd43499feeaf59c5aeb65f5380a5e6ffb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 18 May 2015 11:50:36 +1000 Subject: Fix multi-drag & multi-select, Alt press mid-drag This would enable multi-value-editing in the middle of the drag action. --- source/blender/editors/interface/interface_handlers.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 9db6ce77d76..11254ec0e3f 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1911,6 +1911,12 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton } #ifdef USE_ALLSELECT +# ifdef USE_DRAG_MULTINUM + if (but->flag & UI_BUT_DRAG_MULTI) { + /* pass */ + } + else +# endif if (data->select_others.elems_len == 0) { wmWindow *win = CTX_wm_window(C); /* may have been enabled before activating */ -- cgit v1.2.3 From 924f31e54f59e13007b75f9388ef4bd089f847b2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 18 May 2015 13:42:47 +1000 Subject: Fix T44543: painted texture lost after first save Fix for T36639 caused all path changes to reload (which could loose user content). Change behavior: - Only reload data when a flag is explicitly passed (currently only used by Find Files operator) - Don't reload images which have been painted onto and not saved (dirty flag set). --- source/blender/blenkernel/BKE_bpath.h | 22 +++++++++++++++------- source/blender/blenkernel/intern/bpath.c | 14 ++++++++++---- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/BKE_bpath.h b/source/blender/blenkernel/BKE_bpath.h index 990b414a4cf..10ee504f244 100644 --- a/source/blender/blenkernel/BKE_bpath.h +++ b/source/blender/blenkernel/BKE_bpath.h @@ -48,13 +48,21 @@ void *BKE_bpath_list_backup(struct Main *bmain, const int flag); void BKE_bpath_list_restore(struct Main *bmain, const int flag, void *ls_handle); void BKE_bpath_list_free(void *ls_handle); -#define BKE_BPATH_TRAVERSE_ABS (1 << 0) /* convert paths to absolute */ -#define BKE_BPATH_TRAVERSE_SKIP_LIBRARY (1 << 2) /* skip library paths */ -#define BKE_BPATH_TRAVERSE_SKIP_PACKED (1 << 3) /* skip packed data */ -#define BKE_BPATH_TRAVERSE_SKIP_MULTIFILE (1 << 4) /* skip paths where a single dir is used with an array of files, eg. - * sequence strip images and pointcache. in this case only use the first - * file, this is needed for directory manipulation functions which might - * otherwise modify the same directory multiple times */ +enum { + /* convert paths to absolute */ + BKE_BPATH_TRAVERSE_ABS = (1 << 0), + /* skip library paths */ + BKE_BPATH_TRAVERSE_SKIP_LIBRARY = (1 << 1), + /* skip packed data */ + BKE_BPATH_TRAVERSE_SKIP_PACKED = (1 << 2), + /* skip paths where a single dir is used with an array of files, eg. + * sequence strip images and pointcache. in this case only use the first + * file, this is needed for directory manipulation functions which might + * otherwise modify the same directory multiple times */ + BKE_BPATH_TRAVERSE_SKIP_MULTIFILE = (1 << 3), + /* reload data (when the path is edited) */ + BKE_BPATH_TRAVERSE_RELOAD_EDITED = (1 << 4), +}; /* high level funcs */ diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 265cb0aa403..76544e5ed42 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -322,13 +322,14 @@ void BKE_bpath_missing_files_find(Main *bmain, const char *searchpath, ReportLis const bool find_all) { struct BPathFind_Data data = {NULL}; + const int flag = BKE_BPATH_TRAVERSE_ABS | BKE_BPATH_TRAVERSE_RELOAD_EDITED; data.basedir = bmain->name; data.reports = reports; data.searchdir = searchpath; data.find_all = find_all; - BKE_bpath_traverse_main(bmain, missing_files_find__visit_cb, BKE_BPATH_TRAVERSE_ABS, (void *)&data); + BKE_bpath_traverse_main(bmain, missing_files_find__visit_cb, flag, (void *)&data); } /* Run a visitor on a string, replacing the contents of the string as needed. */ @@ -435,9 +436,14 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int if (BKE_image_has_packedfile(ima) == false || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) { if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { if (rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data)) { - if (!BKE_image_has_packedfile(ima)) { - BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); - BKE_image_walk_all_users(bmain, ima, bpath_traverse_image_user_cb); + if (flag & BKE_BPATH_TRAVERSE_RELOAD_EDITED) { + if (!BKE_image_has_packedfile(ima) && + /* image may have been painted onto (and not saved, T44543) */ + !BKE_image_is_dirty(ima)) + { + BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); + BKE_image_walk_all_users(bmain, ima, bpath_traverse_image_user_cb); + } } } } -- cgit v1.2.3 From 3dfce097e49b8dd443ecd364ff57d5fadc4a2c8c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 18 May 2015 16:26:45 +1000 Subject: Cleanup: use const for Imbuf file types --- source/blender/imbuf/intern/IMB_filetype.h | 6 +++--- source/blender/imbuf/intern/colormanagement.c | 4 ++-- source/blender/imbuf/intern/filetype.c | 12 ++++++------ source/blender/imbuf/intern/readimage.c | 6 +++--- source/blender/imbuf/intern/util.c | 4 ++-- source/blender/imbuf/intern/writeimage.c | 4 ++-- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h index 0e6438fb729..332878b6067 100644 --- a/source/blender/imbuf/intern/IMB_filetype.h +++ b/source/blender/imbuf/intern/IMB_filetype.h @@ -40,7 +40,7 @@ typedef struct ImFileType { int (*is_a)(unsigned char *buf); int (*is_a_filepath)(const char *name); - int (*ftype)(struct ImFileType *type, struct ImBuf *ibuf); + int (*ftype)(const struct ImFileType *type, struct ImBuf *ibuf); struct ImBuf *(*load)(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); struct ImBuf *(*load_filepath)(const char *name, int flags, char colorspace[IM_MAX_SPACE]); int (*save)(struct ImBuf *ibuf, const char *name, int flags); @@ -51,8 +51,8 @@ typedef struct ImFileType { int default_save_role; } ImFileType; -extern ImFileType IMB_FILE_TYPES[]; -extern ImFileType *IMB_FILE_TYPES_LAST; +extern const ImFileType IMB_FILE_TYPES[]; +extern const ImFileType *IMB_FILE_TYPES_LAST; void imb_filetypes_init(void); void imb_filetypes_exit(void); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index d6fdcad0819..a2f89ec4cbe 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1948,7 +1948,7 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, bool save_as_render, boo if (do_colormanagement) { bool make_byte = false; - ImFileType *type; + const ImFileType *type; /* for proper check whether byte buffer is required by a format or not * should be pretty safe since this image buffer is supposed to be used for @@ -2457,7 +2457,7 @@ const char *IMB_colormanagement_colorspace_get_indexed_name(int index) void IMB_colormanagment_colorspace_from_ibuf_ftype(ColorManagedColorspaceSettings *colorspace_settings, ImBuf *ibuf) { - ImFileType *type; + const ImFileType *type; for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { if (type->save && type->ftype(type, ibuf)) { diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c index c6e358dd3d2..e58cda07ecf 100644 --- a/source/blender/imbuf/intern/filetype.c +++ b/source/blender/imbuf/intern/filetype.c @@ -51,17 +51,17 @@ #include "quicktime_import.h" #endif -static int imb_ftype_default(ImFileType *type, ImBuf *ibuf) +static int imb_ftype_default(const ImFileType *type, ImBuf *ibuf) { return (ibuf->ftype & type->filetype); } -static int imb_ftype_iris(ImFileType *type, ImBuf *ibuf) +static int imb_ftype_iris(const ImFileType *type, ImBuf *ibuf) { (void)type; return (ibuf->ftype == IMAGIC); } -ImFileType IMB_FILE_TYPES[] = { +const ImFileType IMB_FILE_TYPES[] = { {NULL, NULL, imb_is_a_jpeg, NULL, imb_ftype_default, imb_load_jpeg, NULL, imb_savejpeg, NULL, 0, JPG, COLOR_ROLE_DEFAULT_BYTE}, {NULL, NULL, imb_is_a_png, NULL, imb_ftype_default, imb_loadpng, NULL, imb_savepng, NULL, 0, PNG, COLOR_ROLE_DEFAULT_BYTE}, {NULL, NULL, imb_is_a_bmp, NULL, imb_ftype_default, imb_bmp_decode, NULL, imb_savebmp, NULL, 0, BMP, COLOR_ROLE_DEFAULT_BYTE}, @@ -92,11 +92,11 @@ ImFileType IMB_FILE_TYPES[] = { {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0} }; -ImFileType *IMB_FILE_TYPES_LAST = &IMB_FILE_TYPES[sizeof(IMB_FILE_TYPES) / sizeof(ImFileType) - 1]; +const ImFileType *IMB_FILE_TYPES_LAST = &IMB_FILE_TYPES[sizeof(IMB_FILE_TYPES) / sizeof(ImFileType) - 1]; void imb_filetypes_init(void) { - ImFileType *type; + const ImFileType *type; for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) if (type->init) @@ -109,7 +109,7 @@ void imb_filetypes_init(void) void imb_filetypes_exit(void) { - ImFileType *type; + const ImFileType *type; for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) if (type->exit) diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index bb09c57d1e5..3cf123fbc28 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -103,7 +103,7 @@ static void imb_handle_alpha(ImBuf *ibuf, int flags, char colorspace[IM_MAX_SPAC ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE], const char *descr) { ImBuf *ibuf; - ImFileType *type; + const ImFileType *type; char effective_colorspace[IM_MAX_SPACE] = ""; if (mem == NULL) { @@ -133,7 +133,7 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co static ImBuf *IMB_ibImageFromFile(const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr) { ImBuf *ibuf; - ImFileType *type; + const ImFileType *type; char effective_colorspace[IM_MAX_SPACE] = ""; if (colorspace) @@ -257,7 +257,7 @@ ImBuf *IMB_testiffname(const char *filepath, int flags) static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int *rect) { - ImFileType *type; + const ImFileType *type; unsigned char *mem; size_t size; diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index 3fee6688014..77962d43470 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -186,7 +186,7 @@ int IMB_ispic_type(const char *name) #define HEADER_SIZE 64 unsigned char buf[HEADER_SIZE]; - ImFileType *type; + const ImFileType *type; BLI_stat_t st; int fp; @@ -442,7 +442,7 @@ bool IMB_isanim(const char *filename) bool IMB_isfloat(ImBuf *ibuf) { - ImFileType *type; + const ImFileType *type; for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { if (type->ftype(type, ibuf)) { diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c index 5e9ccf4437e..2f688803804 100644 --- a/source/blender/imbuf/intern/writeimage.c +++ b/source/blender/imbuf/intern/writeimage.c @@ -41,14 +41,14 @@ #include "IMB_colormanagement.h" #include "IMB_colormanagement_intern.h" -static ImBuf *prepare_write_imbuf(ImFileType *type, ImBuf *ibuf) +static ImBuf *prepare_write_imbuf(const ImFileType *type, ImBuf *ibuf) { return IMB_prepare_write_ImBuf((type->flag & IM_FTYPE_FLOAT), ibuf); } short IMB_saveiff(struct ImBuf *ibuf, const char *name, int flags) { - ImFileType *type; + const ImFileType *type; if (ibuf == NULL) return (false); ibuf->flags = flags; -- cgit v1.2.3 From 5dfe88adbaeec63ede5c76dd84457e240f2fb602 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 18 May 2015 18:22:31 +1000 Subject: Fix T44553: Dyntopo ignores front-face option When 'Front Faces' brush option was enabled, dyntop would still adjust detail on back-faces. --- source/blender/blenkernel/BKE_pbvh.h | 6 ++- source/blender/blenkernel/intern/pbvh_bmesh.c | 62 ++++++++++++++++++++++++--- source/blender/editors/sculpt_paint/sculpt.c | 13 ++++-- 3 files changed, 70 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 1df633cc966..c7ef53589aa 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -145,8 +145,10 @@ typedef enum { PBVH_Subdivide = 1, PBVH_Collapse = 2, } PBVHTopologyUpdateMode; -bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, - const float center[3], float radius); +bool BKE_pbvh_bmesh_update_topology( + PBVH *bvh, PBVHTopologyUpdateMode mode, + const float center[3], const float view_normal[3], + float radius); /* Node Access */ diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index e631a4a365d..9f092bd651f 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -48,6 +48,9 @@ # include "BKE_global.h" #endif +/* Support for only operating on front-faces */ +#define USE_EDGEQUEUE_FRONTFACE + /* don't add edges into the queue multiple times */ #define USE_EDGEQUEUE_TAG /** @@ -598,6 +601,12 @@ typedef struct { #ifdef USE_EDGEQUEUE_EVEN_SUBDIV float limit_len; #endif + +#ifdef USE_EDGEQUEUE_FRONTFACE + const float *view_normal; + unsigned int use_view_normal : 1; +#endif + } EdgeQueue; typedef struct { @@ -719,6 +728,14 @@ static void long_edge_queue_edge_add_recursive( { BLI_assert(len_sq > SQUARE(limit_len)); +#ifdef USE_EDGEQUEUE_FRONTFACE + if (eq_ctx->q->use_view_normal) { + if (dot_v3v3(l_edge->f->no, eq_ctx->q->view_normal) < 0.0f) { + return; + } + } +#endif + #ifdef USE_EDGEQUEUE_TAG if (EDGE_QUEUE_TEST(l_edge->e) == false) #endif @@ -787,6 +804,14 @@ static void long_edge_queue_face_add( EdgeQueueContext *eq_ctx, BMFace *f) { +#ifdef USE_EDGEQUEUE_FRONTFACE + if (eq_ctx->q->use_view_normal) { + if (dot_v3v3(f->no, eq_ctx->q->view_normal) < 0.0f) { + return; + } + } +#endif + if (edge_queue_tri_in_sphere(eq_ctx->q, f)) { BMLoop *l_iter; BMLoop *l_first; @@ -814,6 +839,14 @@ static void short_edge_queue_face_add( EdgeQueueContext *eq_ctx, BMFace *f) { +#ifdef USE_EDGEQUEUE_FRONTFACE + if (eq_ctx->q->use_view_normal) { + if (dot_v3v3(f->no, eq_ctx->q->view_normal) < 0.0f) { + return; + } + } +#endif + if (edge_queue_tri_in_sphere(eq_ctx->q, f)) { BMLoop *l_iter; BMLoop *l_first; @@ -837,7 +870,7 @@ static void short_edge_queue_face_add( */ static void long_edge_queue_create( EdgeQueueContext *eq_ctx, - PBVH *bvh, const float center[3], + PBVH *bvh, const float center[3], const float view_normal[3], float radius) { int n; @@ -850,6 +883,13 @@ static void long_edge_queue_create( eq_ctx->q->limit_len = bvh->bm_max_edge_len; #endif +#ifdef USE_EDGEQUEUE_FRONTFACE + eq_ctx->q->view_normal = view_normal; + eq_ctx->q->use_view_normal = (view_normal != NULL); +#else + UNUSED_VARS(view_normal); +#endif + #ifdef USE_EDGEQUEUE_TAG_VERIFY pbvh_bmesh_edge_tag_verify(bvh); #endif @@ -886,7 +926,7 @@ static void long_edge_queue_create( */ static void short_edge_queue_create( EdgeQueueContext *eq_ctx, - PBVH *bvh, const float center[3], + PBVH *bvh, const float center[3], const float view_normal[3], float radius) { int n; @@ -899,6 +939,13 @@ static void short_edge_queue_create( eq_ctx->q->limit_len = bvh->bm_min_edge_len; #endif +#ifdef USE_EDGEQUEUE_FRONTFACE + eq_ctx->q->view_normal = view_normal; + eq_ctx->q->use_view_normal = (view_normal != NULL); +#else + UNUSED_VARS(view_normal); +#endif + for (n = 0; n < bvh->totnode; n++) { PBVHNode *node = &bvh->nodes[n]; @@ -1704,7 +1751,8 @@ void BKE_pbvh_build_bmesh( /* Collapse short edges, subdivide long edges */ bool BKE_pbvh_bmesh_update_topology( PBVH *bvh, PBVHTopologyUpdateMode mode, - const float center[3], float radius) + const float center[3], const float view_normal[3], + float radius) { /* 2 is enough for edge faces - manifold edge */ BLI_buffer_declare_static(BMLoop *, edge_loops, BLI_BUFFER_NOP, 2); @@ -1716,12 +1764,16 @@ bool BKE_pbvh_bmesh_update_topology( bool modified = false; int n; + if (view_normal) { + BLI_assert(len_squared_v3(view_normal) != 0.0f); + } + if (mode & PBVH_Collapse) { EdgeQueue q; BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert *[2]), 0, 128, BLI_MEMPOOL_NOP); EdgeQueueContext eq_ctx = {&q, queue_pool, bvh->bm, cd_vert_mask_offset, cd_vert_node_offset, cd_face_node_offset}; - short_edge_queue_create(&eq_ctx, bvh, center, radius); + short_edge_queue_create(&eq_ctx, bvh, center, view_normal, radius); modified |= !BLI_heap_is_empty(q.heap); pbvh_bmesh_collapse_short_edges(&eq_ctx, bvh, &deleted_faces); @@ -1734,7 +1786,7 @@ bool BKE_pbvh_bmesh_update_topology( BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert *[2]), 0, 128, BLI_MEMPOOL_NOP); EdgeQueueContext eq_ctx = {&q, queue_pool, bvh->bm, cd_vert_mask_offset, cd_vert_node_offset, cd_face_node_offset}; - long_edge_queue_create(&eq_ctx, bvh, center, radius); + long_edge_queue_create(&eq_ctx, bvh, center, view_normal, radius); modified |= !BLI_heap_is_empty(q.heap); pbvh_bmesh_subdivide_long_edges(&eq_ctx, bvh, &edge_loops); BLI_heap_free(q.heap, NULL); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index e2403a57556..0d1ee08cc75 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -3126,9 +3126,11 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush, Unified } if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { - BKE_pbvh_bmesh_update_topology(ss->pbvh, mode, - ss->cache->location, - ss->cache->radius); + BKE_pbvh_bmesh_update_topology( + ss->pbvh, mode, + ss->cache->location, + (brush->flag & BRUSH_FRONTFACE) ? ss->cache->view_normal : NULL, + ss->cache->radius); } MEM_freeN(nodes); @@ -5167,7 +5169,10 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op)) sculpt_undo_push_begin("Dynamic topology flood fill"); sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_COORDS); - while (BKE_pbvh_bmesh_update_topology(ss->pbvh, PBVH_Collapse | PBVH_Subdivide, bb_min, size)) { + while (BKE_pbvh_bmesh_update_topology( + ss->pbvh, PBVH_Collapse | PBVH_Subdivide, + bb_min, NULL, size)) + { for (i = 0; i < totnodes; i++) BKE_pbvh_node_mark_topology_update(nodes[i]); } -- cgit v1.2.3 From bf93316c5260af54c7aa504952011810e42ab579 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 18 May 2015 12:53:06 +0200 Subject: Fix assert in outliner regarding WM and SCR ID types... --- source/blender/editors/space_outliner/outliner_intern.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 38672ef14dd..24842d20573 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -59,7 +59,8 @@ typedef struct TreeElement { #define TREESTORE_ID_TYPE(_id) \ (ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \ - ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS)) + ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS) || \ + ELEM(GS((_id)->name), ID_SCR, ID_WM)) /* Only in 'blendfile' mode ... :/ */ /* TreeElement->flag */ #define TE_ACTIVE 1 -- cgit v1.2.3 From 17388794ce0d31344944842b1f76d23921687cc4 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 18 May 2015 13:02:05 +0200 Subject: Filebrowser: Do not intent to draw empty strings, loss of time. Fixes assert raised in `UI_text_clip_middle_ex()` when trying to draw (empty) 'size' string for appended/linked blender datablocks. --- source/blender/editors/space_file/file_draw.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 3553a0ed79a..2bd92b1e207 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -295,11 +295,18 @@ static void file_draw_icon(uiBlock *block, char *path, int sx, int sy, int icon, static void file_draw_string(int sx, int sy, const char *string, float width, int height, short align) { - uiStyle *style = UI_style_get(); - uiFontStyle fs = style->widgetlabel; + uiStyle *style; + uiFontStyle fs; rcti rect; char fname[FILE_MAXFILE]; + if (string[0] == '\0') { + return; + } + + style = UI_style_get(); + fs = style->widgetlabel; + fs.align = align; BLI_strncpy(fname, string, FILE_MAXFILE); -- cgit v1.2.3 From b88597c2186689e8eaaf3cb3f5b2601b449781fe Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 18 May 2015 12:41:51 +0500 Subject: Make switching to threaded malloc safe to be called from threads For a long time this function was only intended to be used from the main thread, but since out implementation of parallel range (which is currently only used by mesh deform modifier) we might want to switch to threaded alloc from object update thread. Now we're using spinlock around the check, which makes the code safe to be used from all over the place. We might consider using a bit of atomics operations magic there, but it's not so much important for now, this code is not used in the performance critical code path. --- source/blender/blenlib/intern/threads.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index da06500565c..a404f46a6e2 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -802,10 +802,12 @@ void BLI_begin_threaded_malloc(void) /* Used for debug only */ /* BLI_assert(thread_levels >= 0); */ + BLI_spin_lock(&_malloc_lock); if (thread_levels == 0) { MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); } thread_levels++; + BLI_spin_unlock(&_malloc_lock); } void BLI_end_threaded_malloc(void) @@ -813,8 +815,10 @@ void BLI_end_threaded_malloc(void) /* Used for debug only */ /* BLI_assert(thread_levels >= 0); */ + BLI_spin_lock(&_malloc_lock); thread_levels--; if (thread_levels == 0) MEM_set_lock_callback(NULL, NULL); + BLI_spin_unlock(&_malloc_lock); } -- cgit v1.2.3 From 40091ff83aa2482db93855f53d1b4c7208a500ac Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 18 May 2015 12:44:59 +0500 Subject: Correction to early output in the parallel range implementation The used heuristic of checking the value prior to lock is not totally safe because assignment is not atomic and check might not give proper result. --- source/blender/blenlib/intern/task.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c index f442a6219a5..08d40a158ca 100644 --- a/source/blender/blenlib/intern/task.c +++ b/source/blender/blenlib/intern/task.c @@ -508,16 +508,14 @@ BLI_INLINE bool parallel_range_next_iter_get( int * __restrict iter, int * __restrict count) { bool result = false; + BLI_spin_lock(&state->lock); if (state->iter < state->stop) { - BLI_spin_lock(&state->lock); - if (state->iter < state->stop) { - *count = min_ii(state->chunk_size, state->stop - state->iter); - *iter = state->iter; - state->iter += *count; - result = true; - } - BLI_spin_unlock(&state->lock); + *count = min_ii(state->chunk_size, state->stop - state->iter); + *iter = state->iter; + state->iter += *count; + result = true; } + BLI_spin_unlock(&state->lock); return result; } -- cgit v1.2.3 From 8540907d6067eee8645f7f079c7fc103bd068573 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 18 May 2015 13:52:01 +0500 Subject: Attempt to make drivers more safe for threading There were some reported data race conditions in the python interpreter which seems to be rather valid. Surely this is not very pretty solution, but it might solve some annoying bugs related on threading. --- source/blender/blenkernel/intern/fcurve.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 413e34e72a8..322da9f1095 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -46,6 +46,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_easing.h" +#include "BLI_threads.h" #include "BLI_utildefines.h" #include "BLF_translation.h" @@ -69,6 +70,8 @@ #define SMALL -1.0e-10 #define SELECT 1 +static ThreadMutex python_driver_lock = BLI_MUTEX_INITIALIZER; + /* ************************** Data-Level Functions ************************* */ /* ---------------------- Freeing --------------------------- */ @@ -1807,7 +1810,9 @@ static float evaluate_driver(ChannelDriver *driver, const float evaltime) /* this evaluates the expression using Python, and returns its result: * - on errors it reports, then returns 0.0f */ + BLI_mutex_lock(&python_driver_lock); driver->curval = BPY_driver_exec(driver, evaltime); + BLI_mutex_unlock(&python_driver_lock); } #else /* WITH_PYTHON*/ (void)evaltime; -- cgit v1.2.3 From 61f9f508a4473e1d2bb353396717b4e1a085e646 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 18 May 2015 13:53:48 +0500 Subject: Make object material drivers evaluation thread safe Previously it was very easy to run into situation when two objects are sharing the same materials with drivers which will cause threading access issues. This actually only needed for the old depsgraph, but since it's still the one we're using by default we'd better solve this issue. --- source/blender/blenkernel/intern/object_update.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 46d68e7ccab..d9373b9595a 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -37,6 +37,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_math.h" +#include "BLI_threads.h" #include "BKE_global.h" #include "BKE_armature.h" @@ -65,6 +66,8 @@ # define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf #endif +static ThreadMutex material_lock = BLI_MUTEX_INITIALIZER; + void BKE_object_eval_local_transform(EvaluationContext *UNUSED(eval_ctx), Scene *UNUSED(scene), Object *ob) @@ -239,12 +242,16 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx, */ if (ob->totcol) { int a; - for (a = 1; a <= ob->totcol; a++) { - Material *ma = give_current_material(ob, a); - if (ma) { - /* recursively update drivers for this material */ - material_drivers_update(scene, ma, ctime); + if (ob->totcol != 0) { + BLI_mutex_lock(&material_lock); + for (a = 1; a <= ob->totcol; a++) { + Material *ma = give_current_material(ob, a); + if (ma) { + /* recursively update drivers for this material */ + material_drivers_update(scene, ma, ctime); + } } + BLI_mutex_unlock(&material_lock); } } else if (ob->type == OB_LAMP) -- cgit v1.2.3 From 45afc02f11871b5c9f4d7bc6794761c6a4d883d8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 18 May 2015 14:06:46 +0500 Subject: Solve threading conflict related on proxy group's inverse matrix It was possible that two threads will start calculating proxy group's inverted matrix and store it in the object itself. This isn't good idea because it means some threads might be using partially written matrix. --- source/blender/blenkernel/intern/object.c | 5 +++-- source/blender/blenkernel/intern/object_update.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index e04f1b19dc5..e05fc91f276 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -3031,8 +3031,9 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx, // printf("ob proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name); if (ob->proxy_from->proxy_group) { /* transform proxy into group space */ Object *obg = ob->proxy_from->proxy_group; - invert_m4_m4(obg->imat, obg->obmat); - mul_m4_m4m4(ob->obmat, obg->imat, ob->proxy_from->obmat); + float imat[4][4]; + invert_m4_m4(imat, obg->obmat); + mul_m4_m4m4(ob->obmat, imat, ob->proxy_from->obmat); if (obg->dup_group) { /* should always be true */ add_v3_v3(ob->obmat[3], obg->dup_group->dupli_ofs); } diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index d9373b9595a..483968c6bd9 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -318,8 +318,9 @@ void BKE_object_eval_uber_transform(EvaluationContext *UNUSED(eval_ctx), if (ob->proxy_from->proxy_group) { /* Transform proxy into group space. */ Object *obg = ob->proxy_from->proxy_group; - invert_m4_m4(obg->imat, obg->obmat); - mul_m4_m4m4(ob->obmat, obg->imat, ob->proxy_from->obmat); + float imat[4][4]; + invert_m4_m4(imat, obg->obmat); + mul_m4_m4m4(ob->obmat, imat, ob->proxy_from->obmat); /* Should always be true. */ if (obg->dup_group) { add_v3_v3(ob->obmat[3], obg->dup_group->dupli_ofs); -- cgit v1.2.3 From cecd1f98a4c1295421ca011ea5bec95b1c918111 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 18 May 2015 16:40:12 +0500 Subject: Fix T44752: Clip Editor doesn't respect ColorSpace setting when playback after Prefetch --- source/blender/editors/space_clip/clip_editor.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 9acb9f3effc..d67c03f3622 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -767,13 +767,15 @@ static void prefetch_task_func(TaskPool *pool, void *task_data, int UNUSED(threa int flag = IB_rect | IB_alphamode_detect; int result; char *colorspace_name = NULL; + const bool use_proxy = (clip->flag & MCLIP_USE_PROXY) && + (queue->render_size != MCLIP_PROXY_RENDER_SIZE_FULL); user.framenr = current_frame; user.render_size = queue->render_size; user.render_flag = queue->render_flag; /* Proxies are stored in the display space. */ - if (queue->render_flag & MCLIP_USE_PROXY) { + if (!use_proxy) { colorspace_name = clip->colorspace_settings.name; } -- cgit v1.2.3 From 947b756d5e8af3d056fe0a7cabc7a8e376732255 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Mon, 18 May 2015 10:57:59 -0300 Subject: Multi-View: small cleranup/refactor with RE_pass_find_by_type and RE_RenderLayerGetPass --- source/blender/render/extern/include/RE_pipeline.h | 2 +- source/blender/render/intern/source/pipeline.c | 33 ++++++++-------------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 2df4cde2b27..9331c45237d 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -321,7 +321,7 @@ int RE_seq_render_active(struct Scene *scene, struct RenderData *rd); bool RE_layers_have_name(struct RenderResult *result); -struct RenderPass *RE_pass_find_by_type(struct RenderLayer *rl, int passtype, const char *viewname); +struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname); /* shaded view or baking options */ #define RE_BAKE_LIGHT 0 /* not listed in rna_scene.c -> can't be enabled! */ diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 9407412a6d0..64ed8f1153a 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -195,21 +195,8 @@ void RE_FreeRenderResult(RenderResult *res) float *RE_RenderLayerGetPass(volatile RenderLayer *rl, int passtype, const char *viewname) { - RenderPass *rpass; - float *rect = NULL; - - for (rpass = rl->passes.last; rpass; rpass = rpass->prev) { - if (rpass->passtype == passtype) { - rect = rpass->rect; - - if (viewname == NULL) - break; - else if (STREQ(rpass->view, viewname)) - break; - } - } - - return rect; + RenderPass *rpass = RE_pass_find_by_type(rl, passtype, viewname); + return rpass ? rpass->rect : NULL; } RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name) @@ -3893,14 +3880,18 @@ bool RE_layers_have_name(struct RenderResult *rr) return false; } -RenderPass *RE_pass_find_by_type(RenderLayer *rl, int passtype, const char *viewname) +RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const char *viewname) { - RenderPass *rp; - for (rp = rl->passes.first; rp; rp = rp->next) { + RenderPass *rp = NULL; + + for (rp = rl->passes.last; rp; rp = rp->prev) { if (rp->passtype == passtype) { - if (STREQ(rp->view, viewname)) - return rp; + + if (viewname == NULL) + break; + else if (STREQ(rp->view, viewname)) + break; } } - return NULL; + return rp; } -- cgit v1.2.3 From 5fa0b8778bba85261526f818f392a95bc3035a1a Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Mon, 18 May 2015 18:10:03 +0200 Subject: BGE: Set default envMap resolution to 512 pixels I propose to change the environment map render default resolution (600) to 512 (Thanks brecht for the correction... I don't know why I said dpi) (to make it compatible with this script: http://en.wikibooks.org/wiki/GLSL_Pr...cting_Surfaces ) to make cubeMap reflections easier and avoid this error: invalid envmap size please render with CubeRes @ power of two unable to initialize image(0) in MAMaterial, image will not be available http://blenderartists.org/forum/showthread.php?371232-BGE-proposal-Set-default-envMap-resolution-to-512-dpi http://blenderartists.org/forum/showthread.php?370026-Problem-with-cube-map-textures (post 11) Author : youle (Ulysse MARTIN) Reviewers: hg1, agoose77, lordloki, moguri, panzergame, dfelinto Reviewed By: panzergame, dfelinto Subscribers: brecht Projects: #game_engine Differential Revision: https://developer.blender.org/D1306 --- source/blender/blenkernel/intern/texture.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 246e3f2a316..2ea903247b2 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -629,7 +629,7 @@ void BKE_texture_default(Tex *tex) tex->env->stype = ENV_ANIM; tex->env->clipsta = 0.1; tex->env->clipend = 100; - tex->env->cuberes = 600; + tex->env->cuberes = 512; tex->env->depth = 0; } @@ -1423,7 +1423,7 @@ EnvMap *BKE_texture_envmap_add(void) env->stype = ENV_ANIM; env->clipsta = 0.1; env->clipend = 100.0; - env->cuberes = 600; + env->cuberes = 512; env->viewscale = 0.5; return env; -- cgit v1.2.3 From 192fddb324222c0ac9b38f9c8c2e3450f7f487ae Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Mon, 18 May 2015 18:52:45 +0200 Subject: BGE: Fix blenderplayer bad call stubs not updated. Please (dfelinto) compile the bge to avoid these kind of problems. --- source/blenderplayer/bad_level_call_stubs/stubs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 8e26a9e5b78..f1cb2358582 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -95,6 +95,7 @@ struct ScrArea; struct SculptSession; struct ShadeInput; struct ShadeResult; +struct SpaceButs; struct SpaceClip; struct SpaceImage; struct SpaceNode; @@ -233,7 +234,7 @@ void RE_engine_get_camera_model_matrix(struct RenderEngine *engine, struct Objec float RE_engine_get_camera_shift_x(struct RenderEngine *engine, struct Object *camera) RET_ZERO void RE_SetActiveRenderView(struct Render *re, const char *viewname) {STUB_ASSERT(0);} -struct RenderPass *RE_pass_find_by_type(struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL +struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL bool RE_HasFakeLayer(RenderResult *res) RET_ZERO /* zbuf.c stub */ -- cgit v1.2.3 From 598c2dffe92f5a5deea5d2da97c405f93f7941a4 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 18 May 2015 21:29:57 +0200 Subject: Fix T44708: UI label should use plural Just to keep commit ratio up while being busy preparing for final exams ;) --- release/scripts/startup/bl_ui/properties_render_layer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/properties_render_layer.py b/release/scripts/startup/bl_ui/properties_render_layer.py index b23892df408..8b26d82b28a 100644 --- a/release/scripts/startup/bl_ui/properties_render_layer.py +++ b/release/scripts/startup/bl_ui/properties_render_layer.py @@ -87,7 +87,7 @@ class RENDERLAYER_PT_layer_options(RenderLayerButtonsPanel, Panel): col = split.column() col.prop(scene, "layers", text="Scene") col.label(text="") - col.prop(rl, "light_override", text="Light") + col.prop(rl, "light_override", text="Lights") col.prop(rl, "material_override", text="Material") col = split.column() -- cgit v1.2.3 From 65328fadc3c63c73d5c2e2e977de3dad5bd74219 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 18 May 2015 22:05:38 +0200 Subject: Final solution for Intel card Ambient Occlusion in T43987. Forgot to account for offscreen case in addition to compositing --- source/blender/gpu/intern/gpu_compositing.c | 2 +- source/blender/gpu/intern/gpu_extensions.c | 21 +++++++-------------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index bf3d1753888..2bafee0fb52 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -724,7 +724,7 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str sample_params[1] = fx->gbuffer_dim[0] / 64.0; sample_params[2] = fx->gbuffer_dim[1] / 64.0; - ssao_params[3] = (passes_left == 1) ? dfdyfac[0] : dfdyfac[1]; + ssao_params[3] = (passes_left == 1 && !ofs) ? dfdyfac[0] : dfdyfac[1]; ssao_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_params"); ssao_color_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_color"); diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 976a65aff7c..0fcdd87a1ff 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -263,20 +263,13 @@ void gpu_extensions_init(void) GG.dfdyfactors[0] = 1.0; GG.dfdyfactors[1] = -1.0; } - else if (GG.device == GPU_DEVICE_INTEL && GG.os == GPU_OS_WIN) { - if (strstr(version, "4.0.0 - Build 9.18.10.3165")) - { - GG.dfdyfactors[0] = -1.0; - GG.dfdyfactors[1] = 1.0; - } - else if (strstr(version, "3.1.0 - Build 9.17.10.4101")) { - GG.dfdyfactors[0] = -1.0; - GG.dfdyfactors[1] = -1.0; - } - else { - GG.dfdyfactors[0] = 1.0; - GG.dfdyfactors[1] = 1.0; - } + else if (GG.device == GPU_DEVICE_INTEL && GG.os == GPU_OS_WIN && + (strstr(version, "4.0.0 - Build 9.18.10.3165") || + strstr(version, "3.1.0 - Build 9.17.10.3347") || + strstr(version, "3.1.0 - Build 9.17.10.4101"))) + { + GG.dfdyfactors[0] = -1.0; + GG.dfdyfactors[1] = 1.0; } else { GG.dfdyfactors[0] = 1.0; -- cgit v1.2.3 From 183b6437744f69bbeadf503f791f763f3c7c4a6f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 May 2015 11:34:52 +1000 Subject: Building without Python works again --- source/blender/blenfont/CMakeLists.txt | 9 +++++++-- source/blender/blenfont/SConscript | 5 ++++- source/blender/blenfont/intern/blf_translation.c | 4 ++++ source/blender/blenkernel/intern/fcurve.c | 2 ++ source/blender/windowmanager/intern/wm_keymap.c | 4 ++++ 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt index 2f10c3580e0..059e2cac680 100644 --- a/source/blender/blenfont/CMakeLists.txt +++ b/source/blender/blenfont/CMakeLists.txt @@ -29,7 +29,6 @@ set(INC ../gpu ../makesdna ../makesrna - ../python ../imbuf ../../../intern/guardedalloc ../../../intern/glew-mx @@ -67,7 +66,13 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() +if(WITH_PYTHON) + add_definitions(-DWITH_PYTHON) + list(APPEND INC + ../python + ) +endif() + add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_blenfont "${SRC}" "${INC}" "${INC_SYS}") - diff --git a/source/blender/blenfont/SConscript b/source/blender/blenfont/SConscript index b6cf052a980..61d2ca9b12d 100644 --- a/source/blender/blenfont/SConscript +++ b/source/blender/blenfont/SConscript @@ -44,7 +44,6 @@ incs = [ '../imbuf', '../makesdna', '../makesrna', - '../python', ] incs.extend(Split(env['BF_FREETYPE_INC'])) @@ -57,6 +56,10 @@ if sys.platform == 'win32' or env['OURPLATFORM'] == 'linuxcross': if env['WITH_BF_INTERNATIONAL']: defs.append('WITH_INTERNATIONAL') +if env['WITH_BF_PYTHON']: + defs.append('WITH_PYTHON') + incs.append('../python') + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): incs.append(env['BF_PTHREADS_INC']) diff --git a/source/blender/blenfont/intern/blf_translation.c b/source/blender/blenfont/intern/blf_translation.c index 25464864657..5d828d9b7be 100644 --- a/source/blender/blenfont/intern/blf_translation.c +++ b/source/blender/blenfont/intern/blf_translation.c @@ -46,7 +46,9 @@ #include "DNA_userdef_types.h" /* For user settings. */ +#ifdef WITH_PYTHON #include "BPY_extern.h" +#endif #ifdef WITH_INTERNATIONAL @@ -152,9 +154,11 @@ const char *BLF_pgettext(const char *msgctxt, const char *msgid) /* We assume if the returned string is the same (memory level) as the msgid, no translation was found, * and we can try py scripts' ones! */ +#ifdef WITH_PYTHON if (ret == msgid) { ret = BPY_app_translations_py_pgettext(msgctxt, msgid); } +#endif } return ret; diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 322da9f1095..6e58513e38e 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -70,7 +70,9 @@ #define SMALL -1.0e-10 #define SELECT 1 +#ifdef WITH_PYTHON static ThreadMutex python_driver_lock = BLI_MUTEX_INITIALIZER; +#endif /* ************************** Data-Level Functions ************************* */ diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index c765587b7cb..45177903cce 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -990,10 +990,12 @@ static wmKeyMapItem *wm_keymap_item_find_handlers( "this might not be desired!\n", opname); printf("\tkm: '%s', kmi: '%s'\n", keymap->idname, kmi_str); #ifndef NDEBUG +#ifdef WITH_PYTHON printf("OPERATOR\n"); IDP_spit(properties); printf("KEYMAP\n"); IDP_spit(kmi->ptr->data); +#endif #endif printf("\n"); } @@ -1137,10 +1139,12 @@ static wmKeyMapItem *wm_keymap_item_find( "this might not be desired!\n", opname); printf("\tkm: '%s', kmi: '%s'\n", km->idname, kmi_str); #ifndef NDEBUG +#ifdef WITH_PYTHON printf("OPERATOR\n"); IDP_spit(properties); printf("KEYMAP\n"); IDP_spit(kmi->ptr->data); +#endif #endif printf("\n"); } -- cgit v1.2.3 From 3d70a04a8ae439560795e4b3e530585841798b9d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 May 2015 16:26:03 +1000 Subject: CMake: remove temp assignment, unused vars --- CMakeLists.txt | 1 - build_files/cmake/packaging.cmake | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a8b32b4dc0f..9d41c4975a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,7 +197,6 @@ option(WITH_PYTHON "Enable Embedded Python API (only disable for develop option(WITH_PYTHON_SECURITY "Disables execution of scripts within blend files by default" ON) mark_as_advanced(WITH_PYTHON) # dont want people disabling this unless they really know what they are doing. mark_as_advanced(WITH_PYTHON_SECURITY) # some distributions see this as a security issue, rather than have them patch it, make a build option. -set(WITH_PYTHON_SECURITY ON CACHE BOOL "ON" FORCE) # temp force on. option(WITH_PYTHON_SAFETY "Enable internal API error checking to track invalid data to prevent crash on access (at the expense of some effeciency, only enable for development)." OFF) mark_as_advanced(WITH_PYTHON_SAFETY) diff --git a/build_files/cmake/packaging.cmake b/build_files/cmake/packaging.cmake index f0dd0482d4d..0cb13e0fc66 100644 --- a/build_files/cmake/packaging.cmake +++ b/build_files/cmake/packaging.cmake @@ -112,3 +112,9 @@ elseif(UNIX) "tar.bz2") endif() +unset(MAJOR_VERSION) +unset(MINOR_VERSION) +unset(PATCH_VERSION) + +unset(BUILD_REV) + -- cgit v1.2.3 From d5a85f87b0bab4476dc4e0e945444262fd5d3ff9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 May 2015 15:55:31 +1000 Subject: Python: search for 'python' and 'python#.#' --- source/blender/blenkernel/intern/appdir.c | 34 +++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index e4ed8c3ef73..3f69618b591 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -607,30 +607,42 @@ bool BKE_appdir_program_python_search( const int version_major, const int version_minor) { const char *basename = "python"; + char python_ver[16]; + /* check both possible names */ + const char *python_names[] = {basename, python_ver}; + int i; + bool is_found = false; + BLI_snprintf(python_ver, sizeof(python_ver), "%s%d.%d", basename, version_major, version_minor); + { const char *python_bin_dir = BKE_appdir_folder_id(BLENDER_SYSTEM_PYTHON, "bin"); if (python_bin_dir) { - BLI_join_dirfile(fullpath, fullpath_len, python_bin_dir, basename); - if ( + + for (i = 0; i < ARRAY_SIZE(python_names); i++) { + BLI_join_dirfile(fullpath, fullpath_len, python_bin_dir, python_names[i]); + + if ( #ifdef _WIN32 - BLI_path_program_extensions_add_win32(fullpath, fullpath_len) + BLI_path_program_extensions_add_win32(fullpath, fullpath_len) #else - BLI_exists(fullpath) + BLI_exists(fullpath) #endif - ) - { - is_found = true; + ) + { + is_found = true; + } } } } if (is_found == false) { - char python_ver[16]; - BLI_snprintf(python_ver, sizeof(python_ver), "%s%d.%d", basename, version_major, version_minor); - if (BLI_path_program_search(fullpath, fullpath_len, python_ver)) { - is_found = true; + for (i = 0; i < ARRAY_SIZE(python_names); i++) { + if (BLI_path_program_search(fullpath, fullpath_len, python_names[i])) { + is_found = true; + break; + } } } -- cgit v1.2.3 From e698299e4f2aade0f526dbeb5ea9f7a3a5117527 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 May 2015 15:56:28 +1000 Subject: CMake: install Python executable when its bundled --- CMakeLists.txt | 4 +-- build_files/cmake/Modules/FindPythonLibsUnix.cmake | 35 +++++++++++++++------- source/creator/CMakeLists.txt | 6 ++++ 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d41c4975a4..176d13b86af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1844,14 +1844,14 @@ elseif(APPLE) if(NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK) # normally cached but not since we include them with blender set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}m") - # set(PYTHON_BINARY "${LIBDIR}/python/bin/python${PYTHON_VERSION}") # not used yet + # set(PYTHON_EXECUTABLE "${LIBDIR}/python/bin/python${PYTHON_VERSION}") # not used yet set(PYTHON_LIBRARY python${PYTHON_VERSION}m) set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}") # set(PYTHON_LINKFLAGS "-u _PyMac_Error") # won't build with this enabled else() # module must be compiled against Python framework set(PYTHON_INCLUDE_DIR "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/include/python${PYTHON_VERSION}m") - set(PYTHON_BINARY "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/bin/python${PYTHON_VERSION}") + set(PYTHON_EXECUTABLE "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/bin/python${PYTHON_VERSION}") #set(PYTHON_LIBRARY python${PYTHON_VERSION}) set(PYTHON_LIBPATH "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/lib/python${PYTHON_VERSION}/config-${PYTHON_VERSION}m") #set(PYTHON_LINKFLAGS "-u _PyMac_Error -framework Python") # won't build with this enabled diff --git a/build_files/cmake/Modules/FindPythonLibsUnix.cmake b/build_files/cmake/Modules/FindPythonLibsUnix.cmake index 555ca4cf0a0..e4236fb4c24 100644 --- a/build_files/cmake/Modules/FindPythonLibsUnix.cmake +++ b/build_files/cmake/Modules/FindPythonLibsUnix.cmake @@ -66,6 +66,14 @@ IF(DEFINED PYTHON_LIBPATH) SET(_IS_LIB_PATH_DEF ON) ENDIF() +STRING(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) + +SET(_python_SEARCH_DIRS + ${PYTHON_ROOT_DIR} + "$ENV{HOME}/py${_PYTHON_VERSION_NO_DOTS}" + "/opt/py${_PYTHON_VERSION_NO_DOTS}" + "/opt/lib/python-${PYTHON_VERSION}" +) # only search for the dirs if we havn't already IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_LIB_PATH_DEF)) @@ -75,14 +83,7 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_ "dm;dmu;du;d" # debug ) - STRING(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) - SET(_python_SEARCH_DIRS - ${PYTHON_ROOT_DIR} - "$ENV{HOME}/py${_PYTHON_VERSION_NO_DOTS}" - "/opt/py${_PYTHON_VERSION_NO_DOTS}" - "/opt/lib/python-${PYTHON_VERSION}" - ) FOREACH(_CURRENT_ABI_FLAGS ${_python_ABI_FLAGS}) #IF(CMAKE_BUILD_TYPE STREQUAL Debug) @@ -147,6 +148,7 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_ ENDIF() IF(PYTHON_LIBRARY AND PYTHON_LIBPATH AND PYTHON_INCLUDE_DIR AND PYTHON_INCLUDE_CONFIG_DIR) + SET(_PYTHON_ABI_FLAGS "${_CURRENT_ABI_FLAGS}") break() ELSE() # ensure we dont find values from 2 different ABI versions @@ -169,7 +171,6 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_ UNSET(_CURRENT_PATH) UNSET(_python_ABI_FLAGS) - UNSET(_python_SEARCH_DIRS) ENDIF() UNSET(_IS_INC_DEF) @@ -201,14 +202,28 @@ IF(PYTHONLIBSUNIX_FOUND) # XXX No more valid with debian-like py3.4 packages... # GET_FILENAME_COMPONENT(PYTHON_LIBPATH ${PYTHON_LIBRARY} PATH) - # not used - # SET(PYTHON_BINARY ${PYTHON_EXECUTABLE} CACHE STRING "") + # not required for build, just used when bundling Python. + FIND_PROGRAM( + PYTHON_EXECUTABLE + NAMES + "python${PYTHON_VERSION}${_PYTHON_ABI_FLAGS}" + "python${PYTHON_VERSION}" + "python" + HINTS + ${_python_SEARCH_DIRS} + PATH_SUFFIXES bin + ) ENDIF() +UNSET(_PYTHON_VERSION_NO_DOTS) +UNSET(_PYTHON_ABI_FLAGS) +UNSET(_python_SEARCH_DIRS) + MARK_AS_ADVANCED( PYTHON_INCLUDE_DIR PYTHON_INCLUDE_CONFIG_DIR PYTHON_LIBRARY PYTHON_LIBPATH PYTHON_SITE_PACKAGES + PYTHON_EXECUTABLE ) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index ffaf6f42b18..5e0288ea3d6 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -494,6 +494,12 @@ if(UNIX AND NOT APPLE) if(WITH_PYTHON) if(WITH_PYTHON_INSTALL) + + install( + FILES ${PYTHON_EXECUTABLE} + DESTINATION ${TARGETDIR_VER}/python/bin + ) + # on some platforms (like openSUSE) Python is linked # to be used from lib64 folder. # determine this from Python's libraries path -- cgit v1.2.3 From ddb1a068e99c7abf086202d01a3114d8147cb3a9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 May 2015 16:17:49 +1000 Subject: SCons: install Python executable when its bundled --- build_files/scons/tools/Blender.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py index ecf34759033..16bb19b59cd 100644 --- a/build_files/scons/tools/Blender.py +++ b/build_files/scons/tools/Blender.py @@ -843,6 +843,7 @@ def UnixPyBundle(target=None, source=None, env=None): py_src = env.subst( env['BF_PYTHON_LIBPATH'] + '/python'+env['BF_PYTHON_VERSION'] ) py_target = env.subst( dir + '/python/' + target_lib + '/python'+env['BF_PYTHON_VERSION'] ) + py_target_bin = env.subst(dir + '/python/bin') # This is a bit weak, but dont install if its been installed before, makes rebuilds quite slow. if os.path.exists(py_target): @@ -862,6 +863,11 @@ def UnixPyBundle(target=None, source=None, env=None): except: pass + # install the executable + run("rm -rf '%s'" % py_target_bin) + os.makedirs(py_target_bin) + run("cp '%s' '%s'" % (env.subst(env['BF_PYTHON_BINARY']), py_target_bin)) + run("cp -R '%s' '%s'" % (py_src, os.path.dirname(py_target))) run("rm -rf '%s/distutils'" % py_target) run("rm -rf '%s/lib2to3'" % py_target) -- cgit v1.2.3 From f868be62950c06ad348d8326f9cbd6d6c285bfcb Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 19 May 2015 12:28:49 +0500 Subject: Cycles: Check for whether update/write callbacks are set prior to calling them This changes the progressive refine part, regular update was already checking for whether callbacks are set. --- intern/cycles/render/session.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 7b329af008d..275de4d15d8 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -928,10 +928,14 @@ bool Session::update_progressive_refine(bool cancel) rtile.buffers = buffers; rtile.sample = sample; - if(write) - write_render_tile_cb(rtile); - else - update_render_tile_cb(rtile); + if(write) { + if(write_render_tile_cb) + write_render_tile_cb(rtile); + } + else { + if(update_render_tile_cb) + update_render_tile_cb(rtile); + } } } -- cgit v1.2.3 From da34136de1093e7da9bc10881d11e2f553f4d8d0 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 19 May 2015 12:31:37 +0500 Subject: Cycles: Check for validity of the tiles arrays in progressive refine In certain configurations (for example when start resolution is set to small value for background render and progressive refine enabled) number of tiles might change in the tile manager. This situation will confuse progressive refine feature and likely cause crash. We might also add some settings verification in the session constructor, but having an assert with brief explanation about what's wrong should already be much better than nothing. --- intern/cycles/render/session.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 275de4d15d8..b880a62f4de 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -409,6 +409,11 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) if(tile_buffers.size() == 0) tile_buffers.resize(tile_manager.state.num_tiles, NULL); + /* In certain circumstances number of tiles in the tile manager could + * be changed. This is not supported by the progressive refine feature. + */ + assert(tile_buffers.size() == tile_manager.state.num_tiles); + tilebuffers = tile_buffers[tile.index]; if(tilebuffers == NULL) { tilebuffers = new RenderBuffers(tile_device); -- cgit v1.2.3 From eb05e87e16147554284d7b8d6b1a7184f9310719 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 May 2015 17:54:47 +1000 Subject: BMesh: editmode drawing set every faces material Check for changes in material (as other drawing code already does) --- source/blender/blenkernel/intern/cdderivedmesh.c | 2 +- source/blender/blenkernel/intern/editderivedmesh.c | 24 ++++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index e4a5dbb9d24..3feea12f017 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -793,7 +793,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, else { /* we need to check if the next material changes */ int next_actualFace = dm->drawObject->triangle_to_mface[0]; - int prev_mat_nr = -1; + short prev_mat_nr = -1; for (i = 0; i < tottri; i++) { //int actualFace = dm->drawObject->triangle_to_mface[i]; diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 5230634fe4c..90decfde30f 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -521,8 +521,6 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, GLenum poly_prev = GL_ZERO; GLenum shade_prev = GL_ZERO; - (void)setMaterial; /* UNUSED */ - /* currently unused -- each original face is handled separately */ (void)compareDrawOptions; @@ -539,6 +537,8 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, } if (bmdm->vertexCos) { + short prev_mat_nr = -1; + /* add direct access */ const float (*vertexCos)[3] = bmdm->vertexCos; const float (*vertexNos)[3]; @@ -569,8 +569,14 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, setDrawOptions(userData, BM_elem_index_get(efa))); if (draw_option != DM_DRAW_OPTION_SKIP) { const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */ - if (setMaterial) - setMaterial(efa->mat_nr + 1, NULL); + + if (efa->mat_nr != prev_mat_nr) { + if (setMaterial) { + setMaterial(efa->mat_nr + 1, NULL); + } + prev_mat_nr = efa->mat_nr; + } + if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */ if (poly_prev != GL_ZERO) glEnd(); @@ -645,6 +651,8 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, } } else { + short prev_mat_nr = -1; + BM_mesh_elem_index_ensure(bm, lnors ? BM_FACE | BM_LOOP : BM_FACE); for (i = 0; i < tottri; i++) { @@ -661,8 +669,12 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, if (draw_option != DM_DRAW_OPTION_SKIP) { const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */ - if (setMaterial) - setMaterial(efa->mat_nr + 1, NULL); + if (efa->mat_nr != prev_mat_nr) { + if (setMaterial) { + setMaterial(efa->mat_nr + 1, NULL); + } + prev_mat_nr = efa->mat_nr; + } if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */ -- cgit v1.2.3 From 293df68ebdd8ecb3d301a20f909787236d5e3db6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 May 2015 17:58:24 +1000 Subject: Object Drawing: avoid redundant material update --- source/blender/editors/space_view3d/drawobject.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 25557af5ddb..f8676d55147 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -4285,7 +4285,9 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 scene->customdata_mask); DM_update_materials(finalDM, ob); - DM_update_materials(cageDM, ob); + if (cageDM != finalDM) { + DM_update_materials(cageDM, ob); + } if (dt > OB_WIRE) { const bool glsl = draw_glsl_material(scene, ob, v3d, dt); -- cgit v1.2.3 From ac636a3c97dd4a699083f7bf3088852a931186ae Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 19 May 2015 13:02:17 +0500 Subject: Fix T44759: Blender has problems reading and writing 42k images to PNG --- source/blender/imbuf/intern/png.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index f3ff6659e1c..1b6b413838d 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -138,6 +138,7 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) int channels_in_float = ibuf->channels ? ibuf->channels : 4; float (*chanel_colormanage_cb)(float); + size_t num_bytes; /* use the jpeg quality setting for compression */ int compression; @@ -184,11 +185,11 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) } /* copy image data */ - + num_bytes = ((size_t)ibuf->x) * ibuf->y * bytesperpixel; if (is_16bit) - pixels16 = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned short), "png 16bit pixels"); + pixels16 = MEM_mallocN(num_bytes * sizeof(unsigned short), "png 16bit pixels"); else - pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "png 8bit pixels"); + pixels = MEM_mallocN(num_bytes * sizeof(unsigned char), "png 8bit pixels"); if (pixels == NULL && pixels16 == NULL) { png_destroy_write_struct(&png_ptr, &info_ptr); @@ -454,13 +455,13 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) if (is_16bit) { for (i = 0; i < ibuf->y; i++) { row_pointers[ibuf->y - 1 - i] = (png_bytep) - ((unsigned short *)pixels16 + (i * ibuf->x) * bytesperpixel); + ((unsigned short *)pixels16 + (((size_t)i) * ibuf->x) * bytesperpixel); } } else { for (i = 0; i < ibuf->y; i++) { row_pointers[ibuf->y - 1 - i] = (png_bytep) - ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char)); + ((unsigned char *)pixels + (((size_t)i) * ibuf->x) * bytesperpixel * sizeof(unsigned char)); } } @@ -682,7 +683,7 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[I else { imb_addrectImBuf(ibuf); - pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels"); + pixels = MEM_mallocN(((size_t)ibuf->x) * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels"); if (pixels == NULL) { printf("Cannot allocate pixels array\n"); longjmp(png_jmpbuf(png_ptr), 1); @@ -698,7 +699,7 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[I /* set the individual row-pointers to point at the correct offsets */ for (i = 0; i < ibuf->y; i++) { row_pointers[ibuf->y - 1 - i] = (png_bytep) - ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char)); + ((unsigned char *)pixels + (((size_t)i) * ibuf->x) * bytesperpixel * sizeof(unsigned char)); } png_read_image(png_ptr, row_pointers); -- cgit v1.2.3 From e8561e966d3d6ced9569e9a91aa123975e9ee95a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 May 2015 19:09:35 +1000 Subject: Fix T44762: Materials flicker in edit-mode --- source/blender/editors/space_view3d/drawobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index f8676d55147..c3bd657badf 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -3042,7 +3042,7 @@ static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *ba data.orig_index_mf_to_mpoly = data.orig_index_mp_to_orig = NULL; } - dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0); + dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, NULL, draw_dm_faces_sel__compareDrawOptions, &data, 0); } static DMDrawOption draw_dm_creases__setDrawOptions(void *userData, int index) -- cgit v1.2.3 From dc3533030abe2f188316fee993b274d7f83df288 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 19 May 2015 11:48:05 +0200 Subject: Fix T44553. Front face option did not get the correct normals to function - area normal would always point to the direction of the stroke --- source/blender/editors/sculpt_paint/sculpt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 0d1ee08cc75..8bdbe23ead8 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2747,7 +2747,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) /* note, the normal from the vertices is ignored, * causes glitch with planes, see: T44390 */ const float fade = bstrength * tex_strength(ss, brush, vd.co, sqrtf(test.dist), - NULL, area_no, vd.mask ? *vd.mask : 0.0f); + vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -2851,7 +2851,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t * causes glitch with planes, see: T44390 */ const float fade = bstrength * tex_strength(ss, brush, vd.co, ss->cache->radius * test.dist, - NULL, area_no, vd.mask ? *vd.mask : 0.0f); + vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], val, fade); -- cgit v1.2.3 From 78411dc7d77328e6c8fb7b38f7cacd186e68171e Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 19 May 2015 15:35:33 +0200 Subject: Fix T44755 set_value node output in node tree not properly converted to color in GLSL Issue here is that intermediate result was clipped as an optimization in such nodes and thus not converted to the correct type properly. Now only clip those values if types match. This keeps both the optimization and the conversion. I looked at converting uniform types always but it's more involved to compare types at conversion time for such links because the type was getting overridden during link duplication. --- source/blender/gpu/intern/gpu_codegen.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 90e4ce69394..8f07df5d3d1 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -930,8 +930,11 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType if (link->output) { outnode = link->output->node; name = outnode->name; + input = outnode->inputs.first; - if (STREQ(name, "set_value") || STREQ(name, "set_rgb")) { + if ((STREQ(name, "set_value") || STREQ(name, "set_rgb")) && + (input->type == type)) + { input = MEM_dupallocN(outnode->inputs.first); input->type = type; if (input->link) -- cgit v1.2.3 From d3cc7419a367452bccb592ee71bf1070c25058de Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 May 2015 23:41:13 +1000 Subject: BMesh: add BM_edge_pair_share_face_by_len --- source/blender/bmesh/intern/bmesh_queries.c | 30 +++++++++++++++++++++++++++++ source/blender/bmesh/intern/bmesh_queries.h | 5 +++++ 2 files changed, 35 insertions(+) diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 4fbba5af733..0f4f34fa5c8 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -257,6 +257,36 @@ BMFace *BM_vert_pair_share_face_by_len( return f_cur; } +BMFace *BM_edge_pair_share_face_by_len( + BMEdge *e_a, BMEdge *e_b, + BMLoop **r_l_a, BMLoop **r_l_b, + const bool allow_adjacent) +{ + BMLoop *l_cur_a = NULL, *l_cur_b = NULL; + BMFace *f_cur = NULL; + + if (e_a->l && e_b->l) { + BMIter iter; + BMLoop *l_a, *l_b; + + BM_ITER_ELEM (l_a, &iter, e_a, BM_LOOPS_OF_EDGE) { + if ((f_cur == NULL) || (l_a->f->len < f_cur->len)) { + l_b = BM_face_edge_share_loop(l_a->f, e_b); + if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) { + f_cur = l_a->f; + l_cur_a = l_a; + l_cur_b = l_b; + } + } + } + } + + *r_l_a = l_cur_a; + *r_l_b = l_cur_b; + + return f_cur; +} + static float bm_face_calc_split_dot(BMLoop *l_a, BMLoop *l_b) { float no[2][3]; diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index d66bd00c2fc..f96d99fd452 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -64,6 +64,11 @@ BMFace *BM_vert_pair_share_face_by_angle( BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent) ATTR_NONNULL(); +BMFace *BM_edge_pair_share_face_by_len( + BMEdge *e_a, BMEdge *e_b, + BMLoop **r_l_a, BMLoop **r_l_b, + const bool allow_adjacent) ATTR_NONNULL(); + int BM_vert_edge_count_nonwire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); #define BM_vert_edge_count_is_equal(v, n) (BM_vert_edge_count_ex(v, (n) + 1) == n) #define BM_vert_edge_count_is_over(v, n) (BM_vert_edge_count_ex(v, (n) + 1) == (n) + 1) -- cgit v1.2.3 From 07e9fb8ec6c9d51fbd44fdf4bc49fdd3ea43992c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 May 2015 23:42:22 +1000 Subject: BMesh: calls to store selection at the list head --- source/blender/bmesh/intern/bmesh_marking.c | 12 ++++++++++++ source/blender/bmesh/intern/bmesh_marking.h | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 93be42ae566..17b6d1d99e7 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -914,6 +914,12 @@ void _bm_select_history_store_notest(BMesh *bm, BMHeader *ele) BLI_addtail(&(bm->selected), ese); } +void _bm_select_history_store_head_notest(BMesh *bm, BMHeader *ele) +{ + BMEditSelection *ese = bm_select_history_create(ele); + BLI_addhead(&(bm->selected), ese); +} + void _bm_select_history_store(BMesh *bm, BMHeader *ele) { if (!BM_select_history_check(bm, (BMElem *)ele)) { @@ -921,6 +927,12 @@ void _bm_select_history_store(BMesh *bm, BMHeader *ele) } } +void _bm_select_history_store_head(BMesh *bm, BMHeader *ele) +{ + if (!BM_select_history_check(bm, (BMElem *)ele)) { + BM_select_history_store_head_notest(bm, (BMElem *)ele); + } +} void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele) { diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h index 0d86567c06e..4730af66a74 100644 --- a/source/blender/bmesh/intern/bmesh_marking.h +++ b/source/blender/bmesh/intern/bmesh_marking.h @@ -95,6 +95,8 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]); #define BM_select_history_remove(bm, ele) _bm_select_history_remove(bm, &(ele)->head) #define BM_select_history_store_notest(bm, ele) _bm_select_history_store_notest(bm, &(ele)->head) #define BM_select_history_store(bm, ele) _bm_select_history_store(bm, &(ele)->head) +#define BM_select_history_store_head_notest(bm, ele) _bm_select_history_store_head_notest(bm, &(ele)->head) +#define BM_select_history_store_head(bm, ele) _bm_select_history_store_head(bm, &(ele)->head) #define BM_select_history_store_after_notest(bm, ese_ref, ele) _bm_select_history_store_after_notest(bm, ese_ref, &(ele)->head) #define BM_select_history_store_after(bm, ese, ese_ref) _bm_select_history_store_after(bm, ese_ref, &(ele)->head) @@ -102,6 +104,8 @@ bool _bm_select_history_check(BMesh *bm, const BMHeader *ele); bool _bm_select_history_remove(BMesh *bm, BMHeader *ele); void _bm_select_history_store_notest(BMesh *bm, BMHeader *ele); void _bm_select_history_store(BMesh *bm, BMHeader *ele); +void _bm_select_history_store_head_notest(BMesh *bm, BMHeader *ele); +void _bm_select_history_store_head(BMesh *bm, BMHeader *ele); void _bm_select_history_store_after(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele); void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele); -- cgit v1.2.3 From df0a1fa3c5de560ddddc87b6694b6ee224422af8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 19 May 2015 23:46:31 +1000 Subject: Fix T44766: Connect fails /w selected ngon edges --- source/blender/editors/mesh/editmesh_tools.c | 91 ++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 54acf4abf7c..f023aecd50b 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -1109,28 +1109,111 @@ static bool bm_vert_connect_select_history(BMesh *bm) return false; } +/** + * Convert an edge selection to a temp vertex selection + * (which must be cleared after use as a path to connect). + */ +static bool bm_vert_connect_select_history_edge_to_vert_path(BMesh *bm, ListBase *r_selected) +{ + ListBase selected_orig = {NULL, NULL}; + BMEditSelection *ese; + int edges_len = 0; + bool side = false; + + /* first check all edges are OK */ + for (ese = bm->selected.first; ese; ese = ese->next) { + if (ese->htype == BM_EDGE) { + edges_len += 1; + } + else { + return false; + } + } + /* if this is a mixed selection, bail out! */ + if (bm->totedgesel != edges_len) { + return false; + } + + SWAP(ListBase, bm->selected, selected_orig); + + /* convert edge selection into 2 ordered loops (where the first edge ends up in the middle) */ + for (ese = selected_orig.first; ese; ese = ese->next) { + BMEdge *e_curr = (BMEdge *)ese->ele; + BMEdge *e_prev = ese->prev ? (BMEdge *)ese->prev->ele : NULL; + BMLoop *l_curr; + BMLoop *l_prev; + BMVert *v; + + if (e_prev) { + BMFace *f = BM_edge_pair_share_face_by_len(e_curr, e_prev, &l_curr, &l_prev, true); + if (f) { + if ((e_curr->v1 != l_curr->v) == (e_prev->v1 != l_prev->v)) { + side = !side; + } + } + else if (is_quad_flip_v3(e_curr->v1->co, e_curr->v2->co, e_prev->v2->co, e_prev->v1->co)) { + side = !side; + } + } + + v = (&e_curr->v1)[side]; + if (!bm->selected.last || (BMVert *)((BMEditSelection *)bm->selected.last)->ele != v) { + BM_select_history_store_notest(bm, v); + } + + v = (&e_curr->v1)[!side]; + if (!bm->selected.first || (BMVert *)((BMEditSelection *)bm->selected.first)->ele != v) { + BM_select_history_store_head_notest(bm, v); + } + + e_prev = e_curr; + } + + *r_selected = bm->selected; + bm->selected = selected_orig; + + return true; +} static int edbm_vert_connect_path_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; bool is_pair = (em->bm->totvertsel == 2); + ListBase selected_orig = {NULL, NULL}; + int retval; /* when there is only 2 vertices, we can ignore selection order */ if (is_pair) { return edbm_vert_connect_exec(C, op); } - if (bm_vert_connect_select_history(em->bm)) { + if (bm->selected.first) { + BMEditSelection *ese = bm->selected.first; + if (ese->htype == BM_EDGE) { + if (bm_vert_connect_select_history_edge_to_vert_path(bm, &selected_orig)) { + SWAP(ListBase, bm->selected, selected_orig); + } + } + } + + if (bm_vert_connect_select_history(bm)) { EDBM_selectmode_flush(em); EDBM_update_generic(em, true, true); - - return OPERATOR_FINISHED; + retval = OPERATOR_FINISHED; } else { BKE_report(op->reports, RPT_ERROR, "Invalid selection order"); - return OPERATOR_CANCELLED; + retval = OPERATOR_CANCELLED; } + + if (!BLI_listbase_is_empty(&selected_orig)) { + BM_select_history_clear(bm); + bm->selected = selected_orig; + } + + return retval; } void MESH_OT_vert_connect_path(wmOperatorType *ot) -- cgit v1.2.3 From 158c891520eecfcf9d7fcb5fb1d396112ac23abc Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 19 May 2015 16:15:38 +0200 Subject: Clear animation list to avoid referencing freed memory. --- source/blender/blenkernel/intern/sequencer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 5429d113518..d4d64af6c94 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -254,15 +254,15 @@ void BKE_sequence_free_anim(Sequence *seq) { while (seq->anims.last) { StripAnim *sanim = seq->anims.last; - BLI_remlink(&seq->anims, sanim); if (sanim->anim) { IMB_free_anim(sanim->anim); sanim->anim = NULL; } - MEM_freeN(sanim); + BLI_freelinkN(&seq->anims, sanim); } + BLI_listbase_clear(&seq->anims); } /* cache must be freed before calling this function -- cgit v1.2.3 From 150a4b23ba848041fb2ba606435207cee8b2bbc2 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 19 May 2015 16:25:42 +0200 Subject: Fix part of T44768 Yet another Intel driver failing on viewport Ambient occlusion (Maybe we should add drivers that DO work instead, but in the future those will be much more since Intel claims to have fixed the issue) --- source/blender/gpu/intern/gpu_extensions.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 0fcdd87a1ff..4eb1612b9ba 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -264,7 +264,8 @@ void gpu_extensions_init(void) GG.dfdyfactors[1] = -1.0; } else if (GG.device == GPU_DEVICE_INTEL && GG.os == GPU_OS_WIN && - (strstr(version, "4.0.0 - Build 9.18.10.3165") || + (strstr(version, "4.0.0 - Build 9.18.10.3186") || + strstr(version, "4.0.0 - Build 9.18.10.3165") || strstr(version, "3.1.0 - Build 9.17.10.3347") || strstr(version, "3.1.0 - Build 9.17.10.4101"))) { -- cgit v1.2.3 From fccf253e3677e023e554641b6118366ef6df937e Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 19 May 2015 18:32:41 +0200 Subject: Support string metadata loading for OpenEXR files. --- source/blender/imbuf/intern/openexr/openexr_api.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 58c5be8b110..b4f81ebeb57 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -1973,6 +1973,21 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char } } + if (flags & IB_metadata) { + const Header & header = file->header(0); + Header::ConstIterator iter; + + for (iter = header.begin(); iter != header.end(); iter++) { + const StringAttribute *attrib = file->header(0).findTypedAttribute (iter.name()); + + /* not all attributes are string attributes so we might get some NULLs here */ + if (attrib) { + IMB_metadata_add_field(ibuf, iter.name(), attrib->value().c_str()); + ibuf->flags |= IB_metadata; + } + } + } + /* file is no longer needed */ delete file; } -- cgit v1.2.3 From 377822729cbf48d86d46f7efbae0c0e3fbeba99f Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Tue, 19 May 2015 19:24:14 +0200 Subject: BGE: Fix T40555: LibLoad material caching issue Previously we don't merge material cached list, it create dangling pointer and memory leak. Now we merge material cache list during the scene merge, and remove material in this list during the library free. Reviewers: agoose77, dfelinto, hg1, pgi, campbellbarton, moguri Reviewed By: campbellbarton, moguri Subscribers: campbellbarton, youle, kupoman Projects: #game_engine Differential Revision: https://developer.blender.org/D1278 --- source/gameengine/Converter/KX_BlenderSceneConverter.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 1a489c301e2..9e53d9e1569 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -903,7 +903,7 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl *err_str = err_local; return NULL; } - + main_newlib = BKE_main_new(); BKE_reports_init(&reports, RPT_STORE); @@ -1218,6 +1218,8 @@ bool KX_BlenderSceneConverter::FreeBlendFile(Main *maggie) bmat = bl_mat->GetBlenderMaterial(); if (IS_TAGGED(bmat)) { + // Remove the poly material coresponding to this Blender Material. + m_polymat_cache[polymit->first].erase(bmat); delete (*polymit).second; *polymit = m_polymaterials.back(); m_polymaterials.pop_back(); @@ -1233,6 +1235,8 @@ bool KX_BlenderSceneConverter::FreeBlendFile(Main *maggie) for (i = 0, matit = m_materials.begin(); i < size; ) { BL_Material *mat = (*matit).second; if (IS_TAGGED(mat->material)) { + // Remove the bl material coresponding to this Blender Material. + m_mat_cache[matit->first].erase(mat->material); delete (*matit).second; *matit = m_materials.back(); m_materials.pop_back(); @@ -1354,6 +1358,16 @@ bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from) } } + MaterialCache::iterator matcacheit = m_mat_cache.find(from); + // Merge cached BL_Material map. + m_mat_cache[to].insert(matcacheit->second.begin(), matcacheit->second.end()); + m_mat_cache.erase(matcacheit); + + PolyMaterialCache::iterator polymatcacheit = m_polymat_cache.find(from); + // Merge cached RAS_IPolyMaterial map. + m_polymat_cache[to].insert(polymatcacheit->second.begin(), polymatcacheit->second.end()); + m_polymat_cache.erase(polymatcacheit); + return true; } -- cgit v1.2.3 From a1e8547877ea4d2f289aab5ccc47c6260f43d1ee Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Tue, 19 May 2015 23:13:30 +0200 Subject: BGE: Use CameCase code style for KX_WorldInfo python API. --- .../rst/bge_types/bge.types.KX_WorldInfo.rst | 18 +++++++++--------- source/gameengine/Ketsji/KX_WorldInfo.cpp | 16 ++++++++-------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/doc/python_api/rst/bge_types/bge.types.KX_WorldInfo.rst b/doc/python_api/rst/bge_types/bge.types.KX_WorldInfo.rst index ffc24b4e6c5..d6cb23c9e62 100644 --- a/doc/python_api/rst/bge_types/bge.types.KX_WorldInfo.rst +++ b/doc/python_api/rst/bge_types/bge.types.KX_WorldInfo.rst @@ -16,7 +16,7 @@ base class --- :class:`PyObjectPlus` sce = bge.logic.getCurrentScene() - sce.world.mist_color = [1.0, 0.0, 0.0] + sce.world.mistColor = [1.0, 0.0, 0.0] ********* Constants @@ -38,49 +38,49 @@ Constants Attributes ********** - .. attribute:: mist_enable + .. attribute:: mistEnable Return the state of the mist. :type: bool - .. attribute:: mist_start + .. attribute:: mistStart The mist start point. :type: float - .. attribute:: mist_distance + .. attribute:: mistDistance The mist distance fom the start point to reach 100% mist. :type: float - .. attribute:: mist_intensity + .. attribute:: mistIntensity The mist intensity. :type: float - .. attribute:: mist_type + .. attribute:: mistType The type of mist - must be KX_MIST_QUADRATIC, KX_MIST_LINEAR or KX_MIST_INV_QUADRATIC - .. attribute:: mist_color + .. attribute:: mistColor The color of the mist. Black = [0.0, 0.0, 0.0], White = [1.0, 1.0, 1.0]. Mist and background color sould always set to the same color. :type: :class:`mathutils.Vector` - .. attribute:: background_color + .. attribute:: backgroundColor The color of the background. Black = [0.0, 0.0, 0.0], White = [1.0, 1.0, 1.0]. Mist and background color sould always set to the same color. :type: :class:`mathutils.Vector` - .. attribute:: ambient_color + .. attribute:: ambientColor The color of the ambient light. Black = [0.0, 0.0, 0.0], White = [1.0, 1.0, 1.0]. diff --git a/source/gameengine/Ketsji/KX_WorldInfo.cpp b/source/gameengine/Ketsji/KX_WorldInfo.cpp index 21e72504a2b..f6caaf03066 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.cpp +++ b/source/gameengine/Ketsji/KX_WorldInfo.cpp @@ -232,17 +232,17 @@ PyMethodDef KX_WorldInfo::Methods[] = { }; PyAttributeDef KX_WorldInfo::Attributes[] = { - KX_PYATTRIBUTE_BOOL_RW("mist_enable", KX_WorldInfo, m_hasmist), - KX_PYATTRIBUTE_FLOAT_RW("mist_start", 0.0f, 10000.0f, KX_WorldInfo, m_miststart), - KX_PYATTRIBUTE_FLOAT_RW("mist_distance", 0.001f, 10000.0f, KX_WorldInfo, m_mistdistance), - KX_PYATTRIBUTE_FLOAT_RW("mist_intensity", 0.0f, 1.0f, KX_WorldInfo, m_mistintensity), - KX_PYATTRIBUTE_SHORT_RW("mist_type", 0, 2, true, KX_WorldInfo, m_misttype), + KX_PYATTRIBUTE_BOOL_RW("mistEnable", KX_WorldInfo, m_hasmist), + KX_PYATTRIBUTE_FLOAT_RW("mistStart", 0.0f, 10000.0f, KX_WorldInfo, m_miststart), + KX_PYATTRIBUTE_FLOAT_RW("mistDistance", 0.001f, 10000.0f, KX_WorldInfo, m_mistdistance), + KX_PYATTRIBUTE_FLOAT_RW("mistIntensity", 0.0f, 1.0f, KX_WorldInfo, m_mistintensity), + KX_PYATTRIBUTE_SHORT_RW("mistType", 0, 2, true, KX_WorldInfo, m_misttype), KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_QUADRATIC", KX_WorldInfo, pyattr_get_mist_typeconst), KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_LINEAR", KX_WorldInfo, pyattr_get_mist_typeconst), KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_INV_QUADRATIC", KX_WorldInfo, pyattr_get_mist_typeconst), - KX_PYATTRIBUTE_RW_FUNCTION("mist_color", KX_WorldInfo, pyattr_get_mist_color, pyattr_set_mist_color), - KX_PYATTRIBUTE_RW_FUNCTION("background_color", KX_WorldInfo, pyattr_get_back_color, pyattr_set_back_color), - KX_PYATTRIBUTE_RW_FUNCTION("ambient_color", KX_WorldInfo, pyattr_get_ambient_color, pyattr_set_ambient_color), + KX_PYATTRIBUTE_RW_FUNCTION("mistColor", KX_WorldInfo, pyattr_get_mist_color, pyattr_set_mist_color), + KX_PYATTRIBUTE_RW_FUNCTION("backgroundColor", KX_WorldInfo, pyattr_get_back_color, pyattr_set_back_color), + KX_PYATTRIBUTE_RW_FUNCTION("ambientColor", KX_WorldInfo, pyattr_get_ambient_color, pyattr_set_ambient_color), { NULL } /* Sentinel */ }; -- cgit v1.2.3 From f0c143ca721cdf651f5e49de98ce466376635c9a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 20 May 2015 12:55:57 +1000 Subject: doxygen: rename included files (they were ignored) --- doc/doxygen/Doxyfile | 8 +- doc/doxygen/doxygen.extern | 17 --- doc/doxygen/doxygen.extern.h | 17 +++ doc/doxygen/doxygen.intern | 102 ------------- doc/doxygen/doxygen.intern.h | 102 +++++++++++++ doc/doxygen/doxygen.main | 19 --- doc/doxygen/doxygen.main.h | 19 +++ doc/doxygen/doxygen.source | 346 ------------------------------------------- doc/doxygen/doxygen.source.h | 346 +++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 488 insertions(+), 488 deletions(-) delete mode 100644 doc/doxygen/doxygen.extern create mode 100644 doc/doxygen/doxygen.extern.h delete mode 100644 doc/doxygen/doxygen.intern create mode 100644 doc/doxygen/doxygen.intern.h delete mode 100644 doc/doxygen/doxygen.main create mode 100644 doc/doxygen/doxygen.main.h delete mode 100644 doc/doxygen/doxygen.source create mode 100644 doc/doxygen/doxygen.source.h diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index 3865729fe56..9edf977f257 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -664,10 +664,10 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = doxygen.main \ - doxygen.source \ - doxygen.intern \ - doxygen.extern \ +INPUT = doxygen.main.h \ + doxygen.source.h \ + doxygen.intern.h \ + doxygen.extern.h \ ../../source \ ../../intern \ ../../extern/bullet2 diff --git a/doc/doxygen/doxygen.extern b/doc/doxygen/doxygen.extern deleted file mode 100644 index 6c6872ff53f..00000000000 --- a/doc/doxygen/doxygen.extern +++ /dev/null @@ -1,17 +0,0 @@ -/** \defgroup extern External libraries - * \section externabout External libraries - * As with \ref intern these libraries are - * provided in the Blender codebase. This is - * to make building Blender easier. The main - * development of these libraries is \b not part - * of the normal Blender development process, but - * each of the library is developed separately. - * Whenever deemed necessary libraries in \c extern/ - * folder are updated. - * - */ - -/** \defgroup bullet Bullet Physics Library - * \ingroup extern - * \see \ref bulletdoc - */ diff --git a/doc/doxygen/doxygen.extern.h b/doc/doxygen/doxygen.extern.h new file mode 100644 index 00000000000..6c6872ff53f --- /dev/null +++ b/doc/doxygen/doxygen.extern.h @@ -0,0 +1,17 @@ +/** \defgroup extern External libraries + * \section externabout External libraries + * As with \ref intern these libraries are + * provided in the Blender codebase. This is + * to make building Blender easier. The main + * development of these libraries is \b not part + * of the normal Blender development process, but + * each of the library is developed separately. + * Whenever deemed necessary libraries in \c extern/ + * folder are updated. + * + */ + +/** \defgroup bullet Bullet Physics Library + * \ingroup extern + * \see \ref bulletdoc + */ diff --git a/doc/doxygen/doxygen.intern b/doc/doxygen/doxygen.intern deleted file mode 100644 index ae8f6ca88e4..00000000000 --- a/doc/doxygen/doxygen.intern +++ /dev/null @@ -1,102 +0,0 @@ -/** \defgroup intern Internal libraries - * \section internabout Internal libraries - * Blender comes with some of its dependencies - * directly included in the codebase. Libraries - * that are in the \c intern/ folder are maintained - * as part of the normal development process. - */ - -/** \defgroup MEM Guarded memory (de)allocation - * \ingroup intern - */ - -/** \defgroup boolop boolop - * \ingroup intern - */ - -/** \defgroup ctr container - * \ingroup intern - */ - -/** \defgroup decimation decimation - * \ingroup intern - */ - -/** \defgroup elbeem elbeem - * \ingroup intern - */ - -/** \defgroup bsp bsp - * \ingroup intern - */ - -/** \defgroup iksolver iksolver - * \ingroup intern - */ - -/** \defgroup itasc itasc - * \ingroup intern - */ - -/** \defgroup memutil memutil - * \ingroup intern - */ - -/** \defgroup mikktspace mikktspace - * \ingroup intern - */ - -/** \defgroup moto moto - * \ingroup intern - */ - -/** \defgroup opennl opennl - * \ingroup intern - */ - -/** \defgroup smoke smoke - * \ingroup intern - */ - -/** \defgroup string string - * \ingroup intern - */ - -/** \defgroup audaspace Audaspace - * \ingroup intern undoc - * \todo add to doxygen - */ -/** \defgroup audfx Audaspace FX - * \ingroup audaspace - */ -/** \defgroup audopenal Audaspace OpenAL - * \ingroup audaspace - */ -/** \defgroup audpython Audaspace Python - * \ingroup audaspace - */ -/** \defgroup audsdl Audaspace SDL - * \ingroup audaspace - */ -/** \defgroup audsrc Audaspace SRC - - * \ingroup audaspace - */ -/** \defgroup audffmpeg Audaspace FFMpeg - * \ingroup audaspace - */ -/** \defgroup audfftw Audaspace FFTW - * \ingroup audaspace - */ -/** \defgroup audjack Audaspace Jack - * \ingroup audaspace - */ -/** \defgroup audsndfile Audaspace sndfile - * \ingroup audaspace - */ - -/** \defgroup GHOST GHOST API - * \ingroup intern GUI - * \ref GHOSTPage - */ - diff --git a/doc/doxygen/doxygen.intern.h b/doc/doxygen/doxygen.intern.h new file mode 100644 index 00000000000..ae8f6ca88e4 --- /dev/null +++ b/doc/doxygen/doxygen.intern.h @@ -0,0 +1,102 @@ +/** \defgroup intern Internal libraries + * \section internabout Internal libraries + * Blender comes with some of its dependencies + * directly included in the codebase. Libraries + * that are in the \c intern/ folder are maintained + * as part of the normal development process. + */ + +/** \defgroup MEM Guarded memory (de)allocation + * \ingroup intern + */ + +/** \defgroup boolop boolop + * \ingroup intern + */ + +/** \defgroup ctr container + * \ingroup intern + */ + +/** \defgroup decimation decimation + * \ingroup intern + */ + +/** \defgroup elbeem elbeem + * \ingroup intern + */ + +/** \defgroup bsp bsp + * \ingroup intern + */ + +/** \defgroup iksolver iksolver + * \ingroup intern + */ + +/** \defgroup itasc itasc + * \ingroup intern + */ + +/** \defgroup memutil memutil + * \ingroup intern + */ + +/** \defgroup mikktspace mikktspace + * \ingroup intern + */ + +/** \defgroup moto moto + * \ingroup intern + */ + +/** \defgroup opennl opennl + * \ingroup intern + */ + +/** \defgroup smoke smoke + * \ingroup intern + */ + +/** \defgroup string string + * \ingroup intern + */ + +/** \defgroup audaspace Audaspace + * \ingroup intern undoc + * \todo add to doxygen + */ +/** \defgroup audfx Audaspace FX + * \ingroup audaspace + */ +/** \defgroup audopenal Audaspace OpenAL + * \ingroup audaspace + */ +/** \defgroup audpython Audaspace Python + * \ingroup audaspace + */ +/** \defgroup audsdl Audaspace SDL + * \ingroup audaspace + */ +/** \defgroup audsrc Audaspace SRC + + * \ingroup audaspace + */ +/** \defgroup audffmpeg Audaspace FFMpeg + * \ingroup audaspace + */ +/** \defgroup audfftw Audaspace FFTW + * \ingroup audaspace + */ +/** \defgroup audjack Audaspace Jack + * \ingroup audaspace + */ +/** \defgroup audsndfile Audaspace sndfile + * \ingroup audaspace + */ + +/** \defgroup GHOST GHOST API + * \ingroup intern GUI + * \ref GHOSTPage + */ + diff --git a/doc/doxygen/doxygen.main b/doc/doxygen/doxygen.main deleted file mode 100644 index 7f63764d7c6..00000000000 --- a/doc/doxygen/doxygen.main +++ /dev/null @@ -1,19 +0,0 @@ -/** \mainpage Blender - * - * \section intro Introduction - * - * Blender is an integrated 3d package. - * - * These pages document the source code of blender. - * - * \subsection implinks Important Links - * - developer.blender.org with bug tracker - * - Development documents on our wiki. - * - * \subsection blother Other - * For more information on using Blender browse to http://www.blender.org - * - */ - -/** \defgroup undoc Undocumented - * \brief Modules and libraries that are still undocumented, or lacking proper integration into the doxygen system, are marked in this group. */ diff --git a/doc/doxygen/doxygen.main.h b/doc/doxygen/doxygen.main.h new file mode 100644 index 00000000000..7f63764d7c6 --- /dev/null +++ b/doc/doxygen/doxygen.main.h @@ -0,0 +1,19 @@ +/** \mainpage Blender + * + * \section intro Introduction + * + * Blender is an integrated 3d package. + * + * These pages document the source code of blender. + * + * \subsection implinks Important Links + * - developer.blender.org with bug tracker + * - Development documents on our wiki. + * + * \subsection blother Other + * For more information on using Blender browse to http://www.blender.org + * + */ + +/** \defgroup undoc Undocumented + * \brief Modules and libraries that are still undocumented, or lacking proper integration into the doxygen system, are marked in this group. */ diff --git a/doc/doxygen/doxygen.source b/doc/doxygen/doxygen.source deleted file mode 100644 index f27a5a87807..00000000000 --- a/doc/doxygen/doxygen.source +++ /dev/null @@ -1,346 +0,0 @@ - -/** \defgroup blenderplayer Blender Player */ - -/** \defgroup blc bad level calls - * \ingroup blenderplayer - */ - -/** \defgroup render Rendering - * \ingroup blender - */ -/** \defgroup bmesh BMesh - * \ingroup blender - */ -/** \defgroup texture Texturing */ -/** \defgroup compositor Compositing */ - -/** \defgroup python Python - * \ingroup blender - */ - -/** \defgroup pygen Python Generic - * \ingroup python - */ - -/** \defgroup pymathutils Python Mathutils - * \ingroup python - */ - -/** \defgroup pythonintern Python RNA and Operators - * \ingroup python - */ - -/** \defgroup blpluginapi Blender pluginapi - * \ingroup blender - * \attention not in use currently - */ - -/* ================================ */ - -/** \defgroup bge Game Engine */ -/** \defgroup gamelogic Game Logic - * \ingroup bge - */ -/** \defgroup bgeconv Converter - * \ingroup bge - */ -/** \defgroup blroutines Blender Routines - * \ingroup bge - */ -/** \defgroup expressions Expressions - * \ingroup bge - */ -/** \defgroup player Game Player - * \ingroup bge - */ -/** \defgroup ketsji Ketsji - * \ingroup bge - * \todo check all headers and code files for proper licenses - */ -/** \defgroup ketsjinet Ketsji Network - * \ingroup ketsji - */ -/** \defgroup bgenet Network - * \ingroup bge - */ -/** \defgroup bgenetlb Loopback Network - * \ingroup bgenet - */ -/** \defgroup phys Physics - * \ingroup bge - */ -/** \defgroup physbullet Bullet Physics - * \ingroup phys - */ -/** \defgroup physdummy Dummy Physics (none) - * \ingroup phys - */ -/** \defgroup bgerast Rasterizer - * \ingroup bge - */ -/** \defgroup bgerastoglfilters OpenGL Filters - * \ingroup bgerast - */ -/** \defgroup bgerastogl OpenGL Rasterizer - * \ingroup bgerast - */ -/** \defgroup bgesg BGE SceneGraph - * \ingroup bge - */ -/** \defgroup bgevideotex BGE Video Texture - * \ingroup bge - */ - -/* ================================ */ - -/** \defgroup blender blender */ - -/** \defgroup blf blenfont - * \ingroup blender - */ - -/** \defgroup bke blenkernel - * \ingroup blender - */ - -/** \defgroup bli blenlib - * \ingroup blender - */ - -/** \defgroup nodes nodes - * \ingroup blender - */ - -/** \defgroup cmpnodes cmpnodes - * \ingroup nodes - */ - -/** \defgroup shdnodes shdnodes - * \ingroup nodes - */ - -/** \defgroup texnodes texnodes - * \ingroup nodes - */ -/** \defgroup modifiers modifiers - * \ingroup blender - */ - -/** \defgroup data DNA, RNA and .blend access*/ - -/** \defgroup gpu GPU - * \ingroup blender - */ - -/** \defgroup ikplugin ikplugin - * \ingroup blender - */ - -/** \defgroup DNA sDNA - * \ingroup blender data - */ -/** \defgroup RNA RNA - * \ingroup blender data - */ - -/** \defgroup blenloader .blend read and write functions - * \ingroup blender data - * \todo check if \ref blo and \ref blenloader groups can be - * merged in docs. - */ - -/** \defgroup quicktime quicktime - * \ingroup blender - -/** \defgroup gui GUI */ - -/** \defgroup wm windowmanager - * \ingroup blender gui - */ - -/* ================================ */ - -/** \defgroup editors Editors - * \ingroup blender - */ - -/** \defgroup edanimation animation - * \ingroup editors - */ - -/** \defgroup edarmature armature - * \ingroup editors - */ - -/** \defgroup edcurve curve - * \ingroup editors - */ - -/** \defgroup eddatafiles datafiles - * \ingroup editors - */ - -/** \defgroup edgpencil gpencil - * \ingroup editors - */ - -/** \defgroup edinterface interface - * \ingroup editors - */ - -/** \defgroup edmesh mesh - * \ingroup editors - */ - -/** \defgroup edmeta metaball - * \ingroup editors - */ - -/** \defgroup edobj object - * \ingroup editors - */ - -/** \defgroup edphys physics - * \ingroup editors - */ - -/** \defgroup edrend render - * \ingroup editors - */ - -/** \defgroup edscr screen - * \ingroup editors - */ - -/** \defgroup edsculpt sculpt and paint - * \ingroup editors - */ - -/** \defgroup edsnd sound - * \ingroup editors - */ - -/** \defgroup spaction action space - * \ingroup editors - */ - -/** \defgroup spapi space API - * \ingroup editors - */ - -/** \defgroup spbuttons buttons space - * \ingroup editors - */ - -/** \defgroup spconsole console space - * \ingroup editors - */ - -/** \defgroup spfile fileselector - * \ingroup editors - */ - -/** \defgroup spgraph graph editor - * \ingroup editors - */ - -/** \defgroup spimage image and UV editor - * \ingroup editors - */ - -/** \defgroup spinfo info space - * \ingroup editors - */ - -/** \defgroup splogic game logic editor - * \ingroup editors - */ - -/** \defgroup spnla NLA editor - * \ingroup editors - */ - -/** \defgroup spnode node editor - * \ingroup editors - */ - -/** \defgroup spoutliner outliner space - * \ingroup editors - */ - -/** \defgroup spscript script space - * \ingroup editors - */ - -/** \defgroup spseq sequencer - * \ingroup editors - */ - -/** \defgroup spsnd sound space - * \ingroup editors - */ - -/** \defgroup sptext text editor - * \ingroup editors - */ - -/** \defgroup sptime time line - * \ingroup editors - */ - -/** \defgroup spuserpref user preferences - * \ingroup editors - */ - -/** \defgroup spview3d 3D view - * \ingroup editors - */ - -/** \defgroup edtransform transform - * \ingroup editors - */ - -/** \defgroup edutil editor utilities - * \ingroup editors - */ - -/** \defgroup spuv UV editing - * \ingroup editors - */ - -/* ================================ */ - -/** \defgroup editorui Interface and Widgets - * \ingroup gui - */ - -/** \defgroup externformats external formats */ - -/** \defgroup collada COLLADA - * \ingroup externformats - */ - -/** \defgroup avi AVI - * \ingroup externformats - */ - -/** \defgroup imbuf IMage Buffer - * \ingroup blender - */ - -/** \defgroup imbcineon Cineon - * \ingroup imbuf - */ - -/** \defgroup imbdds DDS - * \ingroup imbuf - */ - -/** \defgroup openexr OpenEXR - * \ingroup imbuf - */ - -/* ================================ */ - -/** \defgroup undoc Undocumented - * \brief Modules and libraries that are still undocumented, or lacking proper integration into the doxygen system, are marked in this group. */ diff --git a/doc/doxygen/doxygen.source.h b/doc/doxygen/doxygen.source.h new file mode 100644 index 00000000000..f27a5a87807 --- /dev/null +++ b/doc/doxygen/doxygen.source.h @@ -0,0 +1,346 @@ + +/** \defgroup blenderplayer Blender Player */ + +/** \defgroup blc bad level calls + * \ingroup blenderplayer + */ + +/** \defgroup render Rendering + * \ingroup blender + */ +/** \defgroup bmesh BMesh + * \ingroup blender + */ +/** \defgroup texture Texturing */ +/** \defgroup compositor Compositing */ + +/** \defgroup python Python + * \ingroup blender + */ + +/** \defgroup pygen Python Generic + * \ingroup python + */ + +/** \defgroup pymathutils Python Mathutils + * \ingroup python + */ + +/** \defgroup pythonintern Python RNA and Operators + * \ingroup python + */ + +/** \defgroup blpluginapi Blender pluginapi + * \ingroup blender + * \attention not in use currently + */ + +/* ================================ */ + +/** \defgroup bge Game Engine */ +/** \defgroup gamelogic Game Logic + * \ingroup bge + */ +/** \defgroup bgeconv Converter + * \ingroup bge + */ +/** \defgroup blroutines Blender Routines + * \ingroup bge + */ +/** \defgroup expressions Expressions + * \ingroup bge + */ +/** \defgroup player Game Player + * \ingroup bge + */ +/** \defgroup ketsji Ketsji + * \ingroup bge + * \todo check all headers and code files for proper licenses + */ +/** \defgroup ketsjinet Ketsji Network + * \ingroup ketsji + */ +/** \defgroup bgenet Network + * \ingroup bge + */ +/** \defgroup bgenetlb Loopback Network + * \ingroup bgenet + */ +/** \defgroup phys Physics + * \ingroup bge + */ +/** \defgroup physbullet Bullet Physics + * \ingroup phys + */ +/** \defgroup physdummy Dummy Physics (none) + * \ingroup phys + */ +/** \defgroup bgerast Rasterizer + * \ingroup bge + */ +/** \defgroup bgerastoglfilters OpenGL Filters + * \ingroup bgerast + */ +/** \defgroup bgerastogl OpenGL Rasterizer + * \ingroup bgerast + */ +/** \defgroup bgesg BGE SceneGraph + * \ingroup bge + */ +/** \defgroup bgevideotex BGE Video Texture + * \ingroup bge + */ + +/* ================================ */ + +/** \defgroup blender blender */ + +/** \defgroup blf blenfont + * \ingroup blender + */ + +/** \defgroup bke blenkernel + * \ingroup blender + */ + +/** \defgroup bli blenlib + * \ingroup blender + */ + +/** \defgroup nodes nodes + * \ingroup blender + */ + +/** \defgroup cmpnodes cmpnodes + * \ingroup nodes + */ + +/** \defgroup shdnodes shdnodes + * \ingroup nodes + */ + +/** \defgroup texnodes texnodes + * \ingroup nodes + */ +/** \defgroup modifiers modifiers + * \ingroup blender + */ + +/** \defgroup data DNA, RNA and .blend access*/ + +/** \defgroup gpu GPU + * \ingroup blender + */ + +/** \defgroup ikplugin ikplugin + * \ingroup blender + */ + +/** \defgroup DNA sDNA + * \ingroup blender data + */ +/** \defgroup RNA RNA + * \ingroup blender data + */ + +/** \defgroup blenloader .blend read and write functions + * \ingroup blender data + * \todo check if \ref blo and \ref blenloader groups can be + * merged in docs. + */ + +/** \defgroup quicktime quicktime + * \ingroup blender + +/** \defgroup gui GUI */ + +/** \defgroup wm windowmanager + * \ingroup blender gui + */ + +/* ================================ */ + +/** \defgroup editors Editors + * \ingroup blender + */ + +/** \defgroup edanimation animation + * \ingroup editors + */ + +/** \defgroup edarmature armature + * \ingroup editors + */ + +/** \defgroup edcurve curve + * \ingroup editors + */ + +/** \defgroup eddatafiles datafiles + * \ingroup editors + */ + +/** \defgroup edgpencil gpencil + * \ingroup editors + */ + +/** \defgroup edinterface interface + * \ingroup editors + */ + +/** \defgroup edmesh mesh + * \ingroup editors + */ + +/** \defgroup edmeta metaball + * \ingroup editors + */ + +/** \defgroup edobj object + * \ingroup editors + */ + +/** \defgroup edphys physics + * \ingroup editors + */ + +/** \defgroup edrend render + * \ingroup editors + */ + +/** \defgroup edscr screen + * \ingroup editors + */ + +/** \defgroup edsculpt sculpt and paint + * \ingroup editors + */ + +/** \defgroup edsnd sound + * \ingroup editors + */ + +/** \defgroup spaction action space + * \ingroup editors + */ + +/** \defgroup spapi space API + * \ingroup editors + */ + +/** \defgroup spbuttons buttons space + * \ingroup editors + */ + +/** \defgroup spconsole console space + * \ingroup editors + */ + +/** \defgroup spfile fileselector + * \ingroup editors + */ + +/** \defgroup spgraph graph editor + * \ingroup editors + */ + +/** \defgroup spimage image and UV editor + * \ingroup editors + */ + +/** \defgroup spinfo info space + * \ingroup editors + */ + +/** \defgroup splogic game logic editor + * \ingroup editors + */ + +/** \defgroup spnla NLA editor + * \ingroup editors + */ + +/** \defgroup spnode node editor + * \ingroup editors + */ + +/** \defgroup spoutliner outliner space + * \ingroup editors + */ + +/** \defgroup spscript script space + * \ingroup editors + */ + +/** \defgroup spseq sequencer + * \ingroup editors + */ + +/** \defgroup spsnd sound space + * \ingroup editors + */ + +/** \defgroup sptext text editor + * \ingroup editors + */ + +/** \defgroup sptime time line + * \ingroup editors + */ + +/** \defgroup spuserpref user preferences + * \ingroup editors + */ + +/** \defgroup spview3d 3D view + * \ingroup editors + */ + +/** \defgroup edtransform transform + * \ingroup editors + */ + +/** \defgroup edutil editor utilities + * \ingroup editors + */ + +/** \defgroup spuv UV editing + * \ingroup editors + */ + +/* ================================ */ + +/** \defgroup editorui Interface and Widgets + * \ingroup gui + */ + +/** \defgroup externformats external formats */ + +/** \defgroup collada COLLADA + * \ingroup externformats + */ + +/** \defgroup avi AVI + * \ingroup externformats + */ + +/** \defgroup imbuf IMage Buffer + * \ingroup blender + */ + +/** \defgroup imbcineon Cineon + * \ingroup imbuf + */ + +/** \defgroup imbdds DDS + * \ingroup imbuf + */ + +/** \defgroup openexr OpenEXR + * \ingroup imbuf + */ + +/* ================================ */ + +/** \defgroup undoc Undocumented + * \brief Modules and libraries that are still undocumented, or lacking proper integration into the doxygen system, are marked in this group. */ -- cgit v1.2.3 From 922d5ed939139d578d4f9fdc55e891e0a23f7709 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 20 May 2015 14:08:09 +1000 Subject: doxygen: update config --- doc/doxygen/Doxyfile | 2378 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 1425 insertions(+), 953 deletions(-) diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index 9edf977f257..153c7983ee5 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -1,106 +1,122 @@ -# Doxyfile 1.8.4 +# Doxyfile 1.8.9.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # -# All text after a double hash (##) is considered a comment and is placed -# in front of the TAG it is preceding . -# All text after a hash (#) is considered a comment and will be ignored. +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. # The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" "). +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or sequence of words) that should -# identify the project. Note that if you do not use Doxywizard you need -# to put quotes around the project name if it contains spaces. +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. PROJECT_NAME = Blender -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. PROJECT_NUMBER = "V2.7x" # Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer -# a quick idea about the purpose of the project. Keep the description short. +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = -# With the PROJECT_LOGO tag one can specify an logo or icon that is -# included in the documentation. The maximum height of the logo should not -# exceed 55 pixels and the maximum width should not exceed 200 pixels. -# Doxygen will copy the logo to the output directory. +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. PROJECT_LOGO = ../../release/freedesktop/icons/48x48/apps/blender.png -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. OUTPUT_DIRECTORY = -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. CREATE_SUBDIRS = YES +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian, -# Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, -# Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. +# The default value is: YES. REPEAT_BRIEF = YES -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ @@ -115,8 +131,9 @@ ABBREVIATE_BRIEF = "The $name class" \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief +# doxygen will generate a detailed section even if there is only a brief # description. +# The default value is: NO. ALWAYS_DETAILED_SEC = NO @@ -124,231 +141,269 @@ ALWAYS_DETAILED_SEC = NO # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. +# The default value is: NO. INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. FULL_PATH_NAMES = NO -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. Note that you specify absolute paths here, but also -# relative paths, which will be relative from the directory where doxygen is -# started. +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. STRIP_FROM_INC_PATH = -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful if your file system -# doesn't support long names like on DOS, Mac, or CD-ROM. +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. SHORT_NAMES = NO -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. JAVADOC_AUTOBRIEF = NO -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. QT_AUTOBRIEF = NO -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. SEPARATE_MEMBER_PAGES = NO -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding -# "class=itcl::class" will allow you to use the command class in the -# itcl::class meaning. +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. TCL_SUBST = -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it -# using this tag. The format is ext=language, where ext is a file extension, -# and language is one of the parsers supported by doxygen: IDL, Java, -# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, -# C++. For instance to make doxygen treat .inc files as Fortran files (default -# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note -# that for custom extensions you also need to set FILE_PATTERNS otherwise the -# files are not read by doxygen. +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. EXTENSION_MAPPING = -# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all -# comments according to the Markdown format, which allows for more readable +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you -# can mix doxygen, HTML, and XML commands with Markdown formatting. -# Disable only in case of backward compatibilities issues. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by by putting a % sign in front of the word -# or globally by setting AUTOLINK_SUPPORT to NO. +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also makes the inheritance and collaboration +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. +# The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. +# The default value is: NO. CPP_CLI_SUPPORT = NO -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate -# getter and setter methods for a property. Setting this option to YES (the -# default) will make doxygen replace the get and set methods by a property in -# the documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first +# tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. +# The default value is: NO. DISTRIBUTE_GROUP_DOC = YES -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. SUBGROUPING = YES -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and -# unions are shown inside the group in which they are included (e.g. using -# @ingroup) instead of on a separate page (for HTML and Man pages) or -# section (for LaTeX and RTF). +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. INLINE_GROUPED_CLASSES = NO -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and -# unions with only public data fields or simple typedef fields will be shown -# inline in the documentation of the scope in which they are defined (i.e. file, +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set -# to NO (the default), structs, classes, and unions are shown on a separate -# page (for HTML and Man pages) or section (for LaTeX and RTF). +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. INLINE_SIMPLE_STRUCTS = NO -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This -# cache is used to resolve symbols given their name and scope. Since this can -# be an expensive process and often the same symbol appear multiple times in -# the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too -# small doxygen will become slower. If the cache is too large, memory is wasted. -# The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid -# range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536 -# symbols. +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 @@ -356,313 +411,362 @@ LOOKUP_CACHE_SIZE = 0 # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. EXTRACT_ALL = YES -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. EXTRACT_PRIVATE = NO -# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. +# The default value is: NO. EXTRACT_PACKAGE = NO -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. EXTRACT_STATIC = YES -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. EXTRACT_LOCAL_CLASSES = YES -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespaces are hidden. +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. EXTRACT_ANON_NSPACES = NO -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_MEMBERS = NO -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_CLASSES = NO -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. HIDE_IN_BODY_DOCS = NO -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. INTERNAL_DOCS = YES -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. +# The default value is: system dependent. CASE_SENSE_NAMES = YES -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. HIDE_SCOPE_NAMES = NO -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. SHOW_INCLUDE_FILES = YES -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. FORCE_LOCAL_INCLUDES = NO -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. SORT_MEMBER_DOCS = YES -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. SORT_BRIEF_DOCS = NO -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. SORT_GROUP_NAMES = NO -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. SORT_BY_SCOPE_NAME = NO -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to -# do proper type resolution of all parameters of a function it will reject a -# match between the prototype and the implementation of a member function even -# if there is only one candidate or it is obvious which candidate to choose -# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen -# will still accept a match between prototype and implementation in such cases. +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. STRICT_PROTO_MATCHING = NO -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. GENERATE_TODOLIST = YES -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. GENERATE_TESTLIST = YES -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. GENERATE_BUGLIST = YES -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. GENERATE_DEPRECATEDLIST= YES -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if section-label ... \endif -# and \cond section-label ... \endcond blocks. +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. ENABLED_SECTIONS = -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or macro consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and macros in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. +# The default value is: YES. SHOW_USED_FILES = YES -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. SHOW_FILES = YES -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. LAYOUT_FILE = -# The CITE_BIB_FILES tag can be used to specify one or more bib files -# containing the references data. This must be a list of .bib files. The -# .bib extension is automatically appended if omitted. Using this command -# requires the bibtex tool to be installed. See also -# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style -# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this -# feature you need bibtex and perl available in the search path. Do not use -# file names with spaces, bibtex cannot handle them. +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- -# configuration options related to warning and progress messages +# Configuration options related to warning and progress messages #--------------------------------------------------------------------------- -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. WARNINGS = YES -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. WARN_IF_UNDOCUMENTED = YES -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. WARN_IF_DOC_ERROR = YES -# The WARN_NO_PARAMDOC option can be enabled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. WARN_NO_PARAMDOC = NO -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- -# configuration options related to the input files +# Configuration options related to the input files #--------------------------------------------------------------------------- -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. INPUT = doxygen.main.h \ doxygen.source.h \ @@ -673,32 +777,35 @@ INPUT = doxygen.main.h \ ../../extern/bullet2 # This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh -# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py -# *.f90 *.f *.for *.vhd *.vhdl +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. FILE_PATTERNS = -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. +# # Note that relative paths are relative to the directory from which doxygen is # run. @@ -708,14 +815,16 @@ EXCLUDE = ../../build_files, \ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. +# The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = .svn \ .git \ @@ -726,42 +835,49 @@ EXCLUDE_PATTERNS = .svn \ # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. EXAMPLE_RECURSIVE = NO -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be ignored. +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. @@ -769,172 +885,224 @@ IMAGE_PATH = INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty or if -# non of the patterns match the file name, INPUT_FILTER is applied. +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) -# and it is also possible to disable source filtering for a specific pattern -# using *.ext= (so without naming a filter). This option only has effect when -# FILTER_SOURCE_FILES is enabled. +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = -# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub -# and want reuse the introduction page also for the doxygen output. +# and want to reuse the introduction page also for the doxygen output. -USE_MDFILE_AS_MAINPAGE = +# USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- -# configuration options related to source browsing +# Configuration options related to source browsing #--------------------------------------------------------------------------- -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. SOURCE_BROWSER = YES -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C, C++ and Fortran comments will always remain visible. +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. STRIP_CODE_COMMENTS = YES -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. REFERENCED_BY_RELATION = YES -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. REFERENCES_RELATION = YES -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. REFERENCES_LINK_SOURCE = YES -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index +# Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. ALPHABETICAL_INDEX = YES -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- -# configuration options related to the HTML output +# Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. Note that when using a custom header you are responsible -# for the proper inclusion of any scripts and style sheets that doxygen -# needs, which is dependent on the configuration options used. -# It is advised to generate a default header using "doxygen -w html -# header.html footer.html stylesheet.css YourConfigFile" and then modify -# that header. Note that the header is subject to change so you typically -# have to redo this when upgrading to a newer version of doxygen or when -# changing the value of configuration settings such as GENERATE_TREEVIEW! +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = footer.html -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If left blank doxygen will -# generate a default style sheet. Note that it is recommended to use -# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this -# tag will in the future become obsolete. +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = -# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional -# user-defined cascading style sheet that is included after the standard -# style sheets created by doxygen. Using this option one can overrule -# certain style aspects. This is preferred over using HTML_STYLESHEET -# since it does not replace the standard style sheet and is therefor more -# robust against future updates. Doxygen will copy the style sheet file to -# the output directory. +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = @@ -942,632 +1110,835 @@ HTML_EXTRA_STYLESHEET = # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that -# the files will be copied as-is; there are no commands or markers available. +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the style sheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 79 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of -# entries shown in the various tree structured indices initially; the user -# can expand and collapse entries dynamically later on. Doxygen will expand -# the tree to such a level that at most the specified number of entries are -# visible (unless a fully collapsed tree already exceeds this amount). -# So setting the number of entries 1 will produce a full collapsed tree by -# default. 0 is a special value representing an infinite number of entries -# and will result in a full expanded tree by default. +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely -# identify the documentation publisher. This should be a reverse domain-name -# style string, e.g. com.mycompany.MyDocSet.documentation. +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = YES -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be # written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = blender.chm -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = "C:/Program Files (x86)/HTML Help Workshop/hhc.exe" -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# -# Qt Help Project / Custom Filters. +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project -# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) -# at top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. Since the tabs have the same information as the -# navigation tree you can set this option to NO if you already set -# GENERATE_TREEVIEW to YES. +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. -# Since the tree basically has the same information as the tab index you -# could consider to set DISABLE_INDEX to NO when enabling this option. +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values -# (range [0,1..20]) that doxygen will group on one line in the generated HTML -# documentation. Note that a value of 0 will completely suppress the enum -# values from appearing in the overview section. +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 246 -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax -# (see http://www.mathjax.org) which uses client side Javascript for the -# rendering instead of using prerendered bitmaps. Use this if you do not -# have LaTeX installed or if you want to formulas look prettier in the HTML -# output. When enabled you may also need to install MathJax separately and -# configure the path to it using the MATHJAX_RELPATH option. +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for -# the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and -# SVG. The default value is HTML-CSS, which is slower, but has the best -# compatibility. +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS -# When MathJax is enabled you need to specify the location relative to the -# HTML output directory using the MATHJAX_RELPATH option. The destination -# directory should contain the MathJax.js script. For instance, if the mathjax -# directory is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to -# the MathJax Content Delivery Network so you can quickly see the result without -# installing MathJax. -# However, it is strongly recommended to install a local -# copy of MathJax from http://www.mathjax.org before deployment. +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://www.mathjax.org/mathjax -# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension -# names that should be enabled during MathJax rendering. +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript -# pieces of code that will be used on startup of the MathJax code. +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /